Sfoglia il codice sorgente

Merge branch 'component_bt/optimize_spp_stop_server_v4.2' into 'release/v4.2'

component_bt/Optimize SPP Stop Server API[backport v4.2]

See merge request espressif/esp-idf!12620
Jiang Jiang Jian 4 anni fa
parent
commit
0d5286471a

+ 24 - 2
components/bt/host/bluedroid/api/esp_spp_api.c

@@ -133,7 +133,8 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask,
     btc_spp_args_t arg;
     ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
 
-    if (strlen(name) > ESP_SPP_SERVER_NAME_MAX) {
+    if (name == NULL || strlen(name) > ESP_SPP_SERVER_NAME_MAX) {
+        LOG_ERROR("Invalid server name!\n");
         return ESP_ERR_INVALID_ARG;
     }
 
@@ -157,13 +158,34 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask,
 esp_err_t esp_spp_stop_srv(void)
 {
     btc_msg_t msg;
+    btc_spp_args_t arg;
     ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
 
     msg.sig = BTC_SIG_API_CALL;
     msg.pid = BTC_PID_SPP;
     msg.act = BTC_SPP_ACT_STOP_SRV;
+    arg.stop_srv.scn = BTC_SPP_INVALID_SCN;
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_spp_stop_srv_scn(uint8_t scn)
+{
+    btc_msg_t msg;
+    btc_spp_args_t arg;
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
 
-    return (btc_transfer_context(&msg, NULL, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+    if ((scn == 0) || (scn >= PORT_MAX_RFC_PORTS)) {
+        LOG_ERROR("Invalid SCN!\n");
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_SPP;
+    msg.act = BTC_SPP_ACT_STOP_SRV;
+    arg.stop_srv.scn = scn;
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
 }
 
 

+ 31 - 9
components/bt/host/bluedroid/api/include/api/esp_spp_api.h

@@ -26,11 +26,12 @@ typedef enum {
     ESP_SPP_SUCCESS   = 0,          /*!< Successful operation. */
     ESP_SPP_FAILURE,                /*!< Generic failure. */
     ESP_SPP_BUSY,                   /*!< Temporarily can not handle this request. */
-    ESP_SPP_NO_DATA,                /*!< no data. */
+    ESP_SPP_NO_DATA,                /*!< No data */
     ESP_SPP_NO_RESOURCE,            /*!< No more resource */
     ESP_SPP_NEED_INIT,              /*!< SPP module shall init first */
     ESP_SPP_NEED_DEINIT,            /*!< SPP module shall deinit first */
-    ESP_SPP_NO_CONNECTION,          /*!< connection may have been closed */
+    ESP_SPP_NO_CONNECTION,          /*!< Connection may have been closed */
+    ESP_SPP_NO_SERVER,              /*!< No SPP server */
 } esp_spp_status_t;
 
 /* Security Setting Mask, Suggest to use ESP_SPP_SEC_NONE, ESP_SPP_SEC_AUTHORIZE or ESP_SPP_SEC_AUTHENTICATE only.*/
@@ -96,9 +97,10 @@ typedef union {
      * @brief SPP_DISCOVERY_COMP_EVT
      */
     struct spp_discovery_comp_evt_param {
-        esp_spp_status_t    status;         /*!< status */
-        uint8_t             scn_num;        /*!< The num of scn_num */
-        uint8_t             scn[ESP_SPP_MAX_SCN];    /*!< channel # */
+        esp_spp_status_t status;                   /*!< status */
+        uint8_t scn_num;                           /*!< The num of scn_num */
+        uint8_t scn[ESP_SPP_MAX_SCN];              /*!< channel # */
+        const char *service_name[ESP_SPP_MAX_SCN]; /*!< service_name */
     } disc_comp;                            /*!< SPP callback param of SPP_DISCOVERY_COMP_EVT */
 
     /**
@@ -138,6 +140,7 @@ typedef union {
         esp_spp_status_t    status;         /*!< status */
         uint32_t            handle;         /*!< The connection handle */
         uint8_t             sec_id;         /*!< security ID used by this server */
+        uint8_t             scn;            /*!< Server channel number */
         bool                use_co;         /*!< TRUE to use co_rfc_data */
     } start;                                /*!< SPP callback param of ESP_SPP_START_EVT */
 
@@ -146,7 +149,8 @@ typedef union {
      */
     struct spp_srv_stop_evt_param {
         esp_spp_status_t    status;         /*!< status */
-    } srv_stop;                                 /*!< SPP callback param of ESP_SPP_SRV_STOP_EVT */
+        uint8_t             scn;            /*!< Server channel number */
+    } srv_stop;                             /*!< SPP callback param of ESP_SPP_SRV_STOP_EVT */
 
     /**
      * @brief ESP_SPP_CL_INIT_EVT
@@ -294,16 +298,34 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask,
                             esp_spp_role_t role, uint8_t local_scn, const char *name);
 
 /**
- * @brief       This function stops a SPP server
- *              When the server is stopped successfully, the callback is called
- *              with ESP_SPP_SRV_STOP_EVT.
+ * @brief       This function stops all SPP servers.
+ *              The operation will close all active SPP connection first, then the callback function will be called
+ *              with ESP_SPP_CLOSE_EVT, and the number of ESP_SPP_CLOSE_EVT is equal to the number of connection.
+ *              When the operation is completed, the callback is called with ESP_SPP_SRV_STOP_EVT.
+ *              This funciton must be called after esp_spp_init() successful and before esp_spp_deinit().
  *
  * @return
  *              - ESP_OK: success
  *              - other: failed
  */
+
 esp_err_t esp_spp_stop_srv(void);
 
+/**
+ * @brief       This function stops a specific SPP server.
+ *              The operation will close all active SPP connection first on the specific SPP server, then the callback function will be called
+ *              with ESP_SPP_CLOSE_EVT, and the number of ESP_SPP_CLOSE_EVT is equal to the number of connection.
+ *              When the operation is completed, the callback is called with ESP_SPP_SRV_STOP_EVT.
+ *              This funciton must be called after esp_spp_init() successful and before esp_spp_deinit().
+ *
+ * @param[in]   scn:         Server channel number.
+ *
+ * @return
+ *              - ESP_OK: success
+ *              - other: failed
+ */
+esp_err_t esp_spp_stop_srv_scn(uint8_t scn);
+
 /**
  * @brief       This function is used to write data, only for ESP_SPP_MODE_CB.
  *

+ 8 - 5
components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h

@@ -172,9 +172,10 @@ typedef struct {
 
 /* data associated with BTA_JV_DISCOVERY_COMP_EVT_ */
 typedef struct {
-    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
-    UINT8 scn_num;              /* num of channel */
-    UINT8 scn[BTA_JV_MAX_SCN];  /* channel # */
+    tBTA_JV_STATUS status;                    /* Whether the operation succeeded or failed. */
+    UINT8 scn_num;                            /* num of channel */
+    UINT8 scn[BTA_JV_MAX_SCN];                /* channel # */
+    const char *service_name[BTA_JV_MAX_SCN]; /* service_name */
 } tBTA_JV_DISCOVERY_COMP;
 
 /* data associated with BTA_JV_CREATE_RECORD_EVT */
@@ -305,6 +306,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 */
     BOOLEAN         use_co;     /* TRUE to use co_rfc_data */
 } tBTA_JV_RFCOMM_START;
 
@@ -376,8 +378,9 @@ typedef struct {
 
 /* data associated with BTA_JV_FREE_SCN_EVT  */
 typedef struct {
-    tBTA_JV_STATUS          status; /* Status of the operation */
-    tBTA_JV_SERVER_STATUS   server_status;
+    tBTA_JV_STATUS          status;         /* Status of the operation */
+    tBTA_JV_SERVER_STATUS   server_status;  /* Server status */
+    UINT8                   scn;            /* Server channe number */
 } tBTA_JV_FREE_SCN;
 
 

+ 10 - 1
components/bt/host/bluedroid/bta/jv/bta_jv_act.c

@@ -856,6 +856,7 @@ void bta_jv_free_scn(tBTA_JV_MSG *p_data)
     tBTA_JV_FREE_SCN evt_data = {
         .status = BTA_JV_SUCCESS,
         .server_status = BTA_JV_SERVER_STATUS_MAX,
+        .scn = scn
     };
 
     tBTA_JV_FREE_SCN_USER_DATA *user_data = NULL;
@@ -949,6 +950,7 @@ static void bta_jv_start_discovery_cback(UINT16 result, void *user_data)
         status = BTA_JV_FAILURE;
         if (result == SDP_SUCCESS || result == SDP_DB_FULL) {
             tSDP_DISC_REC       *p_sdp_rec = NULL;
+            tSDP_DISC_ATTR *p_attr = NULL;
             tSDP_PROTOCOL_ELEM  pe;
             logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128);
             tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid);
@@ -957,7 +959,13 @@ static void bta_jv_start_discovery_cback(UINT16 result, void *user_data)
                 p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec);
                 APPL_TRACE_DEBUG("p_sdp_rec:%p", p_sdp_rec);
                 if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)){
-                    dcomp.scn[dcomp.scn_num++] = (UINT8) pe.params[0];
+                    dcomp.scn[dcomp.scn_num] = (UINT8) pe.params[0];
+                    if ((p_attr = SDP_FindAttributeInRec(p_sdp_rec, ATTR_ID_SERVICE_NAME)) != NULL) {
+                        dcomp.service_name[dcomp.scn_num] = (char *)p_attr->attr_value.v.array;
+                    } else {
+                        dcomp.service_name[dcomp.scn_num] = NULL;
+                    }
+                    dcomp.scn_num++;
                     status = BTA_JV_SUCCESS;
                 }
             } while (p_sdp_rec);
@@ -2154,6 +2162,7 @@ void bta_jv_rfcomm_start_server(tBTA_JV_MSG *p_data)
         evt_data.status = BTA_JV_SUCCESS;
         evt_data.handle = p_pcb->handle;
         evt_data.sec_id = sec_id;
+        evt_data.scn = rs->local_scn;
         evt_data.use_co = TRUE;
 
         PORT_ClearKeepHandleFlag(handle);

+ 6 - 0
components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h

@@ -28,6 +28,8 @@
 
 #define ESP_SPP_RINGBUF_SIZE 1000
 
+#define BTC_SPP_INVALID_SCN 0x00
+
 typedef enum {
     BTC_SPP_ACT_INIT = 0,
     BTC_SPP_ACT_UNINIT,
@@ -74,6 +76,10 @@ typedef union {
         UINT8 max_session;
         char name[ESP_SPP_SERVER_NAME_MAX + 1];
     } start_srv;
+    //BTC_SPP_ACT_STOP_SRV
+    struct stop_srv_arg {
+        UINT8 scn;
+    } stop_srv;
     //BTC_SPP_ACT_WRITE
     struct write_arg {
         UINT32 handle;

+ 93 - 28
components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c

@@ -265,6 +265,10 @@ static void btc_create_server_fail_cb(void)
 {
     esp_spp_cb_param_t param;
     param.start.status = ESP_SPP_FAILURE;
+    param.start.handle = 0;
+    param.start.sec_id = 0;
+    param.start.scn = BTC_SPP_INVALID_SCN;
+    param.start.use_co = FALSE;
     btc_spp_cb_to_app(ESP_SPP_START_EVT, &param);
 }
 
@@ -531,6 +535,7 @@ static void btc_spp_uninit(void)
                     esp_spp_cb_param_t param;
                     BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
                     param.srv_stop.status = ESP_SPP_NO_RESOURCE;
+                    param.srv_stop.scn = spp_local_param.spp_slots[i]->scn;
                     btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
                 }
                 BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
@@ -672,61 +677,117 @@ static void btc_spp_start_srv(btc_spp_args_t *arg)
     if (ret != ESP_SPP_SUCCESS) {
         esp_spp_cb_param_t param;
         param.start.status = ret;
+        param.start.handle = 0;
+        param.start.sec_id = 0;
+        param.start.scn = BTC_SPP_INVALID_SCN;
+        param.start.use_co = FALSE;
         btc_spp_cb_to_app(ESP_SPP_START_EVT, &param);
     }
 }
 
-static void btc_spp_stop_srv(void) 
+static void btc_spp_stop_srv(btc_spp_args_t *arg)
 {
     esp_spp_status_t ret = ESP_SPP_SUCCESS;
+    bool is_remove_all = false;
+    uint8_t i, j, srv_cnt = 0;
+    uint8_t *srv_scn_arr = osi_malloc(MAX_RFC_PORTS);
+    if (arg->stop_srv.scn == BTC_SPP_INVALID_SCN) {
+        is_remove_all = true;
+    }
+
     do {
         if (!is_spp_init()) {
             BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
             ret = ESP_SPP_NEED_INIT;
             break;
         }
+        if (srv_scn_arr == NULL) {
+            BTC_TRACE_ERROR("%s malloc srv_scn_arr failed\n", __func__);
+            ret = ESP_SPP_NO_RESOURCE;
+            break;
+        }
+
         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) {
-                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);
+        // [1] find all server
+        for (i = 1; i <= MAX_RFC_PORTS; i++) {
+            if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected &&
+                spp_local_param.spp_slots[i]->sdp_handle > 0) {
+                if (is_remove_all) {
+                    srv_scn_arr[srv_cnt++] = spp_local_param.spp_slots[i]->scn;
+                } else if (spp_local_param.spp_slots[i]->scn == arg->stop_srv.scn) {
+                    srv_scn_arr[srv_cnt++] = spp_local_param.spp_slots[i]->scn;
+                    break;
+                }
             }
         }
-        // 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]->sdp_handle > 0) {
-                    BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
-                }
+        if (srv_cnt == 0) {
+            if (is_remove_all) {
+                BTC_TRACE_ERROR("%s can not find any server!\n", __func__);
+            } else {
+                BTC_TRACE_ERROR("%s can not find server:%d!\n", __func__, arg->stop_srv.scn);
+            }
+            ret = ESP_SPP_NO_SERVER;
+            break;
+        }
 
-                if (spp_local_param.spp_slots[i]->rfc_handle > 0) {
-                    BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->rfc_handle,
-                                           (void *)spp_local_param.spp_slots[i]->id);
+        // [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 &&
+                    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);
                 }
+            }
+        }
 
-                tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA));
-                if (user_data) {
-                    user_data->server_status = BTA_JV_SERVER_RUNNING;
-                    user_data->slot_id = spp_local_param.spp_slots[i]->id;
-                } else {
-                    esp_spp_cb_param_t param;
-                    BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
-                    param.srv_stop.status = ESP_SPP_NO_RESOURCE;
-                    btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
+        // [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 &&
+                    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) {
+                        BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
+                    }
+
+                    if (spp_local_param.spp_slots[i]->rfc_handle > 0) {
+                        BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->rfc_handle,
+                                               (void *)spp_local_param.spp_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 = BTA_JV_SERVER_RUNNING;
+                        user_data->slot_id = spp_local_param.spp_slots[i]->id;
+                    } else {
+                        esp_spp_cb_param_t param;
+                        BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
+                        param.srv_stop.status = ESP_SPP_NO_RESOURCE;
+                        param.srv_stop.scn = spp_local_param.spp_slots[i]->scn;
+                        btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
+                    }
+                    BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
+                                      (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)user_data);
                 }
-                BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
-                                  (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)user_data);
             }
         }
         osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
-    } while(0);
+    } while (0);
 
     if (ret != ESP_SPP_SUCCESS) {
         esp_spp_cb_param_t param;
         param.srv_stop.status = ret;
+        param.srv_stop.scn = BTC_SPP_INVALID_SCN;
         btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
     }
+
+    if (srv_scn_arr) {
+        osi_free(srv_scn_arr);
+        srv_scn_arr = NULL;
+    }
 }
 
 static void btc_spp_write(btc_spp_args_t *arg)
@@ -849,7 +910,7 @@ void btc_spp_call_handler(btc_msg_t *msg)
         btc_spp_start_srv(arg);
         break;
     case BTC_SPP_ACT_STOP_SRV:
-        btc_spp_stop_srv();
+        btc_spp_stop_srv(arg);
         break;
     case BTC_SPP_ACT_WRITE:
         btc_spp_write(arg);
@@ -876,6 +937,8 @@ void btc_spp_cb_handler(btc_msg_t *msg)
         param.disc_comp.status = p_data->disc_comp.status;
         param.disc_comp.scn_num = p_data->disc_comp.scn_num;
         memcpy(param.disc_comp.scn, p_data->disc_comp.scn, p_data->disc_comp.scn_num);
+        memcpy(param.disc_comp.service_name, p_data->disc_comp.service_name,
+               p_data->disc_comp.scn_num * sizeof(const char *));
         btc_spp_cb_to_app(ESP_SPP_DISCOVERY_COMP_EVT, &param);
         break;
     case BTA_JV_RFCOMM_CL_INIT_EVT:
@@ -909,6 +972,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
         param.start.status = p_data->rfc_start.status;
         param.start.handle = p_data->rfc_start.handle;
         param.start.sec_id = p_data->rfc_start.sec_id;
+        param.start.scn = p_data->rfc_start.scn;
         param.start.use_co = p_data->rfc_start.use_co;
         btc_spp_cb_to_app(ESP_SPP_START_EVT, &param);
         break;
@@ -1130,6 +1194,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
     case BTA_JV_FREE_SCN_EVT:
         if (p_data->free_scn.server_status == BTA_JV_SERVER_RUNNING) {
             param.srv_stop.status = p_data->free_scn.status;
+            param.srv_stop.scn = p_data->free_scn.scn;
             btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
         }
         break;