From 6674d0f0e508658be27a0849fdd8fcd6183b735c Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Mon, 18 Dec 2023 17:00:23 +0800 Subject: [PATCH] fix(bt/bluedroid): Fixed SPP connection failure The connection failure is caused by the BTU and application layer status being out of sync. --- .../bluedroid/bta/include/bta/bta_jv_api.h | 2 +- .../bt/host/bluedroid/bta/jv/bta_jv_act.c | 48 ++++++++----------- .../bt/host/bluedroid/bta/jv/bta_jv_api.c | 3 +- .../bluedroid/bta/jv/include/bta_jv_int.h | 1 - .../bluedroid/btc/profile/std/spp/btc_spp.c | 33 ++++--------- 5 files changed, 29 insertions(+), 58 deletions(-) diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h index 241c97a86e..660ce5cf31 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h @@ -847,7 +847,7 @@ extern tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, ** BTA_JV_FAILURE, otherwise. ** *******************************************************************************/ -extern tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data); +extern tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, void *user_data); /******************************************************************************* ** diff --git a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c index eabb4ff258..214ef746af 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c @@ -294,11 +294,10 @@ tBTA_JV_RFC_CB *bta_jv_rfc_port_to_cb(UINT16 port_handle) return p_cb; } -static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb, BOOLEAN close_server) +static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb, BOOLEAN close_server, BOOLEAN close_pending) { tBTA_JV_STATUS status = BTA_JV_SUCCESS; BOOLEAN remove_server = FALSE; - int close_pending = 0; UINT8 used = 0, i, listen = 0; tPORT_STATE port_state; @@ -321,11 +320,11 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pc switch (p_pcb->state) { case BTA_JV_ST_CL_CLOSING: case BTA_JV_ST_SR_CLOSING: - APPL_TRACE_WARNING("bta_jv_free_sr_rfc_cb: return on closing, port state:%d, " + APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: return on closing, port state:%d, " "scn:%d, p_pcb:%p, user_data:%p", p_pcb->state, p_cb->scn, p_pcb, p_pcb->user_data); status = BTA_JV_FAILURE; - return status; + break; case BTA_JV_ST_CL_OPEN: case BTA_JV_ST_CL_OPENING: APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: %d, scn:%d," @@ -1729,6 +1728,7 @@ static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle, void* dat UINT16 lcid; tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */ tPORT_MGMT_CL_CALLBACK_ARG *p_mgmt_cb_arg = (tPORT_MGMT_CL_CALLBACK_ARG *)data; + void *user_data = NULL; APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback:code:%d, port_handle%d", code, port_handle); if (NULL == p_cb || NULL == p_cb->p_cback) { @@ -1758,13 +1758,14 @@ static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle, void* dat evt_data.rfc_close.async = FALSE; evt_data.rfc_close.status = BTA_JV_SUCCESS; } - //p_pcb->state = BTA_JV_ST_NONE; - //p_pcb->cong = FALSE; p_cback = p_cb->p_cback; - p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, p_pcb->user_data); - //bta_jv_free_rfc_cb(p_cb, p_pcb); - } + user_data = p_pcb->user_data; + // To free up resources. + p_pcb->state = BTA_JV_ST_CL_CLOSING; + bta_jv_free_rfc_cb(p_cb, p_pcb, FALSE, FALSE); + p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data); + } } /******************************************************************************* @@ -1937,7 +1938,6 @@ void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data) tBTA_JV_API_RFCOMM_CLOSE *cc = &(p_data->rfcomm_close); tBTA_JV_RFC_CB *p_cb = NULL; tBTA_JV_PCB *p_pcb = NULL; - tBTA_JV evt_data = {0}; APPL_TRACE_DEBUG("%s, rfc handle:%d",__func__, cc->handle); if (!cc->handle) { APPL_TRACE_ERROR("%s, rfc handle is null", __func__); @@ -1948,20 +1948,9 @@ void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data) if (!find_rfc_pcb(user_data, &p_cb, &p_pcb)) { return; } - if(cc->p_cback) { - evt_data.rfc_close.status = BTA_JV_SUCCESS; - evt_data.rfc_close.port_status = PORT_LOCAL_CLOSED; - evt_data.rfc_close.handle = cc->handle; - evt_data.rfc_close.async = TRUE; - if (p_pcb && (p_pcb->state == BTA_JV_ST_SR_LISTEN || - p_pcb->state == BTA_JV_ST_SR_OPEN || - p_pcb->state == BTA_JV_ST_CL_OPEN || - p_pcb->state == BTA_JV_ST_CL_OPENING)) { - evt_data.rfc_close.async = FALSE; - } - cc->p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data); - } - bta_jv_free_rfc_cb(p_cb, p_pcb, FALSE); + + bta_jv_free_rfc_cb(p_cb, p_pcb, FALSE, TRUE); + APPL_TRACE_DEBUG("%s: sec id in use:%d, rfc_cb in use:%d",__func__, get_sec_id_used(), get_rfc_cb_used()); } @@ -2062,7 +2051,7 @@ static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle, void *dat APPL_TRACE_ERROR("create new listen port, but upper layer reject connection"); p_pcb_new_listen->user_data = NULL; p_pcb->state = BTA_JV_ST_SR_LISTEN; - bta_jv_free_rfc_cb(p_cb, p_pcb_new_listen, FALSE); + bta_jv_free_rfc_cb(p_cb, p_pcb_new_listen, FALSE, FALSE); if (p_mgmt_cb_arg) { p_mgmt_cb_arg->accept = FALSE; } @@ -2102,10 +2091,11 @@ static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle, void *dat evt_data.rfc_close.async = FALSE; evt_data.rfc_close.status = BTA_JV_SUCCESS; } - //p_pcb->state = BTA_JV_ST_NONE; - p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data); - //bta_jv_free_rfc_cb(p_cb, p_pcb); + // To free up resources. + p_pcb->state = BTA_JV_ST_SR_CLOSING; + bta_jv_free_rfc_cb(p_cb, p_pcb, FALSE, FALSE); + p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data); APPL_TRACE_DEBUG("PORT_CLOSED after BTA_JV_RFCOMM_CLOSE_EVT: curr_sess:%d, max_sess:%d", p_cb->curr_sess, p_cb->max_sess); } @@ -2339,7 +2329,7 @@ void bta_jv_rfcomm_stop_server(tBTA_JV_MSG *p_data) } APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: p_pcb:%p, p_pcb->port_handle:%d", p_pcb, p_pcb->port_handle); - bta_jv_free_rfc_cb(p_cb, p_pcb, TRUE); + bta_jv_free_rfc_cb(p_cb, p_pcb, TRUE, FALSE); APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: sec id in use:%d, rfc_cb in use:%d", get_sec_id_used(), get_rfc_cb_used()); } diff --git a/components/bt/host/bluedroid/bta/jv/bta_jv_api.c b/components/bt/host/bluedroid/bta/jv/bta_jv_api.c index 7ca6f7d567..c0bd066dc7 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_api.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_api.c @@ -939,7 +939,7 @@ tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, ** BTA_JV_FAILURE, otherwise. ** *******************************************************************************/ -tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data) +tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, void *user_data) { tBTA_JV_STATUS status = BTA_JV_FAILURE; tBTA_JV_API_RFCOMM_CLOSE *p_msg; @@ -954,7 +954,6 @@ tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, tBTA_JV_RFCOMM_CBACK *p_cback, v p_msg->handle = handle; p_msg->p_cb = &bta_jv_cb.rfc_cb[hi]; p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1]; - p_msg->p_cback = p_cback; p_msg->user_data = user_data; bta_sys_sendmsg(p_msg); status = BTA_JV_SUCCESS; diff --git a/components/bt/host/bluedroid/bta/jv/include/bta_jv_int.h b/components/bt/host/bluedroid/bta/jv/include/bta_jv_int.h index af1e3699d3..d6cd785a85 100644 --- a/components/bt/host/bluedroid/bta/jv/include/bta_jv_int.h +++ b/components/bt/host/bluedroid/bta/jv/include/bta_jv_int.h @@ -340,7 +340,6 @@ typedef struct { UINT32 handle; tBTA_JV_RFC_CB *p_cb; tBTA_JV_PCB *p_pcb; - tBTA_JV_RFCOMM_CBACK *p_cback; void *user_data; } tBTA_JV_API_RFCOMM_CLOSE; #endif /* BTA_JV_RFCOMM_INCLUDED */ diff --git a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c index 4f9ce3eb01..d488be8e54 100644 --- a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c @@ -424,19 +424,6 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_open.handle); BTA_JvSetPmProfile(p_data->rfc_open.handle, BTA_JV_PM_ID_1, BTA_JV_CONN_OPEN); break; - case BTA_JV_RFCOMM_CLOSE_EVT: - slot = spp_find_slot_by_id(id); - if (!slot) { - BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event); - p_data->rfc_close.status = ESP_SPP_NO_CONNECTION; - break; - } - if (slot->rfc_handle && p_data->rfc_close.port_status != PORT_LOCAL_CLOSED) { - BTA_JvRfcommClose(slot->rfc_handle, NULL, (void *)slot->id); - } - p_data->rfc_close.status = BTA_JV_SUCCESS; - p_data->rfc_close.user_data = (void *)(uintptr_t)slot->id; - break; case BTA_JV_RFCOMM_DATA_IND_EVT: break; case BTA_JV_FREE_SCN_EVT: @@ -608,8 +595,7 @@ static void btc_spp_uninit(void) // first, remove all connection for (size_t i = 1; i <= MAX_RFC_PORTS; i++) { if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->is_server) { - BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, - (void *)spp_local_param.spp_slots[i]->id); + BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, (void *)spp_local_param.spp_slots[i]->id); } } // second, remove all server @@ -727,7 +713,7 @@ static void btc_spp_disconnect(btc_spp_args_t *arg) ret = ESP_SPP_NO_CONNECTION; break; } - BTA_JvRfcommClose(arg->disconnect.handle, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)slot->id); + BTA_JvRfcommClose(arg->disconnect.handle, (void *)slot->id); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); } while(0); @@ -835,9 +821,7 @@ static void btc_spp_stop_srv(btc_spp_args_t *arg) if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->is_server && spp_local_param.spp_slots[i]->sdp_handle > 0 && spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) { - BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, - (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, - (void *)spp_local_param.spp_slots[i]->id); + BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, (void *)spp_local_param.spp_slots[i]->id); } } } @@ -1175,28 +1159,27 @@ void btc_spp_cb_handler(btc_msg_t *msg) osi_mutex_unlock(&spp_local_param.spp_slot_mutex); break; case BTA_JV_RFCOMM_CLOSE_EVT: - param.close.status = p_data->rfc_close.status; + param.close.status = BTA_JV_SUCCESS; param.close.port_status = p_data->rfc_close.port_status; param.close.handle = p_data->rfc_close.handle; param.close.async = p_data->rfc_close.async; if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) { - btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, ¶m); osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - uint32_t id = (uintptr_t)p_data->rfc_close.user_data; - slot = spp_find_slot_by_id(id); + slot = spp_find_slot_by_handle(p_data->rfc_close.handle); if (!slot) { + param.close.status = ESP_SPP_NO_CONNECTION; osi_mutex_unlock(&spp_local_param.spp_slot_mutex); BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event); break; } spp_free_slot(slot); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); + btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, ¶m); } else { bool need_call = true; do { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - uint32_t id = (uintptr_t)p_data->rfc_close.user_data; - slot = spp_find_slot_by_id(id); + slot = spp_find_slot_by_handle(p_data->rfc_close.handle); if (!slot) { param.close.status = ESP_SPP_NO_CONNECTION; osi_mutex_unlock(&spp_local_param.spp_slot_mutex);