/************************************************************* 此文件函数主要是蓝牙模式各种状态处理 void app_bt_task() bt模式主函数 static int bt_sys_event_handler(struct sys_event *event) bt模式系统事件所有处理入口 static void bt_task_close(void) bt模式退出 void bt_function_select_init() 蓝牙功能配置 void bredr_handle_register() 蓝牙协议栈回调函数 static int bt_connction_status_event_handler(struct bt_event *bt) 蓝牙状态事件处理函数 static int bt_hci_event_handler(struct bt_event *bt) 蓝牙协议栈事件回调,app处理函数 static int bt_ai_event_handler(struct bt_event *bt) 蓝牙ai事件处理函数 int bt_background_event_handler_filter(struct sys_event *event) 蓝牙后台事件过滤处理 int bt_background_event_handler(struct sys_event *event) 蓝牙后台事件处理函数 int bt_key_event_handler(struct sys_event *event) 蓝牙按键处理函数 avctp_user.h 有蓝牙支持的命令介绍 **************************************************************/ #include "system/includes.h" #include "media/includes.h" #include "app_config.h" #include "app_task.h" #include "btstack/avctp_user.h" #include "btstack/btstack_task.h" #include "btstack/bluetooth.h" #include "btstack/btstack_error.h" #include "btctrler/btctrler_task.h" #include "classic/hci_lmp.h" #include "bt/bt_tws.h" #include "bt/bt_ble.h" #include "bt/bt.h" #include "bt/vol_sync.h" #include "bt/bt_emitter.h" #include "bt_common.h" #include "aec_user.h" #include "math.h" #include "spp_user.h" #include "app_protocol_common.h" #include "app_chargestore.h" #include "app_charge.h" #include "app_main.h" #include "app_power_manage.h" #include "user_cfg.h" #include "asm/pwm_led.h" #include "asm/timer.h" #include "asm/hwi.h" #include "cpu.h" #include "ui/ui_api.h" #include "ui_manage.h" #include "ui/ui_style.h" #include "key_event_deal.h" #include "clock_cfg.h" #include "gSensor/gSensor_manage.h" #include "soundcard/soundcard.h" #include "audio_dec.h" #include "tone_player.h" #include "dac.h" #include "soundbox.h" #include "le_client_demo.h" #include "tuya_multi/tuya_le_multi_common.h" #include "multi_demo/le_multi_common.h" #include "kt.h" #define LOG_TAG_CONST BT #define LOG_TAG "[BT]" #define LOG_ERROR_ENABLE #define LOG_DEBUG_ENABLE #define LOG_INFO_ENABLE #define LOG_DUMP_ENABLE #define LOG_CLI_ENABLE #include "debug.h" #if TCFG_APP_BT_EN struct app_bt_opr app_bt_hdl = { .exit_flag = 1, .replay_tone_flag = 1, .esco_dump_packet = ESCO_DUMP_PACKET_CALL, .hid_mode = 0, .wait_exit = 0, }; #define __this (&app_bt_hdl) BT_USER_PRIV_VAR bt_user_priv_var; static u8 event_conn_complete = 0; void user_avrcp_status_callback(u8 *addr,u8 flag) { //flag = 0 是暂停,1是播放 put_buf(addr,6); } #if BT_EMITTER_TEST_ENABLE u8 ag_at_cmd_all_by_user(u8 *packet, u16 size)//奇祥在用 { /* ATCMD_CMD_CHUP: 挂断 14 */ /* ATCMD_CMD_BLDN: 回拨 7 */ /* ATCMD_CMD_ATD: 来电 2 */ #if (!NORM_VERSION) u8 rsp_buf[64] = {0}; int rsp_len = 0; put_buf(packet, size); g_printf("[%d]>>>>>>>>>>>>>>>>>>>>---atcmd start------%s -- %d\n", size, packet, get_call_status()); if (0 == strncmp("AT+BLDN", packet, 7)) { // g_printf(">>>>>>>>>>>>>>>>>+++++++%s\n", packet); // at_serv_opr_t * at_opr = at_server_get_opr(); // at_opr->rsp_hfreq_state(1); // at_opr->rsp_hfp_incoming_state(1); rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); log_i("[%s]: %d\n", __FUNCTION__, ret); return 1; }else if (0 == strncmp("AT+CHUP", packet, 7)) { // g_printf(">>>>>>>>>>>>>>>>>-------%s\n", packet); // at_serv_opr_t * at_opr = at_server_get_opr(); // at_opr->rsp_hfreq_state(0); // at_opr->rsp_hfp_incoming_state(0); rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); log_i("[%s]: %d\n", __FUNCTION__, ret); return 1; }else if (0 == strncmp("AT+ATD", packet, 6)) { // g_printf(">>>>>>>>>>>>>>>>>88888888%s\n", packet); rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); log_i("[%s]: %d\n", __FUNCTION__, ret); return 1; } else if (0 == strncmp("AT+CLCC", packet, 7)) { // g_printf(">>>>>>>>>>>>>>>>>555555%s\n", packet); if (get_call_status() == BT_CALL_ACTIVE) { rsp_len = sprintf(rsp_buf, "\r\n+CLCC: 1,0,0,0,0,\" \",129\r\n"); u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); log_i("[%s]: %d\n", __FUNCTION__, ret); memset(rsp_buf, 0, sizeof(rsp_buf)); rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); log_i("[%s]: %d\n", __FUNCTION__, ret); }else { rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); log_i("[%s]: %d\n", __FUNCTION__, ret); } return 1; } // else if(0 == strncmp("AT+BRSF=", packet, 8)) // { // line_inf // printf("[%s]: %s\n"); // rsp_len = sprintf(rsp_buf, "\r\n+BRSF: 2052\r\n"); // int ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); // log_i("[%s]: %d\n", rsp_buf, ret); // memset(rsp_buf, 0, sizeof(rsp_buf)); // rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); // ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); // log_i("[%s]: %d\n", rsp_buf, ret); // return 1; // } return 0; // const at_serv_opr_t * at_opr = at_server_get_opr(); // for (size_t i = 0; i < size + 1; i++) // { // if (i == size) // { // at_opr->parse_cmd_hendle('\n', user_send_at_cmd_prepare); // }else // { // at_opr->parse_cmd_hendle(packet[i], user_send_at_cmd_prepare); // } // } // g_printf(">>>>>>>>>>>>>>>>>>>>>---atcmd end-----[%d]\n", at_opr->get_ignore_flag()); // return at_opr->get_ignore_flag(); #else g_printf("---atcmd-----[%d]\n", parse_atcmd_type); switch (parse_atcmd_type) { case 2:/* ATCMD_CMD_ATD: 来电 2 */ { // at_serv_opr_t * at_opr = at_server_get_opr(); // at_opr->rsp_hfreq_state(0); return 1; } break; case 7:/* ATCMD_CMD_BLDN: 回拨 7 */ { at_serv_opr_t * at_opr = at_server_get_opr(); at_opr->rsp_hfreq_state(1); at_opr->rsp_hfp_incoming_state(1); return 1; } break; case 14:/* ATCMD_CMD_CHUP: 挂断 14 */ { at_serv_opr_t * at_opr = at_server_get_opr(); at_opr->rsp_hfreq_state(0); at_opr->rsp_hfp_incoming_state(0); return 1; } break; default: break; } log_i("---------------no process cmd\n"); return 0; #endif } #else u8 ag_at_cmd_all_by_user(u8 *packet, u16 size) { line_inf put_buf(packet,size); return 0; } #endif u8 user_diy_atcmd_handle(u8 parse_atcmd_type) { #if BT_EMITTER_TEST_ENABLE /* ATCMD_CMD_CHUP: 挂断 14 */ /* ATCMD_CMD_BLDN: 回拨 7 */ /* ATCMD_CMD_ATD: 来电 2 */ g_printf("---atcmd------%d\n", parse_atcmd_type); switch (parse_atcmd_type) { case 2:/* ATCMD_CMD_ATD: 来电 2 */ { return 1; } break; case 7:/* ATCMD_CMD_BLDN: 回拨 7 */ { return 1; } break; case 14:/* ATCMD_CMD_CHUP: 挂断 14 */ { return 1; } break; default: break; } #endif return 0; } //接收数据 int at_cmd_analysis_by_user(u8 *packet,u16 size) { puts(packet); printf("size == %d\n",size); return 0; } void bt_event_status_start_connected(struct bt_event *bt) { if(bt_user_priv_var.auto_connection_timer) { sys_timeout_del(bt_user_priv_var.auto_connection_timer); bt_user_priv_var.auto_connection_timer = 0; } bt_user_priv_var.auto_connection_counter = 0; } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙模式变量初始化 @param 无 @return 无 @note */ /*----------------------------------------------------------------------------*/ void bt_var_init() { memset((u8 *)&bt_user_priv_var, 0, sizeof(BT_USER_PRIV_VAR)); } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙模式协议栈回调函数 @param 无 @return 无 @note */ /*----------------------------------------------------------------------------*/ void bredr_handle_register() { #if (USER_SUPPORT_PROFILE_SPP==1) #if APP_ONLINE_DEBUG extern void online_spp_init(void); spp_data_deal_handle_register(user_spp_data_handler); online_spp_init(); #else spp_data_deal_handle_register(spp_data_handler); #endif #endif #if BT_SUPPORT_MUSIC_VOL_SYNC ///蓝牙音乐和通话音量同步 music_vol_change_handle_register(bt_set_music_device_volume, phone_get_device_vol); #endif #if BT_SUPPORT_DISPLAY_BAT ///电量显示获取电量的接口 get_battery_value_register(bt_get_battery_value); #endif ///被测试盒链接上进入快速测试回调 bt_fast_test_handle_register(bt_fast_test_api); ///样机进入dut被测试仪器链接上回调 bt_dut_test_handle_register(bt_dut_api); ///获取远端设备蓝牙名字回调 read_remote_name_handle_register(bt_read_remote_name); ////获取歌曲信息回调 /* bt_music_info_handle_register(user_get_bt_music_info); */ BT_BREDR_HANDLE_REG(); } #if (TRANS_MULTI_BLE_EN || TUYA_MULTI_BLE_EN) && TRANS_MULTI_BLE_MASTER_NUMS //指定搜索uuid //指定搜索uuid static const target_uuid_t jl_search_uuid_table[] = { // for uuid16 // PRIMARY_SERVICE, ae30 // CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, // CHARACTERISTIC, ae02, NOTIFY, { .services_uuid16 = 0xae30, .characteristic_uuid16 = 0xae01, .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, }, { .services_uuid16 = 0xae30, .characteristic_uuid16 = 0xae02, .opt_type = ATT_PROPERTY_NOTIFY, }, //for uuid128,sample // PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 // CHARACTERISTIC, 0000F531-1212-EFDE-1523-785FEABCD123, NOTIFY, // CHARACTERISTIC, 0000F532-1212-EFDE-1523-785FEABCD123, WRITE_WITHOUT_RESPONSE | DYNAMIC, /* { .services_uuid16 = 0, .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , .characteristic_uuid16 = 0, .characteristic_uuid128 = {0x00,0x00,0xF5,0x31 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, .opt_type = ATT_PROPERTY_NOTIFY, }, { .services_uuid16 = 0, .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , .characteristic_uuid16 = 0, .characteristic_uuid128 = {0x00,0x00,0xF5,0x32 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, }, */ }; static void ble_report_data_deal(att_data_report_t *report_data, target_uuid_t *search_uuid) { log_info("conn_handle:%04x,report_data:%02x,%02x,%d,len(%d)", report_data->conn_handle, report_data->packet_type, report_data->value_handle, report_data->value_offset, report_data->blob_length); log_info_hexdump(report_data->blob, report_data->blob_length); /* if (search_uuid == NULL) { */ /* log_info("not_match handle"); */ /* return; */ /* } */ switch (report_data->packet_type) { case GATT_EVENT_NOTIFICATION: //notify break; case GATT_EVENT_INDICATION://indicate case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read break; case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long break; default: break; } } static struct ble_client_operation_t *ble_client_api; static const u8 test_remoter_name1[] = "AC897N_MX(BLE)";// /* static const u8 test_remoter_name2[] = "AC630N_HID567(BLE)";// */ static u16 ble_client_write_handle; static u16 ble_client_timer = 0; static const client_match_cfg_t match_dev01 = { .create_conn_mode = BIT(CLI_CREAT_BY_NAME), .compare_data_len = sizeof(test_remoter_name1) - 1, //去结束符 .compare_data = test_remoter_name1, .bonding_flag = 0, }; /* static const client_match_cfg_t match_dev02 = { */ /* .create_conn_mode = BIT(CLI_CREAT_BY_NAME), */ /* .compare_data_len = sizeof(test_remoter_name2) - 1, //去结束符 */ /* .compare_data = test_remoter_name2, */ /* .bonding_flag = 1, */ /* }; */ static void client_test_write(void) { static u32 count = 0; int i, ret = 0; u16 tmp_handle; count++; for (i = 0; i < TRANS_MULTI_BLE_MASTER_NUMS; i++) { tmp_handle = mul_dev_get_conn_handle(i, MULTI_ROLE_CLIENT); if (tmp_handle && ble_client_write_handle) { ret = ble_client_api->opt_comm_send_ext(tmp_handle, ble_client_write_handle, &count, 16, ATT_OP_WRITE_WITHOUT_RESPOND); log_info("test_write:%04x,%d", tmp_handle, ret); } } /* int ret = ble_client_api->opt_comm_send(ble_client_write_handle, &count, 16, ATT_OP_WRITE_WITHOUT_RESPOND); */ /* log_info("test_write:%x", ret); */ } static void client_event_callback(le_client_event_e event, u8 *packet, int size) { switch (event) { case CLI_EVENT_MATCH_DEV: { client_match_cfg_t *match_dev = packet; log_info("match_name:%s\n", match_dev->compare_data); } break; case CLI_EVENT_MATCH_UUID: { opt_handle_t *opt_hdl = packet; if (opt_hdl->search_uuid == &jl_search_uuid_table[0]) { ble_client_write_handle = opt_hdl->value_handle; log_info("match_uuid22\n"); } } break; case CLI_EVENT_SEARCH_PROFILE_COMPLETE: log_info("CLI_EVENT_SEARCH_PROFILE_COMPLETE\n"); if ((!ble_client_timer) && ble_client_write_handle) { log_info("test timer_add\n"); ble_client_timer = sys_timer_add(0, client_test_write, 500); } break; case CLI_EVENT_CONNECTED: break; case CLI_EVENT_DISCONNECT: if (ble_client_timer && TRANS_MULTI_BLE_MASTER_NUMS == 1) { sys_timeout_del(ble_client_timer); ble_client_write_handle = 0; ble_client_timer = 0; } break; default: break; } } static const client_conn_cfg_t client_conn_config = { .match_dev_cfg[0] = &match_dev01, .match_dev_cfg[1] = NULL, .match_dev_cfg[2] = NULL, /* .match_dev_cfg[1] = &match_dev02, */ .report_data_callback = ble_report_data_deal, /* .search_uuid_cnt = 0, //配置不搜索profile,加快回连速度 */ .search_uuid_cnt = (sizeof(jl_search_uuid_table) / sizeof(target_uuid_t)), .search_uuid_table = jl_search_uuid_table, .security_en = 0, //支持加密使能,对应配置 config_le_sm_support_enable .event_callback = client_event_callback, }; static void ble_client_config_init(void) { ble_client_api = ble_get_client_operation_table(); ble_client_api->init_config(0, &client_conn_config); /* client_clear_bonding_info();//for test */ } #endif /*----------------------------------------------------------------------------*/ /**@brief 蓝牙模式协议栈功能配置 @param 无 @return 无 @note */ /*----------------------------------------------------------------------------*/ // int set_remove_esco_req_not_accepted_flag = 0; void bt_function_select_init() { // void __set_hfp_ag_res_hangup_flag(bool flag); // __set_hfp_ag_res_hangup_flag(0); set_idle_period_slot(1600); ////设置协议栈支持设备数 __set_user_ctrl_conn_num(TCFG_BD_NUM); ////msbc功能使能 __set_support_msbc_flag(1); set_bt_version(0x09);//修改蓝牙版本 __set_sbc_cap_bitpool(30); #if TCFG_BT_SUPPORT_AAC ////AAC功能使能 __set_support_aac_flag(1); #else __set_support_aac_flag(0); #endif #if BT_SUPPORT_DISPLAY_BAT ////设置更新电池电量的时间间隔 __bt_set_update_battery_time(60); #else __bt_set_update_battery_time(0); #endif ////回连搜索时间长度设置,可使用该函数注册使用,ms单位,u16 __set_page_timeout_value(8000); ////回连时超时参数设置。ms单位。做主机有效 __set_super_timeout_value(8000); #if (TCFG_BD_NUM == 2) ////设置开机回链的设备个数 __set_auto_conn_device_num(2); #endif #if (TCFG_SPI_LCD_ENABLE) #if TCFG_USER_EMITTER_ENABLE//带有屏幕的方案根据UI选项连接 ////设置开机回链的设备个数 __set_auto_conn_device_num(10);//彩屏方案支持10个设备的连接 #endif #endif #if BT_SUPPORT_MUSIC_VOL_SYNC ////设置音乐音量同步的表 vol_sys_tab_init(); #endif ////设置蓝牙是否跑后台 __set_user_background_goback(BACKGROUND_GOBACK); // 后台链接是否跳回蓝牙 1:跳回 ////设置蓝牙加密的level //io_capabilities ; /*0: Display only 1: Display YesNo 2: KeyboardOnly 3: NoInputNoOutput*/ //authentication_requirements: 0:not protect 1 :protect //flym 20251014 20:12:00 // 修改为Just Works配对模式,避免配对码出现 __set_simple_pair_param(3, 0, 0);//__set_simple_pair_param(3, 0, 2); #if (USER_SUPPORT_PROFILE_PBAP==1) ////设置蓝牙设备类型 __change_hci_class_type(BD_CLASS_CAR_AUDIO); #endif __change_hci_class_type(BD_CLASS_SMART_PHONE_2); #if (TCFG_BT_SNIFF_ENABLE == 0) void lmp_set_sniff_disable(void); lmp_set_sniff_disable(); #endif /* TX RX AI800x PA13 PA12 AC692x PA13 PA12 AC693x PA8 PA9 AC695x PA9 PA10 AC696x PA9 PA10 AC694x PB1 PB2 AC697x PC2 PC3 AC631x PA7 PA8 */ ////设置蓝牙接收状态io输出,可以外接pa /* bt_set_rxtx_status_enable(1); */ #if TCFG_USER_BLE_ENABLE { u8 tmp_ble_addr[6]; #if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV \ || TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_GMA) /* bt_set_tx_power(9);//ble txpwer level:0~9 */ memcpy(tmp_ble_addr, (void *)bt_get_mac_addr(), 6); #else lib_make_ble_address(tmp_ble_addr, (void *)bt_get_mac_addr()); #endif // le_controller_set_mac((void *)tmp_ble_addr); printf("\n-----edr + ble 's address-----"); printf_buf((void *)bt_get_mac_addr(), 6); printf_buf((void *)tmp_ble_addr, 6); } #if (TRANS_MULTI_BLE_EN || TUYA_MULTI_BLE_EN) && TRANS_MULTI_BLE_MASTER_NUMS ble_client_config_init(); #endif #endif // TCFG_USER_BLE_ENABLE #if (CONFIG_BT_MODE != BT_NORMAL) set_bt_enhanced_power_control(1); #endif } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙模式协议栈对应状态处理函数 @param bt:事件 @return @note 蓝牙初始化完成、链接、通话播歌等状态 */ /*----------------------------------------------------------------------------*/ static int bt_connction_status_event_handler(struct bt_event *bt) { log_debug("-----------------------bt_connction_status_event_handler %d", bt->event); if (bt_status_event_filter(bt) == false) { return false; } switch (bt->event) { case BT_STATUS_EXIT_OK: log_info("BT_STATUS_EXIT_OK\n"); break; case BT_STATUS_INIT_OK: log_info("BT_STATUS_INIT_OK\n"); bt_status_init_ok(bt); #if(TCFG_TEST_BOX_ENABLE || TCFG_CHARGESTORE_ENABLE) chargestore_set_bt_init_ok(1); #endif break; case BT_STATUS_START_CONNECTED: log_info(" BT_STATUS_START_CONNECTED\n"); #if CONFIG_TWS_DISCONN_NO_RECONN extern u8 tws_detach_by_remove_key; tws_detach_by_remove_key = 0; #endif if(bt_emitter_role_get() == BT_EMITTER_EN) { bt_event_status_start_connected(bt); } break; case BT_STATUS_ENCRY_COMPLETE: log_info(" BT_STATUS_ENCRY_COMPLETE\n"); #ifdef CONFIG_DEBUG_ENABLE extern u8 *get_last_device_connect_linkkey(u16 *len); u8 *test_linkkey; u16 test_linkkey_len = 16; test_linkkey = get_last_device_connect_linkkey(&test_linkkey_len); if(test_linkkey){ printf("test_linkkey================\n"); put_buf(test_linkkey, test_linkkey_len); } #endif break; case BT_STATUS_SECOND_CONNECTED: log_info(" BT_STATUS_SECOND_CONNECTED\n"); clear_current_poweron_memory_search_index(0); case BT_STATUS_FIRST_CONNECTED: log_info("BT_STATUS_CONNECTED\n"); bt_status_connect(bt); break; case BT_STATUS_FIRST_DISCONNECT: case BT_STATUS_SECOND_DISCONNECT: log_info(" BT_STATUS_SECOND_DISCONNECT\n"); bt_status_disconnect(bt); break; case BT_STATUS_PHONE_INCOME: log_info("BT_STATUS_PHONE_INCOME\n"); bt_status_phone_income(bt); break; case BT_STATUS_PHONE_OUT: log_info("BT_STATUS_PHONE_OUT\n"); bt_status_phone_out(bt); break; case BT_STATUS_PHONE_ACTIVE: log_info("BT_STATUS_PHONE_ACTIVE\n"); bt_status_phone_active(bt); break; case BT_STATUS_PHONE_HANGUP: log_info(" BT_STATUS_PHONE_HANGUP\n"); bt_status_phone_hangup(bt); break; case BT_STATUS_PHONE_NUMBER: log_info("BT_STATUS_PHONE_NUMBER\n"); bt_status_phone_number(bt); break; case BT_STATUS_INBAND_RINGTONE: log_info("BT_STATUS_INBAND_RINGTONE\n"); bt_status_inband_ringtone(bt); break; case BT_STATUS_BEGIN_AUTO_CON: log_info("BT_STATUS_BEGIN_AUTO_CON\n"); break; case BT_STATUS_A2DP_MEDIA_START: log_info(" BT_STATUS_A2DP_MEDIA_START\n"); bt_status_a2dp_media_start(bt); break; case BT_STATUS_A2DP_MEDIA_STOP: log_info(" BT_STATUS_A2DP_MEDIA_STOP"); bt_status_a2dp_media_stop(bt); break; case BT_STATUS_SCO_STATUS_CHANGE: log_info(" BT_STATUS_SCO_STATUS_CHANGE"); bt_status_sco_change(bt); break; case BT_STATUS_CALL_VOL_CHANGE: log_info(" BT_STATUS_CALL_VOL_CHANGE "); bt_status_call_vol_change(bt); break; case BT_STATUS_SNIFF_STATE_UPDATE: log_info(" BT_STATUS_SNIFF_STATE_UPDATE \n"); //0退出SNIFF bt_status_sniff_state_update(bt); break; case BT_STATUS_LAST_CALL_TYPE_CHANGE: log_info("BT_STATUS_LAST_CALL_TYPE_CHANGE\n"); bt_status_last_call_type_change(bt); break; case BT_STATUS_CONN_A2DP_CH: bt_status_conn_a2dp_ch(bt); /* break; */ case BT_STATUS_CONN_HFP_CH: bt_status_conn_hfp_ch(bt); break; case BT_STATUS_PHONE_MANUFACTURER: log_info("BT_STATUS_PHONE_MANUFACTURER\n"); bt_status_phone_menufactuer(bt); break; case BT_STATUS_VOICE_RECOGNITION: log_info(" BT_STATUS_VOICE_RECOGNITION \n"); bt_status_voice_recognition(bt); break; case BT_STATUS_AVRCP_INCOME_OPID: log_info(" BT_STATUS_AVRCP_INCOME_OPID \n"); bt_status_avrcp_income_opid(bt); break; case BT_STATUS_RECONN_OR_CONN: log_info(" BT_STATUS_RECONN_OR_CONN \n"); if (kt_get_mode() == MODE_BT_EMITTER) { emitter_or_receiver_switch(BT_EMITTER_EN); app_task_switch_to(APP_LINEIN_TASK); } break; default: log_info(" BT STATUS DEFAULT\n"); //printf("user_role : %d conn_total : %d bt_role : %d \n", kt_get_user_role(), get_total_connect_dev(), bt_emitter_role_get()); if (kt_get_user_role() == MODE_BT_EMITTER && get_total_connect_dev() == 0) { printf("[EMITTER][SEARCH_STOP][%s-%d] no device found, restart search\n",__func__,__LINE__); bt_emitter_start_search_device(); } break; } return 0; } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙模式协议栈事件 @param bt:事件 @return @note 蓝牙底层事件,通过app层处理 */ /*----------------------------------------------------------------------------*/ static int bt_hci_event_handler(struct bt_event *bt) { //对应原来的蓝牙连接上断开处理函数 ,bt->value=reason log_debug("------------------------bt_hci_event_handler reason %x %x", bt->event, bt->value); if (bt_hci_event_filter(bt) == 0) { return 0; } switch (bt->event) { case HCI_EVENT_INQUIRY_COMPLETE: log_info(" HCI_EVENT_INQUIRY_COMPLETE \n"); bt_hci_event_inquiry(bt); break; case HCI_EVENT_IO_CAPABILITY_REQUEST: log_info(" HCI_EVENT_IO_CAPABILITY_REQUEST \n"); clock_add_set(BT_CONN_CLK); // IO Capability请求由底层自动处理,这里只需要添加时钟 break; case HCI_EVENT_USER_CONFIRMATION_REQUEST: log_info(" HCI_EVENT_USER_CONFIRMATION_REQUEST %d \n", bt->value); ///<可通过按键来确认是否配对 1:配对 0:取消 bt_send_pair(1); clock_remove_set(BT_CONN_CLK); break; case HCI_EVENT_USER_PASSKEY_REQUEST: log_info(" HCI_EVENT_USER_PASSKEY_REQUEST \n"); ///<可以开始输入6位passkey break; case HCI_EVENT_USER_PRESSKEY_NOTIFICATION: log_info(" HCI_EVENT_USER_PRESSKEY_NOTIFICATION %x\n", bt->value); ///<可用于显示输入passkey位置 value 0:start 1:enrer 2:earse 3:clear 4:complete break; case HCI_EVENT_PIN_CODE_REQUEST : log_info("HCI_EVENT_PIN_CODE_REQUEST \n"); bt_send_pair(1); break; case HCI_EVENT_VENDOR_NO_RECONN_ADDR : log_info("HCI_EVENT_VENDOR_NO_RECONN_ADDR \n"); bt_hci_event_disconnect(bt) ; break; case HCI_EVENT_DISCONNECTION_COMPLETE : log_info("HCI_EVENT_DISCONNECTION_COMPLETE \n"); bt_hci_event_disconnect(bt) ; clock_remove_set(BT_CONN_CLK); break; case BTSTACK_EVENT_HCI_CONNECTIONS_DELETE: case HCI_EVENT_CONNECTION_COMPLETE: log_info(" HCI_EVENT_CONNECTION_COMPLETE \n"); switch (bt->value) { case ERROR_CODE_SUCCESS : log_info("ERROR_CODE_SUCCESS \n"); bt_hci_event_connection(bt); break; case ERROR_CODE_PIN_OR_KEY_MISSING: log_info(" ERROR_CODE_PIN_OR_KEY_MISSING \n"); bt_hci_event_linkkey_missing(bt); do { u8 is_emitter = (bt_emitter_role_get() == BT_EMITTER_EN); u16 ch = is_emitter ? get_emitter_curr_channel_state() : get_curr_channel_state(); printf("[RECONNECT][FAIL][%s] reason:0x%02x ch:0x%04x file:%s line:%d\n", is_emitter ? "EMITTER" : "RECEIVER", bt->value, ch, __FILE__, __LINE__); } while (0); case ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED : case ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES: case ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR: case ERROR_CODE_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED : case ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION : case ERROR_CODE_CONNECTION_TERMINATED_BY_LOCAL_HOST : case ERROR_CODE_AUTHENTICATION_FAILURE : case CUSTOM_BB_AUTO_CANCEL_PAGE: do { u8 is_emitter = (bt_emitter_role_get() == BT_EMITTER_EN); u16 ch = is_emitter ? get_emitter_curr_channel_state() : get_curr_channel_state(); printf("[RECONNECT][FAIL][%s] reason:0x%02x ch:0x%04x file:%s line:%d\n", is_emitter ? "EMITTER" : "RECEIVER", bt->value, ch, __FILE__, __LINE__); } while (0); bt_hci_event_disconnect(bt) ; if(bt_emitter_role_get() == BT_EMITTER_EN && get_total_connect_dev() == 0) { printf("EMITTER][VM] reconnect failed, start search\n"); bt_emitter_start_search_device(); } break; case ERROR_CODE_PAGE_TIMEOUT: log_info(" ERROR_CODE_PAGE_TIMEOUT \n"); do { u8 is_emitter = (bt_emitter_role_get() == BT_EMITTER_EN); u16 ch = is_emitter ? get_emitter_curr_channel_state() : get_curr_channel_state(); printf("[RECONNECT][FAIL][%s] reason:0x%02x ch:0x%04x file:%s line:%d\n", is_emitter ? "EMITTER" : "RECEIVER", bt->value, ch, __FILE__, __LINE__); } while (0); bt_hci_event_page_timeout(bt); if(bt_emitter_role_get() == BT_EMITTER_EN && get_total_connect_dev() == 0) { printf("EMITTER][VM] reconnect failed, start search\n"); bt_emitter_start_search_device(); } break; case ERROR_CODE_CONNECTION_TIMEOUT: log_info(" ERROR_CODE_CONNECTION_TIMEOUT \n"); do { u8 is_emitter = (bt_emitter_role_get() == BT_EMITTER_EN); u16 ch = is_emitter ? get_emitter_curr_channel_state() : get_curr_channel_state(); printf("[RECONNECT][FAIL][%s] reason:0x%02x ch:0x%04x file:%s line:%d\n", is_emitter ? "EMITTER" : "RECEIVER", bt->value, ch, __FILE__, __LINE__); } while (0); bt_hci_event_connection_timeout(bt); if(bt_emitter_role_get() == BT_EMITTER_EN && get_total_connect_dev() == 0) { printf("EMITTER][VM] reconnect failed, start search\n"); bt_emitter_start_search_device(); } break; case ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS : log_info("ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS \n"); bt_hci_event_connection_exist(bt); break; default: break; } break; default: break; } return 0; } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙后台事件过滤处理 @param event: 事件 @return 0:不需要切换模式, 1:需要切换模式,2:通话导致需要切换 @note */ /*----------------------------------------------------------------------------*/ int bt_background_event_handler_filter(struct sys_event *event) { u8 ret = 0; #if TCFG_BLUETOOTH_BACK_MODE if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) { log_info("bt con event: %d \n", event->u.bt.event); switch (event->u.bt.event) { // 需要切换蓝牙的命令 case BT_STATUS_A2DP_MEDIA_START: if (__this->sbc_packet_step != 0) { /* log_info("sbc_packet_step : %d \n", __this->sbc_packet_step); */ break; } case BT_STATUS_FIRST_DISCONNECT: case BT_STATUS_SECOND_DISCONNECT: //关机导致的断开不可以回去蓝牙,否则后台关机会有问题 if (app_var.goto_poweroff_flag) { break; } #if BACKGROUND_GOBACK #if USER_SUPPORT_DUAL_A2DP_SOURCE /* ret = 1; */ #else ret = 1; #endif #else //判断断开的是sink设备,默认切换蓝牙 if (event->u.bt.value) { ret = 1; } if (ret == 0) { bt_status_disconnect_background(&event->u.bt); } #endif break; case BT_STATUS_SECOND_CONNECTED: case BT_STATUS_FIRST_CONNECTED: #if BACKGROUND_GOBACK #if USER_SUPPORT_DUAL_A2DP_SOURCE /* ret = 1; */ #else ret = 1; #endif #else bt_status_connect_background(&event->u.bt); #endif break; case BT_STATUS_START_CONNECTED: #if BACKGROUND_GOBACK #if USER_SUPPORT_DUAL_A2DP_SOURCE /* ret = 1; */ #else ret = 1; #endif #endif if(bt_emitter_role_get() == BT_EMITTER_EN) { bt_event_status_start_connected(&event->u.bt); } break; case BT_STATUS_ENCRY_COMPLETE: break; case BT_STATUS_SCO_STATUS_CHANGE: ret = 1; break; case BT_STATUS_LAST_CALL_TYPE_CHANGE: bt_status_last_call_type_change(&event->u.bt); case BT_STATUS_VOICE_RECOGNITION: case BT_STATUS_PHONE_INCOME: case BT_STATUS_PHONE_NUMBER: /* case BT_STATUS_PHONE_MANUFACTURER: */ case BT_STATUS_PHONE_OUT: case BT_STATUS_PHONE_ACTIVE: /* case BT_STATUS_PHONE_HANGUP: */ ret = 2; break; // 不需要处理的命令 case BT_STATUS_INIT_OK: bt_status_init_ok_background(&event->u.bt); break; case BT_STATUS_A2DP_MEDIA_STOP: bt_drop_a2dp_frame_stop(); case BT_STATUS_CALL_VOL_CHANGE: break; // 按原方式处理的命令 default: bt_connction_status_event_handler(&event->u.bt); break; } } else if ((u32)event->arg == SYS_BT_EVENT_TYPE_HCI_STATUS) { /* log_info("bt hci event: %d \n", event->u.bt.event); */ switch (event->u.bt.event) { case HCI_EVENT_IO_CAPABILITY_REQUEST: clock_add_set(BT_CONN_CLK); #if BACKGROUND_GOBACK #if USER_SUPPORT_DUAL_A2DP_SOURCE /* ret = 1; */ #else ret = 1; #endif #endif break; default: bt_hci_event_handler(&event->u.bt); break; } } #if TCFG_USER_TWS_ENABLE else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) { /* log_info("bt tws event: %d \n", event->u.bt.event); */ switch (event->u.bt.event) { /* case TWS_EVENT_CONNECTED: */ /* ret = 1; */ /* break; */ default: bt_tws_connction_status_event_handler(&event->u.bt); #if (TCFG_DEC2TWS_ENABLE) localtws_bt_event_deal(&event->u.bt); #endif break; } } #endif else if ((u32)event->arg == SYS_EVENT_FROM_CTRLER) { switch (event->u.bt.event) { case BTCTRLER_EVENT_RESUME_REQ: /*log_info("------- BTCTRLER_EVENT_RESUME_REQ \n"); */ ret = 2; break; } } #endif return ret; } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙后台事件处理 @param event: 事件 @return 无 @note */ /*----------------------------------------------------------------------------*/ int bt_background_event_handler(struct sys_event *event) { int ret = bt_background_event_handler_filter(event); if (ret) { if (false == app_check_curr_task(APP_BT_TASK)) { __this->cmd_flag = 1; if (ret == 2) { __this->call_flag = 1; } else { __this->call_flag = 0; } app_task_switch_to(APP_BT_TASK); sys_event_notify(event); } } return 0; } //#if (USER_SUPPORT_PROFILE_HID==1) ////重写bt_get_hid_name //const char * bt_get_hid_name() //{ // return "HID_USER"; //} //#endif extern int multi_spp_send_data(u8 local_cid, u8 rfcomm_cid, u8 *buf, u16 len); int mutil_handle_data_deal(u8 local_id, u8 packet_type, u16 channel, u8 *packet, u16 size) //该函数在底层是weak函数 { printf("local_id %d\n",local_id); switch (packet_type) { case 1: printf("connect\n"); break; case 2: printf("disconnect\n"); break; case 7: put_buf(packet, size); multi_spp_send_data(local_id,0,packet,size); break; default: break; } } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙模式按键响应处理 @param event: 按键 @return 1:事件处理 0:事件无处理 @note */ /*----------------------------------------------------------------------------*/ int bt_key_event_handler(struct sys_event *event) { int ret = true; struct key_event *key = &event->u.key; if (bt_key_event_filter_before() == false) { return false; } int key_event = event->u.key.event; int key_value = event->u.key.value; log_debug("bt key_event:%d %d %d %d\n", key_event, key->value, key->event, key->init); if (bt_key_event_filter_after(key_event) == true) { return true; } if (kt_key_event_filter_after(key_event) == true) { return true; } switch (key_event) { case KEY_HCI_DISCONNECT_CLEAR_VM: printf("KEY_HCI_DISCONNECT_CLEAR_VM\n"); user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI,0,NULL); user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL);//清除配对信息 break; case KEY_TEST_1: printf("KEY_TEST_1"); user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_LAST_NO, 0, NULL); break; case KEY_TEST_2: printf("KEY_TEST_2"); // user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); break; case KEY_TEST_3: printf("KEY_TEST_3"); user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_ANSWER, 0, NULL); break; case KEY_TEST_4: printf("KEY_TEST_4"); bt_search_device(); break; case KEY_MUSIC_PP: log_info(" KEY_MUSIC_PP \n"); bt_key_music_pp(); break; case KEY_MUSIC_PREV: log_info(" KEY_MUSIC_PREV \n"); bt_key_music_prev(); break; case KEY_MUSIC_NEXT: log_info(" KEY_MUSIC_NEXT \n"); bt_key_music_next(); break; case KEY_VOL_UP: log_info(" KEY_VOL_UP \n"); bt_key_vol_up(); break; case KEY_VOL_DOWN: log_info(" KEY_VOL_DOWN \n"); bt_key_vol_down(); break; case KEY_CALL_LAST_NO: log_info(" KEY_CALL_LAST_NO \n"); bt_key_call_last_on(); break; case KEY_CALL_HANG_UP: log_info(" KEY_CALL_HANG_UP \n"); bt_key_call_hand_up(); break; case KEY_CALL_ANSWER: log_info(" KEY_CALL_ANSWER \n"); bt_key_call_answer(); break; case KEY_OPEN_SIRI: log_info(" KEY_OPEN_SIRI \n"); bt_key_call_siri(); break; case KEY_HID_CONTROL: log_info(" KEY_HID_CONTROL \n"); bt_key_hid_control(); break; case KEY_THIRD_CLICK: log_info(" KEY_THIRD_CLICK \n"); bt_key_third_click(event); break; case KEY_LOW_LANTECY: log_info(" KEY_LOW_LANTECY \n"); bt_key_low_lantecy(); break; case KEY_NULL: log_info(" KEY_NULL \n"); ret = false; #if TCFG_USER_TWS_ENABLE if ((u32)event->arg == KEY_EVENT_FROM_TWS) { break; } #endif break; case KEY_HID_MODE_SWITCH: #if (USER_SUPPORT_PROFILE_HID==1) __this->hid_mode = !__this->hid_mode; printf("KEY_HID_TAKE_PICTURE, %d\n", __this->hid_mode); user_change_profile_mode(__this->hid_mode);///HID设备名称, 默认蓝牙名称追加_HID //如果要修改名称, 可以重写重写这个函数,上面有重写例子 //const char *__attribute__((weak)) bt_get_hid_name() #endif break; case KEY_HID_TAKE_PICTURE: if (__this->hid_mode) { printf("KEY_HID_TAKE_PICTURE\n"); user_send_cmd_prepare(USER_CTRL_HID_BOTH, 0, NULL); } break; #if TCFG_USER_TWS_ENABLE case KEY_CHANGE_MODE: #if (TCFG_DEC2TWS_ENABLE) ret = false; #else if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) { if (tws_api_get_role() == TWS_ROLE_MASTER) { bt_tws_api_push_cmd(SYNC_CMD_MODE_CHANGE, 400); } } else { ret = false; break; } #endif break; #endif default: ret = false; break; } #if (SMART_BOX_EN) extern int smartbox_bt_key_event_deal(int key_event, int ret); ret = smartbox_bt_key_event_deal(key_event, ret); #endif return ret; } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙模式协议栈状态事件、hci事件、对箱事件 @param event: 事件 @return 无 @note */ /*----------------------------------------------------------------------------*/ int bt_sys_event_office(struct sys_event *event) { u8 ret = false; if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) { bt_connction_status_event_handler(&event->u.bt); } else if ((u32)event->arg == SYS_BT_EVENT_TYPE_HCI_STATUS) { bt_hci_event_handler(&event->u.bt); } else if ((u32)event->arg == SYS_BT_EVENT_FORM_SELF) { bt_reverb_status_change(&event->u.bt); } #if TCFG_USER_TWS_ENABLE else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) { ret = bt_tws_connction_status_event_handler(&event->u.bt); } #endif else if (((u32)event->arg == SYS_BT_EVENT_FROM_KEY)) { switch (event->u.key.event) { case KEY_CHANGE_MODE: app_task_switch_next(); break; } } return ret; } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙模式事件消息处理 @param event: 事件 @return 1:处理完成,消息不需要进入common处理 0:common defult处理 @note */ /*----------------------------------------------------------------------------*/ static int bt_sys_event_handler(struct sys_event *event) { int ret = false; switch (event->type) { case SYS_KEY_EVENT: ret = bt_key_event_handler(event); break; case SYS_BT_EVENT: ret = bt_sys_event_office(event); break; case SYS_DEVICE_EVENT: #if APP_ONLINE_DEBUG if ((u32)event->arg == DEVICE_EVENT_ONLINE_DATA) { //putchar('%'); extern void app_online_event_handle(int evt_value); app_online_event_handle(event->u.dev.value); } #endif /* #if TCFG_EARTCH_EVENT_HANDLE_ENABLE */ break; default: return false; } // SYS_EVENT_HANDLER_SPECIFIC(event); app_protocol_sys_event_handler(event); return ret; } //*----------------------------------------------------------------------------*/ /**@brief BT 模式提示音播放结束处理 @param @return @note */ /*----------------------------------------------------------------------------*/ static void bt_tone_play_end_callback(void *priv, int flag) { u32 index = (u32)priv; if (APP_BT_TASK != app_get_curr_task()) { log_error("tone callback task out \n"); return; } switch (index) { case IDEX_TONE_BT_MODE: ///提示音播放结束, 启动播放器播放 bt_task_start(); break; default: break; } } /*----------------------------------------------------------------------------*/ /**@brief 蓝牙模式 @param @return 无 @note */ /*----------------------------------------------------------------------------*/ void app_bt_task() { int res; int msg[32]; ui_update_status(STATUS_EXIT_LOWPOWER); bt_task_init();//初始化变量、时钟、显示(未进行协议栈初始化) #if TCFG_TONE2TWS_ENABLE extern void tone2tws_bt_task_start(u8 tone_play); tone2tws_bt_task_start(!__this->cmd_flag); #endif extern u8 get_tws_background_connected_flag(); if (!__this->cmd_flag && (!get_tws_background_connected_flag())) { //蓝牙后台拉回蓝牙模式不播放提示音 tone_play_with_callback_by_name(tone_table[IDEX_TONE_BT_MODE], 1, bt_tone_play_end_callback, (void *)IDEX_TONE_BT_MODE); //协议栈初始化在提示音结束进行 } else { //后台返回的情况没有播放提示音,需要在这里进行协议栈的resume bt_task_start(); } #if TCFG_DEC2TWS_ENABLE extern void set_tws_background_connected_flag(u8 flag); if (get_tws_background_connected_flag()) { int state = tws_api_get_tws_state(); if (state & TWS_STA_SIBLING_CONNECTED) { if (tws_api_get_role() == TWS_ROLE_MASTER) { app_task_switch_back(); } else { set_tws_background_connected_flag(0); } } } #endif while (1) { app_task_get_msg(msg, ARRAY_SIZE(msg), 1); switch (msg[0]) { case APP_MSG_SYS_EVENT: if (bt_sys_event_handler((struct sys_event *)(msg + 1)) == false) { app_default_event_deal((struct sys_event *)(&msg[1])); } break; default: break; } #if TCFG_BLUETOOTH_BACK_MODE if (!__this->init_ok && !app_var.goto_poweroff_flag) { //蓝牙后台方案必须要等待协议栈初始化完成 continue; } #else if (__this->init_start && (!__this->init_ok)) { //协议栈已经初始化 但没有初始化完成 //需要等待初始化完成才可以走退出流程 continue; } #endif if (app_task_exitting()) { if (__this->init_start) { bt_task_close(); __this->wait_exit = 1; } else { //蓝牙协议栈没有初始化,可以直接退出 bt_task_close(); return; } } if (__this->wait_exit) { //开始退出 if (!__this->exiting) { ///等待蓝牙退出处理完成 __this->wait_exit = 0; return; } } } } u8 bt_app_exit_check() { return bt_app_switch_exit_check(); } #else void app_bt_task() { } u8 bt_app_exit_check() { return 1; } int bt_background_event_handler_filter(struct sys_event *event) { return 0; } u8 get_call_status() { return BT_CALL_HANGUP; } u32 bt_tws_master_slot_clk(void) { return 0; } #endif