From dd906a91a5053514ab05c0f451a6f49f49e0fedf Mon Sep 17 00:00:00 2001 From: baohongde Date: Tue, 14 May 2019 15:19:07 +0800 Subject: [PATCH] components/bt: Enable mSBC and add decoder and encoder --- .../bta/hf_client/bta_hf_client_main.c | 12 +- .../bta/hf_client/bta_hf_client_sco.c | 30 +- .../bta/hf_client/include/bta_hf_client_int.h | 7 + .../bta/include/bta/bta_hf_client_co.h | 4 +- .../btc/profile/std/a2dp/btc_a2dp_sink.c | 2 +- .../profile/std/hf_client/bta_hf_client_co.c | 339 ++++++++++++++++-- .../common/include/common/bt_target.h | 20 +- .../sbc/decoder/include/oi_codec_sbc.h | 7 +- .../decoder/include/oi_codec_sbc_private.h | 3 +- .../sbc/decoder/srce/decoder-private.c | 9 +- .../external/sbc/decoder/srce/decoder-sbc.c | 11 +- .../bt/bluedroid/external/sbc/plc/sbc_plc.c | 26 +- .../bt/bluedroid/stack/btm/include/btm_int.h | 4 + .../bluedroid/stack/include/stack/btm_api.h | 2 +- 14 files changed, 417 insertions(+), 59 deletions(-) diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c index 16e67cf731..dcaf665dbc 100644 --- a/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c @@ -232,6 +232,8 @@ const tBTA_HF_CLIENT_ST_TBL bta_hf_client_st_tbl[] = { bta_hf_client_st_closing }; +const char *bta_hf_client_version = "1.6"; + /* HF Client control block */ #if BTA_DYNAMIC_MEMORY == FALSE tBTA_HF_CLIENT_CB bta_hf_client_cb; @@ -385,15 +387,11 @@ static void bta_hf_client_api_enable(tBTA_HF_CLIENT_DATA *p_data) bta_hf_client_cb.p_cback = p_data->api_enable.p_cback; /* check if mSBC support enabled */ -#if 0 // todo - char value[PROPERTY_VALUE_MAX]; - property_get("ro.bluetooth.hfp.ver", value, "0"); - if (strcmp(value, "1.6") == 0) { + if (strcmp(bta_hf_client_version, "1.6") == 0) { bta_hf_client_cb.msbc_enabled = TRUE; + } else{ + bta_hf_client_cb.msbc_enabled = FALSE; } -#else - bta_hf_client_cb.msbc_enabled = FALSE; -#endif bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c index 16efd66736..e9396f14a3 100644 --- a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c @@ -268,13 +268,28 @@ static void bta_hf_client_sco_conn_cback(UINT16 sco_idx) { BT_HDR *p_buf; UINT8 *rem_bd; + tBTM_ESCO_DATA sco_data; APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx); rem_bd = BTM_ReadScoBdAddr(sco_idx); + BTM_ReadEScoLinkParms (sco_idx, &sco_data); if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 && bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) { + + bta_hf_client_cb.scb.link_type = sco_data.link_type; + bta_hf_client_cb.scb.tx_interval = sco_data.tx_interval; + bta_hf_client_cb.scb.retrans_window = sco_data.retrans_window; + bta_hf_client_cb.scb.air_mode = sco_data.air_mode; + if (sco_data.air_mode == BTM_SCO_AIR_MODE_CVSD) { + bta_hf_client_cb.scb.tx_pkt_len = sco_data.tx_pkt_len * 2; + bta_hf_client_cb.scb.rx_pkt_len = sco_data.rx_pkt_len * 2; + } else { + bta_hf_client_cb.scb.tx_pkt_len = sco_data.tx_pkt_len; + bta_hf_client_cb.scb.rx_pkt_len = sco_data.rx_pkt_len; + } + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT; p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle; @@ -428,20 +443,20 @@ static void bta_hf_client_sco_event(UINT8 event) #if (BTM_SCO_HCI_INCLUDED == TRUE ) if (event == BTA_HF_CLIENT_SCO_CI_DATA_E) { - uint16_t pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE; - uint16_t len_to_send = 0; + UINT16 pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE; + UINT16 len_to_send = 0; while (true) { - p_buf = osi_malloc(sizeof(BT_HDR) + pkt_offset + BTM_SCO_DATA_SIZE_MAX); + p_buf = osi_calloc(sizeof(BT_HDR) + pkt_offset + p_scb->tx_pkt_len); if (!p_buf) { APPL_TRACE_WARNING("%s, no mem", __FUNCTION__); break; } p_buf->offset = pkt_offset; - p_buf->len = BTM_SCO_DATA_SIZE_MAX; - len_to_send = bta_hf_client_sco_co_out_data(p_buf->data + pkt_offset, BTM_SCO_DATA_SIZE_MAX); - if (len_to_send == BTM_SCO_DATA_SIZE_MAX) { + len_to_send = bta_hf_client_sco_co_out_data(p_buf->data + pkt_offset); + p_buf->len = len_to_send; + if (len_to_send == p_scb->tx_pkt_len) { // expect to get the exact size of data from upper layer if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) { tBTM_STATUS write_stat = BTM_WriteScoData(p_scb->sco_idx, p_buf); @@ -731,7 +746,8 @@ void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data) #if (BTM_SCO_HCI_INCLUDED == TRUE) bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_ON, 0); /* open SCO codec if SCO is routed through transport */ - bta_hf_client_sco_co_open(bta_hf_client_cb.scb.sco_idx, BTA_HFP_SCO_OUT_PKT_SIZE, BTA_HF_CLIENT_CI_SCO_DATA_EVT); + bta_hf_client_sco_co_open(bta_hf_client_cb.scb.sco_idx, bta_hf_client_cb.scb.air_mode, + bta_hf_client_cb.scb.tx_pkt_len, BTA_HF_CLIENT_CI_SCO_DATA_EVT); #endif if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) { diff --git a/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h index 2e3fab9c1b..b5b07b9c59 100644 --- a/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h +++ b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h @@ -157,6 +157,13 @@ typedef struct { tBTM_SCO_CODEC_TYPE negotiated_codec; /* negotiated codec */ TIMER_LIST_ENT colli_timer; /* Collision timer */ BOOLEAN colli_tmr_on; /* TRUE if collision timer is active */ + + UINT16 rx_pkt_len; + UINT16 tx_pkt_len; + UINT8 link_type; /* BTM_LINK_TYPE_SCO or BTM_LINK_TYPE_ESCO */ + UINT8 tx_interval; + UINT8 retrans_window; + UINT8 air_mode; } tBTA_HF_CLIENT_SCB; /* sco states */ diff --git a/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h b/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h index af53e6e318..eef1c6668c 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h +++ b/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h @@ -73,7 +73,7 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, ** Returns void ** *******************************************************************************/ -void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event); +void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 pkt_size, UINT16 event); /******************************************************************************* ** @@ -96,7 +96,7 @@ void bta_hf_client_sco_co_close(void); ** Returns number of bytes got from application ** *******************************************************************************/ -uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz); +uint32_t bta_hf_client_sco_co_out_data(UINT8 *p_buf); /******************************************************************************* ** diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c index 619e0143a2..a5d09b2ca1 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c @@ -516,7 +516,7 @@ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg btc_aa_snk_cb.rx_flush = FALSE; APPL_TRACE_EVENT("Reset to sink role"); status = OI_CODEC_SBC_DecoderReset(&btc_sbc_decoder_context, btc_sbc_decoder_context_data, - BTC_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 2, 2, FALSE); + BTC_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 2, 2, FALSE, FALSE); if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); } diff --git a/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c index a0e003872b..6b3830b5e7 100644 --- a/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c +++ b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c @@ -22,10 +22,17 @@ #if (BTM_SCO_HCI_INCLUDED == TRUE) +#include "btm_int.h" +#include "stack/btm_api.h" +#include "oi_codec_sbc.h" +#include "oi_status.h" +#include "sbc_encoder.h" + #if (PLC_INCLUDED == TRUE) #include "sbc_plc.h" typedef struct { + bool first_good_frame_found; sbc_plc_state_t plc_state; int16_t sbc_plc_out[SBC_FS]; } bta_hf_ct_plc_t; @@ -39,6 +46,31 @@ static bta_hf_ct_plc_t *bta_hf_ct_plc_ptr; #endif ///(PLC_INCLUDED == TRUE) + +#define HF_SBC_DEC_CONTEXT_DATA_LEN (CODEC_DATA_WORDS(1, SBC_CODEC_FAST_FILTER_BUFFERS)) +#define HF_SBC_DEC_PCM_DATA_LEN 240 +#define HF_SBC_ENC_PCM_DATA_LEN 240 + +#if HFP_DYNAMIC_MEMORY == FALSE +static OI_CODEC_SBC_DECODER_CONTEXT hf_sbc_decoder_context; +static OI_UINT32 hf_sbc_decoder_context_data[HF_SBC_DEC_CONTEXT_DATA_LEN]; +static OI_INT16 hf_sbc_decode_pcm_data[HF_SBC_DEC_PCM_DATA_LEN]; + +static SBC_ENC_PARAMS hf_sbc_encoder; +#else +static OI_CODEC_SBC_DECODER_CONTEXT *hf_sbc_decoder_context_ptr; +static OI_UINT32 *hf_sbc_decoder_context_data; +static OI_INT16 *hf_sbc_decode_pcm_data; +#define hf_sbc_decoder_context (*hf_sbc_decoder_context_ptr) + +static SBC_ENC_PARAMS *hf_sbc_encoder_ptr; +#define hf_sbc_encoder (*hf_sbc_encoder_ptr) +#endif /* HFP_DYNAMIC_MEMORY == FALSE */ + +static UINT8 hf_sequence_number = 0; +static UINT8 hf_air_mode; +static UINT8 hf_pkt_size; + /******************************************************************************* ** ** Function bta_hf_client_co_audio_state @@ -86,10 +118,56 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, { APPL_TRACE_EVENT("%s rx_bw %d, tx_bw %d, codec %d", __FUNCTION__, rx_bw, tx_bw, p_codec_info->codec_type); - return BTA_HFP_SCO_ROUTE_HCI; } +/******************************************************************************* + ** + ** Function bta_hf_dec_init + ** + ** Description Initialize decoding task + ** + ** Returns void + ** + *******************************************************************************/ +static void bta_hf_dec_init(void) { +#if (PLC_INCLUDED == TRUE) + sbc_plc_init(&(bta_hf_ct_plc.plc_state)); +#endif ///(PLC_INCLUDED == TRUE) + + OI_STATUS status; + + status = OI_CODEC_SBC_DecoderReset(&hf_sbc_decoder_context, hf_sbc_decoder_context_data, + HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 1, 1, FALSE, TRUE); + if (!OI_SUCCESS(status)) { + APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); + } +} + +/******************************************************************************* + ** + ** Function bta_hf_enc_init + ** + ** Description Initialize encoding task + ** + ** Returns void + ** + *******************************************************************************/ +static void bta_hf_enc_init(void) { + hf_sequence_number = 0; + + hf_sbc_encoder.sbc_mode = SBC_MODE_MSBC; + hf_sbc_encoder.s16NumOfBlocks = 15; + hf_sbc_encoder.s16NumOfSubBands = 8; + hf_sbc_encoder.s16AllocationMethod = SBC_LOUDNESS; + hf_sbc_encoder.s16BitPool = 26; + hf_sbc_encoder.s16ChannelMode = SBC_MONO; + hf_sbc_encoder.s16NumOfChannels = 1; + hf_sbc_encoder.s16SamplingFreq = SBC_sf16000; + + SBC_Encoder_Init(&(hf_sbc_encoder)); +} + /******************************************************************************* ** ** Function bta_hf_client_sco_co_open @@ -100,23 +178,78 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, ** Returns void ** *******************************************************************************/ -void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event) +void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 pkt_size, UINT16 event) { APPL_TRACE_EVENT("%s hdl %x, pkt_sz %u, event %u", __FUNCTION__, handle, pkt_size, event); -#if (PLC_INCLUDED == TRUE) + hf_air_mode = air_mode; + hf_pkt_size = pkt_size; + if (air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { #if (HFP_DYNAMIC_MEMORY == TRUE) - if ((bta_hf_ct_plc_ptr = (bta_hf_ct_plc_t *)osi_malloc(sizeof(bta_hf_ct_plc_t))) == NULL) { - APPL_TRACE_ERROR("%s malloc fail.", __FUNCTION__); - return; - } - memset((void *)bta_hf_ct_plc_ptr, 0, sizeof(bta_hf_ct_plc_t)); + hf_sbc_decoder_context_ptr = osi_calloc(sizeof(OI_CODEC_SBC_DECODER_CONTEXT)); + hf_sbc_decoder_context_data = osi_calloc(HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32)); + hf_sbc_decode_pcm_data = osi_calloc(HF_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16)); + if (!hf_sbc_decoder_context_ptr || !hf_sbc_decoder_context_data || !hf_sbc_decode_pcm_data) { + APPL_TRACE_ERROR("%s failed to allocate SBC decoder", __FUNCTION__); + goto error_exit; + } + + hf_sbc_encoder_ptr = osi_calloc(sizeof(SBC_ENC_PARAMS)); + + if (!hf_sbc_encoder_ptr) { + APPL_TRACE_ERROR("%s failed to allocate SBC encoder", __FUNCTION__); + goto error_exit; + } + +#if (PLC_INCLUDED == TRUE) + bta_hf_ct_plc_ptr = (bta_hf_ct_plc_t *)osi_calloc(sizeof(bta_hf_ct_plc_t)); + if (!bta_hf_ct_plc_ptr) { + APPL_TRACE_ERROR("%s malloc fail.", __FUNCTION__); + goto error_exit; + } +#endif ///(PLC_INCLUDED == TRUE) + #endif /// (HFP_DYNAMIC_MEMORY == TRUE) - sbc_plc_init(&(bta_hf_ct_plc.plc_state)); + bta_hf_dec_init(); + bta_hf_enc_init(); + + return; + +error_exit:; +#if (HFP_DYNAMIC_MEMORY == TRUE) + if (hf_sbc_decoder_context_ptr) { + osi_free(hf_sbc_decoder_context_ptr); + hf_sbc_decoder_context_ptr = NULL; + } + if (hf_sbc_decoder_context_data) { + osi_free(hf_sbc_decoder_context_data); + hf_sbc_decoder_context_data = NULL; + } + if (hf_sbc_decode_pcm_data) { + osi_free(hf_sbc_decode_pcm_data); + hf_sbc_decode_pcm_data = NULL; + } + if (hf_sbc_encoder_ptr) { + osi_free(hf_sbc_encoder_ptr); + hf_sbc_encoder_ptr = NULL; + } + +#if (PLC_INCLUDED == TRUE) + if (bta_hf_ct_plc_ptr) { + osi_free(bta_hf_ct_plc_ptr); + bta_hf_ct_plc_ptr = NULL; + } #endif ///(PLC_INCLUDED == TRUE) + +#endif /// (HFP_DYNAMIC_MEMORY == TRUE) + } else { + // Nothing to do + } + + return; } /******************************************************************************* @@ -133,14 +266,66 @@ void bta_hf_client_sco_co_close(void) { APPL_TRACE_EVENT("%s", __FUNCTION__); + if (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { #if (PLC_INCLUDED == TRUE) - sbc_plc_deinit(&(bta_hf_ct_plc.plc_state)); + sbc_plc_deinit(&(bta_hf_ct_plc.plc_state)); + bta_hf_ct_plc.first_good_frame_found = FALSE; #if (HFP_DYNAMIC_MEMORY == TRUE) - osi_free(bta_hf_ct_plc_ptr); + osi_free(bta_hf_ct_plc_ptr); #endif /// (HFP_DYNAMIC_MEMORY == TRUE) #endif ///(PLC_INCLUDED == TRUE) + +#if (HFP_DYNAMIC_MEMORY == TRUE) + osi_free(hf_sbc_decoder_context_ptr); + hf_sbc_decoder_context_ptr = NULL; + + osi_free(hf_sbc_decoder_context_data); + hf_sbc_decoder_context_data = NULL; + + osi_free(hf_sbc_decode_pcm_data); + hf_sbc_decode_pcm_data = NULL; + + osi_free(hf_sbc_encoder_ptr); + hf_sbc_encoder_ptr = NULL; +#endif /* HFP_DYNAMIC_MEMORY == TRUE */ + } else { + // Nothing to do + } +} + +/******************************************************************************* +** +** Function bta_hf_client_h2_header +** +** Description This function is called to fill in H2 header +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_h2_header(UINT16 *p_buf) +{ + // H2: Header with synchronization word and sequence number +#define BTA_HF_H2_HEADER 0x0801 +#define BTA_HF_H2_HEADER_BIT0_MASK (1 << 0) +#define BTA_HF_H2_HEADER_BIT1_MASK (1 << 1) +#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 12 +#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET2 13 +#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET1 14 +#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 15 + + UINT16 h2_header = BTA_HF_H2_HEADER; + UINT8 h2_header_sn0 = hf_sequence_number & BTA_HF_H2_HEADER_BIT0_MASK; + UINT8 h2_header_sn1 = hf_sequence_number & BTA_HF_H2_HEADER_BIT1_MASK; + h2_header |= (h2_header_sn0 << BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 + | h2_header_sn0 << BTA_HF_H2_HEADER_SN0_BIT_OFFSET2 + | h2_header_sn1 << (BTA_HF_H2_HEADER_SN1_BIT_OFFSET1 - 1) + | h2_header_sn1 << (BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 - 1) + ); + + hf_sequence_number++; + *p_buf = h2_header; } /******************************************************************************* @@ -152,9 +337,101 @@ void bta_hf_client_sco_co_close(void) ** Returns number of bytes got from application ** *******************************************************************************/ -uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz) +uint32_t bta_hf_client_sco_co_out_data(UINT8 *p_buf) { - return btc_hf_client_outgoing_data_cb_to_app(p_buf, sz); + if (hf_air_mode == BTM_SCO_AIR_MODE_CVSD) { + // CVSD + return btc_hf_client_outgoing_data_cb_to_app(p_buf, hf_pkt_size); + } else if (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { + // mSBC + UINT32 size = btc_hf_client_outgoing_data_cb_to_app((UINT8 *)hf_sbc_encoder.as16PcmBuffer, HF_SBC_ENC_PCM_DATA_LEN); + if (size != HF_SBC_ENC_PCM_DATA_LEN){ + return 0; + } + + bta_hf_client_h2_header((UINT16 *)p_buf); + hf_sbc_encoder.pu8Packet = p_buf + 2; + + SBC_Encoder(&hf_sbc_encoder); + if (hf_sbc_encoder.u16PacketLength == BTM_ESCO_DATA_SIZE) { + return BTM_ESCO_DATA_SIZE_MAX; + } else { + return 0; + } + } else { + APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, hf_air_mode); + return 0; + } +} + +/******************************************************************************* +** +** Function bta_hf_client_decode_msbc_frame +** +** Description This function is called decode a mSBC frame +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN is_bad_frame){ + OI_STATUS status; + const OI_BYTE *zero_signal_frame_data; + UINT8 zero_signal_frame_len = BTM_ESCO_DATA_SIZE; + UINT32 sbc_frame_len = HF_SBC_DEC_PCM_DATA_LEN; + + if (is_bad_frame){ + status = OI_CODEC_SBC_CHECKSUM_MISMATCH; + } else { + status = OI_CODEC_SBC_DecodeFrame(&hf_sbc_decoder_context, (const OI_BYTE **)data, + (OI_UINT32 *)length, + (OI_INT16 *)hf_sbc_decode_pcm_data, + (OI_UINT32 *)&sbc_frame_len); + } + +// PLC_INCLUDED will be set to TRUE when enabling Wide Band Speech +#if (PLC_INCLUDED == TRUE) + switch(status){ + case OI_OK: + bta_hf_ct_plc.first_good_frame_found = TRUE; + sbc_plc_good_frame(&(bta_hf_ct_plc.plc_state), (int16_t *)hf_sbc_decode_pcm_data, bta_hf_ct_plc.sbc_plc_out); + case OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA: + case OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA: + case OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA: + break; + case OI_CODEC_SBC_NO_SYNCWORD: + case OI_CODEC_SBC_CHECKSUM_MISMATCH: + if (!bta_hf_ct_plc.first_good_frame_found) { + break; + } + zero_signal_frame_data = sbc_plc_zero_signal_frame(); + sbc_frame_len = HF_SBC_DEC_PCM_DATA_LEN; + status = OI_CODEC_SBC_DecodeFrame(&hf_sbc_decoder_context, &zero_signal_frame_data, + (OI_UINT32 *)&zero_signal_frame_len, + (OI_INT16 *)hf_sbc_decode_pcm_data, + (OI_UINT32 *)&sbc_frame_len); + + sbc_plc_bad_frame(&(bta_hf_ct_plc.plc_state), hf_sbc_decode_pcm_data, bta_hf_ct_plc.sbc_plc_out); + break; + case OI_STATUS_INVALID_PARAMETERS: + // This caused by corrupt frames. + // The codec apparently does not recover from this. + // Re-initialize the codec. + APPL_TRACE_ERROR("Frame decode error: OI_STATUS_INVALID_PARAMETERS"); + + if (!OI_SUCCESS(OI_CODEC_SBC_DecoderReset(&hf_sbc_decoder_context, hf_sbc_decoder_context_data, + HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 1, 1, FALSE, TRUE))) { + APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); + } + break; + default: + APPL_TRACE_ERROR("Frame decode error: %d", status); + break; + } +#endif ///(PLC_INCLUDED == TRUE) + + if (OI_SUCCESS(status)){ + btc_hf_client_incoming_data_cb_to_app((const uint8_t *)(bta_hf_ct_plc.sbc_plc_out), sbc_frame_len); + } } /******************************************************************************* @@ -168,18 +445,40 @@ uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz) *******************************************************************************/ void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status) { - UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; - UINT8 pkt_size = 0; + UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; + UINT8 pkt_size = 0; + UINT16 handle, sco_index; - STREAM_SKIP_UINT16(p); + STREAM_TO_UINT16 (handle, p); STREAM_TO_UINT8 (pkt_size, p); - if(status != BTM_SCO_DATA_CORRECT){ - APPL_TRACE_DEBUG("%s: not a correct frame(%d).", __func__, status); + handle = BTMD_GET_HANDLE (handle); + sco_index = btm_find_scb_by_handle(handle); + tSCO_CONN *sco_p = &btm_cb.sco_cb.sco_db[sco_index]; + + if (sco_p->esco.data.air_mode == BTM_SCO_AIR_MODE_CVSD) { + // CVSD + if(status != BTM_SCO_DATA_CORRECT){ + APPL_TRACE_DEBUG("%s: not a correct frame(%d).", __func__, status); + } + btc_hf_client_incoming_data_cb_to_app(p, pkt_size); + } else if (sco_p->esco.data.air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { + // mSBC + BOOLEAN is_bad_frame = false; + UINT8 msbc_frame_size = BTM_ESCO_DATA_SIZE; + if (pkt_size < msbc_frame_size) { + is_bad_frame = true; + } + if (status != BTM_SCO_DATA_CORRECT) { + is_bad_frame = true; + } + UINT8 *data = p; + bta_hf_client_decode_msbc_frame(&data, &pkt_size, is_bad_frame); + } else { + APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, sco_p->esco.data.air_mode); } - btc_hf_client_incoming_data_cb_to_app(p, pkt_size); } #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ -#endif /* #if (BTA_HF_INCLUDED == TRUE) */ +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ \ No newline at end of file diff --git a/components/bt/bluedroid/common/include/common/bt_target.h b/components/bt/bluedroid/common/include/common/bt_target.h index 258c13d2d1..0c57d0e16f 100644 --- a/components/bt/bluedroid/common/include/common/bt_target.h +++ b/components/bt/bluedroid/common/include/common/bt_target.h @@ -87,6 +87,12 @@ #ifndef BTM_MAX_SCO_LINKS #define BTM_MAX_SCO_LINKS (1) #endif +#ifndef SBC_DEC_INCLUDED +#define SBC_DEC_INCLUDED TRUE +#endif +#ifndef SBC_ENC_INCLUDED +#define SBC_ENC_INCLUDED TRUE +#endif #endif /* CONFIG_HFP_HF_ENABLE */ #if CONFIG_BT_SSP_ENABLED @@ -152,13 +158,13 @@ #ifndef CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM #define BLE_ADV_REPORT_FLOW_CONTROL_NUM 100 -#else +#else #define BLE_ADV_REPORT_FLOW_CONTROL_NUM CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM #endif /* CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM */ #ifndef CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD #define BLE_ADV_REPORT_DISCARD_THRSHOLD 20 -#else +#else #define BLE_ADV_REPORT_DISCARD_THRSHOLD CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD #endif /* CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD */ @@ -610,6 +616,16 @@ #define BTM_SCO_DATA_SIZE_MAX 120 //240 #endif +/* max TX eSCO data packet size */ +#ifndef BTM_ESCO_DATA_SIZE_MAX +#define BTM_ESCO_DATA_SIZE_MAX 60 +#endif + +/* TX eSCO data packet size */ +#ifndef BTM_ESCO_DATA_SIZE +#define BTM_ESCO_DATA_SIZE 57 +#endif + /* The size in bytes of the BTM inquiry database. 5 As Default */ #ifndef BTM_INQ_DB_SIZE #define BTM_INQ_DB_SIZE 5 diff --git a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h index 6f31348957..643bd82cc5 100644 --- a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h +++ b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h @@ -78,6 +78,9 @@ Declarations of codec functions, data types, and macros. #define OI_SBC_ENHANCED_SYNCWORD 0x9d #define OI_mSBC_SYNCWORD 0xad +#define OI_SBC_MODE_STD 0 +#define OI_SBC_MODE_MSBC 1 + /**@name Sampling frequencies */ /**@{*/ #define SBC_FREQ_16000 0 /**< The sampling frequency is 16 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */ @@ -200,6 +203,7 @@ typedef struct { OI_UINT8 restrictSubbands; OI_UINT8 enhancedEnabled; OI_UINT8 bufferedBlocks; + OI_UINT8 sbc_mode; /* OI_SBC_MODE_STD or OI_SBC_MODE_MSBC */ } OI_CODEC_SBC_DECODER_CONTEXT; typedef struct { @@ -236,7 +240,8 @@ OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_UINT32 decoderDataBytes, OI_UINT8 maxChannels, OI_UINT8 pcmStride, - OI_BOOL enhanced); + OI_BOOL enhanced, + OI_BOOL msbc_enable); /** * This function restricts the kind of SBC frames that the Decoder will diff --git a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc_private.h b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc_private.h index 4e3897614f..092d26f9af 100644 --- a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc_private.h +++ b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc_private.h @@ -170,7 +170,8 @@ INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_UINT32 decoderDataBytes, OI_BYTE maxChannels, OI_BYTE pcmStride, - OI_BOOL enhanced); + OI_BOOL enhanced, + OI_BOOL msbc_enable); INLINE OI_UINT16 OI_SBC_CalculateFrameAndHeaderlen(OI_CODEC_SBC_FRAME_INFO *frame, OI_UINT *headerLen_); diff --git a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c index 1e4d73995e..f198f57933 100644 --- a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c +++ b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c @@ -47,7 +47,8 @@ INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_UINT32 decoderDataBytes, OI_BYTE maxChannels, OI_BYTE pcmStride, - OI_BOOL enhanced) + OI_BOOL enhanced, + OI_BOOL msbc_enable) { OI_UINT i; OI_STATUS status; @@ -65,6 +66,12 @@ INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, } #endif + if (msbc_enable) { + context->sbc_mode = OI_SBC_MODE_MSBC; + } else { + context->sbc_mode = OI_SBC_MODE_STD; + } + status = OI_CODEC_SBC_Alloc(&context->common, decoderData, decoderDataBytes, maxChannels, pcmStride); if (!OI_SUCCESS(status)) { diff --git a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c index b2cd75cec9..553b4eddd4 100644 --- a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c +++ b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c @@ -79,9 +79,9 @@ PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context, return OI_CODEC_SBC_NO_SYNCWORD; } #else // SBC_ENHANCED - - while (*frameBytes && (**frameData != OI_SBC_SYNCWORD) - && (**frameData != OI_mSBC_SYNCWORD)) { + while (*frameBytes + && (!(context->sbc_mode == OI_SBC_MODE_STD && **frameData == OI_SBC_SYNCWORD)) + && (!(context->sbc_mode == OI_SBC_MODE_MSBC && **frameData == OI_mSBC_SYNCWORD))) { (*frameBytes)--; (*frameData)++; } @@ -230,9 +230,10 @@ OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_UINT32 decoderDataBytes, OI_UINT8 maxChannels, OI_UINT8 pcmStride, - OI_BOOL enhanced) + OI_BOOL enhanced, + OI_BOOL msbc_enable) { - return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced); + return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced, msbc_enable); } OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, diff --git a/components/bt/bluedroid/external/sbc/plc/sbc_plc.c b/components/bt/bluedroid/external/sbc/plc/sbc_plc.c index b44593082e..dceae9a849 100644 --- a/components/bt/bluedroid/external/sbc/plc/sbc_plc.c +++ b/components/bt/bluedroid/external/sbc/plc/sbc_plc.c @@ -50,21 +50,25 @@ static float rcos[SBC_OLAL] = { // 0.96984631f,0.88302222f, 0.75f,0.58682409f, // 0.41317591f, 0.25f,0.11697778f,0.09015369f}; + static float SqrtByCarmack(const float x){ - int i; - float x2, y; + union { + int i; + float y; + } float_int; + + float x2; const float threehalfs = 1.5f; x2 = x * 0.5f; - y = x; - i = *(int *)&y; - i = 0x5f375a86 - (i >> 1); - y = *(float *)&i; - y = y * (threehalfs - (x2 * y *y)); - // y = y * (threehalfs - (x2 * y *y)); - // y = y * (threehalfs - (x2 * y *y)); - - return (x * y); + float_int.y = x; + + float_int.i = 0x5f375a86 - (float_int.i >> 1); + float_int.y = float_int.y * (threehalfs - (x2 * float_int.y * float_int.y)); + // float_int.y = float_int.y * (threehalfs - (x2 * float_int.y * float_int.y)); + // float_int.y = float_int.y * (threehalfs - (x2 * float_int.y * float_int.y)); + + return (x * float_int.y); } static float absolute(float x){ diff --git a/components/bt/bluedroid/stack/btm/include/btm_int.h b/components/bt/bluedroid/stack/btm/include/btm_int.h index 79c3eff727..455ce7ca36 100644 --- a/components/bt/bluedroid/stack/btm/include/btm_int.h +++ b/components/bt/bluedroid/stack/btm/include/btm_int.h @@ -320,6 +320,10 @@ typedef UINT8 *BTM_BD_NAME_PTR; /* Pointer to Device name */ typedef tBTM_SEC_CBACK tBTM_SEC_CALLBACK; +#define BTM_DATA_HANDLE_MASK 0x0FFF + +#define BTMD_GET_HANDLE(u16) (UINT16)((u16) & BTM_DATA_HANDLE_MASK) + typedef void (tBTM_SCO_IND_CBACK) (UINT16 sco_inx) ; /* MACROs to convert from SCO packet types mask to ESCO and back */ diff --git a/components/bt/bluedroid/stack/include/stack/btm_api.h b/components/bt/bluedroid/stack/include/stack/btm_api.h index 6aa833c036..03a0e79d4d 100644 --- a/components/bt/bluedroid/stack/include/stack/btm_api.h +++ b/components/bt/bluedroid/stack/include/stack/btm_api.h @@ -992,7 +992,7 @@ typedef UINT8 tBTM_SCO_AIR_MODE_TYPE; #define BTM_VOICE_SETTING_TRANS ((UINT16) (HCI_INP_CODING_LINEAR | \ HCI_INP_DATA_FMT_2S_COMPLEMENT | \ - HCI_INP_SAMPLE_SIZE_16BIT | \ + HCI_INP_SAMPLE_SIZE_8BIT | \ HCI_AIR_CODING_FORMAT_TRANSPNT)) /******************* -- 2.40.0