/*************************************************************************** * *Copyright 2015-2019 BES. *All rights reserved. All unpublished rights reserved. * *No part of this work may be used or reproduced in any form or by any *means, or stored in a database or retrieval system, without prior written *permission of BES. * *Use of this work is governed by a license granted by BES. *This work contains confidential and proprietary information of *BES. which is protected by copyright, trade secret, *trademark and other intellectual property rights. * ****************************************************************************/ /*****************************header include********************************/ #include "app.h" #include "app_ble_include.h" #include "app_bt.h" #include "app_bt_func.h" #include "app_hfp.h" #include "app_sec.h" #include "app_thread.h" #include "app_utils.h" #include "apps.h" #include "ble_app_dbg.h" #include "cmsis_os.h" #include "co_math.h" // Common Maths Definition #include "hal_timer.h" #include "nvrecord.h" #include "nvrecord_ble.h" #include "rwprf_config.h" #include "stdbool.h" #include "string.h" /************************private macro defination***************************/ #define DEBUG_BLE_STATE_MACHINE true #if DEBUG_BLE_STATE_MACHINE #define SET_BLE_STATE(newState) \ do { \ LOG_I("[STATE]%s->%s at line %d", ble_state2str(bleModeEnv.state), \ ble_state2str(newState), __LINE__); \ bleModeEnv.state = (newState); \ } while (0); #define SET_BLE_OP(newOp) \ do { \ LOG_I("[OP]%s->%s at line %d", ble_op2str(bleModeEnv.op), \ ble_op2str(newOp), __LINE__); \ bleModeEnv.op = (newOp); \ } while (0); #else #define SET_BLE_STATE(newState) \ do { \ bleModeEnv.state = (newState); \ } while (0); #define SET_BLE_OP(newOp) \ do { \ bleModeEnv.op = (newOp); \ } while (0); #endif extern void bt_drv_reg_op_set_rand_seed(uint32_t seed); /************************private type defination****************************/ /************************extern function declearation***********************/ extern uint8_t bt_addr[6]; /**********************private function declearation************************/ /*--------------------------------------------------------------------------- * ble_state2str *--------------------------------------------------------------------------- * *Synopsis: * get the string of the ble state * * Parameters: * state - state to get string * * Return: * the string of the BLE state */ static char *ble_state2str(uint8_t state); /*--------------------------------------------------------------------------- * ble_op2str *--------------------------------------------------------------------------- * *Synopsis: * get the string of the ble operation * * Parameters: * op - operation to get string * * Return: * the string of the BLE operation */ static char *ble_op2str(uint8_t op); /*--------------------------------------------------------------------------- * ble_adv_user2str *--------------------------------------------------------------------------- * *Synopsis: * get the string of the ble_adv_user * * Parameters: * op - operation to get string * * Return: * the string of the ble_adv_user */ static char *ble_adv_user2str(enum BLE_ADV_USER_E user); /*--------------------------------------------------------------------------- * ble_adv_config_param *--------------------------------------------------------------------------- * *Synopsis: * configure BLE adv related parameter in @advParam for further use * * Parameters: * advType - advertisment mode, see @ for more info * advInterval - advertisement interval in MS * * Return: * void */ static void ble_adv_config_param(uint8_t advType, uint16_t advInterval); /*--------------------------------------------------------------------------- * ble_adv_is_allowed *--------------------------------------------------------------------------- * *Synopsis: * check if BLE advertisment is allowed or not * * Parameters: * void * * Return: * true - if advertisement is allowed * flase - if adverstisement is not allowed */ static bool ble_adv_is_allowed(void); /*--------------------------------------------------------------------------- * ble_start_adv *--------------------------------------------------------------------------- * *Synopsis: * start BLE advertisement * * Parameters: * param - see @BLE_ADV_PARAM_T to get more info * * Return: * void */ static void ble_start_adv(void *param); /*--------------------------------------------------------------------------- * ble_start_adv_failed_cb *--------------------------------------------------------------------------- * *Synopsis: * callback function of start BLE advertisement failed * * Parameters: * void * * Return: * void */ static void ble_start_adv_failed_cb(void); /*--------------------------------------------------------------------------- * ble_start_scan *--------------------------------------------------------------------------- * *Synopsis: * start BLE scan api * * Parameters: * param - see @BLE_SCAN_PARAM_T to get more info * * Return: * void */ static void ble_start_scan(void *param); /*--------------------------------------------------------------------------- * ble_start_connect *--------------------------------------------------------------------------- * *Synopsis: * start BLE connection * * Parameters: * bleBdAddr - address of BLE device to connect * * Return: * void */ static void ble_start_connect(uint8_t *bleBdAddr); /*--------------------------------------------------------------------------- * ble_stop_all_activities *--------------------------------------------------------------------------- * *Synopsis: * stop all BLE pending operations, stop ongoing adv and scan * NOTE: will not disconnect BLE connections * * Parameters: * void * * Return: * void */ static void ble_stop_all_activities(void); /*--------------------------------------------------------------------------- * ble_execute_pending_op *--------------------------------------------------------------------------- * *Synopsis: * execute pended BLE op * * Parameters: * void * * Return: * void */ static void ble_execute_pending_op(void); /*--------------------------------------------------------------------------- * ble_switch_activities *--------------------------------------------------------------------------- * *Synopsis: * switch BLE activities after last state complete * * Parameters: * void * * Return: * void */ static void ble_switch_activities(void); /************************private variable defination************************/ static BLE_MODE_ENV_T bleModeEnv; static BLE_ADV_PARAM_T advParam; static BLE_SCAN_PARAM_T scanParam; /****************************function defination****************************/ // common used function #ifdef USE_LOG_I_ID static inline char *ble_state2str(uint8_t state) { return (char *)(uint32_t)state; } static inline char *ble_op2str(uint8_t op) { return (char *)(uint32_t)op; } static inline char *ble_adv_user2str(enum BLE_ADV_USER_E user) { return (char *)(uint32_t)user; } #else static char *ble_state2str(uint8_t state) { char *str = NULL; #define CASES(state) \ case state: \ str = "[" #state "]"; \ break switch (state) { CASES(STATE_IDLE); CASES(ADVERTISING); CASES(STARTING_ADV); CASES(STOPPING_ADV); CASES(SCANNING); CASES(STARTING_SCAN); CASES(STOPPING_SCAN); CASES(CONNECTING); CASES(STARTING_CONNECT); CASES(STOPPING_CONNECT); default: str = "[INVALID]"; break; } return str; } static char *ble_op2str(uint8_t op) { char *str = NULL; #define CASEO(op) \ case op: \ str = "[" #op "]"; \ break switch (op) { CASEO(OP_IDLE); CASEO(START_ADV); CASEO(START_SCAN); CASEO(START_CONNECT); CASEO(STOP_ADV); CASEO(STOP_SCAN); CASEO(STOP_CONNECT); default: str = "[INVALID]"; break; } return str; } static char *ble_adv_user2str(enum BLE_ADV_USER_E user) { #define CASE_S(s) \ case s: \ return "[" #s "]"; #define CASE_D() \ default: \ return "[INVALID]"; switch (user) { CASE_S(USER_STUB) CASE_S(USER_GFPS) CASE_S(USER_GSOUND) CASE_S(USER_AI) CASE_S(USER_INTERCONNECTION) CASE_S(USER_TILE) CASE_S(USER_OTA) CASE_D() } } #endif void app_ble_mode_init(void) { LOG_I("%s", __func__); memset(&bleModeEnv, 0, sizeof(bleModeEnv)); SET_BLE_STATE(STATE_IDLE); SET_BLE_OP(OP_IDLE); bleModeEnv.bleEnv = &app_env; } // ble advertisement used functions static void ble_adv_config_param(uint8_t advType, uint16_t advInterval) { uint8_t avail_space; memset(&advParam, 0, sizeof(advParam)); advParam.advType = advType; advParam.advInterval = advInterval; advParam.withFlag = true; // connectable adv is not allowed if max connection reaches if (app_is_arrive_at_max_ble_connections() && (GAPM_ADV_UNDIRECT == advType)) { LOG_W("will change adv type to none-connectable because max ble connection " "reaches"); advParam.advType = GAPM_ADV_NON_CONN; } for (uint8_t user = 0; user < BLE_ADV_USER_NUM; user++) { if (bleModeEnv.bleDataFillFunc[user]) { bleModeEnv.bleDataFillFunc[user]((void *)&advParam); // check if the adv/scan_rsp data length is legal if (advParam.withFlag) { ASSERT(BLE_ADV_DATA_WITH_FLAG_LEN >= advParam.advDataLen, "[BLE][ADV]adv data exceed"); } else { ASSERT(BLE_ADV_DATA_WITHOUT_FLAG_LEN >= advParam.advDataLen, "[BLE][ADV]adv data exceed"); } ASSERT(SCAN_RSP_DATA_LEN >= advParam.scanRspDataLen, "[BLE][ADV]scan response data exceed"); } } if (advParam.withFlag) { avail_space = BLE_ADV_DATA_WITH_FLAG_LEN - advParam.advDataLen - BLE_ADV_DATA_STRUCT_HEADER_LEN; } else { avail_space = BLE_ADV_DATA_WITHOUT_FLAG_LEN - advParam.advDataLen - BLE_ADV_DATA_STRUCT_HEADER_LEN; } // Check if data can be added to the adv Data if (avail_space > 2) { avail_space = co_min(avail_space, bleModeEnv.bleEnv->dev_name_len); advParam.advData[advParam.advDataLen++] = avail_space + 1; // Fill Device Name Flag advParam.advData[advParam.advDataLen++] = (avail_space == bleModeEnv.bleEnv->dev_name_len) ? '\x08' : '\x09'; // Copy device name memcpy(&advParam.advData[advParam.advDataLen], bleModeEnv.bleEnv->dev_name, avail_space); // Update adv Data Length advParam.advDataLen += avail_space; } } static bool ble_adv_is_allowed(void) { bool allowed_adv = true; if (!app_is_stack_ready()) { LOG_I("reason: stack not ready"); allowed_adv = false; } if (app_is_power_off_in_progress()) { LOG_I("reason: in power off mode"); allowed_adv = false; } if (bleModeEnv.advSwitch) { LOG_I("adv switched off:%d", bleModeEnv.advSwitch); allowed_adv = false; } if (btapp_hfp_is_sco_active()) { LOG_I("SCO ongoing"); allowed_adv = false; } if (false == allowed_adv) { app_ble_stop_activities(); } return allowed_adv; } static void ble_start_adv(void *param) { switch (bleModeEnv.state) { case ADVERTISING: SET_BLE_STATE(STOPPING_ADV); SET_BLE_OP(START_ADV); appm_stop_advertising(); break; case SCANNING: SET_BLE_STATE(STOPPING_SCAN); SET_BLE_OP(START_ADV); appm_stop_scanning(); break; case CONNECTING: SET_BLE_STATE(STOPPING_CONNECT); SET_BLE_OP(START_ADV); appm_stop_connecting(); break; case STARTING_ADV: case STARTING_SCAN: case STARTING_CONNECT: case STOPPING_ADV: case STOPPING_SCAN: case STOPPING_CONNECT: SET_BLE_OP(START_ADV); break; case STATE_IDLE: if (!ble_adv_is_allowed()) { LOG_I("[ADV] not allowed."); if (START_ADV == bleModeEnv.op) { SET_BLE_OP(OP_IDLE); } break; } memcpy(&bleModeEnv.advInfo, param, sizeof(bleModeEnv.advInfo)); appm_start_advertising(&bleModeEnv.advInfo); SET_BLE_STATE(STARTING_ADV); break; default: break; } } static void ble_start_adv_failed_cb(void) { if (STARTING_ADV == bleModeEnv.state) { SET_BLE_STATE(STATE_IDLE); } // start pending op(start adv again) } static void ble_start_scan(void *param) { switch (bleModeEnv.state) { case ADVERTISING: SET_BLE_STATE(STOPPING_ADV); SET_BLE_OP(START_SCAN); appm_stop_advertising(); break; case SCANNING: SET_BLE_STATE(STOPPING_SCAN); SET_BLE_OP(START_SCAN); appm_stop_scanning(); break; case CONNECTING: SET_BLE_STATE(STOPPING_CONNECT); SET_BLE_OP(START_SCAN); appm_stop_connecting(); break; case STARTING_ADV: case STARTING_SCAN: case STARTING_CONNECT: case STOPPING_ADV: case STOPPING_SCAN: case STOPPING_CONNECT: SET_BLE_OP(START_SCAN); break; case STATE_IDLE: SET_BLE_STATE(STARTING_SCAN); memcpy(&bleModeEnv.scanInfo, param, sizeof(BLE_SCAN_PARAM_T)); appm_start_scanning(bleModeEnv.scanInfo.scanInterval, bleModeEnv.scanInfo.scanWindow, bleModeEnv.scanInfo.scanType); break; default: break; } } static void ble_start_connect(uint8_t *bleBdAddr) { SET_BLE_OP(START_CONNECT); if ((CONNECTING != bleModeEnv.state) && (STARTING_CONNECT != bleModeEnv.state)) { switch (bleModeEnv.state) { case ADVERTISING: SET_BLE_STATE(STOPPING_ADV); appm_stop_advertising(); break; case SCANNING: SET_BLE_STATE(STOPPING_SCAN); appm_stop_scanning(); break; case STATE_IDLE: SET_BLE_STATE(STARTING_CONNECT); struct gap_bdaddr bdAddr; memcpy(bdAddr.addr.addr, bleBdAddr, BTIF_BD_ADDR_SIZE); bdAddr.addr_type = 0; LOG_I("Master paired with mobile dev is scanned, connect it via BLE."); appm_start_connecting(&bdAddr); break; default: break; } } } static void ble_stop_all_activities(void) { switch (bleModeEnv.state) { case ADVERTISING: SET_BLE_OP(OP_IDLE); SET_BLE_STATE(STOPPING_ADV); appm_stop_advertising(); break; case SCANNING: SET_BLE_OP(OP_IDLE); SET_BLE_STATE(STOPPING_SCAN); appm_stop_scanning(); break; case CONNECTING: SET_BLE_OP(OP_IDLE); SET_BLE_STATE(STOPPING_CONNECT); appm_stop_connecting(); break; case STARTING_ADV: SET_BLE_OP(STOP_ADV); break; case STARTING_SCAN: SET_BLE_OP(STOP_SCAN); break; case STARTING_CONNECT: SET_BLE_OP(STOP_CONNECT); break; case STOPPING_ADV: case STOPPING_SCAN: case STOPPING_CONNECT: SET_BLE_OP(OP_IDLE); break; default: break; } } static void ble_execute_pending_op(void) { LOG_I("%s", __func__); uint8_t op = bleModeEnv.op; SET_BLE_OP(OP_IDLE); switch (op) { case START_ADV: ble_start_adv(&advParam); break; case START_SCAN: ble_start_scan(&scanParam); break; case START_CONNECT: ble_start_connect(bleModeEnv.bleAddrToConnect); break; case STOP_ADV: case STOP_SCAN: case STOP_CONNECT: ble_stop_all_activities(); break; default: break; } } static void ble_switch_activities(void) { switch (bleModeEnv.state) { case STARTING_ADV: SET_BLE_STATE(ADVERTISING); break; case STARTING_SCAN: SET_BLE_STATE(SCANNING); break; case STARTING_CONNECT: SET_BLE_STATE(CONNECTING); break; case STOPPING_ADV: SET_BLE_STATE(STATE_IDLE); break; case STOPPING_SCAN: SET_BLE_STATE(STATE_IDLE); break; case STOPPING_CONNECT: SET_BLE_STATE(STATE_IDLE); break; default: break; } ble_execute_pending_op(); } // BLE advertisement event callbacks void app_advertising_started(void) { app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)ble_switch_activities); } void app_advertising_starting_failed(void) { memset(&bleModeEnv.advInfo, 0, sizeof(bleModeEnv.advInfo)); app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)ble_start_adv_failed_cb); } void app_advertising_stopped(void) { memset(&bleModeEnv.advInfo, 0, sizeof(bleModeEnv.advInfo)); app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)ble_switch_activities); } // BLE adv data updated event callback void app_adv_data_updated(void) { app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)ble_switch_activities); } // BLE scan event callbacks void app_scanning_started(void) { app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)ble_switch_activities); } void app_scanning_stopped(void) { app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)ble_switch_activities); } // BLE connect event callbacks void app_connecting_started(void) { app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)ble_switch_activities); } void app_connecting_stopped(void) { app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)ble_switch_activities); } /** * @brief : callback function of BLE connect failed * */ static void app_ble_connecting_failed_handler(void) { if ((CONNECTING == bleModeEnv.state) || (STOPPING_CONNECT == bleModeEnv.state) || (STARTING_CONNECT == bleModeEnv.state)) { SET_BLE_STATE(STATE_IDLE); } } void app_connecting_failed(void) { app_bt_start_custom_function_in_bt_thread( 0, 0, (uint32_t)app_ble_connecting_failed_handler); } void app_ble_connected_evt_handler(uint8_t conidx, const uint8_t *pPeerBdAddress) { ble_evnet_t event; if ((ADVERTISING == bleModeEnv.state) || (STARTING_ADV == bleModeEnv.state) || (CONNECTING == bleModeEnv.state)) { SET_BLE_STATE(STATE_IDLE); } if (START_CONNECT == bleModeEnv.op) { SET_BLE_OP(OP_IDLE); } event.evt_type = BLE_CONNECT_EVENT; event.p.connect_handled.conidx = conidx; event.p.connect_handled.peer_bdaddr = pPeerBdAddress; app_ble_core_global_handle(&event, NULL); app_ble_refresh_adv_state(BLE_ADVERTISING_INTERVAL); app_stop_fast_connectable_ble_adv_timer(); } void app_ble_disconnected_evt_handler(uint8_t conidx) { ble_evnet_t event; event.evt_type = BLE_DISCONNECT_EVENT; event.p.disconnect_handled.conidx = conidx; app_ble_core_global_handle(&event, NULL); app_ble_refresh_adv_state(BLE_ADVERTISING_INTERVAL); } // BLE APIs for external use void app_ble_data_fill_enable(enum BLE_ADV_USER_E user, bool enable) { LOG_I("%s user %d%s enable %d", __func__, user, ble_adv_user2str(user), enable); ASSERT(user < BLE_ADV_USER_NUM, "%s user %d", __func__, user); if (enable) { bleModeEnv.adv_user_enable |= (1 << user); } else { bleModeEnv.adv_user_enable &= ~(1 << user); } } bool app_ble_get_data_fill_enable(enum BLE_ADV_USER_E user) { bool enable = bleModeEnv.adv_user_enable & (1 << user); LOG_I("%s user %d enable %d", __func__, user, enable); return enable; } /** * @brief : callback function of BLE scan starting failed * */ static void app_ble_scanning_starting_failed_handler(void) { if (STARTING_SCAN == bleModeEnv.state) { SET_BLE_STATE(STATE_IDLE); } } void app_scanning_starting_failed(void) { app_bt_start_custom_function_in_bt_thread( 0, 0, (uint32_t)app_ble_scanning_starting_failed_handler); } // BLE APIs for external use void app_ble_register_data_fill_handle(enum BLE_ADV_USER_E user, BLE_DATA_FILL_FUNC_T func, bool enable) { bool needUpdateAdv = false; if (BLE_ADV_USER_NUM <= user) { LOG_W("invalid user"); } else { if (func != bleModeEnv.bleDataFillFunc[user] && NULL != func) { needUpdateAdv = true; bleModeEnv.bleDataFillFunc[user] = func; } } bleModeEnv.adv_user_register |= (1 << user); if (needUpdateAdv) { app_ble_data_fill_enable(user, enable); } } void app_ble_system_ready(void) { uint32_t generatedSeed = hal_sys_timer_get(); for (uint8_t index = 0; index < sizeof(bt_addr); index++) { generatedSeed ^= (((uint32_t)(bt_addr[index])) << (hal_sys_timer_get() & 0xF)); } bt_drv_reg_op_set_rand_seed(generatedSeed); #if defined(ENHANCED_STACK) app_notify_stack_ready(STACK_READY_BLE); #else app_notify_stack_ready(STACK_READY_BLE | STACK_READY_BT); #endif } static void ble_adv_refreshing(void *param) { BLE_ADV_PARAM_T *pAdvParam = (BLE_ADV_PARAM_T *)param; // four conditions that we just need to update the ble adv data instead of // restarting ble adv // 1. BLE advertising is on // 2. No on-going BLE operation // 3. BLE adv type is the same // 4. BLE adv interval is the same if ((ADVERTISING == bleModeEnv.state) && (OP_IDLE == bleModeEnv.op) && bleModeEnv.advInfo.advType == pAdvParam->advType && bleModeEnv.advInfo.advInterval == pAdvParam->advInterval) { memcpy(&bleModeEnv.advInfo, param, sizeof(bleModeEnv.advInfo)); SET_BLE_STATE(STARTING_ADV); appm_update_adv_data(pAdvParam->advData, pAdvParam->advDataLen, pAdvParam->scanRspData, pAdvParam->scanRspDataLen); } else { // otherwise, restart ble adv ble_start_adv(param); } } static bool app_ble_start_adv(uint8_t advType, uint16_t advInterval) { uint32_t adv_user_enable = bleModeEnv.adv_user_enable; LOG_I("[ADV]type:%d, interval:%d ca:%p", advType, advInterval, __builtin_return_address(0)); if (!ble_adv_is_allowed()) { LOG_I("[ADV] not allowed."); return false; } ble_adv_config_param(advType, advInterval); LOG_I("%s old_user_enable 0x%x new 0x%x", __func__, adv_user_enable, bleModeEnv.adv_user_enable); if (!bleModeEnv.adv_user_enable) { LOG_I("no adv user enable"); LOG_I("[ADV] not allowed."); app_ble_stop_activities(); return false; } // param of adv request is exactly same as current adv if (ADVERTISING == bleModeEnv.state && !memcmp(&bleModeEnv.advInfo, &advParam, sizeof(advParam))) { LOG_I("reason: adv param not changed"); LOG_I("[ADV] not allowed."); return false; } LOG_I("[ADV_LEN] %d [DATA]:", advParam.advDataLen); DUMP8("%02x ", advParam.advData, advParam.advDataLen); LOG_I("[SCAN_RSP_LEN] %d [DATA]:", advParam.scanRspDataLen); DUMP8("%02x ", advParam.scanRspData, advParam.scanRspDataLen); ble_adv_refreshing(&advParam); return true; } void app_ble_start_connectable_adv(uint16_t advInterval) { LOG_D("%s", __func__); app_bt_start_custom_function_in_bt_thread((uint32_t)GAPM_ADV_UNDIRECT, (uint32_t)advInterval, (uint32_t)app_ble_start_adv); } void app_ble_refresh_adv_state(uint16_t advInterval) { LOG_D("%s", __func__); app_bt_start_custom_function_in_bt_thread((uint32_t)GAPM_ADV_UNDIRECT, (uint32_t)advInterval, (uint32_t)app_ble_start_adv); } void app_ble_start_scan(enum BLE_SCAN_FILTER_POLICY scanFilterPolicy, uint16_t scanWindow, uint16_t scanInterval) { scanParam.scanWindow = scanWindow; scanParam.scanInterval = scanInterval; scanParam.scanType = scanFilterPolicy; // BLE_SCAN_ALLOW_ADV_WLST app_bt_start_custom_function_in_bt_thread((uint32_t)(&scanParam), 0, (uint32_t)ble_start_scan); } void app_ble_start_connect(uint8_t *bdAddrToConnect) { memcpy(bleModeEnv.bleAddrToConnect, bdAddrToConnect, BTIF_BD_ADDR_SIZE); app_bt_start_custom_function_in_bt_thread( (uint32_t)bleModeEnv.bleAddrToConnect, 0, (uint32_t)ble_start_connect); } bool app_ble_is_connection_on(uint8_t index) { return (BLE_CONNECTED == bleModeEnv.bleEnv->context[index].connectStatus); } bool app_ble_is_any_connection_exist(void) { bool ret = false; for (uint8_t i = 0; i < BLE_CONNECTION_MAX; i++) { if (app_ble_is_connection_on(i)) { ret = true; } } return ret; } void app_ble_start_disconnect(uint8_t conIdx) { if (BLE_CONNECTED == bleModeEnv.bleEnv->context[conIdx].connectStatus) { LOG_I("will disconnect connection:%d", conIdx); bleModeEnv.bleEnv->context[conIdx].connectStatus = BLE_DISCONNECTING; app_bt_start_custom_function_in_bt_thread((uint32_t)conIdx, 0, (uint32_t)appm_disconnect); } else { LOG_I("will not execute disconnect since state is:%d", bleModeEnv.bleEnv->context[conIdx].connectStatus); } } void app_ble_disconnect_all(void) { for (uint8_t i = 0; i < BLE_CONNECTION_MAX; i++) { app_ble_start_disconnect(i); } } void app_ble_stop_activities(void) { LOG_I("%s %p", __func__, __builtin_return_address(0)); app_stop_fast_connectable_ble_adv_timer(); if (bleModeEnv.state != OP_IDLE) { app_bt_start_custom_function_in_bt_thread( 0, 0, (uint32_t)ble_stop_all_activities); } } void app_ble_force_switch_adv(uint8_t user, bool onOff) { ASSERT(user < BLE_SWITCH_USER_NUM, "ble switch user exceed"); if (onOff) { bleModeEnv.advSwitch &= ~(1 << user); app_ble_refresh_adv_state(BLE_ADVERTISING_INTERVAL); } else if ((bleModeEnv.advSwitch & (1 << user)) == 0) { bleModeEnv.advSwitch |= (1 << user); app_ble_stop_activities(); // disconnect all of the BLE connections if box is closed if (BLE_SWITCH_USER_BOX == user) { app_ble_disconnect_all(); } } LOG_I("%s user %d onoff %d switch 0x%x", __func__, user, onOff, bleModeEnv.advSwitch); } bool app_ble_is_in_advertising_state(void) { return (ADVERTISING == bleModeEnv.state) || (STARTING_ADV == bleModeEnv.state) || (STOPPING_ADV == bleModeEnv.state); } static uint32_t POSSIBLY_UNUSED ble_get_manufacture_data_ptr( uint8_t *advData, uint32_t dataLength, uint8_t *manufactureData) { uint8_t followingDataLengthOfSection; uint8_t rawContentDataLengthOfSection; uint8_t flag; while (dataLength > 0) { followingDataLengthOfSection = *advData++; dataLength--; if (dataLength < followingDataLengthOfSection) { return 0; // wrong adv data format } if (followingDataLengthOfSection > 0) { flag = *advData++; dataLength--; rawContentDataLengthOfSection = followingDataLengthOfSection - 1; if (BLE_ADV_MANU_FLAG == flag) { uint32_t lengthToCopy; if (dataLength < rawContentDataLengthOfSection) { lengthToCopy = dataLength; } else { lengthToCopy = rawContentDataLengthOfSection; } memcpy(manufactureData, advData - 2, lengthToCopy + 2); return lengthToCopy + 2; } else { advData += rawContentDataLengthOfSection; dataLength -= rawContentDataLengthOfSection; } } } return 0; } // received adv data void app_adv_reported_scanned(struct gapm_adv_report_ind *ptInd) { /* LOG_I("Scanned RSSI %d BD addr:", (int8_t)ptInd->report.rssi); DUMP8("0x%02x ", ptInd->report.adv_addr.addr, BTIF_BD_ADDR_SIZE); LOG_I("Scanned adv data:"); DUMP8("0x%02x ", ptInd->report.data, ptInd->report.data_len); */ ble_adv_data_parse(ptInd->report.adv_addr.addr, (int8_t)ptInd->report.rssi, ptInd->report.data, (unsigned char)ptInd->report.data_len); } void app_ibrt_ui_disconnect_ble(void) { app_ble_disconnect_all(); } uint32_t app_ble_get_user_register(void) { return bleModeEnv.adv_user_register; } enum BLE_STATE_E app_ble_get_current_state(void) { return bleModeEnv.state; } enum BLE_OP_E app_ble_get_current_operation(void) { return bleModeEnv.op; } void app_ble_get_runtime_adv_param(uint8_t *pAdvType, uint16_t *pAdvIntervalMs) { *pAdvType = advParam.advType; *pAdvIntervalMs = advParam.advInterval; }