diff --git a/SConstruct b/SConstruct index 698ea85ec..8d389b70b 100644 --- a/SConstruct +++ b/SConstruct @@ -77,8 +77,6 @@ if GetOption("fullenv") or any( "${COPRO_DISCLAIMER}", "--obdata", '"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"', - "--stackversion", - "${COPRO_CUBE_VERSION}", ] dist_resource_arguments = [ "-r", diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index 31fa54161..d75a88888 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -1,7 +1,7 @@ #include "bt_i.h" +#include "battery_service.h" #include "bt_keys_storage.h" -#include #include #include #include diff --git a/fbt_options.py b/fbt_options.py index 3f44bec3b..18b636822 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -25,7 +25,7 @@ DIST_SUFFIX = f"XFW-DEV_@{subprocess.check_output(['git', 'rev-parse', '--short= COPRO_OB_DATA = "scripts/ob.data" # Must match lib/stm32wb_copro version -COPRO_CUBE_VERSION = "1.17.2" +COPRO_CUBE_VERSION = "1.15.0" COPRO_CUBE_DIR = "lib/stm32wb_copro" diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 338697ad7..30b63ca3a 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1025,10 +1025,8 @@ Function,+,furi_hal_clock_mco_disable,void, Function,+,furi_hal_clock_mco_enable,void,"FuriHalClockMcoSourceId, FuriHalClockMcoDivisorId" Function,-,furi_hal_clock_resume_tick,void, Function,-,furi_hal_clock_suspend_tick,void, -Function,-,furi_hal_clock_switch_hse2hsi,void, -Function,-,furi_hal_clock_switch_hse2pll,_Bool, -Function,-,furi_hal_clock_switch_hsi2hse,void, -Function,-,furi_hal_clock_switch_pll2hse,_Bool, +Function,-,furi_hal_clock_switch_to_hsi,void, +Function,-,furi_hal_clock_switch_to_pll,void, Function,+,furi_hal_console_disable,void, Function,+,furi_hal_console_enable,void, Function,+,furi_hal_console_init,void, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 32646daef..01095b832 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1162,10 +1162,8 @@ Function,+,furi_hal_clock_mco_disable,void, Function,+,furi_hal_clock_mco_enable,void,"FuriHalClockMcoSourceId, FuriHalClockMcoDivisorId" Function,-,furi_hal_clock_resume_tick,void, Function,-,furi_hal_clock_suspend_tick,void, -Function,-,furi_hal_clock_switch_hse2hsi,void, -Function,-,furi_hal_clock_switch_hse2pll,_Bool, -Function,-,furi_hal_clock_switch_hsi2hse,void, -Function,-,furi_hal_clock_switch_pll2hse,_Bool, +Function,-,furi_hal_clock_switch_to_hsi,void, +Function,-,furi_hal_clock_switch_to_pll,void, Function,+,furi_hal_console_disable,void, Function,+,furi_hal_console_enable,void, Function,+,furi_hal_console_init,void, diff --git a/firmware/targets/f7/ble_glue/app_common.h b/firmware/targets/f7/ble_glue/app_common.h index e969636d2..8eaf23085 100644 --- a/firmware/targets/f7/ble_glue/app_common.h +++ b/firmware/targets/f7/ble_glue/app_common.h @@ -1,4 +1,30 @@ -#pragma once +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : app_common.h + * Description : App Common application configuration file for STM32WPAN Middleware. + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef APP_COMMON_H +#define APP_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif #include #include @@ -10,3 +36,5 @@ #include #include "app_conf.h" + +#endif diff --git a/firmware/targets/f7/ble_glue/app_conf.h b/firmware/targets/f7/ble_glue/app_conf.h index 25fa688c7..ee5115cfe 100644 --- a/firmware/targets/f7/ble_glue/app_conf.h +++ b/firmware/targets/f7/ble_glue/app_conf.h @@ -1,32 +1,80 @@ #pragma once -#include +#include "hw_conf.h" +#include "hw_if.h" + +#include +#include #define CFG_TX_POWER (0x19) /* +0dBm */ #define CFG_IDENTITY_ADDRESS GAP_PUBLIC_ADDR +/** + * Define Advertising parameters + */ +#define CFG_ADV_BD_ADDRESS (0x7257acd87a6c) +#define CFG_FAST_CONN_ADV_INTERVAL_MIN (0x80) /**< 80ms */ +#define CFG_FAST_CONN_ADV_INTERVAL_MAX (0xa0) /**< 100ms */ +#define CFG_LP_CONN_ADV_INTERVAL_MIN (0x640) /**< 1s */ +#define CFG_LP_CONN_ADV_INTERVAL_MAX (0xfa0) /**< 2.5s */ + /** * Define IO Authentication */ -#define CFG_USED_FIXED_PIN USE_FIXED_PIN_FOR_PAIRING_FORBIDDEN +#define CFG_BONDING_MODE (1) +#define CFG_FIXED_PIN (111111) +#define CFG_USED_FIXED_PIN (1) #define CFG_ENCRYPTION_KEY_SIZE_MAX (16) #define CFG_ENCRYPTION_KEY_SIZE_MIN (8) /** * Define IO capabilities */ -#define CFG_IO_CAPABILITY IO_CAP_DISPLAY_YES_NO +#define CFG_IO_CAPABILITY_DISPLAY_ONLY (0x00) +#define CFG_IO_CAPABILITY_DISPLAY_YES_NO (0x01) +#define CFG_IO_CAPABILITY_KEYBOARD_ONLY (0x02) +#define CFG_IO_CAPABILITY_NO_INPUT_NO_OUTPUT (0x03) +#define CFG_IO_CAPABILITY_KEYBOARD_DISPLAY (0x04) + +#define CFG_IO_CAPABILITY CFG_IO_CAPABILITY_DISPLAY_YES_NO /** * Define MITM modes */ -#define CFG_MITM_PROTECTION MITM_PROTECTION_REQUIRED +#define CFG_MITM_PROTECTION_NOT_REQUIRED (0x00) +#define CFG_MITM_PROTECTION_REQUIRED (0x01) + +#define CFG_MITM_PROTECTION CFG_MITM_PROTECTION_REQUIRED /** * Define Secure Connections Support */ -#define CFG_SC_SUPPORT SC_PAIRING_OPTIONAL +#define CFG_SECURE_NOT_SUPPORTED (0x00) +#define CFG_SECURE_OPTIONAL (0x01) +#define CFG_SECURE_MANDATORY (0x02) + +#define CFG_SC_SUPPORT CFG_SECURE_OPTIONAL + +/** + * Define Keypress Notification Support + */ +#define CFG_KEYPRESS_NOT_SUPPORTED (0x00) +#define CFG_KEYPRESS_SUPPORTED (0x01) + +#define CFG_KEYPRESS_NOTIFICATION_SUPPORT CFG_KEYPRESS_NOT_SUPPORTED + +/** + * Numeric Comparison Answers + */ +#define YES (0x01) +#define NO (0x00) + +/** + * Device name configuration for Generic Access Service + */ +#define CFG_GAP_DEVICE_NAME "TEMPLATE" +#define CFG_GAP_DEVICE_NAME_LENGTH (8) /** * Define PHY @@ -39,6 +87,42 @@ #define RX_1M 0x01 #define RX_2M 0x02 +/** +* Identity root key used to derive LTK and CSRK +*/ +#define CFG_BLE_IRK \ + { \ + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, \ + 0xf0 \ + } + +/** +* Encryption root key used to derive LTK and CSRK +*/ +#define CFG_BLE_ERK \ + { \ + 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21, 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, \ + 0x21 \ + } + +/* USER CODE BEGIN Generic_Parameters */ +/** + * SMPS supply + * SMPS not used when Set to 0 + * SMPS used when Set to 1 + */ +#define CFG_USE_SMPS 1 +/* USER CODE END Generic_Parameters */ + +/**< specific parameters */ +/*****************************************************/ + +/** +* AD Element - Group B Feature +*/ +/* LSB - Second Byte */ +#define CFG_FEATURE_OTA_REBOOT (0x20) + /****************************************************************************** * BLE Stack ******************************************************************************/ @@ -119,9 +203,7 @@ * 1 : external high speed crystal HSE/32/32 * 0 : external low speed crystal ( no calibration ) */ -#define CFG_BLE_LSE_SOURCE \ - SHCI_C2_BLE_INIT_CFG_BLE_LS_CLK_LSE | SHCI_C2_BLE_INIT_CFG_BLE_LS_OTHER_DEV | \ - SHCI_C2_BLE_INIT_CFG_BLE_LS_CALIB +#define CFG_BLE_LSE_SOURCE 0 /** * Start up time of the high speed (16 or 32 MHz) crystal oscillator in units of 625/256 us (~2.44 us) @@ -171,8 +253,8 @@ */ #define CFG_BLE_OPTIONS \ (SHCI_C2_BLE_INIT_OPTIONS_LL_HOST | SHCI_C2_BLE_INIT_OPTIONS_WITH_SVC_CHANGE_DESC | \ - SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RO | SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV | \ - SHCI_C2_BLE_INIT_OPTIONS_CS_ALGO2 | SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_2_3) + SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RW | SHCI_C2_BLE_INIT_OPTIONS_NO_EXT_ADV | \ + SHCI_C2_BLE_INIT_OPTIONS_NO_CS_ALGO2 | SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_2_3) /** * Queue length of BLE Event @@ -200,3 +282,187 @@ 255 /**< Set to 255 with the memory manager and the mailbox */ #define TL_BLE_EVENT_FRAME_SIZE (TL_EVT_HDR_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE) +/****************************************************************************** + * UART interfaces + ******************************************************************************/ + +/** + * Select UART interfaces + */ +#define CFG_DEBUG_TRACE_UART hw_uart1 +#define CFG_CONSOLE_MENU 0 + +/****************************************************************************** + * Low Power + ******************************************************************************/ +/** + * When set to 1, the low power mode is enable + * When set to 0, the device stays in RUN mode + */ +#define CFG_LPM_SUPPORTED 1 + +/****************************************************************************** + * Timer Server + ******************************************************************************/ +/** + * CFG_RTC_WUCKSEL_DIVIDER: This sets the RTCCLK divider to the wakeup timer. + * The lower is the value, the better is the power consumption and the accuracy of the timerserver + * The higher is the value, the finest is the granularity + * + * CFG_RTC_ASYNCH_PRESCALER: This sets the asynchronous prescaler of the RTC. It should as high as possible ( to ouput + * clock as low as possible) but the output clock should be equal or higher frequency compare to the clock feeding + * the wakeup timer. A lower clock speed would impact the accuracy of the timer server. + * + * CFG_RTC_SYNCH_PRESCALER: This sets the synchronous prescaler of the RTC. + * When the 1Hz calendar clock is required, it shall be sets according to other settings + * When the 1Hz calendar clock is not needed, CFG_RTC_SYNCH_PRESCALER should be set to 0x7FFF (MAX VALUE) + * + * CFG_RTCCLK_DIVIDER_CONF: + * Shall be set to either 0,2,4,8,16 + * When set to either 2,4,8,16, the 1Hhz calendar is supported + * When set to 0, the user sets its own configuration + * + * The following settings are computed with LSI as input to the RTC + */ +#define CFG_RTCCLK_DIVIDER_CONF 0 + +#if(CFG_RTCCLK_DIVIDER_CONF == 0) +/** + * Custom configuration + * It does not support 1Hz calendar + * It divides the RTC CLK by 16 + */ +#define CFG_RTCCLK_DIV (16) +#define CFG_RTC_WUCKSEL_DIVIDER (0) +#define CFG_RTC_ASYNCH_PRESCALER (CFG_RTCCLK_DIV - 1) +#define CFG_RTC_SYNCH_PRESCALER (0x7FFF) + +#else + +#if(CFG_RTCCLK_DIVIDER_CONF == 2) +/** + * It divides the RTC CLK by 2 + */ +#define CFG_RTC_WUCKSEL_DIVIDER (3) +#endif + +#if(CFG_RTCCLK_DIVIDER_CONF == 4) +/** + * It divides the RTC CLK by 4 + */ +#define CFG_RTC_WUCKSEL_DIVIDER (2) +#endif + +#if(CFG_RTCCLK_DIVIDER_CONF == 8) +/** + * It divides the RTC CLK by 8 + */ +#define CFG_RTC_WUCKSEL_DIVIDER (1) +#endif + +#if(CFG_RTCCLK_DIVIDER_CONF == 16) +/** + * It divides the RTC CLK by 16 + */ +#define CFG_RTC_WUCKSEL_DIVIDER (0) +#endif + +#define CFG_RTCCLK_DIV CFG_RTCCLK_DIVIDER_CONF +#define CFG_RTC_ASYNCH_PRESCALER (CFG_RTCCLK_DIV - 1) +#define CFG_RTC_SYNCH_PRESCALER (DIVR(LSE_VALUE, (CFG_RTC_ASYNCH_PRESCALER + 1)) - 1) + +#endif + +/** tick timer value in us */ +#define CFG_TS_TICK_VAL DIVR((CFG_RTCCLK_DIV * 1000000), LSE_VALUE) + +typedef enum { + CFG_TIM_PROC_ID_ISR, + /* USER CODE BEGIN CFG_TimProcID_t */ + + /* USER CODE END CFG_TimProcID_t */ +} CFG_TimProcID_t; + +/****************************************************************************** + * Debug + ******************************************************************************/ +/** + * When set, this resets some hw resources to set the device in the same state than the power up + * The FW resets only register that may prevent the FW to run properly + * + * This shall be set to 0 in a final product + * + */ +#define CFG_HW_RESET_BY_FW 0 + +/** + * keep debugger enabled while in any low power mode when set to 1 + * should be set to 0 in production + */ +#define CFG_DEBUGGER_SUPPORTED 1 + +/** + * When set to 1, the traces are enabled in the BLE services + */ +#define CFG_DEBUG_BLE_TRACE 0 + +/** + * Enable or Disable traces in application + */ +#define CFG_DEBUG_APP_TRACE 0 + +#if(CFG_DEBUG_APP_TRACE != 0) +#define APP_DBG_MSG PRINT_MESG_DBG +#else +#define APP_DBG_MSG PRINT_NO_MESG +#endif + +#if((CFG_DEBUG_BLE_TRACE != 0) || (CFG_DEBUG_APP_TRACE != 0)) +#define CFG_DEBUG_TRACE 1 +#endif + +#if(CFG_DEBUG_TRACE != 0) +#undef CFG_LPM_SUPPORTED +#undef CFG_DEBUGGER_SUPPORTED +#define CFG_LPM_SUPPORTED 0 +#define CFG_DEBUGGER_SUPPORTED 1 +#endif + +/** + * When CFG_DEBUG_TRACE_FULL is set to 1, the trace are output with the API name, the file name and the line number + * When CFG_DEBUG_TRACE_LIGHT is set to 1, only the debug message is output + * + * When both are set to 0, no trace are output + * When both are set to 1, CFG_DEBUG_TRACE_FULL is selected + */ +#define CFG_DEBUG_TRACE_LIGHT 0 +#define CFG_DEBUG_TRACE_FULL 0 + +#if((CFG_DEBUG_TRACE != 0) && (CFG_DEBUG_TRACE_LIGHT == 0) && (CFG_DEBUG_TRACE_FULL == 0)) +#undef CFG_DEBUG_TRACE_FULL +#undef CFG_DEBUG_TRACE_LIGHT +#define CFG_DEBUG_TRACE_FULL 0 +#define CFG_DEBUG_TRACE_LIGHT 1 +#endif + +#if(CFG_DEBUG_TRACE == 0) +#undef CFG_DEBUG_TRACE_FULL +#undef CFG_DEBUG_TRACE_LIGHT +#define CFG_DEBUG_TRACE_FULL 0 +#define CFG_DEBUG_TRACE_LIGHT 0 +#endif + +/** + * When not set, the traces is looping on sending the trace over UART + */ +#define DBG_TRACE_USE_CIRCULAR_QUEUE 0 + +/** + * max buffer Size to queue data traces and max data trace allowed. + * Only Used if DBG_TRACE_USE_CIRCULAR_QUEUE is defined + */ +#define DBG_TRACE_MSG_QUEUE_SIZE 4096 +#define MAX_DBG_TRACE_MSG_SIZE 1024 + +#define CFG_OTP_BASE_ADDRESS OTP_AREA_BASE +#define CFG_OTP_END_ADRESS OTP_AREA_END_ADDR diff --git a/firmware/targets/f7/ble_glue/app_debug.c b/firmware/targets/f7/ble_glue/app_debug.c index fe76687b9..b443bee21 100644 --- a/firmware/targets/f7/ble_glue/app_debug.c +++ b/firmware/targets/f7/ble_glue/app_debug.c @@ -6,9 +6,6 @@ #include #include -#include "stm32wbxx_ll_bus.h" -#include "stm32wbxx_ll_pwr.h" - #include typedef PACKED_STRUCT { @@ -111,6 +108,10 @@ static void APPD_SetCPU2GpioConfig(void); static void APPD_BleDtbCfg(void); void APPD_Init() { +#if(CFG_DEBUG_TRACE != 0) + DbgTraceInit(); +#endif + APPD_SetCPU2GpioConfig(); APPD_BleDtbCfg(); } @@ -195,14 +196,14 @@ static void APPD_SetCPU2GpioConfig(void) { gpio_config.Pin = gpiob_pin_list; LL_C2_AHB2_GRP1_EnableClock(LL_C2_AHB2_GRP1_PERIPH_GPIOB); LL_GPIO_Init(GPIOB, &gpio_config); - LL_GPIO_ResetOutputPin(GPIOB, gpiob_pin_list); + LL_GPIO_ResetOutputPin(GPIOB, gpioa_pin_list); } if(gpioc_pin_list != 0) { gpio_config.Pin = gpioc_pin_list; LL_C2_AHB2_GRP1_EnableClock(LL_C2_AHB2_GRP1_PERIPH_GPIOC); LL_GPIO_Init(GPIOC, &gpio_config); - LL_GPIO_ResetOutputPin(GPIOC, gpioc_pin_list); + LL_GPIO_ResetOutputPin(GPIOC, gpioa_pin_list); } } @@ -251,3 +252,13 @@ static void APPD_BleDtbCfg(void) { } #endif } + +#if(CFG_DEBUG_TRACE != 0) +void DbgOutputInit(void) { +} + +void DbgOutputTraces(uint8_t* p_data, uint16_t size, void (*cb)(void)) { + furi_hal_console_tx(p_data, size); + cb(); +} +#endif diff --git a/firmware/targets/f7/ble_glue/app_debug.h b/firmware/targets/f7/ble_glue/app_debug.h index 213470bed..92a54d75b 100644 --- a/firmware/targets/f7/ble_glue/app_debug.h +++ b/firmware/targets/f7/ble_glue/app_debug.h @@ -1,4 +1,26 @@ -#pragma once +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : app_debug.h + * Description : Header for app_debug.c module + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __APP_DEBUG_H +#define __APP_DEBUG_H #ifdef __cplusplus extern "C" { @@ -10,3 +32,7 @@ void APPD_EnableCPU2(void); #ifdef __cplusplus } #endif + +#endif /*__APP_DEBUG_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/ble_glue/services/battery_service.c b/firmware/targets/f7/ble_glue/battery_service.c similarity index 53% rename from firmware/targets/f7/ble_glue/services/battery_service.c rename to firmware/targets/f7/ble_glue/battery_service.c index 63f736b3b..8c371efad 100644 --- a/firmware/targets/f7/ble_glue/services/battery_service.c +++ b/firmware/targets/f7/ble_glue/battery_service.c @@ -1,7 +1,5 @@ #include "battery_service.h" #include "app_common.h" -#include "gatt_char.h" - #include #include @@ -9,6 +7,12 @@ #define TAG "BtBatterySvc" +typedef struct { + uint16_t svc_handle; + uint16_t battery_level_char_handle; + uint16_t power_state_char_handle; +} BatterySvc; + enum { // Common states BatterySvcPowerStateUnknown = 0b00, @@ -36,44 +40,13 @@ typedef struct { _Static_assert(sizeof(BattrySvcPowerState) == 1, "Incorrect structure size"); +static BatterySvc* battery_svc = NULL; + #define BATTERY_POWER_STATE (0x2A1A) static const uint16_t service_uuid = BATTERY_SERVICE_UUID; - -typedef enum { - BatterySvcGattCharacteristicBatteryLevel = 0, - BatterySvcGattCharacteristicPowerState, - BatterySvcGattCharacteristicCount, -} BatterySvcGattCharacteristicId; - -static const FlipperGattCharacteristicParams battery_svc_chars[BatterySvcGattCharacteristicCount] = - {[BatterySvcGattCharacteristicBatteryLevel] = - {.name = "Battery Level", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = 1, - .uuid.Char_UUID_16 = BATTERY_LEVEL_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [BatterySvcGattCharacteristicPowerState] = { - .name = "Power State", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = 1, - .uuid.Char_UUID_16 = BATTERY_POWER_STATE, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}}; - -typedef struct { - uint16_t svc_handle; - FlipperGattCharacteristicInstance chars[BatterySvcGattCharacteristicCount]; -} BatterySvc; - -static BatterySvc* battery_svc = NULL; +static const uint16_t battery_level_char_uuid = BATTERY_LEVEL_CHAR_UUID; +static const uint16_t power_state_char_uuid = BATTERY_POWER_STATE; void battery_svc_start() { battery_svc = malloc(sizeof(BatterySvc)); @@ -85,19 +58,53 @@ void battery_svc_start() { if(status) { FURI_LOG_E(TAG, "Failed to add Battery service: %d", status); } - for(size_t i = 0; i < BatterySvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_init( - battery_svc->svc_handle, &battery_svc_chars[i], &battery_svc->chars[i]); + // Add Battery level characteristic + status = aci_gatt_add_char( + battery_svc->svc_handle, + UUID_TYPE_16, + (Char_UUID_t*)&battery_level_char_uuid, + 1, + CHAR_PROP_READ | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &battery_svc->battery_level_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status); } - + // Add Power state characteristic + status = aci_gatt_add_char( + battery_svc->svc_handle, + UUID_TYPE_16, + (Char_UUID_t*)&power_state_char_uuid, + 1, + CHAR_PROP_READ | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &battery_svc->power_state_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status); + } + // Update power state charachteristic battery_svc_update_power_state(); } void battery_svc_stop() { tBleStatus status; if(battery_svc) { - for(size_t i = 0; i < BatterySvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_delete(battery_svc->svc_handle, &battery_svc->chars[i]); + // Delete Battery level characteristic + status = + aci_gatt_del_char(battery_svc->svc_handle, battery_svc->battery_level_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status); + } + // Delete Power state characteristic + status = aci_gatt_del_char(battery_svc->svc_handle, battery_svc->power_state_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status); } // Delete Battery service status = aci_gatt_del_service(battery_svc->svc_handle); @@ -119,10 +126,13 @@ bool battery_svc_update_level(uint8_t battery_charge) { return false; } // Update battery level characteristic - return flipper_gatt_characteristic_update( - battery_svc->svc_handle, - &battery_svc->chars[BatterySvcGattCharacteristicBatteryLevel], - &battery_charge); + FURI_LOG_D(TAG, "Updating battery level characteristic"); + tBleStatus result = aci_gatt_update_char_value( + battery_svc->svc_handle, battery_svc->battery_level_char_handle, 0, 1, &battery_charge); + if(result) { + FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result); + } + return result != BLE_STATUS_SUCCESS; } bool battery_svc_update_power_state() { @@ -142,9 +152,15 @@ bool battery_svc_update_power_state() { power_state.charging = BatterySvcPowerStateNotCharging; power_state.discharging = BatterySvcPowerStateDischarging; } - - return flipper_gatt_characteristic_update( + FURI_LOG_D(TAG, "Updating power state characteristic"); + tBleStatus result = aci_gatt_update_char_value( battery_svc->svc_handle, - &battery_svc->chars[BatterySvcGattCharacteristicPowerState], - &power_state); + battery_svc->power_state_char_handle, + 0, + 1, + (uint8_t*)&power_state); + if(result) { + FURI_LOG_E(TAG, "Failed updating Power state characteristic: %d", result); + } + return result != BLE_STATUS_SUCCESS; } diff --git a/firmware/targets/f7/ble_glue/services/battery_service.h b/firmware/targets/f7/ble_glue/battery_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/services/battery_service.h rename to firmware/targets/f7/ble_glue/battery_service.h diff --git a/firmware/targets/f7/ble_glue/ble_app.c b/firmware/targets/f7/ble_glue/ble_app.c index 37ec3d0b9..ed62b1884 100644 --- a/firmware/targets/f7/ble_glue/ble_app.c +++ b/firmware/targets/f7/ble_glue/ble_app.c @@ -18,8 +18,8 @@ PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t ble_app_cmd_buffer; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint32_t ble_app_nvm[BLE_NVM_SRAM_SIZE]; _Static_assert( - sizeof(SHCI_C2_Ble_Init_Cmd_Packet_t) == 58, - "Ble stack config structure size mismatch (check new config options - last updated for v.1.17.2)"); + sizeof(SHCI_C2_Ble_Init_Cmd_Packet_t) == 57, + "Ble stack config structure size mismatch (check new config options - last updated for v.1.15.0)"); typedef struct { FuriMutex* hci_mtx; @@ -33,54 +33,6 @@ static int32_t ble_app_hci_thread(void* context); static void ble_app_hci_event_handler(void* pPayload); static void ble_app_hci_status_not_handler(HCI_TL_CmdStatus_t status); -static const HCI_TL_HciInitConf_t hci_tl_config = { - .p_cmdbuffer = (uint8_t*)&ble_app_cmd_buffer, - .StatusNotCallBack = ble_app_hci_status_not_handler, -}; - -static const SHCI_C2_CONFIG_Cmd_Param_t config_param = { - .PayloadCmdSize = SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE, - .Config1 = SHCI_C2_CONFIG_CONFIG1_BIT0_BLE_NVM_DATA_TO_SRAM, - .BleNvmRamAddress = (uint32_t)ble_app_nvm, - .EvtMask1 = SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE, -}; - -static const SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = { - .Header = {{0, 0, 0}}, // Header unused - .Param = { - .pBleBufferAddress = 0, // pBleBufferAddress not used - .BleBufferSize = 0, // BleBufferSize not used - .NumAttrRecord = CFG_BLE_NUM_GATT_ATTRIBUTES, - .NumAttrServ = CFG_BLE_NUM_GATT_SERVICES, - .AttrValueArrSize = CFG_BLE_ATT_VALUE_ARRAY_SIZE, - .NumOfLinks = CFG_BLE_NUM_LINK, - .ExtendedPacketLengthEnable = CFG_BLE_DATA_LENGTH_EXTENSION, - .PrWriteListSize = CFG_BLE_PREPARE_WRITE_LIST_SIZE, - .MblockCount = CFG_BLE_MBLOCK_COUNT, - .AttMtu = CFG_BLE_MAX_ATT_MTU, - .SlaveSca = CFG_BLE_SLAVE_SCA, - .MasterSca = CFG_BLE_MASTER_SCA, - .LsSource = CFG_BLE_LSE_SOURCE, - .MaxConnEventLength = CFG_BLE_MAX_CONN_EVENT_LENGTH, - .HsStartupTime = CFG_BLE_HSE_STARTUP_TIME, - .ViterbiEnable = CFG_BLE_VITERBI_MODE, - .Options = CFG_BLE_OPTIONS, - .HwVersion = 0, - .max_coc_initiator_nbr = 32, - .min_tx_power = 0, - .max_tx_power = 0, - .rx_model_config = 1, - /* New stack (13.3->15.0) */ - .max_adv_set_nbr = 1, // Only used if SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV is set - .max_adv_data_len = 1650, // Only used if SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV is set - .tx_path_compens = 0, // RF TX Path Compensation, * 0.1 dB - .rx_path_compens = 0, // RF RX Path Compensation, * 0.1 dB - .ble_core_version = SHCI_C2_BLE_INIT_BLE_CORE_5_4, - /*15.0->17.0*/ - .Options_extension = SHCI_C2_BLE_INIT_OPTIONS_ENHANCED_ATT_NOTSUPPORTED | - SHCI_C2_BLE_INIT_OPTIONS_APPEARANCE_READONLY, - }}; - bool ble_app_init() { SHCI_CmdStatus_t status; ble_app = malloc(sizeof(BleApp)); @@ -92,16 +44,58 @@ bool ble_app_init() { furi_thread_start(ble_app->thread); // Initialize Ble Transport Layer + HCI_TL_HciInitConf_t hci_tl_config = { + .p_cmdbuffer = (uint8_t*)&ble_app_cmd_buffer, + .StatusNotCallBack = ble_app_hci_status_not_handler, + }; hci_init(ble_app_hci_event_handler, (void*)&hci_tl_config); // Configure NVM store for pairing data - status = SHCI_C2_Config((SHCI_C2_CONFIG_Cmd_Param_t*)&config_param); + SHCI_C2_CONFIG_Cmd_Param_t config_param = { + .PayloadCmdSize = SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE, + .Config1 = SHCI_C2_CONFIG_CONFIG1_BIT0_BLE_NVM_DATA_TO_SRAM, + .BleNvmRamAddress = (uint32_t)ble_app_nvm, + .EvtMask1 = SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE, + }; + status = SHCI_C2_Config(&config_param); if(status) { FURI_LOG_E(TAG, "Failed to configure 2nd core: %d", status); } // Start ble stack on 2nd core - status = SHCI_C2_BLE_Init((SHCI_C2_Ble_Init_Cmd_Packet_t*)&ble_init_cmd_packet); + SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = { + .Header = {{0, 0, 0}}, // Header unused + .Param = { + .pBleBufferAddress = 0, // pBleBufferAddress not used + .BleBufferSize = 0, // BleBufferSize not used + .NumAttrRecord = CFG_BLE_NUM_GATT_ATTRIBUTES, + .NumAttrServ = CFG_BLE_NUM_GATT_SERVICES, + .AttrValueArrSize = CFG_BLE_ATT_VALUE_ARRAY_SIZE, + .NumOfLinks = CFG_BLE_NUM_LINK, + .ExtendedPacketLengthEnable = CFG_BLE_DATA_LENGTH_EXTENSION, + .PrWriteListSize = CFG_BLE_PREPARE_WRITE_LIST_SIZE, + .MblockCount = CFG_BLE_MBLOCK_COUNT, + .AttMtu = CFG_BLE_MAX_ATT_MTU, + .SlaveSca = CFG_BLE_SLAVE_SCA, + .MasterSca = CFG_BLE_MASTER_SCA, + .LsSource = CFG_BLE_LSE_SOURCE, + .MaxConnEventLength = CFG_BLE_MAX_CONN_EVENT_LENGTH, + .HsStartupTime = CFG_BLE_HSE_STARTUP_TIME, + .ViterbiEnable = CFG_BLE_VITERBI_MODE, + .Options = CFG_BLE_OPTIONS, + .HwVersion = 0, + .max_coc_initiator_nbr = 32, + .min_tx_power = 0, + .max_tx_power = 0, + .rx_model_config = 1, + /* New stack (13.3->15.0) */ + .max_adv_set_nbr = 1, // Only used if SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV is set + .max_adv_data_len = 31, // Only used if SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV is set + .tx_path_compens = 0, // RF TX Path Compensation, * 0.1 dB + .rx_path_compens = 0, // RF RX Path Compensation, * 0.1 dB + .ble_core_version = 11, // BLE Core Version: 11(5.2), 12(5.3) + }}; + status = SHCI_C2_BLE_Init(&ble_init_cmd_packet); if(status) { FURI_LOG_E(TAG, "Failed to start ble stack: %d", status); } diff --git a/firmware/targets/f7/ble_glue/ble_app.h b/firmware/targets/f7/ble_glue/ble_app.h index 2e6babab7..495005ec4 100644 --- a/firmware/targets/f7/ble_glue/ble_app.h +++ b/firmware/targets/f7/ble_glue/ble_app.h @@ -1,12 +1,12 @@ #pragma once -#include -#include - #ifdef __cplusplus extern "C" { #endif +#include +#include + bool ble_app_init(); void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size); void ble_app_thread_stop(); diff --git a/firmware/targets/f7/ble_glue/ble_conf.h b/firmware/targets/f7/ble_glue/ble_conf.h index 2b9c22dfe..a04d1def1 100644 --- a/firmware/targets/f7/ble_glue/ble_conf.h +++ b/firmware/targets/f7/ble_glue/ble_conf.h @@ -1,7 +1,51 @@ -#pragma once +/** + ****************************************************************************** + * File Name : App/ble_conf.h + * Description : Configuration file for BLE Middleware. + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef BLE_CONF_H +#define BLE_CONF_H #include "app_conf.h" +#ifndef __weak +#define __weak __attribute__((weak)) +#endif + +/****************************************************************************** + * + * BLE SERVICES CONFIGURATION + * blesvc + * + ******************************************************************************/ + +/** + * This setting shall be set to '1' if the device needs to support the Peripheral Role + * In the MS configuration, both BLE_CFG_PERIPHERAL and BLE_CFG_CENTRAL shall be set to '1' + */ +#define BLE_CFG_PERIPHERAL 1 + +/** + * This setting shall be set to '1' if the device needs to support the Central Role + * In the MS configuration, both BLE_CFG_PERIPHERAL and BLE_CFG_CENTRAL shall be set to '1' + */ +#define BLE_CFG_CENTRAL 0 + /** * There is one handler per service enabled * Note: There is no handler for the Device Information Service @@ -12,3 +56,18 @@ #define BLE_CFG_SVC_MAX_NBR_CB 7 #define BLE_CFG_CLT_MAX_NBR_CB 0 + +/****************************************************************************** + * GAP Service - Apprearance + ******************************************************************************/ + +#define BLE_CFG_UNKNOWN_APPEARANCE (0) +#define BLE_CFG_GAP_APPEARANCE (0x0086) + +/****************************************************************************** + * Over The Air Feature (OTA) - STM Proprietary + ******************************************************************************/ +#define BLE_CFG_OTA_REBOOT_CHAR 0 /**< REBOOT OTA MODE CHARACTERISTIC */ + +#endif /*BLE_CONF_H */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/ble_glue/ble_const.h b/firmware/targets/f7/ble_glue/ble_const.h index 1e6647d90..85f734b62 100644 --- a/firmware/targets/f7/ble_glue/ble_const.h +++ b/firmware/targets/f7/ble_glue/ble_const.h @@ -1,4 +1,22 @@ -#pragma once +/***************************************************************************** + * @file ble_const.h + * @author MDG + * @brief This file contains the definitions which are compiler dependent. + ***************************************************************************** + * @attention + * + * Copyright (c) 2018-2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ***************************************************************************** + */ + +#ifndef BLE_CONST_H__ +#define BLE_CONST_H__ #include #include @@ -97,3 +115,5 @@ extern int hci_send_req(struct hci_request* req, uint8_t async); #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif + +#endif /* BLE_CONST_H__ */ diff --git a/firmware/targets/f7/ble_glue/ble_dbg_conf.h b/firmware/targets/f7/ble_glue/ble_dbg_conf.h index 6f70f09be..8305f8106 100644 --- a/firmware/targets/f7/ble_glue/ble_dbg_conf.h +++ b/firmware/targets/f7/ble_glue/ble_dbg_conf.h @@ -1 +1,199 @@ -#pragma once +/** + ****************************************************************************** + * File Name : App/ble_dbg_conf.h + * Description : Debug configuration file for BLE Middleware. + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __BLE_DBG_CONF_H +#define __BLE_DBG_CONF_H + +/** + * Enable or Disable traces from BLE + */ + +#define BLE_DBG_APP_EN 1 +#define BLE_DBG_DIS_EN 1 +#define BLE_DBG_HRS_EN 1 +#define BLE_DBG_SVCCTL_EN 1 +#define BLE_DBG_BLS_EN 1 +#define BLE_DBG_HTS_EN 1 +#define BLE_DBG_P2P_STM_EN 1 + +/** + * Macro definition + */ +#if(BLE_DBG_APP_EN != 0) +#define BLE_DBG_APP_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_APP_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_DIS_EN != 0) +#define BLE_DBG_DIS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_DIS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_HRS_EN != 0) +#define BLE_DBG_HRS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_HRS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_P2P_STM_EN != 0) +#define BLE_DBG_P2P_STM_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_P2P_STM_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_TEMPLATE_STM_EN != 0) +#define BLE_DBG_TEMPLATE_STM_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_TEMPLATE_STM_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_EDS_STM_EN != 0) +#define BLE_DBG_EDS_STM_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_EDS_STM_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_LBS_STM_EN != 0) +#define BLE_DBG_LBS_STM_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_LBS_STM_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_SVCCTL_EN != 0) +#define BLE_DBG_SVCCTL_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_SVCCTL_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_CTS_EN != 0) +#define BLE_DBG_CTS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_CTS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_HIDS_EN != 0) +#define BLE_DBG_HIDS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_HIDS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_PASS_EN != 0) +#define BLE_DBG_PASS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_PASS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_BLS_EN != 0) +#define BLE_DBG_BLS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_BLS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_HTS_EN != 0) +#define BLE_DBG_HTS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_HTS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_ANS_EN != 0) +#define BLE_DBG_ANS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_ANS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_ESS_EN != 0) +#define BLE_DBG_ESS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_ESS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_GLS_EN != 0) +#define BLE_DBG_GLS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_GLS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_BAS_EN != 0) +#define BLE_DBG_BAS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_BAS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_RTUS_EN != 0) +#define BLE_DBG_RTUS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_RTUS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_HPS_EN != 0) +#define BLE_DBG_HPS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_HPS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_TPS_EN != 0) +#define BLE_DBG_TPS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_TPS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_LLS_EN != 0) +#define BLE_DBG_LLS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_LLS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_IAS_EN != 0) +#define BLE_DBG_IAS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_IAS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_WSS_EN != 0) +#define BLE_DBG_WSS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_WSS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_LNS_EN != 0) +#define BLE_DBG_LNS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_LNS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_SCPS_EN != 0) +#define BLE_DBG_SCPS_MSG PRINT_MESG_DBG +#else +#define BLE_DBG_SCPS_MSG PRINT_NO_MESG +#endif + +#if(BLE_DBG_DTS_EN != 0) +#define BLE_DBG_DTS_MSG PRINT_MESG_DBG +#define BLE_DBG_DTS_BUF PRINT_LOG_BUFF_DBG +#else +#define BLE_DBG_DTS_MSG PRINT_NO_MESG +#define BLE_DBG_DTS_BUF PRINT_NO_MESG +#endif + +#endif /*__BLE_DBG_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index 5f129ba8c..2c30612b5 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -32,6 +32,7 @@ static uint8_t ble_glue_ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_ typedef struct { FuriMutex* shci_mtx; + FuriSemaphore* shci_sem; FuriThread* thread; BleGlueStatus status; BleGlueKeyStorageChangedCallback callback; @@ -103,6 +104,7 @@ void ble_glue_init() { TL_Init(); ble_glue->shci_mtx = furi_mutex_alloc(FuriMutexTypeNormal); + ble_glue->shci_sem = furi_semaphore_alloc(1, 0); // FreeRTOS system task creation ble_glue->thread = furi_thread_alloc_ex("BleShciDriver", 1024, ble_glue_shci_thread, ble_glue); @@ -391,6 +393,7 @@ void ble_glue_thread_stop() { furi_thread_free(ble_glue->thread); // Free resources furi_mutex_free(ble_glue->shci_mtx); + furi_semaphore_free(ble_glue->shci_sem); ble_glue_clear_shared_memory(); free(ble_glue); ble_glue = NULL; @@ -424,6 +427,22 @@ void shci_notify_asynch_evt(void* pdata) { } } +void shci_cmd_resp_release(uint32_t flag) { + UNUSED(flag); + if(ble_glue) { + furi_semaphore_release(ble_glue->shci_sem); + } +} + +void shci_cmd_resp_wait(uint32_t timeout) { + UNUSED(timeout); + if(ble_glue) { + furi_hal_power_insomnia_enter(); + furi_semaphore_acquire(ble_glue->shci_sem, FuriWaitForever); + furi_hal_power_insomnia_exit(); + } +} + bool ble_glue_reinit_c2() { return SHCI_C2_Reinit() == SHCI_Success; } diff --git a/firmware/targets/f7/ble_glue/compiler.h b/firmware/targets/f7/ble_glue/compiler.h index 1d32c2a2e..98a93d712 100644 --- a/firmware/targets/f7/ble_glue/compiler.h +++ b/firmware/targets/f7/ble_glue/compiler.h @@ -1,4 +1,22 @@ -#pragma once +/***************************************************************************** + * @file compiler.h + * @author MDG + * @brief This file contains the definitions which are compiler dependent. + ***************************************************************************** + * @attention + * + * Copyright (c) 2018-2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ***************************************************************************** + */ + +#ifndef COMPILER_H__ +#define COMPILER_H__ #ifndef __PACKED_STRUCT #define __PACKED_STRUCT PACKED(struct) @@ -136,3 +154,5 @@ #endif #endif #endif + +#endif /* COMPILER_H__ */ diff --git a/firmware/targets/f7/ble_glue/dev_info_service.c b/firmware/targets/f7/ble_glue/dev_info_service.c new file mode 100644 index 000000000..d24058632 --- /dev/null +++ b/firmware/targets/f7/ble_glue/dev_info_service.c @@ -0,0 +1,220 @@ +#include "dev_info_service.h" +#include "app_common.h" +#include + +#include +#include +#include + +#define TAG "BtDevInfoSvc" + +typedef struct { + uint16_t service_handle; + uint16_t man_name_char_handle; + uint16_t serial_num_char_handle; + uint16_t firmware_rev_char_handle; + uint16_t software_rev_char_handle; + uint16_t rpc_version_char_handle; + FuriString* version_string; + char hardware_revision[4]; +} DevInfoSvc; + +static DevInfoSvc* dev_info_svc = NULL; + +static const char dev_info_man_name[] = "Flipper Devices Inc."; +static const char dev_info_serial_num[] = "1.0"; +static const char dev_info_rpc_version[] = TOSTRING(PROTOBUF_MAJOR_VERSION.PROTOBUF_MINOR_VERSION); + +static const uint8_t dev_info_rpc_version_uuid[] = + {0x33, 0xa9, 0xb5, 0x3e, 0x87, 0x5d, 0x1a, 0x8e, 0xc8, 0x47, 0x5e, 0xae, 0x6d, 0x66, 0xf6, 0x03}; + +void dev_info_svc_start() { + dev_info_svc = malloc(sizeof(DevInfoSvc)); + dev_info_svc->version_string = furi_string_alloc_printf( + "%s %s %s %s", + version_get_githash(NULL), + version_get_version(NULL), + version_get_gitbranchnum(NULL), + version_get_builddate(NULL)); + snprintf( + dev_info_svc->hardware_revision, + sizeof(dev_info_svc->hardware_revision), + "%d", + version_get_target(NULL)); + tBleStatus status; + + // Add Device Information Service + uint16_t uuid = DEVICE_INFORMATION_SERVICE_UUID; + status = aci_gatt_add_service( + UUID_TYPE_16, (Service_UUID_t*)&uuid, PRIMARY_SERVICE, 11, &dev_info_svc->service_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add Device Information Service: %d", status); + } + + // Add characteristics + uuid = MANUFACTURER_NAME_UUID; + status = aci_gatt_add_char( + dev_info_svc->service_handle, + UUID_TYPE_16, + (Char_UUID_t*)&uuid, + strlen(dev_info_man_name), + CHAR_PROP_READ, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &dev_info_svc->man_name_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add manufacturer name char: %d", status); + } + uuid = SERIAL_NUMBER_UUID; + status = aci_gatt_add_char( + dev_info_svc->service_handle, + UUID_TYPE_16, + (Char_UUID_t*)&uuid, + strlen(dev_info_serial_num), + CHAR_PROP_READ, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &dev_info_svc->serial_num_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add serial number char: %d", status); + } + uuid = FIRMWARE_REVISION_UUID; + status = aci_gatt_add_char( + dev_info_svc->service_handle, + UUID_TYPE_16, + (Char_UUID_t*)&uuid, + strlen(dev_info_svc->hardware_revision), + CHAR_PROP_READ, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &dev_info_svc->firmware_rev_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add firmware revision char: %d", status); + } + uuid = SOFTWARE_REVISION_UUID; + status = aci_gatt_add_char( + dev_info_svc->service_handle, + UUID_TYPE_16, + (Char_UUID_t*)&uuid, + furi_string_size(dev_info_svc->version_string), + CHAR_PROP_READ, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &dev_info_svc->software_rev_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add software revision char: %d", status); + } + status = aci_gatt_add_char( + dev_info_svc->service_handle, + UUID_TYPE_128, + (const Char_UUID_t*)dev_info_rpc_version_uuid, + strlen(dev_info_rpc_version), + CHAR_PROP_READ, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &dev_info_svc->rpc_version_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add rpc version characteristic: %d", status); + } + + // Update characteristics + status = aci_gatt_update_char_value( + dev_info_svc->service_handle, + dev_info_svc->man_name_char_handle, + 0, + strlen(dev_info_man_name), + (uint8_t*)dev_info_man_name); + if(status) { + FURI_LOG_E(TAG, "Failed to update manufacturer name char: %d", status); + } + status = aci_gatt_update_char_value( + dev_info_svc->service_handle, + dev_info_svc->serial_num_char_handle, + 0, + strlen(dev_info_serial_num), + (uint8_t*)dev_info_serial_num); + if(status) { + FURI_LOG_E(TAG, "Failed to update serial number char: %d", status); + } + status = aci_gatt_update_char_value( + dev_info_svc->service_handle, + dev_info_svc->firmware_rev_char_handle, + 0, + strlen(dev_info_svc->hardware_revision), + (uint8_t*)dev_info_svc->hardware_revision); + if(status) { + FURI_LOG_E(TAG, "Failed to update firmware revision char: %d", status); + } + status = aci_gatt_update_char_value( + dev_info_svc->service_handle, + dev_info_svc->software_rev_char_handle, + 0, + furi_string_size(dev_info_svc->version_string), + (uint8_t*)furi_string_get_cstr(dev_info_svc->version_string)); + if(status) { + FURI_LOG_E(TAG, "Failed to update software revision char: %d", status); + } + status = aci_gatt_update_char_value( + dev_info_svc->service_handle, + dev_info_svc->rpc_version_char_handle, + 0, + strlen(dev_info_rpc_version), + (uint8_t*)dev_info_rpc_version); + if(status) { + FURI_LOG_E(TAG, "Failed to update rpc version char: %d", status); + } +} + +void dev_info_svc_stop() { + tBleStatus status; + if(dev_info_svc) { + furi_string_free(dev_info_svc->version_string); + // Delete service characteristics + status = + aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->man_name_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete manufacturer name char: %d", status); + } + status = + aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->serial_num_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete serial number char: %d", status); + } + status = aci_gatt_del_char( + dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete firmware revision char: %d", status); + } + status = aci_gatt_del_char( + dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete software revision char: %d", status); + } + status = + aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->rpc_version_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete rpc version char: %d", status); + } + // Delete service + status = aci_gatt_del_service(dev_info_svc->service_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete device info service: %d", status); + } + free(dev_info_svc); + dev_info_svc = NULL; + } +} + +bool dev_info_svc_is_started() { + return dev_info_svc != NULL; +} diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.h b/firmware/targets/f7/ble_glue/dev_info_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/services/dev_info_service.h rename to firmware/targets/f7/ble_glue/dev_info_service.h diff --git a/firmware/targets/f7/ble_glue/hid_service.c b/firmware/targets/f7/ble_glue/hid_service.c new file mode 100644 index 000000000..a31d6015f --- /dev/null +++ b/firmware/targets/f7/ble_glue/hid_service.c @@ -0,0 +1,416 @@ +#include "hid_service.h" +#include "app_common.h" +#include + +#include + +#define TAG "BtHid" + +typedef struct { + uint16_t svc_handle; + uint16_t protocol_mode_char_handle; + uint16_t report_char_handle[HID_SVC_REPORT_COUNT]; + uint16_t report_ref_desc_handle[HID_SVC_REPORT_COUNT]; + uint16_t report_map_char_handle; + uint16_t info_char_handle; + uint16_t ctrl_point_char_handle; + // led state + uint16_t led_state_char_handle; + uint16_t led_state_desc_handle; + HidLedStateEventCallback led_state_event_callback; + void* led_state_ctx; +} HIDSvc; + +static HIDSvc* hid_svc = NULL; + +static SVCCTL_EvtAckStatus_t hid_svc_event_handler(void* event) { + SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; + hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data); + evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data; + // aci_gatt_attribute_modified_event_rp0* attribute_modified; + if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) { + if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) { + // Process modification events + ret = SVCCTL_EvtAckFlowEnable; + } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { + // Process notification confirmation + ret = SVCCTL_EvtAckFlowEnable; + } else if(blecore_evt->ecode == ACI_GATT_WRITE_PERMIT_REQ_VSEVT_CODE) { + // Process write request + aci_gatt_write_permit_req_event_rp0* req = + (aci_gatt_write_permit_req_event_rp0*)blecore_evt->data; + + furi_check(hid_svc->led_state_event_callback && hid_svc->led_state_ctx); + + // this check is likely to be incorrect, it will actually work in our case + // but we need to investigate gatt api to see what is the rules + // that specify attibute handle value from char handle (or the reverse) + if(req->Attribute_Handle == (hid_svc->led_state_char_handle + 1)) { + hid_svc->led_state_event_callback(req->Data[0], hid_svc->led_state_ctx); + aci_gatt_write_resp( + req->Connection_Handle, + req->Attribute_Handle, + 0x00, /* write_status = 0 (no error))*/ + 0x00, /* err_code */ + req->Data_Length, + req->Data); + aci_gatt_write_char_value( + req->Connection_Handle, + hid_svc->led_state_char_handle, + req->Data_Length, + req->Data); + ret = SVCCTL_EvtAckFlowEnable; + } + } + } + return ret; +} + +void hid_svc_start() { + tBleStatus status; + hid_svc = malloc(sizeof(HIDSvc)); + Service_UUID_t svc_uuid = {}; + Char_Desc_Uuid_t desc_uuid = {}; + Char_UUID_t char_uuid = {}; + + // Register event handler + SVCCTL_RegisterSvcHandler(hid_svc_event_handler); + // Add service + svc_uuid.Service_UUID_16 = HUMAN_INTERFACE_DEVICE_SERVICE_UUID; + /** + * Add Human Interface Device Service + */ + status = aci_gatt_add_service( + UUID_TYPE_16, + &svc_uuid, + PRIMARY_SERVICE, + 2 + /* protocol mode */ + (4 * HID_SVC_INPUT_REPORT_COUNT) + (3 * HID_SVC_OUTPUT_REPORT_COUNT) + + (3 * HID_SVC_FEATURE_REPORT_COUNT) + 1 + 2 + 2 + 2 + + 4, /* Service + Report Map + HID Information + HID Control Point + LED state */ + &hid_svc->svc_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add HID service: %d", status); + } + // Add Protocol mode characteristics + char_uuid.Char_UUID_16 = PROTOCOL_MODE_CHAR_UUID; + status = aci_gatt_add_char( + hid_svc->svc_handle, + UUID_TYPE_16, + &char_uuid, + 1, + CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP, + ATTR_PERMISSION_NONE, + GATT_NOTIFY_ATTRIBUTE_WRITE, + 10, + CHAR_VALUE_LEN_CONSTANT, + &hid_svc->protocol_mode_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add protocol mode characteristic: %d", status); + } + // Update Protocol mode characteristic + uint8_t protocol_mode = 1; + status = aci_gatt_update_char_value( + hid_svc->svc_handle, hid_svc->protocol_mode_char_handle, 0, 1, &protocol_mode); + if(status) { + FURI_LOG_E(TAG, "Failed to update protocol mode characteristic: %d", status); + } + +#if(HID_SVC_REPORT_COUNT != 0) + for(uint8_t i = 0; i < HID_SVC_REPORT_COUNT; i++) { + if(i < HID_SVC_INPUT_REPORT_COUNT) { //-V547 + uint8_t buf[2] = {i + 1, 1}; // 1 input + char_uuid.Char_UUID_16 = REPORT_CHAR_UUID; + status = aci_gatt_add_char( + hid_svc->svc_handle, + UUID_TYPE_16, + &char_uuid, + HID_SVC_REPORT_MAX_LEN, + CHAR_PROP_READ | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_NONE, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_VARIABLE, + &(hid_svc->report_char_handle[i])); + if(status) { + FURI_LOG_E(TAG, "Failed to add report characteristic: %d", status); + } + + desc_uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID; + status = aci_gatt_add_char_desc( + hid_svc->svc_handle, + hid_svc->report_char_handle[i], + UUID_TYPE_16, + &desc_uuid, + HID_SVC_REPORT_REF_LEN, + HID_SVC_REPORT_REF_LEN, + buf, + ATTR_PERMISSION_NONE, + ATTR_ACCESS_READ_WRITE, + GATT_DONT_NOTIFY_EVENTS, + MIN_ENCRY_KEY_SIZE, + CHAR_VALUE_LEN_CONSTANT, + &(hid_svc->report_ref_desc_handle[i])); + if(status) { + FURI_LOG_E(TAG, "Failed to add report reference descriptor: %d", status); + } + } else if((i - HID_SVC_INPUT_REPORT_COUNT) < HID_SVC_OUTPUT_REPORT_COUNT) { + uint8_t buf[2] = {i + 1, 2}; // 2 output + char_uuid.Char_UUID_16 = REPORT_CHAR_UUID; + status = aci_gatt_add_char( + hid_svc->svc_handle, + UUID_TYPE_16, + &char_uuid, + HID_SVC_REPORT_MAX_LEN, + CHAR_PROP_READ | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_NONE, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_VARIABLE, + &(hid_svc->report_char_handle[i])); + if(status) { + FURI_LOG_E(TAG, "Failed to add report characteristic: %d", status); + } + + desc_uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID; + status = aci_gatt_add_char_desc( + hid_svc->svc_handle, + hid_svc->report_char_handle[i], + UUID_TYPE_16, + &desc_uuid, + HID_SVC_REPORT_REF_LEN, + HID_SVC_REPORT_REF_LEN, + buf, + ATTR_PERMISSION_NONE, + ATTR_ACCESS_READ_WRITE, + GATT_DONT_NOTIFY_EVENTS, + MIN_ENCRY_KEY_SIZE, + CHAR_VALUE_LEN_CONSTANT, + &(hid_svc->report_ref_desc_handle[i])); + if(status) { + FURI_LOG_E(TAG, "Failed to add report reference descriptor: %d", status); + } + } else { + uint8_t buf[2] = {i + 1, 3}; // 3 feature + char_uuid.Char_UUID_16 = REPORT_CHAR_UUID; + status = aci_gatt_add_char( + hid_svc->svc_handle, + UUID_TYPE_16, + &char_uuid, + HID_SVC_REPORT_MAX_LEN, + CHAR_PROP_READ | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_NONE, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_VARIABLE, + &(hid_svc->report_char_handle[i])); + if(status) { + FURI_LOG_E(TAG, "Failed to add report characteristic: %d", status); + } + + desc_uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID; + status = aci_gatt_add_char_desc( + hid_svc->svc_handle, + hid_svc->report_char_handle[i], + UUID_TYPE_16, + &desc_uuid, + HID_SVC_REPORT_REF_LEN, + HID_SVC_REPORT_REF_LEN, + buf, + ATTR_PERMISSION_NONE, + ATTR_ACCESS_READ_WRITE, + GATT_DONT_NOTIFY_EVENTS, + MIN_ENCRY_KEY_SIZE, + CHAR_VALUE_LEN_CONSTANT, + &(hid_svc->report_ref_desc_handle[i])); + if(status) { + FURI_LOG_E(TAG, "Failed to add report reference descriptor: %d", status); + } + } + } +#endif + // Add led state output report + char_uuid.Char_UUID_16 = REPORT_CHAR_UUID; + status = aci_gatt_add_char( + hid_svc->svc_handle, + UUID_TYPE_16, + &char_uuid, + 1, + CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE, + ATTR_PERMISSION_NONE, + GATT_NOTIFY_ATTRIBUTE_WRITE | GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP, + 10, + CHAR_VALUE_LEN_CONSTANT, + &(hid_svc->led_state_char_handle)); + if(status) { + FURI_LOG_E(TAG, "Failed to add led state characteristic: %d", status); + } + + // Add led state char descriptor specifying it is an output report + uint8_t buf[2] = {HID_SVC_REPORT_COUNT + 1, 2}; + desc_uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID; + status = aci_gatt_add_char_desc( + hid_svc->svc_handle, + hid_svc->led_state_char_handle, + UUID_TYPE_16, + &desc_uuid, + HID_SVC_REPORT_REF_LEN, + HID_SVC_REPORT_REF_LEN, + buf, + ATTR_PERMISSION_NONE, + ATTR_ACCESS_READ_WRITE, + GATT_DONT_NOTIFY_EVENTS, + MIN_ENCRY_KEY_SIZE, + CHAR_VALUE_LEN_CONSTANT, + &(hid_svc->led_state_desc_handle)); + if(status) { + FURI_LOG_E(TAG, "Failed to add led state descriptor: %d", status); + } + // Add Report Map characteristic + char_uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID; + status = aci_gatt_add_char( + hid_svc->svc_handle, + UUID_TYPE_16, + &char_uuid, + HID_SVC_REPORT_MAP_MAX_LEN, + CHAR_PROP_READ, + ATTR_PERMISSION_NONE, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_VARIABLE, + &hid_svc->report_map_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add report map characteristic: %d", status); + } + + // Add Information characteristic + char_uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID; + status = aci_gatt_add_char( + hid_svc->svc_handle, + UUID_TYPE_16, + &char_uuid, + HID_SVC_INFO_LEN, + CHAR_PROP_READ, + ATTR_PERMISSION_NONE, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &hid_svc->info_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add information characteristic: %d", status); + } + // Add Control Point characteristic + char_uuid.Char_UUID_16 = HID_CONTROL_POINT_CHAR_UUID; + status = aci_gatt_add_char( + hid_svc->svc_handle, + UUID_TYPE_16, + &char_uuid, + HID_SVC_CONTROL_POINT_LEN, + CHAR_PROP_WRITE_WITHOUT_RESP, + ATTR_PERMISSION_NONE, + GATT_NOTIFY_ATTRIBUTE_WRITE, + 10, + CHAR_VALUE_LEN_CONSTANT, + &hid_svc->ctrl_point_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add control point characteristic: %d", status); + } + + hid_svc->led_state_event_callback = NULL; + hid_svc->led_state_ctx = NULL; +} + +bool hid_svc_update_report_map(const uint8_t* data, uint16_t len) { + furi_assert(data); + furi_assert(hid_svc); + + tBleStatus status = aci_gatt_update_char_value( + hid_svc->svc_handle, hid_svc->report_map_char_handle, 0, len, data); + if(status) { + FURI_LOG_E(TAG, "Failed updating report map characteristic: %d", status); + return false; + } + return true; +} + +bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16_t len) { + furi_assert(data); + furi_assert(hid_svc); + + tBleStatus status = aci_gatt_update_char_value( + hid_svc->svc_handle, hid_svc->report_char_handle[input_report_num], 0, len, data); + if(status) { + FURI_LOG_E(TAG, "Failed updating report characteristic: %d", status); + return false; + } + return true; +} + +bool hid_svc_update_info(uint8_t* data, uint16_t len) { + furi_assert(data); + furi_assert(hid_svc); + + tBleStatus status = + aci_gatt_update_char_value(hid_svc->svc_handle, hid_svc->info_char_handle, 0, len, data); + if(status) { + FURI_LOG_E(TAG, "Failed updating info characteristic: %d", status); + return false; + } + return true; +} + +void hid_svc_register_led_state_callback(HidLedStateEventCallback callback, void* context) { + furi_assert(hid_svc); + furi_assert(callback); + furi_assert(context); + + hid_svc->led_state_event_callback = callback; + hid_svc->led_state_ctx = context; +} + +bool hid_svc_is_started() { + return hid_svc != NULL; +} + +void hid_svc_stop() { + tBleStatus status; + if(hid_svc) { + // Delete characteristics + status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->report_map_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Report Map characteristic: %d", status); + } +#if(HID_SVC_INPUT_REPORT_COUNT != 0) + for(uint8_t i = 0; i < HID_SVC_REPORT_COUNT; i++) { + status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->report_char_handle[i]); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Report characteristic: %d", status); + } + } +#endif + status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->protocol_mode_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Protocol Mode characteristic: %d", status); + } + status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->info_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Information characteristic: %d", status); + } + status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->ctrl_point_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Control Point characteristic: %d", status); + } + status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->led_state_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete led state characteristic: %d", status); + } + // Delete service + status = aci_gatt_del_service(hid_svc->svc_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete HID service: %d", status); + } + // Delete buffer size mutex + free(hid_svc); + hid_svc = NULL; + } +} diff --git a/firmware/targets/f7/ble_glue/services/hid_service.h b/firmware/targets/f7/ble_glue/hid_service.h similarity index 89% rename from firmware/targets/f7/ble_glue/services/hid_service.h rename to firmware/targets/f7/ble_glue/hid_service.h index 4d0ed4c4f..b8f6b244d 100644 --- a/firmware/targets/f7/ble_glue/services/hid_service.h +++ b/firmware/targets/f7/ble_glue/hid_service.h @@ -27,7 +27,6 @@ bool hid_svc_update_report_map(const uint8_t* data, uint16_t len); bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16_t len); -// Expects data to be of length HID_SVC_INFO_LEN (4 bytes) -bool hid_svc_update_info(uint8_t* data); +bool hid_svc_update_info(uint8_t* data, uint16_t len); void hid_svc_register_led_state_callback(HidLedStateEventCallback callback, void* context); diff --git a/firmware/targets/f7/ble_glue/hsem_map.h b/firmware/targets/f7/ble_glue/hsem_map.h deleted file mode 100644 index 9a5f51d20..000000000 --- a/firmware/targets/f7/ble_glue/hsem_map.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -/****************************************************************************** - * Semaphores - * THIS SHALL NO BE CHANGED AS THESE SEMAPHORES ARE USED AS WELL ON THE CM0+ - *****************************************************************************/ -/** -* Index of the semaphore used the prevent conflicts after standby sleep. -* Each CPUs takes this semaphore at standby wakeup until conflicting elements are restored. -*/ -#define CFG_HW_PWR_STANDBY_SEMID 10 -/** -* The CPU2 may be configured to store the Thread persistent data either in internal NVM storage on CPU2 or in -* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config() -* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed. -* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be: -* + CPU1 takes CFG_HW_THREAD_NVM_SRAM_SEMID semaphore -* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1) -* + CPU1 releases CFG_HW_THREAD_NVM_SRAM_SEMID semaphore -* CFG_HW_THREAD_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them. -* There is no timing constraint on how long this semaphore can be kept. -*/ -#define CFG_HW_THREAD_NVM_SRAM_SEMID 9 - -/** -* The CPU2 may be configured to store the BLE persistent data either in internal NVM storage on CPU2 or in -* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config() -* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed. -* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be: -* + CPU1 takes CFG_HW_BLE_NVM_SRAM_SEMID semaphore -* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1) -* + CPU1 releases CFG_HW_BLE_NVM_SRAM_SEMID semaphore -* CFG_HW_BLE_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them. -* There is no timing constraint on how long this semaphore can be kept. -*/ -#define CFG_HW_BLE_NVM_SRAM_SEMID 8 - -/** -* Index of the semaphore used by CPU2 to prevent the CPU1 to either write or erase data in flash -* The CPU1 shall not either write or erase in flash when this semaphore is taken by the CPU2 -* When the CPU1 needs to either write or erase in flash, it shall first get the semaphore and release it just -* after writing a raw (64bits data) or erasing one sector. -* Once the Semaphore has been released, there shall be at least 1us before it can be taken again. This is required -* to give the opportunity to CPU2 to take it. -* On v1.4.0 and older CPU2 wireless firmware, this semaphore is unused and CPU2 is using PES bit. -* By default, CPU2 is using the PES bit to protect its timing. The CPU1 may request the CPU2 to use the semaphore -* instead of the PES bit by sending the system command SHCI_C2_SetFlashActivityControl() -*/ -#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID 7 - -/** -* Index of the semaphore used by CPU1 to prevent the CPU2 to either write or erase data in flash -* In order to protect its timing, the CPU1 may get this semaphore to prevent the CPU2 to either -* write or erase in flash (as this will stall both CPUs) -* The PES bit shall not be used as this may stall the CPU2 in some cases. -*/ -#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID 6 - -/** -* Index of the semaphore used to manage the CLK48 clock configuration -* When the USB is required, this semaphore shall be taken before configuring te CLK48 for USB -* and should be released after the application switch OFF the clock when the USB is not used anymore -* When using the RNG, it is good enough to use CFG_HW_RNG_SEMID to control CLK48. -* More details in AN5289 -*/ -#define CFG_HW_CLK48_CONFIG_SEMID 5 - -/* Index of the semaphore used to manage the entry Stop Mode procedure */ -#define CFG_HW_ENTRY_STOP_MODE_SEMID 4 - -/* Index of the semaphore used to access the RCC */ -#define CFG_HW_RCC_SEMID 3 - -/* Index of the semaphore used to access the FLASH */ -#define CFG_HW_FLASH_SEMID 2 - -/* Index of the semaphore used to access the PKA */ -#define CFG_HW_PKA_SEMID 1 - -/* Index of the semaphore used to access the RNG */ -#define CFG_HW_RNG_SEMID 0 diff --git a/firmware/targets/f7/ble_glue/hw_conf.h b/firmware/targets/f7/ble_glue/hw_conf.h new file mode 100644 index 000000000..bf18a7d0e --- /dev/null +++ b/firmware/targets/f7/ble_glue/hw_conf.h @@ -0,0 +1,231 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file hw_conf.h + * @author MCD Application Team + * @brief Configuration of hardware interface + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef HW_CONF_H +#define HW_CONF_H + +#include "FreeRTOSConfig.h" + +/****************************************************************************** + * Semaphores + * THIS SHALL NO BE CHANGED AS THESE SEMAPHORES ARE USED AS WELL ON THE CM0+ + *****************************************************************************/ +/** +* Index of the semaphore used the prevent conflicts after standby sleep. +* Each CPUs takes this semaphore at standby wakeup until conclicting elements are restored. +*/ +#define CFG_HW_PWR_STANDBY_SEMID 10 +/** +* The CPU2 may be configured to store the Thread persistent data either in internal NVM storage on CPU2 or in +* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config() +* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed. +* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be: +* + CPU1 takes CFG_HW_THREAD_NVM_SRAM_SEMID semaphore +* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1) +* + CPU1 releases CFG_HW_THREAD_NVM_SRAM_SEMID semaphore +* CFG_HW_THREAD_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them. +* There is no timing constraint on how long this semaphore can be kept. +*/ +#define CFG_HW_THREAD_NVM_SRAM_SEMID 9 + +/** +* The CPU2 may be configured to store the BLE persistent data either in internal NVM storage on CPU2 or in +* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config() +* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed. +* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be: +* + CPU1 takes CFG_HW_BLE_NVM_SRAM_SEMID semaphore +* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1) +* + CPU1 releases CFG_HW_BLE_NVM_SRAM_SEMID semaphore +* CFG_HW_BLE_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them. +* There is no timing constraint on how long this semaphore can be kept. +*/ +#define CFG_HW_BLE_NVM_SRAM_SEMID 8 + +/** +* Index of the semaphore used by CPU2 to prevent the CPU1 to either write or erase data in flash +* The CPU1 shall not either write or erase in flash when this semaphore is taken by the CPU2 +* When the CPU1 needs to either write or erase in flash, it shall first get the semaphore and release it just +* after writing a raw (64bits data) or erasing one sector. +* Once the Semaphore has been released, there shall be at least 1us before it can be taken again. This is required +* to give the opportunity to CPU2 to take it. +* On v1.4.0 and older CPU2 wireless firmware, this semaphore is unused and CPU2 is using PES bit. +* By default, CPU2 is using the PES bit to protect its timing. The CPU1 may request the CPU2 to use the semaphore +* instead of the PES bit by sending the system command SHCI_C2_SetFlashActivityControl() +*/ +#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID 7 + +/** +* Index of the semaphore used by CPU1 to prevent the CPU2 to either write or erase data in flash +* In order to protect its timing, the CPU1 may get this semaphore to prevent the CPU2 to either +* write or erase in flash (as this will stall both CPUs) +* The PES bit shall not be used as this may stall the CPU2 in some cases. +*/ +#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID 6 + +/** +* Index of the semaphore used to manage the CLK48 clock configuration +* When the USB is required, this semaphore shall be taken before configuring te CLK48 for USB +* and should be released after the application switch OFF the clock when the USB is not used anymore +* When using the RNG, it is good enough to use CFG_HW_RNG_SEMID to control CLK48. +* More details in AN5289 +*/ +#define CFG_HW_CLK48_CONFIG_SEMID 5 + +/* Index of the semaphore used to manage the entry Stop Mode procedure */ +#define CFG_HW_ENTRY_STOP_MODE_SEMID 4 + +/* Index of the semaphore used to access the RCC */ +#define CFG_HW_RCC_SEMID 3 + +/* Index of the semaphore used to access the FLASH */ +#define CFG_HW_FLASH_SEMID 2 + +/* Index of the semaphore used to access the PKA */ +#define CFG_HW_PKA_SEMID 1 + +/* Index of the semaphore used to access the RNG */ +#define CFG_HW_RNG_SEMID 0 + +/****************************************************************************** + * HW TIMER SERVER + *****************************************************************************/ +/** + * The user may define the maximum number of virtual timers supported. + * It shall not exceed 255 + */ +#define CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER 6 + +/** + * The user may define the priority in the NVIC of the RTC_WKUP interrupt handler that is used to manage the + * wakeup timer. + * This setting is the preemptpriority part of the NVIC. + */ +#define CFG_HW_TS_NVIC_RTC_WAKEUP_IT_PREEMPTPRIO \ + (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1) /* FreeRTOS requirement */ + +/** + * The user may define the priority in the NVIC of the RTC_WKUP interrupt handler that is used to manage the + * wakeup timer. + * This setting is the subpriority part of the NVIC. It does not exist on all processors. When it is not supported + * on the CPU, the setting is ignored + */ +#define CFG_HW_TS_NVIC_RTC_WAKEUP_IT_SUBPRIO 0 + +/** + * Define a critical section in the Timer server + * The Timer server does not support the API to be nested + * The Application shall either: + * a) Ensure this will never happen + * b) Define the critical section + * The default implementations is masking all interrupts using the PRIMASK bit + * The TimerServer driver uses critical sections to avoid context corruption. This is achieved with the macro + * TIMER_ENTER_CRITICAL_SECTION and TIMER_EXIT_CRITICAL_SECTION. When CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION is set + * to 1, all STM32 interrupts are masked with the PRIMASK bit of the CortexM CPU. It is possible to use the BASEPRI + * register of the CortexM CPU to keep allowed some interrupts with high priority. In that case, the user shall + * re-implement TIMER_ENTER_CRITICAL_SECTION and TIMER_EXIT_CRITICAL_SECTION and shall make sure that no TimerServer + * API are called when the TIMER critical section is entered + */ +#define CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION 1 + +/** + * This value shall reflect the maximum delay there could be in the application between the time the RTC interrupt + * is generated by the Hardware and the time when the RTC interrupt handler is called. This time is measured in + * number of RTCCLK ticks. + * A relaxed timing would be 10ms + * When the value is too short, the timerserver will not be able to count properly and all timeout may be random. + * When the value is too long, the device may wake up more often than the most optimal configuration. However, the + * impact on power consumption would be marginal (unless the value selected is extremely too long). It is strongly + * recommended to select a value large enough to make sure it is not too short to ensure reliability of the system + * as this will have marginal impact on low power mode + */ +#define CFG_HW_TS_RTC_HANDLER_MAX_DELAY (10 * (LSI_VALUE / 1000)) + +/** + * Interrupt ID in the NVIC of the RTC Wakeup interrupt handler + * It shall be type of IRQn_Type + */ +#define CFG_HW_TS_RTC_WAKEUP_HANDLER_ID RTC_WKUP_IRQn + +/****************************************************************************** + * HW UART + *****************************************************************************/ +#define CFG_HW_LPUART1_ENABLED 0 +#define CFG_HW_LPUART1_DMA_TX_SUPPORTED 0 + +#define CFG_HW_USART1_ENABLED 1 +#define CFG_HW_USART1_DMA_TX_SUPPORTED 1 + +/** + * UART1 + */ +#define CFG_HW_USART1_PREEMPTPRIORITY 0x0F +#define CFG_HW_USART1_SUBPRIORITY 0 + +/** < The application shall check the selected source clock is enable */ +#define CFG_HW_USART1_SOURCE_CLOCK RCC_USART1CLKSOURCE_SYSCLK + +#define CFG_HW_USART1_BAUDRATE 115200 +#define CFG_HW_USART1_WORDLENGTH UART_WORDLENGTH_8B +#define CFG_HW_USART1_STOPBITS UART_STOPBITS_1 +#define CFG_HW_USART1_PARITY UART_PARITY_NONE +#define CFG_HW_USART1_HWFLOWCTL UART_HWCONTROL_NONE +#define CFG_HW_USART1_MODE UART_MODE_TX_RX +#define CFG_HW_USART1_ADVFEATUREINIT UART_ADVFEATURE_NO_INIT +#define CFG_HW_USART1_OVERSAMPLING UART_OVERSAMPLING_8 + +#define CFG_HW_USART1_TX_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE +#define CFG_HW_USART1_TX_PORT GPIOB +#define CFG_HW_USART1_TX_PIN GPIO_PIN_6 +#define CFG_HW_USART1_TX_MODE GPIO_MODE_AF_PP +#define CFG_HW_USART1_TX_PULL GPIO_NOPULL +#define CFG_HW_USART1_TX_SPEED GPIO_SPEED_FREQ_VERY_HIGH +#define CFG_HW_USART1_TX_ALTERNATE GPIO_AF7_USART1 + +#define CFG_HW_USART1_RX_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE +#define CFG_HW_USART1_RX_PORT GPIOB +#define CFG_HW_USART1_RX_PIN GPIO_PIN_7 +#define CFG_HW_USART1_RX_MODE GPIO_MODE_AF_PP +#define CFG_HW_USART1_RX_PULL GPIO_NOPULL +#define CFG_HW_USART1_RX_SPEED GPIO_SPEED_FREQ_VERY_HIGH +#define CFG_HW_USART1_RX_ALTERNATE GPIO_AF7_USART1 + +#define CFG_HW_USART1_CTS_PORT_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE +#define CFG_HW_USART1_CTS_PORT GPIOA +#define CFG_HW_USART1_CTS_PIN GPIO_PIN_11 +#define CFG_HW_USART1_CTS_MODE GPIO_MODE_AF_PP +#define CFG_HW_USART1_CTS_PULL GPIO_PULLDOWN +#define CFG_HW_USART1_CTS_SPEED GPIO_SPEED_FREQ_VERY_HIGH +#define CFG_HW_USART1_CTS_ALTERNATE GPIO_AF7_USART1 + +#define CFG_HW_USART1_DMA_TX_PREEMPTPRIORITY 0x0F +#define CFG_HW_USART1_DMA_TX_SUBPRIORITY 0 + +#define CFG_HW_USART1_DMAMUX_CLK_ENABLE __HAL_RCC_DMAMUX1_CLK_ENABLE +#define CFG_HW_USART1_DMA_CLK_ENABLE __HAL_RCC_DMA2_CLK_ENABLE +#define CFG_HW_USART1_TX_DMA_REQ DMA_REQUEST_USART1_TX +#define CFG_HW_USART1_TX_DMA_CHANNEL DMA2_Channel4 +#define CFG_HW_USART1_TX_DMA_IRQn DMA2_Channel4_IRQn +#define CFG_HW_USART1_DMA_TX_IRQHandler DMA2_Channel4_IRQHandler + +#endif /*HW_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/ble_glue/hw_if.h b/firmware/targets/f7/ble_glue/hw_if.h new file mode 100644 index 000000000..a0ac23df3 --- /dev/null +++ b/firmware/targets/f7/ble_glue/hw_if.h @@ -0,0 +1,102 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file hw_if.h + * @author MCD Application Team + * @brief Hardware Interface + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef HW_IF_H +#define HW_IF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32wbxx.h" +#include "stm32wbxx_ll_exti.h" +#include "stm32wbxx_ll_system.h" +#include "stm32wbxx_ll_rcc.h" +#include "stm32wbxx_ll_ipcc.h" +#include "stm32wbxx_ll_bus.h" +#include "stm32wbxx_ll_pwr.h" +#include "stm32wbxx_ll_cortex.h" +#include "stm32wbxx_ll_utils.h" +#include "stm32wbxx_ll_hsem.h" +#include "stm32wbxx_ll_gpio.h" +#include "stm32wbxx_ll_rtc.h" + +#ifdef USE_STM32WBXX_USB_DONGLE +#include "stm32wbxx_usb_dongle.h" +#endif +#ifdef USE_STM32WBXX_NUCLEO +#include "stm32wbxx_nucleo.h" +#endif +#ifdef USE_X_NUCLEO_EPD +#include "x_nucleo_epd.h" +#endif + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/****************************************************************************** + * HW UART + ******************************************************************************/ +typedef enum { + hw_uart1, + hw_uart2, + hw_lpuart1, +} hw_uart_id_t; + +typedef enum { + hw_uart_ok, + hw_uart_error, + hw_uart_busy, + hw_uart_to, +} hw_status_t; + +void HW_UART_Init(hw_uart_id_t hw_uart_id); +void HW_UART_Receive_IT( + hw_uart_id_t hw_uart_id, + uint8_t* pData, + uint16_t Size, + void (*Callback)(void)); +void HW_UART_Transmit_IT( + hw_uart_id_t hw_uart_id, + uint8_t* pData, + uint16_t Size, + void (*Callback)(void)); +hw_status_t + HW_UART_Transmit(hw_uart_id_t hw_uart_id, uint8_t* p_data, uint16_t size, uint32_t timeout); +hw_status_t HW_UART_Transmit_DMA( + hw_uart_id_t hw_uart_id, + uint8_t* p_data, + uint16_t size, + void (*Callback)(void)); +void HW_UART_Interrupt_Handler(hw_uart_id_t hw_uart_id); +void HW_UART_DMA_Interrupt_Handler(hw_uart_id_t hw_uart_id); + +#ifdef __cplusplus +} +#endif + +#endif /*HW_IF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/ble_glue/hw_ipcc.c b/firmware/targets/f7/ble_glue/hw_ipcc.c index c2397f351..7c84df09f 100644 --- a/firmware/targets/f7/ble_glue/hw_ipcc.c +++ b/firmware/targets/f7/ble_glue/hw_ipcc.c @@ -1,52 +1,160 @@ +/** + ****************************************************************************** + * File Name : Target/hw_ipcc.c + * Description : Hardware IPCC source file for STM32WPAN Middleware. + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ #include "app_common.h" #include -#include -#include - -#include -#include - -#include - -#define HW_IPCC_TX_PENDING(channel) \ - ((!(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, channel))) && \ - LL_C1_IPCC_IsEnabledTransmitChannel(IPCC, channel)) -#define HW_IPCC_RX_PENDING(channel) \ - (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, channel) && \ - LL_C1_IPCC_IsEnabledReceiveChannel(IPCC, channel)) -static void (*FreeBufCb)(); - -static void HW_IPCC_BLE_EvtHandler(); -static void HW_IPCC_BLE_AclDataEvtHandler(); -static void HW_IPCC_MM_FreeBufHandler(); -static void HW_IPCC_SYS_CmdEvtHandler(); -static void HW_IPCC_SYS_EvtHandler(); -static void HW_IPCC_TRACES_EvtHandler(); - -void HW_IPCC_Rx_Handler() { +/* Global variables ---------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +#define HW_IPCC_TX_PENDING(channel) \ + (!(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, channel))) && (((~(IPCC->C1MR)) & ((channel) << 16U))) +#define HW_IPCC_RX_PENDING(channel) \ + (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, channel)) && (((~(IPCC->C1MR)) & ((channel) << 0U))) + +/* Private macros ------------------------------------------------------------*/ +/* Private typedef -----------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +static void (*FreeBufCb)(void); + +/* Private function prototypes -----------------------------------------------*/ +static void HW_IPCC_BLE_EvtHandler(void); +static void HW_IPCC_BLE_AclDataEvtHandler(void); +static void HW_IPCC_MM_FreeBufHandler(void); +static void HW_IPCC_SYS_CmdEvtHandler(void); +static void HW_IPCC_SYS_EvtHandler(void); +static void HW_IPCC_TRACES_EvtHandler(void); + +#ifdef THREAD_WB +static void HW_IPCC_OT_CmdEvtHandler(void); +static void HW_IPCC_THREAD_NotEvtHandler(void); +static void HW_IPCC_THREAD_CliNotEvtHandler(void); +#endif + +#ifdef LLD_TESTS_WB +static void HW_IPCC_LLDTESTS_ReceiveCliRspHandler(void); +static void HW_IPCC_LLDTESTS_ReceiveM0CmdHandler(void); +#endif +#ifdef LLD_BLE_WB +/*static void HW_IPCC_LLD_BLE_ReceiveCliRspHandler( void );*/ +static void HW_IPCC_LLD_BLE_ReceiveRspHandler(void); +static void HW_IPCC_LLD_BLE_ReceiveM0CmdHandler(void); +#endif + +#ifdef MAC_802_15_4_WB +static void HW_IPCC_MAC_802_15_4_CmdEvtHandler(void); +static void HW_IPCC_MAC_802_15_4_NotEvtHandler(void); +#endif + +#ifdef ZIGBEE_WB +static void HW_IPCC_ZIGBEE_CmdEvtHandler(void); +static void HW_IPCC_ZIGBEE_StackNotifEvtHandler(void); +static void HW_IPCC_ZIGBEE_StackM0RequestHandler(void); +#endif + +/* Public function definition -----------------------------------------------*/ + +/****************************************************************************** + * INTERRUPT HANDLER + ******************************************************************************/ +void HW_IPCC_Rx_Handler(void) { if(HW_IPCC_RX_PENDING(HW_IPCC_SYSTEM_EVENT_CHANNEL)) { HW_IPCC_SYS_EvtHandler(); - } else if(HW_IPCC_RX_PENDING(HW_IPCC_BLE_EVENT_CHANNEL)) { + } +#ifdef MAC_802_15_4_WB + else if(HW_IPCC_RX_PENDING(HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL)) { + HW_IPCC_MAC_802_15_4_NotEvtHandler(); + } +#endif /* MAC_802_15_4_WB */ +#ifdef THREAD_WB + else if(HW_IPCC_RX_PENDING(HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL)) { + HW_IPCC_THREAD_NotEvtHandler(); + } else if(HW_IPCC_RX_PENDING(HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL)) { + HW_IPCC_THREAD_CliNotEvtHandler(); + } +#endif /* THREAD_WB */ +#ifdef LLD_TESTS_WB + else if(HW_IPCC_RX_PENDING(HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL)) { + HW_IPCC_LLDTESTS_ReceiveCliRspHandler(); + } else if(HW_IPCC_RX_PENDING(HW_IPCC_LLDTESTS_M0_CMD_CHANNEL)) { + HW_IPCC_LLDTESTS_ReceiveM0CmdHandler(); + } +#endif /* LLD_TESTS_WB */ +#ifdef LLD_BLE_WB + else if(HW_IPCC_RX_PENDING(HW_IPCC_LLD_BLE_RSP_CHANNEL)) { + HW_IPCC_LLD_BLE_ReceiveRspHandler(); + } else if(HW_IPCC_RX_PENDING(HW_IPCC_LLD_BLE_M0_CMD_CHANNEL)) { + HW_IPCC_LLD_BLE_ReceiveM0CmdHandler(); + } +#endif /* LLD_TESTS_WB */ +#ifdef ZIGBEE_WB + else if(HW_IPCC_RX_PENDING(HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL)) { + HW_IPCC_ZIGBEE_StackNotifEvtHandler(); + } else if(HW_IPCC_RX_PENDING(HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL)) { + HW_IPCC_ZIGBEE_StackM0RequestHandler(); + } +#endif /* ZIGBEE_WB */ + else if(HW_IPCC_RX_PENDING(HW_IPCC_BLE_EVENT_CHANNEL)) { HW_IPCC_BLE_EvtHandler(); } else if(HW_IPCC_RX_PENDING(HW_IPCC_TRACES_CHANNEL)) { HW_IPCC_TRACES_EvtHandler(); } + + return; } -void HW_IPCC_Tx_Handler() { +void HW_IPCC_Tx_Handler(void) { if(HW_IPCC_TX_PENDING(HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) { HW_IPCC_SYS_CmdEvtHandler(); - } else if(HW_IPCC_TX_PENDING(HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) { + } +#ifdef MAC_802_15_4_WB + else if(HW_IPCC_TX_PENDING(HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL)) { + HW_IPCC_MAC_802_15_4_CmdEvtHandler(); + } +#endif /* MAC_802_15_4_WB */ +#ifdef THREAD_WB + else if(HW_IPCC_TX_PENDING(HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL)) { + HW_IPCC_OT_CmdEvtHandler(); + } +#endif /* THREAD_WB */ +#ifdef LLD_TESTS_WB +// No TX handler for LLD tests +#endif /* LLD_TESTS_WB */ +#ifdef ZIGBEE_WB + if(HW_IPCC_TX_PENDING(HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL)) { + HW_IPCC_ZIGBEE_CmdEvtHandler(); + } +#endif /* ZIGBEE_WB */ + else if(HW_IPCC_TX_PENDING(HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) { HW_IPCC_SYS_CmdEvtHandler(); } else if(HW_IPCC_TX_PENDING(HW_IPCC_MM_RELEASE_BUFFER_CHANNEL)) { HW_IPCC_MM_FreeBufHandler(); } else if(HW_IPCC_TX_PENDING(HW_IPCC_HCI_ACL_DATA_CHANNEL)) { HW_IPCC_BLE_AclDataEvtHandler(); } -} -void HW_IPCC_Enable() { + return; +} +/****************************************************************************** + * GENERAL + ******************************************************************************/ +void HW_IPCC_Enable(void) { /** * Such as IPCC IP available to the CPU2, it is required to keep the IPCC clock running when FUS is running on CPU2 and CPU1 enters deep sleep mode @@ -69,9 +177,11 @@ void HW_IPCC_Enable() { __SEV(); /* Set the internal event flag and send an event to the CPU2 */ __WFE(); /* Clear the internal event flag */ LL_PWR_EnableBootC2(); + + return; } -void HW_IPCC_Init() { +void HW_IPCC_Init(void) { LL_C1_IPCC_EnableIT_RXO(IPCC); LL_C1_IPCC_EnableIT_TXF(IPCC); @@ -79,62 +189,366 @@ void HW_IPCC_Init() { NVIC_EnableIRQ(IPCC_C1_RX_IRQn); NVIC_SetPriority(IPCC_C1_TX_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 6, 0)); NVIC_EnableIRQ(IPCC_C1_TX_IRQn); + + return; } -void HW_IPCC_BLE_Init() { +/****************************************************************************** + * BLE + ******************************************************************************/ +void HW_IPCC_BLE_Init(void) { LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_BLE_EVENT_CHANNEL); + + return; } -void HW_IPCC_BLE_SendCmd() { +void HW_IPCC_BLE_SendCmd(void) { LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_BLE_CMD_CHANNEL); + + return; } -static void HW_IPCC_BLE_EvtHandler() { +static void HW_IPCC_BLE_EvtHandler(void) { HW_IPCC_BLE_RxEvtNot(); LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_BLE_EVENT_CHANNEL); + + return; } -void HW_IPCC_BLE_SendAclData() { +void HW_IPCC_BLE_SendAclData(void) { LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_HCI_ACL_DATA_CHANNEL); LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_HCI_ACL_DATA_CHANNEL); + + return; } -static void HW_IPCC_BLE_AclDataEvtHandler() { +static void HW_IPCC_BLE_AclDataEvtHandler(void) { LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_HCI_ACL_DATA_CHANNEL); HW_IPCC_BLE_AclDataAckNot(); + + return; } -void HW_IPCC_SYS_Init() { +__weak void HW_IPCC_BLE_AclDataAckNot(void){}; +__weak void HW_IPCC_BLE_RxEvtNot(void){}; + +/****************************************************************************** + * SYSTEM + ******************************************************************************/ +void HW_IPCC_SYS_Init(void) { LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_SYSTEM_EVENT_CHANNEL); + + return; } -void HW_IPCC_SYS_SendCmd() { +void HW_IPCC_SYS_SendCmd(void) { LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL); + LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL); - FuriHalCortexTimer timer = furi_hal_cortex_timer_get(33000000); - - while(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) { - furi_check(!furi_hal_cortex_timer_is_expired(timer), "HW_IPCC_SYS_SendCmd timeout"); - } - - HW_IPCC_SYS_CmdEvtHandler(); + return; } -static void HW_IPCC_SYS_CmdEvtHandler() { +static void HW_IPCC_SYS_CmdEvtHandler(void) { LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL); HW_IPCC_SYS_CmdEvtNot(); + + return; } -static void HW_IPCC_SYS_EvtHandler() { +static void HW_IPCC_SYS_EvtHandler(void) { HW_IPCC_SYS_EvtNot(); LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_SYSTEM_EVENT_CHANNEL); + + return; +} + +__weak void HW_IPCC_SYS_CmdEvtNot(void){}; +__weak void HW_IPCC_SYS_EvtNot(void){}; + +/****************************************************************************** + * MAC 802.15.4 + ******************************************************************************/ +#ifdef MAC_802_15_4_WB +void HW_IPCC_MAC_802_15_4_Init(void) { + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL); + + return; +} + +void HW_IPCC_MAC_802_15_4_SendCmd(void) { + LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL); + LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL); + + return; +} + +void HW_IPCC_MAC_802_15_4_SendAck(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL); + + return; +} + +static void HW_IPCC_MAC_802_15_4_CmdEvtHandler(void) { + LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL); + + HW_IPCC_MAC_802_15_4_CmdEvtNot(); + + return; +} + +static void HW_IPCC_MAC_802_15_4_NotEvtHandler(void) { + LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL); + + HW_IPCC_MAC_802_15_4_EvtNot(); + + return; +} +__weak void HW_IPCC_MAC_802_15_4_CmdEvtNot(void){}; +__weak void HW_IPCC_MAC_802_15_4_EvtNot(void){}; +#endif + +/****************************************************************************** + * THREAD + ******************************************************************************/ +#ifdef THREAD_WB +void HW_IPCC_THREAD_Init(void) { + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL); + + return; +} + +void HW_IPCC_OT_SendCmd(void) { + LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL); + LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL); + + return; +} + +void HW_IPCC_CLI_SendCmd(void) { + LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_THREAD_CLI_CMD_CHANNEL); + + return; +} + +void HW_IPCC_THREAD_SendAck(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL); + + return; +} + +void HW_IPCC_THREAD_CliSendAck(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL); + + return; +} + +static void HW_IPCC_OT_CmdEvtHandler(void) { + LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL); + + HW_IPCC_OT_CmdEvtNot(); + + return; } -void HW_IPCC_MM_SendFreeBuf(void (*cb)()) { +static void HW_IPCC_THREAD_NotEvtHandler(void) { + LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL); + + HW_IPCC_THREAD_EvtNot(); + + return; +} + +static void HW_IPCC_THREAD_CliNotEvtHandler(void) { + LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL); + + HW_IPCC_THREAD_CliEvtNot(); + + return; +} + +__weak void HW_IPCC_OT_CmdEvtNot(void){}; +__weak void HW_IPCC_CLI_CmdEvtNot(void){}; +__weak void HW_IPCC_THREAD_EvtNot(void){}; + +#endif /* THREAD_WB */ + +/****************************************************************************** + * LLD TESTS + ******************************************************************************/ +#ifdef LLD_TESTS_WB +void HW_IPCC_LLDTESTS_Init(void) { + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL); + return; +} + +void HW_IPCC_LLDTESTS_SendCliCmd(void) { + LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_LLDTESTS_CLI_CMD_CHANNEL); + return; +} + +static void HW_IPCC_LLDTESTS_ReceiveCliRspHandler(void) { + LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL); + HW_IPCC_LLDTESTS_ReceiveCliRsp(); + return; +} + +void HW_IPCC_LLDTESTS_SendCliRspAck(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL); + return; +} + +static void HW_IPCC_LLDTESTS_ReceiveM0CmdHandler(void) { + LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL); + HW_IPCC_LLDTESTS_ReceiveM0Cmd(); + return; +} + +void HW_IPCC_LLDTESTS_SendM0CmdAck(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL); + return; +} +__weak void HW_IPCC_LLDTESTS_ReceiveCliRsp(void){}; +__weak void HW_IPCC_LLDTESTS_ReceiveM0Cmd(void){}; +#endif /* LLD_TESTS_WB */ + +/****************************************************************************** + * LLD BLE + ******************************************************************************/ +#ifdef LLD_BLE_WB +void HW_IPCC_LLD_BLE_Init(void) { + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL); + return; +} + +void HW_IPCC_LLD_BLE_SendCliCmd(void) { + LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_LLD_BLE_CLI_CMD_CHANNEL); + return; +} + +/*static void HW_IPCC_LLD_BLE_ReceiveCliRspHandler( void ) +{ + LL_C1_IPCC_DisableReceiveChannel( IPCC, HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL ); + HW_IPCC_LLD_BLE_ReceiveCliRsp(); + return; +}*/ + +void HW_IPCC_LLD_BLE_SendCliRspAck(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL); + return; +} + +static void HW_IPCC_LLD_BLE_ReceiveM0CmdHandler(void) { + //LL_C1_IPCC_DisableReceiveChannel( IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL ); + HW_IPCC_LLD_BLE_ReceiveM0Cmd(); + return; +} + +void HW_IPCC_LLD_BLE_SendM0CmdAck(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL); + //LL_C1_IPCC_EnableReceiveChannel( IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL ); + return; +} +__weak void HW_IPCC_LLD_BLE_ReceiveCliRsp(void){}; +__weak void HW_IPCC_LLD_BLE_ReceiveM0Cmd(void){}; + +/* Transparent Mode */ +void HW_IPCC_LLD_BLE_SendCmd(void) { + LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_LLD_BLE_CMD_CHANNEL); + return; +} + +static void HW_IPCC_LLD_BLE_ReceiveRspHandler(void) { + LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL); + HW_IPCC_LLD_BLE_ReceiveRsp(); + return; +} + +void HW_IPCC_LLD_BLE_SendRspAck(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL); + return; +} + +#endif /* LLD_BLE_WB */ + +/****************************************************************************** + * ZIGBEE + ******************************************************************************/ +#ifdef ZIGBEE_WB +void HW_IPCC_ZIGBEE_Init(void) { + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL); + + return; +} + +void HW_IPCC_ZIGBEE_SendM4RequestToM0(void) { + LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL); + LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL); + + return; +} + +void HW_IPCC_ZIGBEE_SendM4AckToM0Notify(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL); + + return; +} + +static void HW_IPCC_ZIGBEE_CmdEvtHandler(void) { + LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL); + + HW_IPCC_ZIGBEE_RecvAppliAckFromM0(); + + return; +} + +static void HW_IPCC_ZIGBEE_StackNotifEvtHandler(void) { + LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL); + + HW_IPCC_ZIGBEE_RecvM0NotifyToM4(); + + return; +} + +static void HW_IPCC_ZIGBEE_StackM0RequestHandler(void) { + LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL); + + HW_IPCC_ZIGBEE_RecvM0RequestToM4(); + + return; +} + +void HW_IPCC_ZIGBEE_SendM4AckToM0Request(void) { + LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL); + LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL); + + return; +} + +__weak void HW_IPCC_ZIGBEE_RecvAppliAckFromM0(void){}; +__weak void HW_IPCC_ZIGBEE_RecvM0NotifyToM4(void){}; +__weak void HW_IPCC_ZIGBEE_RecvM0RequestToM4(void){}; +#endif /* ZIGBEE_WB */ + +/****************************************************************************** + * MEMORY MANAGER + ******************************************************************************/ +void HW_IPCC_MM_SendFreeBuf(void (*cb)(void)) { if(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL)) { FreeBufCb = cb; LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL); @@ -143,22 +557,37 @@ void HW_IPCC_MM_SendFreeBuf(void (*cb)()) { LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL); } + + return; } -static void HW_IPCC_MM_FreeBufHandler() { +static void HW_IPCC_MM_FreeBufHandler(void) { LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL); FreeBufCb(); LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL); + + return; } -void HW_IPCC_TRACES_Init() { +/****************************************************************************** + * TRACES + ******************************************************************************/ +void HW_IPCC_TRACES_Init(void) { LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_TRACES_CHANNEL); + + return; } -static void HW_IPCC_TRACES_EvtHandler() { +static void HW_IPCC_TRACES_EvtHandler(void) { HW_IPCC_TRACES_EvtNot(); LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_TRACES_CHANNEL); + + return; } + +__weak void HW_IPCC_TRACES_EvtNot(void){}; + +/******************* (C) COPYRIGHT 2019 STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/ble_glue/osal.h b/firmware/targets/f7/ble_glue/osal.h index 0cde06179..e5e0c4f68 100644 --- a/firmware/targets/f7/ble_glue/osal.h +++ b/firmware/targets/f7/ble_glue/osal.h @@ -1,4 +1,25 @@ -#pragma once +/***************************************************************************** + * @file osal.h + * @author MDG + * @brief This header file defines the OS abstraction layer used by + * the BLE stack. OSAL defines the set of functions which needs to be + * ported to target operating system and target platform. + * Actually, only memset, memcpy and memcmp wrappers are defined. + ***************************************************************************** + * @attention + * + * Copyright (c) 2018-2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ***************************************************************************** + */ + +#ifndef OSAL_H__ +#define OSAL_H__ /** * This function copies size number of bytes from a @@ -38,3 +59,5 @@ extern void* Osal_MemSet(void* ptr, int value, unsigned int size); * @return 0 if the two buffers are equal, 1 otherwise */ extern int Osal_MemCmp(const void* s1, const void* s2, unsigned int size); + +#endif /* OSAL_H__ */ diff --git a/firmware/targets/f7/ble_glue/services/serial_service.c b/firmware/targets/f7/ble_glue/serial_service.c similarity index 57% rename from firmware/targets/f7/ble_glue/services/serial_service.c rename to firmware/targets/f7/ble_glue/serial_service.c index 0db25b3d3..c6421dc28 100644 --- a/firmware/targets/f7/ble_glue/services/serial_service.c +++ b/firmware/targets/f7/ble_glue/serial_service.c @@ -1,67 +1,17 @@ #include "serial_service.h" #include "app_common.h" #include -#include "gatt_char.h" #include -#include "serial_service_uuid.inc" - #define TAG "BtSerialSvc" -typedef enum { - SerialSvcGattCharacteristicRx = 0, - SerialSvcGattCharacteristicTx, - SerialSvcGattCharacteristicFlowCtrl, - SerialSvcGattCharacteristicStatus, - SerialSvcGattCharacteristicCount, -} SerialSvcGattCharacteristicId; - -static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattCharacteristicCount] = { - [SerialSvcGattCharacteristicRx] = - {.name = "RX", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = SERIAL_SVC_DATA_LEN_MAX, - .uuid.Char_UUID_128 = SERIAL_SVC_RX_CHAR_UUID, - .uuid_type = UUID_TYPE_128, - .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE | CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, - .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, - .is_variable = CHAR_VALUE_LEN_VARIABLE}, - [SerialSvcGattCharacteristicTx] = - {.name = "TX", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = SERIAL_SVC_DATA_LEN_MAX, - .uuid.Char_UUID_128 = SERIAL_SVC_TX_CHAR_UUID, - .uuid_type = UUID_TYPE_128, - .char_properties = CHAR_PROP_READ | CHAR_PROP_INDICATE, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_VARIABLE}, - [SerialSvcGattCharacteristicFlowCtrl] = - {.name = "Flow control", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = sizeof(uint32_t), - .uuid.Char_UUID_128 = SERIAL_SVC_FLOW_CONTROL_UUID, - .uuid_type = UUID_TYPE_128, - .char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [SerialSvcGattCharacteristicStatus] = { - .name = "RPC status", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = sizeof(SerialServiceRpcStatus), - .uuid.Char_UUID_128 = SERIAL_SVC_RPC_STATUS_UUID, - .uuid_type = UUID_TYPE_128, - .char_properties = CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, - .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, - .is_variable = CHAR_VALUE_LEN_CONSTANT}}; - typedef struct { uint16_t svc_handle; - FlipperGattCharacteristicInstance chars[SerialSvcGattCharacteristicCount]; + uint16_t rx_char_handle; + uint16_t tx_char_handle; + uint16_t flow_ctrl_char_handle; + uint16_t rpc_status_char_handle; FuriMutex* buff_size_mtx; uint32_t buff_size; uint16_t bytes_ready_to_receive; @@ -71,6 +21,17 @@ typedef struct { static SerialSvc* serial_svc = NULL; +static const uint8_t service_uuid[] = + {0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f}; +static const uint8_t char_tx_uuid[] = + {0x00, 0x00, 0xfe, 0x61, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; +static const uint8_t char_rx_uuid[] = + {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; +static const uint8_t flow_ctrl_uuid[] = + {0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; +static const uint8_t rpc_status_uuid[] = + {0x00, 0x00, 0xfe, 0x64, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; + static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data); @@ -79,14 +40,11 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) { if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) { attribute_modified = (aci_gatt_attribute_modified_event_rp0*)blecore_evt->data; - if(attribute_modified->Attr_Handle == - serial_svc->chars[SerialSvcGattCharacteristicRx].handle + 2) { + if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 2) { // Descriptor handle ret = SVCCTL_EvtAckFlowEnable; FURI_LOG_D(TAG, "RX descriptor event"); - } else if( - attribute_modified->Attr_Handle == - serial_svc->chars[SerialSvcGattCharacteristicRx].handle + 1) { + } else if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 1) { FURI_LOG_D(TAG, "Received %d bytes", attribute_modified->Attr_Data_Length); if(serial_svc->callback) { furi_check( @@ -112,9 +70,7 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk); } ret = SVCCTL_EvtAckFlowEnable; - } else if( - attribute_modified->Attr_Handle == - serial_svc->chars[SerialSvcGattCharacteristicStatus].handle + 1) { + } else if(attribute_modified->Attr_Handle == serial_svc->rpc_status_char_handle + 1) { SerialServiceRpcStatus* rpc_status = (SerialServiceRpcStatus*)attribute_modified->Attr_Data; if(*rpc_status == SerialServiceRpcStatusNotActive) { @@ -141,12 +97,18 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { } static void serial_svc_update_rpc_char(SerialServiceRpcStatus status) { - flipper_gatt_characteristic_update( - serial_svc->svc_handle, &serial_svc->chars[SerialSvcGattCharacteristicStatus], &status); + tBleStatus ble_status = aci_gatt_update_char_value( + serial_svc->svc_handle, + serial_svc->rpc_status_char_handle, + 0, + sizeof(SerialServiceRpcStatus), + (uint8_t*)&status); + if(ble_status) { + FURI_LOG_E(TAG, "Failed to update RPC status char: %d", ble_status); + } } void serial_svc_start() { - UNUSED(serial_svc_chars); tBleStatus status; serial_svc = malloc(sizeof(SerialSvc)); // Register event handler @@ -154,17 +116,72 @@ void serial_svc_start() { // Add service status = aci_gatt_add_service( - UUID_TYPE_128, &service_uuid, PRIMARY_SERVICE, 12, &serial_svc->svc_handle); + UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 12, &serial_svc->svc_handle); if(status) { FURI_LOG_E(TAG, "Failed to add Serial service: %d", status); } - // Add characteristics - for(uint8_t i = 0; i < SerialSvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_init( - serial_svc->svc_handle, &serial_svc_chars[i], &serial_svc->chars[i]); + // Add RX characteristics + status = aci_gatt_add_char( + serial_svc->svc_handle, + UUID_TYPE_128, + (const Char_UUID_t*)char_rx_uuid, + SERIAL_SVC_DATA_LEN_MAX, + CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE | CHAR_PROP_READ, + ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, + GATT_NOTIFY_ATTRIBUTE_WRITE, + 10, + CHAR_VALUE_LEN_VARIABLE, + &serial_svc->rx_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add RX characteristic: %d", status); } + // Add TX characteristic + status = aci_gatt_add_char( + serial_svc->svc_handle, + UUID_TYPE_128, + (const Char_UUID_t*)char_tx_uuid, + SERIAL_SVC_DATA_LEN_MAX, + CHAR_PROP_READ | CHAR_PROP_INDICATE, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_VARIABLE, + &serial_svc->tx_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add TX characteristic: %d", status); + } + // Add Flow Control characteristic + status = aci_gatt_add_char( + serial_svc->svc_handle, + UUID_TYPE_128, + (const Char_UUID_t*)flow_ctrl_uuid, + sizeof(uint32_t), + CHAR_PROP_READ | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_AUTHEN_READ, + GATT_DONT_NOTIFY_EVENTS, + 10, + CHAR_VALUE_LEN_CONSTANT, + &serial_svc->flow_ctrl_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status); + } + // Add RPC status characteristic + status = aci_gatt_add_char( + serial_svc->svc_handle, + UUID_TYPE_128, + (const Char_UUID_t*)rpc_status_uuid, + sizeof(SerialServiceRpcStatus), + CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, + GATT_NOTIFY_ATTRIBUTE_WRITE, + 10, + CHAR_VALUE_LEN_CONSTANT, + &serial_svc->rpc_status_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add RPC status characteristic: %d", status); + } serial_svc_update_rpc_char(SerialServiceRpcStatusNotActive); // Allocate buffer size mutex serial_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal); @@ -179,12 +196,13 @@ void serial_svc_set_callbacks( serial_svc->context = context; serial_svc->buff_size = buff_size; serial_svc->bytes_ready_to_receive = buff_size; - uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size); - flipper_gatt_characteristic_update( + aci_gatt_update_char_value( serial_svc->svc_handle, - &serial_svc->chars[SerialSvcGattCharacteristicFlowCtrl], - &buff_size_reversed); + serial_svc->flow_ctrl_char_handle, + 0, + sizeof(uint32_t), + (uint8_t*)&buff_size_reversed); } void serial_svc_notify_buffer_is_empty() { @@ -195,12 +213,13 @@ void serial_svc_notify_buffer_is_empty() { if(serial_svc->bytes_ready_to_receive == 0) { FURI_LOG_D(TAG, "Buffer is empty. Notifying client"); serial_svc->bytes_ready_to_receive = serial_svc->buff_size; - uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size); - flipper_gatt_characteristic_update( + aci_gatt_update_char_value( serial_svc->svc_handle, - &serial_svc->chars[SerialSvcGattCharacteristicFlowCtrl], - &buff_size_reversed); + serial_svc->flow_ctrl_char_handle, + 0, + sizeof(uint32_t), + (uint8_t*)&buff_size_reversed); } furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk); } @@ -208,8 +227,22 @@ void serial_svc_notify_buffer_is_empty() { void serial_svc_stop() { tBleStatus status; if(serial_svc) { - for(uint8_t i = 0; i < SerialSvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_delete(serial_svc->svc_handle, &serial_svc->chars[i]); + // Delete characteristics + status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->tx_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete TX characteristic: %d", status); + } + status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rx_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete RX characteristic: %d", status); + } + status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status); + } + status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rpc_status_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete RPC Status characteristic: %d", status); } // Delete service status = aci_gatt_del_service(serial_svc->svc_handle); @@ -240,7 +273,7 @@ bool serial_svc_update_tx(uint8_t* data, uint16_t data_len) { tBleStatus result = aci_gatt_update_char_value_ext( 0, serial_svc->svc_handle, - serial_svc->chars[SerialSvcGattCharacteristicTx].handle, + serial_svc->tx_char_handle, remained ? 0x00 : 0x02, data_len, value_offset, diff --git a/firmware/targets/f7/ble_glue/services/serial_service.h b/firmware/targets/f7/ble_glue/serial_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/services/serial_service.h rename to firmware/targets/f7/ble_glue/serial_service.h diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.c b/firmware/targets/f7/ble_glue/services/dev_info_service.c deleted file mode 100644 index 5bee97b41..000000000 --- a/firmware/targets/f7/ble_glue/services/dev_info_service.c +++ /dev/null @@ -1,176 +0,0 @@ -#include "dev_info_service.h" -#include "app_common.h" -#include "gatt_char.h" -#include - -#include -#include -#include - -#include "dev_info_service_uuid.inc" - -#define TAG "BtDevInfoSvc" - -typedef enum { - DevInfoSvcGattCharacteristicMfgName = 0, - DevInfoSvcGattCharacteristicSerial, - DevInfoSvcGattCharacteristicFirmwareRev, - DevInfoSvcGattCharacteristicSoftwareRev, - DevInfoSvcGattCharacteristicRpcVersion, - DevInfoSvcGattCharacteristicCount, -} DevInfoSvcGattCharacteristicId; - -#define DEVICE_INFO_HARDWARE_REV_SIZE 4 -typedef struct { - uint16_t service_handle; - FlipperGattCharacteristicInstance characteristics[DevInfoSvcGattCharacteristicCount]; - FuriString* version_string; - char hardware_revision[DEVICE_INFO_HARDWARE_REV_SIZE]; -} DevInfoSvc; - -static DevInfoSvc* dev_info_svc = NULL; - -static const char dev_info_man_name[] = "Flipper Devices Inc."; -static const char dev_info_serial_num[] = "1.0"; -static const char dev_info_rpc_version[] = TOSTRING(PROTOBUF_MAJOR_VERSION.PROTOBUF_MINOR_VERSION); - -static bool dev_info_char_firmware_rev_callback( - const void* context, - const uint8_t** data, - uint16_t* data_len) { - const DevInfoSvc* dev_info_svc = *(DevInfoSvc**)context; - *data_len = sizeof(dev_info_svc->hardware_revision); - if(data) { - *data = (const uint8_t*)&dev_info_svc->hardware_revision; - } - return false; -} - -static bool dev_info_char_software_rev_callback( - const void* context, - const uint8_t** data, - uint16_t* data_len) { - const DevInfoSvc* dev_info_svc = *(DevInfoSvc**)context; - *data_len = furi_string_size(dev_info_svc->version_string); - if(data) { - *data = (const uint8_t*)furi_string_get_cstr(dev_info_svc->version_string); - } - return false; -} - -static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCharacteristicCount] = - {[DevInfoSvcGattCharacteristicMfgName] = - {.name = "Manufacturer Name", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = sizeof(dev_info_man_name) - 1, - .data.fixed.ptr = (const uint8_t*)&dev_info_man_name, - .uuid.Char_UUID_16 = MANUFACTURER_NAME_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [DevInfoSvcGattCharacteristicSerial] = - {.name = "Serial Number", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = sizeof(dev_info_serial_num) - 1, - .data.fixed.ptr = (const uint8_t*)&dev_info_serial_num, - .uuid.Char_UUID_16 = SERIAL_NUMBER_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [DevInfoSvcGattCharacteristicFirmwareRev] = - {.name = "Firmware Revision", - .data_prop_type = FlipperGattCharacteristicDataCallback, - .data.callback.context = &dev_info_svc, - .data.callback.fn = dev_info_char_firmware_rev_callback, - .uuid.Char_UUID_16 = FIRMWARE_REVISION_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [DevInfoSvcGattCharacteristicSoftwareRev] = - {.name = "Software Revision", - .data_prop_type = FlipperGattCharacteristicDataCallback, - .data.callback.context = &dev_info_svc, - .data.callback.fn = dev_info_char_software_rev_callback, - .uuid.Char_UUID_16 = SOFTWARE_REVISION_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [DevInfoSvcGattCharacteristicRpcVersion] = { - .name = "RPC Version", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = sizeof(dev_info_rpc_version) - 1, - .data.fixed.ptr = (const uint8_t*)&dev_info_rpc_version, - .uuid.Char_UUID_128 = DEV_INVO_RPC_VERSION_UID, - .uuid_type = UUID_TYPE_128, - .char_properties = CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_AUTHEN_READ, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}}; - -void dev_info_svc_start() { - dev_info_svc = malloc(sizeof(DevInfoSvc)); - dev_info_svc->version_string = furi_string_alloc_printf( - "%s %s %s %s", - version_get_githash(NULL), - version_get_version(NULL), - version_get_gitbranchnum(NULL), - version_get_builddate(NULL)); - snprintf( - dev_info_svc->hardware_revision, - sizeof(dev_info_svc->hardware_revision), - "%d", - version_get_target(NULL)); - tBleStatus status; - - // Add Device Information Service - uint16_t uuid = DEVICE_INFORMATION_SERVICE_UUID; - status = aci_gatt_add_service( - UUID_TYPE_16, - (Service_UUID_t*)&uuid, - PRIMARY_SERVICE, - 1 + 2 * DevInfoSvcGattCharacteristicCount, - &dev_info_svc->service_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add Device Information Service: %d", status); - } - - for(size_t i = 0; i < DevInfoSvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_init( - dev_info_svc->service_handle, - &dev_info_svc_chars[i], - &dev_info_svc->characteristics[i]); - flipper_gatt_characteristic_update( - dev_info_svc->service_handle, &dev_info_svc->characteristics[i], NULL); - } -} - -void dev_info_svc_stop() { - tBleStatus status; - if(dev_info_svc) { - furi_string_free(dev_info_svc->version_string); - // Delete service characteristics - for(size_t i = 0; i < DevInfoSvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_delete( - dev_info_svc->service_handle, &dev_info_svc->characteristics[i]); - } - // Delete service - status = aci_gatt_del_service(dev_info_svc->service_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete device info service: %d", status); - } - free(dev_info_svc); - dev_info_svc = NULL; - } -} - -bool dev_info_svc_is_started() { - return dev_info_svc != NULL; -} diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service_uuid.inc b/firmware/targets/f7/ble_glue/services/dev_info_service_uuid.inc deleted file mode 100644 index ad520f62e..000000000 --- a/firmware/targets/f7/ble_glue/services/dev_info_service_uuid.inc +++ /dev/null @@ -1,3 +0,0 @@ -#define DEV_INVO_RPC_VERSION_UID \ - { 0x33, 0xa9, 0xb5, 0x3e, 0x87, 0x5d, 0x1a, 0x8e, 0xc8, 0x47, 0x5e, 0xae, 0x6d, 0x66, 0xf6, 0x03 } - diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c deleted file mode 100644 index c06403f55..000000000 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "gatt_char.h" - -#include - -#define TAG "GattChar" - -#define GATT_MIN_READ_KEY_SIZE (10) - -void flipper_gatt_characteristic_init( - uint16_t svc_handle, - const FlipperGattCharacteristicParams* char_descriptor, - FlipperGattCharacteristicInstance* char_instance) { - furi_assert(char_descriptor); - furi_assert(char_instance); - - // Copy the descriptor to the instance, since it may point to stack memory - char_instance->characteristic = malloc(sizeof(FlipperGattCharacteristicParams)); - memcpy( - (void*)char_instance->characteristic, - char_descriptor, - sizeof(FlipperGattCharacteristicParams)); - - uint16_t char_data_size = 0; - if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataFixed) { - char_data_size = char_descriptor->data.fixed.length; - } else if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataCallback) { - char_descriptor->data.callback.fn( - char_descriptor->data.callback.context, NULL, &char_data_size); - } - - tBleStatus status = aci_gatt_add_char( - svc_handle, - char_descriptor->uuid_type, - &char_descriptor->uuid, - char_data_size, - char_descriptor->char_properties, - char_descriptor->security_permissions, - char_descriptor->gatt_evt_mask, - GATT_MIN_READ_KEY_SIZE, - char_descriptor->is_variable, - &char_instance->handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add %s char: %d", char_descriptor->name, status); - } - - char_instance->descriptor_handle = 0; - if((status == 0) && char_descriptor->descriptor_params) { - uint8_t const* char_data = NULL; - const FlipperGattCharacteristicDescriptorParams* char_data_descriptor = - char_descriptor->descriptor_params; - bool release_data = char_data_descriptor->data_callback.fn( - char_data_descriptor->data_callback.context, &char_data, &char_data_size); - - status = aci_gatt_add_char_desc( - svc_handle, - char_instance->handle, - char_data_descriptor->uuid_type, - &char_data_descriptor->uuid, - char_data_descriptor->max_length, - char_data_size, - char_data, - char_data_descriptor->security_permissions, - char_data_descriptor->access_permissions, - char_data_descriptor->gatt_evt_mask, - MIN_ENCRY_KEY_SIZE, - char_data_descriptor->is_variable, - &char_instance->descriptor_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add %s char descriptor: %d", char_descriptor->name, status); - } - if(release_data) { - free((void*)char_data); - } - } -} - -void flipper_gatt_characteristic_delete( - uint16_t svc_handle, - FlipperGattCharacteristicInstance* char_instance) { - tBleStatus status = aci_gatt_del_char(svc_handle, char_instance->handle); - if(status) { - FURI_LOG_E( - TAG, "Failed to delete %s char: %d", char_instance->characteristic->name, status); - } - free((void*)char_instance->characteristic); -} - -bool flipper_gatt_characteristic_update( - uint16_t svc_handle, - FlipperGattCharacteristicInstance* char_instance, - const void* source) { - furi_assert(char_instance); - const FlipperGattCharacteristicParams* char_descriptor = char_instance->characteristic; - FURI_LOG_D(TAG, "Updating %s char", char_descriptor->name); - - const uint8_t* char_data = NULL; - uint16_t char_data_size = 0; - bool release_data = false; - if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataFixed) { - char_data = char_descriptor->data.fixed.ptr; - if(source) { - char_data = (uint8_t*)source; - } - char_data_size = char_descriptor->data.fixed.length; - } else if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataCallback) { - const void* context = char_descriptor->data.callback.context; - if(source) { - context = source; - } - release_data = char_descriptor->data.callback.fn(context, &char_data, &char_data_size); - } - - tBleStatus result = aci_gatt_update_char_value( - svc_handle, char_instance->handle, 0, char_data_size, char_data); - if(result) { - FURI_LOG_E(TAG, "Failed updating %s characteristic: %d", char_descriptor->name, result); - } - if(release_data) { - free((void*)char_data); - } - return result != BLE_STATUS_SUCCESS; -} \ No newline at end of file diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.h b/firmware/targets/f7/ble_glue/services/gatt_char.h deleted file mode 100644 index 959ab67a4..000000000 --- a/firmware/targets/f7/ble_glue/services/gatt_char.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// Callback signature for getting characteristic data -// Is called when characteristic is created to get max data length. Data ptr is NULL in this case -// The result is passed to aci_gatt_add_char as "Char_Value_Length" -// For updates, called with a context - see flipper_gatt_characteristic_update -// Returns true if *data ownership is transferred to the caller and will be freed -typedef bool (*cbFlipperGattCharacteristicData)( - const void* context, - const uint8_t** data, - uint16_t* data_len); - -typedef enum { - FlipperGattCharacteristicDataFixed, - FlipperGattCharacteristicDataCallback, -} FlipperGattCharacteristicDataType; - -typedef struct { - Char_Desc_Uuid_t uuid; - struct { - cbFlipperGattCharacteristicData fn; - const void* context; - } data_callback; - uint8_t uuid_type; - uint8_t max_length; - uint8_t security_permissions; - uint8_t access_permissions; - uint8_t gatt_evt_mask; - uint8_t is_variable; -} FlipperGattCharacteristicDescriptorParams; - -typedef struct { - const char* name; - FlipperGattCharacteristicDescriptorParams* descriptor_params; - union { - struct { - const uint8_t* ptr; - uint16_t length; - } fixed; - struct { - cbFlipperGattCharacteristicData fn; - const void* context; - } callback; - } data; - Char_UUID_t uuid; - // Some packed bitfields to save space - FlipperGattCharacteristicDataType data_prop_type : 2; - uint8_t is_variable : 2; - uint8_t uuid_type : 2; - uint8_t char_properties; - uint8_t security_permissions; - uint8_t gatt_evt_mask; -} FlipperGattCharacteristicParams; - -_Static_assert( - sizeof(FlipperGattCharacteristicParams) == 36, - "FlipperGattCharacteristicParams size must be 36 bytes"); - -typedef struct { - const FlipperGattCharacteristicParams* characteristic; - uint16_t handle; - uint16_t descriptor_handle; -} FlipperGattCharacteristicInstance; - -// Initialize a characteristic instance; copies the characteristic descriptor into the instance -void flipper_gatt_characteristic_init( - uint16_t svc_handle, - const FlipperGattCharacteristicParams* char_descriptor, - FlipperGattCharacteristicInstance* char_instance); - -// Delete a characteristic instance; frees the copied characteristic descriptor from the instance -void flipper_gatt_characteristic_delete( - uint16_t svc_handle, - FlipperGattCharacteristicInstance* char_instance); - -// Update a characteristic instance; if source==NULL, uses the data from the characteristic -// - For fixed data, fixed.ptr is used as the source if source==NULL -// - For callback-based data, collback.context is passed as the context if source==NULL -bool flipper_gatt_characteristic_update( - uint16_t svc_handle, - FlipperGattCharacteristicInstance* char_instance, - const void* source); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/firmware/targets/f7/ble_glue/services/hid_service.c deleted file mode 100644 index d3fad0108..000000000 --- a/firmware/targets/f7/ble_glue/services/hid_service.c +++ /dev/null @@ -1,366 +0,0 @@ -#include "hid_service.h" -#include "app_common.h" -#include -#include "gatt_char.h" - -#include - -#define TAG "BtHid" - -typedef enum { - HidSvcGattCharacteristicProtocolMode = 0, - HidSvcGattCharacteristicReportMap, - HidSvcGattCharacteristicInfo, - HidSvcGattCharacteristicCtrlPoint, - HidSvcGattCharacteristicLed, - HidSvcGattCharacteristicCount, -} HidSvcGattCharacteristicId; - -typedef struct { - uint8_t report_idx; - uint8_t report_type; -} HidSvcReportId; - -static_assert(sizeof(HidSvcReportId) == sizeof(uint16_t), "HidSvcReportId must be 2 bytes"); - -static const Service_UUID_t hid_svc_uuid = { - .Service_UUID_16 = HUMAN_INTERFACE_DEVICE_SERVICE_UUID, -}; - -static bool - hid_svc_char_desc_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { - const HidSvcReportId* report_id = context; - *data_len = sizeof(HidSvcReportId); - if(data) { - *data = (const uint8_t*)report_id; - } - return false; -} - -typedef struct { - const void* data_ptr; - uint16_t data_len; -} HidSvcDataWrapper; - -static bool - hid_svc_report_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { - const HidSvcDataWrapper* report_data = context; - if(data) { - *data = report_data->data_ptr; - *data_len = report_data->data_len; - } else { - *data_len = HID_SVC_REPORT_MAP_MAX_LEN; - } - return false; -} - -// LED Descriptor params for BadBT - -static uint8_t led_desc_context_buf[2] = {HID_SVC_REPORT_COUNT + 1, 2}; - -static FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_led = { - .uuid_type = UUID_TYPE_16, - .uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID, - .max_length = HID_SVC_REPORT_REF_LEN, - .data_callback.fn = hid_svc_char_desc_data_callback, - .data_callback.context = led_desc_context_buf, - .security_permissions = ATTR_PERMISSION_NONE, - .access_permissions = ATTR_ACCESS_READ_WRITE, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT, -}; - -static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteristicCount] = { - [HidSvcGattCharacteristicProtocolMode] = - {.name = "Protocol Mode", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = 1, - .uuid.Char_UUID_16 = PROTOCOL_MODE_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [HidSvcGattCharacteristicReportMap] = - {.name = "Report Map", - .data_prop_type = FlipperGattCharacteristicDataCallback, - .data.callback.fn = hid_svc_report_data_callback, - .data.callback.context = NULL, - .uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_VARIABLE}, - [HidSvcGattCharacteristicInfo] = - {.name = "HID Information", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = HID_SVC_INFO_LEN, - .data.fixed.ptr = NULL, - .uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [HidSvcGattCharacteristicCtrlPoint] = - {.name = "HID Control Point", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = HID_SVC_CONTROL_POINT_LEN, - .uuid.Char_UUID_16 = HID_CONTROL_POINT_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [HidSvcGattCharacteristicLed] = - { - .name = - "HID LED State", // LED Characteristic and descriptor for BadBT to get numlock state for altchars - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = 1, - .uuid.Char_UUID_16 = REPORT_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE | - GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP, - .is_variable = CHAR_VALUE_LEN_CONSTANT, - .descriptor_params = &hid_svc_char_descr_led, - }, -}; - -static const FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_template = { - .uuid_type = UUID_TYPE_16, - .uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID, - .max_length = HID_SVC_REPORT_REF_LEN, - .data_callback.fn = hid_svc_char_desc_data_callback, - .security_permissions = ATTR_PERMISSION_NONE, - .access_permissions = ATTR_ACCESS_READ_WRITE, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT, -}; - -static const FlipperGattCharacteristicParams hid_svc_report_template = { - .name = "Report", - .data_prop_type = FlipperGattCharacteristicDataCallback, - .data.callback.fn = hid_svc_report_data_callback, - .data.callback.context = NULL, - .uuid.Char_UUID_16 = REPORT_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_VARIABLE, -}; - -typedef struct { - uint16_t svc_handle; - FlipperGattCharacteristicInstance chars[HidSvcGattCharacteristicCount]; - FlipperGattCharacteristicInstance input_report_chars[HID_SVC_INPUT_REPORT_COUNT]; - FlipperGattCharacteristicInstance output_report_chars[HID_SVC_OUTPUT_REPORT_COUNT]; - FlipperGattCharacteristicInstance feature_report_chars[HID_SVC_FEATURE_REPORT_COUNT]; - // led state - HidLedStateEventCallback led_state_event_callback; - void* led_state_ctx; -} HIDSvc; - -static HIDSvc* hid_svc = NULL; - -static SVCCTL_EvtAckStatus_t hid_svc_event_handler(void* event) { - SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; - hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data); - evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data; - // aci_gatt_attribute_modified_event_rp0* attribute_modified; - if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) { - if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) { - // Process modification events - ret = SVCCTL_EvtAckFlowEnable; - } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { - // Process notification confirmation - ret = SVCCTL_EvtAckFlowEnable; - } else if(blecore_evt->ecode == ACI_GATT_WRITE_PERMIT_REQ_VSEVT_CODE) { - // LED Characteristic and descriptor for BadBT to get numlock state for altchars - // - // Process write request - aci_gatt_write_permit_req_event_rp0* req = - (aci_gatt_write_permit_req_event_rp0*)blecore_evt->data; - - furi_check(hid_svc->led_state_event_callback && hid_svc->led_state_ctx); - - // this check is likely to be incorrect, it will actually work in our case - // but we need to investigate gatt api to see what is the rules - // that specify attibute handle value from char handle (or the reverse) - if(req->Attribute_Handle == (hid_svc->chars[HidSvcGattCharacteristicLed].handle + 1)) { - hid_svc->led_state_event_callback(req->Data[0], hid_svc->led_state_ctx); - aci_gatt_write_resp( - req->Connection_Handle, - req->Attribute_Handle, - 0x00, /* write_status = 0 (no error))*/ - 0x00, /* err_code */ - req->Data_Length, - req->Data); - aci_gatt_write_char_value( - req->Connection_Handle, - hid_svc->chars[HidSvcGattCharacteristicLed].handle, - req->Data_Length, - req->Data); - ret = SVCCTL_EvtAckFlowEnable; - } - } - } - return ret; -} - -void hid_svc_start() { - tBleStatus status; - hid_svc = malloc(sizeof(HIDSvc)); - - // Register event handler - SVCCTL_RegisterSvcHandler(hid_svc_event_handler); - /** - * Add Human Interface Device Service - */ - status = aci_gatt_add_service( - UUID_TYPE_16, - &hid_svc_uuid, - PRIMARY_SERVICE, - 2 + /* protocol mode */ - (4 * HID_SVC_INPUT_REPORT_COUNT) + (3 * HID_SVC_OUTPUT_REPORT_COUNT) + - (3 * HID_SVC_FEATURE_REPORT_COUNT) + 1 + 2 + 2 + 2 + - 4, /* Service + Report Map + HID Information + HID Control Point + LED state */ - &hid_svc->svc_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add HID service: %d", status); - } - - for(size_t i = 0; i < HidSvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_init( - hid_svc->svc_handle, &hid_svc_chars[i], &hid_svc->chars[i]); - } - uint8_t protocol_mode = 1; - flipper_gatt_characteristic_update( - hid_svc->svc_handle, - &hid_svc->chars[HidSvcGattCharacteristicProtocolMode], - &protocol_mode); - - // reports - FlipperGattCharacteristicDescriptorParams hid_svc_char_descr; - FlipperGattCharacteristicParams report_char; - HidSvcReportId report_id; - - memcpy(&hid_svc_char_descr, &hid_svc_char_descr_template, sizeof(hid_svc_char_descr)); - memcpy(&report_char, &hid_svc_report_template, sizeof(report_char)); - - hid_svc_char_descr.data_callback.context = &report_id; - report_char.descriptor_params = &hid_svc_char_descr; - - typedef struct { - uint8_t report_type; - uint8_t report_count; - FlipperGattCharacteristicInstance* chars; - } HidSvcReportCharProps; - - HidSvcReportCharProps hid_report_chars[] = { - {0x01, HID_SVC_INPUT_REPORT_COUNT, hid_svc->input_report_chars}, - {0x02, HID_SVC_OUTPUT_REPORT_COUNT, hid_svc->output_report_chars}, - {0x03, HID_SVC_FEATURE_REPORT_COUNT, hid_svc->feature_report_chars}, - }; - - for(size_t report_type_idx = 0; report_type_idx < COUNT_OF(hid_report_chars); - report_type_idx++) { - report_id.report_type = hid_report_chars[report_type_idx].report_type; - for(size_t report_idx = 0; report_idx < hid_report_chars[report_type_idx].report_count; - report_idx++) { - report_id.report_idx = report_idx + 1; - flipper_gatt_characteristic_init( - hid_svc->svc_handle, - &report_char, - &hid_report_chars[report_type_idx].chars[report_idx]); - } - } -} - -bool hid_svc_update_report_map(const uint8_t* data, uint16_t len) { - furi_assert(data); - furi_assert(hid_svc); - - HidSvcDataWrapper report_data = { - .data_ptr = data, - .data_len = len, - }; - return flipper_gatt_characteristic_update( - hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicReportMap], &report_data); -} - -bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16_t len) { - furi_assert(data); - furi_assert(hid_svc); - furi_assert(input_report_num < HID_SVC_INPUT_REPORT_COUNT); - - HidSvcDataWrapper report_data = { - .data_ptr = data, - .data_len = len, - }; - return flipper_gatt_characteristic_update( - hid_svc->svc_handle, &hid_svc->input_report_chars[input_report_num], &report_data); -} - -bool hid_svc_update_info(uint8_t* data) { - furi_assert(data); - furi_assert(hid_svc); - - return flipper_gatt_characteristic_update( - hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicInfo], &data); -} - -void hid_svc_register_led_state_callback(HidLedStateEventCallback callback, void* context) { - furi_assert(hid_svc); - furi_assert(callback); - furi_assert(context); - - hid_svc->led_state_event_callback = callback; - hid_svc->led_state_ctx = context; -} - -bool hid_svc_is_started() { - return hid_svc != NULL; -} - -void hid_svc_stop() { - tBleStatus status; - if(hid_svc) { - // Delete characteristics - for(size_t i = 0; i < HidSvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_delete(hid_svc->svc_handle, &hid_svc->chars[i]); - } - - typedef struct { - uint8_t report_count; - FlipperGattCharacteristicInstance* chars; - } HidSvcReportCharProps; - - HidSvcReportCharProps hid_report_chars[] = { - {HID_SVC_INPUT_REPORT_COUNT, hid_svc->input_report_chars}, - {HID_SVC_OUTPUT_REPORT_COUNT, hid_svc->output_report_chars}, - {HID_SVC_FEATURE_REPORT_COUNT, hid_svc->feature_report_chars}, - }; - - for(size_t report_type_idx = 0; report_type_idx < COUNT_OF(hid_report_chars); - report_type_idx++) { - for(size_t report_idx = 0; report_idx < hid_report_chars[report_type_idx].report_count; - report_idx++) { - flipper_gatt_characteristic_delete( - hid_svc->svc_handle, &hid_report_chars[report_type_idx].chars[report_idx]); - } - } - - // Delete service - status = aci_gatt_del_service(hid_svc->svc_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete HID service: %d", status); - } - free(hid_svc); - hid_svc = NULL; - } -} diff --git a/firmware/targets/f7/ble_glue/services/serial_service_uuid.inc b/firmware/targets/f7/ble_glue/services/serial_service_uuid.inc deleted file mode 100644 index a297d9ad6..000000000 --- a/firmware/targets/f7/ble_glue/services/serial_service_uuid.inc +++ /dev/null @@ -1,12 +0,0 @@ - -static const Service_UUID_t service_uuid = { .Service_UUID_128 = \ - { 0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f }}; - -#define SERIAL_SVC_TX_CHAR_UUID \ - { 0x00, 0x00, 0xfe, 0x61, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19 } -#define SERIAL_SVC_RX_CHAR_UUID \ - { 0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19 } -#define SERIAL_SVC_FLOW_CONTROL_UUID \ - { 0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19 } -#define SERIAL_SVC_RPC_STATUS_UUID \ - { 0x00, 0x00, 0xfe, 0x64, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19 } diff --git a/firmware/targets/f7/ble_glue/tl_dbg_conf.h b/firmware/targets/f7/ble_glue/tl_dbg_conf.h index daaa9d82b..ce58af32b 100644 --- a/firmware/targets/f7/ble_glue/tl_dbg_conf.h +++ b/firmware/targets/f7/ble_glue/tl_dbg_conf.h @@ -1,12 +1,39 @@ -#pragma once +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : App/tl_dbg_conf.h + * Description : Debug configuration file for stm32wpan transport layer interface. + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ -#include "app_conf.h" /* required as some configuration used in dbg_trace.h are set there */ -#include "dbg_trace.h" +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __TL_DBG_CONF_H +#define __TL_DBG_CONF_H #ifdef __cplusplus extern "C" { #endif +/* USER CODE BEGIN Tl_Conf */ + +/* Includes ------------------------------------------------------------------*/ +#include "app_conf.h" /* required as some configuration used in dbg_trace.h are set there */ +#include "dbg_trace.h" +#include "hw_if.h" + /** * Enable or Disable traces * The raw data output is the hci binary packet format as specified by the BT specification * @@ -97,6 +124,12 @@ extern "C" { #define TL_MM_DBG_MSG(...) #endif +/* USER CODE END Tl_Conf */ + #ifdef __cplusplus } #endif + +#endif /*__TL_DBG_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/ble_glue/utilities_conf.h b/firmware/targets/f7/ble_glue/utilities_conf.h new file mode 100644 index 000000000..9c15f2263 --- /dev/null +++ b/firmware/targets/f7/ble_glue/utilities_conf.h @@ -0,0 +1,68 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : utilities_conf.h + * Description : Configuration file for STM32 Utilities. + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef UTILITIES_CONF_H +#define UTILITIES_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cmsis_compiler.h" +#include "string.h" +#include + +/****************************************************************************** + * common + ******************************************************************************/ +#define UTILS_ENTER_CRITICAL_SECTION() FURI_CRITICAL_ENTER() + +#define UTILS_EXIT_CRITICAL_SECTION() FURI_CRITICAL_EXIT() + +#define UTILS_MEMSET8(dest, value, size) memset(dest, value, size); + +/****************************************************************************** + * tiny low power manager + * (any macro that does not need to be modified can be removed) + ******************************************************************************/ +#define UTIL_LPM_INIT_CRITICAL_SECTION() +#define UTIL_LPM_ENTER_CRITICAL_SECTION() UTILS_ENTER_CRITICAL_SECTION() +#define UTIL_LPM_EXIT_CRITICAL_SECTION() UTILS_EXIT_CRITICAL_SECTION() + +/****************************************************************************** + * sequencer + * (any macro that does not need to be modified can be removed) + ******************************************************************************/ +#define UTIL_SEQ_INIT_CRITICAL_SECTION() +#define UTIL_SEQ_ENTER_CRITICAL_SECTION() UTILS_ENTER_CRITICAL_SECTION() +#define UTIL_SEQ_EXIT_CRITICAL_SECTION() UTILS_EXIT_CRITICAL_SECTION() +#define UTIL_SEQ_CONF_TASK_NBR (32) +#define UTIL_SEQ_CONF_PRIO_NBR (2) +#define UTIL_SEQ_MEMSET8(dest, value, size) UTILS_MEMSET8(dest, value, size) + +#ifdef __cplusplus +} +#endif + +#endif /*UTILITIES_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index 9defefbfe..ce6e9e291 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -2,18 +2,15 @@ #include #include - #include -#include - -#include #include #include #include #include #include -#include +#include "battery_service.h" + #include #define TAG "FuriHalBt" diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c b/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c index 2bbfc1523..8e05a9904 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c @@ -1,11 +1,11 @@ #include #include -#include -#include -#include +#include "usb_hid.h" +#include "dev_info_service.h" +#include "battery_service.h" +#include "hid_service.h" #include -#include #define FURI_HAL_BT_INFO_BASE_USB_SPECIFICATION (0x0101) #define FURI_HAL_BT_INFO_COUNTRY_CODE (0x00) @@ -221,7 +221,7 @@ void furi_hal_bt_hid_start() { FURI_HAL_BT_HID_INFO_FLAG_REMOTE_WAKE_MSK | FURI_HAL_BT_HID_INFO_FLAG_NORMALLY_CONNECTABLE_MSK, }; - hid_svc_update_info(hid_info_val); + hid_svc_update_info(hid_info_val, sizeof(hid_info_val)); } void furi_hal_bt_hid_stop() { diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c b/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c index 2927d946f..2539e6bd0 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c @@ -1,7 +1,7 @@ #include -#include -#include -#include +#include "dev_info_service.h" +#include "battery_service.h" +#include "serial_service.h" #include diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.c b/firmware/targets/f7/furi_hal/furi_hal_clock.c index 86c8fd467..736ad9f7c 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_clock.c +++ b/firmware/targets/f7/furi_hal/furi_hal_clock.c @@ -4,26 +4,19 @@ #include #include -#include #include #include -#include -#include - #define TAG "FuriHalClock" -#define CPU_CLOCK_EARLY_HZ 4000000 -#define CPU_CLOCK_HSI16_HZ 16000000 -#define CPU_CLOCK_HSE_HZ 32000000 -#define CPU_CLOCK_PLL_HZ 64000000 - +#define CPU_CLOCK_HZ_EARLY 4000000 +#define CPU_CLOCK_HZ_MAIN 64000000 #define TICK_INT_PRIORITY 15U #define HS_CLOCK_IS_READY() (LL_RCC_HSE_IsReady() && LL_RCC_HSI_IsReady()) #define LS_CLOCK_IS_READY() (LL_RCC_LSE_IsReady() && LL_RCC_LSI1_IsReady()) void furi_hal_clock_init_early() { - LL_SetSystemCoreClock(CPU_CLOCK_EARLY_HZ); + LL_SetSystemCoreClock(CPU_CLOCK_HZ_EARLY); LL_Init1msTick(SystemCoreClock); } @@ -31,6 +24,11 @@ void furi_hal_clock_deinit_early() { } void furi_hal_clock_init() { + /* Prepare Flash memory for 64MHz system clock */ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); + while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3) + ; + /* HSE and HSI configuration and activation */ LL_RCC_HSE_SetCapacitorTuning(0x26); LL_RCC_HSE_Enable(); @@ -51,6 +49,9 @@ void furi_hal_clock_init() { while(!LS_CLOCK_IS_READY()) ; + /* RF wakeup */ + LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE); + LL_EXTI_EnableIT_0_31( LL_EXTI_LINE_18); /* Why? Because that's why. See RM0434, Table 61. CPU1 vector table. */ LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_18); @@ -78,17 +79,12 @@ void furi_hal_clock_init() { ; /* Sysclk activation on the main PLL */ - /* Set CPU1 prescaler */ + /* Set CPU1 prescaler*/ LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - /* Set CPU2 prescaler, from this point we are not allowed to touch it. */ + /* Set CPU2 prescaler*/ LL_C2_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); - /* Prepare Flash memory for work on 64MHz system clock */ - LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); - while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3) - ; - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) ; @@ -108,7 +104,7 @@ void furi_hal_clock_init() { ; /* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */ - LL_SetSystemCoreClock(CPU_CLOCK_PLL_HZ); + LL_SetSystemCoreClock(CPU_CLOCK_HZ_MAIN); /* Update the time base */ LL_Init1msTick(SystemCoreClock); @@ -126,7 +122,7 @@ void furi_hal_clock_init() { FURI_LOG_I(TAG, "Init OK"); } -void furi_hal_clock_switch_hse2hsi() { +void furi_hal_clock_switch_to_hsi() { LL_RCC_HSI_Enable(); while(!LL_RCC_HSI_IsReady()) @@ -138,77 +134,46 @@ void furi_hal_clock_switch_hse2hsi() { while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) ; + LL_C2_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) ; } -void furi_hal_clock_switch_hsi2hse() { +void furi_hal_clock_switch_to_pll() { #ifdef FURI_HAL_CLOCK_TRACK_STARTUP uint32_t clock_start_time = DWT->CYCCNT; #endif LL_RCC_HSE_Enable(); - while(!LL_RCC_HSE_IsReady()) - ; - - LL_FLASH_SetLatency(LL_FLASH_LATENCY_1); - while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_1) - ; - - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE); - - while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) - ; - -#ifdef FURI_HAL_CLOCK_TRACK_STARTUP - uint32_t total = DWT->CYCCNT - clock_start_time; - if(total > (20 * 0x148)) { - furi_crash("Slow HSE/PLL startup"); - } -#endif -} - -bool furi_hal_clock_switch_hse2pll() { - furi_assert(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE); - LL_RCC_PLL_Enable(); LL_RCC_PLLSAI1_Enable(); + while(!LL_RCC_HSE_IsReady()) + ; while(!LL_RCC_PLL_IsReady()) ; while(!LL_RCC_PLLSAI1_IsReady()) ; - if(SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_HSE_TO_PLL) != SHCI_Success) { - return false; - } - - furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL); - - LL_SetSystemCoreClock(CPU_CLOCK_PLL_HZ); - SysTick->LOAD = (uint32_t)((SystemCoreClock / 1000) - 1UL); + LL_C2_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); - return true; -} + LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); + while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3) + ; -bool furi_hal_clock_switch_pll2hse() { - furi_assert(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL); + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); - LL_RCC_HSE_Enable(); - while(!LL_RCC_HSE_IsReady()) + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) ; - if(SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_PLL_ON_TO_HSE) != SHCI_Success) { - return false; +#ifdef FURI_HAL_CLOCK_TRACK_STARTUP + uint32_t total = DWT->CYCCNT - clock_start_time; + if(total > (20 * 0x148)) { + furi_crash("Slow HSE/PLL startup"); } - - furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE); - - LL_SetSystemCoreClock(CPU_CLOCK_HSE_HZ); - SysTick->LOAD = (uint32_t)((SystemCoreClock / 1000) - 1UL); - - return true; +#endif } void furi_hal_clock_suspend_tick() { diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.h b/firmware/targets/f7/furi_hal/furi_hal_clock.h index 3100b619f..5e651bbd3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_clock.h +++ b/firmware/targets/f7/furi_hal/furi_hal_clock.h @@ -1,12 +1,11 @@ #pragma once -#include -#include - #ifdef __cplusplus extern "C" { #endif +#include + typedef enum { FuriHalClockMcoLse, FuriHalClockMcoSysclk, @@ -41,23 +40,11 @@ void furi_hal_clock_deinit_early(); /** Initialize clocks */ void furi_hal_clock_init(); -/** Switch clock from HSE to HSI */ -void furi_hal_clock_switch_hse2hsi(); - -/** Switch clock from HSI to HSE */ -void furi_hal_clock_switch_hsi2hse(); - -/** Switch clock from HSE to PLL - * - * @return true if changed, false if failed or not possible at this moment - */ -bool furi_hal_clock_switch_hse2pll(); +/** Switch to HSI clock */ +void furi_hal_clock_switch_to_hsi(); -/** Switch clock from PLL to HSE - * - * @return true if changed, false if failed or not possible at this moment - */ -bool furi_hal_clock_switch_pll2hse(); +/** Switch to PLL clock */ +void furi_hal_clock_switch_to_pll(); /** Stop SysTick counter without resetting */ void furi_hal_clock_suspend_tick(); diff --git a/firmware/targets/f7/furi_hal/furi_hal_console.c b/firmware/targets/f7/furi_hal/furi_hal_console.c index 0b113d2da..2bdc57250 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_console.c +++ b/firmware/targets/f7/furi_hal/furi_hal_console.c @@ -5,6 +5,8 @@ #include #include +#include + #include #define TAG "FuriHalConsole" diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.c b/firmware/targets/f7/furi_hal/furi_hal_flash.c index bc65b29eb..796d20b19 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_flash.c +++ b/firmware/targets/f7/furi_hal/furi_hal_flash.c @@ -7,9 +7,6 @@ #include #include -#include - -#include #define TAG "FuriHalFlash" diff --git a/firmware/targets/f7/furi_hal/furi_hal_memory.c b/firmware/targets/f7/furi_hal/furi_hal_memory.c index 3f8df1f44..7f69b90ca 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_memory.c +++ b/firmware/targets/f7/furi_hal/furi_hal_memory.c @@ -4,6 +4,9 @@ #define TAG "FuriHalMemory" +// STM(TM) Copro(TM) bug(TM) workaround size +#define RAM2B_COPRO_GAP_SIZE_KB 2 + typedef enum { SRAM_A, SRAM_B, @@ -35,20 +38,13 @@ void furi_hal_memory_init() { uint32_t sbrsa = (FLASH->SRRVR & FLASH_SRRVR_SBRSA_Msk) >> FLASH_SRRVR_SBRSA_Pos; uint32_t snbrsa = (FLASH->SRRVR & FLASH_SRRVR_SNBRSA_Msk) >> FLASH_SRRVR_SNBRSA_Pos; - // STM(TM) Copro(TM) bug(TM): SNBRSA is incorrect if stack version is higher than 1.13 and lower than 1.17.2+ - // Radio core started, but not yet ready, so we'll try to guess - // This will be true only if BLE light radio stack used, - // 0x0D is known to be incorrect, 0x0B is known to be correct since 1.17.2+ - // Lower value by 2 pages to match real memory layout - if(snbrsa > 0x0B) { - FURI_LOG_E(TAG, "SNBRSA workaround"); - snbrsa -= 2; - } - uint32_t sram2a_busy_size = (uint32_t)&__sram2a_free__ - (uint32_t)&__sram2a_start__; uint32_t sram2a_unprotected_size = (sbrsa)*1024; uint32_t sram2b_unprotected_size = (snbrsa)*1024; + // STM(TM) Copro(TM) bug(TM) workaround + sram2b_unprotected_size -= 1024 * RAM2B_COPRO_GAP_SIZE_KB; + memory->region[SRAM_A].start = (uint8_t*)&__sram2a_free__; memory->region[SRAM_B].start = (uint8_t*)&__sram2b_start__; diff --git a/firmware/targets/f7/furi_hal/furi_hal_os.c b/firmware/targets/f7/furi_hal/furi_hal_os.c index 046cf79dc..3fc1fbea8 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_os.c +++ b/firmware/targets/f7/furi_hal/furi_hal_os.c @@ -170,35 +170,27 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { return; } - // Core2 shenanigans takes extra time, so we want to compensate tick skew by reducing sleep duration by 1 tick - TickType_t unexpected_idle_ticks = expected_idle_ticks - 1; - // Limit amount of ticks to maximum that timer can count - if(unexpected_idle_ticks > FURI_HAL_OS_MAX_SLEEP) { - unexpected_idle_ticks = FURI_HAL_OS_MAX_SLEEP; + if(expected_idle_ticks > FURI_HAL_OS_MAX_SLEEP) { + expected_idle_ticks = FURI_HAL_OS_MAX_SLEEP; } // Stop IRQ handling, no one should disturb us till we finish __disable_irq(); - do { - // Confirm OS that sleep is still possible - if(eTaskConfirmSleepModeStatus() == eAbortSleep || furi_hal_os_is_pending_irq()) { - break; - } - // Sleep and track how much ticks we spent sleeping - uint32_t completed_ticks = furi_hal_os_sleep(unexpected_idle_ticks); - // Notify system about time spent in sleep - if(completed_ticks > 0) { - if(completed_ticks > expected_idle_ticks) { -#ifdef FURI_HAL_OS_DEBUG - furi_hal_console_printf(">%lu\r\n", completed_ticks - expected_idle_ticks); -#endif - completed_ticks = expected_idle_ticks; - } - vTaskStepTick(completed_ticks); - } - } while(0); + // Confirm OS that sleep is still possible + if(eTaskConfirmSleepModeStatus() == eAbortSleep || furi_hal_os_is_pending_irq()) { + __enable_irq(); + return; + } + + // Sleep and track how much ticks we spent sleeping + uint32_t completed_ticks = furi_hal_os_sleep(expected_idle_ticks); + // Notify system about time spent in sleep + if(completed_ticks > 0) { + vTaskStepTick(MIN(completed_ticks, expected_idle_ticks)); + } + // Reenable IRQ __enable_irq(); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index c14de8569..035919d78 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include @@ -162,11 +162,6 @@ static inline void furi_hal_power_resume_aux_periphs() { static inline void furi_hal_power_deep_sleep() { furi_hal_power_suspend_aux_periphs(); - if(!furi_hal_clock_switch_pll2hse()) { - // Hello core2 my old friend - return; - } - while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) ; @@ -176,13 +171,13 @@ static inline void furi_hal_power_deep_sleep() { LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); // The switch on HSI before entering Stop Mode is required - furi_hal_clock_switch_hse2hsi(); + furi_hal_clock_switch_to_hsi(); } } else { /** * The switch on HSI before entering Stop Mode is required */ - furi_hal_clock_switch_hse2hsi(); + furi_hal_clock_switch_to_hsi(); } /* Release RCC semaphore */ @@ -206,14 +201,12 @@ static inline void furi_hal_power_deep_sleep() { while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) ; - if(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) { - furi_hal_clock_switch_hsi2hse(); + if(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { + furi_hal_clock_switch_to_pll(); } LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); - furi_check(furi_hal_clock_switch_hse2pll()); - furi_hal_power_resume_aux_periphs(); furi_hal_rtc_sync_shadow(); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_random.c b/firmware/targets/f7/furi_hal/furi_hal_random.c index 225519303..cf4b552f6 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_random.c +++ b/firmware/targets/f7/furi_hal/furi_hal_random.c @@ -6,7 +6,7 @@ #include #include -#include +#include #define TAG "FuriHalRandom" diff --git a/firmware/targets/furi_hal_include/furi_hal_bt.h b/firmware/targets/furi_hal_include/furi_hal_bt.h index 25a20c4c3..b7d4eae1a 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h index 0472d31d1..1b6e79ab0 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "serial_service.h" #ifdef __cplusplus extern "C" { diff --git a/lib/stm32wb.scons b/lib/stm32wb.scons index 8a8ad9644..94a1c7075 100644 --- a/lib/stm32wb.scons +++ b/lib/stm32wb.scons @@ -64,6 +64,7 @@ sources += [ "stm32wb_copro/wpan/ble/core/auto/ble_l2cap_aci.c", "stm32wb_copro/wpan/ble/core/template/osal.c", "stm32wb_copro/wpan/utilities/dbg_trace.c", + "stm32wb_copro/wpan/utilities/otp.c", "stm32wb_copro/wpan/utilities/stm_list.c", ] diff --git a/lib/stm32wb_copro b/lib/stm32wb_copro index bbccbefae..6c9c54f05 160000 --- a/lib/stm32wb_copro +++ b/lib/stm32wb_copro @@ -1 +1 @@ -Subproject commit bbccbefae26a2301b8a4b58e57ebdeb93c08269b +Subproject commit 6c9c54f05669b2c4d436df58bb691d3b0d7c86df diff --git a/scripts/ob.data b/scripts/ob.data index 9f6f1d081..605faccbf 100644 --- a/scripts/ob.data +++ b/scripts/ob.data @@ -14,15 +14,15 @@ IWDGSTOP:0x1:rw IWDGSW:0x1:rw IPCCDBA:0x0:rw ESE:0x1:r -SFSA:0xD7:r +SFSA:0xD5:r FSD:0x0:r DDS:0x1:r C2OPT:0x1:r NBRSD:0x0:r -SNBRSA:0xB:r +SNBRSA:0xD:r BRSD:0x0:r SBRSA:0x12:r -SBRV:0x35C00:r +SBRV:0x35400:r PCROP1A_STRT:0x1FF:r PCROP1A_END:0x0:r PCROP_RDP:0x1:rw diff --git a/scripts/update.py b/scripts/update.py index da4a93aee..e6c69d35f 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -74,9 +74,6 @@ class Main(App): self.parser_generate.add_argument( "--I-understand-what-I-am-doing", dest="disclaimer", required=False ) - self.parser_generate.add_argument( - "--stackversion", dest="stack_version", required=False, default="" - ) self.parser_generate.set_defaults(func=self.generate) @@ -97,13 +94,6 @@ class Main(App): if not self.args.radiotype: raise ValueError("Missing --radiotype") radio_meta = CoproBinary(self.args.radiobin) - if self.args.stack_version: - actual_stack_version_str = f"{radio_meta.img_sig.version_major}.{radio_meta.img_sig.version_minor}.{radio_meta.img_sig.version_sub}" - if actual_stack_version_str != self.args.stack_version: - self.logger.error( - f"Stack version mismatch: expected {self.args.stack_version}, actual {actual_stack_version_str}" - ) - return 1 radio_version = self.copro_version_as_int(radio_meta, self.args.radiotype) if ( get_stack_type(self.args.radiotype) not in self.WHITELISTED_STACK_TYPES