From d783f9f02db746f35dde468a90e2546db321c9e5 Mon Sep 17 00:00:00 2001 From: linruihao Date: Tue, 15 Sep 2026 16:04:43 +0800 Subject: [PATCH] fix(bt/bluedroid): check HFP audio status before forwarding SCO data --- .../bt/host/bluedroid/api/esp_hf_client_api.c | 6 ++++-- .../host/bluedroid/api/include/api/esp_hf_ag_api.h | 2 ++ .../bluedroid/api/include/api/esp_hf_client_api.h | 3 +++ .../bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c | 4 ++-- .../btc/profile/std/hf_client/btc_hf_client.c | 13 +++++++++++++ .../btc/profile/std/include/btc_hf_client.h | 2 ++ 6 files changed, 26 insertions(+), 4 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_hf_client_api.c b/components/bt/host/bluedroid/api/esp_hf_client_api.c index 978a7f99e13..6ebeff75989 100644 --- a/components/bt/host/bluedroid/api/esp_hf_client_api.c +++ b/components/bt/host/bluedroid/api/esp_hf_client_api.c @@ -645,8 +645,10 @@ esp_err_t esp_hf_client_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, es return ESP_ERR_INVALID_ARG; } - BTA_HfClientAudioDataSend(sync_conn_hdl, (uint8_t *)audio_buf, audio_buf->data, audio_buf->data_len); - return ESP_OK; + if (btc_hf_client_audio_data_send(sync_conn_hdl, (uint8_t *)audio_buf, audio_buf->data, audio_buf->data_len) == BT_STATUS_SUCCESS) { + return ESP_OK; + } + return ESP_FAIL; } esp_err_t esp_hf_client_pcm_resample_init(uint32_t src_sps, uint32_t bits, uint32_t channels) diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h index 65020dfb937..662ec226bde 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h @@ -689,6 +689,8 @@ void esp_hf_ag_audio_buff_free(esp_hf_audio_buff_t *audio_buf); * If the length of the audio data is equal to preferred_frame_size indicated by * ESP_HF_AUDIO_STATE_EVT, then we can reduce one memory copy inside the Bluedroid stack. * This function is only used in the case that Voice Over HCI is enabled. + * On success, the stack takes ownership of audio_buf and will free it internally. + * On failure, the caller is responsible for freeing audio_buf with esp_hf_ag_audio_buff_free. * * @param[in] sync_conn_hdl: (e)SCO connection handle * diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h b/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h index 9ae45e33495..482117981bf 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h @@ -715,6 +715,8 @@ void esp_hf_client_audio_buff_free(esp_hf_audio_buff_t *audio_buf); * If the length of the audio data is equal to preferred_frame_size indicated by * ESP_HF_CLIENT_AUDIO_STATE_EVT, then we can reduce one memory copy inside the Bluedroid stack. * This function is only used in the case that Voice Over HCI is enabled. + * On success, the stack takes ownership of audio_buf and will free it internally. + * On failure, the caller is responsible for freeing audio_buf with esp_hf_client_audio_buff_free. * * @param[in] sync_conn_hdl: (e)SCO connection handle * @@ -724,6 +726,7 @@ void esp_hf_client_audio_buff_free(esp_hf_audio_buff_t *audio_buf); * - ESP_OK: success * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled * - ESP_ERR_INVALID_ARG: invalid parameter + * - ESP_FAIL: others * */ esp_err_t esp_hf_client_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf); diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c index 73d048f8139..78413302fe5 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c @@ -964,10 +964,10 @@ bt_status_t btc_hf_ci_sco_data(void) bt_status_t btc_hf_ag_audio_data_send(uint16_t sync_conn_hdl, uint8_t *p_buff_start, uint8_t *p_data, uint8_t data_len) { #if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) - /* currently, sync_conn_hdl is not used */ int idx = btc_hf_latest_connected_idx(); CHECK_HF_SLC_CONNECTED(idx); - if (idx != BTC_HF_INVALID_IDX) { + + if (sync_conn_hdl != ESP_INVALID_CONN_HANDLE && hf_local_param.btc_hf_cb[idx].sync_conn_hdl == sync_conn_hdl) { BTA_AgAudioDataSend(hf_local_param.btc_hf_cb[idx].handle, p_buff_start, p_data, data_len); return BT_STATUS_SUCCESS; } diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c b/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c index b4813c16337..ad8451b2314 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c @@ -352,6 +352,19 @@ bt_status_t btc_hf_client_disconnect_audio( bt_bdaddr_t *bd_addr ) return BT_STATUS_FAIL; } +bt_status_t btc_hf_client_audio_data_send(uint16_t sync_conn_hdl, uint8_t *p_buff_start, uint8_t *p_data, uint8_t data_len) +{ +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) + CHECK_HF_CLIENT_SLC_CONNECTED(); + + if (sync_conn_hdl != ESP_INVALID_CONN_HANDLE && hf_client_local_param.btc_hf_client_cb.sync_conn_hdl == sync_conn_hdl) { + BTA_HfClientAudioDataSend(sync_conn_hdl, p_buff_start, p_data, data_len); + return BT_STATUS_SUCCESS; + } +#endif + return BT_STATUS_FAIL; +} + /******************************************************************************* ** ** Function btc_hf_client_start_voice_recognition diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h index 7211d87cd62..04ca8034bf2 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h @@ -176,6 +176,8 @@ void btc_hf_client_incoming_data_cb_to_app(const uint8_t *data, uint32_t len); uint32_t btc_hf_client_outgoing_data_cb_to_app(uint8_t *data, uint32_t len); +bt_status_t btc_hf_client_audio_data_send(uint16_t sync_conn_hdl, uint8_t *p_buff_start, uint8_t *p_data, uint8_t data_len); + void btc_hf_client_get_profile_status(esp_hf_client_profile_status_t *param); #endif ///BTC_HF_CLIENT_INCLUDED == TRUE