diff --git a/revert_hardfault_fix_for_ios_hid.patch b/revert_hardfault_fix_for_ios_hid.patch deleted file mode 100644 index 6b904fc58..000000000 --- a/revert_hardfault_fix_for_ios_hid.patch +++ /dev/null @@ -1,4889 +0,0 @@ -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