Merge branch 'bugfix/fix_spp_listen_err' into 'master'

Component_bt/Fix SPP cannot malloc slot bugs

Closes BCI-300

See merge request espressif/esp-idf!16035
This commit is contained in:
Li Qi Gan 2021-12-02 07:20:58 +00:00
commit 54c5d42a62
13 changed files with 207 additions and 116 deletions

View File

@ -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_2(UINT32 code, UINT16 port_handle);
void bta_ag_port_cback_3(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_1(UINT32 code, UINT16 port_handle, void* data);
void bta_ag_mgmt_cback_2(UINT32 code, UINT16 port_handle); 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 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_1(UINT16 port_handle, void *p_data, UINT16 len);
int bta_ag_data_cback_2(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 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_1,
bta_ag_mgmt_cback_2, 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 ** Returns void
** **
*******************************************************************************/ *******************************************************************************/
void bta_ag_mgmt_cback_1(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 1);} 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) {bta_ag_mgmt_cback(code, handle, 2);} 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) {bta_ag_mgmt_cback(code, handle, 3);} 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_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_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);} void bta_ag_port_cback_3(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 3);}

View File

@ -70,7 +70,7 @@ static void bta_hf_client_port_cback(UINT32 code, UINT16 port_handle)
** Returns void ** 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; tBTA_HF_CLIENT_RFC *p_buf;
UINT16 event; UINT16 event;

View File

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

View File

@ -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); 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 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 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); 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; 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; tBTA_JV_STATUS status = BTA_JV_SUCCESS;
BOOLEAN remove_server = FALSE; 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; tPORT_STATE port_state;
UINT32 event_mask = BTA_JV_RFC_EV_MASK; UINT32 event_mask = BTA_JV_RFC_EV_MASK;
UINT32 scn_num = (UINT32)p_cb->scn; UINT32 scn_num = (UINT32)p_cb->scn;
tBTA_JV evt_data; tBTA_JV evt_data = {0};
if (!p_cb || !p_pcb) { if (!p_cb || !p_pcb) {
APPL_TRACE_ERROR("bta_jv_free_sr_rfc_cb, p_cb or p_pcb cannot be null"); 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_pcb->handle = 0;
p_cb->curr_sess--; p_cb->curr_sess--;
if ((p_cb->max_sess > 1) && /* only needs a listening port when has a server */
(p_cb->scn != 0) && if (!close_server && (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++) { for (i = 0; i < p_cb->max_sess; i++) {
if (p_cb->rfc_hdl[i] != 0) { if (p_cb->rfc_hdl[i] != 0) {
p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1]; 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++; used++;
} }
} }
APPL_TRACE_DEBUG("%s max_sess=%d used:%d curr_sess:%d, listen:%d si:%d", APPL_TRACE_DEBUG("%s max_sess=%d used:%d curr_sess:%d, listen:%d si:%d", __func__, p_cb->max_sess, used,
__func__, p_cb->max_sess, used, p_cb->curr_sess, listen, si); p_cb->curr_sess, listen, si);
if (used < p_cb->max_sess && if (used < p_cb->max_sess &&
listen == 0 && listen == 0 &&
0 <= si && 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->handle = 0;
p_cb->curr_sess = -1; p_cb->curr_sess = -1;
} }
if (remove_server) {
bta_jv_free_sec_id(&p_cb->sec_id);
}
} }
return status; 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) 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_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) { if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) {
return; 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) 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_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; tBTA_JV_L2CAP_CBACK *p_cback;
void *user_data; void *user_data;
@ -1666,11 +1661,11 @@ static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len,
** Returns void ** 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_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_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
tBTA_JV evt_data; tBTA_JV evt_data = {0};
BD_ADDR rem_bda; BD_ADDR rem_bda;
UINT16 lcid; UINT16 lcid;
tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */ 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_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_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); APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback:%d", port_handle);
if (NULL == p_cb || NULL == p_cb->p_cback) { 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_API_RFCOMM_CLOSE *cc = &(p_data->rfcomm_close);
tBTA_JV_RFC_CB *p_cb = NULL; tBTA_JV_RFC_CB *p_cb = NULL;
tBTA_JV_PCB *p_pcb = 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); APPL_TRACE_DEBUG("%s, rfc handle:%d",__func__, cc->handle);
if (!cc->handle) { if (!cc->handle) {
APPL_TRACE_ERROR("%s, rfc handle is null", __func__); APPL_TRACE_ERROR("%s, rfc handle is null", __func__);
@ -1887,7 +1882,7 @@ void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data)
} }
cc->p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data); cc->p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
} }
bta_jv_free_rfc_cb(p_cb, p_pcb); 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__, APPL_TRACE_DEBUG("%s: sec id in use:%d, rfc_cb in use:%d",__func__,
get_sec_id_used(), get_rfc_cb_used()); 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 ** 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_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_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; BD_ADDR rem_bda;
UINT16 lcid; 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); // 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) { 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", // 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); // p_cb, p_cb ? p_cb->p_cback : NULL);
return; 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", // 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); // code, port_handle, p_cb->handle, p_pcb, p_pcb->user_data);
PORT_CheckConnection(port_handle, rem_bda, &lcid); PORT_CheckConnection(port_handle, rem_bda, &lcid);
int failed = TRUE; int failed = TRUE;
if (code == PORT_SUCCESS) { 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.handle = p_pcb->handle;
evt_data.rfc_srv_open.status = BTA_JV_SUCCESS; evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda); 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); tBTA_JV_PCB *p_pcb_new_listen = bta_jv_add_rfc_port(p_cb, p_pcb);
if (p_pcb_new_listen) { if (p_pcb_new_listen) {
evt_data.rfc_srv_open.new_listen_handle = p_pcb_new_listen->handle; 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); new_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); if (new_user_data) {
failed = FALSE; 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 { } 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"); APPL_TRACE_ERROR("bta_jv_add_rfc_port failed to create new listen port");
} }
} }
if (failed) { if (failed) {
evt_data.rfc_close.handle = p_pcb->handle; evt_data.rfc_close.handle = p_pcb->handle;
evt_data.rfc_close.status = BTA_JV_FAILURE; 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_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_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) { if (NULL == p_cb || NULL == p_cb->p_cback) {
return; 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", 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); p_cb->max_sess, used, p_cb->curr_sess, listen, si);
if (used < p_cb->max_sess && listen == 1 && 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 { } else {
/* avoid p_pcb always points to the last element of rfc_hdl */ /* 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"); 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", APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: p_pcb:%p, p_pcb->port_handle:%d",
p_pcb, p_pcb->port_handle); 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", 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()); 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) 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; // tBTA_JV evt_open;
struct fc_channel *tc; struct fc_channel *tc;
struct fc_client *t = NULL; struct fc_client *t = NULL;

View File

@ -1,16 +1,8 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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.
#include <string.h> #include <string.h>
@ -55,8 +47,9 @@ typedef struct {
} slot_data_t; } slot_data_t;
typedef struct { typedef struct {
uint8_t serial;
bool connected; bool connected;
bool is_server;
uint8_t serial;
uint8_t scn; uint8_t scn;
uint8_t max_session; uint8_t max_session;
uint32_t id; uint32_t id;
@ -137,29 +130,34 @@ static spp_slot_t *spp_malloc_slot(void)
(*slot)->sdp_handle = 0; (*slot)->sdp_handle = 0;
(*slot)->rfc_handle = 0; (*slot)->rfc_handle = 0;
(*slot)->rfc_port_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)->write_data = NULL;
(*slot)->close_alarm = NULL; (*slot)->close_alarm = NULL;
if (init_slot_data(&(*slot)->rx, QUEUE_SIZE_MAX)) { if (init_slot_data(&(*slot)->rx, QUEUE_SIZE_MAX)) {
BTC_TRACE_ERROR("%s unable to malloc rx queue!", __func__); BTC_TRACE_ERROR("%s unable to malloc rx queue!", __func__);
err_no = 1; err_no = 1;
break; goto err;
} }
if (init_slot_data(&(*slot)->tx, SLOT_TX_QUEUE_SIZE)) { if (init_slot_data(&(*slot)->tx, SLOT_TX_QUEUE_SIZE)) {
BTC_TRACE_ERROR("%s unable to malloc tx queue!", __func__); BTC_TRACE_ERROR("%s unable to malloc tx queue!", __func__);
err_no = 2; err_no = 2;
break; goto err;
} }
if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { 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) { if (esp_vfs_register_fd(spp_local_param.spp_vfs_id, &(*slot)->fd) != ESP_OK) {
BTC_TRACE_ERROR("%s unable to register fd!", __func__); BTC_TRACE_ERROR("%s unable to register fd!", __func__);
err_no = 3; err_no = 3;
break; goto err;
} }
} }
return (*slot); return (*slot);
} }
} }
return NULL;
err:
switch (err_no) { switch (err_no) {
case 3: case 3:
free_slot_data(&(*slot)->tx); free_slot_data(&(*slot)->tx);
@ -177,9 +175,11 @@ static spp_slot_t *spp_malloc_slot(void)
static spp_slot_t *spp_find_slot_by_id(uint32_t id) 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++) { 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) { slot = spp_local_param.spp_slots[i];
return spp_local_param.spp_slots[i]; if (slot != NULL && slot->id == id) {
return slot;
} }
} }
return NULL; return NULL;
@ -187,9 +187,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) 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++) { 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) { slot = spp_local_param.spp_slots[i];
return spp_local_param.spp_slots[i]; if (slot != NULL && slot->rfc_handle == handle) {
return slot;
} }
} }
return NULL; return NULL;
@ -197,9 +199,11 @@ static spp_slot_t *spp_find_slot_by_handle(uint32_t handle)
static spp_slot_t *spp_find_slot_by_fd(int fd) 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++) { 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) { slot = spp_local_param.spp_slots[i];
return spp_local_param.spp_slots[i]; if (slot != NULL && slot->fd == fd) {
return slot;
} }
} }
return NULL; return NULL;
@ -207,9 +211,11 @@ static spp_slot_t *spp_find_slot_by_fd(int fd)
static spp_slot_t *spp_find_slot_by_scn(uint32_t scn) 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++) { 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) { slot = spp_local_param.spp_slots[i];
return spp_local_param.spp_slots[i]; if (slot != NULL && slot->is_server && slot->scn == (uint8_t)scn) {
return slot;
} }
} }
return NULL; return NULL;
@ -277,9 +283,9 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
bt_status_t status; bt_status_t status;
btc_msg_t msg; btc_msg_t msg;
void *new_user_data = NULL; void *new_user_data = NULL;
uint32_t id = (uintptr_t)user_data, id_temp = 0;
uint32_t id = (uintptr_t)user_data;
spp_slot_t *slot = NULL, *slot_new = NULL; spp_slot_t *slot = NULL, *slot_new = NULL;
if (!is_spp_init()) { if (!is_spp_init()) {
BTC_TRACE_WARNING("%s SPP have been deinit, incoming events ignore!\n", __func__); BTC_TRACE_WARNING("%s SPP have been deinit, incoming events ignore!\n", __func__);
return new_user_data; return new_user_data;
@ -289,7 +295,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
case BTA_JV_RFCOMM_START_EVT: case BTA_JV_RFCOMM_START_EVT:
slot = spp_find_slot_by_id(id); slot = spp_find_slot_by_id(id);
if (!slot) { 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; p_data->rfc_start.status = ESP_SPP_NO_CONNECTION;
break; break;
} }
@ -299,42 +305,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: 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); slot = p_data->rfc_srv_open.handle ? spp_find_slot_by_id(id) : spp_find_slot_by_scn((uint32_t)user_data);
if (!slot) { 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; p_data->rfc_srv_open.status = ESP_SPP_NO_CONNECTION;
break; break;
} }
if (p_data->rfc_srv_open.handle) { if (!p_data->rfc_srv_open.handle) {
new_user_data = (void *)(uintptr_t)slot->id; /* match with the exist server solt */
memcpy(slot->addr, p_data->rfc_srv_open.rem_bda, ESP_BD_ADDR_LEN); slot->rfc_handle = p_data->rfc_srv_open.new_listen_handle;
slot->connected = TRUE; slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(slot->rfc_handle);
slot->rfc_handle = p_data->rfc_srv_open.handle; } else {
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(); slot_new = spp_malloc_slot();
if (!slot_new) { if (!slot_new) {
BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__); BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__);
p_data->rfc_srv_open.status = ESP_SPP_NO_RESOURCE; p_data->rfc_srv_open.status = ESP_SPP_NO_RESOURCE;
break; break;
} }
new_user_data = (void *)(uintptr_t)slot_new->id; slot_new->connected = true;
slot_new->security = slot->security; slot_new->security = slot->security;
slot_new->role = slot->role; slot_new->role = slot->role;
slot_new->scn = slot->scn; slot_new->scn = slot->scn;
slot_new->max_session = slot->max_session; slot_new->max_session = slot->max_session;
strcpy(slot_new->service_name, slot->service_name); strcpy(slot_new->service_name, slot->service_name);
slot_new->sdp_handle = slot->sdp_handle; slot_new->sdp_handle = slot->sdp_handle;
slot_new->rfc_handle = 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(p_data->rfc_srv_open.new_listen_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; break;
case BTA_JV_RFCOMM_OPEN_EVT: case BTA_JV_RFCOMM_OPEN_EVT:
slot = spp_find_slot_by_id(id); slot = spp_find_slot_by_id(id);
if (!slot) { 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; p_data->rfc_open.status = ESP_SPP_NO_CONNECTION;
break; break;
} }
@ -346,7 +362,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
case BTA_JV_RFCOMM_CLOSE_EVT: case BTA_JV_RFCOMM_CLOSE_EVT:
slot = spp_find_slot_by_id(id); slot = spp_find_slot_by_id(id);
if (!slot) { 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; p_data->rfc_close.status = ESP_SPP_NO_CONNECTION;
break; break;
} }
@ -354,6 +370,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); BTA_JvRfcommClose(slot->rfc_handle, NULL, (void *)slot->id);
} }
p_data->rfc_close.status = BTA_JV_SUCCESS; p_data->rfc_close.status = BTA_JV_SUCCESS;
p_data->rfc_close.user_data = (void *)(uintptr_t)slot->id;
break; break;
case BTA_JV_RFCOMM_DATA_IND_EVT: case BTA_JV_RFCOMM_DATA_IND_EVT:
break; break;
@ -364,7 +381,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
if (slot) { if (slot) {
spp_free_slot(slot); spp_free_slot(slot);
} else { } 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; p_data->free_scn.status = ESP_SPP_NO_CONNECTION;
} }
osi_free(user_data); osi_free(user_data);
@ -401,7 +418,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); slot = spp_find_slot_by_id(id);
if (!slot) { if (!slot) {
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; break;
} }
if (p_data->scn == 0) { if (p_data->scn == 0) {
@ -421,7 +438,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); slot = spp_find_slot_by_id(id);
if (!slot) { if (!slot) {
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; break;
} }
if (p_data->create_rec.status == BTA_JV_SUCCESS) { if (p_data->create_rec.status == BTA_JV_SUCCESS) {
@ -510,14 +527,14 @@ static void btc_spp_uninit(void)
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
// first, remove all connection // first, remove all connection
for (size_t i = 1; i <= MAX_RFC_PORTS; 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]->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, 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); (void *)spp_local_param.spp_slots[i]->id);
} }
} }
// second, remove all server // second, remove all server
for (size_t i = 1; i <= MAX_RFC_PORTS; 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]->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) { if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle); BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
} }
@ -669,6 +686,10 @@ static void btc_spp_start_srv(btc_spp_args_t *arg)
ret = ESP_SPP_NO_RESOURCE; ret = ESP_SPP_NO_RESOURCE;
break; break;
} }
/**
* make this slot become a listening slot
*/
slot->is_server = true;
slot->security = arg->start_srv.sec_mask; slot->security = arg->start_srv.sec_mask;
slot->role = arg->start_srv.role; slot->role = arg->start_srv.role;
slot->scn = arg->start_srv.local_scn; slot->scn = arg->start_srv.local_scn;
@ -738,7 +759,7 @@ static void btc_spp_stop_srv(btc_spp_args_t *arg)
// [2] remove all local related connection // [2] remove all local related connection
for (j = 0; j < srv_cnt; j++) { for (j = 0; j < srv_cnt; j++) {
for (i = 1; i <= MAX_RFC_PORTS; i++) { 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]->sdp_handle > 0 &&
spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) { spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) {
BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle,
@ -751,7 +772,7 @@ static void btc_spp_stop_srv(btc_spp_args_t *arg)
// [3] remove all server // [3] remove all server
for (j = 0; j < srv_cnt; j++) { for (j = 0; j < srv_cnt; j++) {
for (i = 1; i <= MAX_RFC_PORTS; i++) { 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]->sdp_handle > 0 &&
spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) { spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) {
if (spp_local_param.spp_slots[i]->sdp_handle > 0) { if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
@ -933,7 +954,9 @@ void btc_spp_cb_handler(btc_msg_t *msg)
tBTA_JV *p_data = (tBTA_JV *)msg->arg; tBTA_JV *p_data = (tBTA_JV *)msg->arg;
spp_slot_t *slot = NULL; spp_slot_t *slot = NULL;
uint8_t serial = 0; uint8_t serial = 0;
switch (msg->act) { uint8_t event = msg->act;
switch (event) {
case BTA_JV_ENABLE_EVT: case BTA_JV_ENABLE_EVT:
param.init.status = p_data->status; param.init.status = p_data->status;
btc_spp_cb_to_app(ESP_SPP_INIT_EVT, &param); btc_spp_cb_to_app(ESP_SPP_INIT_EVT, &param);
@ -960,12 +983,14 @@ void btc_spp_cb_handler(btc_msg_t *msg)
slot = spp_find_slot_by_handle(p_data->rfc_open.handle); slot = spp_find_slot_by_handle(p_data->rfc_open.handle);
if (!slot) { if (!slot) {
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; param.open.status = ESP_SPP_NO_CONNECTION;
break; break;
} }
param.open.fd = slot->fd; param.open.fd = slot->fd;
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
} else {
param.open.fd = -1;
} }
param.open.status = p_data->rfc_open.status; param.open.status = p_data->rfc_open.status;
} while (0); } while (0);
@ -989,12 +1014,14 @@ void btc_spp_cb_handler(btc_msg_t *msg)
slot = spp_find_slot_by_handle(p_data->rfc_srv_open.handle); slot = spp_find_slot_by_handle(p_data->rfc_srv_open.handle);
if (!slot) { if (!slot) {
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; param.srv_open.status = ESP_SPP_NO_CONNECTION;
break; break;
} }
param.srv_open.fd = slot->fd; param.srv_open.fd = slot->fd;
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; param.srv_open.status = p_data->rfc_srv_open.status;
} while (0); } while (0);
@ -1065,10 +1092,11 @@ void btc_spp_cb_handler(btc_msg_t *msg)
if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) { if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) {
btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, &param); btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, &param);
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); 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) { if (!slot) {
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; break;
} }
spp_free_slot(slot); spp_free_slot(slot);
@ -1077,11 +1105,12 @@ void btc_spp_cb_handler(btc_msg_t *msg)
bool need_call = true; bool need_call = true;
do { do {
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); 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) { if (!slot) {
param.close.status = ESP_SPP_NO_CONNECTION; param.close.status = ESP_SPP_NO_CONNECTION;
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; break;
} }
// if rx still has data, delay free slot // if rx still has data, delay free slot
@ -1110,8 +1139,8 @@ void btc_spp_cb_handler(btc_msg_t *msg)
BTC_TRACE_ERROR("%s set slot close_alarm failed!", __func__); BTC_TRACE_ERROR("%s set slot close_alarm failed!", __func__);
break; break;
} }
BTC_TRACE_WARNING("%s slot rx data will be discard in %d seconds!", __func__, BTC_TRACE_WARNING("%s slot rx data will be discard in %d milliseconds!",
VFS_CLOSE_TIMEOUT / 1000); __func__, VFS_CLOSE_TIMEOUT);
slot->connected = false; slot->connected = false;
need_call = false; need_call = false;
} }
@ -1137,7 +1166,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
slot = spp_find_slot_by_handle(p_data->rfc_cong.handle); slot = spp_find_slot_by_handle(p_data->rfc_cong.handle);
if (!slot) { if (!slot) {
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; break;
} }
if (!p_data->rfc_cong.cong) { if (!p_data->rfc_cong.cong) {
@ -1159,7 +1188,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
slot = spp_find_slot_by_handle(p_data->data_ind.handle); slot = spp_find_slot_by_handle(p_data->data_ind.handle);
if (!slot) { if (!slot) {
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; break;
} }
serial = slot->serial; serial = slot->serial;
@ -1416,7 +1445,7 @@ static ssize_t spp_vfs_read(int fd, void * dst, size_t size)
slot = spp_find_slot_by_fd(fd); slot = spp_find_slot_by_fd(fd);
if (!slot) { if (!slot) {
osi_mutex_unlock(&spp_local_param.spp_slot_mutex); 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; errno = ENOENT;
return -1; return -1;
} }
@ -1441,6 +1470,14 @@ static ssize_t spp_vfs_read(int fd, void * dst, size_t size)
break; break;
} }
} else { } 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); osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
break; break;
} }

View File

@ -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_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 ** Define events that registered application can receive in the callback
*/ */
@ -219,7 +221,7 @@ extern "C"
extern int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, extern int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn,
BOOLEAN is_server, UINT16 mtu, BOOLEAN is_server, UINT16 mtu,
BD_ADDR bd_addr, UINT16 *p_handle, BD_ADDR bd_addr, UINT16 *p_handle,
tPORT_CALLBACK *p_mgmt_cb); tPORT_MGMT_CALLBACK *p_mgmt_cb);
/******************************************************************************* /*******************************************************************************

View File

@ -188,7 +188,7 @@ struct t_port_info {
UINT32 ev_mask; /* Event mask for the callback */ UINT32 ev_mask; /* Event mask for the callback */
tPORT_CALLBACK *p_callback; /* Pointer to users callback function */ 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_CALLBACK *p_data_callback; /* Callback function to receive data indications */
tPORT_DATA_CO_CALLBACK *p_data_co_callback; /* Callback function with callouts and flowctrl */ tPORT_DATA_CO_CALLBACK *p_data_co_callback; /* Callback function with callouts and flowctrl */
UINT16 credit_tx; /* Flow control credits for tx path */ UINT16 credit_tx; /* Flow control credits for tx path */

View File

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

View File

@ -175,7 +175,7 @@ void port_start_close (tPORT *p_port)
if ((p_mcb == NULL) || (p_port->rfc.state == RFC_STATE_CLOSED)) { if ((p_mcb == NULL) || (p_port->rfc.state == RFC_STATE_CLOSED)) {
/* Call management callback function before calling port_release_port() to clear tPort */ /* Call management callback function before calling port_release_port() to clear tPort */
if (p_port->p_mgmt_callback) { 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); port_release_port (p_port);
@ -230,7 +230,7 @@ void PORT_StartCnf (tRFC_MCB *p_mcb, UINT16 result)
} }
if (p_port->p_mgmt_callback) { 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); 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) void PORT_DlcEstablishInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
{ {
tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); 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:%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", 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 */ /* If there was an inactivity timer running for MCB stop it */
rfc_timer_stop (p_mcb); 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 */ /* This is the server side. If application wants to know when connection */
/* is established, thats the place */ /* 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) { 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) { 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; 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); p_port->p_callback (events, p_port->inx);
} }
if (p_port->p_mgmt_callback) { 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); p_port->p_mgmt_callback(res, p_port->inx, NULL);
} }
p_port->rfc.state = RFC_STATE_CLOSED; p_port->rfc.state = RFC_STATE_CLOSED;
RFCOMM_TRACE_WARNING ("%s RFCOMM connection in state %d closed: %s (res: %d)", RFCOMM_TRACE_WARNING("%s RFCOMM connection in server:%d state %d closed: %s (res: %d)",
__func__, p_port->state, PORT_GetResultString(res), res); __func__, p_port->is_server, p_port->state, PORT_GetResultString(res),
res);
port_release_port (p_port); port_release_port (p_port);
} }

View File

@ -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) 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) { switch (p_mcb->state) {
case RFC_MX_STATE_IDLE: case RFC_MX_STATE_IDLE:
rfc_mx_sm_state_idle (p_mcb, event, p_data); rfc_mx_sm_state_idle (p_mcb, event, p_data);

View File

@ -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) 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) { if (!p_port) {
RFCOMM_TRACE_WARNING ("NULL port event %d", event); RFCOMM_TRACE_WARNING ("NULL port event %d", event);
return; 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 (*((UINT8 *)p_data) != RFCOMM_SUCCESS) {
if (p_port->rfc.p_mcb) { if (p_port->rfc.p_mcb) {
rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, TRUE); 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 { } else {
rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci); rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);

View File

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

View File

@ -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/include/srvc_api.h
components/bt/host/bluedroid/btc/profile/std/smp/esp_app_sec.c 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/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/bluedroid_user_config.h
components/bt/host/bluedroid/common/include/common/bt_common_types.h components/bt/host/bluedroid/common/include/common/bt_common_types.h
components/bt/host/bluedroid/common/include/common/bt_defs.h components/bt/host/bluedroid/common/include/common/bt_defs.h