Merge branch 'fix/bluedroid_aireview_v6.1' into 'release/v6.1'

Fix/bluedroid aireview (v6.1)

See merge request espressif/esp-idf!51294
This commit is contained in:
Wang Meng Yang
2026-08-27 17:46:38 +08:00
3 changed files with 100 additions and 38 deletions

View File

@@ -201,7 +201,10 @@ static void bta_ag_sco_conn_cback(UINT16 sco_idx)
if (handle != 0 && p_scb)
{
BTM_ReadEScoLinkParms(sco_idx, &sco_data);
if (BTM_ReadEScoLinkParms(sco_idx, &sco_data) == BTM_MODE_UNSUPPORTED) {
APPL_TRACE_WARNING("ESCO link parameters not supported or disabled.");
return;
}
p_scb->link_type = sco_data.link_type;
p_scb->tx_interval = sco_data.tx_interval;
@@ -640,7 +643,7 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
}
else
{
if(p_scb->retry_with_sco_only){
if(p_scb->retry_with_sco_only) {
APPL_TRACE_API("retrying with SCO only");
}
p_scb->retry_with_sco_only = FALSE;

View File

@@ -678,7 +678,10 @@ static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
rem_bd = BTM_ReadScoBdAddr(sco_idx);
BTM_ReadEScoLinkParms (sco_idx, &sco_data);
if (BTM_ReadEScoLinkParms (sco_idx, &sco_data) == BTM_MODE_UNSUPPORTED) {
APPL_TRACE_WARNING("ESCO link parameters not supported or disabled.");
return;
}
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) {

View File

@@ -164,23 +164,8 @@ static void btm_esco_conn_rsp (UINT16 sco_inx, UINT8 hci_status, BD_ADDR bda,
p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
}
/* Reject the connect request if refused by caller or wrong state */
if (hci_status != HCI_SUCCESS || p_sco == NULL) {
if (p_sco) {
p_sco->state = (p_sco->state == SCO_ST_W4_CONN_RSP) ? SCO_ST_LISTENING
: SCO_ST_UNUSED;
}
if (!btm_cb.sco_cb.esco_supported) {
if (!btsnd_hcic_reject_conn (bda, hci_status)) {
BTM_TRACE_ERROR("Could not reject (e)SCO conn: No Buffer!!!");
}
} else {
if (!btsnd_hcic_reject_esco_conn (bda, hci_status)) {
BTM_TRACE_ERROR("Could not reject (e)SCO conn: No Buffer!!!");
}
}
} else { /* Connection is being accepted */
/* Accept only with a valid SCO control block; otherwise fall through to reject */
if (hci_status == HCI_SUCCESS && p_sco != NULL) {
p_sco->state = SCO_ST_CONNECTING;
p_setup = &p_sco->esco.setup;
/* If parameters not specified use the default */
@@ -220,8 +205,28 @@ static void btm_esco_conn_rsp (UINT16 sco_inx, UINT8 hci_status, BD_ADDR bda,
} else {
BTM_TRACE_ERROR("Could not accept SCO conn: No Buffer!!!");
}
return;
}
if (p_sco) {
p_sco->state = (p_sco->state == SCO_ST_W4_CONN_RSP) ? SCO_ST_LISTENING
: SCO_ST_UNUSED;
}
#else
UNUSED(sco_inx);
UNUSED(p_parms);
#endif
/* Reject must still be sent when BTM_MAX_SCO_LINKS is 0 (no SCO CB available) */
if (!btm_cb.sco_cb.esco_supported) {
if (!btsnd_hcic_reject_conn (bda, hci_status)) {
BTM_TRACE_ERROR("Could not reject (e)SCO conn: No Buffer!!!");
}
} else {
if (!btsnd_hcic_reject_esco_conn (bda, hci_status)) {
BTM_TRACE_ERROR("Could not reject (e)SCO conn: No Buffer!!!");
}
}
}
@@ -266,10 +271,13 @@ tBTM_STATUS BTM_ConfigScoPath (tBTM_SCO_ROUTE_TYPE path,
UNUSED(p_pcm_param);
btm_cb.sco_cb.sco_path = path;
if (path == BTM_SCO_ROUTE_PCM) {
btm_cb.sco_cb.p_data_cb = NULL;
return BTM_SUCCESS;
} else if (path == BTM_SCO_ROUTE_HCI) {
if (p_sco_data_cb) {
btm_cb.sco_cb.p_data_cb = p_sco_data_cb;
}else{
return BTM_ILLEGAL_VALUE;
}
}
@@ -314,8 +322,10 @@ void btm_sco_check_send_pkts (UINT16 sco_inx)
fixed_queue_length(p_ccb->xmit_data_q) + 1);
#endif
/* Don't go negative */
p_cb->xmit_window_size -= 1;
p_ccb->sent_not_acked += 1;
if (p_buf->offset != 0) {
p_cb->xmit_window_size -= 1;
p_ccb->sent_not_acked += 1;
}
// HCI_SCO_DATA_TO_LOWER(p_buf);
hci_sco_data_to_lower(p_buf);
@@ -352,9 +362,11 @@ void btm_sco_process_num_completed_pkts (UINT8 *p, UINT8 evt_len)
}
BTM_TRACE_DEBUG("%s, %d, %u", __FUNCTION__, handle, p_cb->xmit_window_size); //debug
p_ccb = &p_cb->sco_db[sco_inx];
p_ccb->sent_not_acked -= num_sent;
// don't go negative
if (p_ccb->sent_not_acked < 0) {
if (p_ccb->sent_not_acked >= num_sent) {
p_ccb->sent_not_acked -= num_sent;
}
else {
// don't go negative
BTM_TRACE_WARNING("SCO: un-acked underf: %u", p_ccb->sent_not_acked);
p_ccb->sent_not_acked = 0;
}
@@ -553,7 +565,9 @@ tBTM_STATUS BTM_WriteScoData (UINT16 sco_inx, BT_HDR *p_buf)
if (fixed_queue_length(p_ccb->xmit_data_q) >= BTM_SCO_XMIT_QUEUE_HIGH_WM) {
status = BTM_NO_RESOURCES;
}
fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
if (!fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT)) {
status = BTM_ERR_PROCESSING;
}
btm_sco_check_send_pkts (sco_inx);
} else {
BTM_TRACE_WARNING ("SCO xmit Q overflow, pkt dropped");
@@ -796,7 +810,7 @@ tBTM_STATUS BTM_CreateSco (BD_ADDR remote_bda, BOOLEAN is_orig, UINT16 pkt_types
for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING)
|| (p->state == SCO_ST_PEND_UNPARK))
&& (!memcmp (p->esco.data.bd_addr, remote_bda, BD_ADDR_LEN))) {
&& (p->rem_bd_known == TRUE && !memcmp (p->esco.data.bd_addr, remote_bda, BD_ADDR_LEN))) {
return (BTM_BUSY);
}
}
@@ -927,9 +941,19 @@ void btm_sco_chk_pend_unpark (UINT8 hci_status, UINT16 hci_handle)
{
BTM_TRACE_API("btm_sco_chk_pend_unpark -> (e)SCO Link for ACL handle 0x%04x, Desired Type %d, hci_status 0x%02x",
acl_handle, btm_cb.sco_cb.desired_sco_mode, hci_status);
if (hci_status != HCI_SUCCESS) {
p->state = SCO_ST_UNUSED;
if (p->p_disc_cb!=NULL) {
(*p->p_disc_cb)(xx);
}
}
if ((btm_send_connect_request(acl_handle, &p->esco.setup)) == BTM_CMD_STARTED) {
p->state = SCO_ST_CONNECTING;
}else{
p->state = SCO_ST_UNUSED;
if (p->p_disc_cb!=NULL) {
(*p->p_disc_cb)(xx);
}
}
}
}
@@ -963,6 +987,9 @@ void btm_sco_chk_pend_rolechange (UINT16 hci_handle)
if ((btm_send_connect_request(acl_handle, &p->esco.setup)) == BTM_CMD_STARTED) {
p->state = SCO_ST_CONNECTING;
}else{
p->state = SCO_ST_UNUSED;
if (p->p_disc_cb!=NULL)(*p->p_disc_cb)(xx);
}
}
}
@@ -1094,13 +1121,17 @@ void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle,
/* avoid calling disconnect callback because of sco creation race */
else if (hci_status != HCI_ERR_LMP_ERR_TRANS_COLLISION) {
p->state = SCO_ST_UNUSED;
(*p->p_disc_cb)(xx);
if (p->p_disc_cb!=NULL) {
(*p->p_disc_cb)(xx);
}
}
} else {
/* Notify the upper layer that incoming sco connection has failed. */
if (p->state == SCO_ST_CONNECTING) {
p->state = SCO_ST_UNUSED;
(*p->p_disc_cb)(xx);
if (p->p_disc_cb!=NULL) {
(*p->p_disc_cb)(xx);
}
} else {
p->state = SCO_ST_LISTENING;
}
@@ -1161,7 +1192,7 @@ UINT16 btm_find_scb_by_handle (UINT16 handle)
tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
if ((p->state == SCO_ST_CONNECTED) && (p->hci_handle == handle)) {
if ((p->state == SCO_ST_CONNECTED || p->state == SCO_ST_DISCONNECTING) && (p->hci_handle == handle)) {
return (xx);
}
}
@@ -1199,6 +1230,11 @@ tBTM_STATUS BTM_RemoveSco (UINT16 sco_inx)
p->hci_handle = BTM_INVALID_HCI_HANDLE;
p->state = SCO_ST_UNUSED;
p->esco.p_esco_cback = NULL; /* Deregister the eSCO event callback */
btm_sco_flush_sco_data(sco_inx);
p->rem_bd_known = FALSE;
if (p->p_disc_cb != NULL) {
(*p->p_disc_cb)(sco_inx);
}
return (BTM_SUCCESS);
}
@@ -1271,7 +1307,9 @@ BOOLEAN btm_sco_removed (UINT16 hci_handle, UINT8 reason)
p->hci_handle = BTM_INVALID_HCI_HANDLE;
p->rem_bd_known = FALSE;
p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */
(*p->p_disc_cb)(xx);
if ((*p->p_disc_cb) != NULL) {
(*p->p_disc_cb)(xx);
}
return TRUE;
}
@@ -1307,7 +1345,9 @@ void btm_sco_acl_removed (BD_ADDR bda)
p->state = SCO_ST_UNUSED;
p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */
(*p->p_disc_cb)(xx);
if (p->p_disc_cb != NULL) {
(*p->p_disc_cb)(xx);
}
}
}
}
@@ -1524,6 +1564,7 @@ tBTM_STATUS BTM_SetEScoMode (tBTM_SCO_TYPE sco_mode, tBTM_ESCO_PARAMS *p_parms)
BTM_TRACE_API("BTM_SetEScoMode -> mode %d", sco_mode);
} else {
p_esco->desired_sco_mode = BTM_LINK_TYPE_SCO;
p_def->packet_types = p_parms->packet_types;
p_def->packet_types &= BTM_SCO_LINK_ONLY_MASK;
p_def->retrans_effort = 0;
BTM_TRACE_API("BTM_SetEScoMode -> mode SCO (eSCO not supported)");
@@ -1653,6 +1694,10 @@ tBTM_STATUS BTM_ChangeEScoLinkParms (UINT16 sco_inx, tBTM_CHG_ESCO_PARAMS *p_par
return (BTM_WRONG_MODE);
}
if (p_parms == NULL) {
return (BTM_ILLEGAL_VALUE);
}
p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
p_setup = &p_sco->esco.setup;
@@ -1692,6 +1737,9 @@ tBTM_STATUS BTM_ChangeEScoLinkParms (UINT16 sco_inx, tBTM_CHG_ESCO_PARAMS *p_par
return (BTM_NO_RESOURCES);
} else {
p_parms->packet_types = temp_pkt_types;
p_setup->packet_types = temp_pkt_types;
p_setup->max_latency = p_parms->max_latency;
p_setup->retrans_effort = p_parms->retrans_effort;
}
}
@@ -1775,15 +1823,21 @@ void btm_esco_proc_conn_chg (UINT8 status, UINT16 handle, UINT8 tx_interval,
for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
if (p->state == SCO_ST_CONNECTED && handle == p->hci_handle) {
if (status == HCI_SUCCESS) {
p->esco.data.rx_pkt_len = rx_pkt_len;
p->esco.data.tx_pkt_len = tx_pkt_len;
p->esco.data.tx_interval = tx_interval;
p->esco.data.retrans_window = retrans_window;
}
/* If upper layer wants notification */
if (p->esco.p_esco_cback) {
memcpy(data.bd_addr, p->esco.data.bd_addr, BD_ADDR_LEN);
data.hci_status = status;
data.sco_inx = xx;
data.rx_pkt_len = p->esco.data.rx_pkt_len = rx_pkt_len;
data.tx_pkt_len = p->esco.data.tx_pkt_len = tx_pkt_len;
data.tx_interval = p->esco.data.tx_interval = tx_interval;
data.retrans_window = p->esco.data.retrans_window = retrans_window;
data.rx_pkt_len = p->esco.data.rx_pkt_len;
data.tx_pkt_len = p->esco.data.tx_pkt_len;
data.tx_interval = p->esco.data.tx_interval;
data.retrans_window = p->esco.data.retrans_window;
(*p->esco.p_esco_cback)(BTM_ESCO_CHG_EVT,
(tBTM_ESCO_EVT_DATA *)&data);
@@ -1842,6 +1896,7 @@ UINT8 BTM_GetNumScoLinks (void)
case SCO_ST_CONNECTED:
case SCO_ST_DISCONNECTING:
case SCO_ST_PEND_UNPARK:
case SCO_ST_PEND_ROLECHANGE:
num_scos++;
}
}
@@ -1869,7 +1924,8 @@ BOOLEAN btm_is_sco_active_by_bdaddr (BD_ADDR remote_bda)
/* If any SCO is being established to the remote BD address, refuse this */
for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
if ((!memcmp (p->esco.data.bd_addr, remote_bda, BD_ADDR_LEN)) && (p->state == SCO_ST_CONNECTED)) {
if (((p->state != SCO_ST_UNUSED &&
p->state != SCO_ST_LISTENING) && !memcmp (p->esco.data.bd_addr, remote_bda, BD_ADDR_LEN))) {
return (TRUE);
}
}