/*************************************************************************** * * 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. * ****************************************************************************/ #include "hal_aud.h" #include "hal_chipid.h" #include "hal_trace.h" #include "apps.h" #include "app_thread.h" #include "app_status_ind.h" #include "bluetooth.h" #include "nvrecord.h" #include "besbt.h" #include "besbt_cfg.h" #include "me_api.h" #include "mei_api.h" #include "a2dp_api.h" #include "hci_api.h" #include "l2cap_api.h" #include "hfp_api.h" #include "dip_api.h" #include "btapp.h" #include "app_bt.h" #include "app_hfp.h" #include "app_bt_func.h" #include "bt_drv_interface.h" #include "os_api.h" #include "bt_drv_reg_op.h" #include "app_a2dp.h" #include "app_dip.h" #include "app_ai_manager_api.h" #include "app_bt.h" #if defined(IBRT) #include "app_tws_ibrt.h" #include "app_ibrt_ui.h" #include "app_ibrt_if.h" #include "app_ibrt_a2dp.h" #endif #ifdef __THIRDPARTY #include "app_thirdparty.h" #endif #include "app_ble_mode_switch.h" #ifdef GFPS_ENABLED #include "app_gfps.h" #endif #ifdef __AI_VOICE__ #include "ai_spp.h" #include "ai_thread.h" #include "ai_manager.h" #endif #ifdef __INTERCONNECTION__ #include "app_interconnection.h" #include "app_interconnection_ble.h" #include "spp_api.h" #include "app_interconnection_ccmp.h" #include "app_spp.h" #include "app_interconnection_spp.h" #endif #ifdef __INTERACTION__ #include "app_interaction.h" #endif #ifdef BISTO_ENABLED #include "gsound_custom_bt.h" #endif #if defined(__EARPHONE_STAY_BCR_SLAVE__) && defined(__BT_ONE_BRING_TWO__) #error can not defined at the same time. #endif #ifdef GFPS_ENABLED #include "app_gfps.h" #endif #ifdef TILE_DATAPATH #include "tile_target_ble.h" #include "rwip_config.h" #endif #if (A2DP_DECODER_VER >= 2) #include "a2dp_decoder.h" #endif extern "C" { #include "ddbif.h" } extern struct BT_DEVICE_T app_bt_device; extern "C" bool app_anc_work_status(void); extern uint8_t avrcp_get_media_status(void); void avrcp_set_media_status(uint8_t status); #ifdef GFPS_ENABLED extern "C" void app_gfps_handling_on_mobile_link_disconnection(btif_remote_device_t* pRemDev); #endif static btif_remote_device_t *connectedMobile = NULL; static btif_remote_device_t *sppOpenMobile = NULL; U16 bt_accessory_feature_feature = BTIF_HF_CUSTOM_FEATURE_SUPPORT; #ifdef __BT_ONE_BRING_TWO__ btif_device_record_t record2_copy; uint8_t record2_avalible; #endif enum bt_profile_reconnect_mode { bt_profile_reconnect_null, bt_profile_reconnect_openreconnecting, bt_profile_reconnect_reconnecting, bt_profile_reconnect_reconnect_pending, }; enum bt_profile_connect_status { bt_profile_connect_status_unknow, bt_profile_connect_status_success, bt_profile_connect_status_failure, }; struct app_bt_profile_manager { bool has_connected; enum bt_profile_connect_status hfp_connect; enum bt_profile_connect_status hsp_connect; enum bt_profile_connect_status a2dp_connect; bt_bdaddr_t rmt_addr; bt_profile_reconnect_mode reconnect_mode; bt_profile_reconnect_mode saved_reconnect_mode; a2dp_stream_t *stream; //HfChannel *chan; hf_chan_handle_t chan; #if defined (__HSP_ENABLE__) HsChannel * hs_chan; #endif uint16_t reconnect_cnt; osTimerId connect_timer; void (* connect_timer_cb)(void const *); APP_BT_CONNECTING_STATE_E connectingState; }; //reconnect = (INTERVAL+PAGETO)*CNT = (3000ms+5000ms)*15 = 120s #define APP_BT_PROFILE_RECONNECT_RETRY_INTERVAL_MS (3000) #define APP_BT_PROFILE_OPENNING_RECONNECT_RETRY_LIMIT_CNT (2) #define APP_BT_PROFILE_RECONNECT_RETRY_LIMIT_CNT (15) #define APP_BT_PROFILE_CONNECT_RETRY_MS (10000) static struct app_bt_profile_manager bt_profile_manager[BT_DEVICE_NUM]; static int8_t app_bt_profile_reconnect_pending_process(void); void app_bt_connectable_mode_stop_reconnecting(void); btif_accessible_mode_t g_bt_access_mode = BTIF_BAM_NOT_ACCESSIBLE; #define APP_BT_PROFILE_BOTH_SCAN_MS (11000) #define APP_BT_PROFILE_PAGE_SCAN_MS (4000) osTimerId app_bt_accessmode_timer = NULL; btif_accessible_mode_t app_bt_accessmode_timer_argument = BTIF_BAM_NOT_ACCESSIBLE; static int app_bt_accessmode_timehandler(void const *param); osTimerDef (APP_BT_ACCESSMODE_TIMER, (void (*)(void const *))app_bt_accessmode_timehandler); // define timers #define A2DP_CONN_CLOSED 10 #ifdef __IAG_BLE_INCLUDE__ #define APP_FAST_BLE_ADV_TIMEOUT_IN_MS 30000 osTimerId app_fast_ble_adv_timeout_timer = NULL; static int app_fast_ble_adv_timeout_timehandler(void const *param); osTimerDef(APP_FAST_BLE_ADV_TIMEOUT_TIMER, ( void (*)(void const *) )app_fast_ble_adv_timeout_timehandler); // define timers /*--------------------------------------------------------------------------- * app_start_fast_connectable_ble_adv *--------------------------------------------------------------------------- * *Synopsis: * start fast connectable BLE adv * * Parameters: * advInterval - adv interval * * Return: * void */ static void app_start_fast_connectable_ble_adv(uint16_t advInterval); #endif #if defined(__INTERCONNECTION__) btif_accessible_mode_t app_bt_get_current_access_mode(void) { return g_bt_access_mode; } bool app_bt_is_connected() { uint8_t i=0; bool connceted_value=false; for(i=0; i= (int8_t)nameLen) { // Check if data can be added to the adv Data adv_data[adv_data_len++] = nameLen + 1; // Fill Device Name Flag adv_data[adv_data_len++] = '\x09'; // Copy device name memcpy(&adv_data[adv_data_len], ble_name_in_nv, nameLen); // Update adv Data Length adv_data_len += nameLen; btif_me_ble_set_adv_data(adv_data_len, adv_data); btif_adv_para_struct_t adv_para; adv_para.interval_min = 32; adv_para.interval_max = 32; adv_para.adv_type = 0; adv_para.own_addr_type = 0; adv_para.peer_addr_type = 0; adv_para.adv_chanmap = 0x07; adv_para.adv_filter_policy = 0; btif_me_ble_set_adv_parameters(&adv_para); btif_me_set_ble_bd_address(ble_addr); btif_me_ble_set_adv_en(1); } else { nameLen = avail_space - 2; // Check if data can be added to the adv Data adv_data[adv_data_len++] = nameLen + 1; // Fill Device Name Flag adv_data[adv_data_len++] = '\x08'; // Copy device name memcpy(&adv_data[adv_data_len], ble_name_in_nv, nameLen); // Update adv Data Length adv_data_len += nameLen; btif_me_ble_set_adv_data(adv_data_len, adv_data); btif_adv_para_struct_t adv_para; adv_para.interval_min = 256; adv_para.interval_max = 256; adv_para.adv_type = 0; adv_para.own_addr_type = 0; adv_para.peer_addr_type = 0; adv_para.adv_chanmap = 0x07; adv_para.adv_filter_policy = 0; btif_me_ble_set_adv_parameters(&adv_para); btif_me_set_ble_bd_address(ble_addr); avail_space = 31; nameLen = strlen(ble_name_in_nv); if(avail_space - 2 < (int8_t)nameLen) nameLen = avail_space - 2; scan_rsp_data[scan_rsp_data_len++] = nameLen + 1; // Fill Device Name Flag scan_rsp_data[scan_rsp_data_len++] = '\x09'; // Copy device name memcpy(&scan_rsp_data[scan_rsp_data_len], ble_name_in_nv, nameLen); // Update Scan response Data Length scan_rsp_data_len += nameLen; btif_me_ble_set_scan_rsp_data(scan_rsp_data_len, scan_rsp_data); btif_me_ble_set_adv_en(1); } } void app_bt_write_controller_memory_for_test(uint32_t addr,uint32_t val,uint8_t type) { TRACE(2,"%s addr=0x%x val=0x%x type=%d",__func__, addr,val,type); app_bt_ME_Write_Controller_Memory_Fortest(addr,val,type); } void app_bt_read_controller_memory_for_test(uint32_t addr,uint32_t len,uint8_t type) { TRACE(2,"%s addr=0x%x len=%x type=%d",__func__, addr,len,type); app_bt_ME_Read_Controller_Memory_Fortest(addr,len,type); } #endif extern "C" uint8_t app_bt_get_act_cons(void) { int activeCons; osapi_lock_stack(); activeCons = btif_me_get_activeCons(); osapi_unlock_stack(); TRACE(2,"%s %d",__func__,activeCons); return activeCons; } enum { INITIATE_PAIRING_NONE = 0, INITIATE_PAIRING_RUN = 1, }; static uint8_t initiate_pairing = INITIATE_PAIRING_NONE; void app_bt_connectable_state_set(uint8_t set) { initiate_pairing = set; } bool is_app_bt_pairing_running(void) { return (initiate_pairing == INITIATE_PAIRING_RUN)?(true):(false); } #define APP_DISABLE_PAGE_SCAN_AFTER_CONN #ifdef APP_DISABLE_PAGE_SCAN_AFTER_CONN osTimerId disable_page_scan_check_timer = NULL; static void disable_page_scan_check_timer_handler(void const *param); osTimerDef (DISABLE_PAGE_SCAN_CHECK_TIMER, (void (*)(void const *))disable_page_scan_check_timer_handler); // define timers static void disable_page_scan_check_timer_handler(void const *param) { #ifdef __BT_ONE_BRING_TWO__ if((btif_me_get_activeCons() > 1) && (initiate_pairing == INITIATE_PAIRING_NONE)) { #else if((btif_me_get_activeCons() > 0) && (initiate_pairing == INITIATE_PAIRING_NONE)) { #endif app_bt_accessmode_set_req(BTIF_BAM_NOT_ACCESSIBLE); } } static void disable_page_scan_check_timer_start(void) { if(disable_page_scan_check_timer == NULL) { disable_page_scan_check_timer = osTimerCreate(osTimer(DISABLE_PAGE_SCAN_CHECK_TIMER), osTimerOnce, NULL); } osTimerStart(disable_page_scan_check_timer, 4000); } #endif void PairingTransferToConnectable(void) { int activeCons; osapi_lock_stack(); activeCons = btif_me_get_activeCons(); osapi_unlock_stack(); TRACE(1,"%s",__func__); app_bt_connectable_state_set(INITIATE_PAIRING_NONE); if(activeCons == 0) { TRACE(0,"!!!PairingTransferToConnectable BAM_CONNECTABLE_ONLY\n"); app_bt_accessmode_set_req(BTIF_BAM_CONNECTABLE_ONLY); } } int app_bt_get_audio_up_id(void) { uint8_t i; btif_remote_device_t *remDev = NULL; btif_cmgr_handler_t *cmgrHandler; for (i=0; imaxInterval); TRACE(2,"checker: %s remDev:%p remote_dev_address:", str,remDev); DUMP8("0x%02x ", btif_me_get_remote_device_bdaddr(remDev)->address, BTIF_BD_ADDR_SIZE); } else { TRACE(3,"checker: %s remDev:%p cmgrHandler:%p", str, remDev, cmgrHandler); } if (a2dp_stream) { TRACE(1,"a2dp State:%d", btif_a2dp_get_stream_state(a2dp_stream)); if (btif_a2dp_get_stream_state(a2dp_stream) > BTIF_AVDTP_STRM_STATE_IDLE) { TRACE(1,"a2dp cmgrHandler remDev:%p", btif_a2dp_get_stream_devic_cmgrHandler_remdev(a2dp_stream)); } } else { TRACE(1,"%s a2dp stream NULL", str); } if (hf_channel) { TRACE(4,"hf_channel Connected:%d IsAudioUp:%d/%d remDev:%p", btif_hf_is_acl_connected(hf_channel), app_bt_device.hf_audio_state[0], btif_hf_check_AudioConnect_status(hf_channel), btif_hf_cmgr_get_remote_device(hf_channel)); } else { TRACE(1,"%s hf_channel NULL", str); } return 0; } #endif int app_bt_state_checker(void) { btif_remote_device_t *remDev = NULL; btif_cmgr_handler_t *cmgrHandler; osapi_lock_stack(); #if defined(IBRT) ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); if (app_tws_ibrt_mobile_link_connected()) { TRACE(1,"checker: IBRT_MASTER activeCons:%d", btif_me_get_activeCons()); remDev = p_ibrt_ctrl->p_tws_remote_dev; if (remDev != NULL) { cmgrHandler = btif_cmgr_get_acl_handler(remDev); if (cmgrHandler) { app_bt_ibrt_profile_checker("tws peers", remDev, cmgrHandler, NULL, NULL); } else { TRACE(0,"checker: cmgrhandler not handle p_tws_remote_dev!"); } } else { TRACE(0,"checker: tws_remote_dev is NULL!"); } remDev = p_ibrt_ctrl->p_mobile_remote_dev; if (remDev != NULL) { cmgrHandler = btif_cmgr_get_acl_handler(remDev); if (cmgrHandler) { app_bt_ibrt_profile_checker("master mobile", remDev, cmgrHandler, app_bt_device.a2dp_connected_stream[0], app_bt_device.hf_conn_flag[0] ? app_bt_device.hf_channel[0] : NULL); } else { TRACE(0,"checker: cmgrhandler not handle mobile_remote_dev"); } } else { TRACE(0,"checker: mobile_remote_dev is NULL!"); } } else if (app_tws_ibrt_slave_ibrt_link_connected()) { TRACE(1,"checker: IBRT_SLAVE activeCons:%d", btif_me_get_activeCons()); remDev = p_ibrt_ctrl->p_tws_remote_dev; if (remDev != NULL) { cmgrHandler = btif_cmgr_get_acl_handler(remDev); if (cmgrHandler) { app_bt_ibrt_profile_checker("tws peers", remDev, cmgrHandler, NULL, NULL); } else { TRACE(0,"checker: cmgrhandler not handle p_tws_remote_dev!"); } } else { TRACE(0,"checker: tws_remote_dev is NULL!"); } if (app_ibrt_ui_is_profile_exchanged()) { app_bt_ibrt_profile_checker("ibrt mobile", NULL, NULL, app_bt_device.a2dp_connected_stream[0], app_bt_device.hf_conn_flag[0] ? app_bt_device.hf_channel[0] : NULL); } } else { TRACE(1,"checker: IBRT_UNKNOW activeCons:%d", btif_me_get_activeCons()); } app_ibrt_if_ctx_checker(); #if defined(ENHANCED_STACK) btif_me_cobuf_state_dump(); btif_me_hcibuff_state_dump(); #endif //BT controller state checker ASSERT(bt_drv_reg_op_check_bt_controller_state(), "BT controller dead!"); #else for (uint8_t i=0; imaxInterval, app_bt_device.hf_audio_state[i]); DUMP8("0x%02x ", btif_me_get_remote_device_bdaddr(remDev)->address, BTIF_BD_ADDR_SIZE); TRACE(4,"remDev:%p a2dp State:%d hf_channel Connected:%d remDev:%p ", remDev, app_bt_device.a2dp_connected_stream[i] ? btif_a2dp_get_stream_state(app_bt_device.a2dp_connected_stream[i]):BTIF_A2DP_STREAM_STATE_CLOSED, app_bt_device.hf_conn_flag[i], app_bt_device.hf_conn_flag[i] ? (btif_remote_device_t *)btif_hf_cmgr_get_remote_device(app_bt_device.hf_channel[i]):NULL); } } else { TRACE(1,"checker: id:%d remDev is NULL!", i); } #ifdef __AI_VOICE__ TRACE(1,"ai_setup_complete %d", app_ai_is_setup_complete()); #endif #ifdef IS_MULTI_AI_ENABLED TRACE(1,"current_spec %d", app_ai_manager_get_current_spec()); #endif #if defined (__HSP_ENABLE__) TRACE(2,"hs_channel Connected:%d remDev:%p ", app_bt_device.hs_conn_flag[i], app_bt_device.hs_channel[i].cmgrHandler.remDev); #endif TRACE(2,"%s btif_me_get_activeCons = %d",__func__,btif_me_get_activeCons()); #ifdef HFP_DEBUG hfp_call_state_checker(); #endif } #if defined(ENHANCED_STACK) btif_me_cobuf_state_dump(); btif_me_hcibuff_state_dump(); #endif #endif osapi_unlock_stack(); return 0; } static uint8_t app_bt_get_devId_from_RemDev( btif_remote_device_t* remDev) { uint8_t connectedDevId = 0; for (uint8_t devId = 0; devId < BT_DEVICE_NUM; devId++) { if ( btif_me_enumerate_remote_devices(devId) == remDev) { TRACE(2, "%s %d", __func__, devId); connectedDevId = devId; break; } } return connectedDevId; } void app_bt_accessible_manager_process(const btif_event_t *Event) { #if defined(IBRT) //IBRT device's access mode will be controlled by UI return; #else btif_event_type_t etype = btif_me_get_callback_event_type(Event); #ifdef __BT_ONE_BRING_TWO__ static uint8_t opening_reconnect_cnf_cnt = 0; //uint8_t disconnectedDevId = app_bt_get_devId_from_RemDev(btif_me_get_callback_event_rem_dev( Event)); if (app_bt_profile_connect_openreconnecting(NULL)) { if (etype == BTIF_BTEVENT_LINK_CONNECT_CNF) { opening_reconnect_cnf_cnt++; } if (record2_avalible) { if (opening_reconnect_cnf_cnt<2) { return; } } } #endif switch (etype) { case BTIF_BTEVENT_LINK_CONNECT_CNF: case BTIF_BTEVENT_LINK_CONNECT_IND: TRACE(1,"BTEVENT_LINK_CONNECT_IND/CNF activeCons:%d",btif_me_get_activeCons()); #if defined(__BTIF_EARPHONE__) && !defined(FPGA) app_stop_10_second_timer(APP_PAIR_TIMER_ID); #endif #ifdef __BT_ONE_BRING_TWO__ if(btif_me_get_activeCons() == 0) { #ifdef __EARPHONE_STAY_BOTH_SCAN__ app_bt_accessmode_set_req(BTIF_BT_DEFAULT_ACCESS_MODE_PAIR); #else app_bt_accessmode_set_req(BTIF_BAM_CONNECTABLE_ONLY); #endif } else if(btif_me_get_activeCons() == 1) { app_bt_accessmode_set_req(BTIF_BAM_CONNECTABLE_ONLY); } else if(btif_me_get_activeCons() >= 2) { app_bt_accessmode_set_req(BTIF_BAM_NOT_ACCESSIBLE); } #else if(btif_me_get_activeCons() == 0) { #ifdef __EARPHONE_STAY_BOTH_SCAN__ app_bt_accessmode_set_req(BTIF_BT_DEFAULT_ACCESS_MODE_PAIR); #else app_bt_accessmode_set_req(BTIF_BAM_CONNECTABLE_ONLY); #endif } else if(btif_me_get_activeCons() >= 1) { app_bt_accessmode_set_req(BTIF_BAM_NOT_ACCESSIBLE); } #endif break; case BTIF_BTEVENT_LINK_DISCONNECT: TRACE(1,"DISCONNECT activeCons:%d",btif_me_get_activeCons()); #ifdef __EARPHONE_STAY_BOTH_SCAN__ #ifdef __BT_ONE_BRING_TWO__ if(btif_me_get_activeCons() == 0) { app_bt_accessmode_set_req(BTIF_BT_DEFAULT_ACCESS_MODE_PAIR); } else if(btif_me_get_activeCons() == 1) { app_bt_accessmode_set_req(BTIF_BAM_CONNECTABLE_ONLY); } else if(btif_me_get_activeCons() >= 2) { app_bt_accessmode_set_req(BTIF_BAM_NOT_ACCESSIBLE); } #else app_bt_accessmode_set_req(BTIF_BT_DEFAULT_ACCESS_MODE_PAIR); #endif #else app_bt_accessmode_set_req(BTIF_BAM_CONNECTABLE_ONLY); #endif break; #ifdef __BT_ONE_BRING_TWO__ case BTIF_BTEVENT_SCO_CONNECT_IND: case BTIF_BTEVENT_SCO_CONNECT_CNF: if(btif_me_get_activeCons() == 1) { app_bt_accessmode_set_req(BTIF_BAM_NOT_ACCESSIBLE); } break; case BTIF_BTEVENT_SCO_DISCONNECT: if(btif_me_get_activeCons() == 1) { app_bt_accessmode_set_req(BTIF_BAM_CONNECTABLE_ONLY); } break; #endif default: break; } #endif } #define APP_BT_SWITCHROLE_LIMIT (2) //#define __SET_OUR_AS_MASTER__ void app_bt_role_manager_process(const btif_event_t *Event) { #if defined(IBRT) || defined(APP_LINEIN_A2DP_SOURCE) || defined(APP_I2S_A2DP_SOURCE) || defined(__APP_A2DP_SOURCE__) return; #else static btif_remote_device_t *opRemDev = NULL; static uint8_t switchrole_cnt = 0; btif_remote_device_t *remDev = NULL; btif_event_type_t etype = btif_me_get_callback_event_type(Event); //on phone connecting switch (etype) { case BTIF_BTEVENT_LINK_CONNECT_IND: if( btif_me_get_callback_event_err_code(Event) == BTIF_BEC_NO_ERROR) { if (btif_me_get_activeCons() == 1) { switch ( btif_me_get_callback_event_rem_dev_role (Event)) { #if defined(__SET_OUR_AS_MASTER__) case BTIF_BCR_SLAVE: case BTIF_BCR_PSLAVE: #else case BTIF_BCR_MASTER: case BTIF_BCR_PMASTER: #endif TRACE(1,"CONNECT_IND try to role %p\n", btif_me_get_callback_event_rem_dev( Event)); //curr connectrot try to role opRemDev =btif_me_get_callback_event_rem_dev( Event); switchrole_cnt = 0; app_bt_Me_SetLinkPolicy(btif_me_get_callback_event_rem_dev( Event), BTIF_BLP_MASTER_SLAVE_SWITCH|BTIF_BLP_SNIFF_MODE); break; #if defined(__SET_OUR_AS_MASTER__) case BTIF_BCR_MASTER: case BTIF_BCR_PMASTER: #else case BTIF_BCR_SLAVE: case BTIF_BCR_PSLAVE: #endif case BTIF_BCR_ANY: case BTIF_BCR_UNKNOWN: default: TRACE(1,"CONNECT_IND disable role %p\n",btif_me_get_callback_event_rem_dev( Event)); //disable roleswitch when 1 connect app_bt_Me_SetLinkPolicy ( btif_me_get_callback_event_rem_dev( Event), BTIF_BLP_SNIFF_MODE); break; } //set next connector to master app_bt_ME_SetConnectionRole(BTIF_BCR_MASTER); } else if (btif_me_get_activeCons() > 1) { switch (btif_me_get_callback_event_rem_dev_role (Event)) { case BTIF_BCR_MASTER: case BTIF_BCR_PMASTER: TRACE(1,"CONNECT_IND disable role %p\n",btif_me_get_callback_event_rem_dev( Event)); //disable roleswitch app_bt_Me_SetLinkPolicy(btif_me_get_callback_event_rem_dev( Event), BTIF_BLP_SNIFF_MODE); break; case BTIF_BCR_SLAVE: case BTIF_BCR_PSLAVE: case BTIF_BCR_ANY: case BTIF_BCR_UNKNOWN: default: //disconnect slave TRACE(1,"CONNECT_IND disconnect slave %p\n",btif_me_get_callback_event_rem_dev( Event)); app_bt_MeDisconnectLink(btif_me_get_callback_event_rem_dev( Event)); break; } //set next connector to master app_bt_ME_SetConnectionRole(BTIF_BCR_MASTER); } } break; case BTIF_BTEVENT_LINK_CONNECT_CNF: if (btif_me_get_activeCons() == 1) { switch (btif_me_get_callback_event_rem_dev_role (Event)) { #if defined(__SET_OUR_AS_MASTER__) case BTIF_BCR_SLAVE: case BTIF_BCR_PSLAVE: #else case BTIF_BCR_MASTER: case BTIF_BCR_PMASTER: #endif TRACE(1,"CONNECT_CNF try to role %p\n",btif_me_get_callback_event_rem_dev( Event)); //curr connectrot try to role opRemDev =btif_me_get_callback_event_rem_dev( Event); switchrole_cnt = 0; app_bt_Me_SetLinkPolicy(btif_me_get_callback_event_rem_dev( Event), BTIF_BLP_MASTER_SLAVE_SWITCH|BTIF_BLP_SNIFF_MODE); app_bt_ME_SwitchRole(btif_me_get_callback_event_rem_dev( Event)); break; #if defined(__SET_OUR_AS_MASTER__) case BTIF_BCR_MASTER: case BTIF_BCR_PMASTER: #else case BTIF_BCR_SLAVE: case BTIF_BCR_PSLAVE: #endif case BTIF_BCR_ANY: case BTIF_BCR_UNKNOWN: default: TRACE(1,"CONNECT_CNF disable role %p\n",btif_me_get_callback_event_rem_dev( Event)); //disable roleswitch app_bt_Me_SetLinkPolicy(btif_me_get_callback_event_rem_dev( Event), BTIF_BLP_SNIFF_MODE); break; } //set next connector to master app_bt_ME_SetConnectionRole(BTIF_BCR_MASTER); } else if (btif_me_get_activeCons() > 1) { switch (btif_me_get_callback_event_rem_dev_role (Event)) { case BTIF_BCR_MASTER: case BTIF_BCR_PMASTER : TRACE(1,"CONNECT_CNF disable role %p\n",btif_me_get_callback_event_rem_dev( Event)); //disable roleswitch app_bt_Me_SetLinkPolicy(btif_me_get_callback_event_rem_dev( Event), BTIF_BLP_SNIFF_MODE); break; case BTIF_BCR_SLAVE: case BTIF_BCR_ANY: case BTIF_BCR_UNKNOWN: default: //disconnect slave TRACE(1,"CONNECT_CNF disconnect slave %p\n",btif_me_get_callback_event_rem_dev( Event)); app_bt_MeDisconnectLink(btif_me_get_callback_event_rem_dev( Event)); break; } //set next connector to master app_bt_ME_SetConnectionRole(BTIF_BCR_MASTER); } break; case BTIF_BTEVENT_LINK_DISCONNECT: if (opRemDev ==btif_me_get_callback_event_rem_dev( Event)) { opRemDev = NULL; switchrole_cnt = 0; } if (btif_me_get_activeCons() == 0) { for (uint8_t i=0; i 1) { uint8_t slave_cnt = 0; for (uint8_t i=0; i1) { TRACE(1,"ROLE_CHANGE disconnect slave %p\n",btif_me_get_callback_event_rem_dev( Event)); app_bt_MeDisconnectLink(btif_me_get_callback_event_rem_dev( Event)); } } break; default: break; } #endif } void app_bt_role_manager_process_dual_slave(const btif_event_t *Event) { #if defined(IBRT) || defined(APP_LINEIN_A2DP_SOURCE) || defined(APP_I2S_A2DP_SOURCE) || defined(__APP_A2DP_SOURCE__) return; #else static btif_remote_device_t *opRemDev = NULL; static uint8_t switchrole_cnt = 0; //btif_remote_device_t *remDev = NULL; //on phone connecting switch ( btif_me_get_callback_event_type(Event)) { case BTIF_BTEVENT_LINK_CONNECT_IND: case BTIF_BTEVENT_LINK_CONNECT_CNF: if(btif_me_get_callback_event_err_code(Event) == BTIF_BEC_NO_ERROR) { switch (btif_me_get_callback_event_rem_dev_role (Event)) { #if defined(__SET_OUR_AS_MASTER__) case BTIF_BCR_SLAVE: case BTIF_BCR_PSLAVE: #else case BTIF_BCR_MASTER: case BTIF_BCR_PMASTER: #endif TRACE(1,"CONNECT_IND/CNF try to role %p\n",btif_me_get_callback_event_rem_dev( Event)); opRemDev =btif_me_get_callback_event_rem_dev( Event); switchrole_cnt = 0; app_bt_Me_SetLinkPolicy(btif_me_get_callback_event_rem_dev( Event), BTIF_BLP_MASTER_SLAVE_SWITCH|BTIF_BLP_SNIFF_MODE); app_bt_ME_SwitchRole(btif_me_get_callback_event_rem_dev( Event)); break; #if defined(__SET_OUR_AS_MASTER__) case BTIF_BCR_MASTER: case BTIF_BCR_PMASTER: #else case BTIF_BCR_SLAVE: case BTIF_BCR_PSLAVE: #endif case BTIF_BCR_ANY: case BTIF_BCR_UNKNOWN: default: TRACE(1,"CONNECT_IND disable role %p\n",btif_me_get_callback_event_rem_dev( Event)); app_bt_Me_SetLinkPolicy(btif_me_get_callback_event_rem_dev( Event), BTIF_BLP_SNIFF_MODE); break; } app_bt_ME_SetConnectionRole(BTIF_BCR_SLAVE); } break; case BTIF_BTEVENT_LINK_DISCONNECT: if (opRemDev ==btif_me_get_callback_event_rem_dev( Event)) { opRemDev = NULL; switchrole_cnt = 0; } if ( btif_me_get_activeCons() == 0) { for (uint8_t i=0; i 1) { btif_remote_device_t* tmpRemDev = NULL; btif_cmgr_handler_t *currbtif_cmgr_handler_t = NULL; btif_cmgr_handler_t *otherbtif_cmgr_handler_t = NULL; currbtif_cmgr_handler_t = btif_cmgr_get_conn_ind_handler(remDev); for (uint8_t i=0; imaxInterval == btif_cmgr_get_cmgrhandler_sniff_info(currbtif_cmgr_handler_t)->maxInterval) { sniffInfo.maxInterval = btif_cmgr_get_cmgrhandler_sniff_info(otherbtif_cmgr_handler_t)->maxInterval -20; sniffInfo.minInterval = btif_cmgr_get_cmgrhandler_sniff_info(otherbtif_cmgr_handler_t)->minInterval - 20; sniffInfo.attempt = BTIF_CMGR_SNIFF_ATTEMPT; sniffInfo.timeout = BTIF_CMGR_SNIFF_TIMEOUT; app_bt_CMGR_SetSniffInfoToAllHandlerByRemDev(&sniffInfo, remDev); } } break; } else { TRACE(3,"%s:enumerate i:%d remDev is NULL, param remDev:%p, this may cause error!", __func__, i, remDev); } } } #endif } void app_bt_sniff_manager_process(const btif_event_t *Event) { static btif_remote_device_t *opRemDev = NULL; btif_remote_device_t *remDev = NULL; btif_cmgr_handler_t *currbtif_cmgr_handler_t = NULL; btif_cmgr_handler_t *otherbtif_cmgr_handler_t = NULL; btif_sniff_info_t sniffInfo; if (!besbt_cfg.sniff) return; switch (btif_me_get_callback_event_type(Event)) { case BTIF_BTEVENT_LINK_CONNECT_IND: break; case BTIF_BTEVENT_LINK_CONNECT_CNF: break; case BTIF_BTEVENT_LINK_DISCONNECT: if (opRemDev ==btif_me_get_callback_event_rem_dev( Event)) { opRemDev = NULL; } sniffInfo.maxInterval = BTIF_CMGR_SNIFF_MAX_INTERVAL; sniffInfo.minInterval = BTIF_CMGR_SNIFF_MIN_INTERVAL; sniffInfo.attempt = BTIF_CMGR_SNIFF_ATTEMPT; sniffInfo.timeout = BTIF_CMGR_SNIFF_TIMEOUT; app_bt_CMGR_SetSniffInfoToAllHandlerByRemDev(&sniffInfo,btif_me_get_callback_event_rem_dev( Event)); break; case BTIF_BTEVENT_MODE_CHANGE: /* if(Event->p.modeChange.curMode == BLM_SNIFF_MODE){ currbtif_cmgr_handler_t = btif_cmgr_get_acl_handler(btif_me_get_callback_event_rem_dev( Event)); if (Event->p.modeChange.interval > CMGR_SNIFF_MAX_INTERVAL){ if (!opRemDev){ opRemDev = currbtif_cmgr_handler_t->remDev; } currbtif_cmgr_handler_t->sniffInfo.maxInterval = CMGR_SNIFF_MAX_INTERVAL; currbtif_cmgr_handler_t->sniffInfo.minInterval = CMGR_SNIFF_MIN_INTERVAL; currbtif_cmgr_handler_t->sniffInfo.attempt = CMGR_SNIFF_ATTEMPT; currbtif_cmgr_handler_t->sniffInfo.timeout = CMGR_SNIFF_TIMEOUT; app_bt_CMGR_SetSniffInfoToAllHandlerByRemDev(&currbtif_cmgr_handler_t->sniffInfo,btif_me_get_callback_event_rem_dev( Event)); app_bt_ME_StopSniff(currbtif_cmgr_handler_t->remDev); }else{ if (currbtif_cmgr_handler_t){ currbtif_cmgr_handler_t->sniffInfo.maxInterval = Event->p.modeChange.interval; currbtif_cmgr_handler_t->sniffInfo.minInterval = Event->p.modeChange.interval; currbtif_cmgr_handler_t->sniffInfo.attempt = CMGR_SNIFF_ATTEMPT; currbtif_cmgr_handler_t->sniffInfo.timeout = CMGR_SNIFF_TIMEOUT; app_bt_CMGR_SetSniffInfoToAllHandlerByRemDev(&currbtif_cmgr_handler_t->sniffInfo,btif_me_get_callback_event_rem_dev( Event)); } if (btif_me_get_activeCons() > 1){ for (uint8_t i=0; isniffInfo.maxInterval == currbtif_cmgr_handler_t->sniffInfo.maxInterval){ if (btif_me_get_current_mode(remDev) == BLM_ACTIVE_MODE){ otherbtif_cmgr_handler_t->sniffInfo.maxInterval -= 20; otherbtif_cmgr_handler_t->sniffInfo.minInterval -= 20; otherbtif_cmgr_handler_t->sniffInfo.attempt = CMGR_SNIFF_ATTEMPT; otherbtif_cmgr_handler_t->sniffInfo.timeout = CMGR_SNIFF_TIMEOUT; app_bt_CMGR_SetSniffInfoToAllHandlerByRemDev(&otherbtif_cmgr_handler_t->sniffInfo, remDev); TRACE(1,"reconfig sniff other RemDev:%x\n", remDev); }else if (btif_me_get_current_mode(remDev) == BLM_SNIFF_MODE){ need_reconfig = true; } } } break; } } } if (need_reconfig){ opRemDev = remDev; if (currbtif_cmgr_handler_t){ currbtif_cmgr_handler_t->sniffInfo.maxInterval -= 20; currbtif_cmgr_handler_t->sniffInfo.minInterval -= 20; currbtif_cmgr_handler_t->sniffInfo.attempt = CMGR_SNIFF_ATTEMPT; currbtif_cmgr_handler_t->sniffInfo.timeout = CMGR_SNIFF_TIMEOUT; app_bt_CMGR_SetSniffInfoToAllHandlerByRemDev(&currbtif_cmgr_handler_t->sniffInfo, currbtif_cmgr_handler_t->remDev); } app_bt_ME_StopSniff(currbtif_cmgr_handler_t->remDev); TRACE(1,"reconfig sniff setup op opRemDev:%x\n", opRemDev); } } } if (Event->p.modeChange.curMode == BLM_ACTIVE_MODE){ if (opRemDev ==btif_me_get_callback_event_rem_dev( Event)){ TRACE(1,"reconfig sniff op opRemDev:%x\n", opRemDev); opRemDev = NULL; currbtif_cmgr_handler_t = btif_cmgr_get_acl_handler(btif_me_get_callback_event_rem_dev( Event)); if (currbtif_cmgr_handler_t){ app_bt_CMGR_SetSniffTimer(currbtif_cmgr_handler_t, NULL, CMGR_SNIFF_TIMER); } } } */ break; case BTIF_BTEVENT_ACL_DATA_ACTIVE: btif_cmgr_handler_t *cmgrHandler; /* Start the sniff timer */ cmgrHandler = btif_cmgr_get_acl_handler(btif_me_get_callback_event_rem_dev( Event)); if (cmgrHandler) app_bt_CMGR_SetSniffTimer(cmgrHandler, NULL, BTIF_CMGR_SNIFF_TIMER); break; case BTIF_BTEVENT_SCO_CONNECT_IND: case BTIF_BTEVENT_SCO_CONNECT_CNF: TRACE(1,"BTEVENT_SCO_CONNECT_IND/CNF cur_remDev = %p",btif_me_get_callback_event_rem_dev( Event)); currbtif_cmgr_handler_t = btif_cmgr_get_conn_ind_handler(btif_me_get_callback_event_rem_dev( Event)); app_bt_Me_SetLinkPolicy( btif_me_get_callback_event_sco_connect_rem_dev(Event), BTIF_BLP_DISABLE_ALL); if (btif_me_get_activeCons() > 1) { for (uint8_t i=0; imobile_pair_canceled) #endif { memset(&record, 0, sizeof(record)); record.bdAddr = *bd_ddr; ddbif_add_record(&record); } nv_record_flash_flush(); } } break; } // trace filter switch (btif_me_get_callback_event_type(Event)) { case BTIF_BTEVENT_HCI_COMMAND_SENT: case BTIF_BTEVENT_ACL_DATA_NOT_ACTIVE: case BTIF_BTEVENT_ACL_DATA_ACTIVE: break; default: TRACE(1,"[BTEVENT] evt = %d", btif_me_get_callback_event_type(Event)); break; } switch (btif_me_get_callback_event_type(Event)) { case BTIF_BTEVENT_LINK_CONNECT_IND: hfp_reconnecting_timer_stop_callback(Event); case BTIF_BTEVENT_LINK_CONNECT_CNF: #ifdef __BT_ONE_BRING_TWO__ if(bt_drv_reg_op_get_reconnecting_flag()) { bt_drv_reg_op_clear_reconnecting_flag(); if(a2dp_is_music_ongoing()) a2dp_update_music_link(); } #endif if (BTIF_BEC_NO_ERROR == btif_me_get_callback_event_err_code(Event)) { connectedMobile = btif_me_get_callback_event_rem_dev( Event); uint8_t connectedDevId = app_bt_get_devId_from_RemDev(connectedMobile); app_bt_set_connecting_profiles_state(connectedDevId); TRACE(1,"MEC(pendCons) is %d", btif_me_get_pendCons()); app_bt_stay_active_rem_dev(btif_me_get_callback_event_rem_dev( Event)); #ifdef __BT_ONE_BRING_TWO__ btif_remote_device_t *remote_dev = btif_me_get_callback_event_rem_dev(Event); uint16_t conn_handle = btif_me_get_remote_device_hci_handle(remote_dev); btif_me_qos_set_up(conn_handle); #endif #if (defined(__AI_VOICE__) || defined(BISTO_ENABLED)) app_ai_if_mobile_connect_handle(btif_me_get_callback_event_rem_dev_bd_addr(Event)); #endif } TRACE(4,"[BTEVENT] CONNECT_IND/CNF evt:%d errCode:0x%0x newRole:%d activeCons:%d",btif_me_get_callback_event_type(Event), btif_me_get_callback_event_err_code(Event),btif_me_get_callback_event_rem_dev_role (Event), btif_me_get_activeCons()); DUMP8("%02x ", btif_me_get_callback_event_rem_dev_bd_addr(Event), BTIF_BD_ADDR_SIZE); #if defined(__BTIF_EARPHONE__) && defined(__BTIF_AUTOPOWEROFF__) && !defined(FPGA) if (btif_me_get_activeCons() == 0) { app_start_10_second_timer(APP_POWEROFF_TIMER_ID); } else { app_stop_10_second_timer(APP_POWEROFF_TIMER_ID); } #endif #if defined(__BT_ONE_BRING_TWO__)||defined(IBRT) if (btif_me_get_activeCons() > 2) { TRACE(1,"CONNECT_IND/CNF activeCons:%d so disconnect it", btif_me_get_activeCons()); app_bt_MeDisconnectLink(btif_me_get_callback_event_rem_dev( Event)); } #else if (btif_me_get_activeCons() > 1) { TRACE(1,"CONNECT_IND/CNF activeCons:%d so disconnect it", btif_me_get_activeCons()); app_bt_MeDisconnectLink(btif_me_get_callback_event_rem_dev( Event)); } #endif break; case BTIF_BTEVENT_LINK_DISCONNECT: { connectedMobile = btif_me_get_callback_event_rem_dev( Event); uint8_t disconnectedDevId = app_bt_get_devId_from_RemDev(connectedMobile); connectedMobile = NULL; app_bt_clear_connecting_profiles_state(disconnectedDevId); btif_remote_device_t *remote_dev = btif_me_get_callback_event_disconnect_rem_dev(Event); if(remote_dev) { uint16_t conhdl = btif_me_get_remote_device_hci_handle(remote_dev); bt_drv_reg_op_acl_tx_silence_clear(conhdl); bt_drv_hwspi_select(conhdl-0x80, 0); } TRACE(5,"[BTEVENT] DISCONNECT evt = %d encryptState:%d reason:0x%02x/0x%02x activeCons:%d", btif_me_get_callback_event_type(Event), btif_me_get_remote_sevice_encrypt_state(btif_me_get_callback_event_rem_dev( Event)), btif_me_get_remote_device_disc_reason_saved(btif_me_get_callback_event_rem_dev( Event)), btif_me_get_remote_device_disc_reason(btif_me_get_callback_event_rem_dev( Event)), btif_me_get_activeCons()); DUMP8("%02x ", btif_me_get_callback_event_rem_dev_bd_addr(Event), BTIF_BD_ADDR_SIZE); #ifdef CHIP_BEST2000 bt_drv_patch_force_disconnect_ack(); #endif //disconnect from reconnect connection, and the HF don't connect successful once //(whitch will release the saved_reconnect_mode ). so we are reconnect fail with remote link key loss. // goto pairing. //reason 07 maybe from the controller's error . //05 auth error //16 io cap reject. #if defined(__BTIF_EARPHONE__) && defined(__BTIF_AUTOPOWEROFF__) && !defined(FPGA) if (btif_me_get_activeCons() == 0) { app_start_10_second_timer(APP_POWEROFF_TIMER_ID); } #endif #if defined(BISTO_ENABLED) gsound_custom_bt_link_disconnected_handler(btif_me_get_callback_event_rem_dev_bd_addr(Event)->address); #endif #if defined(__AI_VOICE__) app_ai_mobile_disconnect_handle(btif_me_get_callback_event_rem_dev_bd_addr(Event)); #endif #ifdef __IAG_BLE_INCLUDE__ // start BLE adv app_ble_force_switch_adv(BLE_SWITCH_USER_BT_CONNECT, true); #endif #ifdef BTIF_DIP_DEVICE btif_dip_clear(remote_dev); #endif app_bt_active_mode_reset(disconnectedDevId); #ifdef GFPS_ENABLED app_gfps_handling_on_mobile_link_disconnection( btif_me_get_callback_event_rem_dev(Event)); #endif #if !defined(IBRT) && defined( BT_XTAL_SYNC_NO_RESET) bt_term_xtal_sync_default(); #endif break; } case BTIF_BTEVENT_ROLE_CHANGE: TRACE(3,"[BTEVENT] ROLE_CHANGE eType:0x%x errCode:0x%x newRole:%d activeCons:%d", btif_me_get_callback_event_type(Event), btif_me_get_callback_event_err_code(Event), btif_me_get_callback_event_role_change_new_role(Event), btif_me_get_activeCons()); break; case BTIF_BTEVENT_MODE_CHANGE: TRACE(4,"[BTEVENT] MODE_CHANGE evt:%d errCode:0x%0x curMode=0x%0x, interval=%d ",btif_me_get_callback_event_type(Event), btif_me_get_callback_event_err_code(Event), btif_me_get_callback_event_mode_change_curMode(Event), btif_me_get_callback_event_mode_change_interval(Event)); DUMP8("%02x ", btif_me_get_callback_event_rem_dev_bd_addr(Event), BTIF_BD_ADDR_SIZE); break; case BTIF_BTEVENT_ACCESSIBLE_CHANGE: TRACE(3,"[BTEVENT] ACCESSIBLE_CHANGE evt:%d errCode:0x%0x aMode=0x%0x", btif_me_get_callback_event_type(Event), btif_me_get_callback_event_err_code(Event), btif_me_get_callback_event_a_mode(Event)); #if !defined(IBRT) if (app_is_access_mode_set_pending()) { app_set_pending_access_mode(); } else { if (BTIF_BEC_NO_ERROR != btif_me_get_callback_event_err_code(Event)) { app_retry_setting_access_mode(); } } #endif break; case BTIF_BTEVENT_LINK_POLICY_CHANGED: { BT_SET_LINKPOLICY_REQ_T* pReq = app_bt_pop_pending_set_linkpolicy(); if (NULL != pReq) { app_bt_Me_SetLinkPolicy(pReq->remDev, pReq->policy); } break; } case BTIF_BTEVENT_DEFAULT_LINK_POLICY_CHANGED: { TRACE(0,"[BTEVENT] DEFAULT_LINK_POLICY_CHANGED-->BT_STACK_INITIALIZED"); app_notify_stack_ready(STACK_READY_BT); break; } case BTIF_BTEVENT_NAME_RESULT: { uint8_t* ptrName; uint8_t nameLen; nameLen = btif_me_get_callback_event_remote_dev_name(Event, &ptrName); TRACE(1,"[BTEVENT] NAME_RESULT name len %d", nameLen); if (nameLen > 0) { TRACE(1,"remote dev name: %s", ptrName); } //return; } default: break; } #ifdef MULTIPOINT_DUAL_SLAVE app_bt_role_manager_process_dual_slave(Event); #else app_bt_role_manager_process(Event); #endif app_bt_accessible_manager_process(Event); #if !defined(IBRT) app_bt_sniff_manager_process(Event); #endif app_bt_global_handle_hook(Event); #if defined(IBRT) app_tws_ibrt_global_callback(Event); #endif } #include "app_bt_media_manager.h" osTimerId bt_sco_recov_timer = NULL; static void bt_sco_recov_timer_handler(void const *param); osTimerDef (BT_SCO_RECOV_TIMER, (void (*)(void const *))bt_sco_recov_timer_handler); // define timers void hfp_reconnect_sco(uint8_t flag); static void bt_sco_recov_timer_handler(void const *param) { TRACE(1,"%s",__func__); hfp_reconnect_sco(0); } static void bt_sco_recov_timer_start() { osTimerStop(bt_sco_recov_timer); osTimerStart(bt_sco_recov_timer, 2500); } enum { SCO_DISCONNECT_RECONN_START, SCO_DISCONNECT_RECONN_RUN, SCO_DISCONNECT_RECONN_NONE, }; static uint8_t sco_reconnect_status = SCO_DISCONNECT_RECONN_NONE; void hfp_reconnect_sco(uint8_t set) { TRACE(3,"%s cur_chl_id=%d reconnect_status =%d",__func__,app_bt_device.curr_hf_channel_id, sco_reconnect_status); if(set == 1) { sco_reconnect_status = SCO_DISCONNECT_RECONN_START; } if(sco_reconnect_status == SCO_DISCONNECT_RECONN_START) { app_audio_manager_sendrequest(APP_BT_STREAM_MANAGER_STOP,BT_STREAM_VOICE, app_bt_device.curr_hf_channel_id,MAX_RECORD_NUM); app_bt_HF_DisconnectAudioLink(app_bt_device.hf_channel[app_bt_device.curr_hf_channel_id]); sco_reconnect_status = SCO_DISCONNECT_RECONN_RUN; bt_sco_recov_timer_start(); } else if(sco_reconnect_status == SCO_DISCONNECT_RECONN_RUN) { app_bt_HF_CreateAudioLink(app_bt_device.hf_channel[app_bt_device.curr_hf_channel_id]); sco_reconnect_status = SCO_DISCONNECT_RECONN_NONE; } } void app_bt_global_handle_init(void) { btif_event_mask_t mask = BTIF_BEM_NO_EVENTS; btif_me_init_handler(&app_bt_handler); app_bt_handler.callback = app_bt_global_handle; btif_me_register_global_handler(&app_bt_handler); #if defined(IBRT) btif_me_register_accept_handler(&app_bt_handler); #endif #ifdef IBRT_SEARCH_UI app_bt_global_handle_hook_set(APP_BT_GOLBAL_HANDLE_HOOK_USER_0,app_bt_manager_ibrt_role_process); #endif mask |= BTIF_BEM_ROLE_CHANGE | BTIF_BEM_SCO_CONNECT_CNF | BTIF_BEM_SCO_DISCONNECT | BTIF_BEM_SCO_CONNECT_IND; mask |= BTIF_BEM_AUTHENTICATED; mask |= BTIF_BEM_LINK_CONNECT_IND; mask |= BTIF_BEM_LINK_DISCONNECT; mask |= BTIF_BEM_LINK_CONNECT_CNF; mask |= BTIF_BEM_ACCESSIBLE_CHANGE; mask |= BTIF_BEM_ENCRYPTION_CHANGE; mask |= BTIF_BEM_SIMPLE_PAIRING_COMPLETE; #if (defined(__BT_ONE_BRING_TWO__)||defined(IBRT)) mask |= BTIF_BEM_MODE_CHANGE; #endif mask |= BTIF_BEM_LINK_POLICY_CHANGED; app_bt_ME_SetConnectionRole(BTIF_BCR_ANY); for (uint8_t i=0; ia2dp_stream, FALSE); #if defined(A2DP_LHDC_ON) app_bt_A2DP_SetMasterRole(app_bt_device.a2dp_lhdc_stream[i]->a2dp_stream, FALSE); #endif #if defined(A2DP_AAC_ON) app_bt_A2DP_SetMasterRole(app_bt_device.a2dp_aac_stream[i]->a2dp_stream, FALSE); #endif #if defined(A2DP_SCALABLE_ON) app_bt_A2DP_SetMasterRole(app_bt_device.a2dp_scalable_stream[i]->a2dp_stream, FALSE); #endif #if defined(A2DP_LDAC_ON) app_bt_A2DP_SetMasterRole(app_bt_device.a2dp_ldac_stream[i]->a2dp_stream, FALSE); #endif app_bt_HF_SetMasterRole(app_bt_device.hf_channel[i], FALSE); #if defined (__HSP_ENABLE__) HS_SetMasterRole(&app_bt_device.hs_channel[i], FALSE); #endif } btif_me_set_event_mask(&app_bt_handler, mask); app_bt_sniff_manager_init(); app_bt_accessmode_timer = osTimerCreate (osTimer(APP_BT_ACCESSMODE_TIMER), osTimerOnce, &app_bt_accessmode_timer_argument); bt_sco_recov_timer = osTimerCreate (osTimer(BT_SCO_RECOV_TIMER), osTimerOnce, NULL); } void app_bt_send_request(uint32_t message_id, uint32_t param0, uint32_t param1, uint32_t ptr) { APP_MESSAGE_BLOCK msg; msg.mod_id = APP_MODUAL_BT; msg.msg_body.message_id = message_id; msg.msg_body.message_Param0 = param0; msg.msg_body.message_Param1 = param1; msg.msg_body.message_ptr = ptr; app_mailbox_put(&msg); } extern void app_start_10_second_timer(uint8_t timer_id); static int app_bt_handle_process(APP_MESSAGE_BODY *msg_body) { btif_accessible_mode_t old_access_mode; switch (msg_body->message_id) { case APP_BT_REQ_ACCESS_MODE_SET: old_access_mode = g_bt_access_mode; app_bt_accessmode_set(msg_body->message_Param0); if (msg_body->message_Param0 == BTIF_BAM_GENERAL_ACCESSIBLE && old_access_mode != BTIF_BAM_GENERAL_ACCESSIBLE) { #ifndef FPGA //app_status_indication_set(APP_STATUS_INDICATION_BOTHSCAN); #ifdef MEDIA_PLAYER_SUPPORT app_voice_report(APP_STATUS_INDICATION_BOTHSCAN, 0); #endif app_start_10_second_timer(APP_PAIR_TIMER_ID); #endif } else { #ifndef FPGA //app_status_indication_set(APP_STATUS_INDICATION_PAGESCAN); #endif } break; default: break; } return 0; } void *app_bt_profile_active_store_ptr_get(uint8_t *bdAddr) { static btdevice_profile device_profile = {true, false, true,0}; btdevice_profile *ptr; #ifndef FPGA nvrec_btdevicerecord *record = NULL; if (!nv_record_btdevicerecord_find((bt_bdaddr_t *)bdAddr,&record)) { uint32_t lock = nv_record_pre_write_operation(); ptr = &(record->device_plf); DUMP8("0x%02x ", bdAddr, BTIF_BD_ADDR_SIZE); TRACE(5,"%s hfp_act:%d hsp_act:%d a2dp_act:0x%x codec_type=%x", __func__, ptr->hfp_act, ptr->hsp_act, ptr->a2dp_act,ptr->a2dp_codectype); /* always need connect a2dp and hfp */ ptr->hfp_act = true; ptr->a2dp_act = true; nv_record_post_write_operation(lock); } else #endif { ptr = &device_profile; TRACE(1,"%s default", __func__); } return (void *)ptr; } static void app_bt_profile_reconnect_timehandler(void const *param); extern void startonce_delay_event_Timer_(int ms); osTimerDef (BT_PROFILE_CONNECT_TIMER0, app_bt_profile_reconnect_timehandler); // define timers #ifdef __BT_ONE_BRING_TWO__ osTimerDef (BT_PROFILE_CONNECT_TIMER1, app_bt_profile_reconnect_timehandler); #endif #ifdef __AUTO_CONNECT_OTHER_PROFILE__ static void app_bt_profile_connect_hf_retry_handler(void) { struct app_bt_profile_manager *bt_profile_manager_p = (struct app_bt_profile_manager *)param; if (MEC(pendCons) > 0) { TRACE(1,"Former link is not down yet, reset the timer %s.", __FUNCTION__); osTimerStart(bt_profile_manager_p->connect_timer, APP_BT_PROFILE_RECONNECT_RETRY_INTERVAL_MS); } else { app_bt_precheck_before_starting_connecting(bt_profile_manager_p->has_connected); if (bt_profile_manager_p->hfp_connect != bt_profile_connect_status_success) { app_bt_HF_CreateServiceLink(bt_profile_manager_p->chan, &bt_profile_manager_p->rmt_addr); } } } static void app_bt_profile_connect_hf_retry_timehandler(void const *param) { app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)app_bt_profile_connect_hf_retry_handler); } #if defined (__HSP_ENABLE__) static void app_bt_profile_connect_hs_retry_timehandler(void const *param) { struct app_bt_profile_manager *bt_profile_manager_p = (struct app_bt_profile_manager *)param; if (MEC(pendCons) > 0) { if (bt_profile_manager_p->reconnect_cnt < APP_BT_PROFILE_OPENNING_RECONNECT_RETRY_LIMIT_CNT) { bt_profile_manager_p->reconnect_cnt++; } TRACE(1,"Former link is not down yet, reset the timer %s.", __FUNCTION__); osTimerStart(bt_profile_manager_p->connect_timer, BTIF_BT_DEFAULT_PAGE_TIMEOUT_IN_MS+APP_BT_PROFILE_RECONNECT_RETRY_INTERVAL_MS); } else { if (bt_profile_manager_p->hsp_connect != bt_profile_connect_status_success) { app_bt_HS_CreateServiceLink(bt_profile_manager_p->hs_chan, &bt_profile_manager_p->rmt_addr); } } } #endif static bool app_bt_profile_manager_connect_a2dp_filter_connected_a2dp_stream(BT_BD_ADDR bd_addr) { uint8_t i =0; BtRemoteDevice *StrmRemDev; A2dpStream * connected_stream; for(i =0; ibdAddr.addr,bd_addr.addr,BD_ADDR_SIZE) == 0) { return true; } } } return false; } static void app_bt_profile_connect_a2dp_retry_handler(void) { struct app_bt_profile_manager *bt_profile_manager_p = (struct app_bt_profile_manager *)param; TRACE(1,"%s reconnect_cnt = %d",__func__,bt_profile_manager_p->reconnect_cnt); if (MEC(pendCons) > 0) { if (bt_profile_manager_p->reconnect_cnt < APP_BT_PROFILE_OPENNING_RECONNECT_RETRY_LIMIT_CNT) { bt_profile_manager_p->reconnect_cnt++; } TRACE(1,"Former link is not down yet, reset the timer %s.", __FUNCTION__); osTimerStart(bt_profile_manager_p->connect_timer, BTIF_BT_DEFAULT_PAGE_TIMEOUT_IN_MS+APP_BT_PROFILE_RECONNECT_RETRY_INTERVAL_MS); } else { if(app_bt_profile_manager_connect_a2dp_filter_connected_a2dp_stream(bt_profile_manager_p->rmt_addr) == true) { TRACE(0,"has been connected , no need to init connect again"); return ; } app_bt_precheck_before_starting_connecting(bt_profile_manager_p->has_connected); if (bt_profile_manager_p->a2dp_connect != bt_profile_connect_status_success) { app_bt_A2DP_OpenStream(bt_profile_manager_p->stream, &bt_profile_manager_p->rmt_addr); } } } static void app_bt_profile_connect_a2dp_retry_timehandler(void const *param) { app_bt_start_custom_function_in_bt_thread(0, 0, (uint32_t)app_bt_profile_connect_a2dp_retry_handler); } #endif void app_bt_reset_reconnect_timer(bt_bdaddr_t *pBdAddr) { uint8_t devId = 0; for (uint8_t i = 0; i < BT_DEVICE_NUM; i++) { if (pBdAddr == &(bt_profile_manager[i].rmt_addr)) { devId = i; break; } } TRACE(1,"Resart the reconnecting timer of dev %d", devId); osTimerStart(bt_profile_manager[devId].connect_timer, BTIF_BT_DEFAULT_PAGE_TIMEOUT_IN_MS+APP_BT_PROFILE_RECONNECT_RETRY_INTERVAL_MS); } static void app_bt_profile_reconnect_handler(void const *param) { #if !defined(IBRT) struct app_bt_profile_manager *bt_profile_manager_p = (struct app_bt_profile_manager *)param; TRACE(1,"%s reconnect_cnt = %d",__FUNCTION__,bt_profile_manager_p->reconnect_cnt); if ( btif_me_get_pendCons() > 0) { if (bt_profile_manager_p->reconnect_cnt < APP_BT_PROFILE_OPENNING_RECONNECT_RETRY_LIMIT_CNT) { bt_profile_manager_p->reconnect_cnt++; } TRACE(1,"Former link is not down yet, reset the timer %s.", __FUNCTION__); osTimerStart(bt_profile_manager_p->connect_timer, BTIF_BT_DEFAULT_PAGE_TIMEOUT_IN_MS+APP_BT_PROFILE_RECONNECT_RETRY_INTERVAL_MS); } else { btdevice_profile *btdevice_plf_p = (btdevice_profile *)app_bt_profile_active_store_ptr_get(bt_profile_manager_p->rmt_addr.address); #ifdef __BT_ONE_BRING_TWO__ if(a2dp_is_music_ongoing()&&(bt_profile_manager_p->has_connected == false)) { bt_drv_reg_op_set_reconnecting_flag(); a2dp_update_music_link(); } #endif if (bt_profile_manager_p->connect_timer_cb) { bt_profile_manager_p->connect_timer_cb(param); bt_profile_manager_p->connect_timer_cb = NULL; } else { if ((btdevice_plf_p->hfp_act) &&(bt_profile_manager_p->hfp_connect != bt_profile_connect_status_success)) { TRACE(0,"try connect hf"); app_bt_precheck_before_starting_connecting(bt_profile_manager_p->has_connected); app_bt_HF_CreateServiceLink(bt_profile_manager_p->chan, (bt_bdaddr_t *)&bt_profile_manager_p->rmt_addr); } #if defined (__HSP_ENABLE__) else if(btdevice_plf_p->hsp_act) &&(bt_profile_manager_p->hsp_connect != bt_profile_connect_status_success)) { TRACE(0,"try connect hs"); app_bt_precheck_before_starting_connecting(bt_profile_manager_p->has_connected); app_bt_HS_CreateServiceLink(bt_profile_manager_p->hs_chan, &bt_profile_manager_p->rmt_addr); } #endif else if((btdevice_plf_p->a2dp_act) &&(bt_profile_manager_p->a2dp_connect != bt_profile_connect_status_success)) { TRACE(0,"try connect a2dp"); app_bt_precheck_before_starting_connecting(bt_profile_manager_p->has_connected); app_bt_A2DP_OpenStream(bt_profile_manager_p->stream, &bt_profile_manager_p->rmt_addr); } } } #else TRACE(0,"ibrt_ui_log:app_bt_profile_reconnect_timehandler called"); #endif } static void app_bt_profile_reconnect_timehandler(void const *param) { app_bt_start_custom_function_in_bt_thread((uint32_t)param, 0, (uint32_t)app_bt_profile_reconnect_handler); } bool app_bt_is_in_connecting_profiles_state(void) { for (uint8_t devId = 0; devId < BT_DEVICE_NUM; devId++) { if (APP_BT_IN_CONNECTING_PROFILES_STATE == bt_profile_manager[devId].connectingState) { return true; } } return false; } void app_bt_clear_connecting_profiles_state(uint8_t devId) { TRACE(1,"Dev %d exists connecting profiles state", devId); bt_profile_manager[devId].connectingState = APP_BT_IDLE_STATE; if (!app_bt_is_in_connecting_profiles_state()) { #ifdef __IAG_BLE_INCLUDE__ app_start_fast_connectable_ble_adv(BLE_FAST_ADVERTISING_INTERVAL); #endif } } void app_bt_set_connecting_profiles_state(uint8_t devId) { TRACE(1,"Dev %d enters connecting profiles state", devId); bt_profile_manager[devId].connectingState = APP_BT_IN_CONNECTING_PROFILES_STATE; } void app_bt_profile_connect_manager_open(void) { uint8_t i=0; for (i=0; ihfp_act)&&!(btdevice_plf_p->a2dp_act)) { nv_record_ddbrec_delete((bt_bdaddr_t *)&record1.bdAddr); find_invalid_record_cnt++; } } else if(ret == 2) { btdevice_plf_p = (btdevice_profile *)app_bt_profile_active_store_ptr_get(record1.bdAddr.address); if (!(btdevice_plf_p->hfp_act)&&!(btdevice_plf_p->a2dp_act)) { nv_record_ddbrec_delete((bt_bdaddr_t *)&record1.bdAddr); find_invalid_record_cnt++; } btdevice_plf_p = (btdevice_profile *)app_bt_profile_active_store_ptr_get(record2.bdAddr.address); if (!(btdevice_plf_p->hfp_act)&&!(btdevice_plf_p->a2dp_act)) { nv_record_ddbrec_delete((bt_bdaddr_t *)&record2.bdAddr); find_invalid_record_cnt++; } } } while(find_invalid_record_cnt); TRACE(0,"!!!app_bt_opening_reconnect:\n"); DUMP8("%02x ", &record1.bdAddr, 6); DUMP8("%02x ", &record2.bdAddr, 6); if(ret > 0) { TRACE(0,"!!!start reconnect first device\n"); if( btif_me_get_pendCons() == 0) { bt_profile_manager[BT_DEVICE_ID_1].reconnect_mode = bt_profile_reconnect_openreconnecting; bt_profile_manager[BT_DEVICE_ID_1].reconnect_cnt = 0; memcpy(bt_profile_manager[BT_DEVICE_ID_1].rmt_addr.address, record1.bdAddr.address, BTIF_BD_ADDR_SIZE); btdevice_plf_p = (btdevice_profile *)app_bt_profile_active_store_ptr_get(bt_profile_manager[BT_DEVICE_ID_1].rmt_addr.address); #if defined(A2DP_LHDC_ON) if(btdevice_plf_p->a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_1]->a2dp_stream; else #endif #if defined(A2DP_AAC_ON) if(btdevice_plf_p->a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC) bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream; else #endif #if defined(A2DP_LDAC_ON) //workaround for mate10 no a2dp issue when link back if(btdevice_plf_p->a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { //bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream; //btdevice_plf_p->a2dp_codectype = BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC; bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_ldac_stream[BT_DEVICE_ID_1]->a2dp_stream; btdevice_plf_p->a2dp_codectype = BTIF_AVDTP_CODEC_TYPE_NON_A2DP; } else #endif #if defined(A2DP_SCALABLE_ON) if(btdevice_plf_p->a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_1]->a2dp_stream; else #endif { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream; } btif_a2dp_reset_stream_state(bt_profile_manager[BT_DEVICE_ID_1].stream); bt_profile_manager[BT_DEVICE_ID_1].chan = app_bt_device.hf_channel[BT_DEVICE_ID_1]; #if defined (__HSP_ENABLE__) bt_profile_manager[BT_DEVICE_ID_1].hs_chan = &app_bt_device.hs_channel[BT_DEVICE_ID_1]; #endif if (btdevice_plf_p->hfp_act) { TRACE(0,"try connect hf"); app_bt_precheck_before_starting_connecting(bt_profile_manager[BT_DEVICE_ID_1].has_connected); app_bt_HF_CreateServiceLink(bt_profile_manager[BT_DEVICE_ID_1].chan, (bt_bdaddr_t *)&bt_profile_manager[BT_DEVICE_ID_1].rmt_addr); } else if(btdevice_plf_p->a2dp_act) { TRACE(0,"try connect a2dp"); app_bt_precheck_before_starting_connecting(bt_profile_manager[BT_DEVICE_ID_1].has_connected); app_bt_A2DP_OpenStream(bt_profile_manager[BT_DEVICE_ID_1].stream, &bt_profile_manager[BT_DEVICE_ID_1].rmt_addr); } #if defined (__HSP_ENABLE__) else if (btdevice_plf_p->hsp_act) { TRACE(0,"try connect hs"); app_bt_precheck_before_starting_connecting(bt_profile_manager[BT_DEVICE_ID_1].has_connected); app_bt_HS_CreateServiceLink(bt_profile_manager[BT_DEVICE_ID_1].hs_chan, &bt_profile_manager[BT_DEVICE_ID_1].rmt_addr); } #endif } #ifdef __BT_ONE_BRING_TWO__ if(ret > 1) { TRACE(0,"!!!need reconnect second device\n"); bt_profile_manager[BT_DEVICE_ID_2].reconnect_mode = bt_profile_reconnect_openreconnecting; bt_profile_manager[BT_DEVICE_ID_2].reconnect_cnt = 0; memcpy(bt_profile_manager[BT_DEVICE_ID_2].rmt_addr.address, record2.bdAddr.address, BTIF_BD_ADDR_SIZE); btdevice_plf_p = (btdevice_profile *)app_bt_profile_active_store_ptr_get(bt_profile_manager[BT_DEVICE_ID_2].rmt_addr.address); #if defined(A2DP_LHDC_ON) if(btdevice_plf_p->a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) bt_profile_manager[BT_DEVICE_ID_2].stream = app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_2]->a2dp_stream; else #endif #if defined(A2DP_AAC_ON) if(btdevice_plf_p->a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC) bt_profile_manager[BT_DEVICE_ID_2].stream = app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_2]->a2dp_stream; else #endif #if defined(A2DP_SCALABLE_ON) if(btdevice_plf_p->a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) bt_profile_manager[BT_DEVICE_ID_2].stream = app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_2]->a2dp_stream; else #endif { bt_profile_manager[BT_DEVICE_ID_2].stream = app_bt_device.a2dp_stream[BT_DEVICE_ID_2]->a2dp_stream; } btif_a2dp_reset_stream_state(bt_profile_manager[BT_DEVICE_ID_2].stream); bt_profile_manager[BT_DEVICE_ID_2].chan = app_bt_device.hf_channel[BT_DEVICE_ID_2]; #if defined (__HSP_ENABLE__) bt_profile_manager[BT_DEVICE_ID_2].hs_chan = &app_bt_device.hs_channel[BT_DEVICE_ID_2]; #endif } #endif } else { TRACE(0,"!!!go to pairing\n"); #ifdef __EARPHONE_STAY_BOTH_SCAN__ app_bt_accessmode_set_req(BTIF_BT_DEFAULT_ACCESS_MODE_PAIR); #else app_bt_accessmode_set_req(BTIF_BAM_CONNECTABLE_ONLY); #endif } osapi_unlock_stack(); } void app_bt_resume_sniff_mode(uint8_t deviceId) { if (bt_profile_connect_status_success == bt_profile_manager[deviceId].a2dp_connect|| bt_profile_connect_status_success == bt_profile_manager[deviceId].hfp_connect|| bt_profile_connect_status_success == bt_profile_manager[deviceId].hsp_connect) { app_bt_allow_sniff(deviceId); btif_remote_device_t* currentRemDev = app_bt_get_remoteDev(deviceId); app_bt_sniff_config(currentRemDev); } } #if !defined(IBRT) static int8_t app_bt_profile_reconnect_pending(enum BT_DEVICE_ID_T id) { if(btapp_hfp_is_dev_call_active(id) == true) { bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_reconnect_pending; return 0; } return -1; } #endif static int8_t app_bt_profile_reconnect_pending_process(void) { uint8_t i =BT_DEVICE_NUM; btif_remote_device_t *remDev = NULL; btif_cmgr_handler_t *cmgrHandler; for (i=0; ip.remDev->bdAddr.address); osTimerStop(bt_profile_manager[id].connect_timer); bt_profile_manager[id].connect_timer_cb = NULL; bool profile_reconnect_enable = false; if (Chan&&Info) { switch(Info->event) { case HF_EVENT_SERVICE_CONNECTED: TRACE(1,"%s HS_EVENT_SERVICE_CONNECTED",__func__); nv_record_btdevicerecord_set_hsp_profile_active_state(btdevice_plf_p, true); #ifndef FPGA nv_record_touch_cause_flush(); #endif bt_profile_manager[id].hsp_connect = bt_profile_connect_status_success; bt_profile_manager[id].reconnect_cnt = 0; bt_profile_manager[id].hs_chan = &app_bt_device.hs_channel[id]; memcpy(bt_profile_manager[id].rmt_addr.address, Info->p.remDev->bdAddr.address, BTIF_BD_ADDR_SIZE); if (false == bt_profile_manager[id].has_connected) { app_bt_resume_sniff_mode(id); } if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) { //do nothing } else if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_reconnecting) { if (btdevice_plf_p->a2dp_act && bt_profile_manager[id].a2dp_connect != bt_profile_connect_status_success) { TRACE(0,"!!!continue connect a2dp\n"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_A2DP_OpenStream(bt_profile_manager[id].stream, &bt_profile_manager[id].rmt_address); } } #ifdef __AUTO_CONNECT_OTHER_PROFILE__ else { if (btdevice_plf_p->a2dp_act && bt_profile_manager[id].a2dp_connect != bt_profile_connect_status_success) { bt_profile_manager[id].connect_timer_cb = app_bt_profile_connect_a2dp_retry_timehandler; app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); osTimerStart(bt_profile_manager[id].connect_timer, APP_BT_PROFILE_CONNECT_RETRY_MS); } } #endif break; case HF_EVENT_SERVICE_DISCONNECTED: TRACE(2,"%s HS_EVENT_SERVICE_DISCONNECTED discReason:%d",__func__, Info->p.remDev->discReason); bt_profile_manager[id].hsp_connect = bt_profile_connect_status_failure; if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) { if (++bt_profile_manager[id].reconnect_cnt < APP_BT_PROFILE_OPENNING_RECONNECT_RETRY_LIMIT_CNT) { app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); profile_reconnect_enable = true; bt_profile_manager[id].hfp_connect = bt_profile_connect_status_unknow; } } else if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_reconnecting) { if (++bt_profile_manager[id].reconnect_cnt < APP_BT_PROFILE_RECONNECT_RETRY_LIMIT_CNT) { app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); profile_reconnect_enable = true } else { app_bt_restore_reconnecting_idle_mode(id); //bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_null; } TRACE(2,"%s try to reconnect cnt:%d",__func__, bt_profile_manager[id].reconnect_cnt); #if !defined(IBRT) } else if(Info->p.remDev->discReason == 0x8) { bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_reconnecting; app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); TRACE(1,"%s try to reconnect",__func__); if(app_bt_profile_reconnect_pending(id) != 0) { profile_reconnect_enable = true; } #endif } else { bt_profile_manager[id].hsp_connect = bt_profile_connect_status_unknow; } if (profile_reconnect_enable) { #ifdef __IAG_BLE_INCLUDE__ app_ble_refresh_adv_state(BLE_ADVERTISING_INTERVAL); #endif osTimerStart(bt_profile_manager[id].connect_timer, APP_BT_PROFILE_RECONNECT_RETRY_INTERVAL_MS); } break; default: break; } } if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_reconnecting) { bool reconnect_hsp_proc_final = true; bool reconnect_a2dp_proc_final = true; if (bt_profile_manager[id].hsp_connect == bt_profile_connect_status_failure) { reconnect_hsp_proc_final = false; } if (bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_failure) { reconnect_a2dp_proc_final = false; } if (reconnect_hsp_proc_final && reconnect_a2dp_proc_final) { TRACE(3,"!!!reconnect success %d/%d/%d\n", bt_profile_manager[id].hfp_connect, bt_profile_manager[id].hsp_connect, bt_profile_manager[id].a2dp_connect); app_bt_restore_reconnecting_idle_mode(id); // bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_null; } } else if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) { bool opening_hsp_proc_final = false; bool opening_a2dp_proc_final = false; if (btdevice_plf_p->hsp_act && bt_profile_manager[id].hsp_connect == bt_profile_connect_status_unknow) { opening_hsp_proc_final = false; } else { opening_hsp_proc_final = true; } if (btdevice_plf_p->a2dp_act && bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_unknow) { opening_a2dp_proc_final = false; } else { opening_a2dp_proc_final = true; } if ((opening_hsp_proc_final && opening_a2dp_proc_final) || (bt_profile_manager[id].hsp_connect == bt_profile_connect_status_failure)) { TRACE(3,"!!!reconnect success %d/%d/%d\n", bt_profile_manager[id].hfp_connect, bt_profile_manager[id].hsp_connect, bt_profile_manager[id].a2dp_connect); app_bt_restore_reconnecting_idle_mode(id); // bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_null; } if (btdevice_plf_p->hsp_act && bt_profile_manager[id].hsp_connect == bt_profile_connect_status_success) { if (btdevice_plf_p->a2dp_act && !opening_a2dp_proc_final) { TRACE(0,"!!!continue connect a2dp\n"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_A2DP_OpenStream(bt_profile_manager[id].stream, &bt_profile_manager[id].rmt_addr); } } if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_null) { for (uint8_t i=0; istart reconnect second device\n"); if ((btdevice_plf_p->hfp_act)&&(!bt_profile_manager[i].hfp_connect)) { TRACE(0,"try connect hf"); app_bt_precheck_before_starting_connecting(bt_profile_manager[i].has_connected); app_bt_HF_CreateServiceLink(bt_profile_manager[i].chan, &bt_profile_manager[i].rmt_addr); } else if ((btdevice_plf_p->hsp_act)&&(!bt_profile_manager[i].hsp_connect)) { TRACE(0,"try connect hs"); app_bt_precheck_before_starting_connecting(bt_profile_manager[i].has_connected); app_bt_HS_CreateServiceLink(bt_profile_manager[i].hs_chan, &bt_profile_manager[i].rmt_addr); } else if((btdevice_plf_p->a2dp_act)&&(!bt_profile_manager[i].a2dp_connect)) { TRACE(0,"try connect a2dp"); app_bt_precheck_before_starting_connecting(bt_profile_manager[i].has_connected); app_bt_A2DP_OpenStream(bt_profile_manager[i].stream, &bt_profile_manager[i].rmt_addr); } break; } } } } #ifdef __IAG_BLE_INCLUDE__ if (bt_profile_manager[id].hfp_connect == bt_profile_connect_status_success && bt_profile_manager[id].hsp_connect == bt_profile_connect_status_success&& bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_success) { app_ble_force_switch_adv(BLE_SWITCH_USER_BT_CONNECT, true); } #endif if (!bt_profile_manager[id].has_connected && (bt_profile_manager[id].hfp_connect == bt_profile_connect_status_success || bt_profile_manager[id].hsp_connect == bt_profile_connect_status_success|| bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_success)) { bt_profile_manager[id].has_connected = true; TRACE(0,"BT connected!!!"); #ifndef IBRT btif_me_get_remote_device_name(&(ctx->remote_dev_bdaddr), app_bt_global_handle); #endif #if defined(MEDIA_PLAYER_SUPPORT)&& !defined(IBRT) app_voice_report(APP_STATUS_INDICATION_CONNECTED, id); #endif #ifdef __INTERCONNECTION__ app_interconnection_start_disappear_adv(INTERCONNECTION_BLE_ADVERTISING_INTERVAL, APP_INTERCONNECTION_DISAPPEAR_ADV_IN_MS); if (btif_me_get_activeCons() <= 2) { app_interconnection_spp_open(btif_me_enumerate_remote_devices(id)); } #endif #ifdef __INTERACTION__ // app_interaction_spp_open(); #endif } if (bt_profile_manager[id].has_connected && (bt_profile_manager[id].hfp_connect != bt_profile_connect_status_success && bt_profile_manager[id].hsp_connect != bt_profile_connect_status_success && bt_profile_manager[id].a2dp_connect != bt_profile_connect_status_success)) { bt_profile_manager[id].has_connected = false; TRACE(0,"BT disconnected!!!"); #ifdef GFPS_ENABLED if (app_gfps_is_last_response_pending()) { app_gfps_enter_connectable_mode_req_handler(app_gfps_get_last_response()); } #endif #if defined(MEDIA_PLAYER_SUPPORT)&& !defined(IBRT) app_voice_report(APP_STATUS_INDICATION_DISCONNECTED, id); #endif #ifdef __INTERCONNECTION__ app_interconnection_disconnected_callback(); #endif app_set_disconnecting_all_bt_connections(false); } #ifdef __BT_ONE_BRING_TWO__ app_bt_update_connectable_mode_after_connection_management(); #endif } #endif void hfp_reconnecting_timer_stop_callback(const btif_event_t *event) { uint8_t i =0; uint8_t id =BT_DEVICE_NUM; bt_bdaddr_t *remote = NULL; bt_bdaddr_t *hfp_remote = NULL; remote = btif_me_get_callback_event_rem_dev_bd_addr(event); if(remote != NULL){ for(i = 0; ip.remDev->bdAddr.address); btdevice_profile *btdevice_plf_p = (btdevice_profile *)app_bt_profile_active_store_ptr_get((uint8_t *)ctx->remote_dev_bdaddr.address); bool profile_reconnect_enable = false; osTimerStop(bt_profile_manager[id].connect_timer); bt_profile_manager[id].connect_timer_cb = NULL; //if (Chan&&Info){ if (Chan) { switch(ctx->event) { case BTIF_HF_EVENT_SERVICE_CONNECTED: TRACE(1,"%s HF_EVENT_SERVICE_CONNECTED",__func__); nv_record_btdevicerecord_set_hfp_profile_active_state(btdevice_plf_p, true); #ifndef FPGA nv_record_touch_cause_flush(); #endif bt_profile_manager[id].hfp_connect = bt_profile_connect_status_success; bt_profile_manager[id].saved_reconnect_mode =bt_profile_reconnect_null; bt_profile_manager[id].reconnect_cnt = 0; bt_profile_manager[id].chan = app_bt_device.hf_channel[id]; memcpy(bt_profile_manager[id].rmt_addr.address, ctx->remote_dev_bdaddr.address, BTIF_BD_ADDR_SIZE); if (false == bt_profile_manager[id].has_connected) { app_bt_resume_sniff_mode(id); } #ifdef BTIF_DIP_DEVICE btif_dip_get_remote_info(app_bt_get_remoteDev(id)); #endif if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) { //do nothing } #if defined(IBRT) else if (app_bt_ibrt_reconnect_mobile_profile_flag_get()) { app_bt_ibrt_reconnect_mobile_profile_flag_clear(); #else else if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_reconnecting) { #endif TRACE(2,"app_bt: a2dp_act in NV =%d,a2dp_connect=%d",btdevice_plf_p->a2dp_act,bt_profile_manager[id].a2dp_connect); if (btdevice_plf_p->a2dp_act && bt_profile_manager[id].a2dp_connect != bt_profile_connect_status_success) { TRACE(0,"!!!continue connect a2dp\n"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_A2DP_OpenStream(bt_profile_manager[id].stream, &bt_profile_manager[id].rmt_addr); } } #ifdef __AUTO_CONNECT_OTHER_PROFILE__ else { //befor auto connect a2dp profile, check whether a2dp is supported if (btdevice_plf_p->a2dp_act && bt_profile_manager[id].a2dp_connect != bt_profile_connect_status_success) { bt_profile_manager[id].connect_timer_cb = app_bt_profile_connect_a2dp_retry_timehandler; app_bt_accessmode_set(BAM_CONNECTABLE_ONLY); osTimerStart(bt_profile_manager[id].connect_timer, APP_BT_PROFILE_CONNECT_RETRY_MS); } } #endif break; case BTIF_HF_EVENT_SERVICE_DISCONNECTED: if(((ctx->disc_reason == 0)||(ctx->disc_reason == 19))&&(p_ibrt_ctrl->current_role != IBRT_SLAVE)) { once_event_case = 2; startonce_delay_event_Timer_(1000); } //TRACE(3,"%s HF_EVENT_SERVICE_DISCONNECTED discReason:%d/%d",__func__, Info->p.remDev->discReason, Info->p.remDev->discReason_saved); TRACE(3,"%s HF_EVENT_SERVICE_DISCONNECTED discReason:%d/%d",__func__, ctx->disc_reason, ctx->disc_reason_saved); bt_profile_manager[id].hfp_connect = bt_profile_connect_status_failure; if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) { if (++bt_profile_manager[id].reconnect_cnt < APP_BT_PROFILE_OPENNING_RECONNECT_RETRY_LIMIT_CNT) { app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); profile_reconnect_enable = true; bt_profile_manager[id].hfp_connect = bt_profile_connect_status_unknow; } } else if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_reconnecting) { if (++bt_profile_manager[id].reconnect_cnt < APP_BT_PROFILE_RECONNECT_RETRY_LIMIT_CNT) { app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); profile_reconnect_enable = true; } else { app_bt_restore_reconnecting_idle_mode(id); // bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_null; } TRACE(2,"%s try to reconnect cnt:%d",__func__, bt_profile_manager[id].reconnect_cnt); /* }else if ((Info->p.remDev->discReason == 0x8)|| (Info->p.remDev->discReason_saved == 0x8)){ */ } #if !defined(IBRT) #if defined(ENHANCED_STACK) else if ((ctx->disc_reason == 0x8)|| (ctx->disc_reason_saved == 0x8) || (ctx->disc_reason == 0x4)|| (ctx->disc_reason_saved == 0x4)) #else else if ((ctx->disc_reason == 0x8)|| (ctx->disc_reason_saved == 0x8) || (ctx->disc_reason == 0x0)|| (ctx->disc_reason_saved == 0x0)) #endif { bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_reconnecting; app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); TRACE(2,"%s try to reconnect reason =%d",__func__,ctx->disc_reason); if(app_bt_profile_reconnect_pending(id) != 0) { profile_reconnect_enable = true; } } #endif else { bt_profile_manager[id].hfp_connect = bt_profile_connect_status_unknow; } if (profile_reconnect_enable) { #ifdef __IAG_BLE_INCLUDE__ app_ble_refresh_adv_state(BLE_ADVERTISING_INTERVAL); #endif osTimerStart(bt_profile_manager[id].connect_timer, APP_BT_PROFILE_RECONNECT_RETRY_INTERVAL_MS); } break; default: break; } } DUMP8("%02x ", &bt_profile_manager[id].rmt_addr.address, 6); btdevice_profile *btdevice_plf_p1 = (btdevice_profile *)app_bt_profile_active_store_ptr_get((uint8_t *)&bt_profile_manager[id].rmt_addr.address); if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_reconnecting) { bool reconnect_hfp_proc_final = false; bool reconnect_a2dp_proc_final = false; if (bt_profile_manager[id].hfp_connect != bt_profile_connect_status_success) { reconnect_hfp_proc_final = false; } else { reconnect_hfp_proc_final = true; } if (bt_profile_manager[id].a2dp_connect != bt_profile_connect_status_success) { if(btdevice_plf_p1->hfp_act && btdevice_plf_p1->a2dp_act) { reconnect_a2dp_proc_final = false; } else { reconnect_a2dp_proc_final = true; } } if (reconnect_hfp_proc_final && reconnect_a2dp_proc_final) { TRACE(3,"!!!reconnect success %d/%d/%d\n", bt_profile_manager[id].hfp_connect, bt_profile_manager[id].hsp_connect, bt_profile_manager[id].a2dp_connect); app_bt_restore_reconnecting_idle_mode(id); // bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_null; } } else if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) { bool opening_hfp_proc_final = false; bool opening_a2dp_proc_final = false; if (btdevice_plf_p1->hfp_act && bt_profile_manager[id].hfp_connect == bt_profile_connect_status_unknow) { opening_hfp_proc_final = false; } else { opening_hfp_proc_final = true; } if (btdevice_plf_p1->a2dp_act && bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_unknow) { opening_a2dp_proc_final = false; } else { opening_a2dp_proc_final = true; } if(opening_hfp_proc_final && opening_a2dp_proc_final) { TRACE(3,"!!!reconnect success %d/%d/%d\n", bt_profile_manager[id].hfp_connect, bt_profile_manager[id].hsp_connect, bt_profile_manager[id].a2dp_connect); bt_profile_manager[id].saved_reconnect_mode = bt_profile_reconnect_openreconnecting; app_bt_restore_reconnecting_idle_mode(id); } else if(bt_profile_manager[id].hfp_connect == bt_profile_connect_status_failure) { TRACE(3,"reconnect_mode888:%d",bt_profile_manager[0].reconnect_mode); TRACE(3,"!!!reconnect success %d/%d/%d\n", bt_profile_manager[id].hfp_connect, bt_profile_manager[id].hsp_connect, bt_profile_manager[id].a2dp_connect); bt_profile_manager[id].saved_reconnect_mode = bt_profile_reconnect_openreconnecting; if ((bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) &&(bt_profile_manager[id].reconnect_cnt >= APP_BT_PROFILE_OPENNING_RECONNECT_RETRY_LIMIT_CNT)) { app_bt_restore_reconnecting_idle_mode(id); } } if (btdevice_plf_p1->hfp_act && bt_profile_manager[id].hfp_connect == bt_profile_connect_status_success) { if (btdevice_plf_p1->a2dp_act && !opening_a2dp_proc_final) { TRACE(1,"!!!continue connect a2dp %p\n", bt_profile_manager[id].stream); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_A2DP_OpenStream(bt_profile_manager[id].stream, &bt_profile_manager[id].rmt_addr); } } if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_null) { for (uint8_t i=0; istart reconnect second device\n"); if ((btdevice_plf_p_temp->hfp_act)&&(!bt_profile_manager[i].hfp_connect)) { TRACE(0,"try connect hf"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_HF_CreateServiceLink(bt_profile_manager[i].chan, (bt_bdaddr_t *)&bt_profile_manager[i].rmt_addr); } #if defined (__HSP_ENABLE__) else if((btdevice_plf_p_temp->hsp_act)&&(!bt_profile_manager[i].hsp_connect)) { TRACE(0,"try connect hs"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_HS_CreateServiceLink(bt_profile_manager[i].hs_chan, &bt_profile_manager[i].rmt_addr); } #endif else if((btdevice_plf_p_temp->a2dp_act)&&(!bt_profile_manager[i].a2dp_connect)) { TRACE(0,"try connect a2dp"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_A2DP_OpenStream(bt_profile_manager[i].stream, &bt_profile_manager[i].rmt_addr); } break; } } } } #ifdef __INTERCONNECTION__ if (bt_profile_manager[id].hfp_connect == bt_profile_connect_status_success && bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_success) { app_interconnection_start_disappear_adv(INTERCONNECTION_BLE_ADVERTISING_INTERVAL, APP_INTERCONNECTION_DISAPPEAR_ADV_IN_MS); if (btif_me_get_activeCons() <= 2) { app_interconnection_spp_open(btif_me_enumerate_remote_devices(id)); } } #endif #ifdef __IAG_BLE_INCLUDE__ TRACE(3, "%s hfp %d a2dp %d", __func__, bt_profile_manager[id].hfp_connect, bt_profile_manager[id].a2dp_connect); if (bt_profile_manager[id].hfp_connect == bt_profile_connect_status_success && #ifdef __HSP_ENABLE__ bt_profile_manager[id].hsp_connect == bt_profile_connect_status_success&& #endif bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_success) { app_ble_force_switch_adv(BLE_SWITCH_USER_BT_CONNECT, true); } #endif if (!bt_profile_manager[id].has_connected && (bt_profile_manager[id].hfp_connect == bt_profile_connect_status_success || #ifdef __HSP_ENABLE__ bt_profile_manager[id].hsp_connect == bt_profile_connect_status_success|| #endif bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_success)) { bt_profile_manager[id].has_connected = true; TRACE(0,"BT connected!!!"); once_event_case = 1; /*if(IsMobileLinkLossing){ startonce_delay_event_Timer_(3000); } else{ startonce_delay_event_Timer_(1500); }*/ app_voice_report(APP_STATUS_INDICATION_CONNECTED,0); IsMobileLinkLossing = FALSE; #ifndef IBRT btif_me_get_remote_device_name(&(ctx->remote_dev_bdaddr), app_bt_global_handle); #endif #if defined(MEDIA_PLAYER_SUPPORT)&& !defined(IBRT) app_voice_report(APP_STATUS_INDICATION_CONNECTED, id); #endif #if 0 // #ifdef __INTERCONNECTION__ app_interconnection_start_disappear_adv(BLE_ADVERTISING_INTERVAL, APP_INTERCONNECTION_DISAPPEAR_ADV_IN_MS); app_interconnection_spp_open(); #endif #ifdef __INTERACTION__ // app_interaction_spp_open(); #endif } if (bt_profile_manager[id].has_connected && (bt_profile_manager[id].hfp_connect != bt_profile_connect_status_success && #ifdef __HSP_ENABLE__ bt_profile_manager[id].hsp_connect != bt_profile_connect_status_success && #endif bt_profile_manager[id].a2dp_connect != bt_profile_connect_status_success)) { bt_profile_manager[id].has_connected = false; TRACE(0,"BT disconnected!!!"); #ifdef GFPS_ENABLED if (app_gfps_is_last_response_pending()) { app_gfps_enter_connectable_mode_req_handler(app_gfps_get_last_response()); } #endif #if defined(MEDIA_PLAYER_SUPPORT)&& !defined(IBRT) app_voice_report(APP_STATUS_INDICATION_DISCONNECTED, id); #endif #ifdef __INTERCONNECTION__ app_interconnection_disconnected_callback(); #endif app_set_disconnecting_all_bt_connections(false); } #ifdef __BT_ONE_BRING_TWO__ app_bt_update_connectable_mode_after_connection_management(); #endif } void app_bt_profile_connect_manager_a2dp(enum BT_DEVICE_ID_T id, a2dp_stream_t *Stream, const a2dp_callback_parms_t *info) { btdevice_profile *btdevice_plf_p = NULL; btif_remote_device_t *remDev = NULL; btif_a2dp_callback_parms_t* Info = (btif_a2dp_callback_parms_t*)info; osTimerStop(bt_profile_manager[id].connect_timer); bt_profile_manager[id].connect_timer_cb = NULL; bool profile_reconnect_enable = false; remDev = btif_a2dp_get_stream_conn_remDev(Stream); if (remDev) { btdevice_plf_p = (btdevice_profile *)app_bt_profile_active_store_ptr_get(btif_me_get_remote_device_bdaddr(remDev)->address); } else { btdevice_plf_p = (btdevice_profile *)app_bt_profile_active_store_ptr_get(NULL); } if (Stream&&Info) { switch(Info->event) { case BTIF_A2DP_EVENT_STREAM_OPEN: TRACE(4,"%s A2DP_EVENT_STREAM_OPEN,codec type=%x a2dp:%d mode:%d", __func__, Info->p.configReq->codec.codecType, bt_profile_manager[id].a2dp_connect, bt_profile_manager[id].reconnect_mode); nv_record_btdevicerecord_set_a2dp_profile_active_state(btdevice_plf_p, true); nv_record_btdevicerecord_set_a2dp_profile_codec(btdevice_plf_p, Info->p.configReq->codec.codecType); #ifndef FPGA nv_record_touch_cause_flush(); #endif if(bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_success) { TRACE(0,"!!!a2dp has opened force return "); return; } bt_profile_manager[id].a2dp_connect = bt_profile_connect_status_success; bt_profile_manager[id].reconnect_cnt = 0; bt_profile_manager[id].stream = app_bt_device.a2dp_connected_stream[id]; memcpy(bt_profile_manager[id].rmt_addr.address, btif_me_get_remote_device_bdaddr(btif_a2dp_get_stream_conn_remDev(Stream))->address, BTIF_BD_ADDR_SIZE); app_bt_record_latest_connected_service_device_id(id); if (false == bt_profile_manager[id].has_connected) { app_bt_resume_sniff_mode(id); } #ifdef BTIF_DIP_DEVICE btif_dip_get_remote_info(remDev); #endif if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) { //do nothing } #if defined(IBRT) else if (app_bt_ibrt_reconnect_mobile_profile_flag_get()) { app_bt_ibrt_reconnect_mobile_profile_flag_clear(); #else else if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_reconnecting) { #endif TRACE(2,"app_bt: hfp_act in NV =%d,a2dp_connect=%d",btdevice_plf_p->hfp_act,bt_profile_manager[id].hfp_connect); if (btdevice_plf_p->hfp_act&& bt_profile_manager[id].hfp_connect != bt_profile_connect_status_success) { if (btif_hf_check_rfcomm_l2cap_channel_is_creating(&bt_profile_manager[id].rmt_addr)) { TRACE(0,"!!!remote is creating hfp after a2dp connected\n"); } else { TRACE(0,"!!!continue connect hfp\n"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_HF_CreateServiceLink(bt_profile_manager[id].chan, (bt_bdaddr_t *)&bt_profile_manager[id].rmt_addr); } } #if defined (__HSP_ENABLE__) else if(btdevice_plf_p->hsp_act&& bt_profile_manager[id].hsp_connect != bt_profile_connect_status_success) { TRACE(0,"!!!continue connect hsp\n"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_HS_CreateServiceLink(bt_profile_manager[id].hs_chan, &bt_profile_manager[id].rmt_addr); } #endif } #ifdef __AUTO_CONNECT_OTHER_PROFILE__ else { if(btdevice_plf_p->hfp_act && bt_profile_manager[id].hfp_connect != bt_profile_connect_status_success) { bt_profile_manager[id].connect_timer_cb = app_bt_profile_connect_hf_retry_timehandler; app_bt_accessmode_set(BAM_CONNECTABLE_ONLY); osTimerStart(bt_profile_manager[id].connect_timer, APP_BT_PROFILE_CONNECT_RETRY_MS); } #if defined (__HSP_ENABLE__) else if(btdevice_plf_p->hsp_act && bt_profile_manager[id].hsp_connect != bt_profile_connect_status_success) { bt_profile_manager[id].connect_timer_cb = app_bt_profile_connect_hs_retry_timehandler; app_bt_accessmode_set(BAM_CONNECTABLE_ONLY); osTimerStart(bt_profile_manager[id].connect_timer, APP_BT_PROFILE_CONNECT_RETRY_MS); } #endif } #endif #ifdef APP_DISABLE_PAGE_SCAN_AFTER_CONN disable_page_scan_check_timer_start(); #endif break; case BTIF_A2DP_EVENT_STREAM_CLOSED: TRACE(2,"%s A2DP_EVENT_STREAM_CLOSED discReason1:%d",__func__, Info->discReason); if(Info->subevt != A2DP_CONN_CLOSED) { TRACE(0,"do not need set access mode"); return ; } if(Stream!=NULL) { if(btif_a2dp_get_remote_device(Stream)!=NULL) TRACE(2,"%s A2DP_EVENT_STREAM_CLOSED discReason2:%d",__func__,btif_me_get_remote_device_disc_reason_saved(btif_a2dp_get_remote_device(Stream))); } #if defined(IBRT) if (app_bt_ibrt_reconnect_mobile_profile_flag_get()) { app_bt_HF_CreateServiceLink(bt_profile_manager[id].chan, (bt_bdaddr_t *)&bt_profile_manager[id].rmt_addr); } #endif bt_profile_manager[id].a2dp_connect = bt_profile_connect_status_failure; if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) { if (++bt_profile_manager[id].reconnect_cnt < APP_BT_PROFILE_OPENNING_RECONNECT_RETRY_LIMIT_CNT) { app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); profile_reconnect_enable = true; bt_profile_manager[id].a2dp_connect = bt_profile_connect_status_unknow; } } else if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_reconnecting) { if (++bt_profile_manager[id].reconnect_cnt < APP_BT_PROFILE_RECONNECT_RETRY_LIMIT_CNT) { app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); profile_reconnect_enable = true; } else { app_bt_restore_reconnecting_idle_mode(id); // bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_null; } TRACE(2,"%s try to reconnect cnt:%d",__func__, bt_profile_manager[id].reconnect_cnt); } #if !defined(IBRT) #if defined(ENHANCED_STACK) else if(((Info->discReason == 0x08)|| (Info->discReason == 0x04)) && #else else if(((Info->discReason == 0x8)|| (Info->discReason_saved == 0x8)|| (Info->discReason_saved == 0x0)) && #endif (btdevice_plf_p->a2dp_act)&& (!btdevice_plf_p->hfp_act) && (!btdevice_plf_p->hsp_act)) { bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_reconnecting; TRACE(2,"%s try to reconnect cnt:%d",__func__, bt_profile_manager[id].reconnect_cnt); app_bt_accessmode_set(BTIF_BAM_CONNECTABLE_ONLY); if(app_bt_profile_reconnect_pending(id) != 0) { profile_reconnect_enable = true; } } #endif else { bt_profile_manager[id].a2dp_connect = bt_profile_connect_status_unknow; } if (profile_reconnect_enable) { #ifdef __IAG_BLE_INCLUDE__ app_ble_refresh_adv_state(BLE_ADVERTISING_INTERVAL); #endif osTimerStart(bt_profile_manager[id].connect_timer, APP_BT_PROFILE_RECONNECT_RETRY_INTERVAL_MS); } break; default: break; } } if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_reconnecting) { bool reconnect_hfp_proc_final = true; bool reconnect_a2dp_proc_final = true; if (bt_profile_manager[id].hfp_connect == bt_profile_connect_status_failure) { reconnect_hfp_proc_final = false; } #if defined (__HSP_ENABLE__) if(btdevice_plf_p->hsp_act !=0) //has HSP { reconnect_hfp_proc_final = true; if (bt_profile_manager[id].hsp_connect == bt_profile_connect_status_failure) { reconnect_hfp_proc_final = false; } } #endif if (bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_failure) { reconnect_a2dp_proc_final = false; } if (reconnect_hfp_proc_final && reconnect_a2dp_proc_final) { TRACE(3,"!!!reconnect success %d/%d/%d\n", bt_profile_manager[id].hfp_connect, bt_profile_manager[id].hsp_connect, bt_profile_manager[id].a2dp_connect); app_bt_restore_reconnecting_idle_mode(id); // bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_null; } } else if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_openreconnecting) { bool opening_hfp_proc_final = false; bool opening_a2dp_proc_final = false; if (btdevice_plf_p->hfp_act && bt_profile_manager[id].hfp_connect == bt_profile_connect_status_unknow) { opening_hfp_proc_final = false; } else { opening_hfp_proc_final = true; } if (btdevice_plf_p->a2dp_act && bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_unknow) { opening_a2dp_proc_final = false; } else { opening_a2dp_proc_final = true; } if ((opening_hfp_proc_final && opening_a2dp_proc_final) || (bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_failure)) { TRACE(3,"!!!reconnect success %d/%d/%d\n", bt_profile_manager[id].hfp_connect, bt_profile_manager[id].hsp_connect, bt_profile_manager[id].a2dp_connect); app_bt_restore_reconnecting_idle_mode(id); // bt_profile_manager[id].reconnect_mode = bt_profile_reconnect_null; } if (btdevice_plf_p->a2dp_act && bt_profile_manager[id].a2dp_connect== bt_profile_connect_status_success) { if (btdevice_plf_p->hfp_act && !opening_hfp_proc_final) { if (btif_hf_check_rfcomm_l2cap_channel_is_creating(&bt_profile_manager[id].rmt_addr)) { TRACE(0,"!!!remote is creating hf after a2dp connected\n"); } else { TRACE(0,"!!!continue connect hf\n"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_HF_CreateServiceLink(bt_profile_manager[id].chan, (bt_bdaddr_t *)&bt_profile_manager[id].rmt_addr); } } #if defined (__HSP_ENABLE) else if(btdevice_plf_p->hsp_act && !opening_hfp_hsp_proc_final) { TRACE(0,"!!!continue connect hs\n"); app_bt_precheck_before_starting_connecting(bt_profile_manager[id].has_connected); app_bt_HS_CreateServiceLink(bt_profile_manager[id].hs_chan, &bt_profile_manager[id].rmt_addr); } #endif } if (bt_profile_manager[id].reconnect_mode == bt_profile_reconnect_null) { for (uint8_t i=0; istart reconnect device %d\n", i); if ((btdevice_plf_p->hfp_act)&&(!bt_profile_manager[i].hfp_connect)) { TRACE(0,"try connect hf"); app_bt_precheck_before_starting_connecting(bt_profile_manager[i].has_connected); app_bt_HF_CreateServiceLink(bt_profile_manager[i].chan, (bt_bdaddr_t *)&bt_profile_manager[i].rmt_addr); } #if defined (__HSP_ENABLE__) else if((btdevice_plf_p->hsp_act)&&(!bt_profile_manager[i].hsp_connect)) { TRACE(0,"try connect hs"); app_bt_precheck_before_starting_connecting(bt_profile_manager[i].has_connected); app_bt_HS_CreateServiceLink(bt_profile_manager[i].hs_chan, &bt_profile_manager[i].rmt_addr); } #endif else if((btdevice_plf_p->a2dp_act)&&(!bt_profile_manager[i].a2dp_connect)) { TRACE(0,"try connect a2dp"); app_bt_precheck_before_starting_connecting(bt_profile_manager[i].has_connected); app_bt_A2DP_OpenStream(bt_profile_manager[i].stream, &bt_profile_manager[i].rmt_addr); } break; } } } } #ifdef __INTERCONNECTION__ if (bt_profile_manager[id].hfp_connect == bt_profile_connect_status_success && bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_success) { app_interconnection_start_disappear_adv(INTERCONNECTION_BLE_ADVERTISING_INTERVAL, APP_INTERCONNECTION_DISAPPEAR_ADV_IN_MS); if (btif_me_get_activeCons() <= 2) { app_interconnection_spp_open(remDev); } } #endif #ifdef __IAG_BLE_INCLUDE__ TRACE(3, "%s hfp %d a2dp %d", __func__, bt_profile_manager[id].hfp_connect, bt_profile_manager[id].a2dp_connect); if (bt_profile_manager[id].hfp_connect == bt_profile_connect_status_success && #ifdef __HSP_ENABLE__ bt_profile_manager[id].hsp_connect == bt_profile_connect_status_success && #endif bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_success) { app_ble_force_switch_adv(BLE_SWITCH_USER_BT_CONNECT, true); } #endif if (!bt_profile_manager[id].has_connected && (bt_profile_manager[id].hfp_connect == bt_profile_connect_status_success || #ifdef __HSP_ENABLE__ bt_profile_manager[id].hsp_connect == bt_profile_connect_status_success|| #endif bt_profile_manager[id].a2dp_connect == bt_profile_connect_status_success)) { bt_profile_manager[id].has_connected = true; TRACE(0,"BT connected!!!"); IsMobileLinkLossing = FALSE; #ifndef IBRT btif_me_get_remote_device_name(&(bt_profile_manager[id].rmt_addr), app_bt_global_handle); #endif #if defined(MEDIA_PLAYER_SUPPORT)//&& !defined(IBRT) app_voice_report(APP_STATUS_INDICATION_CONNECTED, id); #endif #if 0 // #ifdef __INTERCONNECTION__ app_interconnection_start_disappear_adv(BLE_ADVERTISING_INTERVAL, APP_INTERCONNECTION_DISAPPEAR_ADV_IN_MS); app_interconnection_spp_open(); #endif #ifdef __INTERACTION__ // app_interaction_spp_open(); #endif } if (bt_profile_manager[id].has_connected && (bt_profile_manager[id].hfp_connect != bt_profile_connect_status_success && #ifdef __HSP_ENABLE__ bt_profile_manager[id].hsp_connect != bt_profile_connect_status_success && #endif bt_profile_manager[id].a2dp_connect != bt_profile_connect_status_success)) { bt_profile_manager[id].has_connected = false; TRACE(0,"BT disconnected!!!"); #ifdef GFPS_ENABLED if (app_gfps_is_last_response_pending()) { app_gfps_enter_connectable_mode_req_handler(app_gfps_get_last_response()); } #endif #if defined(MEDIA_PLAYER_SUPPORT)&& !defined(IBRT) app_voice_report(APP_STATUS_INDICATION_DISCONNECTED, id); #endif #ifdef __INTERCONNECTION__ app_interconnection_disconnected_callback(); #endif app_set_disconnecting_all_bt_connections(false); } #ifdef __BT_ONE_BRING_TWO__ app_bt_update_connectable_mode_after_connection_management(); #endif } #ifdef BTIF_HID_DEVICE void hid_exit_shutter_mode(void); #endif static bool isDisconnectAllBtConnections = false; bool app_is_disconnecting_all_bt_connections(void) { return isDisconnectAllBtConnections; } void app_set_disconnecting_all_bt_connections(bool isEnable) { isDisconnectAllBtConnections = isEnable; } bt_status_t LinkDisconnectDirectly(bool PowerOffFlag) { app_set_disconnecting_all_bt_connections(true); //TRACE(1,"osapi_lock_is_exist:%d",osapi_lock_is_exist()); if(osapi_lock_is_exist()) osapi_lock_stack(); #ifdef __IAG_BLE_INCLUDE__ TRACE(1,"ble_connected_state:%d", app_ble_is_any_connection_exist()); #endif #if defined(IBRT) ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); if(true==PowerOffFlag) p_ibrt_ctrl->ibrt_in_poweroff= true; if (p_ibrt_ctrl->init_done) { if(IBRT_MASTER==p_ibrt_ctrl->current_role) { if(app_tws_ibrt_mobile_link_connected()) { //should check return status app_tws_ibrt_disconnect_connection(btif_me_get_remote_device_by_handle(p_ibrt_ctrl->mobile_conhandle)); } } if (app_tws_ibrt_tws_link_connected()) { app_tws_ibrt_disconnect_connection(btif_me_get_remote_device_by_handle(p_ibrt_ctrl->tws_conhandle)); } } if(osapi_lock_is_exist()) osapi_unlock_stack(); osDelay(500); return BT_STS_SUCCESS; #endif TRACE(1,"activeCons:%d", btif_me_get_activeCons()); uint8_t Tmp_activeCons = btif_me_get_activeCons(); if(Tmp_activeCons) { //TRACE(3,"%s id1 hf:%d a2dp:%d",__func__, app_bt_device.hf_channel[BT_DEVICE_ID_1].state, btif_a2dp_get_stream_state(app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream)); TRACE(3,"%s id1 hf:%d a2dp:%d",__func__, btif_get_hf_chan_state(app_bt_device.hf_channel[BT_DEVICE_ID_1]), btif_a2dp_get_stream_state(app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream)); #ifdef BTIF_HID_DEVICE hid_exit_shutter_mode(); #endif if (btif_get_hf_chan_state(app_bt_device.hf_channel[BT_DEVICE_ID_1]) == BTIF_HF_STATE_OPEN) { app_bt_HF_DisconnectServiceLink(app_bt_device.hf_channel[BT_DEVICE_ID_1]); } #if defined (__HSP_ENABLE__) if(app_bt_device.hs_channel[BT_DEVICE_ID_1].state == HS_STATE_OPEN) { app_bt_HS_DisconnectServiceLink(&app_bt_device.hs_channel[BT_DEVICE_ID_1]); } #endif //btif_a2dp_get_stream_state(app_bt_device.a2dp_stream[device_id]->a2dp_stream) if(btif_a2dp_get_stream_state(app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state(app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_OPEN) { app_bt_A2DP_CloseStream(app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream); } #if defined(A2DP_LHDC_ON) if(btif_a2dp_get_stream_state(app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state(app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_OPEN) { app_bt_A2DP_CloseStream(app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_1]->a2dp_stream); } #endif #if defined(A2DP_LDAC_ON) if(btif_a2dp_get_stream_state(app_bt_device.a2dp_ldac_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state(app_bt_device.a2dp_ldac_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_OPEN) { app_bt_A2DP_CloseStream(app_bt_device.a2dp_ldac_stream[BT_DEVICE_ID_1]->a2dp_stream); } #endif #if defined(A2DP_AAC_ON) if(btif_a2dp_get_stream_state( app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state( app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_OPEN) { app_bt_A2DP_CloseStream(app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream); } #endif #if defined(A2DP_SCALABLE_ON) if(btif_a2dp_get_stream_state( app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state(app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_1]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_OPEN) { app_bt_A2DP_CloseStream(app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_1]->a2dp_stream); } #endif if( btif_avrcp_get_remote_device(app_bt_device.avrcp_channel[BT_DEVICE_ID_1]->avrcp_channel_handle)) { btif_avrcp_disconnect(app_bt_device.avrcp_channel[BT_DEVICE_ID_1]->avrcp_channel_handle); } #ifdef __BT_ONE_BRING_TWO__ TRACE(3,"%s id2 hf:%d a2dp:%d",__func__, btif_get_hf_chan_state(app_bt_device.hf_channel[BT_DEVICE_ID_2]), btif_a2dp_get_stream_state(app_bt_device.a2dp_stream[BT_DEVICE_ID_2]->a2dp_stream)); //if(app_bt_device.hf_channel[BT_DEVICE_ID_2].state == HF_STATE_OPEN){ if(btif_get_hf_chan_state(app_bt_device.hf_channel[BT_DEVICE_ID_2]) == BTIF_HF_STATE_OPEN) { app_bt_HF_DisconnectServiceLink(app_bt_device.hf_channel[BT_DEVICE_ID_2]); } #if defined (__HSP_ENABLE__) if(app_bt_device.hs_channel[BT_DEVICE_ID_2].state == HS_STATE_OPEN) { app_bt_HS_DisconnectServiceLink(&app_bt_device.hs_channel[BT_DEVICE_ID_2]); } #endif // __HSP_ENABLE__ if( btif_a2dp_get_stream_state(app_bt_device.a2dp_stream[BT_DEVICE_ID_2]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state(app_bt_device.a2dp_stream[BT_DEVICE_ID_2]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_OPEN) { app_bt_A2DP_CloseStream(app_bt_device.a2dp_stream[BT_DEVICE_ID_2]->a2dp_stream); } #if defined(A2DP_LHDC_ON) if(btif_a2dp_get_stream_state(app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_2]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state(app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_2]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_OPEN) { app_bt_A2DP_CloseStream(app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_2]->a2dp_stream); } #endif // A2DP_LHDC_ON #if defined(A2DP_AAC_ON) if(btif_a2dp_get_stream_state(app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_2]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state(app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_2]->a2dp_stream)== BTIF_AVDTP_STRM_STATE_OPEN) { app_bt_A2DP_CloseStream(app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_2]->a2dp_stream); } #endif // A2DP_AAC_ON #if defined(A2DP_SCALABLE_ON) if(btif_a2dp_get_stream_state(app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_2]->a2dp_stream)== BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state(app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_2]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_OPEN) { app_bt_A2DP_CloseStream(app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_2]->a2dp_stream); } #endif // A2DP_SCALABLE_ON if( btif_avrcp_get_remote_device(app_bt_device.avrcp_channel[BT_DEVICE_ID_2]->avrcp_channel_handle)) { btif_avrcp_disconnect(app_bt_device.avrcp_channel[BT_DEVICE_ID_2]->avrcp_channel_handle); } #endif //__BT_ONE_BRING_TWO__ #ifdef BISTO_ENABLED gsound_custom_bt_disconnect_all_channel(); #endif } #ifdef __IAG_BLE_INCLUDE__ if(app_ble_is_any_connection_exist()) { #ifdef GFPS_ENABLED if (!app_gfps_is_last_response_pending()) #endif app_ble_disconnect_all(); } #endif if(osapi_lock_is_exist()) osapi_unlock_stack(); osDelay(500); if(Tmp_activeCons) { btif_remote_device_t* remDev = app_bt_get_remoteDev(BT_DEVICE_ID_1); if (NULL != remDev) { app_bt_MeDisconnectLink(remDev); } #ifdef __BT_ONE_BRING_TWO__ remDev = app_bt_get_remoteDev(BT_DEVICE_ID_2); if (NULL != remDev) { osDelay(200); app_bt_MeDisconnectLink(remDev); } #endif } return BT_STS_SUCCESS; } void app_disconnect_all_bt_connections(void) { LinkDisconnectDirectly(false); } static int app_custom_function_process(APP_MESSAGE_BODY *msg_body) { APP_APPTHREAD_REQ_CUSTOMER_CALL_FN_T customer_call = (APP_APPTHREAD_REQ_CUSTOMER_CALL_FN_T)(msg_body->message_ptr); TRACE(4, "func:0x%08x,param0:0x%08x, param1:0x%08x", msg_body->message_ptr, msg_body->message_Param0, msg_body->message_Param1); if (customer_call){ customer_call((void *)msg_body->message_Param0, (void *)msg_body->message_Param1); } return 0; } int app_bt_start_custom_function_in_app_thread( uint32_t param0, uint32_t param1, uint32_t funcPtr) { APP_MESSAGE_BLOCK msg; msg.mod_id = APP_MODUAL_CUSTOM_FUNCTION; msg.msg_body.message_id = 0; msg.msg_body.message_ptr = funcPtr; msg.msg_body.message_Param0 = param0; msg.msg_body.message_Param1 = param1; app_mailbox_put(&msg); return 0; } void app_bt_init(void) { app_bt_mail_init(); app_set_threadhandle(APP_MODUAL_BT, app_bt_handle_process); btif_me_sec_set_io_cap_rsp_reject_ext(app_bt_profile_connect_openreconnecting); app_bt_active_mode_manager_init(); app_set_threadhandle(APP_MODUAL_CUSTOM_FUNCTION, app_custom_function_process); } extern "C" bool app_bt_has_connectivitys(void) { int activeCons; osapi_lock_stack(); activeCons = btif_me_get_activeCons(); osapi_unlock_stack(); if(activeCons > 0) return true; return false; #if 0 if(app_bt_device.hf_channel[BT_DEVICE_ID_1].cmgrHandler.remDev) return true; if(app_bt_device.a2dp_stream[BT_DEVICE_ID_1].device->cmgrHandler.remDev) return true; #ifdef __BT_ONE_BRING_TWO__ if(app_bt_device.hf_channel[BT_DEVICE_ID_2].cmgrHandler.remDev) return true; if(app_bt_device.a2dp_stream[BT_DEVICE_ID_2].device->cmgrHandler.remDev) return true; #endif return false; #endif } #ifdef __TWS_CHARGER_BOX__ extern "C" { bt_status_t ME_Ble_Clear_Whitelist(void); bt_status_t ME_Ble_Set_Private_Address(BT_BD_ADDR *addr); bt_status_t ME_Ble_Add_Dev_To_Whitelist(U8 addr_type,BT_BD_ADDR *addr); bt_status_t ME_Ble_SetAdv_data(U8 len, U8 *data); bt_status_t ME_Ble_SetScanRsp_data(U8 len, U8 *data); bt_status_t ME_Ble_SetAdv_parameters(adv_para_struct *para); bt_status_t ME_Ble_SetAdv_en(U8 en); bt_status_t ME_Ble_Setscan_parameter(scan_para_struct *para); bt_status_t ME_Ble_Setscan_en(U8 scan_en, U8 filter_duplicate); } int8_t power_level=0; #define TWS_BOX_OPEN 1 #define TWS_BOX_CLOSE 0 void app_tws_box_set_slave_adv_data(uint8_t power_level,uint8_t box_status) { uint8_t adv_data[] = { 0x02,0xfe, 0x00, 0x02, 0xfd, 0x00 // manufacturer data }; adv_data[2] = power_level; adv_data[5] = box_status; ME_Ble_SetAdv_data(sizeof(adv_data), adv_data); } void app_tws_box_set_slave_adv_para(void) { uint8_t peer_addr[BTIF_BD_ADDR_SIZE] = {0}; adv_para_struct para; para.interval_min = 0x0040; // 20ms para.interval_max = 0x0040; // 20ms para.adv_type = 0x03; para.own_addr_type = 0x01; para.peer_addr_type = 0x01; para.adv_chanmap = 0x07; para.adv_filter_policy = 0x00; memcpy(para.bd_addr.addr, peer_addr, BTIF_BD_ADDR_SIZE); ME_Ble_SetAdv_parameters(¶); } extern uint8_t bt_addr[6]; void app_tws_start_chargerbox_adv(void) { app_tws_box_set_slave_adv_data(power_level,TWS_BOX_OPEN); ME_Ble_Set_Private_Address((BT_BD_ADDR *)bt_addr); app_tws_box_set_slave_adv_para(); ME_Ble_SetAdv_en(1); } #endif bool app_is_hfp_service_connected(void) { return (bt_profile_manager[BT_DEVICE_ID_1].hfp_connect == bt_profile_connect_status_success); } btif_remote_device_t* app_bt_get_remoteDev(uint8_t deviceId) { btif_remote_device_t* currentRemDev = NULL; if(btif_a2dp_get_stream_state( app_bt_device.a2dp_stream[deviceId]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_STREAMING || btif_a2dp_get_stream_state( app_bt_device.a2dp_stream[deviceId]->a2dp_stream) == BTIF_AVDTP_STRM_STATE_OPEN) { currentRemDev = btif_a2dp_get_stream_conn_remDev(app_bt_device.a2dp_stream[deviceId]->a2dp_stream); } else if (btif_get_hf_chan_state(app_bt_device.hf_channel[deviceId]) == BTIF_HF_STATE_OPEN) { currentRemDev = (btif_remote_device_t *)btif_hf_cmgr_get_remote_device(app_bt_device.hf_channel[deviceId]); } TRACE(2,"%s get current Remdev %p", __FUNCTION__, currentRemDev); return currentRemDev; } void app_bt_stay_active_rem_dev(btif_remote_device_t* pRemDev) { if (pRemDev) { btif_cmgr_handler_t *cmgrHandler; /* Clear the sniff timer */ cmgrHandler = btif_cmgr_get_acl_handler(pRemDev); btif_cmgr_clear_sniff_timer(cmgrHandler); btif_cmgr_disable_sniff_timer(cmgrHandler); app_bt_Me_SetLinkPolicy(pRemDev, BTIF_BLP_MASTER_SLAVE_SWITCH); } } void app_bt_stay_active(uint8_t deviceId) { btif_remote_device_t* currentRemDev = app_bt_get_remoteDev(deviceId); app_bt_stay_active_rem_dev(currentRemDev); } void app_bt_allow_sniff_rem_dev(btif_remote_device_t* pRemDev) { if (pRemDev && (BTIF_BDS_CONNECTED == btif_me_get_remote_device_state(pRemDev))) { btif_cmgr_handler_t *cmgrHandler; /* Enable the sniff timer */ cmgrHandler = btif_cmgr_get_acl_handler(pRemDev); /* Start the sniff timer */ btif_sniff_info_t sniffInfo; sniffInfo.minInterval = BTIF_CMGR_SNIFF_MIN_INTERVAL; sniffInfo.maxInterval = BTIF_CMGR_SNIFF_MAX_INTERVAL; sniffInfo.attempt = BTIF_CMGR_SNIFF_ATTEMPT; sniffInfo.timeout = BTIF_CMGR_SNIFF_TIMEOUT; if (cmgrHandler) { btif_cmgr_set_sniff_timer(cmgrHandler, &sniffInfo, BTIF_CMGR_SNIFF_TIMER); } app_bt_Me_SetLinkPolicy(pRemDev, BTIF_BLP_MASTER_SLAVE_SWITCH | BTIF_BLP_SNIFF_MODE); } } extern "C" uint8_t is_sco_mode (void); void app_bt_allow_sniff(uint8_t deviceId) { if (a2dp_is_music_ongoing() || is_sco_mode()) { return; } btif_remote_device_t* currentRemDev = app_bt_get_remoteDev(deviceId); app_bt_allow_sniff_rem_dev(currentRemDev); } void app_bt_stop_sniff(uint8_t deviceId) { btif_remote_device_t* currentRemDev = app_bt_get_remoteDev(deviceId); if (currentRemDev && (btif_me_get_remote_device_state(currentRemDev) == BTIF_BDS_CONNECTED)) { if (btif_me_get_current_mode(currentRemDev) == BTIF_BLM_SNIFF_MODE) { TRACE(1,"!!! stop sniff currmode:%d\n", btif_me_get_current_mode(currentRemDev)); app_bt_ME_StopSniff(currentRemDev); } } } bool app_bt_is_device_connected(uint8_t deviceId) { if (deviceId < BT_DEVICE_NUM) { return bt_profile_manager[deviceId].has_connected; } else { // Indicate no connection is user passes invalid deviceId return false; } } #if defined(__BT_SELECT_PROF_DEVICE_ID__) int8_t app_bt_a2dp_is_same_stream(a2dp_stream_t *src_Stream, a2dp_stream_t *dst_Stream) { return btif_a2dp_is_register_codec_same(src_Stream, dst_Stream); } void app_bt_a2dp_find_same_unused_stream(a2dp_stream_t *in_Stream, a2dp_stream_t **out_Stream, uint32_t device_id) { *out_Stream = NULL; if (app_bt_a2dp_is_same_stream(app_bt_device.a2dp_stream[device_id]->a2dp_stream, in_Stream)) *out_Stream = app_bt_device.a2dp_stream[device_id]->a2dp_stream; #if defined(A2DP_LHDC_ON) else if (app_bt_a2dp_is_same_stream(app_bt_device.a2dp_lhdc_stream[device_id]->a2dp_stream, in_Stream)) *out_Stream = app_bt_device.a2dp_lhdc_stream[device_id]->a2dp_stream; #endif #if defined(A2DP_LDAC_ON) else if (app_bt_a2dp_is_same_stream(app_bt_device.a2dp_ldac_stream[device_id]->a2dp_stream, in_Stream)) *out_Stream = app_bt_device.a2dp_ldac_stream[device_id]->a2dp_stream; #endif #if defined(A2DP_AAC_ON) else if (app_bt_a2dp_is_same_stream(app_bt_device.a2dp_aac_stream[device_id]->a2dp_stream, in_Stream)) *out_Stream = app_bt_device.a2dp_aac_stream[device_id]->a2dp_stream; #endif #if defined(A2DP_SCALABLE_ON) else if (app_bt_a2dp_is_same_stream(app_bt_device.a2dp_scalable_stream[device_id]->a2dp_stream, in_Stream)) *out_Stream = app_bt_device.a2dp_scalable_stream[device_id]->a2dp_stream; #endif } int8_t app_bt_a2dp_is_stream_on_device_id(a2dp_stream_t *in_Stream, uint32_t device_id) { if (app_bt_device.a2dp_stream[device_id]->a2dp_stream == in_Stream) return 1; #if defined(A2DP_LHDC_ON) else if (app_bt_device.a2dp_lhdc_stream[device_id]->a2dp_stream == in_Stream) return 1; #endif #if defined(A2DP_LDAC_ON) else if (app_bt_device.a2dp_ldac_stream[device_id]->a2dp_stream == in_Stream) return 1; #endif #if defined(A2DP_AAC_ON) else if (app_bt_device.a2dp_aac_stream[device_id]->a2dp_stream == in_Stream) return 1; #endif #if defined(A2DP_SCALABLE_ON) else if (app_bt_device.a2dp_scalable_stream[device_id]->a2dp_stream == in_Stream) return 1; #endif return 0; } int8_t app_bt_hfp_is_chan_on_device_id(hf_chan_handle_t chan, uint32_t device_id) { if (app_bt_device.hf_channel[device_id] == chan) return 1; return 0; } int8_t app_bt_is_any_profile_connected(uint32_t device_id) { // TODO avrcp?spp?hid?bisto?ama?dma?rfcomm? if ((bt_profile_manager[device_id].hfp_connect == bt_profile_connect_status_success) || (bt_profile_manager[device_id].hsp_connect == bt_profile_connect_status_success) || (bt_profile_manager[device_id].a2dp_connect == bt_profile_connect_status_success)) { return 1; } return 0; } int8_t app_bt_is_a2dp_connected(uint32_t device_id) { if (bt_profile_manager[device_id].a2dp_connect == bt_profile_connect_status_success) { return 1; } return 0; } btif_remote_device_t *app_bt_get_connected_profile_remdev(uint32_t device_id) { if (bt_profile_manager[device_id].a2dp_connect == bt_profile_connect_status_success) { return (btif_remote_device_t *)btif_a2dp_get_remote_device(app_bt_device.a2dp_connected_stream[device_id]); } else if (bt_profile_manager[device_id].hfp_connect == bt_profile_connect_status_success) { return (btif_remote_device_t *)btif_hf_cmgr_get_remote_device(app_bt_device.hf_channel[device_id]); } #if defined (__HSP_ENABLE__) else if (bt_profile_manager[device_id].hsp_connect == bt_profile_connect_status_success) { // TODO hsp support //return (btif_remote_device_t *)btif_hs_cmgr_get_remote_device(app_bt_device.hs_channel[i]); } #endif return NULL; } #endif bool app_bt_get_device_bdaddr(uint8_t deviceId, uint8_t* btAddr) { bool ret = false; if (app_bt_is_device_connected(deviceId)) { btif_remote_device_t* currentRemDev = app_bt_get_remoteDev(deviceId); if (currentRemDev) { memcpy(btAddr, btif_me_get_remote_device_bdaddr(currentRemDev)->address, BTIF_BD_ADDR_SIZE); ret = true; } } return ret; } void fast_pair_enter_pairing_mode_handler(void) { #if defined(IBRT) app_ibrt_ui_judge_scan_type(IBRT_FASTPAIR_TRIGGER, MOBILE_LINK, 0); #else app_bt_accessmode_set(BTIF_BAM_GENERAL_ACCESSIBLE); #endif #ifdef __INTERCONNECTION__ clear_discoverable_adv_timeout_flag(); app_interceonnection_start_discoverable_adv(INTERCONNECTION_BLE_FAST_ADVERTISING_INTERVAL, APP_INTERCONNECTION_FAST_ADV_TIMEOUT_IN_MS); #endif } bool app_bt_is_hfp_audio_on(void) { bool hfp_audio_is_on = false; for (uint8_t i=0; iaddress[0], addr->address[1], addr->address[2], addr->address[3], addr->address[4], addr->address[5], name); #if defined(HFP_MOBILE_AG_ROLE) bt_bdaddr_t test_device1 = {{0xd2, 0x53, 0x86, 0x42, 0x71, 0x31}}; bt_bdaddr_t test_device2 = {{0xd3, 0x53, 0x86, 0x42, 0x71, 0x31}}; return (memcmp(addr, test_device1.address, sizeof(bt_bdaddr_t)) == 0 || memcmp(addr, test_device2.address, sizeof(bt_bdaddr_t)) == 0); #else return false; #endif } static struct app_bt_search_t g_bt_search; static void app_bt_search_callback(const btif_event_t* event) { TRACE(2,"%s event %d\n", __func__, btif_me_get_callback_event_type(event)); switch(btif_me_get_callback_event_type(event)) { case BTIF_BTEVENT_INQUIRY_RESULT: { bt_bdaddr_t *addr = btif_me_get_callback_event_inq_result_bd_addr(event); uint8_t mode = btif_me_get_callback_event_inq_result_inq_mode(event); const int NAME_MAX_LEN = 255; char device_name[NAME_MAX_LEN+1] = {0}; int device_name_len = 0; uint8_t *eir = NULL; if ((mode == BTIF_INQ_MODE_EXTENDED) && (eir = btif_me_get_callback_event_inq_result_ext_inq_resp(event))) { device_name_len = btif_me_get_ext_inq_data(eir, 0x09, (uint8_t *)device_name, NAME_MAX_LEN); } if (app_bt_search_device_match(addr, device_name_len > 0 ? device_name : "")) { g_bt_search.address = *addr; g_bt_search.device_searched = true; btif_me_cancel_inquiry(); } } break; case BTIF_BTEVENT_INQUIRY_COMPLETE: case BTIF_BTEVENT_INQUIRY_CANCELED: btif_me_unregister_globa_handler((btif_handler *)btif_me_get_bt_handler()); g_bt_search.search_start = false; g_bt_search.inquiry_pending = false; if (g_bt_search.device_searched) { #if defined(HFP_MOBILE_AG_ROLE) bt_profile_manager[BT_DEVICE_ID_1].reconnect_mode = bt_profile_reconnect_null; bt_profile_manager[BT_DEVICE_ID_1].rmt_addr = g_bt_search.address; bt_profile_manager[BT_DEVICE_ID_1].chan = app_bt_device.hf_channel[BT_DEVICE_ID_1]; app_bt_precheck_before_starting_connecting(bt_profile_manager[BT_DEVICE_ID_1].has_connected); app_bt_HF_CreateServiceLink(bt_profile_manager[BT_DEVICE_ID_1].chan, &bt_profile_manager[BT_DEVICE_ID_1].rmt_addr); #endif } else { TRACE(1,"%s no device matched\n", __func__); #if 0 /* continue to search ??? */ app_bt_start_search(); #endif } break; default: break; } } void app_bt_start_search(void) { uint8_t max_search_time = 10; /* 12.8s */ if (g_bt_search.search_start) { TRACE(1,"%s already started\n", __func__); return; } btif_me_set_handler(btif_me_get_bt_handler(), app_bt_search_callback); btif_me_set_event_mask(btif_me_get_bt_handler(), BTIF_BEM_INQUIRY_RESULT | BTIF_BEM_INQUIRY_COMPLETE | BTIF_BEM_INQUIRY_CANCELED | BTIF_BEM_LINK_CONNECT_IND | BTIF_BEM_LINK_CONNECT_CNF | BTIF_BEM_LINK_DISCONNECT | BTIF_BEM_ROLE_CHANGE | BTIF_BEM_MODE_CHANGE); btif_me_register_global_handler(btif_me_get_bt_handler()); g_bt_search.search_start = true; g_bt_search.device_searched = false; g_bt_search.inquiry_pending = false; if (BT_STS_PENDING != btif_me_inquiry(BTIF_BT_IAC_GIAC, max_search_time, 0)) { TRACE(1,"%s start inquiry failed\n", __func__); g_bt_search.inquiry_pending = true; } } uint8_t app_bt_avrcp_get_notify_trans_id(void) { return btif_a2dp_get_avrcpadvancedpdu_trans_id(app_bt_device.avrcp_notify_rsp[BT_DEVICE_ID_1]); } void app_bt_avrcp_set_notify_trans_id(uint8_t trans_id) { TRACE(3,"%s %d %p\n", __func__, trans_id, app_bt_device.avrcp_notify_rsp[BT_DEVICE_ID_1]); btif_a2dp_set_avrcpadvancedpdu_trans_id(app_bt_device.avrcp_notify_rsp[BT_DEVICE_ID_1], trans_id); } uint8_t app_bt_avrcp_get_ctl_trans_id(void) { return btif_avrcp_get_ctl_trans_id(app_bt_device.avrcp_channel[BT_DEVICE_ID_1]); } void app_bt_avrcp_set_ctl_trans_id(uint8_t trans_id) { TRACE(3,"%s %d %p\n", __func__, trans_id, app_bt_device.avrcp_channel[BT_DEVICE_ID_1]); btif_avrcp_set_ctl_trans_id(app_bt_device.avrcp_channel[BT_DEVICE_ID_1], trans_id); } void app_bt_set_mobile_a2dp_stream(uint32_t deviceId,a2dp_stream_t *stream) { bt_profile_manager[deviceId].stream = stream; } #if defined(IBRT) #if defined(ENHANCED_STACK) uint32_t app_bt_save_spp_app_ctx(uint32_t app_id,btif_remote_device_t *rem_dev, uint8_t *buf, uint32_t buf_len) { bt_bdaddr_t *remote = NULL; uint32_t offset = 0; struct spp_device *device = (struct spp_device *)btif_spp_get_device(app_id); ASSERT(device, "%s NULL spp device app_id=0x%x",__func__, app_id); // save app_id buf[offset++] = app_id & 0xFF; buf[offset++] = (app_id >> 8) & 0xFF; buf[offset++] = (app_id >> 16) & 0xFF; buf[offset++] = (app_id >> 24) & 0xFF; // save port type buf[offset++] = device->portType; //save remote address remote = btif_me_get_remote_device_bdaddr(rem_dev); memcpy(buf+offset, remote, sizeof(bt_bdaddr_t)); offset += sizeof(bt_bdaddr_t); //TRACE(7,"%s:%02x:%02x:%02x:%02x:%02x:%02x\r\n", // __func__, remote->addr[5], remote->addr[4], remote->addr[3], // remote->addr[2], remote->addr[1], remote->addr[0]); //spp device buf[offset++] = device->spp_connected_flag; return offset; } uint32_t app_bt_restore_spp_app_ctx(uint8_t *buf, uint32_t buf_len, uint32_t app_id) { bt_bdaddr_t remote; uint32_t offset = 0; struct spp_device *device = NULL; uint8_t i = 0; uint8_t port_type = 0; uint32_t app_id_restore = 0; // restore app_id for (i=0; i<4; i++) { app_id_restore += (buf[offset+i]<<(8*i)); } offset += 4; port_type = buf[offset++]; ASSERT(app_id_restore == app_id,"%s,spp app id mismatch=%x,%x",__func__,app_id_restore,app_id); // restore remote address memcpy(&remote, buf+offset, sizeof(remote)); offset += sizeof(remote); device = (struct spp_device *)btif_spp_get_device(app_id); #ifdef __INTERCONNECTION__ TRACE(1,"%s,%x,%x,%x", __func__,app_id,BTIF_APP_SPP_CLIENT_CCMP_ID,BTIF_APP_SPP_CLIENT_RED_ID); #endif if (device == NULL) { /* * SPP client device may not be created in bt host initialized stage,so IBRT SLAVE will restore it */ if (port_type == BTIF_SPP_CLIENT_PORT) { TRACE(1,"%s,spp client device null", __func__); switch (app_id) { #ifdef __INTERCONNECTION__ case BTIF_APP_SPP_CLIENT_CCMP_ID: app_ccmp_client_open((uint8_t *)SppServiceSearchReq, app_interconnection_get_length(), 0, 1); device = (struct spp_device *)btif_spp_get_device(BTIF_APP_SPP_CLIENT_CCMP_ID); device->spp_callback = ccmp_callback; //device->_channel = chnl; //restore in btif_spp_profile_restore_ctx device->sppUsedFlag = 1; break; case BTIF_APP_SPP_CLIENT_RED_ID: app_spp_client_open((uint8_t*)SppServiceSearchReq, app_interconnection_get_length(),1); device = (struct spp_device *)btif_spp_get_device(BTIF_APP_SPP_CLIENT_RED_ID); device->spp_callback = spp_client_callback; //device->_channel = chnl; //restore in btif_spp_profile_restore_ctx device->sppUsedFlag = 1; break; #endif default: ASSERT(device, "%s NULL spp client device app_id=0x%x", __func__, app_id); break; } } else { ASSERT(device, "%s NULL spp server device app_id=0x%x", __func__, app_id); } } #ifdef __INTERCONNECTION__ if (app_id == BTIF_APP_SPP_CLIENT_RED_ID) { //btm_conn will NULL if only SPP profile since btm_conn restore later app_bt_set_spp_device_ptr((btif_remote_device_t *)btif_me_get_remote_device_by_bdaddr(&remote)); } #endif //restore spp device device->portType = port_type; device->spp_connected_flag = buf[offset++]; return offset; } uint32_t app_bt_save_hfp_app_ctx(btif_remote_device_t *rem_dev, uint8_t *buf, uint32_t buf_len) { BTIF_CTX_INIT(buf); BTIF_CTX_STR_BUF(btif_me_get_remote_device_bdaddr(rem_dev), BTIF_BD_ADDR_SIZE); BTIF_CTX_STR_VAL8(app_bt_device.hfchan_call[BT_DEVICE_ID_1]); BTIF_CTX_STR_VAL8(app_bt_device.hfchan_callSetup[BT_DEVICE_ID_1]); BTIF_CTX_STR_VAL8(app_bt_device.hf_callheld[BT_DEVICE_ID_1]); BTIF_CTX_SAVE_UPDATE_DATA_LEN(); return BTIF_CTX_GET_TOTAL_LEN(); } uint32_t app_bt_restore_hfp_app_ctx(uint8_t *buf, uint32_t buf_len) { bt_bdaddr_t remote; uint8_t call, callsetup, callheld; BTIF_CTX_INIT(buf); BTIF_CTX_LDR_BUF(&remote, BTIF_BD_ADDR_SIZE); BTIF_CTX_LDR_VAL8(call); BTIF_CTX_LDR_VAL8(callsetup); BTIF_CTX_LDR_VAL8(callheld); app_bt_device.hfchan_call[BT_DEVICE_ID_1] = call; app_bt_device.hfchan_callSetup[BT_DEVICE_ID_1] = callsetup; app_bt_device.hf_callheld[BT_DEVICE_ID_1] = callheld; TRACE(4,"%s call %d callsetup %d callheld %d", __func__, call, callsetup, callheld); return BTIF_CTX_GET_TOTAL_LEN(); } uint32_t app_bt_save_a2dp_app_ctx(btif_remote_device_t *rem_dev, uint8_t *buf, uint32_t buf_len) { uint32_t offset = 0; unsigned char stream_enc = 0; uint32_t factor = 0; // TODO // more codecs, BT_DEVICE_ID_2 if (bt_profile_manager[BT_DEVICE_ID_1].stream == app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream) { stream_enc = 0; } #if defined(A2DP_AAC_ON) else if (bt_profile_manager[BT_DEVICE_ID_1].stream == app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream) { stream_enc = 1; } #endif #if defined(A2DP_LHDC_ON) else if (bt_profile_manager[BT_DEVICE_ID_1].stream == app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_1]->a2dp_stream) { stream_enc = 2; } #endif #if defined(A2DP_LDAC_ON) else if (bt_profile_manager[BT_DEVICE_ID_1].stream == app_bt_device.a2dp_ldac_stream[BT_DEVICE_ID_1]->a2dp_stream) { stream_enc = 2; } #endif buf[offset++] = stream_enc; memcpy(buf+offset,btif_me_get_remote_device_bdaddr(rem_dev),BTIF_BD_ADDR_SIZE); offset += BTIF_BD_ADDR_SIZE; buf[offset++] = app_bt_device.a2dp_state[BT_DEVICE_ID_1]; buf[offset++] = app_bt_device.a2dp_play_pause_flag; buf[offset++] = avrcp_get_media_status(); //codec buf[offset++] = app_bt_device.codec_type[BT_DEVICE_ID_1]; buf[offset++] = app_bt_device.sample_rate[BT_DEVICE_ID_1]; buf[offset++] = app_bt_device.sample_bit[BT_DEVICE_ID_1]; #if defined(A2DP_LHDC_ON) buf[offset++] = app_bt_device.a2dp_lhdc_llc[BT_DEVICE_ID_1]; #endif #if defined(__A2DP_AVDTP_CP__) buf[offset++] = app_bt_device.avdtp_cp[BT_DEVICE_ID_1]; #endif //volume buf[offset++] = (uint8_t)a2dp_volume_get(BT_DEVICE_ID_1); //latency factor factor = (uint32_t)a2dp_audio_latency_factor_get(); buf[offset++] = factor & 0xFF; buf[offset++] = (factor >> 8) & 0xFF; buf[offset++] = (factor >> 16) & 0xFF; buf[offset++] = (factor >> 24) & 0xFF; //a2dp session buf[offset++] = a2dp_ibrt_session_get() & 0xFF; buf[offset++] = (a2dp_ibrt_session_get() >> 8) & 0xFF; buf[offset++] = (a2dp_ibrt_session_get() >> 16) & 0xFF; buf[offset++] = (a2dp_ibrt_session_get() >> 24) & 0xFF; return offset; } uint32_t app_bt_restore_a2dp_app_ctx(uint8_t *buf, uint32_t buf_len) { uint32_t offset = 0; bt_bdaddr_t remote; unsigned char stream_enc = 0; stream_enc = buf[offset++]; memcpy(&remote,buf+offset,BTIF_BD_ADDR_SIZE); offset += BTIF_BD_ADDR_SIZE; app_bt_device.a2dp_state[BT_DEVICE_ID_1] = buf[offset++]; app_bt_device.a2dp_play_pause_flag = buf[offset++]; avrcp_set_media_status(buf[offset++]); //codec info app_bt_device.codec_type[BT_DEVICE_ID_1] = buf[offset++]; app_bt_device.sample_rate[BT_DEVICE_ID_1] = buf[offset++]; app_bt_device.sample_bit[BT_DEVICE_ID_1] = buf[offset++]; #if defined(A2DP_LHDC_ON) app_bt_device.a2dp_lhdc_llc[BT_DEVICE_ID_1] = buf[offset++]; #endif #if defined(__A2DP_AVDTP_CP__) app_bt_device.avdtp_cp[BT_DEVICE_ID_1] = buf[offset++]; #endif //volume a2dp_volume_set(BT_DEVICE_ID_1, buf[offset++]); //latency factor a2dp_audio_latency_factor_set((float)(buf[offset] + (buf[offset+1] << 8) + (buf[offset+2] << 16) + (buf[offset+3] << 24))); offset += 4; //a2dp session a2dp_ibrt_session_set((buf[offset] + (buf[offset+1] << 8) + (buf[offset+2] << 16) + (buf[offset+3] << 24))); offset += 4; // TODO // more codecs, BT_DEVICE_ID_2 if (stream_enc == 0) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream; } #if defined(A2DP_AAC_ON) else if (stream_enc == 1) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream; } #endif #if defined(A2DP_LHDC_ON) else if (stream_enc == 2) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_1]->a2dp_stream; } #endif #if defined(A2DP_LDAC_ON) else if (stream_enc == 2) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_ldac_stream[BT_DEVICE_ID_1]->a2dp_stream; } #endif memcpy(bt_profile_manager[BT_DEVICE_ID_1].rmt_addr.address, &remote, BTIF_BD_ADDR_SIZE); bt_profile_manager[BT_DEVICE_ID_1].a2dp_connect = bt_profile_connect_status_success; bt_profile_manager[BT_DEVICE_ID_1].hfp_connect = bt_profile_connect_status_success; bt_profile_manager[BT_DEVICE_ID_1].has_connected = true; return offset; } uint32_t app_bt_save_avrcp_app_ctx(btif_remote_device_t *rem_dev, uint8_t *buf, uint32_t buf_len) { uint32_t offset = 0; buf[offset++] = app_bt_device.avrcp_state[BT_DEVICE_ID_1]; buf[offset++] = app_bt_device.volume_report[BT_DEVICE_ID_1]; if (app_bt_device.avrcp_notify_rsp[BT_DEVICE_ID_1]) { buf[offset++] = true; buf[offset++] = app_bt_avrcp_get_notify_trans_id(); } else { buf[offset++] = false; buf[offset++] = 0; } return offset; } uint32_t app_bt_restore_avrcp_app_ctx(uint8_t *buf, uint32_t buf_len) { uint32_t offset = 0; uint8_t notify_rsp_exist = 0; uint8_t trans_id = 0; app_bt_device.avrcp_state[BT_DEVICE_ID_1] = buf[offset++]; app_bt_device.volume_report[BT_DEVICE_ID_1] = buf[offset++]; notify_rsp_exist = buf[offset++]; trans_id = buf[offset++]; TRACE(4,"app_bt_restore_avrcp_app_ctx state %d report %d notify %d %d\n", app_bt_device.avrcp_state[BT_DEVICE_ID_1], app_bt_device.volume_report[BT_DEVICE_ID_1], notify_rsp_exist, trans_id); if (notify_rsp_exist && app_bt_device.avrcp_notify_rsp[BT_DEVICE_ID_1] == NULL) { btif_app_a2dp_avrcpadvancedpdu_mempool_calloc(&app_bt_device.avrcp_notify_rsp[BT_DEVICE_ID_1]); } app_bt_avrcp_set_notify_trans_id(trans_id); return offset; } #ifdef __BTMAP_ENABLE__ uint32_t app_bt_save_map_app_ctx(btif_remote_device_t *rem_dev, uint8_t *buf, uint32_t buf_len) { //struct bdaddr_t *remote = NULL; uint32_t offset = 0; memcpy((void *)buf, (void *)app_bt_device.map_session_handle, sizeof(app_bt_device.map_session_handle)); offset += sizeof(app_bt_device.map_session_handle); return offset; } uint32_t app_bt_restore_map_app_ctx(uint8_t *buf, uint32_t buf_len) { uint32_t offset = 0; memcpy((void *)app_bt_device.map_session_handle, (void *)buf, sizeof(btif_map_session_handle_t)); offset += sizeof(btif_map_session_handle_t); return offset; } #endif #if BTIF_HID_DEVICE uint32_t app_bt_save_hid_app_ctx(uint8_t *buf) { uint32_t offset = 0; if(app_bt_device.hid_channel == NULL) { TRACE(0, "app_bt_save_hid_app_ctx app_bt_device.hid_channel is NULL"); return offset; } memcpy((void *)buf, (void *)app_bt_device.hid_channel, sizeof(app_bt_device.hid_channel)); offset += sizeof(app_bt_device.hid_channel); return offset; } uint32_t app_bt_restore_hid_app_ctx(uint8_t *buf) { uint32_t offset = 0; memcpy((void *)app_bt_device.hid_channel, (void *)buf, sizeof(hid_channel_t)); offset += sizeof(hid_channel_t); return offset; } #endif #endif /* ENHANCED_STACK */ a2dp_stream_t * app_bt_get_mobile_a2dp_stream(uint32_t deviceId) { return bt_profile_manager[deviceId].stream; } void app_bt_update_bt_profile_manager(void) { ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); memcpy(bt_profile_manager[BT_DEVICE_ID_1].rmt_addr.address, p_ibrt_ctrl->mobile_addr.address, BTIF_BD_ADDR_SIZE); #if defined(A2DP_AAC_ON) if(p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif #if defined(A2DP_SCALABLE_ON) if (p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif #if defined(A2DP_LHDC_ON) if (p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif #if defined(A2DP_LDAC_ON) if (p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_ldac_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif if (p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_SBC) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream; } else { ASSERT(0, "%s err codec_type:%d ", __func__, p_ibrt_ctrl->a2dp_codec.codec_type); } bt_profile_manager[BT_DEVICE_ID_1].a2dp_connect = bt_profile_connect_status_success; bt_profile_manager[BT_DEVICE_ID_1].hfp_connect = bt_profile_connect_status_success; bt_profile_manager[BT_DEVICE_ID_1].has_connected = true; TRACE(3,"%s codec_type:%x if_a2dp_stream:%p", __func__, p_ibrt_ctrl->a2dp_codec.codec_type, bt_profile_manager[BT_DEVICE_ID_1].stream); DUMP8("%02x ", bt_profile_manager[BT_DEVICE_ID_1].rmt_addr.address, BTIF_BD_ADDR_SIZE); } void app_bt_update_bt_profile_manager_codec_type(uint8_t codec_type) { ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); p_ibrt_ctrl->a2dp_codec.codec_type = codec_type; #if defined(A2DP_AAC_ON) if(p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif #if defined(A2DP_SCALABLE_ON) if (p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif #if defined(A2DP_LHDC_ON) if (p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif #if defined(A2DP_LDAC_ON) if (p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_ldac_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif if (p_ibrt_ctrl->a2dp_codec.codec_type == BTIF_AVDTP_CODEC_TYPE_SBC) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream; } else { ASSERT(0, "%s err codec_type:%d ", __func__, p_ibrt_ctrl->a2dp_codec.codec_type); } bt_profile_manager[BT_DEVICE_ID_1].a2dp_connect = bt_profile_connect_status_success; bt_profile_manager[BT_DEVICE_ID_1].hfp_connect = bt_profile_connect_status_success; bt_profile_manager[BT_DEVICE_ID_1].has_connected = true; TRACE(3,"%s codec_type:%x if_a2dp_stream:%p", __func__, p_ibrt_ctrl->a2dp_codec.codec_type, bt_profile_manager[BT_DEVICE_ID_1].stream); } static bool ibrt_reconnect_mobile_profile_flag = false; void app_bt_ibrt_reconnect_mobile_profile_flag_set(void) { ibrt_reconnect_mobile_profile_flag = true; } void app_bt_ibrt_reconnect_mobile_profile_flag_clear(void) { ibrt_reconnect_mobile_profile_flag = false; } bool app_bt_ibrt_reconnect_mobile_profile_flag_get(void) { return ibrt_reconnect_mobile_profile_flag; } void app_bt_ibrt_reconnect_mobile_profile(bt_bdaddr_t mobile_addr) { nvrec_btdevicerecord *mobile_record = NULL; bt_profile_manager[BT_DEVICE_ID_1].reconnect_mode = bt_profile_reconnect_null; bt_profile_manager[BT_DEVICE_ID_1].rmt_addr = mobile_addr; bt_profile_manager[BT_DEVICE_ID_1].chan = app_bt_device.hf_channel[BT_DEVICE_ID_1]; if (!nv_record_btdevicerecord_find(&mobile_addr, &mobile_record)) { #if defined(A2DP_AAC_ON) if(mobile_record->device_plf.a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_aac_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif #if defined(A2DP_SCALABLE_ON) if(mobile_record->device_plf.a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_scalable_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif #if defined(A2DP_LHDC_ON) if(mobile_record->device_plf.a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_lhdc_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif #if defined(A2DP_LDAC_ON) if(mobile_record->device_plf.a2dp_codectype == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_ldac_stream[BT_DEVICE_ID_1]->a2dp_stream; } else #endif { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream; } } else { bt_profile_manager[BT_DEVICE_ID_1].stream = app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream;//default using SBC } btif_a2dp_reset_stream_state(bt_profile_manager[BT_DEVICE_ID_1].stream); TRACE(0,"ibrt_ui_log:start reconnect mobile, addr below:"); DUMP8("0x%02x ",&(mobile_addr.address[0]),BTIF_BD_ADDR_SIZE); app_bt_ibrt_reconnect_mobile_profile_flag_set(); app_bt_precheck_before_starting_connecting(bt_profile_manager[BT_DEVICE_ID_1].has_connected); app_ibrt_ui_t *p_ibrt_ui = app_ibrt_ui_get_ctx(); if (p_ibrt_ui->config.profile_concurrency_supported) { app_bt_A2DP_OpenStream(bt_profile_manager[BT_DEVICE_ID_1].stream, &(bt_profile_manager[BT_DEVICE_ID_1].rmt_addr)); app_bt_HF_CreateServiceLink(bt_profile_manager[BT_DEVICE_ID_1].chan, &(bt_profile_manager[BT_DEVICE_ID_1].rmt_addr)); } else { app_bt_A2DP_OpenStream(bt_profile_manager[BT_DEVICE_ID_1].stream, &(bt_profile_manager[BT_DEVICE_ID_1].rmt_addr)); //app_bt_HF_CreateServiceLink(bt_profile_manager[BT_DEVICE_ID_1].chan, &(bt_profile_manager[BT_DEVICE_ID_1].rmt_addr)); } //osTimerStart(bt_profile_manager[BT_DEVICE_ID_1].connect_timer, APP_IBRT_RECONNECT_TIMEOUT_MS); } #endif #ifdef __IAG_BLE_INCLUDE__ static void app_start_fast_connectable_ble_adv(uint16_t advInterval) { bool ret = FALSE; if (NULL == app_fast_ble_adv_timeout_timer) { app_fast_ble_adv_timeout_timer = osTimerCreate(osTimer(APP_FAST_BLE_ADV_TIMEOUT_TIMER), osTimerOnce, NULL); } osTimerStart(app_fast_ble_adv_timeout_timer, APP_FAST_BLE_ADV_TIMEOUT_IN_MS); #ifdef IBRT ret = app_ibrt_ui_get_snoop_via_ble_enable(); #endif if (FALSE == ret) { app_ble_start_connectable_adv(advInterval); } } static int app_fast_ble_adv_timeout_timehandler(void const *param) { bool ret = FALSE; #ifdef IBRT ret = app_ibrt_ui_get_snoop_via_ble_enable(); #endif if (FALSE == ret) { app_ble_refresh_adv_state(BLE_ADVERTISING_INTERVAL); } return 0; } void app_stop_fast_connectable_ble_adv_timer(void) { if (NULL != app_fast_ble_adv_timeout_timer) { osTimerStop(app_fast_ble_adv_timeout_timer); } } #endif static uint32_t bt_link_active_mode_bits[MAX_ACTIVE_MODE_MANAGED_LINKS]; void app_bt_active_mode_manager_init(void) { memset(bt_link_active_mode_bits, 0, sizeof(bt_link_active_mode_bits)); } void app_bt_active_mode_reset(uint32_t linkIndex) { bt_link_active_mode_bits[linkIndex] = 0; } void app_bt_active_mode_set(BT_LINK_ACTIVE_MODE_KEEPER_USER_E user, uint32_t linkIndex) { #if defined(IBRT) return; #endif bool isAlreadyInActiveMode = false; if (linkIndex < MAX_ACTIVE_MODE_MANAGED_LINKS) { uint32_t lock = int_lock_global(); if (bt_link_active_mode_bits[linkIndex] > 0) { isAlreadyInActiveMode = true; } else { isAlreadyInActiveMode = false; } bt_link_active_mode_bits[linkIndex] |= (1 << user); int_unlock_global(lock); if (!isAlreadyInActiveMode) { app_bt_stop_sniff(linkIndex); app_bt_stay_active(linkIndex); } } else if (MAX_ACTIVE_MODE_MANAGED_LINKS == linkIndex) { for (uint8_t devId = 0; devId < BT_DEVICE_NUM; devId++) { uint32_t lock = int_lock_global(); if (bt_link_active_mode_bits[devId] > 0) { isAlreadyInActiveMode = true; } else { isAlreadyInActiveMode = false; } bt_link_active_mode_bits[devId] |= (1 << user); int_unlock_global(lock); if (!isAlreadyInActiveMode) { app_bt_stop_sniff(devId); app_bt_stay_active(devId); } } } TRACE(2,"set active mode for user %d, link %d, now state:", user, linkIndex); DUMP32("%08x", bt_link_active_mode_bits, MAX_ACTIVE_MODE_MANAGED_LINKS); } void app_bt_active_mode_clear(BT_LINK_ACTIVE_MODE_KEEPER_USER_E user, uint32_t linkIndex) { #if defined(IBRT) return; #endif bool isAlreadyAllowSniff = false; if (linkIndex < MAX_ACTIVE_MODE_MANAGED_LINKS) { uint32_t lock = int_lock_global(); if (0 == bt_link_active_mode_bits[linkIndex]) { isAlreadyAllowSniff = true; } else { isAlreadyAllowSniff = false; } bt_link_active_mode_bits[linkIndex] &= (~(1 << user)); int_unlock_global(lock); if (!isAlreadyAllowSniff) { app_bt_allow_sniff(linkIndex); } } else if (MAX_ACTIVE_MODE_MANAGED_LINKS == linkIndex) { for (uint8_t devId = 0; devId < BT_DEVICE_NUM; devId++) { uint32_t lock = int_lock_global(); if (0 == bt_link_active_mode_bits[devId]) { isAlreadyAllowSniff = true; } else { isAlreadyAllowSniff = false; } bt_link_active_mode_bits[devId] &= (~(1 << user)); int_unlock_global(lock); if (!isAlreadyAllowSniff) { app_bt_allow_sniff(devId); } } } TRACE(2,"clear active mode for user %d, link %d, now state:", user, linkIndex); DUMP32("%08x ", bt_link_active_mode_bits, MAX_ACTIVE_MODE_MANAGED_LINKS); } int8_t app_bt_get_rssi(void) { int8_t rssi=127; uint8_t i; btif_remote_device_t *remDev = NULL; rx_agc_t tws_agc = {0}; for (i=0; iconfig.disable_tws_switch = true;//disable role switch app_key_close(); if(IBRT_MASTER == app_tws_ibrt_role_get_callback(NULL)){ btif_hf_disconnect_service_link(app_bt_device.hf_channel[BT_DEVICE_ID_1]); btif_a2dp_suspend_stream(app_bt_device.a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream); } TRACE(0,"app_bt_prepare_for_ota"); } #endif