diff --git a/components/bt/host/bluedroid/bta/av/bta_av_aact.c b/components/bt/host/bluedroid/bta/av/bta_av_aact.c index a23f4e5f878..c0e73e670a1 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_aact.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_aact.c @@ -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); diff --git a/components/bt/host/bluedroid/bta/av/include/bta_av_int.h b/components/bt/host/bluedroid/bta/av/include/bta_av_int.h index 9d8e6dfd7a5..40535bb1c32 100644 --- a/components/bt/host/bluedroid/bta/av/include/bta_av_int.h +++ b/components/bt/host/bluedroid/bta/av/include/bta_av_int.h @@ -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 diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_av_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_av_api.h index 5a670bd07c7..d1331bf1cb6 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_av_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_av_api.h @@ -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; diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c index f2668e2e04a..eb6f7f40afd 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c @@ -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], diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c index e52102a845f..44f86950f27 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c @@ -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);