Merge branch 'feat/set_encoder_params_v5.5' into 'release/v5.5'

fix(bt/bluedroid): Handle stream reconfiguration via stream close and re-open for A2DP ACP(v5.5)

See merge request espressif/esp-idf!45465
This commit is contained in:
Wang Meng Yang
2026-02-25 10:27:59 +08:00
5 changed files with 40 additions and 4 deletions
@@ -468,6 +468,10 @@ static void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, t
* from the 2nd SEP. */
if ((bta_av_find_lcb(bd_addr, BTA_AV_LCB_FIND) != NULL) && (bta_av_is_scb_init(p_scb))) {
bta_av_set_scb_sst_incoming (p_scb);
/* Mark this forced switch so we can notify upper layers (BTC) from BTA thread
* when handling STR_CONFIG_IND_EVT. */
p_scb->force_incoming = TRUE;
APPL_TRACE_DEBUG("change state to incoming");
/* When ACP_CONNECT_EVT was received, we put first available scb to incoming state.
* Later when we receive AVDT_CONFIG_IND_EVT, we use a new p_scb and set its state to
@@ -1123,6 +1127,16 @@ void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
tBTA_AV_STR_MSG *p_msg = (tBTA_AV_STR_MSG *)p_data;
UNUSED(p_data);
/* If stream SSM was force-switched to INCOMING due to CONFIG_IND while in INIT,
* notify upper layers early so BTC can move to OPENING and handle upcoming config/open events. */
if (p_scb->force_incoming) {
tBTA_AV evt;
memset(&evt, 0, sizeof(evt));
bdcpy(evt.incoming.bd_addr, p_data->str_msg.bd_addr);
(*bta_av_cb.p_cback)(BTA_AV_INCOMING_CFG_EVT, &evt);
p_scb->force_incoming = FALSE;
}
local_sep = bta_av_get_scb_sep_type(p_scb, p_msg->handle);
p_scb->avdt_label = p_data->str_msg.msg.hdr.label;
memcpy(p_scb->cfg.codec_info, p_evt_cfg->codec_info, AVDT_CODEC_SIZE);
@@ -553,6 +553,7 @@ typedef struct {
BOOLEAN no_rtp_hdr; /* TRUE if add no RTP header*/
UINT8 disc_rsn; /* disconnection reason */
UINT16 uuid_int; /*intended UUID of Initiator to connect to */
BOOLEAN force_incoming; /* TRUE if stream SSM state is force-switched to INCOMING due to CONFIG_IND while in INIT, else FALSE */
} tBTA_AV_SCB;
#define BTA_AV_RC_ROLE_MASK 0x10
@@ -267,8 +267,13 @@ typedef UINT8 tBTA_AV_GET_TYPE;
#define BTA_AV_CA_STATUS_EVT 26 /* Cover Art Client status event */
#define BTA_AV_CA_DATA_EVT 27 /* Cover Art response body data */
/* Incoming stream configuration indication received while local stream SSM is in INIT state.
* This is used to notify upper layers (BTC) that the stream state was force-switched to INCOMING
* to handle the new signalling/configuration. */
#define BTA_AV_INCOMING_CFG_EVT 28
/* Max BTA event */
#define BTA_AV_MAX_EVT 28
#define BTA_AV_MAX_EVT 29
/* function types for call-out functions */
@@ -502,6 +507,10 @@ typedef struct {
UINT16 psc_mask;
} tBTA_AV_SNK_PSC_CFG;
/* data associated with BTA_AV_INCOMING_CFG_EVT */
typedef struct {
BD_ADDR bd_addr;
} tBTA_AV_INCOMING;
#if BTA_AV_CA_INCLUDED
@@ -547,6 +556,7 @@ typedef union {
tBTA_AV_RC_FEAT rc_feat;
tBTA_AV_DELAY delay;
tBTA_AV_SNK_PSC_CFG psc;
tBTA_AV_INCOMING incoming;
#if BTA_AV_CA_INCLUDED
tBTA_AV_CA_STATUS ca_status;
tBTA_AV_CA_DATA ca_data;
@@ -1110,8 +1110,8 @@ static BOOLEAN bta_av_co_audio_codec_cfg_matches_caps(UINT8 codec_id, const UINT
p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
/* Must match all items exactly except bitpool boundaries which can be adjusted */
if (!((p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF] & p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF]) &&
(p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF] & p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF]))) {
if ((~p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF] & p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF]) ||
(~p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF] & p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF])) {
APPL_TRACE_EVENT("FALSE %x %x %x %x",
p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF],
p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF],
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -224,6 +224,7 @@ UNUSED_ATTR static const char *dump_av_sm_event_name(btc_av_sm_event_t event)
CASE_RETURN_STR(BTA_AV_RECONFIG_EVT)
CASE_RETURN_STR(BTA_AV_SUSPEND_EVT)
CASE_RETURN_STR(BTA_AV_PENDING_EVT)
CASE_RETURN_STR(BTA_AV_INCOMING_CFG_EVT)
CASE_RETURN_STR(BTA_AV_META_MSG_EVT)
CASE_RETURN_STR(BTA_AV_REJECT_EVT)
CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT)
@@ -385,6 +386,16 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENING);
} break;
case BTA_AV_INCOMING_CFG_EVT: {
/* Upper layer notification that incoming CONFIG_IND was received while stream SSM was in INIT
* and BTA force-switched to INCOMING. BTC should move to OPENING so upcoming CONFIG/OPEN/START
* can be handled in the correct state, but MUST NOT call BTA_AvOpen() here to avoid
* restarting discovery/open procedure while config is already in progress. */
bdcpy(btc_av_cb.peer_bda.address, ((tBTA_AV *)p_data)->incoming.bd_addr);
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENING);
break;
}
case BTC_AV_DISCONNECT_REQ_EVT:
BTC_TRACE_WARNING("No Link At All.");
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0, 0);