Merge branch 'component_bt/optimize_spp_stop_server' into 'master'

component_bt/Optimize SPP Stop Server API

Closes BT-960

See merge request espressif/esp-idf!11124
This commit is contained in:
Jiang Jiang Jian 2021-03-04 03:34:44 +00:00
commit 6677cd5498
6 changed files with 167 additions and 42 deletions

View File

@ -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, NULL, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
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);
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);
}

View File

@ -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
@ -101,9 +102,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 */
/**
@ -143,6 +145,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 */
@ -151,6 +154,7 @@ typedef union {
*/
struct spp_srv_stop_evt_param {
esp_spp_status_t status; /*!< status */
uint8_t scn; /*!< Server channel number */
} srv_stop; /*!< SPP callback param of ESP_SPP_SRV_STOP_EVT */
/**
@ -304,7 +308,7 @@ esp_err_t esp_spp_disconnect(uint32_t handle);
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.
* @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.
@ -314,8 +318,24 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask, esp_spp_role_t role, uint8_t
* - 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.
* When this function need to be called repeatedly, it is strongly recommended to call this function again after

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;