/*************************************************************************** * * 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 "cmsis_os.h" #include #include "me_api.h" #include "app_tws_ibrt_trace.h" #include "audioflinger.h" #include "app_bt_stream.h" #include "app_media_player.h" #include "app_bt_media_manager.h" #include "bt_drv_interface.h" #include "app_ibrt_if.h" #include "app_tws_ibrt_cmd_handler.h" #include "app_tws_ctrl_thread.h" #include "app_ibrt_voice_report.h" #include "app_bt.h" #ifdef TWS_PROMPT_SYNC #include "audio_prompt_sbc.h" #endif #include "app_audio.h" #if defined(IBRT) extern uint8_t g_findme_fadein_vol; typedef uint8_t voice_report_role_t; #define VOICE_REPORT_MASTER 0x00 #define VOICE_REPORT_SLAVE 0x01 #define VOICE_REPORT_LOCAL 0x02 #define APP_PLAY_AUDIO_SYNC_DELAY_US (250*1000) #define APP_PLAY_AUDIO_SYNC_TRIGGER_TIMEROUT (APP_PLAY_AUDIO_SYNC_DELAY_US/1000*2) static uint32_t app_ibrt_voice_tg_tick = 0; static uint32_t app_ibrt_voice_trigger_enable = 0; static void app_ibrt_voice_report_trigger_timeout_cb(void const *n); osTimerDef(APP_IBRT_VOICE_REPORT_TRIGGER_TIMEOUT, app_ibrt_voice_report_trigger_timeout_cb); osTimerId app_ibrt_voice_report_trigger_timeout_id = NULL; static void app_ibrt_voice_report_trigger_timeout_cb(void const *n) { TRACE_VOICE_RPT_D("[TRIG][TIMEOUT]"); app_play_audio_stop(); } static int app_ibrt_voice_report_trigger_checker_init(void) { if (app_ibrt_voice_report_trigger_timeout_id == NULL){ app_ibrt_voice_report_trigger_timeout_id = osTimerCreate(osTimer(APP_IBRT_VOICE_REPORT_TRIGGER_TIMEOUT), osTimerOnce, NULL); } return 0; } static int app_ibrt_voice_report_trigger_checker_start(void) { app_ibrt_voice_trigger_enable = true; osTimerStart(app_ibrt_voice_report_trigger_timeout_id, APP_PLAY_AUDIO_SYNC_TRIGGER_TIMEROUT); return 0; } static int app_ibrt_voice_report_trigger_checker_stop(void) { app_ibrt_voice_trigger_enable = false; osTimerStop(app_ibrt_voice_report_trigger_timeout_id); return 0; } int app_ibrt_voice_report_trigger_checker(void) { ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); if (!p_ibrt_ctrl->init_done){ return 0; } if (app_ibrt_voice_trigger_enable){ TRACE_VOICE_RPT_I("[TRIG][OK]"); app_ibrt_voice_trigger_enable = false; osTimerStop(app_ibrt_voice_report_trigger_timeout_id); } return 0; } voice_report_role_t app_ibrt_voice_report_get_role(void) { voice_report_role_t report_role = VOICE_REPORT_LOCAL; ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); if (app_ibrt_ui_is_profile_exchanged()){ if (app_tws_ibrt_mobile_link_connected()){ report_role = VOICE_REPORT_MASTER; }else if (app_tws_ibrt_slave_ibrt_link_connected()){ report_role = VOICE_REPORT_SLAVE; }else{ TRACE_VOICE_RPT_I("[GET_ROLE] skip it (profile_exchanged)"); } }else if (app_tws_ibrt_tws_link_connected()){ if (app_tws_ibrt_mobile_link_connected()){ report_role = VOICE_REPORT_MASTER; }else if(p_ibrt_ctrl->current_role == IBRT_MASTER){ report_role = VOICE_REPORT_MASTER; }else{ report_role = VOICE_REPORT_SLAVE; } }else{ TRACE_VOICE_RPT_I("[GET_ROLE] loc only"); } TRACE_VOICE_RPT_I("[GET_ROLE] report_role: %d", report_role); return report_role; } static void app_ibrt_voice_report_set_trigger_time(uint32_t tg_tick) { if (tg_tick){ ibrt_ctrl_t *p_ibrt_ctrl = app_ibrt_if_get_bt_ctrl_ctx(); btif_connection_role_t connection_role = app_tws_ibrt_get_local_tws_role(); btdrv_syn_trigger_codec_en(0); btdrv_syn_clr_trigger(); btdrv_enable_playback_triggler(ACL_TRIGGLE_MODE); if (connection_role == BTIF_BCR_MASTER){ bt_syn_set_tg_ticks(tg_tick, p_ibrt_ctrl->tws_conhandle, BT_TRIG_MASTER_ROLE); }else if (connection_role == BTIF_BCR_SLAVE){ bt_syn_set_tg_ticks(tg_tick, p_ibrt_ctrl->tws_conhandle, BT_TRIG_SLAVE_ROLE); } btdrv_syn_trigger_codec_en(1); app_ibrt_voice_report_trigger_checker_start(); TRACE_VOICE_RPT_I("[TRIG] set trigger tg_tick:%08x", tg_tick); }else{ btdrv_syn_trigger_codec_en(0); btdrv_syn_clr_trigger(); app_ibrt_voice_report_trigger_checker_stop(); TRACE_VOICE_RPT_I("[TRIG] trigger clear"); } } int app_ibrt_voice_report_trigger_init(uint32_t aud_id, uint32_t aud_pram) { ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); if (!p_ibrt_ctrl->init_done){ TRACE_VOICE_RPT_I("ibrt not init done."); return 0; } app_ibrt_voice_report_trigger_checker_init(); if (app_tws_ibrt_tws_link_connected()){ ibrt_ctrl_t *p_ibrt_ctrl = app_ibrt_if_get_bt_ctrl_ctx(); voice_report_role_t report_role = app_ibrt_voice_report_get_role(); uint32_t curr_ticks = 0; uint32_t tg_tick = 0; app_ibrt_voice_report_trigger_deinit(); curr_ticks = bt_syn_get_curr_ticks(p_ibrt_ctrl->tws_conhandle); if (report_role == VOICE_REPORT_MASTER){ app_ibrt_voice_report_info_t voice_report_info; tg_tick = curr_ticks + US_TO_BTCLKS(APP_PLAY_AUDIO_SYNC_DELAY_US); #ifdef PLAYBACK_USE_I2S af_i2s_sync_config(AUD_STREAM_PLAYBACK, AF_I2S_SYNC_TYPE_BT, false); af_i2s_sync_config(AUD_STREAM_PLAYBACK, AF_I2S_SYNC_TYPE_BT, true); #else af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, false); af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, true); #endif app_ibrt_voice_report_set_trigger_time(tg_tick); voice_report_info.aud_id = aud_id; voice_report_info.aud_pram = aud_pram; voice_report_info.tg_tick = tg_tick; #ifdef __INTERACTION__ voice_report_info.vol = g_findme_fadein_vol; #endif if (p_ibrt_ctrl->tws_mode == IBRT_SNIFF_MODE) { TRACE_VOICE_RPT_I("[TRIG][INIT][EXIT_SNIFF] force_exit_with_tws\n"); app_tws_ibrt_exit_sniff_with_tws(); } tws_ctrl_send_cmd(APP_TWS_CMD_VOICE_REPORT_START, (uint8_t *)&voice_report_info, sizeof(app_ibrt_voice_report_info_t)); TRACE_VOICE_RPT_I("[TRIG][INIT] MASTER aud_id:%d trigger [%08x]-->[%08x]", aud_id, bt_syn_get_curr_ticks(p_ibrt_ctrl->tws_conhandle), tg_tick); }else if (report_role == VOICE_REPORT_SLAVE){ tg_tick = app_ibrt_voice_tg_tick; if (curr_ticks < tg_tick && tg_tick != 0) { #ifdef PLAYBACK_USE_I2S af_i2s_sync_config(AUD_STREAM_PLAYBACK, AF_I2S_SYNC_TYPE_BT, false); af_i2s_sync_config(AUD_STREAM_PLAYBACK, AF_I2S_SYNC_TYPE_BT, true); #else af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, false); af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, true); #endif app_ibrt_voice_report_set_trigger_time(tg_tick); } app_ibrt_voice_tg_tick = 0; if (tg_tick <= curr_ticks) { app_audio_sendrequest(APP_PLAY_BACK_AUDIO, (uint8_t)APP_BT_SETTING_CLOSE, 0); TRACE_VOICE_RPT_I("[TRIG][INIT] Prompt TRIGGER ERROR !!!"); } TRACE_VOICE_RPT_I("[TRIG][INIT] SLAVE aud_id:%d trigger [%08x]-->[%08x]", aud_id, bt_syn_get_curr_ticks(p_ibrt_ctrl->tws_conhandle), tg_tick); } } else { TRACE_VOICE_RPT_I("[TRIG][INIT] tws not connected."); } return 0; } int app_ibrt_voice_report_trigger_deinit(void) { ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); if (!p_ibrt_ctrl->init_done){ return 0; } #ifdef PLAYBACK_USE_I2S af_i2s_sync_config(AUD_STREAM_PLAYBACK, AF_I2S_SYNC_TYPE_BT, false); #else af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, false); #endif app_ibrt_voice_report_set_trigger_time(0); return 0; } int app_ibrt_if_voice_report_filter(uint32_t aud_id) { int nRet = 0; ibrt_ctrl_t *p_ibrt_ctrl = app_ibrt_if_get_bt_ctrl_ctx(); switch (aud_id){ case AUD_ID_BT_PAIRING_SUC: nRet = 1; break; default: break; } if (app_tws_ibrt_slave_ibrt_link_connected()){ switch (aud_id){ case AUD_ID_BT_CALL_INCOMING_CALL: case AUD_ID_BT_CALL_INCOMING_NUMBER: case AUD_ID_BT_CALL_OVER: case AUD_ID_BT_CALL_ANSWER: case AUD_ID_BT_CONNECTED: case AUD_ID_BT_CALL_HUNG_UP: case AUD_ID_BT_CALL_REFUSE: nRet = 1; break; default: break; } } if (!app_tws_ibrt_slave_ibrt_link_connected() && !app_tws_ibrt_mobile_link_connected()){ if (p_ibrt_ctrl->nv_role == IBRT_SLAVE){ switch (aud_id){ case AUD_ID_BT_CONNECTED: nRet = 1; break; default: break; } } } return nRet; } int app_ibrt_if_voice_report_local_only(uint32_t aud_id) { int nRet = 0; switch (aud_id){ default: break; } return nRet; } int app_ibrt_if_voice_report_force_audio_retrigger_hander(uint32_t msg_id, uint32_t aud_id) { if (msg_id == APP_BT_STREAM_MANAGER_STOP_MEDIA){ if (aud_id == AUDIO_ID_BT_MUTE){ TRACE_VOICE_RPT_I("[ID_BT_MUTE]"); #ifdef MEDIA_PLAYER_SUPPORT trigger_media_play((AUD_ID_ENUM)aud_id, 0, PROMOT_ID_BIT_MASK_CHNLSEl_ALL); #endif } } return 0; } static int app_ibrt_if_voice_report_init(uint32_t aud_id, uint16_t aud_pram, uint8_t init_play) { #ifdef MEDIA_PLAYER_SUPPORT ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); if (!p_ibrt_ctrl->init_done) { trigger_media_play((AUD_ID_ENUM)aud_id, 0, aud_pram); } else if (app_ibrt_if_voice_report_filter(aud_id) && init_play) { TRACE_VOICE_RPT_I("[INIT] skip aud_id:%d%s", aud_id, aud_id2str(aud_id)); } else if (app_ibrt_if_voice_report_local_only(aud_id)) { trigger_media_play((AUD_ID_ENUM)aud_id, 0, aud_pram); } else if (!app_tws_ibrt_tws_link_connected()) { trigger_media_play((AUD_ID_ENUM)aud_id, 0, aud_pram); } else { voice_report_role_t report_role = app_ibrt_voice_report_get_role(); app_ibrt_if_tws_sniff_block(5); if (report_role == VOICE_REPORT_MASTER) { TRACE_VOICE_RPT_I("[INIT] loc aud_id:%d%s aud_pram:%04x", aud_id, aud_id2str(aud_id), aud_pram); if (aud_id == AUDIO_ID_BT_MUTE) { #ifdef TWS_PROMPT_SYNC audio_prompt_stop_playing(); #endif app_audio_manager_sendrequest_need_callback(APP_BT_STREAM_MANAGER_STOP_MEDIA, BT_STREAM_MEDIA, BT_DEVICE_ID_1, 0, (uintptr_t)app_ibrt_if_voice_report_force_audio_retrigger_hander, AUDIO_ID_BT_MUTE); } else { trigger_media_play((AUD_ID_ENUM)aud_id, 0, aud_pram); } } else if (report_role == VOICE_REPORT_SLAVE) { app_ibrt_voice_report_request_t voice_report_request; TRACE_VOICE_RPT_I("[INIT] rmt aud_id:%d%s aud_pram:%04x", aud_id, aud_id2str(aud_id), aud_pram); app_ibrt_voice_tg_tick = 0; if (aud_id == AUDIO_ID_BT_MUTE) { #ifdef TWS_PROMPT_SYNC audio_prompt_stop_playing(); #endif app_audio_manager_sendrequest_need_callback(APP_BT_STREAM_MANAGER_STOP_MEDIA, BT_STREAM_MEDIA, BT_DEVICE_ID_1, 0, 0, 0); } voice_report_request.aud_id = aud_id; voice_report_request.aud_pram = aud_pram; voice_report_request.vol = 0; if((aud_id & AUDIO_ID_FIND_MY_BUDS) == AUDIO_ID_FIND_MY_BUDS) { trigger_media_play(( AUD_ID_ENUM )aud_id, 0, aud_pram); } else tws_ctrl_send_cmd(APP_TWS_CMD_VOICE_REPORT_REQUEST, (uint8_t *)&voice_report_request, sizeof(voice_report_request)); } else { TRACE_VOICE_RPT_I("[INIT] loc only aud_id:%d aud_pram:%04x", aud_id, aud_pram); #ifdef MEDIA_PLAYER_SUPPORT trigger_media_play((AUD_ID_ENUM)aud_id, 0, aud_pram); #endif } } #endif return 0; } int app_ibrt_if_voice_report_trig_retrigger(void) { return app_ibrt_if_voice_report_handler(AUDIO_ID_BT_MUTE, PROMOT_ID_BIT_MASK_CHNLSEl_ALL); } int app_ibrt_if_voice_report_handler(uint32_t aud_id, uint16_t aud_pram) { return app_ibrt_if_voice_report_init(aud_id, aud_pram, true); } void app_ibrt_send_voice_report_request_req(uint8_t *p_buff, uint16_t length) { voice_report_role_t report_role = app_ibrt_voice_report_get_role(); if (report_role == VOICE_REPORT_SLAVE) { app_ibrt_send_cmd_without_rsp(APP_TWS_CMD_VOICE_REPORT_REQUEST, p_buff, length); } } void app_ibrt_voice_report_request_req_handler(uint16_t rsp_seq, uint8_t *p_buff, uint16_t length) { voice_report_role_t report_role = app_ibrt_voice_report_get_role(); if (report_role == VOICE_REPORT_MASTER) { app_ibrt_voice_report_request_t *voice_report_request = (app_ibrt_voice_report_request_t *)p_buff; app_ibrt_if_voice_report_init(voice_report_request->aud_id, voice_report_request->aud_pram, false); } else { TRACE_VOICE_RPT_I("[REQUEST_REQ][HANDLER] role is :%d", report_role); } } void app_ibrt_send_voice_report_start_req(uint8_t *p_buff, uint16_t length) { voice_report_role_t report_role = app_ibrt_voice_report_get_role(); if (report_role == VOICE_REPORT_MASTER) { app_ibrt_send_cmd_without_rsp(APP_TWS_CMD_VOICE_REPORT_START, p_buff, length); } else { TRACE_VOICE_RPT_I("[START_REQ] role is :%d", report_role); } } void app_ibrt_voice_report_request_start_handler(uint16_t rsp_seq, uint8_t *p_buff, uint16_t length) { #ifdef MEDIA_PLAYER_SUPPORT voice_report_role_t report_role = app_ibrt_voice_report_get_role(); if (report_role == VOICE_REPORT_SLAVE) { app_ibrt_voice_report_info_t *voice_report_info = (app_ibrt_voice_report_info_t *)p_buff; app_ibrt_voice_tg_tick = voice_report_info->tg_tick; #ifdef __INTERACTION__ g_findme_fadein_vol = voice_report_info->vol; #endif if (voice_report_info->aud_id == AUDIO_ID_BT_MUTE) { app_audio_manager_sendrequest_need_callback(APP_BT_STREAM_MANAGER_STOP_MEDIA, BT_STREAM_MEDIA, BT_DEVICE_ID_1, 0, (uintptr_t)app_ibrt_if_voice_report_force_audio_retrigger_hander, AUDIO_ID_BT_MUTE); } else { TRACE_VOICE_RPT_I("[START_REQ][HANDLER] aud id:%d", voice_report_info->aud_id); trigger_media_play((AUD_ID_ENUM)voice_report_info->aud_id, 0, voice_report_info->aud_pram); } } else { TRACE_VOICE_RPT_I("[START_REQ][HANDLER] role is :%d", report_role); } #endif } bool app_ibrt_voice_report_is_me(uint32_t voice_chnlsel) { bool is_me = true; ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx(); switch ((AUDIO_CHANNEL_SELECT_E)p_ibrt_ctrl->audio_chnl_sel) { case AUDIO_CHANNEL_SELECT_LCHNL: if (IS_PROMPT_CHNLSEl_RCHNL(voice_chnlsel)){ is_me = false; } break; case AUDIO_CHANNEL_SELECT_RCHNL: if (IS_PROMPT_CHNLSEl_LCHNL(voice_chnlsel)){ is_me = false; } break; default: break; } return is_me; } #endif