From 66432dcffe211e317d35978283a04a96d5620bdf Mon Sep 17 00:00:00 2001 From: Matthew Xie Date: Sun, 27 Apr 2014 05:45:32 -0700 Subject: [PATCH] Add WBS support on Bluedroid (2/6) Bug 13764086 Change-Id: I12bf302f7dd19efb497ad49d4d1d638a7a926049 --- bta/ag/bta_ag_act.c | 52 +++++++++++++++ bta/ag/bta_ag_cmd.c | 52 +++------------ bta/ag/bta_ag_int.h | 9 +++ bta/ag/bta_ag_main.c | 9 ++- bta/ag/bta_ag_sco.c | 155 ++++++++++++++++++++++++++++++++------------ bta/include/bta_ag_api.h | 7 +- bta/include/bta_ag_co.h | 10 +++ btif/co/bta_ag_co.c | 46 ++++++++++++- btif/src/btif_hf.c | 88 ++++++++++++++++++++++++- btif/src/btif_util.c | 4 +- hci/include/bt_hci_bdroid.h | 10 +++ hci/include/bt_hci_lib.h | 8 +++ hci/include/bt_vendor_lib.h | 22 +++++++ hci/src/bt_hci_bdroid.c | 58 ++++++++++++++++- hci/src/vendor.c | 20 ++++++ main/bte_main.c | 62 +++++++++++++++++- 16 files changed, 520 insertions(+), 92 deletions(-) mode change 100644 => 100755 bta/ag/bta_ag_cmd.c mode change 100644 => 100755 btif/co/bta_ag_co.c mode change 100644 => 100755 main/bte_main.c diff --git a/bta/ag/bta_ag_act.c b/bta/ag/bta_ag_act.c index 18185d8b3..ca4f8ebc9 100644 --- a/bta/ag/bta_ag_act.c +++ b/bta/ag/bta_ag_act.c @@ -423,6 +423,10 @@ void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) #if (BTM_WBS_INCLUDED == TRUE ) p_scb->peer_codecs = BTA_AG_CODEC_NONE; p_scb->sco_codec = BTA_AG_CODEC_NONE; + /* Clear these flags upon SLC teardown */ + p_scb->codec_updated = FALSE; + p_scb->codec_fallback = FALSE; + p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2; #endif p_scb->role = 0; p_scb->post_sco = BTA_AG_POST_SCO_NONE; @@ -876,3 +880,51 @@ void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) } } +/******************************************************************************* +** +** Function bta_ag_setcodec +** +** Description Handle API SetCodec +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ +#if (BTM_WBS_INCLUDED == TRUE ) + tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec; + tBTA_AG_VAL val; + + /* Check if the requested codec type is valid */ + if((codec_type != BTA_AG_CODEC_NONE) && + (codec_type != BTA_AG_CODEC_CVSD) && + (codec_type != BTA_AG_CODEC_MSBC)) + { + val.num = codec_type; + val.hdr.status = BTA_AG_FAIL_RESOURCES; + APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); + (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val); + return; + } + + if((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) || + (codec_type == BTA_AG_CODEC_CVSD)) + { + p_scb->sco_codec = codec_type; + p_scb->codec_updated = TRUE; + val.num = codec_type; + val.hdr.status = BTA_AG_SUCCESS; + APPL_TRACE_DEBUG("bta_ag_setcodec: Updated codec type %d", codec_type); + } + else + { + val.num = codec_type; + val.hdr.status = BTA_AG_FAIL_RESOURCES; + APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); + } + + (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val); +#endif +} + diff --git a/bta/ag/bta_ag_cmd.c b/bta/ag/bta_ag_cmd.c old mode 100644 new mode 100755 index 285c70a6c..fd3024773 --- a/bta/ag/bta_ag_cmd.c +++ b/bta/ag/bta_ag_cmd.c @@ -1203,7 +1203,10 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, p_scb->sco_codec = UUID_CODEC_CVSD; APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to CVSD"); } - + /* The above logic sets the stack preferred codec based on local and peer codec + capabilities. This can be overridden by the application depending on its preference + using the bta_ag_setcodec API. We send the peer_codecs to the application. */ + val.num = p_scb->peer_codecs; /* Received BAC while in codec negotiation. */ if ((bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST) && (bta_ag_cb.sco.p_curr_scb == p_scb)) { @@ -1218,6 +1221,8 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, break; case BTA_AG_HF_CMD_BCS: + bta_ag_send_ok(p_scb); + /* stop cn timer */ bta_sys_stop_timer(&p_scb->cn_timer); @@ -1241,7 +1246,8 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, else bta_ag_sco_codec_nego(p_scb, FALSE); - bta_ag_send_ok(p_scb); + /* send final codec info to callback */ + val.num = codec_sent; break; case BTA_AG_HF_CMD_BCC: @@ -1718,47 +1724,6 @@ void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) } } -/******************************************************************************* -** -** Function bta_ag_setcodec -** -** Description Handle API SetCodec -** -** -** Returns void -** -*******************************************************************************/ -void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) -{ -#if (BTM_WBS_INCLUDED == TRUE ) - tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec; - - /* Check if the requested codec type is valid */ - if((codec_type != BTA_AG_CODEC_NONE) && - (codec_type != BTA_AG_CODEC_CVSD) && - (codec_type != BTA_AG_CODEC_MSBC)) - { - APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); - return; - } - - if((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) || (codec_type == BTA_AG_CODEC_CVSD)) - { - p_scb->sco_codec = codec_type; - p_scb->codec_updated = TRUE; - APPL_TRACE_DEBUG("bta_ag_setcodec: Updated codec type %d", codec_type); - } - else - { - APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); - } -#else - UNUSED(p_scb); - UNUSED(p_data); -#endif -} - - #if (BTM_WBS_INCLUDED == TRUE ) /******************************************************************************* ** @@ -1792,6 +1757,7 @@ void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) } /* send +BCS */ + APPL_TRACE_DEBUG("send +BCS codec is %d", codec_uuid); bta_ag_send_result(p_scb, BTA_AG_RES_BCS, NULL, codec_uuid); } diff --git a/bta/ag/bta_ag_int.h b/bta/ag/bta_ag_int.h index b0d1b1d42..b2d9fb0c6 100644 --- a/bta/ag/bta_ag_int.h +++ b/bta/ag/bta_ag_int.h @@ -237,6 +237,14 @@ typedef struct UINT8 scn; } tBTA_AG_PROFILE; +#if (BTM_WBS_INCLUDED == TRUE) +typedef enum +{ + BTA_AG_SCO_MSBC_SETTINGS_T2 = 0, /* preferred/default when codec is mSBC */ + BTA_AG_SCO_MSBC_SETTINGS_T1, +} tBTA_AG_SCO_MSBC_SETTINGS; +#endif + /* type for each service control block */ typedef struct { @@ -261,6 +269,7 @@ typedef struct tBTA_AG_PEER_CODEC inuse_codec; /* codec being used for the current SCO connection */ BOOLEAN codec_updated; /* set to TRUE whenever the app updates codec type */ BOOLEAN codec_fallback; /* If sco nego fails for mSBC, fallback to CVSD */ + tBTA_AG_SCO_MSBC_SETTINGS codec_msbc_settings; /* settings to be used for the impending eSCO */ TIMER_LIST_ENT cn_timer; /* codec negotiation timer */ #endif UINT16 sco_idx; /* SCO handle */ diff --git a/bta/ag/bta_ag_main.c b/bta/ag/bta_ag_main.c index 020d54265..3a32a9d9e 100644 --- a/bta/ag/bta_ag_main.c +++ b/bta/ag/bta_ag_main.c @@ -318,11 +318,16 @@ static tBTA_AG_SCB *bta_ag_scb_alloc(void) /* initialize variables */ p_scb->in_use = TRUE; p_scb->sco_idx = BTM_INVALID_SCO_INDEX; - +#if (BTM_WBS_INCLUDED == TRUE ) + p_scb->codec_updated = FALSE; +#endif /* set up timers */ p_scb->act_timer.param = (UINT32) p_scb; p_scb->act_timer.p_cback = bta_ag_timer_cback; - +#if (BTM_WBS_INCLUDED == TRUE) + /* set eSCO mSBC setting to T2 as the preferred */ + p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2; +#endif APPL_TRACE_DEBUG("bta_ag_scb_alloc %d", bta_ag_scb_to_idx(p_scb)); break; } diff --git a/bta/ag/bta_ag_sco.c b/bta/ag/bta_ag_sco.c index 9081ba218..ec00514d4 100644 --- a/bta/ag/bta_ag_sco.c +++ b/bta/ag/bta_ag_sco.c @@ -69,7 +69,11 @@ enum }; #if (BTM_WBS_INCLUDED == TRUE ) -#define BTA_AG_NUM_CODECS 2 +#define BTA_AG_NUM_CODECS 3 +#define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD */ +#define BTA_AG_ESCO_SETTING_IDX_T1 1 /* eSCO setting for mSBC T1 */ +#define BTA_AG_ESCO_SETTING_IDX_T2 2 /* eSCO setting for mSBC T2 */ + static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] = { /* CVSD */ @@ -88,7 +92,20 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] = BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), BTM_ESCO_RETRANS_POWER /* Retransmission effort */ }, - /* mSBC */ + /* mSBC T1 */ + { + BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec), 8000 */ + BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec), 8000 */ + 8, /* 8 ms */ + BTM_VOICE_SETTING_TRANS, /* Inp Linear, Transparent, 2s Comp, 16bit */ + (BTM_SCO_PKT_TYPES_MASK_EV3 | /* Packet Types : EV3 + NO_2_EV3 */ + BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV5 | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 ), + BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */ + }, + /* mSBC T2*/ { BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec), 8000 */ BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec), 8000 */ @@ -102,6 +119,7 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] = } }; #else +/* WBS not included, CVSD by default */ static const tBTM_ESCO_PARAMS bta_ag_esco_params = { BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */ @@ -208,7 +226,7 @@ static void bta_ag_sco_disc_cback(UINT16 sco_idx) #if (BTM_SCO_HCI_INCLUDED == TRUE ) tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, TRUE); APPL_TRACE_DEBUG("bta_ag_sco_disc_cback sco close config status = %d", status); - /* SCO clean up here */ + /* SCO clean up here */ bta_dm_sco_co_close(); #endif @@ -216,14 +234,23 @@ static void bta_ag_sco_disc_cback(UINT16 sco_idx) /* Restore settings */ if(bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC) { - BTM_SetWBSCodec (BTM_SCO_CODEC_NONE); + /* set_sco_codec(BTM_SCO_CODEC_NONE); we should get a close */ BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD); - /* If SCO open was initiated by AG and failed for mSBC, try CVSD again. */ + /* If SCO open was initiated by AG and failed for mSBC, then attempt + mSBC with T1 settings i.e. 'Safe Settings'. If this fails, then switch to CVSD */ if (bta_ag_sco_is_opening (bta_ag_cb.sco.p_curr_scb)) { - bta_ag_cb.sco.p_curr_scb->codec_fallback = TRUE; - APPL_TRACE_DEBUG("Fallback to CVSD"); + if (bta_ag_cb.sco.p_curr_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) + { + APPL_TRACE_DEBUG("Fallback to mSBC T1 settings"); + bta_ag_cb.sco.p_curr_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T1; + } + else + { + APPL_TRACE_DEBUG("Fallback to CVSD settings"); + bta_ag_cb.sco.p_curr_scb->codec_fallback = TRUE; + } } } @@ -450,11 +477,23 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig) p_scb->codec_updated = TRUE; } + /* If WBS included, use CVSD by default, index is 0 for CVSD by initialization */ + /* If eSCO codec is mSBC, index is T2 or T1 */ if (esco_codec == BTM_SCO_CODEC_MSBC) - codec_index = esco_codec - 1; + { + if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) + { + codec_index = BTA_AG_ESCO_SETTING_IDX_T2; + } + else + { + codec_index = BTA_AG_ESCO_SETTING_IDX_T1; + } + } params = bta_ag_esco_params[codec_index]; #else + /* When WBS is not included, use CVSD by default */ params = bta_ag_esco_params; #endif @@ -464,7 +503,7 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig) if(!bta_ag_cb.sco.param_updated) { #if (BTM_WBS_INCLUDED == TRUE) - if (!codec_index) /* For non-WBS */ + if (esco_codec == BTM_SCO_CODEC_CVSD) /* For CVSD */ #endif { /* Use the application packet types (5 slot EV packets not allowed) */ @@ -518,8 +557,23 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig) /* tell sys to stop av if any */ bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); +#if (BTM_WBS_INCLUDED == TRUE ) + /* Allow any platform specific pre-SCO set up to take place */ + bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP,\ + esco_codec); + + /* This setting may not be necessary */ + /* To be verified with stable 2049 boards */ + if (esco_codec == BTA_AG_CODEC_MSBC) + BTM_WriteVoiceSettings (BTM_VOICE_SETTING_TRANS); + else + BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD); + /* save the current codec because sco_codec can be updated while SCO is open. */ + p_scb->inuse_codec = esco_codec; +#else /* Allow any platform specific pre-SCO set up to take place */ bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP); +#endif #if (BTM_SCO_HCI_INCLUDED == TRUE ) #if (BTM_WBS_INCLUDED == TRUE) @@ -532,26 +586,6 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig) sco_route = bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id); #endif -#if (BTM_WBS_INCLUDED == TRUE ) - if (esco_codec == BTA_AG_CODEC_MSBC) - { - /* Enable mSBC codec in fw */ - BTM_SetWBSCodec (esco_codec); - } - - /* Specify PCM input for SBC codec in fw */ - BTM_ConfigI2SPCM (esco_codec, (UINT8)HCI_BRCM_I2SPCM_IS_DEFAULT_ROLE, (UINT8)HCI_BRCM_I2SPCM_SAMPLE_DEFAULT, (UINT8)HCI_BRCM_I2SPCM_CLOCK_DEFAULT); - - /* This setting may not be necessary */ - /* To be verified with stable 2049 boards */ - if (esco_codec == BTA_AG_CODEC_MSBC) - BTM_WriteVoiceSettings (BTM_VOICE_SETTING_TRANS); - else - BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD); - - /* save the current codec because sco_codec can be updated while SCO is open. */ - p_scb->inuse_codec = esco_codec; -#endif #if (BTM_SCO_HCI_INCLUDED == TRUE ) /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */ @@ -586,6 +620,25 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig) #if (BTM_WBS_INCLUDED == TRUE ) /******************************************************************************* ** +** Function bta_ag_attempt_msbc_safe_settings +** +** Description Checks if ESCO connection needs to be attempted using mSBC T1(safe) settings +** +** +** Returns TRUE if T1 settings has to be used, FALSE otherwise +** +*******************************************************************************/ +BOOLEAN bta_ag_attempt_msbc_safe_settings(tBTA_AG_SCB *p_scb) +{ + if (p_scb->svc_conn && p_scb->sco_codec == BTM_SCO_CODEC_MSBC && + p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T1) + return TRUE; + else + return FALSE; +} + +/******************************************************************************* +** ** Function bta_ag_cn_timer_cback ** ** Description @@ -627,7 +680,9 @@ void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb) { bta_ag_cb.sco.p_curr_scb = p_scb; - if (p_scb->codec_updated || p_scb->codec_fallback) + if ((p_scb->codec_updated || p_scb->codec_fallback || + bta_ag_attempt_msbc_safe_settings(p_scb)) && + (p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) { /* Change the power mode to Active until sco open is completed. */ bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); @@ -643,10 +698,11 @@ void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb) else { /* use same codec type as previous SCO connection, skip codec negotiation */ + APPL_TRACE_DEBUG("use same codec type as previous SCO connection,skip codec negotiation"); bta_ag_sco_codec_nego(p_scb, TRUE); } } -#endif +#endif /* (BTM_WBS_INCLUDED == TRUE ) */ /******************************************************************************* ** @@ -1399,7 +1455,12 @@ void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); +#if (BTM_WBS_INCLUDED == TRUE) + bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_ON, + p_scb->inuse_codec); +#else bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_ON); +#endif #if (BTM_SCO_HCI_INCLUDED == TRUE ) /* open SCO codec if SCO is routed through transport */ @@ -1410,6 +1471,10 @@ void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT); p_scb->retry_with_sco_only = FALSE; +#if (BTM_WBS_INCLUDED == TRUE) + /* reset to mSBC T2 settings as the preferred */ + p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2; +#endif } /******************************************************************************* @@ -1433,7 +1498,9 @@ void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) #if (BTM_WBS_INCLUDED == TRUE) /* codec_fallback is set when AG is initiator and connection failed for mSBC. */ - if (p_scb->codec_fallback && p_scb->svc_conn) + /* OR if codec is msbc and T2 settings failed, then retry Safe T1 settings */ + if ((p_scb->codec_fallback && p_scb->svc_conn) || + bta_ag_attempt_msbc_safe_settings(p_scb)) { bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E); } @@ -1452,12 +1519,15 @@ void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) #endif else { +#if (BTM_WBS_INCLUDED == TRUE) /* Indicate if the closing of audio is because of transfer */ - if (bta_ag_cb.sco.p_xfer_scb) - bta_ag_co_audio_state(handle, p_scb->app_id, BTA_AG_CO_AUD_STATE_OFF_XFER); - else - bta_ag_co_audio_state(handle, p_scb->app_id, BTA_AG_CO_AUD_STATE_OFF); - + bta_ag_co_audio_state(handle, p_scb->app_id,(bta_ag_cb.sco.p_xfer_scb)?\ + BTA_AG_CO_AUD_STATE_OFF_XFER:BTA_AG_CO_AUD_STATE_OFF,p_scb->inuse_codec); +#else + /* Indicate if the closing of audio is because of transfer */ + bta_ag_co_audio_state(handle, p_scb->app_id,(bta_ag_cb.sco.p_xfer_scb)?\ + BTA_AG_CO_AUD_STATE_OFF_XFER:BTA_AG_CO_AUD_STATE_OFF); +#endif bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E); bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); @@ -1472,6 +1542,9 @@ void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) /* call app callback */ bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT); +#if (BTM_WBS_INCLUDED == TRUE) + p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2; +#endif } p_scb->retry_with_sco_only = FALSE; } @@ -1531,12 +1604,14 @@ void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data /* tell sys to stop av if any */ bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); +#if (BTM_WBS_INCLUDED == FALSE ) /* Allow any platform specific pre-SCO set up to take place */ bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP); - -#if (BTM_WBS_INCLUDED == TRUE ) +#else /* When HS initiated SCO, it cannot be WBS. */ - BTM_ConfigI2SPCM (BTM_SCO_CODEC_CVSD, (UINT8)HCI_BRCM_I2SPCM_IS_DEFAULT_ROLE, (UINT8)HCI_BRCM_I2SPCM_SAMPLE_DEFAULT, (UINT8)HCI_BRCM_I2SPCM_CLOCK_DEFAULT); + /* Allow any platform specific pre-SCO set up to take place */ + bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP, + BTA_AG_CODEC_CVSD); #endif #if (BTM_SCO_HCI_INCLUDED == TRUE ) diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h index 85f82a0e5..62342cb76 100644 --- a/bta/include/bta_ag_api.h +++ b/bta/include/bta_ag_api.h @@ -229,7 +229,9 @@ typedef struct #define BTA_AG_MIC_EVT 8 /* Microphone volume changed */ #define BTA_AG_AT_CKPD_EVT 9 /* CKPD from the HS */ #define BTA_AG_DISABLE_EVT 30 /* AG disabled */ - +#if (BTM_WBS_INCLUDED == TRUE ) +#define BTA_AG_WBS_EVT 31 /* SCO codec info */ +#endif /* Values below are for HFP only */ #define BTA_AG_AT_A_EVT 10 /* Answer a call */ #define BTA_AG_AT_D_EVT 11 /* Place a call using number or memory dial */ @@ -247,7 +249,7 @@ typedef struct #define BTA_AG_AT_COPS_EVT 23 /* Query list of current calls */ #define BTA_AG_AT_UNAT_EVT 24 /* Unknown AT command */ #define BTA_AG_AT_CBC_EVT 25 /* Battery Level report from HF */ -#define BTA_AG_AT_BAC_EVT 26 /* Codec select */ +#define BTA_AG_AT_BAC_EVT 26 /* avablable codec */ #define BTA_AG_AT_BCS_EVT 27 /* Codec select */ typedef UINT8 tBTA_AG_EVT; @@ -257,6 +259,7 @@ typedef struct { UINT16 handle; UINT8 app_id; + tBTA_AG_STATUS status; } tBTA_AG_HDR; /* data associated with BTA_AG_REGISTER_EVT */ diff --git a/bta/include/bta_ag_co.h b/bta/include/bta_ag_co.h index c6a33920c..4ef3ce75c 100644 --- a/bta/include/bta_ag_co.h +++ b/bta/include/bta_ag_co.h @@ -60,11 +60,21 @@ BTA_API extern void bta_ag_co_init(void); ** BTA_AG_CO_AUD_STATE_OFF_XFER - Audio is closed pending transfer ** BTA_AG_CO_AUD_STATE_ON - Audio has been turned on ** BTA_AG_CO_AUD_STATE_SETUP - Audio is about to be turned on +** codec - if WBS support is compiled in, codec to going to be used is provided +** and when in BTA_AG_CO_AUD_STATE_SETUP, BTM_I2SPCMConfig() must be called with +** the correct platform parameters. +** in the other states codec type should not be ignored ** ** Returns void ** *******************************************************************************/ +#if (BTM_WBS_INCLUDED == TRUE ) +BTA_API extern void bta_ag_co_audio_state(UINT16 handle, UINT8 app_id, UINT8 state, + tBTA_AG_PEER_CODEC codec); + +#else BTA_API extern void bta_ag_co_audio_state(UINT16 handle, UINT8 app_id, UINT8 state); +#endif /******************************************************************************* ** diff --git a/btif/co/bta_ag_co.c b/btif/co/bta_ag_co.c old mode 100644 new mode 100755 index 56a11e679..13c1aff40 --- a/btif/co/bta_ag_co.c +++ b/btif/co/bta_ag_co.c @@ -37,6 +37,11 @@ #endif +/************************************************************************************ +** Externs +************************************************************************************/ +extern int set_audio_state(UINT16 handle, UINT16 codec, UINT8 state, void *param); + /******************************************************************************* ** ** Function bta_ag_co_init @@ -69,14 +74,53 @@ void bta_ag_co_init(void) ** BTA_AG_CO_AUD_STATE_OFF_XFER - Audio has been turned off (xfer) ** BTA_AG_CO_AUD_STATE_ON - Audio has been turned on ** BTA_AG_CO_AUD_STATE_SETUP - Audio is about to be turned on +** codec - if WBS support is compiled in, codec to going to be used is provided +** and when in BTA_AG_CO_AUD_STATE_SETUP, BTM_I2SPCMConfig() must be called with +** the correct platform parameters. +** in the other states codec type should not be ignored ** ** Returns void ** *******************************************************************************/ +#if (BTM_WBS_INCLUDED == TRUE ) +void bta_ag_co_audio_state(UINT16 handle, UINT8 app_id, UINT8 state, tBTA_AG_PEER_CODEC codec) +#else void bta_ag_co_audio_state(UINT16 handle, UINT8 app_id, UINT8 state) +#endif { - UNUSED(app_id); BTIF_TRACE_DEBUG("bta_ag_co_audio_state: handle %d, state %d", handle, state); + switch (state) + { + case BTA_AG_CO_AUD_STATE_OFF: +#if (BTM_WBS_INCLUDED == TRUE ) + BTIF_TRACE_DEBUG("bta_ag_co_audio_state(handle %d)::Closed (OFF), codec: 0x%x", + handle, codec); + set_audio_state(handle, codec, state, NULL); +#else + BTIF_TRACE_DEBUG("bta_ag_co_audio_state(handle %d)::Closed (OFF)", + handle); +#endif + break; + case BTA_AG_CO_AUD_STATE_OFF_XFER: + BTIF_TRACE_DEBUG("bta_ag_co_audio_state(handle %d)::Closed (XFERRING)", handle); + break; + case BTA_AG_CO_AUD_STATE_SETUP: +#if (BTM_WBS_INCLUDED == TRUE ) + set_audio_state(handle, codec, state, NULL); +#else + set_audio_state(handle, BTA_AG_CODEC_CVSD, state, NULL); +#endif + break; + default: + break; + } +#if (BTM_WBS_INCLUDED == TRUE ) + APPL_TRACE_DEBUG("bta_ag_co_audio_state(handle %d, app_id: %d, state %d, codec: 0x%x)", + handle, app_id, state, codec); +#else + APPL_TRACE_DEBUG("bta_ag_co_audio_state(handle %d, app_id: %d, state %d)", \ + handle, app_id, state); +#endif } diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c index bd9f8ff26..c0cc4df18 100644 --- a/btif/src/btif_hf.c +++ b/btif/src/btif_hf.c @@ -60,6 +60,7 @@ #define BTIF_HF_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT) #endif +#if (BTM_WBS_INCLUDED == TRUE ) #ifndef BTIF_HF_FEATURES #define BTIF_HF_FEATURES ( BTA_AG_FEAT_3WAY | \ BTA_AG_FEAT_ECNR | \ @@ -68,8 +69,21 @@ BTA_AG_FEAT_EXTERR | \ BTA_AG_FEAT_BTRH | \ BTA_AG_FEAT_VREC | \ + BTA_AG_FEAT_CODEC |\ BTA_AG_FEAT_UNAT) #endif +#else +#ifndef BTIF_HF_FEATURES +#define BTIF_HF_FEATURES ( BTA_AG_FEAT_3WAY | \ + BTA_AG_FEAT_ECNR | \ + BTA_AG_FEAT_REJECT | \ + BTA_AG_FEAT_ECS | \ + BTA_AG_FEAT_EXTERR | \ + BTA_AG_FEAT_BTRH | \ + BTA_AG_FEAT_VREC | \ + BTA_AG_FEAT_UNAT) +#endif +#endif #define BTIF_HF_CALL_END_TIMEOUT 6 @@ -156,6 +170,14 @@ static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB]; /************************************************************************************ ** Externs ************************************************************************************/ +/* By default, even though codec negotiation is enabled, we will not use WBS as the default +* codec unless this variable is set to TRUE. +*/ +#ifndef BTIF_HF_WBS_PREFERRED +#define BTIF_HF_WBS_PREFERRED FALSE +#endif + +BOOLEAN btif_conf_hf_force_wbs = BTIF_HF_WBS_PREFERRED; /************************************************************************************ ** Functions @@ -525,6 +547,18 @@ static void btif_hf_upstreams_evt(UINT16 event, char* p_param) &btif_hf_cb[idx].connected_bda); break; +#if (BTM_WBS_INCLUDED == TRUE ) + case BTA_AG_WBS_EVT: + BTIF_TRACE_DEBUG("BTA_AG_WBS_EVT Set codec status %d codec %d 1=CVSD 2=MSBC", \ + p_data->val.hdr.status, p_data->val.num); + if(p_data->val.num == BTA_AG_CODEC_CVSD) + { HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NO, &btif_hf_cb[idx].connected_bda);} + else if(p_data->val.num == BTA_AG_CODEC_MSBC) + {HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_YES, &btif_hf_cb[idx].connected_bda);} + else + {HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NONE, &btif_hf_cb[idx].connected_bda);} + break; +#endif /* Java needs to send OK/ERROR for these commands */ case BTA_AG_AT_CHLD_EVT: HAL_CBACK(bt_hf_callbacks, chld_cmd_cb, atoi(p_data->val.str), @@ -556,7 +590,30 @@ static void btif_hf_upstreams_evt(UINT16 event, char* p_param) case BTA_AG_AT_BTRH_EVT: send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED, idx); break; - + case BTA_AG_AT_BAC_EVT: + BTIF_TRACE_DEBUG("AG Bitmap of peer-codecs %d", p_data->val.num); +#if (BTM_WBS_INCLUDED == TRUE ) + /* If the peer supports mSBC and the BTIF prefferred codec is also mSBC, then + we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC at the time + of SCO connection establishment */ + if ((btif_conf_hf_force_wbs == TRUE) && (p_data->val.num & BTA_AG_CODEC_MSBC)) + { + BTIF_TRACE_EVENT("%s btif_hf override-Preferred Codec to MSBC", __FUNCTION__); + BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_MSBC); + } + else + { + BTIF_TRACE_EVENT("%s btif_hf override-Preferred Codec to CVSD", __FUNCTION__); + BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_CVSD); + } +#endif + break; + case BTA_AG_AT_BCS_EVT: + BTIF_TRACE_DEBUG("AG final seleded codec is %d 1=CVSD 2=MSBC", p_data->val.num); + /* no BTHF_WBS_NONE case, becuase HF1.6 supported device can send BCS */ + HAL_CBACK(bt_hf_callbacks, wbs_cb,(p_data->val.num == BTA_AG_CODEC_MSBC) ? \ + BTHF_WBS_YES : BTHF_WBS_NO, &btif_hf_cb[idx].connected_bda); + break; default: BTIF_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event); @@ -1362,6 +1419,34 @@ static void cleanup( void ) } } +/******************************************************************************* +** +** Function configure_wbs +** +** Description set to over-ride the current WBS configuration. +** It will not send codec setting cmd to the controller now. +** It just change the configure. +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t configure_wbs( bt_bdaddr_t *bd_addr , bthf_wbs_config_t config ) +{ + CHECK_BTHF_INIT(); + + int idx = btif_hf_idx_by_bdaddr(bd_addr); + + BTIF_TRACE_EVENT("%s config is %d", __FUNCTION__,config); + if (config == BTHF_WBS_YES) + BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_MSBC); + else if(config == BTHF_WBS_NO) + BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_CVSD); + else + BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_NONE); + + return BT_STATUS_SUCCESS; +} + static const bthf_interface_t bthfInterface = { sizeof(bthfInterface), init, @@ -1380,6 +1465,7 @@ static const bthf_interface_t bthfInterface = { clcc_response, phone_state_change, cleanup, + configure_wbs, }; /******************************************************************************* diff --git a/btif/src/btif_util.c b/btif/src/btif_util.c index 2a86e128d..693e76857 100644 --- a/btif/src/btif_util.c +++ b/btif/src/btif_util.c @@ -303,7 +303,9 @@ const char* dump_hf_event(UINT16 event) CASE_RETURN_STR(BTA_AG_MIC_EVT) CASE_RETURN_STR(BTA_AG_AT_CKPD_EVT) CASE_RETURN_STR(BTA_AG_DISABLE_EVT) - +#if (BTM_WBS_INCLUDED == TRUE ) + CASE_RETURN_STR(BTA_AG_WBS_EVT) +#endif CASE_RETURN_STR(BTA_AG_AT_A_EVT) CASE_RETURN_STR(BTA_AG_AT_D_EVT) CASE_RETURN_STR(BTA_AG_AT_CHLD_EVT) diff --git a/hci/include/bt_hci_bdroid.h b/hci/include/bt_hci_bdroid.h index ce98ea1be..b7e433048 100644 --- a/hci/include/bt_hci_bdroid.h +++ b/hci/include/bt_hci_bdroid.h @@ -78,6 +78,9 @@ #define HC_EVENT_LPM_IDLE_TIMEOUT 0x0100 #define HC_EVENT_EXIT 0x0200 #define HC_EVENT_EPILOG 0x0400 +#define HC_EVENT_TX_CMD 0x0800 + +#define MSG_CTRL_TO_HC_CMD 0x0100 /* evt mask used by HC_EVENT_TX_CMD */ /* Message event mask across Host/Controller lib and stack */ #define MSG_EVT_MASK 0xFF00 /* eq. BT_EVT_MASK */ @@ -98,6 +101,13 @@ /* Local Bluetooth Controller ID for BR/EDR */ #define LOCAL_BR_EDR_CONTROLLER_ID 0 +/* Definitions of audio codec type + * inherited from AG callout function "codec" parameter + */ +#define SCO_CODEC_NONE 0x0000 /* BTA_AG_CODEC_NONE/BTM_SCO_CODEC_NONE */ +#define SCO_CODEC_CVSD 0x0001 /* BTA_AG_CODEC_CVSD/BTM_SCO_CODEC_CVSD */ +#define SCO_CODEC_MSBC 0x0002 /* BTA_AG_CODEC_MSBC/BTM_SCO_CODEC_MSBC */ + /****************************************************************************** ** Type definitions and return values ******************************************************************************/ diff --git a/hci/include/bt_hci_lib.h b/hci/include/bt_hci_lib.h index 541ca6e30..261a22c79 100644 --- a/hci/include/bt_hci_lib.h +++ b/hci/include/bt_hci_lib.h @@ -57,6 +57,11 @@ typedef enum { BT_HC_LOGGING_ON, } bt_hc_logging_state_t; +/* commands to be used in LSB with MSG_CTRL_TO_HC_CMD */ +typedef enum { + BT_HC_AUDIO_STATE = 0, + BT_HC_CMD_MAX +} bt_hc_tx_cmd_t; /** Result of write request */ typedef enum { BT_HC_TX_SUCCESS, /* a buffer is fully processed and can be released */ @@ -186,6 +191,9 @@ typedef struct { /** Closes the interface */ void (*cleanup)( void ); + + /** sends commands to hc layer (e.g. SCO state) */ + int (*tx_cmd)(TRANSAC transac, char *p_buf, int len); } bt_hc_interface_t; diff --git a/hci/include/bt_vendor_lib.h b/hci/include/bt_vendor_lib.h index f774a1431..65d448bf4 100644 --- a/hci/include/bt_vendor_lib.h +++ b/hci/include/bt_vendor_lib.h @@ -143,6 +143,18 @@ typedef enum { BT_VND_OP_LPM_WAKE_SET_STATE, /* [operation] + * Perform any vendor specific commands related to audio state changes. + * [input param] + * a pointer to bt_vendor_op_audio_state_t indicating what audio state is + * set. + * [return] + * 0 - default, don't care. + * [callback] + * None. + */ + BT_VND_OP_SET_AUDIO_STATE, + +/* [operation] * The epilog call to the vendor module so that it can perform any * vendor-specific processes (e.g. send a HCI_RESET to BT Controller) * before the caller calls for cleanup(). @@ -193,6 +205,13 @@ typedef enum { BT_VND_OP_RESULT_FAIL, } bt_vendor_op_result_t; +/** audio (SCO) state changes triggering VS commands for configuration */ +typedef struct { + uint16_t handle; + uint16_t peer_codec; + uint16_t state; +} bt_vendor_op_audio_state_t; + /* * Bluetooth Host/Controller Vendor callback structure. */ @@ -286,6 +305,9 @@ typedef struct { /* notifies caller result of lpm enable/disable */ cfg_result_cb lpm_cb; + /* notifies the result of codec setting */ + cfg_result_cb audio_state_cb; + /* buffer allocation request */ malloc_cb alloc; diff --git a/hci/src/bt_hci_bdroid.c b/hci/src/bt_hci_bdroid.c index 6b0ccc5a0..93266af75 100644 --- a/hci/src/bt_hci_bdroid.c +++ b/hci/src/bt_hci_bdroid.c @@ -87,6 +87,7 @@ typedef struct pthread_t worker_thread; pthread_mutex_t mutex; pthread_cond_t cond; + BUFFER_Q cmd_q; uint8_t epilog_timer_created; timer_t epilog_timer_id; } bt_hc_cb_t; @@ -223,6 +224,7 @@ static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr) lib_running = 1; ready_events = 0; + utils_queue_init(&hc_cb.cmd_q); pthread_mutex_init(&hc_cb.mutex, NULL); pthread_cond_init(&hc_cb.cond, NULL); pthread_attr_init(&thread_attr); @@ -346,6 +348,49 @@ static int logging(bt_hc_logging_state_t state, char *p_path) return BT_HC_STATUS_SUCCESS; } +/** sends command HC controller to configure platform specific behaviour */ +static int tx_hc_cmd(TRANSAC transac, char *p_buf, int len) +{ + BTHCDBG("tx_hc_cmd: transac %p", transac); + if ((TRANSAC)0 != transac) + { + utils_enqueue(&hc_cb.cmd_q, (void *)transac); + bthc_signal_event(HC_EVENT_TX_CMD); + return BT_HC_STATUS_SUCCESS; + } + return BT_HC_STATUS_FAIL; +} + +/** handle HC controller command to configure platform specific behaviour */ +static int tx_hc_msg(HC_BT_HDR *p_msg) +{ + int ret_val = 0; + int event, sub_event; + BTHCDBG("tx_hc_msg: p_msg %p, event: 0x%x", (void *)p_msg, p_msg->event); + + event = p_msg->event & MSG_EVT_MASK; + sub_event = p_msg->event & MSG_SUB_EVT_MASK; + switch (event) + { + case MSG_CTRL_TO_HC_CMD: + { + switch (sub_event) + { + case BT_HC_AUDIO_STATE: + vendor_send_command(BT_VND_OP_SET_AUDIO_STATE, (p_msg+1)); + break; + default: + ALOGW("tx_hc_msg(sub_event: 0x%x) not supported", sub_event); + break; + } + } + break; + default: + ALOGW("tx_hc_msg(event: 0x%x) not supported", event); + break; + } + return ret_val; +} /** Closes the interface */ static void cleanup( void ) @@ -397,7 +442,8 @@ static const bt_hc_interface_t bluetoothHCLibInterface = { postload, transmit_buf, logging, - cleanup + cleanup, + tx_hc_cmd, }; @@ -540,6 +586,16 @@ static void *bt_hc_worker_thread(void *arg) lpm_wake_assert(); } + if (events & HC_EVENT_TX_CMD) + { + HC_BT_HDR *p_cmd_msg; + while ((p_cmd_msg = utils_dequeue(&hc_cb.cmd_q)) != NULL) + { + if ((0 >= tx_hc_msg(p_cmd_msg)) && bt_hc_cbacks) + bt_hc_cbacks->dealloc(p_cmd_msg); + } + } + if (events & HC_EVENT_EPILOG) { vendor_send_command(BT_VND_OP_EPILOG, NULL); diff --git a/hci/src/vendor.c b/hci/src/vendor.c index 2e5846cc5..bfda0254d 100644 --- a/hci/src/vendor.c +++ b/hci/src/vendor.c @@ -41,6 +41,7 @@ static bt_vendor_interface_t *vendor_interface; static void firmware_config_cb(bt_vendor_op_result_t result); static void sco_config_cb(bt_vendor_op_result_t result); static void low_power_mode_cb(bt_vendor_op_result_t result); +static void sco_audiostate_cb(bt_vendor_op_result_t result); static void *buffer_alloc(int size); static void buffer_free(void *buffer); static uint8_t transmit_cb(uint16_t opcode, void *buffer, tINT_CMD_CBACK callback); @@ -51,6 +52,7 @@ static const bt_vendor_callbacks_t vendor_callbacks = { firmware_config_cb, sco_config_cb, low_power_mode_cb, + sco_audiostate_cb, buffer_alloc, buffer_free, transmit_cb, @@ -134,6 +136,24 @@ static void low_power_mode_cb(bt_vendor_op_result_t result) { lpm_vnd_cback(result != BT_VND_OP_RESULT_SUCCESS); } +/****************************************************************************** +** +** Function sco_audiostate_cb +** +** Description HOST/CONTROLLER VENDOR LIB CALLBACK API - This function is +** called when the libbt-vendor completed vendor specific codec +** setup request +** +** Returns None +** +******************************************************************************/ +static void sco_audiostate_cb(bt_vendor_op_result_t result) +{ + uint8_t status = (result == BT_VND_OP_RESULT_SUCCESS) ? 0 : 1; + + ALOGI("sco_audiostate_cb(status: %d)",status); +} + // Called by vendor library when it needs an HCI buffer. static void *buffer_alloc(int size) { assert(bt_hc_cbacks != NULL); diff --git a/main/bte_main.c b/main/bte_main.c old mode 100644 new mode 100755 index 36f12d0fe..906f38318 --- a/main/bte_main.c +++ b/main/bte_main.c @@ -35,8 +35,8 @@ #include "btu.h" #include "bte.h" #include "bta_api.h" -#include "bt_hci_lib.h" #include "bt_utils.h" +#include "bt_hci_bdroid.h" /******************************************************************************* ** Constants & Macros @@ -492,6 +492,66 @@ void bte_main_lpm_wake_bt_device() } #endif // HCILP_INCLUDED + +/* NOTICE: + * Definitions for audio state structure, this type needs to match to + * the bt_vendor_op_audio_state_t type defined in bt_vendor_lib.h + */ +typedef struct { + UINT16 handle; + UINT16 peer_codec; + UINT16 state; +} bt_hc_audio_state_t; + +struct bt_audio_state_tag { + BT_HDR hdr; + bt_hc_audio_state_t audio; +}; + +/****************************************************************************** +** +** Function set_audio_state +** +** Description Sets audio state on controller state for SCO (PCM, WBS, FM) +** +** Parameters handle: codec related handle for SCO: sco cb idx, unused for +** codec: BTA_AG_CODEC_MSBC, BTA_AG_CODEC_CSVD or FM codec +** state: codec state, eg. BTA_AG_CO_AUD_STATE_SETUP +** param: future extensions, e.g. call-in structure/event. +** +** Returns None +** +******************************************************************************/ +int set_audio_state(UINT16 handle, UINT16 codec, UINT8 state, void *param) +{ + struct bt_audio_state_tag *p_msg; + int result = -1; + + APPL_TRACE_API("set_audio_state(handle: %d, codec: 0x%x, state: %d)", handle, + codec, state); + if (NULL != param) + APPL_TRACE_WARNING("set_audio_state() non-null param not supported"); + p_msg = (struct bt_audio_state_tag *)GKI_getbuf(sizeof(*p_msg)); + if (!p_msg) + return result; + p_msg->audio.handle = handle; + p_msg->audio.peer_codec = codec; + p_msg->audio.state = state; + + p_msg->hdr.event = MSG_CTRL_TO_HC_CMD | (MSG_SUB_EVT_MASK & BT_HC_AUDIO_STATE); + p_msg->hdr.len = sizeof(p_msg->audio); + p_msg->hdr.offset = 0; + /* layer_specific shall contain return path event! for BTA events! + * 0 means no return message is expected. */ + p_msg->hdr.layer_specific = 0; + if (bt_hc_if) + { + bt_hc_if->tx_cmd((TRANSAC)p_msg, (char *)(&p_msg->audio), sizeof(*p_msg)); + } + return result; +} + + /****************************************************************************** ** ** Function bte_main_hci_send -- 2.11.0