ble: profile rework (#3272)

* ble: profile rework, initial
* apps: hid: fix for pairing cleanup
* app: hid: select transport based on #define
* fixing PVS warnings
* ble: serial service: fixed uid naming
* bt service: on-demand dialog init; ble profiles: docs; battery svc: proper update
* Added shci_cmd_resp_wait/shci_cmd_resp_release impl with semaphore
* app: hid: separated transport code
* ble: fixed service init order for serial svc; moved hardfault check to ble_glue
* cli: ps: added thread prio to output, fixed heap display
* ble_glue: naming changes; separate thread for event processing;
* furi: added runtime stats; cli: added cpu% to `ps`
* cli: fixed thread time calculation
* furi: added getter for thread priority
* fixing pvs warnings
* hid profile: fixed naming
* more naming fixes
* hal: ble init small cleanup
* cleanup & draft beacon api
* f18: api sync
* apps: moved example_custom_font from debug to examples
* BLE extra beacon demo app
* naming fix
* UI fixes for demo app (wip)
* desktop, ble svc: added statusbar icon for beacon
* minor cleanup
* Minor cleanup & naming fixes
* api sync
* Removed stale header
* hal: added FURI_BLE_EXTRA_LOG for extra logging; comments & code cleanup
* naming & macro fixes
* quick fixes from review
* Eliminated stock svc_ctl
* cli: ps: removed runtime stats
* minor include fixes
* (void)
* naming fixes
* More naming fixes
* fbt: always build all libs
* fbt: explicitly globbing libs; dist: logging SDK path
* scripts: fixed lib path precedence
* hal: bt: profiles: naming changes, support for passing params to a profile; include cleanup
* ble: hid: added parameter processing for profile template
* api sync
* BLE HID: long name trim
* Removed unused check
* desktop: updated beacon status icon; ble: hid: cleaner device name management
* desktop: updated status icon

Co-authored-by: あく <alleteam@gmail.com>
Co-authored-by: nminaylov <nm29719@gmail.com>
This commit is contained in:
hedger
2024-02-16 11:20:45 +04:00
committed by GitHub
parent 87804374c5
commit 60a9d7e6cf
91 changed files with 3361 additions and 1739 deletions

View File

@@ -1,6 +1,11 @@
#include "ble_glue.h"
#include "app_common.h"
#include "ble_app.h"
#include "ble_event_thread.h"
#include <furi_hal_cortex.h>
#include <core/mutex.h>
#include <core/timer.h>
#include <ble/ble.h>
#include <hci_tl.h>
@@ -13,26 +18,26 @@
#define TAG "Core2"
#define BLE_GLUE_FLAG_SHCI_EVENT (1UL << 0)
#define BLE_GLUE_FLAG_KILL_THREAD (1UL << 1)
#define BLE_GLUE_FLAG_ALL (BLE_GLUE_FLAG_SHCI_EVENT | BLE_GLUE_FLAG_KILL_THREAD)
#define BLE_GLUE_HARDFAULT_CHECK_PERIOD_MS (5000)
#define BLE_GLUE_HARDFAULT_INFO_MAGIC (0x1170FD0F)
#define POOL_SIZE \
(CFG_TLBLE_EVT_QUEUE_LENGTH * 4U * \
DIVC((sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE), 4U))
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_event_pool[POOL_SIZE];
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ble_glue_system_cmd_buff;
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_event_pool[POOL_SIZE];
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ble_glue_cmd_buff;
PLACE_IN_SECTION("MB_MEM2")
ALIGN(4)
static uint8_t ble_glue_system_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U];
static uint8_t ble_glue_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U];
PLACE_IN_SECTION("MB_MEM2")
ALIGN(4)
static uint8_t ble_glue_ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
static uint8_t ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
typedef struct {
FuriMutex* shci_mtx;
FuriThread* thread;
FuriTimer* hardfault_check_timer;
BleGlueStatus status;
BleGlueKeyStorageChangedCallback callback;
BleGlueC2Info c2_info;
@@ -41,9 +46,10 @@ typedef struct {
static BleGlue* ble_glue = NULL;
static int32_t ble_glue_shci_thread(void* argument);
static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status);
static void ble_glue_sys_user_event_callback(void* pPayload);
// static int32_t ble_glue_shci_thread(void* argument);
static void ble_sys_status_not_callback(SHCI_TL_CmdStatus_t status);
static void ble_sys_user_event_callback(void* pPayload);
static void ble_glue_clear_shared_memory();
void ble_glue_set_key_storage_changed_callback(
BleGlueKeyStorageChangedCallback callback,
@@ -54,43 +60,21 @@ void ble_glue_set_key_storage_changed_callback(
ble_glue->context = context;
}
///////////////////////////////////////////////////////////////////////////////
/* TL hook to catch hardfaults */
int32_t ble_glue_TL_SYS_SendCmd(uint8_t* buffer, uint16_t size) {
if(furi_hal_bt_get_hardfault_info()) {
static void furi_hal_bt_hardfault_check(void* context) {
UNUSED(context);
if(ble_glue_get_hardfault_info()) {
furi_crash("ST(R) Copro(R) HardFault");
}
return TL_SYS_SendCmd(buffer, size);
}
void shci_register_io_bus(tSHciIO* fops) {
/* Register IO bus services */
fops->Init = TL_SYS_Init;
fops->Send = ble_glue_TL_SYS_SendCmd;
}
static int32_t ble_glue_TL_BLE_SendCmd(uint8_t* buffer, uint16_t size) {
if(furi_hal_bt_get_hardfault_info()) {
furi_crash("ST(R) Copro(R) HardFault");
}
return TL_BLE_SendCmd(buffer, size);
}
void hci_register_io_bus(tHciIO* fops) {
/* Register IO bus services */
fops->Init = TL_BLE_Init;
fops->Send = ble_glue_TL_BLE_SendCmd;
}
///////////////////////////////////////////////////////////////////////////////
void ble_glue_init() {
void ble_glue_init(void) {
ble_glue = malloc(sizeof(BleGlue));
ble_glue->status = BleGlueStatusStartup;
ble_glue->hardfault_check_timer =
furi_timer_alloc(furi_hal_bt_hardfault_check, FuriTimerTypePeriodic, NULL);
furi_timer_start(ble_glue->hardfault_check_timer, BLE_GLUE_HARDFAULT_CHECK_PERIOD_MS);
#ifdef BLE_GLUE_DEBUG
APPD_Init();
@@ -105,18 +89,17 @@ void ble_glue_init() {
ble_glue->shci_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
// FreeRTOS system task creation
ble_glue->thread = furi_thread_alloc_ex("BleShciDriver", 1024, ble_glue_shci_thread, ble_glue);
furi_thread_start(ble_glue->thread);
ble_event_thread_start();
// System channel initialization
SHci_Tl_Init_Conf.p_cmdbuffer = (uint8_t*)&ble_glue_system_cmd_buff;
SHci_Tl_Init_Conf.StatusNotCallBack = ble_glue_sys_status_not_callback;
shci_init(ble_glue_sys_user_event_callback, (void*)&SHci_Tl_Init_Conf);
SHci_Tl_Init_Conf.p_cmdbuffer = (uint8_t*)&ble_glue_cmd_buff;
SHci_Tl_Init_Conf.StatusNotCallBack = ble_sys_status_not_callback;
shci_init(ble_sys_user_event_callback, (void*)&SHci_Tl_Init_Conf);
/**< Memory Manager channel initialization */
tl_mm_config.p_BleSpareEvtBuffer = ble_glue_ble_spare_event_buff;
tl_mm_config.p_SystemSpareEvtBuffer = ble_glue_system_spare_event_buff;
tl_mm_config.p_AsynchEvtPool = ble_glue_event_pool;
tl_mm_config.p_BleSpareEvtBuffer = ble_spare_event_buff;
tl_mm_config.p_SystemSpareEvtBuffer = ble_glue_spare_event_buff;
tl_mm_config.p_AsynchEvtPool = ble_event_pool;
tl_mm_config.AsynchEvtPoolSize = POOL_SIZE;
TL_MM_Init(&tl_mm_config);
TL_Enable();
@@ -124,15 +107,15 @@ void ble_glue_init() {
/*
* From now, the application is waiting for the ready event ( VS_HCI_C2_Ready )
* received on the system channel before starting the Stack
* This system event is received with ble_glue_sys_user_event_callback()
* This system event is received with ble_sys_user_event_callback()
*/
}
const BleGlueC2Info* ble_glue_get_c2_info() {
const BleGlueC2Info* ble_glue_get_c2_info(void) {
return &ble_glue->c2_info;
}
BleGlueStatus ble_glue_get_c2_status() {
BleGlueStatus ble_glue_get_c2_status(void) {
return ble_glue->status;
}
@@ -159,7 +142,7 @@ static const char* ble_glue_get_reltype_str(const uint8_t reltype) {
}
}
static void ble_glue_update_c2_fw_info() {
static void ble_glue_update_c2_fw_info(void) {
WirelessFwInfo_t wireless_info;
SHCI_GetWirelessFwInfo(&wireless_info);
BleGlueC2Info* local_info = &ble_glue->c2_info;
@@ -178,7 +161,7 @@ static void ble_glue_update_c2_fw_info() {
local_info->StackType = wireless_info.StackType;
snprintf(
local_info->StackTypeString,
BLE_GLUE_MAX_VERSION_STRING_LEN,
BLE_MAX_VERSION_STRING_LEN,
"%d.%d.%d:%s",
local_info->VersionMajor,
local_info->VersionMinor,
@@ -193,7 +176,7 @@ static void ble_glue_update_c2_fw_info() {
local_info->FusMemorySizeFlash = wireless_info.FusMemorySizeFlash;
}
static void ble_glue_dump_stack_info() {
static void ble_glue_dump_stack_info(void) {
const BleGlueC2Info* c2_info = &ble_glue->c2_info;
FURI_LOG_I(
TAG,
@@ -216,59 +199,63 @@ static void ble_glue_dump_stack_info() {
c2_info->MemorySizeFlash);
}
bool ble_glue_wait_for_c2_start(int32_t timeout) {
bool ble_glue_wait_for_c2_start(int32_t timeout_ms) {
bool started = false;
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout_ms * 1000);
do {
furi_delay_tick(1);
started = ble_glue->status == BleGlueStatusC2Started;
if(!started) {
timeout--;
furi_delay_tick(1);
}
} while(!started && (timeout > 0));
} while(!started && !furi_hal_cortex_timer_is_expired(timer));
if(started) {
FURI_LOG_I(
TAG,
"C2 boot completed, mode: %s",
ble_glue->c2_info.mode == BleGlueC2ModeFUS ? "FUS" : "Stack");
ble_glue_update_c2_fw_info();
ble_glue_dump_stack_info();
} else {
if(!started) {
FURI_LOG_E(TAG, "C2 startup failed");
ble_glue->status = BleGlueStatusBroken;
return false;
}
return started;
FURI_LOG_I(
TAG,
"C2 boot completed, mode: %s",
ble_glue->c2_info.mode == BleGlueC2ModeFUS ? "FUS" : "Stack");
ble_glue_update_c2_fw_info();
ble_glue_dump_stack_info();
return true;
}
bool ble_glue_start() {
bool ble_glue_start(void) {
furi_assert(ble_glue);
if(ble_glue->status != BleGlueStatusC2Started) {
return false;
}
bool ret = false;
if(ble_app_init()) {
FURI_LOG_I(TAG, "Radio stack started");
ble_glue->status = BleGlueStatusRadioStackRunning;
ret = true;
if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) {
FURI_LOG_I(TAG, "Flash activity control switched to SEM7");
} else {
FURI_LOG_E(TAG, "Failed to switch flash activity control to SEM7");
}
} else {
if(!ble_app_init()) {
FURI_LOG_E(TAG, "Radio stack startup failed");
ble_glue->status = BleGlueStatusRadioStackMissing;
ble_app_thread_stop();
ble_app_deinit();
return false;
}
return ret;
FURI_LOG_I(TAG, "Radio stack started");
ble_glue->status = BleGlueStatusRadioStackRunning;
return true;
}
bool ble_glue_is_alive() {
void ble_glue_stop(void) {
furi_assert(ble_glue);
ble_event_thread_stop();
// Free resources
furi_mutex_free(ble_glue->shci_mtx);
furi_timer_free(ble_glue->hardfault_check_timer);
ble_glue_clear_shared_memory();
free(ble_glue);
ble_glue = NULL;
}
bool ble_glue_is_alive(void) {
if(!ble_glue) {
return false;
}
@@ -276,7 +263,7 @@ bool ble_glue_is_alive() {
return ble_glue->status >= BleGlueStatusC2Started;
}
bool ble_glue_is_radio_stack_ready() {
bool ble_glue_is_radio_stack_ready(void) {
if(!ble_glue) {
return false;
}
@@ -319,7 +306,7 @@ BleGlueCommandResult ble_glue_force_c2_mode(BleGlueC2Mode desired_mode) {
return BleGlueCommandResultError;
}
static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) {
static void ble_sys_status_not_callback(SHCI_TL_CmdStatus_t status) {
switch(status) {
case SHCI_TL_CmdBusy:
furi_mutex_acquire(ble_glue->shci_mtx, FuriWaitForever);
@@ -341,7 +328,7 @@ static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) {
* ( eg ((tSHCI_UserEvtRxParam*)pPayload)->status shall be set to SHCI_TL_UserEventFlow_Disable )
* When the status is not filled, the buffer is released by default
*/
static void ble_glue_sys_user_event_callback(void* pPayload) {
static void ble_sys_user_event_callback(void* pPayload) {
UNUSED(pPayload);
#ifdef BLE_GLUE_DEBUG
@@ -375,60 +362,18 @@ static void ble_glue_sys_user_event_callback(void* pPayload) {
}
}
static void ble_glue_clear_shared_memory() {
memset(ble_glue_event_pool, 0, sizeof(ble_glue_event_pool));
memset(&ble_glue_system_cmd_buff, 0, sizeof(ble_glue_system_cmd_buff));
memset(ble_glue_system_spare_event_buff, 0, sizeof(ble_glue_system_spare_event_buff));
memset(ble_glue_ble_spare_event_buff, 0, sizeof(ble_glue_ble_spare_event_buff));
static void ble_glue_clear_shared_memory(void) {
memset(ble_event_pool, 0, sizeof(ble_event_pool));
memset(&ble_glue_cmd_buff, 0, sizeof(ble_glue_cmd_buff));
memset(ble_glue_spare_event_buff, 0, sizeof(ble_glue_spare_event_buff));
memset(ble_spare_event_buff, 0, sizeof(ble_spare_event_buff));
}
void ble_glue_thread_stop() {
if(ble_glue) {
FuriThreadId thread_id = furi_thread_get_id(ble_glue->thread);
furi_assert(thread_id);
furi_thread_flags_set(thread_id, BLE_GLUE_FLAG_KILL_THREAD);
furi_thread_join(ble_glue->thread);
furi_thread_free(ble_glue->thread);
// Free resources
furi_mutex_free(ble_glue->shci_mtx);
ble_glue_clear_shared_memory();
free(ble_glue);
ble_glue = NULL;
}
bool ble_glue_reinit_c2(void) {
return (SHCI_C2_Reinit() == SHCI_Success);
}
// Wrap functions
static int32_t ble_glue_shci_thread(void* context) {
UNUSED(context);
uint32_t flags = 0;
while(true) {
flags = furi_thread_flags_wait(BLE_GLUE_FLAG_ALL, FuriFlagWaitAny, FuriWaitForever);
if(flags & BLE_GLUE_FLAG_SHCI_EVENT) {
shci_user_evt_proc();
}
if(flags & BLE_GLUE_FLAG_KILL_THREAD) {
break;
}
}
return 0;
}
void shci_notify_asynch_evt(void* pdata) {
UNUSED(pdata);
if(ble_glue) {
FuriThreadId thread_id = furi_thread_get_id(ble_glue->thread);
furi_assert(thread_id);
furi_thread_flags_set(thread_id, BLE_GLUE_FLAG_SHCI_EVENT);
}
}
bool ble_glue_reinit_c2() {
return SHCI_C2_Reinit() == SHCI_Success;
}
BleGlueCommandResult ble_glue_fus_stack_delete() {
BleGlueCommandResult ble_glue_fus_stack_delete(void) {
FURI_LOG_I(TAG, "Erasing stack");
SHCI_CmdStatus_t erase_stat = SHCI_C2_FUS_FwDelete();
FURI_LOG_I(TAG, "Cmd res = %x", erase_stat);
@@ -450,8 +395,9 @@ BleGlueCommandResult ble_glue_fus_stack_install(uint32_t src_addr, uint32_t dst_
return BleGlueCommandResultError;
}
BleGlueCommandResult ble_glue_fus_get_status() {
BleGlueCommandResult ble_glue_fus_get_status(void) {
furi_check(ble_glue->c2_info.mode == BleGlueC2ModeFUS);
SHCI_FUS_GetState_ErrorCode_t error_code = 0;
uint8_t fus_state = SHCI_C2_FUS_GetState(&error_code);
FURI_LOG_I(TAG, "FUS state: %x, error: %x", fus_state, error_code);
@@ -465,7 +411,7 @@ BleGlueCommandResult ble_glue_fus_get_status() {
return BleGlueCommandResultOK;
}
BleGlueCommandResult ble_glue_fus_wait_operation() {
BleGlueCommandResult ble_glue_fus_wait_operation(void) {
furi_check(ble_glue->c2_info.mode == BleGlueC2ModeFUS);
while(true) {
@@ -479,3 +425,12 @@ BleGlueCommandResult ble_glue_fus_wait_operation() {
}
}
}
const BleGlueHardfaultInfo* ble_glue_get_hardfault_info(void) {
/* AN5289, 4.8.2 */
const BleGlueHardfaultInfo* info = (BleGlueHardfaultInfo*)(SRAM2A_BASE);
if(info->magic != BLE_GLUE_HARDFAULT_INFO_MAGIC) {
return NULL;
}
return info;
}