[FL-1976] BLE HID (#852)
* ble: prototype ble hid * ble: add HID service and characteristics * debug tools: add ble keyboard app * ble: change appearance * ble: working keyboard * bt: introduce furi-hal-bt-hid * bt: restart hid service on each keyboard app enter * bt: introduce switch profile * bt: add profile to ble glue * bt: working profile switch * bt: introduce bt serial profile, rework API * bt: rewotk HID profile * bt: rework gap with profile configuration * bt: move change profile routine to furi hal bt * bt: change switch profile API to blocking * bt: move battery update to furi hal bt * bt: cleanup * bt: add support for f6 target * bt: update documentation * bt: clean up code * bt: remove NO OUTPUT setting * bt: set numeric comparison pairing in BLE HID * bt: support f6 target * bt: set mac address in profile configuration * bt: set advertise name in profile config * bt: rework with furi thread * bt: support f6 target * bt: clear hci command buffer on core2 restart * bt: correct thread kill sequence * bt: fix freertos functions calls * bt: add some enterprise delays fo correct memory free * bt: code cleanup * bt: change terminate -> stop * bt: fix memory leakage Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -10,20 +10,24 @@
|
||||
|
||||
#define TAG "Bt"
|
||||
|
||||
#define BLE_APP_FLAG_HCI_EVENT (1UL << 0)
|
||||
#define BLE_APP_FLAG_KILL_THREAD (1UL << 1)
|
||||
#define BLE_APP_FLAG_ALL (BLE_APP_FLAG_HCI_EVENT | BLE_APP_FLAG_KILL_THREAD)
|
||||
|
||||
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];
|
||||
|
||||
typedef struct {
|
||||
osMutexId_t hci_mtx;
|
||||
osSemaphoreId_t hci_sem;
|
||||
osThreadId_t hci_thread_id;
|
||||
osThreadAttr_t hci_thread_attr;
|
||||
FuriThread* thread;
|
||||
osEventFlagsId_t event_flags;
|
||||
} BleApp;
|
||||
|
||||
static BleApp* ble_app;
|
||||
static BleApp* ble_app = NULL;
|
||||
|
||||
static void ble_app_hci_thread(void *arg);
|
||||
static void ble_app_hci_event_handler(void * pPayload);
|
||||
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);
|
||||
|
||||
bool ble_app_init() {
|
||||
@@ -32,10 +36,14 @@ bool ble_app_init() {
|
||||
// Allocate semafore and mutex for ble command buffer access
|
||||
ble_app->hci_mtx = osMutexNew(NULL);
|
||||
ble_app->hci_sem = osSemaphoreNew(1, 0, NULL);
|
||||
ble_app->event_flags = osEventFlagsNew(NULL);
|
||||
// HCI transport layer thread to handle user asynch events
|
||||
ble_app->hci_thread_attr.name = "BleHciWorker";
|
||||
ble_app->hci_thread_attr.stack_size = 1024;
|
||||
ble_app->hci_thread_id = osThreadNew(ble_app_hci_thread, NULL, &ble_app->hci_thread_attr);
|
||||
ble_app->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(ble_app->thread, "BleHciWorker");
|
||||
furi_thread_set_stack_size(ble_app->thread, 1024);
|
||||
furi_thread_set_context(ble_app->thread, ble_app);
|
||||
furi_thread_set_callback(ble_app->thread, ble_app_hci_thread);
|
||||
furi_thread_start(ble_app->thread);
|
||||
|
||||
// Initialize Ble Transport Layer
|
||||
HCI_TL_HciInitConf_t hci_tl_config = {
|
||||
@@ -92,35 +100,68 @@ void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size) {
|
||||
*size = sizeof(ble_app_nvm);
|
||||
}
|
||||
|
||||
static void ble_app_hci_thread(void *arg) {
|
||||
while(1) {
|
||||
osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever);
|
||||
hci_user_evt_proc();
|
||||
void ble_app_thread_stop() {
|
||||
if(ble_app) {
|
||||
osEventFlagsSet(ble_app->event_flags, BLE_APP_FLAG_KILL_THREAD);
|
||||
furi_thread_join(ble_app->thread);
|
||||
furi_thread_free(ble_app->thread);
|
||||
// Wait to make sure that EventFlags delivers pending events before memory free
|
||||
osDelay(50);
|
||||
// Free resources
|
||||
osMutexDelete(ble_app->hci_mtx);
|
||||
osSemaphoreDelete(ble_app->hci_sem);
|
||||
osEventFlagsDelete(ble_app->event_flags);
|
||||
free(ble_app);
|
||||
ble_app = NULL;
|
||||
memset(&ble_app_cmd_buffer, 0, sizeof(ble_app_cmd_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t ble_app_hci_thread(void *arg) {
|
||||
uint32_t flags = 0;
|
||||
while(1) {
|
||||
flags = osEventFlagsWait(ble_app->event_flags, BLE_APP_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & BLE_APP_FLAG_KILL_THREAD) {
|
||||
break;
|
||||
}
|
||||
if(flags & BLE_APP_FLAG_HCI_EVENT) {
|
||||
hci_user_evt_proc();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Called by WPAN lib
|
||||
void hci_notify_asynch_evt(void* pdata) {
|
||||
osThreadFlagsSet(ble_app->hci_thread_id, 1);
|
||||
if(ble_app) {
|
||||
osEventFlagsSet(ble_app->event_flags, BLE_APP_FLAG_HCI_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
void hci_cmd_resp_release(uint32_t flag) {
|
||||
osSemaphoreRelease(ble_app->hci_sem);
|
||||
if(ble_app) {
|
||||
osSemaphoreRelease(ble_app->hci_sem);
|
||||
}
|
||||
}
|
||||
|
||||
void hci_cmd_resp_wait(uint32_t timeout) {
|
||||
osSemaphoreAcquire(ble_app->hci_sem, osWaitForever);
|
||||
if(ble_app) {
|
||||
osSemaphoreAcquire(ble_app->hci_sem, osWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
static void ble_app_hci_event_handler( void * pPayload ) {
|
||||
SVCCTL_UserEvtFlowStatus_t svctl_return_status;
|
||||
tHCI_UserEvtRxParam *pParam = (tHCI_UserEvtRxParam *)pPayload;
|
||||
|
||||
svctl_return_status = SVCCTL_UserEvtRx((void *)&(pParam->pckt->evtserial));
|
||||
if (svctl_return_status != SVCCTL_UserEvtFlowDisable) {
|
||||
pParam->status = HCI_TL_UserEventFlow_Enable;
|
||||
} else {
|
||||
pParam->status = HCI_TL_UserEventFlow_Disable;
|
||||
if(ble_app) {
|
||||
svctl_return_status = SVCCTL_UserEvtRx((void *)&(pParam->pckt->evtserial));
|
||||
if (svctl_return_status != SVCCTL_UserEvtFlowDisable) {
|
||||
pParam->status = HCI_TL_UserEventFlow_Enable;
|
||||
} else {
|
||||
pParam->status = HCI_TL_UserEventFlow_Disable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user