Explorar el Código

fix SPP server bugs when the BTC layer can not allocate a slot for the listen port

liqigan hace 4 años
padre
commit
6c2d8ea653

+ 8 - 7
components/bt/host/bluedroid/bta/hf_ag/bta_ag_rfc.c

@@ -47,9 +47,9 @@ void bta_ag_port_cback_1(UINT32 code, UINT16 port_handle);
 void bta_ag_port_cback_2(UINT32 code, UINT16 port_handle);
 void bta_ag_port_cback_3(UINT32 code, UINT16 port_handle);
 
-void bta_ag_mgmt_cback_1(UINT32 code, UINT16 port_handle);
-void bta_ag_mgmt_cback_2(UINT32 code, UINT16 port_handle);
-void bta_ag_mgmt_cback_3(UINT32 code, UINT16 port_handle);
+void bta_ag_mgmt_cback_1(UINT32 code, UINT16 port_handle, void* data);
+void bta_ag_mgmt_cback_2(UINT32 code, UINT16 port_handle, void* data);
+void bta_ag_mgmt_cback_3(UINT32 code, UINT16 port_handle, void* data);
 
 int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len);
 int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len);
@@ -64,7 +64,8 @@ const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] =
     bta_ag_port_cback_3
 };
 
-const tBTA_AG_PORT_CBACK bta_ag_mgmt_cback_tbl[] =
+typedef tPORT_MGMT_CALLBACK *tBTA_AG_MGMT_CBACK;
+const tBTA_AG_MGMT_CBACK bta_ag_mgmt_cback_tbl[] =
 {
     bta_ag_mgmt_cback_1,
     bta_ag_mgmt_cback_2,
@@ -206,9 +207,9 @@ static int bta_ag_data_cback(UINT16 port_handle, void *p_data, UINT16 len, UINT1
 ** Returns          void
 **
 *******************************************************************************/
-void bta_ag_mgmt_cback_1(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 1);}
-void bta_ag_mgmt_cback_2(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 2);}
-void bta_ag_mgmt_cback_3(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 3);}
+void bta_ag_mgmt_cback_1(UINT32 code, UINT16 handle, void* data) {bta_ag_mgmt_cback(code, handle, 1);}
+void bta_ag_mgmt_cback_2(UINT32 code, UINT16 handle, void* data) {bta_ag_mgmt_cback(code, handle, 2);}
+void bta_ag_mgmt_cback_3(UINT32 code, UINT16 handle, void* data) {bta_ag_mgmt_cback(code, handle, 3);}
 void bta_ag_port_cback_1(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 1);}
 void bta_ag_port_cback_2(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 2);}
 void bta_ag_port_cback_3(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 3);}

+ 1 - 1
components/bt/host/bluedroid/bta/hf_client/bta_hf_client_rfc.c

@@ -70,7 +70,7 @@ static void bta_hf_client_port_cback(UINT32 code, UINT16 port_handle)
 ** Returns          void
 **
 *******************************************************************************/
-static void bta_hf_client_mgmt_cback(UINT32 code, UINT16 port_handle)
+static void bta_hf_client_mgmt_cback(UINT32 code, UINT16 port_handle, void* data)
 {
     tBTA_HF_CLIENT_RFC     *p_buf;
     UINT16                  event;

+ 1 - 0
components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h

@@ -299,6 +299,7 @@ typedef struct {
     UINT32          port_status; /* PORT status */
     UINT32          handle;      /* The connection handle */
     BOOLEAN         async;       /* FALSE, if local initiates disconnect */
+    void *          user_data;   /* piggyback caller's private data */
 } tBTA_JV_RFCOMM_CLOSE;
 
 /* data associated with BTA_JV_RFCOMM_START_EVT */

+ 66 - 30
components/bt/host/bluedroid/bta/jv/bta_jv_act.c

@@ -115,7 +115,7 @@ static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE
 tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE new_st);
 
 static int find_rfc_pcb(void *user_data, tBTA_JV_RFC_CB **cb, tBTA_JV_PCB **pcb);
-static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle);
+static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle, void* data);
 static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle);
 static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len, int type);
 /*******************************************************************************
@@ -285,7 +285,7 @@ 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)
+static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb, BOOLEAN close_server)
 {
     tBTA_JV_STATUS status = BTA_JV_SUCCESS;
     BOOLEAN remove_server = FALSE;
@@ -295,7 +295,7 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pc
     tPORT_STATE port_state;
     UINT32 event_mask = BTA_JV_RFC_EV_MASK;
     UINT32 scn_num = (UINT32)p_cb->scn;
-    tBTA_JV evt_data;
+    tBTA_JV evt_data = {0};
 
     if (!p_cb || !p_pcb) {
         APPL_TRACE_ERROR("bta_jv_free_sr_rfc_cb, p_cb or p_pcb cannot be null");
@@ -373,10 +373,8 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pc
         p_pcb->handle = 0;
         p_cb->curr_sess--;
 
-        if ((p_cb->max_sess > 1) &&
-            (p_cb->scn != 0) &&
-            (p_cb->curr_sess == p_cb->max_sess - 1)) {
-
+        /* only needs a listening port when has a server */
+        if (!close_server && (p_cb->max_sess > 1) && (p_cb->scn != 0)) {
             for (i = 0; i < p_cb->max_sess; i++) {
                 if (p_cb->rfc_hdl[i] != 0) {
                     p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
@@ -386,8 +384,8 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pc
                     used++;
                 }
             }
-            APPL_TRACE_DEBUG("%s max_sess=%d used:%d curr_sess:%d, listen:%d si:%d",
-                             __func__, p_cb->max_sess, used, p_cb->curr_sess, listen, si);
+            APPL_TRACE_DEBUG("%s max_sess=%d used:%d curr_sess:%d, listen:%d si:%d", __func__, p_cb->max_sess, used,
+                             p_cb->curr_sess, listen, si);
             if (used < p_cb->max_sess &&
                 listen == 0 &&
                 0 <= si &&
@@ -430,9 +428,6 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pc
             p_cb->handle = 0;
             p_cb->curr_sess = -1;
         }
-        if (remove_server) {
-            bta_jv_free_sec_id(&p_cb->sec_id);
-        }
     }
     return status;
 }
@@ -1205,7 +1200,7 @@ void bta_jv_delete_record(tBTA_JV_MSG *p_data)
 static void bta_jv_l2cap_client_cback(UINT16 gap_handle, UINT16 event)
 {
     tBTA_JV_L2C_CB  *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
-    tBTA_JV     evt_data;
+    tBTA_JV evt_data = {0};
 
     if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) {
         return;
@@ -1360,7 +1355,7 @@ void bta_jv_l2cap_close(tBTA_JV_MSG *p_data)
 static void bta_jv_l2cap_server_cback(UINT16 gap_handle, UINT16 event)
 {
     tBTA_JV_L2C_CB  *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
-    tBTA_JV evt_data;
+    tBTA_JV evt_data = {0};
     tBTA_JV_L2CAP_CBACK *p_cback;
     void *user_data;
 
@@ -1666,11 +1661,11 @@ static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len,
 ** Returns      void
 **
 *******************************************************************************/
-static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle)
+static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle, void* data)
 {
     tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
     tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
-    tBTA_JV evt_data;
+    tBTA_JV evt_data = {0};
     BD_ADDR rem_bda;
     UINT16 lcid;
     tBTA_JV_RFCOMM_CBACK *p_cback;  /* the callback function */
@@ -1722,7 +1717,7 @@ static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle)
 {
     tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
     tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
-    tBTA_JV evt_data;
+    tBTA_JV evt_data = {0};
 
     APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback:%d", port_handle);
     if (NULL == p_cb || NULL == p_cb->p_cback) {
@@ -1863,7 +1858,7 @@ 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;
+    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__);
@@ -1887,8 +1882,8 @@ void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data)
         }
         cc->p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
     }
-    bta_jv_free_rfc_cb(p_cb, p_pcb);
-    APPL_TRACE_DEBUG("%s: sec id in use:%d, rfc_cb in use:%d",__func__, 
+    bta_jv_free_rfc_cb(p_cb, p_pcb, FALSE);
+    APPL_TRACE_DEBUG("%s: sec id in use:%d, rfc_cb in use:%d",__func__,
                      get_sec_id_used(), get_rfc_cb_used());
 }
 
@@ -1930,39 +1925,80 @@ static UINT8 __attribute__((unused)) bta_jv_get_num_rfc_listen(tBTA_JV_RFC_CB *p
 ** Returns      void
 **
 *******************************************************************************/
-static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle)
+static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle, void *data)
 {
     tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
     tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
-    tBTA_JV evt_data;
+    tBTA_JV evt_data = {0};
     BD_ADDR rem_bda;
     UINT16 lcid;
+    BOOLEAN *accept = (BOOLEAN *)data;
+    void *user_data = NULL;
+    void *new_user_data = NULL;
+
     // APPL_TRACE_DEBUG("bta_jv_port_mgmt_sr_cback, code:0x%x, port_handle:%d", code, (uint16_t)port_handle);
     if (NULL == p_cb || NULL == p_cb->p_cback) {
         // APPL_TRACE_ERROR("bta_jv_port_mgmt_sr_cback, p_cb:%p, p_cb->p_cback%p",
         // p_cb, p_cb ? p_cb->p_cback : NULL);
         return;
     }
-    void *user_data = p_pcb->user_data;
+    user_data = p_pcb->user_data;
     // APPL_TRACE_DEBUG( "bta_jv_port_mgmt_sr_cback code=%p port_handle:0x%x handle:0x%x, p_pcb:%p, user:%p",
     // code, port_handle, p_cb->handle, p_pcb, p_pcb->user_data);
 
     PORT_CheckConnection(port_handle, rem_bda, &lcid);
     int failed = TRUE;
     if (code == PORT_SUCCESS) {
+        failed = FALSE;
+        /* accept the connection defaulted */
+        if (accept) {
+            *accept = TRUE;
+        }
         evt_data.rfc_srv_open.handle = p_pcb->handle;
         evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
         bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda);
         tBTA_JV_PCB *p_pcb_new_listen  = bta_jv_add_rfc_port(p_cb, p_pcb);
         if (p_pcb_new_listen) {
             evt_data.rfc_srv_open.new_listen_handle = p_pcb_new_listen->handle;
-            p_pcb_new_listen->user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data);
-            APPL_TRACE_DEBUG("PORT_SUCCESS: curr_sess:%d, max_sess:%d", p_cb->curr_sess, p_cb->max_sess);
-            failed = FALSE;
+            new_user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data);
+            if (new_user_data) {
+                p_pcb_new_listen->user_data = new_user_data;
+                APPL_TRACE_DEBUG("PORT_SUCCESS: curr_sess:%d, max_sess:%d", p_cb->curr_sess,
+                                 p_cb->max_sess);
+            } else {
+                /**
+                 * new_user_data is NULL, which means the upper layer runs out of slot source.
+                 * Tells the caller to reject this connection.
+                 */
+                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);
+                if (accept) {
+                    *accept = FALSE;
+                }
+            }
         } else {
+            evt_data.rfc_srv_open.new_listen_handle = 0;
+            new_user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data);
+            if (new_user_data) {
+                APPL_TRACE_DEBUG("PORT_SUCCESS: curr_sess:%d, max_sess:%d", p_cb->curr_sess,
+                                 p_cb->max_sess);
+            } else {
+                /**
+                 * new_user_data is NULL, which means the upper layer runs out of slot source.
+                 * Tells the caller to reject this connection.
+                 */
+                APPL_TRACE_ERROR("no listen port, and upper layer reject connection");
+                p_pcb->state = BTA_JV_ST_SR_LISTEN;
+                if (accept) {
+                    *accept = FALSE;
+                }
+            }
             APPL_TRACE_ERROR("bta_jv_add_rfc_port failed to create new listen port");
         }
     }
+
     if (failed) {
         evt_data.rfc_close.handle = p_pcb->handle;
         evt_data.rfc_close.status = BTA_JV_FAILURE;
@@ -1999,7 +2035,7 @@ static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle)
 {
     tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
     tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
-    tBTA_JV evt_data;
+    tBTA_JV evt_data = {0};
 
     if (NULL == p_cb || NULL == p_cb->p_cback) {
         return;
@@ -2067,6 +2103,7 @@ static tBTA_JV_PCB *bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb
             }
         }
 
+        p_pcb = NULL;
         APPL_TRACE_DEBUG("bta_jv_add_rfc_port max_sess=%d used:%d curr_sess:%d, listen:%d si:%d",
                          p_cb->max_sess, used, p_cb->curr_sess, listen, si);
         if (used < p_cb->max_sess && listen == 1 && si) {
@@ -2094,7 +2131,6 @@ static tBTA_JV_PCB *bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb
             }
         } else {
             /* avoid p_pcb always points to the last element of rfc_hdl */
-            p_pcb = p_pcb_open;
             APPL_TRACE_ERROR("bta_jv_add_rfc_port, cannot create new rfc listen port");
         }
     }
@@ -2214,7 +2250,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);
+    bta_jv_free_rfc_cb(p_cb, p_pcb, TRUE);
     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());
 }
@@ -2750,7 +2786,7 @@ static void fcchan_conn_chng_cbk(UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected
 
 static void fcchan_data_cbk(UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
 {
-    tBTA_JV evt_data;
+    tBTA_JV evt_data = {0};
     // tBTA_JV evt_open;
     struct fc_channel *tc;
     struct fc_client *t = NULL;

+ 106 - 64
components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c

@@ -1,16 +1,8 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #include <string.h>
 
@@ -55,8 +47,9 @@ typedef struct {
 } slot_data_t;
 
 typedef struct {
-    uint8_t serial;
     bool connected;
+    bool is_server;
+    uint8_t serial;
     uint8_t scn;
     uint8_t max_session;
     uint32_t id;
@@ -137,29 +130,39 @@ static spp_slot_t *spp_malloc_slot(void)
             (*slot)->sdp_handle = 0;
             (*slot)->rfc_handle = 0;
             (*slot)->rfc_port_handle = 0;
-            (*slot)->connected = FALSE;
+            (*slot)->fd = -1;
+            (*slot)->connected = false;
+            (*slot)->is_server = false;
             (*slot)->write_data = NULL;
             (*slot)->close_alarm = NULL;
+            /* clear the old event bits */
+            if (spp_local_param.tx_event_group) {
+                xEventGroupClearBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(i) | SLOT_CLOSE_BIT(i));
+            }
+
             if (init_slot_data(&(*slot)->rx, QUEUE_SIZE_MAX)) {
                 BTC_TRACE_ERROR("%s unable to malloc rx queue!", __func__);
                 err_no = 1;
-                break;
+                goto err;
             }
             if (init_slot_data(&(*slot)->tx, SLOT_TX_QUEUE_SIZE)) {
                 BTC_TRACE_ERROR("%s unable to malloc tx queue!", __func__);
                 err_no = 2;
-                break;
+                goto err;
             }
             if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
                 if (esp_vfs_register_fd(spp_local_param.spp_vfs_id, &(*slot)->fd) != ESP_OK) {
                     BTC_TRACE_ERROR("%s unable to register fd!", __func__);
                     err_no = 3;
-                    break;
+                    goto err;
                 }
             }
             return (*slot);
         }
     }
+
+    return NULL;
+err:
     switch (err_no) {
         case 3:
             free_slot_data(&(*slot)->tx);
@@ -177,9 +180,11 @@ static spp_slot_t *spp_malloc_slot(void)
 
 static spp_slot_t *spp_find_slot_by_id(uint32_t id)
 {
+    spp_slot_t *slot = NULL;
     for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
-        if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->id == id) {
-            return spp_local_param.spp_slots[i];
+        slot = spp_local_param.spp_slots[i];
+        if (slot != NULL && slot->id == id) {
+            return slot;
         }
     }
     return NULL;
@@ -187,9 +192,11 @@ static spp_slot_t *spp_find_slot_by_id(uint32_t id)
 
 static spp_slot_t *spp_find_slot_by_handle(uint32_t handle)
 {
+    spp_slot_t *slot = NULL;
     for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
-        if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->rfc_handle == handle) {
-            return spp_local_param.spp_slots[i];
+        slot = spp_local_param.spp_slots[i];
+        if (slot != NULL && slot->rfc_handle == handle) {
+            return slot;
         }
     }
     return NULL;
@@ -197,9 +204,11 @@ static spp_slot_t *spp_find_slot_by_handle(uint32_t handle)
 
 static spp_slot_t *spp_find_slot_by_fd(int fd)
 {
+    spp_slot_t *slot = NULL;
     for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
-        if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->fd == fd) {
-            return spp_local_param.spp_slots[i];
+        slot = spp_local_param.spp_slots[i];
+        if (slot != NULL && slot->fd == fd) {
+            return slot;
         }
     }
     return NULL;
@@ -207,9 +216,11 @@ static spp_slot_t *spp_find_slot_by_fd(int fd)
 
 static spp_slot_t *spp_find_slot_by_scn(uint32_t scn)
 {
+    spp_slot_t *slot = NULL;
     for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
-        if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->scn == (uint8_t)scn) {
-            return spp_local_param.spp_slots[i];
+        slot = spp_local_param.spp_slots[i];
+        if (slot != NULL && slot->is_server && slot->scn == (uint8_t)scn) {
+            return slot;
         }
     }
     return NULL;
@@ -277,9 +288,9 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
     bt_status_t status;
     btc_msg_t msg;
     void *new_user_data = NULL;
-
-    uint32_t id = (uintptr_t)user_data;
+    uint32_t id = (uintptr_t)user_data, id_temp = 0;
     spp_slot_t *slot = NULL, *slot_new = NULL;
+
     if (!is_spp_init()) {
         BTC_TRACE_WARNING("%s SPP have been deinit, incoming events ignore!\n", __func__);
         return new_user_data;
@@ -289,7 +300,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
     case BTA_JV_RFCOMM_START_EVT:
         slot = spp_find_slot_by_id(id);
         if (!slot) {
-            BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+            BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
             p_data->rfc_start.status = ESP_SPP_NO_CONNECTION;
             break;
         }
@@ -299,42 +310,52 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
     case BTA_JV_RFCOMM_SRV_OPEN_EVT:
         slot = p_data->rfc_srv_open.handle ? spp_find_slot_by_id(id) : spp_find_slot_by_scn((uint32_t)user_data);
         if (!slot) {
-            BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+            BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
             p_data->rfc_srv_open.status = ESP_SPP_NO_CONNECTION;
             break;
         }
 
-        if (p_data->rfc_srv_open.handle) {
-            new_user_data = (void *)(uintptr_t)slot->id;
-            memcpy(slot->addr, p_data->rfc_srv_open.rem_bda, ESP_BD_ADDR_LEN);
-            slot->connected = TRUE;
-            slot->rfc_handle = p_data->rfc_srv_open.handle;
-            slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_srv_open.handle);
-            BTA_JvSetPmProfile(p_data->rfc_srv_open.handle, BTA_JV_PM_ALL, BTA_JV_CONN_OPEN);
-        }
-
-        if (p_data->rfc_srv_open.handle != p_data->rfc_srv_open.new_listen_handle) {
+        if (!p_data->rfc_srv_open.handle) {
+            /* match with the exist server solt */
+            slot->rfc_handle = p_data->rfc_srv_open.new_listen_handle;
+            slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(slot->rfc_handle);
+        } else {
             slot_new = spp_malloc_slot();
             if (!slot_new) {
                 BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__);
                 p_data->rfc_srv_open.status = ESP_SPP_NO_RESOURCE;
                 break;
             }
-            new_user_data = (void *)(uintptr_t)slot_new->id;
+            slot_new->connected = true;
             slot_new->security = slot->security;
             slot_new->role = slot->role;
             slot_new->scn = slot->scn;
             slot_new->max_session = slot->max_session;
             strcpy(slot_new->service_name, slot->service_name);
             slot_new->sdp_handle = slot->sdp_handle;
-            slot_new->rfc_handle = p_data->rfc_srv_open.new_listen_handle;
-            slot_new->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_srv_open.new_listen_handle);
+            slot_new->rfc_handle = p_data->rfc_srv_open.handle;
+            slot_new->rfc_port_handle = BTA_JvRfcommGetPortHdl(slot_new->rfc_handle);
+            BTA_JvSetPmProfile(p_data->rfc_srv_open.handle, BTA_JV_PM_ALL, BTA_JV_CONN_OPEN);
+
+            if (p_data->rfc_srv_open.new_listen_handle) {
+                slot->rfc_handle = p_data->rfc_srv_open.new_listen_handle;
+                slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(slot->rfc_handle);
+            } else {
+                /* means lower layer can alloc port */
+                slot->rfc_handle = 0;
+                slot->rfc_port_handle = 0;
+            }
+            /* swap slot id */
+            id_temp = slot->id;
+            slot->id = slot_new->id;
+            slot_new->id = id_temp;
         }
+        new_user_data = (void *)(uintptr_t)slot->id;
         break;
     case BTA_JV_RFCOMM_OPEN_EVT:
         slot = spp_find_slot_by_id(id);
         if (!slot) {
-            BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+            BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
             p_data->rfc_open.status = ESP_SPP_NO_CONNECTION;
             break;
         }
@@ -346,7 +367,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
     case BTA_JV_RFCOMM_CLOSE_EVT:
         slot = spp_find_slot_by_id(id);
         if (!slot) {
-            BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+            BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
             p_data->rfc_close.status = ESP_SPP_NO_CONNECTION;
             break;
         }
@@ -354,6 +375,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
             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;
@@ -364,7 +386,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
             if (slot) {
                 spp_free_slot(slot);
             } else {
-                BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+                BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
                 p_data->free_scn.status = ESP_SPP_NO_CONNECTION;
             }
             osi_free(user_data);
@@ -401,7 +423,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d
         slot = spp_find_slot_by_id(id);
         if (!slot) {
             osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
-            BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+            BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
             break;
         }
         if (p_data->scn == 0) {
@@ -421,7 +443,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d
         slot = spp_find_slot_by_id(id);
         if (!slot) {
             osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
-            BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+            BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
             break;
         }
         if (p_data->create_rec.status == BTA_JV_SUCCESS) {
@@ -510,14 +532,14 @@ static void btc_spp_uninit(void)
         osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
         // 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]->connected) {
+            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);
             }
         }
         // second, remove all server
         for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
-            if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected) {
+            if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->is_server) {
                 if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
                     BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
                 }
@@ -669,6 +691,10 @@ static void btc_spp_start_srv(btc_spp_args_t *arg)
             ret = ESP_SPP_NO_RESOURCE;
             break;
         }
+        /**
+         * make this slot become a listening slot
+         */
+        slot->is_server = true;
         slot->security = arg->start_srv.sec_mask;
         slot->role = arg->start_srv.role;
         slot->scn = arg->start_srv.local_scn;
@@ -738,7 +764,7 @@ static void btc_spp_stop_srv(btc_spp_args_t *arg)
         // [2] remove all local related connection
         for (j = 0; j < srv_cnt; j++) {
             for (i = 1; i <= MAX_RFC_PORTS; i++) {
-                if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->connected &&
+                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,
@@ -751,7 +777,7 @@ static void btc_spp_stop_srv(btc_spp_args_t *arg)
         // [3] remove all server
         for (j = 0; j < srv_cnt; j++) {
             for (i = 1; i <= MAX_RFC_PORTS; i++) {
-                if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected &&
+                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]) {
                     if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
@@ -933,7 +959,9 @@ void btc_spp_cb_handler(btc_msg_t *msg)
     tBTA_JV *p_data = (tBTA_JV *)msg->arg;
     spp_slot_t *slot = NULL;
     uint8_t serial = 0;
-    switch (msg->act) {
+    uint8_t event = msg->act;
+
+    switch (event) {
     case BTA_JV_ENABLE_EVT:
         param.init.status = p_data->status;
         btc_spp_cb_to_app(ESP_SPP_INIT_EVT, &param);
@@ -960,12 +988,14 @@ void btc_spp_cb_handler(btc_msg_t *msg)
                 slot = spp_find_slot_by_handle(p_data->rfc_open.handle);
                 if (!slot) {
                     osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
-                    BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+                    BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
                     param.open.status = ESP_SPP_NO_CONNECTION;
                     break;
                 }
                 param.open.fd = slot->fd;
                 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
+            } else {
+                param.open.fd = -1;
             }
             param.open.status = p_data->rfc_open.status;
         } while (0);
@@ -989,12 +1019,14 @@ void btc_spp_cb_handler(btc_msg_t *msg)
                     slot = spp_find_slot_by_handle(p_data->rfc_srv_open.handle);
                     if (!slot) {
                         osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
-                        BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+                        BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
                         param.srv_open.status = ESP_SPP_NO_CONNECTION;
                         break;
                     }
                     param.srv_open.fd = slot->fd;
                     osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
+                } else {
+                    param.srv_open.fd = -1;
                 }
                 param.srv_open.status = p_data->rfc_srv_open.status;
             } while (0);
@@ -1065,10 +1097,11 @@ void btc_spp_cb_handler(btc_msg_t *msg)
         if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) {
             btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, &param);
             osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
-            slot = spp_find_slot_by_handle(p_data->rfc_close.handle);
+            uint32_t id = (uintptr_t)p_data->rfc_close.user_data;
+            slot = spp_find_slot_by_id(id);
             if (!slot) {
                 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
-                BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+                BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
                 break;
             }
             spp_free_slot(slot);
@@ -1077,11 +1110,12 @@ void btc_spp_cb_handler(btc_msg_t *msg)
             bool need_call = true;
             do {
                 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
-                slot = spp_find_slot_by_handle(p_data->rfc_close.handle);
+                uint32_t id = (uintptr_t)p_data->rfc_close.user_data;
+                slot = spp_find_slot_by_id(id);
                 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!", __func__);
+                    BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
                     break;
                 }
                 // if rx still has data, delay free slot
@@ -1110,8 +1144,8 @@ void btc_spp_cb_handler(btc_msg_t *msg)
                         BTC_TRACE_ERROR("%s set slot close_alarm failed!", __func__);
                         break;
                     }
-                    BTC_TRACE_WARNING("%s slot rx data will be discard in %d seconds!", __func__,
-                                      VFS_CLOSE_TIMEOUT / 1000);
+                    BTC_TRACE_WARNING("%s slot rx data will be discard in %d milliseconds!",
+                                      __func__, VFS_CLOSE_TIMEOUT);
                     slot->connected = false;
                     need_call = false;
                 }
@@ -1137,7 +1171,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
             slot = spp_find_slot_by_handle(p_data->rfc_cong.handle);
             if (!slot) {
                 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
-                BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+                BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
                 break;
             }
             if (!p_data->rfc_cong.cong) {
@@ -1159,7 +1193,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
             slot = spp_find_slot_by_handle(p_data->data_ind.handle);
             if (!slot) {
                 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
-                BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
+                BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
                 break;
             }
             serial = slot->serial;
@@ -1416,7 +1450,7 @@ static ssize_t spp_vfs_read(int fd, void * dst, size_t size)
     slot = spp_find_slot_by_fd(fd);
     if (!slot) {
         osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
-        BTC_TRACE_ERROR("%s unable to find RFCOMM slot!\n", __func__);
+        BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
         errno = ENOENT;
         return -1;
     }
@@ -1441,6 +1475,14 @@ static ssize_t spp_vfs_read(int fd, void * dst, size_t size)
                     break;
                 }
             } else {
+                /**
+                 * If close_alarm is not NULL, it means that we have received the BTA_JV_RFCOMM_CLOSE_EVT.
+                 * And we can trigger close_alarm immediately.
+                 */
+                if (slot->close_alarm && osi_alarm_is_active(slot->close_alarm)) {
+                    osi_alarm_cancel(slot->close_alarm);
+                    osi_alarm_set(slot->close_alarm, 0);
+                }
                 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
                 break;
             }

+ 3 - 1
components/bt/host/bluedroid/stack/include/stack/port_api.h

@@ -105,6 +105,8 @@ typedef int  (tPORT_DATA_CO_CALLBACK) (UINT16 port_handle, UINT8 *p_buf, UINT16
 
 typedef void (tPORT_CALLBACK) (UINT32 code, UINT16 port_handle);
 
+typedef void (tPORT_MGMT_CALLBACK) (UINT32 code, UINT16 port_handle, void* data);
+
 /*
 ** Define events that registered application can receive in the callback
 */
@@ -219,7 +221,7 @@ extern "C"
 extern int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn,
                                     BOOLEAN is_server, UINT16 mtu,
                                     BD_ADDR bd_addr, UINT16 *p_handle,
-                                    tPORT_CALLBACK *p_mgmt_cb);
+                                    tPORT_MGMT_CALLBACK *p_mgmt_cb);
 
 
 /*******************************************************************************

+ 1 - 1
components/bt/host/bluedroid/stack/rfcomm/include/port_int.h

@@ -188,7 +188,7 @@ struct t_port_info {
 
     UINT32      ev_mask;                    /* Event mask for the callback */
     tPORT_CALLBACK      *p_callback;        /* Pointer to users callback function */
-    tPORT_CALLBACK      *p_mgmt_callback;   /* Callback function to receive connection up/down */
+    tPORT_MGMT_CALLBACK *p_mgmt_callback;   /* Callback function to receive connection up/down */
     tPORT_DATA_CALLBACK *p_data_callback;   /* Callback function to receive data indications */
     tPORT_DATA_CO_CALLBACK *p_data_co_callback;   /* Callback function with callouts and flowctrl */
     UINT16      credit_tx;                  /* Flow control credits for tx path */

+ 1 - 1
components/bt/host/bluedroid/stack/rfcomm/port_api.c

@@ -103,7 +103,7 @@ static const char *result_code_strings[] = {
 *******************************************************************************/
 int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, BOOLEAN is_server,
                              UINT16 mtu, BD_ADDR bd_addr, UINT16 *p_handle,
-                             tPORT_CALLBACK *p_mgmt_cb)
+                             tPORT_MGMT_CALLBACK *p_mgmt_cb)
 {
     tPORT      *p_port;
     int        i;

+ 17 - 10
components/bt/host/bluedroid/stack/rfcomm/port_rfc.c

@@ -175,7 +175,7 @@ void port_start_close (tPORT *p_port)
     if ((p_mcb == NULL) || (p_port->rfc.state == RFC_STATE_CLOSED)) {
         /* Call management callback function before calling port_release_port() to clear tPort */
         if (p_port->p_mgmt_callback) {
-            p_port->p_mgmt_callback (PORT_CLOSED, p_port->inx);
+            p_port->p_mgmt_callback (PORT_CLOSED, p_port->inx, NULL);
         }
 
         port_release_port (p_port);
@@ -230,7 +230,7 @@ void PORT_StartCnf (tRFC_MCB *p_mcb, UINT16 result)
                 }
 
                 if (p_port->p_mgmt_callback) {
-                    p_port->p_mgmt_callback (PORT_START_FAILED, p_port->inx);
+                    p_port->p_mgmt_callback (PORT_START_FAILED, p_port->inx, NULL);
                 }
 
                 port_release_port (p_port);
@@ -427,6 +427,7 @@ void PORT_ParNegCnf (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k)
 void PORT_DlcEstablishInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
 {
     tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
+    BOOLEAN accept = true;
 
     RFCOMM_TRACE_DEBUG ("PORT_DlcEstablishInd p_mcb:%p, dlci:%d mtu:%di, p_port:%p", p_mcb, dlci, mtu, p_port);
     RFCOMM_TRACE_DEBUG ("PORT_DlcEstablishInd p_mcb addr:%02x:%02x:%02x:%02x:%02x:%02x",
@@ -451,7 +452,7 @@ void PORT_DlcEstablishInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
     /* If there was an inactivity timer running for MCB stop it */
     rfc_timer_stop (p_mcb);
 
-    RFCOMM_DlcEstablishRsp (p_mcb, dlci, p_port->mtu, RFCOMM_SUCCESS);
+    // RFCOMM_DlcEstablishRsp (p_mcb, dlci, p_port->mtu, RFCOMM_SUCCESS);
 
     /* This is the server side.  If application wants to know when connection */
     /* is established, thats the place */
@@ -460,10 +461,15 @@ void PORT_DlcEstablishInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
     }
 
     if (p_port->p_mgmt_callback) {
-        p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx);
+        p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx, &accept);
     }
 
-    p_port->state = PORT_STATE_OPENED;
+    if (accept) {
+        RFCOMM_DlcEstablishRsp(p_mcb, dlci, p_port->mtu, RFCOMM_SUCCESS);
+        p_port->state = PORT_STATE_OPENED;
+    } else {
+        RFCOMM_DlcEstablishRsp(p_mcb, dlci, 0, RFCOMM_LOW_RESOURCES);
+    }
 }
 
 
@@ -506,7 +512,7 @@ void PORT_DlcEstablishCnf (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT16 resul
     }
 
     if (p_port->p_mgmt_callback) {
-        p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx);
+        p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx, NULL);
     }
 
     p_port->state = PORT_STATE_OPENED;
@@ -1063,14 +1069,15 @@ void port_rfc_closed (tPORT *p_port, UINT8 res)
         p_port->p_callback (events, p_port->inx);
     }
 
-    if (p_port->p_mgmt_callback) {
-        p_port->p_mgmt_callback (res, p_port->inx);
+    if (p_port->p_mgmt_callback && !(p_port->state == PORT_STATE_CLOSED && p_port->is_server)) {
+        p_port->p_mgmt_callback(res, p_port->inx, NULL);
     }
 
     p_port->rfc.state = RFC_STATE_CLOSED;
 
-    RFCOMM_TRACE_WARNING ("%s RFCOMM connection in state %d closed: %s (res: %d)",
-                          __func__, p_port->state, PORT_GetResultString(res), res);
+    RFCOMM_TRACE_WARNING("%s RFCOMM connection in server:%d state %d closed: %s (res: %d)",
+                         __func__, p_port->is_server, p_port->state, PORT_GetResultString(res),
+                         res);
 
     port_release_port (p_port);
 }

+ 2 - 0
components/bt/host/bluedroid/stack/rfcomm/rfc_mx_fsm.c

@@ -69,6 +69,8 @@ static void rfc_mx_conf_cnf (tRFC_MCB *p_mcb, tL2CAP_CFG_INFO *p_cfg);
 *******************************************************************************/
 void rfc_mx_sm_execute (tRFC_MCB *p_mcb, UINT16 event, void *p_data)
 {
+    RFCOMM_TRACE_DEBUG("%s st:%d, evt:%d\n", __func__, p_mcb->state, event);
+
     switch (p_mcb->state) {
     case RFC_MX_STATE_IDLE:
         rfc_mx_sm_state_idle (p_mcb, event, p_data);

+ 7 - 0
components/bt/host/bluedroid/stack/rfcomm/rfc_port_fsm.c

@@ -62,6 +62,8 @@ static void rfc_set_port_state(tPORT_STATE *port_pars, MX_FRAME *p_frame);
 *******************************************************************************/
 void rfc_port_sm_execute (tPORT *p_port, UINT16 event, void *p_data)
 {
+    RFCOMM_TRACE_DEBUG("%s st:%d, evt:%d\n", __func__, p_port->rfc.state, event);
+
     if (!p_port) {
         RFCOMM_TRACE_WARNING ("NULL port event %d", event);
         return;
@@ -296,6 +298,11 @@ void rfc_port_sm_term_wait_sec_check (tPORT *p_port, UINT16 event, void *p_data)
         if (*((UINT8 *)p_data) != RFCOMM_SUCCESS) {
             if (p_port->rfc.p_mcb) {
                 rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, TRUE);
+                if (*((UINT8 *)p_data) == RFCOMM_LOW_RESOURCES) {
+                    port_rfc_closed(p_port, PORT_NO_RESOURCES);
+                } else {
+                    port_rfc_closed(p_port, PORT_UNKNOWN_ERROR);
+                }
             }
         } else {
             rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);

+ 0 - 1
components/bt/host/bluedroid/stack/rfcomm/rfc_utils.c

@@ -201,7 +201,6 @@ void osi_free_fun(void *p){
 *******************************************************************************/
 void rfc_release_multiplexer_channel (tRFC_MCB *p_mcb)
 {
-
     rfc_timer_free (p_mcb);
 
     fixed_queue_free(p_mcb->cmd_q, osi_free_fun);

+ 0 - 1
tools/ci/check_copyright_ignore.txt

@@ -300,7 +300,6 @@ components/bt/host/bluedroid/btc/profile/std/include/dis_api.h
 components/bt/host/bluedroid/btc/profile/std/include/srvc_api.h
 components/bt/host/bluedroid/btc/profile/std/smp/esp_app_sec.c
 components/bt/host/bluedroid/btc/profile/std/smp/include/esp_sec_api.h
-components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c
 components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h
 components/bt/host/bluedroid/common/include/common/bt_common_types.h
 components/bt/host/bluedroid/common/include/common/bt_defs.h