/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file app_ble.c * @author MCD Application Team * @brief BLE Application ****************************************************************************** * @attention * * Copyright (c) 2019-2021 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. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "app_common.h" #include "app_ble.h" #include "ble.h" #include "dbg_trace.h" #include "tl.h" #include "app_matter.h" #include "cmsis_os.h" #include "otp.h" #include "shci.h" #include "stm32_lpm.h" #include "timers.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /** * security parameters structure */ typedef struct _tSecurityParams { /** * IO capability of the device */ uint8_t ioCapability; /** * Authentication requirement of the device * Man In the Middle protection required? */ uint8_t mitm_mode; /** * bonding mode of the device */ uint8_t bonding_mode; /** * Flag to tell whether OOB data has * to be used during the pairing process */ uint8_t OOB_Data_Present; /** * OOB data to be used in the pairing process if * OOB_Data_Present is set to TRUE */ uint8_t OOB_Data[16]; /** * this variable indicates whether to use a fixed pin * during the pairing process or a passkey has to be * requested to the application during the pairing process * 0 implies use fixed pin and 1 implies request for passkey */ uint8_t Use_Fixed_Pin; /** * minimum encryption key size requirement */ uint8_t encryptionKeySizeMin; /** * maximum encryption key size requirement */ uint8_t encryptionKeySizeMax; /** * fixed pin to be used in the pairing process if * Use_Fixed_Pin is set to 1 */ uint32_t Fixed_Pin; /** * this flag indicates whether the host has to initiate * the security, wait for pairing or does not have any security * requirements.\n * 0x00 : no security required * 0x01 : host should initiate security by sending the slave security * request command * 0x02 : host need not send the clave security request but it * has to wait for paiirng to complete before doing any other * processing */ uint8_t initiateSecurity; } tSecurityParams; /** * global context * contains the variables common to all * services */ typedef struct _tBLEProfileGlobalContext { /** * security requirements of the host */ tSecurityParams bleSecurityParam; /** * gap service handle */ uint16_t gapServiceHandle; /** * device name characteristic handle */ uint16_t devNameCharHandle; /** * appearance characteristic handle */ uint16_t appearanceCharHandle; /** * connection handle of the current active connection * When not in connection, the handle is set to 0xFFFF */ uint16_t connectionHandle; /** * length of the UUID list to be used while advertising */ uint8_t advtServUUIDlen; /** * the UUID list to be used while advertising */ uint8_t advtServUUID[100]; } BleGlobalContext_t; typedef struct { BleGlobalContext_t BleApplicationContext_legacy; APP_BLE_ConnStatus_t Device_Connection_Status; uint8_t SwitchOffGPIO_timer_Id; } BleApplicationContext_t; /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private defines -----------------------------------------------------------*/ #define APPBLE_GAP_DEVICE_NAME_LENGTH 7 #define FAST_ADV_TIMEOUT (30 * 1000 * 1000 / CFG_TS_TICK_VAL) /**< 30s */ #define INITIAL_ADV_TIMEOUT (1 * 1000 * 1000 / CFG_TS_TICK_VAL) /**< 60s */ #define BD_ADDR_SIZE_LOCAL 6 /* USER CODE BEGIN PD */ #define LED_ON_TIMEOUT (0.005 * 1000 * 1000 / CFG_TS_TICK_VAL) /**< 5ms */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t BleCmdBuffer; static const uint8_t M_bd_addr[BD_ADDR_SIZE_LOCAL] = { (uint8_t) ((CFG_ADV_BD_ADDRESS & 0x0000000000FF)), (uint8_t) ((CFG_ADV_BD_ADDRESS & 0x00000000FF00) >> 8), (uint8_t) ((CFG_ADV_BD_ADDRESS & 0x000000FF0000) >> 16), (uint8_t) ((CFG_ADV_BD_ADDRESS & 0x0000FF000000) >> 24), (uint8_t) ((CFG_ADV_BD_ADDRESS & 0x00FF00000000) >> 32), (uint8_t) ((CFG_ADV_BD_ADDRESS & 0xFF0000000000) >> 40) }; static uint8_t bd_addr_udn[BD_ADDR_SIZE_LOCAL]; /** * Identity root key used to derive IRK and DHK(Legacy) */ static const uint8_t BLE_CFG_IR_VALUE[16] = CFG_BLE_IR; /** * Encryption root key used to derive LTK(Legacy) and CSRK */ static const uint8_t BLE_CFG_ER_VALUE[16] = CFG_BLE_ER; static BleApplicationContext_t BleApplicationContext; static uint16_t AdvIntervalMin, AdvIntervalMax; MATTER_App_Notification_evt_t handleNotification; #if L2CAP_REQUEST_NEW_CONN_PARAM != 0 #define SIZE_TAB_CONN_INT 2 float tab_conn_interval[SIZE_TAB_CONN_INT] = { 50, 1000 }; /* ms */ uint8_t index_con_int, mutex; #endif /** * Advertising Data */ static const char local_name[] = { AD_TYPE_COMPLETE_LOCAL_NAME, 'S', 'T', 'D', 'K', 'M', 'A', 'T', 'T', 'E', 'R' }; uint8_t manuf_data[15] = { 0x02, 0x01, 0x06, 0x0B, 0x16, 0xF6, 0xFF, 0x00, 0x00, 0x0F, 0xF1, 0xFF, 0x04, 0x80, 0x00, }; /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Global variables ----------------------------------------------------------*/ osMutexId_t MtxHciId; osSemaphoreId_t SemHciId; osThreadId_t HciUserEvtProcessId; #if (L2CAP_REQUEST_NEW_CONN_PARAM != 0) osThreadId_t ConnIntUpdateReqProcessId; #endif const osThreadAttr_t HciUserEvtProcess_attr = { .name = CFG_HCI_USER_EVT_PROCESS_NAME, .attr_bits = CFG_HCI_USER_EVT_PROCESS_ATTR_BITS, .cb_mem = CFG_HCI_USER_EVT_PROCESS_CB_MEM, .cb_size = CFG_HCI_USER_EVT_PROCESS_CB_SIZE, .stack_mem = CFG_HCI_USER_EVT_PROCESS_STACK_MEM, .priority = CFG_HCI_USER_EVT_PROCESS_PRIORITY, .stack_size = CFG_HCI_USER_EVT_PROCESS_STACK_SIZE }; #if (L2CAP_REQUEST_NEW_CONN_PARAM != 0) const osThreadAttr_t ConnIntUpdateReqProcess_attr = { .name = CFG_CONN_INT_UPD_REQ_PROCESS_NAME, .attr_bits = CFG_CONN_INT_UPD_REQ_PROCESS_ATTR_BITS, .cb_mem = CFG_CONN_INT_UPD_REQ_PROCESS_CB_MEM, .cb_size = CFG_CONN_INT_UPD_REQ_PROCESS_CB_SIZE, .stack_mem = CFG_CONN_INT_UPD_REQ_PROCESS_STACK_MEM, .priority = CFG_CONN_INT_UPD_REQ_PROCESS_PRIORITY, .stack_size = CFG_CONN_INT_UPD_REQ_PROCESS_STACK_SIZE }; #endif /* Private function prototypes -----------------------------------------------*/ static void BLE_UserEvtRx(void * pPayload); static void BLE_StatusNot(HCI_TL_CmdStatus_t status); static void Ble_Tl_Init(void); static void Ble_Hci_Gap_Gatt_Init(void); static const uint8_t * BleGetBdAddress(void); static void HciUserEvtProcess(void * argument); static void Switch_OFF_GPIO(void); #if (L2CAP_REQUEST_NEW_CONN_PARAM != 0) static void ConnIntUpdateReqProcess(void * argument); static void BLE_SVC_L2CAP_Conn_Update(uint16_t Connection_Handle); #endif /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Functions Definition ------------------------------------------------------*/ void APP_BLE_Init_Dyn_1(void) { /* USER CODE BEGIN APP_BLE_Init_1 */ /* USER CODE END APP_BLE_Init_1 */ SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = { { { 0, 0, 0 } }, /**< Header unused */ { 0, /** pBleBufferAddress not used */ 0, /** BleBufferSize not used */ CFG_BLE_NUM_GATT_ATTRIBUTES, CFG_BLE_NUM_GATT_SERVICES, CFG_BLE_ATT_VALUE_ARRAY_SIZE, CFG_BLE_NUM_LINK, CFG_BLE_DATA_LENGTH_EXTENSION, CFG_BLE_PREPARE_WRITE_LIST_SIZE, CFG_BLE_MBLOCK_COUNT, CFG_BLE_MAX_ATT_MTU, CFG_BLE_PERIPHERAL_SCA, CFG_BLE_CENTRAL_SCA, CFG_BLE_LS_SOURCE, CFG_BLE_MAX_CONN_EVENT_LENGTH, CFG_BLE_HSE_STARTUP_TIME, CFG_BLE_VITERBI_MODE, CFG_BLE_OPTIONS, 0, CFG_BLE_MAX_COC_INITIATOR_NBR, CFG_BLE_MIN_TX_POWER, CFG_BLE_MAX_TX_POWER } }; /** * Initialize Ble Transport Layer */ Ble_Tl_Init(); /** * Do not allow standby in the application */ UTIL_LPM_SetOffMode(1 << CFG_LPM_APP_BLE, UTIL_LPM_DISABLE); /** * Register the hci transport layer to handle BLE User Asynchronous Events */ HciUserEvtProcessId = osThreadNew(HciUserEvtProcess, NULL, &HciUserEvtProcess_attr); /** * Starts the BLE Stack on CPU2 */ SHCI_C2_BLE_Init(&ble_init_cmd_packet); /** * Initialization of HCI & GATT & GAP layer */ Ble_Hci_Gap_Gatt_Init(); /** * Initialization of the BLE Services */ SVCCTL_Init(); /** * Initialization of the BLE App Context */ BleApplicationContext.Device_Connection_Status = APP_BLE_IDLE; BleApplicationContext.BleApplicationContext_legacy.connectionHandle = 0xFFFF; /** * Initialization of ADV - Ad Manufacturer Element - Support OTA Bit Mask */ #if (RADIO_ACTIVITY_EVENT != 0) aci_hal_set_radio_activity_mask(0x0006); #endif #if (L2CAP_REQUEST_NEW_CONN_PARAM != 0) ConnIntUpdateReqProcessId = osThreadNew(ConnIntUpdateReqProcess, NULL, &ConnIntUpdateReqProcess_attr); index_con_int = 0; mutex = 1; #endif /** * Initialize Matter Application */ APP_MATTER_Init(); return; } void APP_BLE_Init_Dyn_2(void) { /** * Make device discoverable */ BleApplicationContext.BleApplicationContext_legacy.advtServUUID[0] = NULL; BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen = 0; /* Initialize intervals for reconnexion without intervals update */ AdvIntervalMin = CFG_FAST_CONN_ADV_INTERVAL_MIN; AdvIntervalMax = CFG_FAST_CONN_ADV_INTERVAL_MAX; /** * Start to Advertise to be connected by P2P Client */ #if (CFG_LPM_SUPPORTED == 1) APP_BLE_Adv_Request(APP_BLE_LP_ADV); #endif /* USER CODE BEGIN APP_BLE_Init_2 */ /* USER CODE END APP_BLE_Init_2 */ return; } SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void * pckt) { hci_event_pckt * event_pckt; evt_le_meta_event * meta_evt; event_pckt = (hci_event_pckt *) ((hci_uart_pckt *) pckt)->data; switch (event_pckt->evt) { case HCI_DISCONNECTION_COMPLETE_EVT_CODE: { hci_disconnection_complete_event_rp0 * disconnection_complete_event; disconnection_complete_event = (hci_disconnection_complete_event_rp0 *) event_pckt->data; if (disconnection_complete_event->Connection_Handle == BleApplicationContext.BleApplicationContext_legacy.connectionHandle) { BleApplicationContext.BleApplicationContext_legacy.connectionHandle = 0; BleApplicationContext.Device_Connection_Status = APP_BLE_IDLE; APP_DBG_MSG("\r\n\r** DISCONNECTION EVENT WITH CLIENT \n"); } /* * SPECIFIC to P2P Server APP */ handleNotification.P2P_Evt_Opcode = MATTER_STM_PEER_DISCON_HANDLE_EVT; handleNotification.ConnectionHandle = disconnection_complete_event->Connection_Handle; APP_MATTER_Notification(&handleNotification); /* USER CODE BEGIN EVT_DISCONN_COMPLETE */ /* USER CODE END EVT_DISCONN_COMPLETE */ } break; /* EVT_DISCONN_COMPLETE */ case HCI_LE_META_EVT_CODE: { meta_evt = (evt_le_meta_event *) event_pckt->data; /* USER CODE BEGIN EVT_LE_META_EVENT */ /* USER CODE END EVT_LE_META_EVENT */ switch (meta_evt->subevent) { case HCI_LE_CONNECTION_UPDATE_COMPLETE_SUBEVT_CODE: APP_DBG_MSG("\r\n\r** CONNECTION UPDATE EVENT WITH CLIENT \n"); /** * The connection is done, there is no need anymore to schedule the LP ADV */ break; case HCI_LE_CONNECTION_COMPLETE_SUBEVT_CODE: { hci_le_connection_complete_event_rp0 * connection_complete_event; /** * The connection is done, there is no need anymore to schedule the LP ADV */ connection_complete_event = (hci_le_connection_complete_event_rp0 *) meta_evt->data; APP_DBG_MSG("EVT_LE_CONN_COMPLETE for connection handle 0x%x\n", connection_complete_event->Connection_Handle); if (BleApplicationContext.Device_Connection_Status == APP_BLE_LP_CONNECTING) { /* Connection as client */ BleApplicationContext.Device_Connection_Status = APP_BLE_CONNECTED_CLIENT; } else { /* Connection as server */ BleApplicationContext.Device_Connection_Status = APP_BLE_CONNECTED_SERVER; } BleApplicationContext.BleApplicationContext_legacy.connectionHandle = connection_complete_event->Connection_Handle; /** SPECIFIC to P2P Server APP*/ hci_le_set_data_length(BleApplicationContext.BleApplicationContext_legacy.connectionHandle, 251, 2120); handleNotification.P2P_Evt_Opcode = MATTER_STM_PEER_CONN_HANDLE_EVT; handleNotification.ConnectionHandle = BleApplicationContext.BleApplicationContext_legacy.connectionHandle; APP_MATTER_Notification(&handleNotification); /**/ /* USER CODE END HCI_EVT_LE_CONN_COMPLETE */ } break; /* HCI_EVT_LE_CONN_COMPLETE */ default: /* USER CODE BEGIN SUBEVENT_DEFAULT */ /* USER CODE END SUBEVENT_DEFAULT */ break; } } break; /* HCI_EVT_LE_META_EVENT */ default: /* USER CODE BEGIN ECODE_DEFAULT*/ /* USER CODE END ECODE_DEFAULT*/ break; } return (SVCCTL_UserEvtFlowEnable); } APP_BLE_ConnStatus_t APP_BLE_Get_Server_Connection_Status(void) { return BleApplicationContext.Device_Connection_Status; } /* USER CODE BEGIN FD*/ void APP_BLE_Key_Button1_Action(void) {} void APP_BLE_Key_Button2_Action(void) { #if (L2CAP_REQUEST_NEW_CONN_PARAM != 0) osThreadFlagsSet(ConnIntUpdateReqProcessId, 1); #endif } void APP_BLE_Key_Button3_Action(void) {} void APP_BLE_Stop(void) { /* BLE STOP Procedure */ aci_hal_stack_reset(); } /* USER CODE END FD*/ /************************************************************* * * LOCAL FUNCTIONS * *************************************************************/ static void Ble_Tl_Init(void) { HCI_TL_HciInitConf_t Hci_Tl_Init_Conf; MtxHciId = osMutexNew(NULL); SemHciId = osSemaphoreNew(1, 0, NULL); /*< Create the semaphore and make it busy at initialization */ Hci_Tl_Init_Conf.p_cmdbuffer = (uint8_t *) &BleCmdBuffer; Hci_Tl_Init_Conf.StatusNotCallBack = BLE_StatusNot; hci_init(BLE_UserEvtRx, (void *) &Hci_Tl_Init_Conf); return; } static void Ble_Hci_Gap_Gatt_Init(void) { uint8_t role; uint8_t index; uint16_t gap_service_handle, gap_dev_name_char_handle, gap_appearance_char_handle; const uint8_t * bd_addr; uint32_t srd_bd_addr[2]; uint16_t appearance[1] = { BLE_CFG_GAP_APPEARANCE }; /** * Initialize HCI layer */ /*HCI Reset to synchronise BLE Stack*/ hci_reset(); /** * Write the BD Address */ bd_addr = BleGetBdAddress(); aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET, CONFIG_DATA_PUBADDR_LEN, (uint8_t *) bd_addr); /* BLE MAC in ADV Packet */ // manuf_data[ sizeof(manuf_data)-6] = bd_addr[5]; // manuf_data[ sizeof(manuf_data)-5] = bd_addr[4]; // manuf_data[ sizeof(manuf_data)-4] = bd_addr[3]; // manuf_data[ sizeof(manuf_data)-3] = bd_addr[2]; // manuf_data[ sizeof(manuf_data)-2] = bd_addr[1]; // manuf_data[ sizeof(manuf_data)-1] = bd_addr[0]; /** * Static random Address * The two upper bits shall be set to 1 * The lowest 32bits is read from the UDN to differentiate between devices * The RNG may be used to provide a random number on each power on */ srd_bd_addr[1] = 0x0000ED6E; srd_bd_addr[0] = LL_FLASH_GetUDN(); aci_hal_write_config_data(CONFIG_DATA_RANDOM_ADDRESS_OFFSET, CONFIG_DATA_RANDOM_ADDRESS_LEN, (uint8_t *) srd_bd_addr); /** * Write Identity root key used to derive IRK and DHK(Legacy) */ aci_hal_write_config_data(CONFIG_DATA_IR_OFFSET, CONFIG_DATA_IR_LEN, (uint8_t *) BLE_CFG_IR_VALUE); /** * Write Encryption root key used to derive LTK and CSRK */ aci_hal_write_config_data(CONFIG_DATA_ER_OFFSET, CONFIG_DATA_ER_LEN, (uint8_t *) BLE_CFG_ER_VALUE); /** * Set TX Power to 0dBm. */ aci_hal_set_tx_power_level(1, CFG_TX_POWER); /** * Initialize GATT interface */ aci_gatt_init(); /** * Initialize GAP interface */ role = 0; #if (BLE_CFG_PERIPHERAL == 1) role |= GAP_PERIPHERAL_ROLE; #endif #if (BLE_CFG_CENTRAL == 1) role |= GAP_CENTRAL_ROLE; #endif if (role > 0) { const char * name = "STM32WB"; aci_gap_init(role, 0, APPBLE_GAP_DEVICE_NAME_LENGTH, &gap_service_handle, &gap_dev_name_char_handle, &gap_appearance_char_handle); if (aci_gatt_update_char_value(gap_service_handle, gap_dev_name_char_handle, 0, strlen(name), (uint8_t *) name)) { BLE_DBG_SVCCTL_MSG("Device Name aci_gatt_update_char_value failed.\n"); } } if (aci_gatt_update_char_value(gap_service_handle, gap_appearance_char_handle, 0, 2, (uint8_t *) &appearance)) { BLE_DBG_SVCCTL_MSG("Appearance aci_gatt_update_char_value failed.\n"); } /** * Initialize Default PHY */ hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED); /** * Initialize IO capability */ BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.ioCapability = CFG_IO_CAPABILITY; aci_gap_set_io_capability(BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.ioCapability); /** * Initialize authentication */ BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.mitm_mode = CFG_MITM_PROTECTION; BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.OOB_Data_Present = 0; BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.encryptionKeySizeMin = 8; BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.encryptionKeySizeMax = 16; BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.Use_Fixed_Pin = 1; BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.Fixed_Pin = 111111; BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.bonding_mode = 1; for (index = 0; index < 16; index++) { BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.OOB_Data[index] = (uint8_t) index; } aci_gap_set_authentication_requirement(BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.bonding_mode, BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.mitm_mode, 0, 0, BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.encryptionKeySizeMin, BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.encryptionKeySizeMax, BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.Use_Fixed_Pin, BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.Fixed_Pin, 0); /** * Initialize whitelist */ if (BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.bonding_mode) { aci_gap_configure_whitelist(); } } void APP_BLE_Adv_Request(APP_BLE_ConnStatus_t New_Status) { tBleStatus ret = BLE_STATUS_INVALID_PARAMS; uint16_t Min_Inter, Max_Inter; if (New_Status == APP_BLE_FAST_ADV) { Min_Inter = AdvIntervalMin; Max_Inter = AdvIntervalMax; } else { Min_Inter = CFG_LP_CONN_ADV_INTERVAL_MIN; Max_Inter = CFG_LP_CONN_ADV_INTERVAL_MAX; } APP_DBG_MSG("First index in %d state \n", BleApplicationContext.Device_Connection_Status); if ((New_Status == APP_BLE_LP_ADV) && ((BleApplicationContext.Device_Connection_Status == APP_BLE_FAST_ADV) || (BleApplicationContext.Device_Connection_Status == APP_BLE_LP_ADV))) { /* Connection in ADVERTISE mode have to stop the current advertising */ ret = aci_gap_set_non_discoverable(); if (ret == BLE_STATUS_SUCCESS) { APP_DBG_MSG("Successfully Stopped Advertising"); } else { APP_DBG_MSG("Stop Advertising Failed , result: %d \n", ret); } } BleApplicationContext.Device_Connection_Status = New_Status; /* Start Fast or Low Power Advertising */ ret = aci_gap_set_discoverable(ADV_IND, Min_Inter, Max_Inter, GAP_PUBLIC_ADDR, NO_WHITE_LIST_USE, /* use white list */ sizeof(local_name), (uint8_t *) &local_name, BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen, BleApplicationContext.BleApplicationContext_legacy.advtServUUID, 0, 0); /* Update Advertising data */ ret = aci_gap_update_adv_data(sizeof(manuf_data), (uint8_t *) manuf_data); if (ret == BLE_STATUS_SUCCESS) { if (New_Status == APP_BLE_FAST_ADV) { APP_DBG_MSG("Successfully Start Fast Advertising \n"); } else { APP_DBG_MSG("\n\rSuccessfully Start Low Power Advertising \n\r"); } } else { if (New_Status == APP_BLE_FAST_ADV) { APP_DBG_MSG("Start Fast Advertising Failed , result: %d \n\r", ret); } else { APP_DBG_MSG("Start Low Power Advertising Failed , result: %d \n", ret); } } return; } const uint8_t * BleGetBdAddress(void) { uint8_t * otp_addr; const uint8_t * bd_addr; uint32_t udn; uint32_t company_id; uint32_t device_id; udn = LL_FLASH_GetUDN(); if (udn != 0xFFFFFFFF) { company_id = LL_FLASH_GetSTCompanyID(); device_id = LL_FLASH_GetDeviceID(); /** * Public Address with the ST company ID * bit[47:24] : 24bits (OUI) equal to the company ID * bit[23:16] : Device ID. * bit[15:0] : The last 16bits from the UDN * Note: In order to use the Public Address in a final product, a dedicated * 24bits company ID (OUI) shall be bought. */ bd_addr_udn[0] = (uint8_t) (udn & 0x000000FF); bd_addr_udn[1] = (uint8_t) ((udn & 0x0000FF00) >> 8); bd_addr_udn[2] = (uint8_t) device_id; bd_addr_udn[3] = (uint8_t) (company_id & 0x000000FF); ; bd_addr_udn[4] = (uint8_t) ((company_id & 0x0000FF00) >> 8); bd_addr_udn[5] = (uint8_t) ((company_id & 0x00FF0000) >> 16); bd_addr = (const uint8_t *) bd_addr_udn; } else { otp_addr = OTP_Read(0); if (otp_addr) { bd_addr = ((OTP_ID0_t *) otp_addr)->bd_address; } else { bd_addr = M_bd_addr; } } return bd_addr; } /* USER CODE BEGIN FD_LOCAL_FUNCTION */ /* USER CODE END FD_LOCAL_FUNCTION */ /************************************************************* * *SPECIFIC FUNCTIONS FOR P2P SERVER * *************************************************************/ void APP_BLE_Adv_Cancel(void) { /* USER CODE BEGIN Adv_Cancel_1 */ /* USER CODE END Adv_Cancel_1 */ if (BleApplicationContext.Device_Connection_Status != APP_BLE_CONNECTED_SERVER) { tBleStatus result = 0x00; result = aci_gap_set_non_discoverable(); BleApplicationContext.Device_Connection_Status = APP_BLE_IDLE; if (result == BLE_STATUS_SUCCESS) { APP_DBG_MSG(" \r\n\r"); APP_DBG_MSG("** STOP ADVERTISING ** \r\n\r"); } else { APP_DBG_MSG("** STOP ADVERTISING ** Failed \r\n\r"); } } /* USER CODE BEGIN Adv_Cancel_2 */ /* USER CODE END Adv_Cancel_2 */ return; } static void Switch_OFF_GPIO() { /* USER CODE BEGIN Switch_OFF_GPIO */ /* USER CODE END Switch_OFF_GPIO */ } #if (L2CAP_REQUEST_NEW_CONN_PARAM != 0) void BLE_SVC_L2CAP_Conn_Update(uint16_t Connection_Handle) { /* USER CODE BEGIN BLE_SVC_L2CAP_Conn_Update_1 */ /* USER CODE END BLE_SVC_L2CAP_Conn_Update_1 */ if (mutex == 1) { mutex = 0; index_con_int = (index_con_int + 1) % SIZE_TAB_CONN_INT; uint16_t interval_min = CONN_P(tab_conn_interval[index_con_int]); uint16_t interval_max = CONN_P(tab_conn_interval[index_con_int]); uint16_t peripheral_latency = L2CAP_PERIPHERAL_LATENCY; uint16_t timeout_multiplier = L2CAP_TIMEOUT_MULTIPLIER; tBleStatus result; result = aci_l2cap_connection_parameter_update_req(BleApplicationContext.BleApplicationContext_legacy.connectionHandle, interval_min, interval_max, peripheral_latency, timeout_multiplier); if (result == BLE_STATUS_SUCCESS) { APP_DBG_MSG("BLE_SVC_L2CAP_Conn_Update(), Successfully \r\n\r"); } else { APP_DBG_MSG("BLE_SVC_L2CAP_Conn_Update(), Failed \r\n\r"); } } /* USER CODE BEGIN BLE_SVC_L2CAP_Conn_Update_2 */ /* USER CODE END BLE_SVC_L2CAP_Conn_Update_2 */ return; } static void ConnIntUpdateReqProcess(void * argument) { UNUSED(argument); for (;;) { osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever); if (BleApplicationContext.Device_Connection_Status != APP_BLE_FAST_ADV && BleApplicationContext.Device_Connection_Status != APP_BLE_IDLE) { BLE_SVC_L2CAP_Conn_Update(BleApplicationContext.BleApplicationContext_legacy.connectionHandle); } } } #endif static void HciUserEvtProcess(void * argument) { UNUSED(argument); for (;;) { osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever); hci_user_evt_proc(); } } /* USER CODE BEGIN FD_SPECIFIC_FUNCTIONS */ /* USER CODE END FD_SPECIFIC_FUNCTIONS */ /************************************************************* * * WRAP FUNCTIONS * *************************************************************/ void hci_notify_asynch_evt(void * pdata) { UNUSED(pdata); osThreadFlagsSet(HciUserEvtProcessId, 1); return; } void hci_cmd_resp_release(uint32_t flag) { UNUSED(flag); osSemaphoreRelease(SemHciId); return; } void hci_cmd_resp_wait(uint32_t timeout) { UNUSED(timeout); osSemaphoreAcquire(SemHciId, osWaitForever); return; } static void BLE_UserEvtRx(void * pPayload) { SVCCTL_UserEvtFlowStatus_t svctl_return_status; tHCI_UserEvtRxParam * p_param; p_param = (tHCI_UserEvtRxParam *) pPayload; svctl_return_status = SVCCTL_UserEvtRx((void *) &(p_param->pckt->evtserial)); if (svctl_return_status != SVCCTL_UserEvtFlowDisable) { p_param->status = HCI_TL_UserEventFlow_Enable; } else { p_param->status = HCI_TL_UserEventFlow_Disable; } } static void BLE_StatusNot(HCI_TL_CmdStatus_t status) { switch (status) { case HCI_TL_CmdBusy: /** * All tasks that may send an aci/hci commands shall be listed here * This is to prevent a new command is sent while one is already pending */ osMutexAcquire(MtxHciId, osWaitForever); break; case HCI_TL_CmdAvailable: /** * All tasks that may send an aci/hci commands shall be listed here * This is to prevent a new command is sent while one is already pending */ osMutexRelease(MtxHciId); break; default: break; } return; } void SVCCTL_ResumeUserEventFlow(void) { hci_resume_flow(); return; } /* USER CODE BEGIN FD_WRAP_FUNCTIONS */ /* USER CODE END FD_WRAP_FUNCTIONS */