Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/targets/f6/ble_glue/ble_app.c')
-rw-r--r--firmware/targets/f6/ble_glue/ble_app.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/firmware/targets/f6/ble_glue/ble_app.c b/firmware/targets/f6/ble_glue/ble_app.c
new file mode 100644
index 00000000..c3359e58
--- /dev/null
+++ b/firmware/targets/f6/ble_glue/ble_app.c
@@ -0,0 +1,185 @@
+#include "ble_app.h"
+
+#include "hci_tl.h"
+#include "ble.h"
+#include "shci.h"
+#include "gap.h"
+
+#include <furi_hal.h>
+
+#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];
+
+_Static_assert(
+ sizeof(SHCI_C2_Ble_Init_Cmd_Packet_t) == 49,
+ "Ble stack config structure size mismatch");
+
+typedef struct {
+ osMutexId_t hci_mtx;
+ osSemaphoreId_t hci_sem;
+ FuriThread* thread;
+ osEventFlagsId_t event_flags;
+} BleApp;
+
+static BleApp* ble_app = NULL;
+
+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() {
+ SHCI_CmdStatus_t status;
+ ble_app = furi_alloc(sizeof(BleApp));
+ // 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->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 = {
+ .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
+ 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
+ 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,
+ }};
+ status = SHCI_C2_BLE_Init(&ble_init_cmd_packet);
+ if(status) {
+ FURI_LOG_E(TAG, "Failed to start ble stack: %d", status);
+ }
+ return status == SHCI_Success;
+}
+
+void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size) {
+ *addr = (uint8_t*)ble_app_nvm;
+ *size = sizeof(ble_app_nvm);
+}
+
+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) {
+ if(ble_app) {
+ osEventFlagsSet(ble_app->event_flags, BLE_APP_FLAG_HCI_EVENT);
+ }
+}
+
+void hci_cmd_resp_release(uint32_t flag) {
+ if(ble_app) {
+ osSemaphoreRelease(ble_app->hci_sem);
+ }
+}
+
+void hci_cmd_resp_wait(uint32_t timeout) {
+ 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;
+
+ 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;
+ }
+ }
+}
+
+static void ble_app_hci_status_not_handler(HCI_TL_CmdStatus_t status) {
+ if(status == HCI_TL_CmdBusy) {
+ osMutexAcquire(ble_app->hci_mtx, osWaitForever);
+ } else if(status == HCI_TL_CmdAvailable) {
+ osMutexRelease(ble_app->hci_mtx);
+ }
+}
+
+void SVCCTL_ResumeUserEventFlow(void) {
+ hci_resume_flow();
+}