diff --git a/components/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h b/components/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h index 7ad90b399b..982cbdaa85 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h @@ -124,7 +124,7 @@ typedef union { */ struct l2cap_srv_stop_evt_param { esp_bt_l2cap_status_t status; /*!< status */ - uint8_t psm; /*!< local psm */ + uint16_t psm; /*!< local psm */ } srv_stop; /*!< L2CAP callback param of ESP_BT_L2CAP_SRV_STOP_EVT */ /** 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 660ce5cf31..20c533a5f7 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 @@ -315,7 +315,7 @@ typedef struct { tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ UINT32 handle; /* The connection handle */ UINT8 sec_id; /* security ID used by this server */ - UINT8 scn; /* Server channe number */ + UINT8 scn; /* Server channel number */ BOOLEAN use_co; /* TRUE to use co_rfc_data */ } tBTA_JV_RFCOMM_START; @@ -378,6 +378,7 @@ typedef struct { typedef enum { BTA_JV_SERVER_START_FAILED, BTA_JV_SERVER_RUNNING, + BTA_JV_SERVER_CONNECTED, BTA_JV_SERVER_STATUS_MAX, } tBTA_JV_SERVER_STATUS; @@ -390,7 +391,7 @@ typedef struct { typedef struct { tBTA_JV_STATUS status; /* Status of the operation */ tBTA_JV_SERVER_STATUS server_status; /* Server status */ - UINT8 scn; /* Server channe number */ + UINT16 scn; /* Server channel number */ } tBTA_JV_FREE_SCN; @@ -822,7 +823,7 @@ extern tBTA_JV_STATUS BTA_JvRfcommConfig(BOOLEAN enable_l2cap_ertm); ** ** Function BTA_JvRfcommConnect ** -** Description This function makes an RFCOMM conection to a remote BD +** Description This function makes an RFCOMM connection to a remote BD ** Address. ** When the connection is initiated or failed to initiate, ** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_CL_INIT_EVT @@ -956,7 +957,7 @@ UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle); ** Parameters: handle, JV handle from RFCOMM or L2CAP ** app_id: app specific pm ID, can be BTA_JV_PM_ALL, see bta_dm_cfg.c for details ** BTA_JV_PM_ID_CLEAR: removes pm management on the handle. init_st is ignored and - ** BTA_JV_CONN_CLOSE is called implicitely + ** BTA_JV_CONN_CLOSE is called implicitly ** init_st: state after calling this API. typically it should be BTA_JV_CONN_OPEN ** ** Returns BTA_JV_SUCCESS, if the request is being processed. 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 5d232524cd..17eba5edd6 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c @@ -899,6 +899,7 @@ void bta_jv_free_scn(tBTA_JV_MSG *p_data) } case BTA_JV_CONN_TYPE_L2CAP: bta_jv_set_free_psm(scn); + user_data = (tBTA_JV_FREE_SCN_USER_DATA *)fc->user_data; if (fc->p_cback) { fc->p_cback(BTA_JV_FREE_SCN_EVT, (tBTA_JV *)&evt_data, (void *)user_data); } @@ -1389,6 +1390,7 @@ void bta_jv_l2cap_close(tBTA_JV_MSG *p_data) evt_data.handle = cc->handle; evt_data.status = bta_jv_free_l2c_cb(cc->p_cb); evt_data.async = FALSE; + evt_data.user_data = (void *)cc->user_data; if (cc->p_cback) { cc->p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data); @@ -1542,19 +1544,13 @@ void bta_jv_l2cap_start_server(tBTA_JV_MSG *p_data) void bta_jv_l2cap_stop_server(tBTA_JV_MSG *p_data) { tBTA_JV_L2C_CB *p_cb; - tBTA_JV_L2CAP_CLOSE evt_data; tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server); - tBTA_JV_L2CAP_CBACK *p_cback; - void *user_data; + for (int i = 0; i < BTA_JV_MAX_L2C_CONN; i++) { if (bta_jv_cb.l2c_cb[i].psm == ls->local_psm) { p_cb = &bta_jv_cb.l2c_cb[i]; - p_cback = p_cb->p_cback; - user_data = p_cb->user_data; - evt_data.handle = p_cb->handle; - evt_data.status = bta_jv_free_l2c_cb(p_cb); - evt_data.async = FALSE; - p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data); + bta_jv_free_l2c_cb(p_cb); + // Report event when free psm break; } } diff --git a/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c b/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c index ca96c09bb1..9155784fb8 100644 --- a/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c +++ b/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c @@ -361,12 +361,20 @@ static void *btc_l2cap_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d // to do break; case BTA_JV_FREE_SCN_EVT: - slot = l2cap_find_slot_by_id(id); - if (slot) { - l2cap_free_slot(slot); - } else { - BTC_TRACE_ERROR("%s unable to find L2CAP slot, event:%d!", __func__, event); - p_data->free_scn.status = ESP_BT_L2CAP_NO_CONNECTION; + if (user_data) { + id = ((tBTA_JV_FREE_SCN_USER_DATA *)user_data)->slot_id; + slot = l2cap_find_slot_by_id(id); + if (slot) { + if (((tBTA_JV_FREE_SCN_USER_DATA *)user_data)->server_status != BTA_JV_SERVER_CONNECTED) { + l2cap_free_slot(slot); + } else { + // Currently running in btu task, free in btc task. It will be free when handling the disconnect event. + } + } else { + BTC_TRACE_ERROR("%s unable to find L2CAP slot, event:%d!", __func__, event); + p_data->free_scn.status = ESP_BT_L2CAP_NO_CONNECTION; + } + osi_free(user_data); } break; default: @@ -464,6 +472,7 @@ static void btc_l2cap_init(void) static void btc_l2cap_uninit(void) { esp_bt_l2cap_status_t ret = ESP_BT_L2CAP_SUCCESS; + tBTA_JV_SERVER_STATUS server_status = BTA_JV_SERVER_RUNNING; do { if (!is_l2cap_init()) { @@ -474,7 +483,8 @@ static void btc_l2cap_uninit(void) osi_mutex_lock(&l2cap_local_param.l2cap_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); // first, remove all connection for (size_t i = 1; i <= BTA_JV_MAX_L2C_CONN; i++) { - if (l2cap_local_param.l2cap_slots[i] != NULL && !l2cap_local_param.l2cap_slots[i]->is_server) { + if (l2cap_local_param.l2cap_slots[i] != NULL && l2cap_local_param.l2cap_slots[i]->connected) { + server_status = BTA_JV_SERVER_CONNECTED; BTA_JvL2capClose(l2cap_local_param.l2cap_slots[i]->handle, (tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb, (void *)l2cap_local_param.l2cap_slots[i]->id); } @@ -487,8 +497,17 @@ static void btc_l2cap_uninit(void) (void *)l2cap_local_param.l2cap_slots[i]->id); } + tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA)); + if (user_data) { + user_data->server_status = server_status; + user_data->slot_id = l2cap_local_param.l2cap_slots[i]->id; + } else { + BTC_TRACE_ERROR("%s unable to malloc user data!", __func__); + assert(0); + } + BTA_JvFreeChannel(l2cap_local_param.l2cap_slots[i]->psm, BTA_JV_CONN_TYPE_L2CAP, - (tBTA_JV_RFCOMM_CBACK *)btc_l2cap_inter_cb, (void *)l2cap_local_param.l2cap_slots[i]->id); + (tBTA_JV_RFCOMM_CBACK *)btc_l2cap_inter_cb, (void *)user_data); } } BTA_JvDisable((tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb); @@ -553,7 +572,8 @@ static void btc_l2cap_stop_srv(btc_l2cap_args_t *arg) esp_bt_l2cap_status_t ret = ESP_BT_L2CAP_SUCCESS; bool is_remove_all = false; uint8_t i, j, srv_cnt = 0; - uint8_t *srv_psm_arr = osi_malloc(BTA_JV_MAX_L2C_CONN); + uint16_t *srv_psm_arr = osi_malloc(BTA_JV_MAX_L2C_CONN); + tBTA_JV_SERVER_STATUS server_status = BTA_JV_SERVER_RUNNING; if (arg->stop_srv.psm == BTC_L2CAP_INVALID_PSM) { is_remove_all = true; @@ -600,6 +620,7 @@ static void btc_l2cap_stop_srv(btc_l2cap_args_t *arg) if (l2cap_local_param.l2cap_slots[i] != NULL && l2cap_local_param.l2cap_slots[i]->connected && l2cap_local_param.l2cap_slots[i]->handle != 0xffff && l2cap_local_param.l2cap_slots[i]->psm == srv_psm_arr[j]) { + server_status = BTA_JV_SERVER_CONNECTED; BTA_JvL2capClose(l2cap_local_param.l2cap_slots[i]->handle, (tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb, (void *)l2cap_local_param.l2cap_slots[i]->id); } @@ -612,14 +633,19 @@ static void btc_l2cap_stop_srv(btc_l2cap_args_t *arg) if (l2cap_local_param.l2cap_slots[i] != NULL && l2cap_local_param.l2cap_slots[i]->is_server && l2cap_local_param.l2cap_slots[i]->handle != 0xffff && l2cap_local_param.l2cap_slots[i]->psm == srv_psm_arr[j]) { + BTA_JvL2capStopServer(l2cap_local_param.l2cap_slots[i]->psm, + (void *)l2cap_local_param.l2cap_slots[i]->id); - if (l2cap_local_param.l2cap_slots[i]->handle > 0) { - BTA_JvL2capStopServer(l2cap_local_param.l2cap_slots[i]->psm, - (void *)l2cap_local_param.l2cap_slots[i]->id); + tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA)); + if (user_data) { + user_data->server_status = server_status; + user_data->slot_id = l2cap_local_param.l2cap_slots[i]->id; + } else { + BTC_TRACE_ERROR("%s unable to malloc user data!", __func__); + assert(0); } - BTA_JvFreeChannel(l2cap_local_param.l2cap_slots[i]->psm, BTA_JV_CONN_TYPE_L2CAP, - (tBTA_JV_RFCOMM_CBACK *)btc_l2cap_inter_cb, (void *)l2cap_local_param.l2cap_slots[i]->id); + (tBTA_JV_RFCOMM_CBACK *)btc_l2cap_inter_cb, (void *)user_data); } } }