From 35b2eeaa65b9e7029e3420e1de952a9a520fe9f9 Mon Sep 17 00:00:00 2001 From: liqigan Date: Mon, 10 Aug 2020 16:08:17 +0800 Subject: [PATCH] add API esp_spp_stop_srv(), fix the error parameter in esp-idf/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/example_spp_initiator_demo.c and fix collection of SPP Closes https://github.com/espressif/esp-idf/issues/5409 Closes https://github.com/espressif/esp-idf/pull/5408 See merge request !9114 --- components/bt/bluedroid/api/esp_spp_api.c | 11 + .../bluedroid/api/include/api/esp_spp_api.h | 27 ++ .../bt/bluedroid/bta/include/bta/bta_jv_api.h | 48 ++- components/bt/bluedroid/bta/jv/bta_jv_act.c | 119 ++++++- components/bt/bluedroid/bta/jv/bta_jv_api.c | 53 ++- .../bt/bluedroid/bta/jv/include/bta_jv_int.h | 10 + .../btc/profile/std/include/btc_spp.h | 1 + .../bluedroid/btc/profile/std/spp/btc_spp.c | 328 ++++++++++++++---- .../common/include/common/bt_target.h | 2 +- components/bt/bluedroid/stack/btm/btm_acl.c | 2 +- components/bt/bluedroid/stack/btm/btm_sec.c | 2 +- .../main/example_spp_acceptor_demo.c | 6 + .../main/example_spp_initiator_demo.c | 5 +- 13 files changed, 516 insertions(+), 98 deletions(-) diff --git a/components/bt/bluedroid/api/esp_spp_api.c b/components/bt/bluedroid/api/esp_spp_api.c index 05157ebdc..e8f7487e3 100644 --- a/components/bt/bluedroid/api/esp_spp_api.c +++ b/components/bt/bluedroid/api/esp_spp_api.c @@ -154,6 +154,17 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask, 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(void) +{ + btc_msg_t msg; + 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; + + return (btc_transfer_context(&msg, NULL, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} esp_err_t esp_spp_write(uint32_t handle, int len, uint8_t *p_data) { diff --git a/components/bt/bluedroid/api/include/api/esp_spp_api.h b/components/bt/bluedroid/api/include/api/esp_spp_api.h index 9628a1ed0..9e6576424 100644 --- a/components/bt/bluedroid/api/include/api/esp_spp_api.h +++ b/components/bt/bluedroid/api/include/api/esp_spp_api.h @@ -57,6 +57,7 @@ typedef enum { */ typedef enum { ESP_SPP_INIT_EVT = 0, /*!< When SPP is inited, the event comes */ + ESP_SPP_UNINIT_EVT = 1, /*!< When SPP is uninited, the event comes */ ESP_SPP_DISCOVERY_COMP_EVT = 8, /*!< When SDP discovery complete, the event comes */ ESP_SPP_OPEN_EVT = 26, /*!< When SPP Client connection open, the event comes */ ESP_SPP_CLOSE_EVT = 27, /*!< When SPP connection closed, the event comes */ @@ -66,6 +67,7 @@ typedef enum { ESP_SPP_CONG_EVT = 31, /*!< When SPP connection congestion status changed, the event comes, only for ESP_SPP_MODE_CB */ ESP_SPP_WRITE_EVT = 33, /*!< When SPP write operation completes, the event comes, only for ESP_SPP_MODE_CB */ ESP_SPP_SRV_OPEN_EVT = 34, /*!< When SPP Server connection open, the event comes */ + ESP_SPP_SRV_STOP_EVT = 35, /*!< When SPP server stopped, the event comes */ } esp_spp_cb_event_t; @@ -80,6 +82,13 @@ typedef union { esp_spp_status_t status; /*!< status */ } init; /*!< SPP callback param of SPP_INIT_EVT */ + /** + * @brief SPP_UNINIT_EVT + */ + struct spp_uninit_evt_param { + esp_spp_status_t status; /*!< status */ + } uninit; /*!< SPP callback param of SPP_UNINIT_EVT */ + /** * @brief SPP_DISCOVERY_COMP_EVT */ @@ -128,6 +137,14 @@ typedef union { uint8_t sec_id; /*!< security ID used by this server */ bool use_co; /*!< TRUE to use co_rfc_data */ } start; /*!< SPP callback param of ESP_SPP_START_EVT */ + + /** + * @brief ESP_SPP_SRV_STOP_EVT + */ + struct spp_srv_stop_evt_param { + esp_spp_status_t status; /*!< status */ + } srv_stop; /*!< SPP callback param of ESP_SPP_SRV_STOP_EVT */ + /** * @brief ESP_SPP_CL_INIT_EVT */ @@ -273,6 +290,16 @@ 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 + * When the server is stopped successfully, the callback is called + * with ESP_SPP_SRV_STOP_EVT. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_spp_stop_srv(void); /** * @brief This function is used to write data, only for ESP_SPP_MODE_CB. diff --git a/components/bt/bluedroid/bta/include/bta/bta_jv_api.h b/components/bt/bluedroid/bta/include/bta/bta_jv_api.h index 7cbf0405c..7bd6195c5 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_jv_api.h +++ b/components/bt/bluedroid/bta/include/bta/bta_jv_api.h @@ -129,6 +129,7 @@ typedef UINT8 tBTA_JV_CONN_STATE; /* Java I/F callback events */ /* events received by tBTA_JV_DM_CBACK */ #define BTA_JV_ENABLE_EVT 0 /* JV enabled */ +#define BTA_JV_DISABLE_EVT 1 /* JV disabled */ #define BTA_JV_GET_SCN_EVT 6 /* Reserved an SCN */ #define BTA_JV_GET_PSM_EVT 7 /* Reserved a PSM */ #define BTA_JV_DISCOVERY_COMP_EVT 8 /* SDP discovery complete */ @@ -157,7 +158,8 @@ typedef UINT8 tBTA_JV_CONN_STATE; #define BTA_JV_RFCOMM_READ_EVT 32 /* the result for BTA_JvRfcommRead */ #define BTA_JV_RFCOMM_WRITE_EVT 33 /* the result for BTA_JvRfcommWrite*/ #define BTA_JV_RFCOMM_SRV_OPEN_EVT 34 /* open status of Server RFCOMM connection */ -#define BTA_JV_MAX_EVT 35 /* max number of JV events */ +#define BTA_JV_FREE_SCN_EVT 35 /* FREE an SCN */ +#define BTA_JV_MAX_EVT 36 /* max number of JV events */ typedef UINT16 tBTA_JV_EVT; @@ -358,6 +360,23 @@ typedef struct { tBTA_JV_CONN_STATE state; /* JV connection stata */ } tBTA_JV_NOTIFY_PM_STATE_CHANGE; +/* indicate server at which status */ +typedef enum { + BTA_JV_SERVER_START_FAILED, + BTA_JV_SERVER_RUNNING, + BTA_JV_SERVER_STATUS_MAX, +} tBTA_JV_SERVER_STATUS; + +typedef struct { + tBTA_JV_SERVER_STATUS server_status; + UINT32 slot_id; +}tBTA_JV_FREE_SCN_USER_DATA; + +/* 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_FREE_SCN; /* union of data associated with JV callback */ typedef union { @@ -386,6 +405,7 @@ typedef union { tBTA_JV_RFCOMM_WRITE rfc_write; /* BTA_JV_RFCOMM_WRITE_EVT */ tBTA_JV_DATA_IND data_ind; /* BTA_JV_L2CAP_DATA_IND_EVT BTA_JV_RFCOMM_DATA_IND_EVT */ + tBTA_JV_FREE_SCN free_scn; /* BTA_JV_FREE_SCN_EVT */ #if BTA_JV_L2CAP_INCLUDED tBTA_JV_L2CAP_LE_OPEN l2c_le_open; /* BTA_JV_L2CAP_OPEN_EVT */ tBTA_JV_LE_DATA_IND le_data_ind; /* BTA_JV_L2CAP_LE_DATA_IND_EVT */ @@ -432,12 +452,25 @@ extern tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback); ** ** Function BTA_JvDisable ** -** Description Disable the Java I/F +** Description Disable the Java I/F. When the enable +** operation is complete the callback function will be +** called with a BTA_JV_DISABLE_EVT. ** ** Returns void ** *******************************************************************************/ -extern void BTA_JvDisable(void); +extern void BTA_JvDisable(tBTA_JV_RFCOMM_CBACK *p_cback); + +/******************************************************************************* +** +** Function BTA_JvFree +** +** Description Free JV configuration +** +** Returns void +** +*******************************************************************************/ +extern void BTA_JvFree(void); /******************************************************************************* ** @@ -492,12 +525,17 @@ extern tBTA_JV_STATUS BTA_JvGetChannelId(int conn_type, void *user_data, ** ** Description This function frees a SCN/PSM that was used ** by an application running over RFCOMM or L2CAP. +** Parameters +** channel The channel to free +** conn_type one of BTA_JV_CONN_TYPE_ +** p_cback tBTA_JV_RFCOMM_CBACK is called with BTA_JV_FREE_SCN_EVT when server frees a SCN/PSM +** user_data indicate the RFCOMM server status ** ** Returns BTA_JV_SUCCESS, if the request is being processed. ** BTA_JV_FAILURE, otherwise. ** *******************************************************************************/ -extern tBTA_JV_STATUS BTA_JvFreeChannel(UINT16 channel, int conn_type); +extern tBTA_JV_STATUS BTA_JvFreeChannel(UINT16 channel, int conn_type, tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data); /******************************************************************************* ** @@ -779,7 +817,7 @@ extern tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, ** BTA_JV_FAILURE, otherwise. ** *******************************************************************************/ -extern tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, void *user_data); +extern tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data); /******************************************************************************* ** diff --git a/components/bt/bluedroid/bta/jv/bta_jv_act.c b/components/bt/bluedroid/bta/jv/bta_jv_act.c index 33132fe7f..e6dba0d36 100644 --- a/components/bt/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/bluedroid/bta/jv/bta_jv_act.c @@ -112,7 +112,12 @@ static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(UINT32 jv_handle); static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb); static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb); static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE state); -tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE new_st); +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_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); /******************************************************************************* ** @@ -287,6 +292,12 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pc BOOLEAN remove_server = FALSE; int close_pending = 0; + UINT8 used = 0, i, listen = 0; + tPORT_STATE port_state; + UINT32 event_mask = BTA_JV_RFC_EV_MASK; + UINT32 scn_num = (UINT32)p_cb->scn; + tBTA_JV evt_data; + if (!p_cb || !p_pcb) { APPL_TRACE_ERROR("bta_jv_free_sr_rfc_cb, p_cb or p_pcb cannot be null"); return BTA_JV_FAILURE; @@ -362,6 +373,57 @@ 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)) { + + 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]; + if (p_pcb->state == BTA_JV_ST_SR_LISTEN) { + listen++; + } + 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); + if (used < p_cb->max_sess && + listen == 0 && + 0 <= si && + si < BTA_JV_MAX_RFC_SR_SESSION) { + /* make sure the server has a listen port */ + if ((RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, TRUE, + BTA_JV_DEF_RFC_MTU, (UINT8 *)bd_addr_any, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS) && + (p_cb->rfc_hdl[si] != 0)) { + p_cb->curr_sess++; + p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1]; + p_pcb->state = BTA_JV_ST_SR_LISTEN; + p_pcb->port_handle = p_cb->rfc_hdl[si]; + // p_pcb->user_data = p_pcb_open->user_data; + + PORT_ClearKeepHandleFlag(p_pcb->port_handle); + PORT_SetEventCallback(p_pcb->port_handle, bta_jv_port_event_sr_cback); + PORT_SetDataCOCallback(p_pcb->port_handle, bta_jv_port_data_co_cback); + PORT_SetEventMask(p_pcb->port_handle, event_mask); + PORT_GetState(p_pcb->port_handle, &port_state); + + port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); + + PORT_SetState(p_pcb->port_handle, &port_state); + p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si); + APPL_TRACE_DEBUG("%s: p_pcb->handle:0x%x, curr_sess:%d", __func__, + p_pcb->handle, p_cb->curr_sess); + + evt_data.rfc_srv_open.handle = 0; + evt_data.rfc_srv_open.new_listen_handle = p_pcb->handle; + evt_data.rfc_srv_open.status = BTA_JV_SUCCESS; + p_pcb->user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, (void *)scn_num); + } + } + } + if (p_cb->curr_sess == 0) { p_cb->scn = 0; bta_jv_free_sec_id(&p_cb->sec_id); @@ -678,7 +740,12 @@ void bta_jv_enable(tBTA_JV_MSG *p_data) *******************************************************************************/ void bta_jv_disable (tBTA_JV_MSG *p_data) { - UNUSED(p_data); + tBTA_JV_STATUS evt_data; + evt_data = BTA_JV_SUCCESS; + // UNUSED(p_data); + if (p_data->disable.p_cback) { + p_data->disable.p_cback(BTA_JV_DISABLE_EVT, (tBTA_JV *)&evt_data, NULL); + } } @@ -787,7 +854,16 @@ void bta_jv_get_channel_id(tBTA_JV_MSG *p_data) *******************************************************************************/ void bta_jv_free_scn(tBTA_JV_MSG *p_data) { - UINT16 scn = p_data->free_channel.scn; + tBTA_JV_API_FREE_CHANNEL *fc = &(p_data->free_channel); + UINT16 scn = fc->scn; + tBTA_JV_FREE_SCN evt_data = { + .status = BTA_JV_SUCCESS, + .server_status = BTA_JV_SERVER_STATUS_MAX, + }; + + tBTA_JV_FREE_SCN_USER_DATA *user_data = NULL; + tBTA_JV_RFC_CB *p_cb = NULL; + tBTA_JV_PCB *p_pcb = NULL; switch (p_data->free_channel.type) { case BTA_JV_CONN_TYPE_RFCOMM: { @@ -807,6 +883,19 @@ void bta_jv_free_scn(tBTA_JV_MSG *p_data) default: break; } + + if (fc->user_data) { + user_data = (tBTA_JV_FREE_SCN_USER_DATA *)fc->user_data; + evt_data.server_status = user_data->server_status; + if (user_data->server_status == BTA_JV_SERVER_RUNNING && find_rfc_pcb((void *)user_data->slot_id, &p_cb, &p_pcb)) { + /* if call bta_jv_rfcomm_stop_server successfully, find_rfc_pcb shall return false */ + evt_data.status = BTA_JV_FAILURE; + } + + if (fc->p_cback) { + fc->p_cback(BTA_JV_FREE_SCN_EVT, (tBTA_JV *)&evt_data, (void *)user_data); + } + } } static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID *u) { @@ -1603,6 +1692,7 @@ static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle) evt_data.rfc_close.async = TRUE; if (p_pcb->state == BTA_JV_ST_CL_CLOSING) { 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; @@ -1767,9 +1857,10 @@ 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; - APPL_TRACE_DEBUG("bta_jv_rfcomm_close, rfc handle:%d", cc->handle); + tBTA_JV evt_data; + APPL_TRACE_DEBUG("%s, rfc handle:%d",__func__, cc->handle); if (!cc->handle) { - APPL_TRACE_ERROR("bta_jv_rfcomm_close, rfc handle is null"); + APPL_TRACE_ERROR("%s, rfc handle is null", __func__); return; } @@ -1777,9 +1868,21 @@ 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); - APPL_TRACE_DEBUG("bta_jv_rfcomm_close: sec id in use:%d, rfc_cb in use:%d", - get_sec_id_used(), get_rfc_cb_used()); + APPL_TRACE_DEBUG("%s: sec id in use:%d, rfc_cb in use:%d", __func__, get_sec_id_used(), get_rfc_cb_used()); } /******************************************************************************* @@ -1983,6 +2086,8 @@ static tBTA_JV_PCB *bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb p_pcb->handle, p_cb->curr_sess); } } 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"); } } diff --git a/components/bt/bluedroid/bta/jv/bta_jv_api.c b/components/bt/bluedroid/bta/jv/bta_jv_api.c index 5cb5d8706..ccbdadcb0 100644 --- a/components/bt/bluedroid/bta/jv/bta_jv_api.c +++ b/components/bt/bluedroid/bta/jv/bta_jv_api.c @@ -69,6 +69,16 @@ tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback) int i; APPL_TRACE_API( "BTA_JvEnable"); + +#if BTA_DYNAMIC_MEMORY == TRUE + /* Malloc buffer for JV configuration structure */ + p_bta_jv_cfg->p_sdp_raw_data = (UINT8 *)osi_malloc(p_bta_jv_cfg->sdp_raw_size); + p_bta_jv_cfg->p_sdp_db = (tSDP_DISCOVERY_DB *)osi_malloc(p_bta_jv_cfg->sdp_db_size); + if (p_bta_jv_cfg->p_sdp_raw_data == NULL || p_bta_jv_cfg->p_sdp_db == NULL) { + return BTA_JV_NO_DATA; + } +#endif + if (p_cback && FALSE == bta_sys_is_register(BTA_ID_JV)) { memset(&bta_jv_cb, 0, sizeof(tBTA_JV_CB)); /* set handle to invalid value by default */ @@ -100,18 +110,39 @@ tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback) ** Returns void ** *******************************************************************************/ -void BTA_JvDisable(void) +void BTA_JvDisable(tBTA_JV_RFCOMM_CBACK *p_cback) { - BT_HDR *p_buf; + tBTA_JV_API_DISABLE *p_buf; APPL_TRACE_API( "BTA_JvDisable"); bta_sys_deregister(BTA_ID_JV); - if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { - p_buf->event = BTA_JV_API_DISABLE_EVT; + if ((p_buf = (tBTA_JV_API_DISABLE *) osi_malloc(sizeof(tBTA_JV_API_DISABLE))) != NULL) { + p_buf->hdr.event = BTA_JV_API_DISABLE_EVT; + p_buf->p_cback = p_cback; bta_sys_sendmsg(p_buf); } } +/******************************************************************************* +** +** Function BTA_JvFree +** +** Description Free JV configuration +** +** Returns void +** +*******************************************************************************/ +void BTA_JvFree(void) +{ +#if BTA_DYNAMIC_MEMORY == TRUE + /* Free buffer for JV configuration structure */ + osi_free(p_bta_jv_cfg->p_sdp_raw_data); + osi_free(p_bta_jv_cfg->p_sdp_db); + p_bta_jv_cfg->p_sdp_raw_data = NULL; + p_bta_jv_cfg->p_sdp_db = NULL; +#endif +} + /******************************************************************************* ** ** Function BTA_JvIsEnable @@ -199,12 +230,14 @@ tBTA_JV_STATUS BTA_JvGetChannelId(int conn_type, void *user_data, INT32 channel) ** Parameters ** channel The channel to free ** conn_type one of BTA_JV_CONN_TYPE_ +** p_cback tBTA_JV_RFCOMM_CBACK is called with when server +** user_data indicate the RFCOMM server status ** ** Returns BTA_JV_SUCCESS, if the request is being processed. ** BTA_JV_FAILURE, otherwise. ** *******************************************************************************/ -tBTA_JV_STATUS BTA_JvFreeChannel(UINT16 channel, int conn_type) +tBTA_JV_STATUS BTA_JvFreeChannel(UINT16 channel, int conn_type, tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data) { tBTA_JV_STATUS status = BTA_JV_FAILURE; tBTA_JV_API_FREE_CHANNEL *p_msg; @@ -214,6 +247,8 @@ tBTA_JV_STATUS BTA_JvFreeChannel(UINT16 channel, int conn_type) p_msg->hdr.event = BTA_JV_API_FREE_SCN_EVT; p_msg->scn = channel; p_msg->type = conn_type; + p_msg->p_cback = p_cback; + p_msg->user_data = user_data; bta_sys_sendmsg(p_msg); status = BTA_JV_SUCCESS; } @@ -870,19 +905,20 @@ tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, ** Function BTA_JvRfcommClose ** ** Description This function closes an RFCOMM connection -** +** When the connection is established or failed, +** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_CLOSE_EVT ** Returns BTA_JV_SUCCESS, if the request is being processed. ** BTA_JV_FAILURE, otherwise. ** *******************************************************************************/ -tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, void *user_data) +tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data) { tBTA_JV_STATUS status = BTA_JV_FAILURE; tBTA_JV_API_RFCOMM_CLOSE *p_msg; UINT32 hi = ((handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1; UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle); - APPL_TRACE_API( "BTA_JvRfcommClose"); + APPL_TRACE_API( "%s", __func__); if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback && si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si] && (p_msg = (tBTA_JV_API_RFCOMM_CLOSE *)osi_malloc(sizeof(tBTA_JV_API_RFCOMM_CLOSE))) != NULL) { @@ -890,6 +926,7 @@ tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle, void *user_data) 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/bluedroid/bta/jv/include/bta_jv_int.h b/components/bt/bluedroid/bta/jv/include/bta_jv_int.h index a822de007..eadbe1ce0 100644 --- a/components/bt/bluedroid/bta/jv/include/bta_jv_int.h +++ b/components/bt/bluedroid/bta/jv/include/bta_jv_int.h @@ -84,6 +84,12 @@ typedef struct { tBTA_JV_DM_CBACK *p_cback; } tBTA_JV_API_ENABLE; +/* data type for BTA_JV_API_DISABLE_EVT */ +typedef struct { + BT_HDR hdr; + tBTA_JV_RFCOMM_CBACK *p_cback; +} tBTA_JV_API_DISABLE; + /* data type for BTA_JV_API_START_DISCOVERY_EVT */ typedef struct { BT_HDR hdr; @@ -309,6 +315,7 @@ 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; @@ -335,6 +342,8 @@ typedef struct { BT_HDR hdr; INT32 type; /* One of BTA_JV_CONN_TYPE_ */ UINT16 scn; + tBTA_JV_RFCOMM_CBACK *p_cback; + void *user_data; } tBTA_JV_API_FREE_CHANNEL; /* data type for BTA_JV_API_ALLOC_CHANNEL_EVT */ @@ -349,6 +358,7 @@ typedef union { /* GKI event buffer header */ BT_HDR hdr; tBTA_JV_API_ENABLE enable; + tBTA_JV_API_DISABLE disable; tBTA_JV_API_START_DISCOVERY start_discovery; tBTA_JV_API_ALLOC_CHANNEL alloc_channel; tBTA_JV_API_FREE_CHANNEL free_channel; diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_spp.h b/components/bt/bluedroid/btc/profile/std/include/btc_spp.h index a8b409e0a..d3c8a4938 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_spp.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_spp.h @@ -35,6 +35,7 @@ typedef enum { BTC_SPP_ACT_CONNECT, BTC_SPP_ACT_DISCONNECT, BTC_SPP_ACT_START_SRV, + BTC_SPP_ACT_STOP_SRV, BTC_SPP_ACT_WRITE, } btc_spp_act_t; diff --git a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c index bc2d62427..dfe07112d 100644 --- a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c @@ -29,6 +29,7 @@ #include #include "esp_vfs.h" #include "esp_vfs_dev.h" +#include "stack/port_api.h" #if (defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE) @@ -55,13 +56,20 @@ typedef struct { char service_name[ESP_SPP_SERVER_NAME_MAX + 1]; } spp_slot_t; -static struct spp_local_param_t { - spp_slot_t *spp_slots[BTA_JV_MAX_RFC_SR_SESSION + 1]; +typedef struct { + spp_slot_t *spp_slots[MAX_RFC_PORTS + 1]; uint32_t spp_slot_id; esp_spp_mode_t spp_mode; osi_mutex_t spp_slot_mutex; esp_vfs_id_t spp_vfs_id; -} spp_local_param; +} spp_local_param_t; + +#if SPP_DYNAMIC_MEMORY == FALSE +static spp_local_param_t spp_local_param; +#else +static spp_local_param_t *spp_local_param_ptr; +#define spp_local_param (*spp_local_param_ptr) +#endif static void spp_osi_free(void *p) { @@ -73,7 +81,7 @@ static spp_slot_t *spp_malloc_slot(void) if (++spp_local_param.spp_slot_id == 0) { spp_local_param.spp_slot_id = 1; } - for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { + for (size_t i = 1; i <= MAX_RFC_PORTS; i++) { if (spp_local_param.spp_slots[i] == NULL) { spp_local_param.spp_slots[i] = (spp_slot_t *)osi_malloc(sizeof(spp_slot_t)); if (!spp_local_param.spp_slots[i]) { @@ -81,6 +89,9 @@ static spp_slot_t *spp_malloc_slot(void) } spp_local_param.spp_slots[i]->id = spp_local_param.spp_slot_id; spp_local_param.spp_slots[i]->serial = i; + spp_local_param.spp_slots[i]->sdp_handle = 0; + spp_local_param.spp_slots[i]->rfc_handle = 0; + spp_local_param.spp_slots[i]->rfc_port_handle = 0; spp_local_param.spp_slots[i]->connected = FALSE; spp_local_param.spp_slots[i]->write_data = NULL; spp_local_param.spp_slots[i]->list = list_new(spp_osi_free); @@ -101,7 +112,7 @@ static spp_slot_t *spp_malloc_slot(void) static spp_slot_t *spp_find_slot_by_id(uint32_t id) { - for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { + 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]; } @@ -111,7 +122,7 @@ static spp_slot_t *spp_find_slot_by_id(uint32_t id) static spp_slot_t *spp_find_slot_by_handle(uint32_t handle) { - for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { + 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]; } @@ -121,7 +132,7 @@ static spp_slot_t *spp_find_slot_by_handle(uint32_t handle) static spp_slot_t *spp_find_slot_by_fd(int fd) { - for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { + 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]; } @@ -129,6 +140,16 @@ static spp_slot_t *spp_find_slot_by_fd(int fd) return NULL; } +static spp_slot_t *spp_find_slot_by_scn(uint32_t scn) +{ + 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]; + } + } + return NULL; +} + static void spp_free_slot(spp_slot_t *slot) { if (!slot) { @@ -160,15 +181,6 @@ static void btc_create_server_fail_cb(void) btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m); } -static void btc_disconnect_cb(uint32_t handle) -{ - esp_spp_cb_param_t param; - param.close.status = ESP_SPP_SUCCESS; - param.close.handle = handle; - param.close.async = FALSE; - btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, ¶m); -} - static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) { bt_status_t status; @@ -177,34 +189,53 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u uint32_t id = (uintptr_t)user_data; spp_slot_t *slot, *slot_new; + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_WARNING("%s SPP have been deinit, incoming events ignore!\n", __func__); + return new_user_data; + } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); switch (event) { - case BTA_JV_RFCOMM_SRV_OPEN_EVT: + 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__); break; } - slot_new = spp_malloc_slot(); - if (!slot_new) { - BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__); + slot->rfc_handle = p_data->rfc_start.handle; + slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_start.handle); + break; + 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__); break; } - new_user_data = (void *)(uintptr_t)slot_new->id; - 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); - 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) { + 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) { + slot_new = spp_malloc_slot(); + if (!slot_new) { + BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__); + break; + } + new_user_data = (void *)(uintptr_t)slot_new->id; + 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); + } break; case BTA_JV_RFCOMM_OPEN_EVT: slot = spp_find_slot_by_id(id); @@ -223,14 +254,26 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); break; } - if (slot->connected) { - BTA_JvRfcommClose(slot->rfc_handle, (void *)slot->id); + if (slot->connected && p_data->rfc_close.port_status != PORT_LOCAL_CLOSED) { + BTA_JvRfcommClose(slot->rfc_handle, NULL, (void *)slot->id); } spp_free_slot(slot); p_data->rfc_close.status = BTA_JV_SUCCESS; break; case BTA_JV_RFCOMM_DATA_IND_EVT: break; + case BTA_JV_FREE_SCN_EVT: + if (user_data) { + id = ((tBTA_JV_FREE_SCN_USER_DATA *)user_data)->slot_id; + slot = spp_find_slot_by_id(id); + if (slot) { + spp_free_slot(slot); + } else { + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); + } + osi_free(user_data); + } + break; default: break; } @@ -292,8 +335,15 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d } else { BTC_TRACE_ERROR("%s unable to create record, start server fail!", __func__); btc_create_server_fail_cb(); - BTA_JvFreeChannel(slot->scn, BTA_JV_CONN_TYPE_RFCOMM); - spp_free_slot(slot); + 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_START_FAILED; + user_data->slot_id = slot->id; + } else { + BTC_TRACE_ERROR("%s unable to malloc user data!", __func__); + } + BTA_JvFreeChannel(slot->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); break; @@ -313,6 +363,22 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d static void btc_spp_init(btc_spp_args_t *arg) { + if (spp_local_param.spp_slot_mutex) { + esp_spp_cb_param_t param; + param.init.status = ESP_SPP_FAILURE; + btc_spp_cb_to_app(ESP_SPP_INIT_EVT, ¶m); + BTC_TRACE_ERROR("%s SPP has been initiated, shall uninit first!", __func__); + return; + } + +#if SPP_DYNAMIC_MEMORY == TRUE + if ((spp_local_param_ptr = (spp_local_param_t *)osi_malloc(sizeof(spp_local_param_t))) == NULL) { + BTC_TRACE_ERROR("%s malloc failed\n", __func__); + return; + } + memset((void *)spp_local_param_ptr, 0, sizeof(spp_local_param_t)); +#endif + if (osi_mutex_new(&spp_local_param.spp_slot_mutex) != 0) { BTC_TRACE_ERROR("%s osi_mutex_new failed\n", __func__); return; @@ -324,40 +390,65 @@ static void btc_spp_init(btc_spp_args_t *arg) static void btc_spp_uninit(void) { + esp_spp_cb_param_t param; if (!spp_local_param.spp_slot_mutex) { - BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + param.uninit.status = ESP_SPP_FAILURE; + btc_spp_cb_to_app(ESP_SPP_UNINIT_EVT, ¶m); + BTC_TRACE_ERROR("%s SPP has not been initiated, shall init first!", __func__); return; } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { + // 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, (void *)spp_local_param.spp_slots[i]->id); - spp_free_slot(spp_local_param.spp_slots[i]); - spp_local_param.spp_slots[i] = NULL; - } - } - for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { - if (spp_local_param.spp_slots[i] != NULL && !(spp_local_param.spp_slots[i]->connected)) { - BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->sdp_handle, (void *)spp_local_param.spp_slots[i]->id); - BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle); - BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM); - spp_free_slot(spp_local_param.spp_slots[i]); - spp_local_param.spp_slots[i] = NULL; + 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]->sdp_handle > 0) { + BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle); + } - BTA_JvDisable(); + 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 { + 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, ¶m); + } + 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_JvDisable((tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); - osi_mutex_free(&spp_local_param.spp_slot_mutex); } static void btc_spp_start_discovery(btc_spp_args_t *arg) { + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return; + } BTA_JvStartDiscovery(arg->start_discovery.bd_addr, arg->start_discovery.num_uuid, arg->start_discovery.p_uuid_list, NULL); } static void btc_spp_connect(btc_spp_args_t *arg) { + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return; + } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = spp_malloc_slot(); if (!slot) { @@ -376,6 +467,10 @@ static void btc_spp_connect(btc_spp_args_t *arg) static void btc_spp_disconnect(btc_spp_args_t *arg) { + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return; + } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = spp_find_slot_by_handle(arg->disconnect.handle); if (!slot) { @@ -383,14 +478,16 @@ static void btc_spp_disconnect(btc_spp_args_t *arg) osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return; } - BTA_JvRfcommClose(arg->disconnect.handle, (void *)slot->id); - btc_disconnect_cb(slot->rfc_handle); - spp_free_slot(slot); + BTA_JvRfcommClose(arg->disconnect.handle, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)slot->id); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); } static void btc_spp_start_srv(btc_spp_args_t *arg) { + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return; + } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = spp_malloc_slot(); if (!slot) { @@ -408,8 +505,54 @@ static void btc_spp_start_srv(btc_spp_args_t *arg) osi_mutex_unlock(&spp_local_param.spp_slot_mutex); } +static void btc_spp_stop_srv(void) { + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return; + } + esp_spp_cb_param_t param; + 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); + } + } + // 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 (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 { + 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, ¶m); + } + 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); +} + static void btc_spp_write(btc_spp_args_t *arg) { + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return; + } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = spp_find_slot_by_handle(arg->write.handle); if (!slot) { @@ -423,7 +566,7 @@ static void btc_spp_write(btc_spp_args_t *arg) osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return; } - uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0,990); + uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0, BTA_JV_DEF_RFC_MTU); if (item_size != 0){ slot->write_data = data; BTA_JvRfcommWrite(arg->write.handle, slot->id, item_size, data); @@ -504,6 +647,9 @@ void btc_spp_call_handler(btc_msg_t *msg) case BTC_SPP_ACT_START_SRV: btc_spp_start_srv(arg); break; + case BTC_SPP_ACT_STOP_SRV: + btc_spp_stop_srv(); + break; case BTC_SPP_ACT_WRITE: btc_spp_write(arg); break; @@ -562,22 +708,24 @@ void btc_spp_cb_handler(btc_msg_t *msg) btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m); break; case BTA_JV_RFCOMM_SRV_OPEN_EVT: - if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { - osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = spp_find_slot_by_handle(p_data->rfc_srv_open.handle); - if (!slot) { - BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); + if (p_data->rfc_srv_open.handle) { + if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { + osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + slot = spp_find_slot_by_handle(p_data->rfc_srv_open.handle); + if (!slot) { + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); + osi_mutex_unlock(&spp_local_param.spp_slot_mutex); + break; + } + param.srv_open.fd = slot->fd; osi_mutex_unlock(&spp_local_param.spp_slot_mutex); - break; } - param.srv_open.fd = slot->fd; - osi_mutex_unlock(&spp_local_param.spp_slot_mutex); + param.srv_open.status = p_data->rfc_srv_open.status; + param.srv_open.handle = p_data->rfc_srv_open.handle; + param.srv_open.new_listen_handle = p_data->rfc_srv_open.new_listen_handle; + memcpy(param.srv_open.rem_bda, p_data->rfc_srv_open.rem_bda, ESP_BD_ADDR_LEN); + btc_spp_cb_to_app(ESP_SPP_SRV_OPEN_EVT, ¶m); } - param.srv_open.status = p_data->rfc_srv_open.status; - param.srv_open.handle = p_data->rfc_srv_open.handle; - param.srv_open.new_listen_handle = p_data->rfc_srv_open.new_listen_handle; - memcpy(param.srv_open.rem_bda, p_data->rfc_srv_open.rem_bda, ESP_BD_ADDR_LEN); - btc_spp_cb_to_app(ESP_SPP_SRV_OPEN_EVT, ¶m); break; case BTA_JV_RFCOMM_WRITE_EVT: osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); @@ -609,7 +757,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) slot->write_data = NULL; } size_t item_size = 0; - uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0,990); + uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0, BTA_JV_DEF_RFC_MTU); if (item_size != 0){ slot->write_data = data; BTA_JvRfcommWrite(slot->rfc_handle, slot->id, item_size, data); @@ -645,7 +793,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) slot->write_data = NULL; } size_t item_size = 0; - uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0,990); + uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0, BTA_JV_DEF_RFC_MTU); if (item_size != 0){ slot->write_data = data; BTA_JvRfcommWrite(slot->rfc_handle, slot->id, item_size, data); @@ -668,6 +816,22 @@ void btc_spp_cb_handler(btc_msg_t *msg) btc_spp_cb_to_app(ESP_SPP_DATA_IND_EVT, ¶m); osi_free (p_data->data_ind.p_buf); break; + 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; + btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m); + } + break; + case BTA_JV_DISABLE_EVT: + param.uninit.status = ESP_SPP_SUCCESS; + BTA_JvFree(); + osi_mutex_free(&spp_local_param.spp_slot_mutex); +#if SPP_DYNAMIC_MEMORY == TRUE + osi_free(spp_local_param_ptr); + spp_local_param_ptr = NULL; +#endif + btc_spp_cb_to_app(ESP_SPP_UNINIT_EVT, ¶m); + break; default: BTC_TRACE_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act); break; @@ -705,12 +869,16 @@ int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) msg.act = BTA_JV_RFCOMM_DATA_IND_EVT; uint32_t id = (uintptr_t)user_data; + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return -1; + } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = spp_find_slot_by_id(id); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); - return 0; + return -1; } p_data.data_ind.handle = slot->rfc_handle; @@ -751,6 +919,10 @@ int bta_co_rfc_data_outgoing(void *user_data, uint8_t *buf, uint16_t size) static ssize_t spp_vfs_write(int fd, const void * data, size_t size) { + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return -1; + } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = spp_find_slot_by_fd(fd); if (!slot) { @@ -770,6 +942,10 @@ static ssize_t spp_vfs_write(int fd, const void * data, size_t size) } static int spp_vfs_close(int fd) { + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return -1; + } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = spp_find_slot_by_fd(fd); if (!slot) { @@ -798,6 +974,10 @@ static bool incoming_list_2_ringbuf_read(spp_slot_t *slot) static ssize_t spp_vfs_read(int fd, void * dst, size_t size) { + if (!spp_local_param.spp_slot_mutex) { + BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); + return -1; + } osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = spp_find_slot_by_fd(fd); if (!slot) { diff --git a/components/bt/bluedroid/common/include/common/bt_target.h b/components/bt/bluedroid/common/include/common/bt_target.h index 00b4c6072..d9f59fc73 100644 --- a/components/bt/bluedroid/common/include/common/bt_target.h +++ b/components/bt/bluedroid/common/include/common/bt_target.h @@ -1360,7 +1360,7 @@ /* The maximum number of ports supported. */ #ifndef MAX_RFC_PORTS -#define MAX_RFC_PORTS 16 /*max is 30*/ +#define MAX_RFC_PORTS 8 /*max is 30*/ #endif /* The maximum simultaneous links to different devices. */ diff --git a/components/bt/bluedroid/stack/btm/btm_acl.c b/components/bt/bluedroid/stack/btm/btm_acl.c index 63bf5f324..fe152b0ee 100644 --- a/components/bt/bluedroid/stack/btm/btm_acl.c +++ b/components/bt/bluedroid/stack/btm/btm_acl.c @@ -794,7 +794,7 @@ void btm_acl_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) BTM_TRACE_WARNING("btm_acl_encrypt_change -> Issuing delayed HCI_Disconnect!!!\n"); btsnd_hcic_disconnect(p_dev_rec->hci_handle, HCI_ERR_PEER_USER); } - BTM_TRACE_ERROR("btm_acl_encrypt_change: tBTM_SEC_DEV:0x%x rs_disc_pending=%d\n", + BTM_TRACE_WARNING("btm_acl_encrypt_change: tBTM_SEC_DEV:0x%x rs_disc_pending=%d\n", (UINT32)p_dev_rec, p_dev_rec->rs_disc_pending); p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */ } diff --git a/components/bt/bluedroid/stack/btm/btm_sec.c b/components/bt/bluedroid/stack/btm/btm_sec.c index 47983f825..a6fc87334 100644 --- a/components/bt/bluedroid/stack/btm/btm_sec.c +++ b/components/bt/bluedroid/stack/btm/btm_sec.c @@ -2257,7 +2257,7 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle } } else if (!(BTM_SM4_KNOWN & p_dev_rec->sm4)) { /* the remote features are not known yet */ - BTM_TRACE_DEBUG("%s: (%s) remote features unknown!!sec_flags:0x%02x\n", __FUNCTION__, + BTM_TRACE_ERROR("%s: (%s) remote features unknown!!sec_flags:0x%02x\n", __FUNCTION__, (is_originator) ? "initiator" : "acceptor", p_dev_rec->sec_flags); p_dev_rec->sm4 |= BTM_SM4_REQ_PEND; diff --git a/examples/bluetooth/bt_spp_acceptor/main/example_spp_acceptor_demo.c b/examples/bluetooth/bt_spp_acceptor/main/example_spp_acceptor_demo.c index e73241e30..5c7974aac 100644 --- a/examples/bluetooth/bt_spp_acceptor/main/example_spp_acceptor_demo.c +++ b/examples/bluetooth/bt_spp_acceptor/main/example_spp_acceptor_demo.c @@ -98,6 +98,12 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) ESP_LOGI(SPP_TAG, "ESP_SPP_SRV_OPEN_EVT"); gettimeofday(&time_old, NULL); break; + case ESP_SPP_SRV_STOP_EVT: + ESP_LOGI(SPP_TAG, "ESP_SPP_SRV_STOP_EVT"); + break; + case ESP_SPP_UNINIT_EVT: + ESP_LOGI(SPP_TAG, "ESP_SPP_UNINIT_EVT"); + break; default: break; } diff --git a/examples/bluetooth/bt_spp_initiator/main/example_spp_initiator_demo.c b/examples/bluetooth/bt_spp_initiator/main/example_spp_initiator_demo.c index 91cf6940b..de8dd0edc 100644 --- a/examples/bluetooth/bt_spp_initiator/main/example_spp_initiator_demo.c +++ b/examples/bluetooth/bt_spp_initiator/main/example_spp_initiator_demo.c @@ -116,7 +116,7 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) break; case ESP_SPP_OPEN_EVT: ESP_LOGI(SPP_TAG, "ESP_SPP_OPEN_EVT"); - esp_spp_write(param->srv_open.handle, SPP_DATA_LEN, spp_data); + esp_spp_write(param->open.handle, SPP_DATA_LEN, spp_data); gettimeofday(&time_old, NULL); break; case ESP_SPP_CLOSE_EVT: @@ -157,6 +157,9 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) case ESP_SPP_SRV_OPEN_EVT: ESP_LOGI(SPP_TAG, "ESP_SPP_SRV_OPEN_EVT"); break; + case ESP_SPP_UNINIT_EVT: + ESP_LOGI(SPP_TAG, "ESP_SPP_UNINIT_EVT"); + break; default: break; }