From fb93a59619a71aaf83e8f250b1148c2ffa71462e Mon Sep 17 00:00:00 2001 From: Yulong Date: Thu, 21 Sep 2017 06:17:38 -0400 Subject: [PATCH 01/13] component/bt: added the queue to store the gattc commands. --- components/bt/bluedroid/bta/gatt/bta_gattc_act.c | 5 +++++ components/bt/bluedroid/bta/gatt/bta_gattc_utils.c | 7 +++++-- components/bt/bluedroid/bta/include/bta_gattc_int.h | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 159baa0632..03338bf255 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -1451,6 +1451,11 @@ void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) bta_gattc_enqueue(p_clcb, p_data); } +void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) +{ + tBTA_GATTC_DATA *p_data = +} + /******************************************************************************* ** ** Function bta_gattc_fail diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index dfa685f67d..afb89cc34f 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -230,6 +230,7 @@ tBTA_GATTC_CLCB *bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bd bdcpy(p_clcb->bda, remote_bda); p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if); + p_clcb->p_cmd_list = list_new(osi_free_func); if ((p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL) { p_clcb->p_srcb = bta_gattc_srcb_alloc(remote_bda); @@ -437,10 +438,12 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { p_clcb->p_q_cmd = p_data; return TRUE; + } else if (p_clcb->p_cmd_list) { + //store the command to the command list. + list_append(p_clcb->p_cmd_list, (void *)p_data); + return FALSE; } - APPL_TRACE_ERROR ("%s: already has a pending command!!", __func__); - /* skip the callback now. ----- need to send callback ? */ return FALSE; } diff --git a/components/bt/bluedroid/bta/include/bta_gattc_int.h b/components/bt/bluedroid/bta/include/bta_gattc_int.h index 2515cb5225..f4af7fc8a3 100644 --- a/components/bt/bluedroid/bta/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/include/bta_gattc_int.h @@ -305,7 +305,7 @@ typedef struct { tBTA_GATTC_RCB *p_rcb; /* pointer to the registration CB */ tBTA_GATTC_SERV *p_srcb; /* server cache CB */ tBTA_GATTC_DATA *p_q_cmd; /* command in queue waiting for execution */ - + list_t *p_cmd_list; /* The list to store the command to be sent */ #define BTA_GATTC_NO_SCHEDULE 0 #define BTA_GATTC_DISC_WAITING 0x01 #define BTA_GATTC_REQ_WAITING 0x10 From 3d3bcd6275ca0f4c0075492a2663c3386a058e6a Mon Sep 17 00:00:00 2001 From: Yulong Date: Mon, 25 Sep 2017 02:27:08 -0400 Subject: [PATCH 02/13] component/bt: Added the gattc command queue support. --- .../bt/bluedroid/bta/gatt/bta_gattc_act.c | 116 +++++++++++++++--- .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 28 ++++- .../bt/bluedroid/bta/include/bta_gattc_int.h | 2 + 3 files changed, 123 insertions(+), 23 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 03338bf255..1e1e929bba 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -916,6 +916,10 @@ void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_CONFIG, status, NULL); @@ -1012,7 +1016,6 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) } if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_list) { /* release pending attribute list buffer */ - APPL_TRACE_DEBUG("+++++++++++++++++++++++++++++++++++++++++++++++++++++++= %p", p_clcb->p_srcb->p_srvc_list); osi_free(p_clcb->p_srcb->p_srvc_list); p_clcb->p_srcb->p_srvc_list = NULL; //osi_free_and_reset((void **)&p_clcb->p_srcb->p_srvc_list); @@ -1034,11 +1037,9 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) * referenced by p_clcb->p_q_cmd */ if (p_q_cmd != p_clcb->p_q_cmd) { - APPL_TRACE_DEBUG("===================================================================="); osi_free(p_q_cmd); p_q_cmd = NULL; } - //osi_free_and_reset((void **)&p_q_cmd); } } /******************************************************************************* @@ -1067,6 +1068,10 @@ void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL); @@ -1102,6 +1107,10 @@ void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL); @@ -1142,6 +1151,10 @@ void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_WRITE, status, NULL); @@ -1166,6 +1179,10 @@ void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_EXE_WRITE, status, NULL); @@ -1228,9 +1245,12 @@ void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) event = p_clcb->p_q_cmd->api_read.cmpl_evt; cb_data.read.conn_id = p_clcb->bta_conn_id; - osi_free(p_clcb->p_q_cmd); - p_clcb->p_q_cmd = NULL; - //osi_free_and_reset((void **)&p_clcb->p_q_cmd); + //free the command data store in the queue. + bta_gattc_free_command_data(p_clcb); + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); /* read complete, callback */ ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data); @@ -1261,9 +1281,12 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) } else { event = p_clcb->p_q_cmd->api_write.cmpl_evt; } - osi_free(p_clcb->p_q_cmd); - p_clcb->p_q_cmd = NULL; - //osi_free_and_reset((void **)&p_clcb->p_q_cmd); + //free the command data store in the queue. + bta_gattc_free_command_data(p_clcb); + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); cb_data.write.conn_id = p_clcb->bta_conn_id; /* write complete, callback */ ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data); @@ -1281,9 +1304,12 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) { tBTA_GATTC cb_data; - osi_free(p_clcb->p_q_cmd); - p_clcb->p_q_cmd = NULL; - //osi_free_and_reset((void **)&p_clcb->p_q_cmd); + //free the command data store in the queue. + bta_gattc_free_command_data(p_clcb); + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); p_clcb->status = BTA_GATT_OK; /* execute complete, callback */ @@ -1306,10 +1332,12 @@ void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) void bta_gattc_cfg_mtu_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) { tBTA_GATTC cb_data; - osi_free(p_clcb->p_q_cmd); - p_clcb->p_q_cmd = NULL; - //osi_free_and_reset((void **)&p_clcb->p_q_cmd); - + //free the command data store in the queue. + bta_gattc_free_command_data(p_clcb); + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); if (p_data->p_cmpl && p_data->status == BTA_GATT_OK) { p_clcb->p_srcb->mtu = p_data->p_cmpl->mtu; @@ -1450,10 +1478,62 @@ void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { bta_gattc_enqueue(p_clcb, p_data); } - +/******************************************************************************* +** +** Function bta_gattc_pop_command_to_send +** +** Description dequeue a command into control block. +** +** Returns None. +** +*******************************************************************************/ void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) { - tBTA_GATTC_DATA *p_data = + if (!list_is_empty(p_clcb->p_cmd_list)) { + list_node_t *node = list_begin(p_clcb->p_cmd_list); + tBTA_GATTC_DATA *p_data = (tBTA_GATTC_DATA *)list_node(node); + if (p_data != NULL) { + /* execute pending operation of link block still present */ + if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda, BT_TRANSPORT_LE) != NULL) { + // The data to be sent to the gattc state machine for processing + if(bta_gattc_sm_execute(p_clcb, p_data->hdr.event, p_data)) { + list_remove(p_clcb->p_cmd_list, (void *)p_data); + } + } + } + } +} +/******************************************************************************* +** +** Function bta_gattc_free_command_data +** +** Description free the command data into control block. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_free_command_data(tBTA_GATTC_CLCB *p_clcb) +{ + //Check the list is empty or not. + if (!list_is_empty(p_clcb->p_cmd_list)) { + /* Traversal the command queue, check the p_q_cmd is point to the queue data or not, if the p_q_cmd point to the + command queue,should remove it from the list */ + for (list_node_t *node = list_begin(p_clcb->p_cmd_list); node != list_end(p_clcb->p_cmd_list); + node = list_next(node)) { + tBTA_GATTC_DATA *p_data = (tBTA_GATTC_DATA *)list_node(node); + if (p_data == p_clcb->p_q_cmd) { + list_remove(p_clcb->p_cmd_list, (void *)p_data); + p_clcb->p_q_cmd = NULL; + return; + } + } + + osi_free(p_clcb->p_q_cmd); + p_clcb->p_q_cmd = NULL; + } else { + osi_free(p_clcb->p_q_cmd); + p_clcb->p_q_cmd = NULL; + } } /******************************************************************************* diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index afb89cc34f..425440ae5b 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -306,6 +306,8 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb) } osi_free(p_clcb->p_q_cmd); p_clcb->p_q_cmd = NULL; + // don't forget to clear the command queue before dealloc the clcb. + list_clear(p_clcb->p_cmd_list); //osi_free_and_reset((void **)&p_clcb->p_q_cmd); memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB)); } else { @@ -434,13 +436,29 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda) BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { - if (p_clcb->p_q_cmd == NULL) - { + if (p_clcb->p_q_cmd == NULL) { p_clcb->p_q_cmd = p_data; return TRUE; - } else if (p_clcb->p_cmd_list) { - //store the command to the command list. - list_append(p_clcb->p_cmd_list, (void *)p_data); + } else if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT && + p_data->api_write.write_type == BTA_GATTC_WRITE_PREPARE && + p_data->api_write.handle == p_clcb->p_q_cmd->api_write.handle) { + APPL_TRACE_ERROR("There is a prepare write command still pending."); + tBTA_GATTC cb_data = {0}; + cb_data.write.status = BTA_GATT_CONGESTED; + cb_data.write.handle = p_data->api_write.handle; + cb_data.write.conn_id = p_clcb->bta_conn_id; + /* write complete, callback */ + ( *p_clcb->p_rcb->p_cback)(p_data->hdr.event, (tBTA_GATTC *)&cb_data); + return FALSE; + } + else if (p_clcb->p_cmd_list) { + void *cmd_data = osi_malloc(sizeof(tBTA_GATTC_DATA)); + if (cmd_data) { + memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + //store the command to the command list. + list_append(p_clcb->p_cmd_list, cmd_data); + } return FALSE; } diff --git a/components/bt/bluedroid/bta/include/bta_gattc_int.h b/components/bt/bluedroid/bta/include/bta_gattc_int.h index f4af7fc8a3..9c04c55596 100644 --- a/components/bt/bluedroid/bta/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/include/bta_gattc_int.h @@ -420,6 +420,8 @@ extern void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); +extern void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb); +extern void bta_gattc_free_command_data(tBTA_GATTC_CLCB *p_clcb); extern void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); From e02ff1ed896d199eab1c2499655f7dc3bd398846 Mon Sep 17 00:00:00 2001 From: Yulong Date: Tue, 10 Oct 2017 03:12:00 -0400 Subject: [PATCH 03/13] component/bt: Change the bta_gattc_pop_command_to_send function to static. --- .../bt/bluedroid/bta/gatt/bta_gattc_act.c | 37 ++++--------------- .../bt/bluedroid/bta/include/bta_gattc_int.h | 1 - 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 1e1e929bba..2ee7bdb09d 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -59,6 +59,7 @@ static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS static void bta_gattc_cmpl_sendmsg(UINT16 conn_id, tGATTC_OPTYPE op, tBTA_GATT_STATUS status, tGATT_CL_COMPLETE *p_data); +static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb); static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg); static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda); @@ -916,10 +917,7 @@ void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ - bta_gattc_pop_command_to_send(p_clcb); + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_CONFIG, status, NULL); @@ -1068,9 +1066,6 @@ void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); } @@ -1107,10 +1102,7 @@ void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ - bta_gattc_pop_command_to_send(p_clcb); + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL); @@ -1151,9 +1143,6 @@ void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); } @@ -1179,9 +1168,6 @@ void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); } @@ -1247,9 +1233,6 @@ void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) cb_data.read.conn_id = p_clcb->bta_conn_id; //free the command data store in the queue. bta_gattc_free_command_data(p_clcb); - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); /* read complete, callback */ ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data); @@ -1283,9 +1266,6 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) } //free the command data store in the queue. bta_gattc_free_command_data(p_clcb); - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); cb_data.write.conn_id = p_clcb->bta_conn_id; /* write complete, callback */ @@ -1306,9 +1286,6 @@ void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) tBTA_GATTC cb_data; //free the command data store in the queue. bta_gattc_free_command_data(p_clcb); - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); p_clcb->status = BTA_GATT_OK; @@ -1334,9 +1311,6 @@ void bta_gattc_cfg_mtu_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) tBTA_GATTC cb_data; //free the command data store in the queue. bta_gattc_free_command_data(p_clcb); - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); if (p_data->p_cmpl && p_data->status == BTA_GATT_OK) { @@ -1483,11 +1457,14 @@ void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) ** Function bta_gattc_pop_command_to_send ** ** Description dequeue a command into control block. +** Check if there has command pending in the command queue or not, +** if there has command pending in the command queue, sent it to the state machine to decision +** should be sent it to the remote device or not. ** ** Returns None. ** *******************************************************************************/ -void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) +static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) { if (!list_is_empty(p_clcb->p_cmd_list)) { list_node_t *node = list_begin(p_clcb->p_cmd_list); diff --git a/components/bt/bluedroid/bta/include/bta_gattc_int.h b/components/bt/bluedroid/bta/include/bta_gattc_int.h index 9c04c55596..1d53f7d1b6 100644 --- a/components/bt/bluedroid/bta/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/include/bta_gattc_int.h @@ -420,7 +420,6 @@ extern void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); -extern void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb); extern void bta_gattc_free_command_data(tBTA_GATTC_CLCB *p_clcb); extern void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); From 8ca40818ebf9e036e55133dd6d6272fc2d7bdef7 Mon Sep 17 00:00:00 2001 From: Yulong Date: Wed, 8 Nov 2017 04:23:12 -0500 Subject: [PATCH 04/13] component/bt: Fix the write value not store in the queue command bug. --- .../bt/bluedroid/bta/gatt/bta_gattc_act.c | 4 +++ .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 25 ++++++++++++++++--- .../btc/profile/std/gatt/btc_gattc.c | 2 +- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 2ee7bdb09d..9a270d80fa 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -1472,6 +1472,9 @@ static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) if (p_data != NULL) { /* execute pending operation of link block still present */ if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda, BT_TRANSPORT_LE) != NULL) { + if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { + APPL_TRACE_ERROR("%s(), p_data = %d", __func__, p_data->api_write.p_value[0]); + } // The data to be sent to the gattc state machine for processing if(bta_gattc_sm_execute(p_clcb, p_data->hdr.event, p_data)) { list_remove(p_clcb->p_cmd_list, (void *)p_data); @@ -1491,6 +1494,7 @@ static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) *******************************************************************************/ void bta_gattc_free_command_data(tBTA_GATTC_CLCB *p_clcb) { + assert(p_clcb->p_cmd_list); //Check the list is empty or not. if (!list_is_empty(p_clcb->p_cmd_list)) { /* Traversal the command queue, check the p_q_cmd is point to the queue data or not, if the p_q_cmd point to the diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index 425440ae5b..75924882bc 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -48,6 +48,8 @@ static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x0 static const BD_ADDR dummy_bda = {0, 0, 0, 0, 0, 0}; +#define GATTC_COMMAND_QUEUE_SIZE_MAX 30 + /******************************************************************************* ** ** Function bta_gatt_convert_uuid16_to_uuid128 @@ -452,13 +454,28 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) return FALSE; } else if (p_clcb->p_cmd_list) { - void *cmd_data = osi_malloc(sizeof(tBTA_GATTC_DATA)); - if (cmd_data) { + UINT16 len = 0; + tBTA_GATTC_DATA *cmd_data = NULL; + if (list_length(p_clcb->p_cmd_list) >= GATTC_COMMAND_QUEUE_SIZE_MAX) { + //APPL_TRACE_ERROR("%s(), the gattc command queue is full." __func__); + return FALSE; + } + + if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { + len = p_data->api_write.len; + cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA) + len); + + cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); + } else { + cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA)); memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); - //store the command to the command list. - list_append(p_clcb->p_cmd_list, cmd_data); } + + //store the command to the command list. + list_append(p_clcb->p_cmd_list, (void *)cmd_data); return FALSE; } diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c index 37f17fcca2..0d9ce7cd05 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -251,7 +251,7 @@ static void btc_gattc_fill_gatt_db_conversion(uint16_t count, uint16_t num, esp_ } case ESP_GATT_DB_DESCRIPTOR: { esp_gattc_descr_elem_t *descr_result = (esp_gattc_descr_elem_t *)result; - for (int i = 0; i < (num - offset); i++) { + for (int i = 0; i < db_size; i++) { descr_result->handle = db[offset + i].attribute_handle; btc128_to_bta_uuid(&bta_uuid, db[offset + i].uuid.uu); bta_to_btc_uuid(&descr_result->uuid, &bta_uuid); From 1ceef122383f9b26a452be37ba6f60a1e974fa4f Mon Sep 17 00:00:00 2001 From: Yulong Date: Thu, 9 Nov 2017 01:44:16 -0500 Subject: [PATCH 05/13] compoent/bt: Modify bta_gattc_utils.c The value pointer copy is overwritten when a write event occurs. --- .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index 75924882bc..fd6d8d78bf 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -461,17 +461,23 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) return FALSE; } - if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { + if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { len = p_data->api_write.len; - cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA) + len); - - cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); - memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); - memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); - } else { - cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA)); - memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); - memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA) + len)) != NULL) { + memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA) + len); + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); + memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); + } else { + APPL_TRACE_ERROR("%s(), alloc fail, no memery.", __func__); + } + } else { + if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) { + memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + } else { + APPL_TRACE_ERROR("%s(), alloc fail, no memery.", __func__); + } } //store the command to the command list. From 7a27e3c74decfce5c54e606ddf7b5c73b16d05ea Mon Sep 17 00:00:00 2001 From: Yulong Date: Thu, 21 Sep 2017 06:17:38 -0400 Subject: [PATCH 06/13] component/bt: added the queue to store the gattc commands. --- components/bt/bluedroid/bta/gatt/bta_gattc_act.c | 5 +++++ components/bt/bluedroid/bta/gatt/bta_gattc_utils.c | 7 +++++-- components/bt/bluedroid/bta/include/bta_gattc_int.h | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 1a9306001c..8d504f6d7f 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -1457,6 +1457,11 @@ void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) bta_gattc_enqueue(p_clcb, p_data); } +void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) +{ + tBTA_GATTC_DATA *p_data = +} + /******************************************************************************* ** ** Function bta_gattc_fail diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index 864a85fe8e..196acf0495 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -230,6 +230,7 @@ tBTA_GATTC_CLCB *bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bd bdcpy(p_clcb->bda, remote_bda); p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if); + p_clcb->p_cmd_list = list_new(osi_free_func); if ((p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL) { p_clcb->p_srcb = bta_gattc_srcb_alloc(remote_bda); @@ -437,10 +438,12 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { p_clcb->p_q_cmd = p_data; return TRUE; + } else if (p_clcb->p_cmd_list) { + //store the command to the command list. + list_append(p_clcb->p_cmd_list, (void *)p_data); + return FALSE; } - APPL_TRACE_ERROR ("%s: already has a pending command!!", __func__); - /* skip the callback now. ----- need to send callback ? */ return FALSE; } diff --git a/components/bt/bluedroid/bta/include/bta_gattc_int.h b/components/bt/bluedroid/bta/include/bta_gattc_int.h index f54c0fbee7..9903a0a053 100644 --- a/components/bt/bluedroid/bta/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/include/bta_gattc_int.h @@ -310,7 +310,7 @@ typedef struct { tBTA_GATTC_RCB *p_rcb; /* pointer to the registration CB */ tBTA_GATTC_SERV *p_srcb; /* server cache CB */ tBTA_GATTC_DATA *p_q_cmd; /* command in queue waiting for execution */ - + list_t *p_cmd_list; /* The list to store the command to be sent */ #define BTA_GATTC_NO_SCHEDULE 0 #define BTA_GATTC_DISC_WAITING 0x01 #define BTA_GATTC_REQ_WAITING 0x10 From 0ae5320f5007f2c24b526a8f9e0305ce5b8cf1a1 Mon Sep 17 00:00:00 2001 From: Yulong Date: Mon, 25 Sep 2017 02:27:08 -0400 Subject: [PATCH 07/13] component/bt: Added the gattc command queue support. --- .../bt/bluedroid/bta/gatt/bta_gattc_act.c | 116 +++++++++++++++--- .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 28 ++++- .../bt/bluedroid/bta/include/bta_gattc_int.h | 2 + 3 files changed, 123 insertions(+), 23 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 8d504f6d7f..7093723e8b 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -916,6 +916,10 @@ void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_CONFIG, status, NULL); @@ -1012,7 +1016,6 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) } if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_list) { /* release pending attribute list buffer */ - APPL_TRACE_DEBUG("+++++++++++++++++++++++++++++++++++++++++++++++++++++++= %p", p_clcb->p_srcb->p_srvc_list); osi_free(p_clcb->p_srcb->p_srvc_list); p_clcb->p_srcb->p_srvc_list = NULL; //osi_free_and_reset((void **)&p_clcb->p_srcb->p_srvc_list); @@ -1034,11 +1037,9 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) * referenced by p_clcb->p_q_cmd */ if (p_q_cmd != p_clcb->p_q_cmd) { - APPL_TRACE_DEBUG("===================================================================="); osi_free(p_q_cmd); p_q_cmd = NULL; } - //osi_free_and_reset((void **)&p_q_cmd); } } /******************************************************************************* @@ -1067,6 +1068,10 @@ void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL); @@ -1102,6 +1107,10 @@ void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL); @@ -1142,6 +1151,10 @@ void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_WRITE, status, NULL); @@ -1166,6 +1179,10 @@ void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_EXE_WRITE, status, NULL); @@ -1232,9 +1249,12 @@ void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) event = p_clcb->p_q_cmd->api_read_multi.cmpl_evt; } cb_data.read.conn_id = p_clcb->bta_conn_id; - osi_free(p_clcb->p_q_cmd); - p_clcb->p_q_cmd = NULL; - //osi_free_and_reset((void **)&p_clcb->p_q_cmd); + //free the command data store in the queue. + bta_gattc_free_command_data(p_clcb); + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); /* read complete, callback */ ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data); @@ -1265,9 +1285,12 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) } else { event = p_clcb->p_q_cmd->api_write.cmpl_evt; } - osi_free(p_clcb->p_q_cmd); - p_clcb->p_q_cmd = NULL; - //osi_free_and_reset((void **)&p_clcb->p_q_cmd); + //free the command data store in the queue. + bta_gattc_free_command_data(p_clcb); + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); cb_data.write.conn_id = p_clcb->bta_conn_id; /* write complete, callback */ ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data); @@ -1285,9 +1308,12 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) { tBTA_GATTC cb_data; - osi_free(p_clcb->p_q_cmd); - p_clcb->p_q_cmd = NULL; - //osi_free_and_reset((void **)&p_clcb->p_q_cmd); + //free the command data store in the queue. + bta_gattc_free_command_data(p_clcb); + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); p_clcb->status = BTA_GATT_OK; /* execute complete, callback */ @@ -1310,10 +1336,12 @@ void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) void bta_gattc_cfg_mtu_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) { tBTA_GATTC cb_data; - osi_free(p_clcb->p_q_cmd); - p_clcb->p_q_cmd = NULL; - //osi_free_and_reset((void **)&p_clcb->p_q_cmd); - + //free the command data store in the queue. + bta_gattc_free_command_data(p_clcb); + /* Check if there has command pending in the command queue or not, + if there has command pending in the command queue, sent it to the state machine to decision + should be sent it to the remote device or not. */ + bta_gattc_pop_command_to_send(p_clcb); if (p_data->p_cmpl && p_data->status == BTA_GATT_OK) { p_clcb->p_srcb->mtu = p_data->p_cmpl->mtu; @@ -1456,10 +1484,62 @@ void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { bta_gattc_enqueue(p_clcb, p_data); } - +/******************************************************************************* +** +** Function bta_gattc_pop_command_to_send +** +** Description dequeue a command into control block. +** +** Returns None. +** +*******************************************************************************/ void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) { - tBTA_GATTC_DATA *p_data = + if (!list_is_empty(p_clcb->p_cmd_list)) { + list_node_t *node = list_begin(p_clcb->p_cmd_list); + tBTA_GATTC_DATA *p_data = (tBTA_GATTC_DATA *)list_node(node); + if (p_data != NULL) { + /* execute pending operation of link block still present */ + if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda, BT_TRANSPORT_LE) != NULL) { + // The data to be sent to the gattc state machine for processing + if(bta_gattc_sm_execute(p_clcb, p_data->hdr.event, p_data)) { + list_remove(p_clcb->p_cmd_list, (void *)p_data); + } + } + } + } +} +/******************************************************************************* +** +** Function bta_gattc_free_command_data +** +** Description free the command data into control block. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_free_command_data(tBTA_GATTC_CLCB *p_clcb) +{ + //Check the list is empty or not. + if (!list_is_empty(p_clcb->p_cmd_list)) { + /* Traversal the command queue, check the p_q_cmd is point to the queue data or not, if the p_q_cmd point to the + command queue,should remove it from the list */ + for (list_node_t *node = list_begin(p_clcb->p_cmd_list); node != list_end(p_clcb->p_cmd_list); + node = list_next(node)) { + tBTA_GATTC_DATA *p_data = (tBTA_GATTC_DATA *)list_node(node); + if (p_data == p_clcb->p_q_cmd) { + list_remove(p_clcb->p_cmd_list, (void *)p_data); + p_clcb->p_q_cmd = NULL; + return; + } + } + + osi_free(p_clcb->p_q_cmd); + p_clcb->p_q_cmd = NULL; + } else { + osi_free(p_clcb->p_q_cmd); + p_clcb->p_q_cmd = NULL; + } } /******************************************************************************* diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index 196acf0495..a91d523293 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -306,6 +306,8 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb) } osi_free(p_clcb->p_q_cmd); p_clcb->p_q_cmd = NULL; + // don't forget to clear the command queue before dealloc the clcb. + list_clear(p_clcb->p_cmd_list); //osi_free_and_reset((void **)&p_clcb->p_q_cmd); memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB)); } else { @@ -434,13 +436,29 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda) BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { - if (p_clcb->p_q_cmd == NULL) - { + if (p_clcb->p_q_cmd == NULL) { p_clcb->p_q_cmd = p_data; return TRUE; - } else if (p_clcb->p_cmd_list) { - //store the command to the command list. - list_append(p_clcb->p_cmd_list, (void *)p_data); + } else if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT && + p_data->api_write.write_type == BTA_GATTC_WRITE_PREPARE && + p_data->api_write.handle == p_clcb->p_q_cmd->api_write.handle) { + APPL_TRACE_ERROR("There is a prepare write command still pending."); + tBTA_GATTC cb_data = {0}; + cb_data.write.status = BTA_GATT_CONGESTED; + cb_data.write.handle = p_data->api_write.handle; + cb_data.write.conn_id = p_clcb->bta_conn_id; + /* write complete, callback */ + ( *p_clcb->p_rcb->p_cback)(p_data->hdr.event, (tBTA_GATTC *)&cb_data); + return FALSE; + } + else if (p_clcb->p_cmd_list) { + void *cmd_data = osi_malloc(sizeof(tBTA_GATTC_DATA)); + if (cmd_data) { + memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + //store the command to the command list. + list_append(p_clcb->p_cmd_list, cmd_data); + } return FALSE; } diff --git a/components/bt/bluedroid/bta/include/bta_gattc_int.h b/components/bt/bluedroid/bta/include/bta_gattc_int.h index 9903a0a053..48da7e1168 100644 --- a/components/bt/bluedroid/bta/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/include/bta_gattc_int.h @@ -425,6 +425,8 @@ extern void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); +extern void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb); +extern void bta_gattc_free_command_data(tBTA_GATTC_CLCB *p_clcb); extern void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); From 68833fe94ca91e3579f3ab98ac9a2ccfaff4b2d4 Mon Sep 17 00:00:00 2001 From: Yulong Date: Tue, 10 Oct 2017 03:12:00 -0400 Subject: [PATCH 08/13] component/bt: Change the bta_gattc_pop_command_to_send function to static. --- .../bt/bluedroid/bta/gatt/bta_gattc_act.c | 37 ++++--------------- .../bt/bluedroid/bta/include/bta_gattc_int.h | 1 - 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 7093723e8b..d7a13bd3f8 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -59,6 +59,7 @@ static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS static void bta_gattc_cmpl_sendmsg(UINT16 conn_id, tGATTC_OPTYPE op, tBTA_GATT_STATUS status, tGATT_CL_COMPLETE *p_data); +static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb); static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg); static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda); @@ -916,10 +917,7 @@ void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ - bta_gattc_pop_command_to_send(p_clcb); + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_CONFIG, status, NULL); @@ -1068,9 +1066,6 @@ void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); } @@ -1107,10 +1102,7 @@ void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ - bta_gattc_pop_command_to_send(p_clcb); + bta_gattc_pop_command_to_send(p_clcb); } bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL); @@ -1151,9 +1143,6 @@ void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); } @@ -1179,9 +1168,6 @@ void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* Dequeue the data, if it was enqueued */ if (p_clcb->p_q_cmd == p_data) { p_clcb->p_q_cmd = NULL; - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); } @@ -1251,9 +1237,6 @@ void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) cb_data.read.conn_id = p_clcb->bta_conn_id; //free the command data store in the queue. bta_gattc_free_command_data(p_clcb); - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); /* read complete, callback */ ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data); @@ -1287,9 +1270,6 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) } //free the command data store in the queue. bta_gattc_free_command_data(p_clcb); - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); cb_data.write.conn_id = p_clcb->bta_conn_id; /* write complete, callback */ @@ -1310,9 +1290,6 @@ void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) tBTA_GATTC cb_data; //free the command data store in the queue. bta_gattc_free_command_data(p_clcb); - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); p_clcb->status = BTA_GATT_OK; @@ -1338,9 +1315,6 @@ void bta_gattc_cfg_mtu_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) tBTA_GATTC cb_data; //free the command data store in the queue. bta_gattc_free_command_data(p_clcb); - /* Check if there has command pending in the command queue or not, - if there has command pending in the command queue, sent it to the state machine to decision - should be sent it to the remote device or not. */ bta_gattc_pop_command_to_send(p_clcb); if (p_data->p_cmpl && p_data->status == BTA_GATT_OK) { @@ -1489,11 +1463,14 @@ void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) ** Function bta_gattc_pop_command_to_send ** ** Description dequeue a command into control block. +** Check if there has command pending in the command queue or not, +** if there has command pending in the command queue, sent it to the state machine to decision +** should be sent it to the remote device or not. ** ** Returns None. ** *******************************************************************************/ -void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) +static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) { if (!list_is_empty(p_clcb->p_cmd_list)) { list_node_t *node = list_begin(p_clcb->p_cmd_list); diff --git a/components/bt/bluedroid/bta/include/bta_gattc_int.h b/components/bt/bluedroid/bta/include/bta_gattc_int.h index 48da7e1168..8bb233fcc4 100644 --- a/components/bt/bluedroid/bta/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/include/bta_gattc_int.h @@ -425,7 +425,6 @@ extern void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); -extern void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb); extern void bta_gattc_free_command_data(tBTA_GATTC_CLCB *p_clcb); extern void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); extern void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); From e6b2c19eea422800fd6c2261fbe2348dad0e3e85 Mon Sep 17 00:00:00 2001 From: Yulong Date: Wed, 8 Nov 2017 04:23:12 -0500 Subject: [PATCH 09/13] component/bt: Fix the write value not store in the queue command bug. --- .../bt/bluedroid/bta/gatt/bta_gattc_act.c | 4 +++ .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 25 ++++++++++++++++--- .../btc/profile/std/gatt/btc_gattc.c | 2 +- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index d7a13bd3f8..c5a2990d9d 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -1478,6 +1478,9 @@ static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) if (p_data != NULL) { /* execute pending operation of link block still present */ if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda, BT_TRANSPORT_LE) != NULL) { + if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { + APPL_TRACE_ERROR("%s(), p_data = %d", __func__, p_data->api_write.p_value[0]); + } // The data to be sent to the gattc state machine for processing if(bta_gattc_sm_execute(p_clcb, p_data->hdr.event, p_data)) { list_remove(p_clcb->p_cmd_list, (void *)p_data); @@ -1497,6 +1500,7 @@ static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) *******************************************************************************/ void bta_gattc_free_command_data(tBTA_GATTC_CLCB *p_clcb) { + assert(p_clcb->p_cmd_list); //Check the list is empty or not. if (!list_is_empty(p_clcb->p_cmd_list)) { /* Traversal the command queue, check the p_q_cmd is point to the queue data or not, if the p_q_cmd point to the diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index a91d523293..a4b8523f59 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -48,6 +48,8 @@ static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x0 static const BD_ADDR dummy_bda = {0, 0, 0, 0, 0, 0}; +#define GATTC_COMMAND_QUEUE_SIZE_MAX 30 + /******************************************************************************* ** ** Function bta_gatt_convert_uuid16_to_uuid128 @@ -452,13 +454,28 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) return FALSE; } else if (p_clcb->p_cmd_list) { - void *cmd_data = osi_malloc(sizeof(tBTA_GATTC_DATA)); - if (cmd_data) { + UINT16 len = 0; + tBTA_GATTC_DATA *cmd_data = NULL; + if (list_length(p_clcb->p_cmd_list) >= GATTC_COMMAND_QUEUE_SIZE_MAX) { + //APPL_TRACE_ERROR("%s(), the gattc command queue is full." __func__); + return FALSE; + } + + if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { + len = p_data->api_write.len; + cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA) + len); + + cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); + } else { + cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA)); memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); - //store the command to the command list. - list_append(p_clcb->p_cmd_list, cmd_data); } + + //store the command to the command list. + list_append(p_clcb->p_cmd_list, (void *)cmd_data); return FALSE; } diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c index 5b33f0f77c..c13b9ff0e2 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -253,7 +253,7 @@ static void btc_gattc_fill_gatt_db_conversion(uint16_t count, uint16_t num, esp_ } case ESP_GATT_DB_DESCRIPTOR: { esp_gattc_descr_elem_t *descr_result = (esp_gattc_descr_elem_t *)result; - for (int i = 0; i < (num - offset); i++) { + for (int i = 0; i < db_size; i++) { descr_result->handle = db[offset + i].attribute_handle; btc128_to_bta_uuid(&bta_uuid, db[offset + i].uuid.uu); bta_to_btc_uuid(&descr_result->uuid, &bta_uuid); From ee43527108c38868b1fe797b175a192c2b6a2eb4 Mon Sep 17 00:00:00 2001 From: Yulong Date: Thu, 9 Nov 2017 01:44:16 -0500 Subject: [PATCH 10/13] compoent/bt: Modify bta_gattc_utils.c The value pointer copy is overwritten when a write event occurs. --- .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index a4b8523f59..4b1127b148 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -461,17 +461,23 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) return FALSE; } - if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { + if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { len = p_data->api_write.len; - cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA) + len); - - cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); - memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); - memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); - } else { - cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA)); - memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); - memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA) + len)) != NULL) { + memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA) + len); + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); + memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); + } else { + APPL_TRACE_ERROR("%s(), alloc fail, no memery.", __func__); + } + } else { + if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) { + memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + } else { + APPL_TRACE_ERROR("%s(), alloc fail, no memery.", __func__); + } } //store the command to the command list. From 8352eb6fa28cf67eac41fc2e03fc6738b2089005 Mon Sep 17 00:00:00 2001 From: Yulong Date: Mon, 13 Nov 2017 02:12:33 -0500 Subject: [PATCH 11/13] component/bt: Added the prepare write check. --- .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index fd6d8d78bf..e589729c0a 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -426,6 +426,25 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda) } return p_tcb; } + +static void bta_gattc_remove_prepare_write_in_queue(tBTA_GATTC_CLCB *p_clcb) +{ + assert(p_clcb != NULL); + + for(list_node_t *sn = list_begin(p_clcb->p_cmd_list); + sn != list_end(p_clcb->p_cmd_list); sn = list_next(sn)) { + + tBTA_GATTC_DATA *cmd_data = (tBTA_GATTC_DATA *)list_node(sn); + if (cmd_data != NULL && ((cmd_data->hdr.event == BTA_GATTC_API_WRITE_EVT && + cmd_data->api_write.write_type == BTA_GATTC_WRITE_PREPARE) || + cmd_data->hdr.event == BTA_GATTC_API_EXEC_EVT)) { + // remove the prepare write command in the command queue + list_remove(p_clcb->p_cmd_list, (void *)cmd_data); + } + } + + return; +} /******************************************************************************* ** ** Function bta_gattc_enqueue @@ -444,7 +463,7 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) } else if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT && p_data->api_write.write_type == BTA_GATTC_WRITE_PREPARE && p_data->api_write.handle == p_clcb->p_q_cmd->api_write.handle) { - APPL_TRACE_ERROR("There is a prepare write command still pending."); + bta_gattc_remove_prepare_write_in_queue (p_clcb); tBTA_GATTC cb_data = {0}; cb_data.write.status = BTA_GATT_CONGESTED; cb_data.write.handle = p_data->api_write.handle; @@ -454,12 +473,12 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) return FALSE; } else if (p_clcb->p_cmd_list) { - UINT16 len = 0; - tBTA_GATTC_DATA *cmd_data = NULL; - if (list_length(p_clcb->p_cmd_list) >= GATTC_COMMAND_QUEUE_SIZE_MAX) { - //APPL_TRACE_ERROR("%s(), the gattc command queue is full." __func__); - return FALSE; - } + UINT16 len = 0; + tBTA_GATTC_DATA *cmd_data = NULL; + if (list_length(p_clcb->p_cmd_list) >= GATTC_COMMAND_QUEUE_SIZE_MAX) { + APPL_TRACE_ERROR("%s(), the gattc command queue is full.", __func__); + return FALSE; + } if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { len = p_data->api_write.len; @@ -469,14 +488,16 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); } else { - APPL_TRACE_ERROR("%s(), alloc fail, no memery.", __func__); + APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memery.", __func__, __LINE__); + return FALSE; } } else { if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) { memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); } else { - APPL_TRACE_ERROR("%s(), alloc fail, no memery.", __func__); + APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memery.", __func__, __LINE__); + return FALSE; } } From 1d13b58c62269cee8376402874f1cee2935ca11a Mon Sep 17 00:00:00 2001 From: Yulong Date: Mon, 13 Nov 2017 22:44:27 -0500 Subject: [PATCH 12/13] component/bt: Added the queue event when the gattc command is full. --- .../bt/bluedroid/api/include/esp_gattc_api.h | 10 +++++++ .../bt/bluedroid/bta/gatt/bta_gattc_act.c | 14 +++++++--- .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 26 +++++++++++++------ .../bt/bluedroid/bta/include/bta_gatt_api.h | 8 ++++++ .../bt/bluedroid/bta/include/bta_gattc_int.h | 1 + .../btc/profile/std/gatt/btc_gattc.c | 9 +++++++ 6 files changed, 57 insertions(+), 11 deletions(-) diff --git a/components/bt/bluedroid/api/include/esp_gattc_api.h b/components/bt/bluedroid/api/include/esp_gattc_api.h index 6a6aa579cf..1bf9d3b9f4 100644 --- a/components/bt/bluedroid/api/include/esp_gattc_api.h +++ b/components/bt/bluedroid/api/include/esp_gattc_api.h @@ -64,6 +64,7 @@ typedef enum { ESP_GATTC_CONNECT_EVT = 40, /*!< When the ble physical connection is set up, the event comes */ ESP_GATTC_DISCONNECT_EVT = 41, /*!< When the ble physical connection disconnected, the event comes */ ESP_GATTC_READ_MUTIPLE_EVT = 42, /*!< When the ble characteristic or descriptor mutiple complete, the event comes */ + ESP_GATTC_QUEUE_FULL_EVT = 43, /*!< When the gattc command queue full, the event comes */ } esp_gattc_cb_event_t; @@ -214,6 +215,15 @@ typedef union { esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ } disconnect; /*!< Gatt client callback param of ESP_GATTC_DISCONNECT_EVT */ + /** + * @brief ESP_GATTC_QUEUE_FULL_EVT + */ + struct gattc_queue_full_evt_param { + esp_gatt_status_t status; /*!< Operation status */ + uint16_t conn_id; /*!< Connection id */ + bool is_full; /*!< The gattc command queue is full or not */ + } queue_full; /*!< Gatt client callback param of ESP_GATTC_QUEUE_FULL_EVT */ + } esp_ble_gattc_cb_param_t; /*!< GATT client callback parameter union type */ /** diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index c5a2990d9d..e93f451a03 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -1478,13 +1478,21 @@ static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb) if (p_data != NULL) { /* execute pending operation of link block still present */ if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda, BT_TRANSPORT_LE) != NULL) { - if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) { - APPL_TRACE_ERROR("%s(), p_data = %d", __func__, p_data->api_write.p_value[0]); - } // The data to be sent to the gattc state machine for processing if(bta_gattc_sm_execute(p_clcb, p_data->hdr.event, p_data)) { list_remove(p_clcb->p_cmd_list, (void *)p_data); } + + if (p_clcb->is_full) { + tBTA_GATTC cb_data = {0}; + p_clcb->is_full = FALSE; + cb_data.status = GATT_SUCCESS; + cb_data.queue_full.conn_id = p_clcb->bta_conn_id; + cb_data.queue_full.is_full = FALSE; + if (p_clcb->p_rcb->p_cback != NULL) { + ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_QUEUE_FULL_EVT, (tBTA_GATTC *)&cb_data); + } + } } } } diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index c5423a1a82..620d08e830 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -427,7 +427,7 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda) return p_tcb; } -static void bta_gattc_remove_prepare_write_in_queue(tBTA_GATTC_CLCB *p_clcb) +static BOOLEAN bta_gattc_has_prepare_command_in_queue(tBTA_GATTC_CLCB *p_clcb) { assert(p_clcb != NULL); @@ -438,12 +438,11 @@ static void bta_gattc_remove_prepare_write_in_queue(tBTA_GATTC_CLCB *p_clcb) if (cmd_data != NULL && ((cmd_data->hdr.event == BTA_GATTC_API_WRITE_EVT && cmd_data->api_write.write_type == BTA_GATTC_WRITE_PREPARE) || cmd_data->hdr.event == BTA_GATTC_API_EXEC_EVT)) { - // remove the prepare write command in the command queue - list_remove(p_clcb->p_cmd_list, (void *)cmd_data); + return TRUE; } } - return; + return FALSE; } /******************************************************************************* ** @@ -456,27 +455,38 @@ static void bta_gattc_remove_prepare_write_in_queue(tBTA_GATTC_CLCB *p_clcb) *******************************************************************************/ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { + tBTA_GATTC cb_data = {0}; if (p_clcb->p_q_cmd == NULL) { p_clcb->p_q_cmd = p_data; return TRUE; } else if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT && p_data->api_write.write_type == BTA_GATTC_WRITE_PREPARE && - p_data->api_write.handle == p_clcb->p_q_cmd->api_write.handle) { - bta_gattc_remove_prepare_write_in_queue (p_clcb); - tBTA_GATTC cb_data = {0}; + p_data->api_write.handle == p_clcb->p_q_cmd->api_write.handle && + bta_gattc_has_prepare_command_in_queue(p_clcb)) { cb_data.write.status = BTA_GATT_CONGESTED; cb_data.write.handle = p_data->api_write.handle; cb_data.write.conn_id = p_clcb->bta_conn_id; /* write complete, callback */ - ( *p_clcb->p_rcb->p_cback)(p_data->hdr.event, (tBTA_GATTC *)&cb_data); + if (p_clcb->p_rcb->p_cback != NULL) { + ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_PREP_WRITE_EVT, (tBTA_GATTC *)&cb_data); + } return FALSE; } else if (p_clcb->p_cmd_list) { UINT16 len = 0; tBTA_GATTC_DATA *cmd_data = NULL; + if (list_length(p_clcb->p_cmd_list) >= GATTC_COMMAND_QUEUE_SIZE_MAX) { + APPL_TRACE_ERROR("%s(), the gattc command queue is full.", __func__); + cb_data.status = GATT_BUSY; + cb_data.queue_full.conn_id = p_clcb->bta_conn_id; + cb_data.queue_full.is_full = TRUE; + p_clcb->is_full = TRUE; + if (p_clcb->p_rcb->p_cback != NULL) { + ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_QUEUE_FULL_EVT, (tBTA_GATTC *)&cb_data); + } return FALSE; } diff --git a/components/bt/bluedroid/bta/include/bta_gatt_api.h b/components/bt/bluedroid/bta/include/bta_gatt_api.h index 4d5b975e10..b7dfa855a6 100644 --- a/components/bt/bluedroid/bta/include/bta_gatt_api.h +++ b/components/bt/bluedroid/bta/include/bta_gatt_api.h @@ -182,6 +182,7 @@ typedef UINT8 tBTA_GATT_STATUS; #define BTA_GATTC_CONNECT_EVT 35 /* GATTC CONNECT event */ #define BTA_GATTC_DISCONNECT_EVT 36 /* GATTC DISCONNECT event */ #define BTA_GATTC_READ_MUTIPLE_EVT 37 /* GATTC Read mutiple event */ +#define BTA_GATTC_QUEUE_FULL_EVT 38 /* GATTC queue full event */ typedef UINT8 tBTA_GATTC_EVT; @@ -354,6 +355,12 @@ typedef struct { BOOLEAN congested; /* congestion indicator */ } tBTA_GATTC_CONGEST; +typedef struct { + tBTA_GATT_STATUS status; + UINT16 conn_id; + BOOLEAN is_full; +} tBTA_GATTC_QUEUE_FULL; + typedef struct { tBTA_GATT_STATUS status; tBTA_GATTC_IF client_if; @@ -399,6 +406,7 @@ typedef union { BD_ADDR remote_bda; /* service change event */ tBTA_GATTC_CFG_MTU cfg_mtu; /* configure MTU operation */ tBTA_GATTC_CONGEST congest; + tBTA_GATTC_QUEUE_FULL queue_full; } tBTA_GATTC; /* GATTC enable callback function */ diff --git a/components/bt/bluedroid/bta/include/bta_gattc_int.h b/components/bt/bluedroid/bta/include/bta_gattc_int.h index 8bb233fcc4..59810b223c 100644 --- a/components/bt/bluedroid/bta/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/include/bta_gattc_int.h @@ -311,6 +311,7 @@ typedef struct { tBTA_GATTC_SERV *p_srcb; /* server cache CB */ tBTA_GATTC_DATA *p_q_cmd; /* command in queue waiting for execution */ list_t *p_cmd_list; /* The list to store the command to be sent */ + BOOLEAN is_full; /* The gattc command queue is full or not */ #define BTA_GATTC_NO_SCHEDULE 0 #define BTA_GATTC_DISC_WAITING 0x01 #define BTA_GATTC_REQ_WAITING 0x10 diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c index c13b9ff0e2..a1a1c88541 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -917,6 +917,15 @@ void btc_gattc_cb_handler(btc_msg_t *msg) btc_gattc_cb_to_app(ESP_GATTC_SRVC_CHG_EVT, ESP_GATT_IF_NONE, ¶m); break; } + case BTA_GATTC_QUEUE_FULL_EVT: { + tBTA_GATTC_QUEUE_FULL *queue_full = &arg->queue_full; + gattc_if = BTC_GATT_GET_GATT_IF(queue_full->conn_id); + param.queue_full.conn_id = BTC_GATT_GET_CONN_ID(queue_full->conn_id); + param.queue_full.status = arg->status; + param.queue_full.is_full = queue_full->is_full; + btc_gattc_cb_to_app(ESP_GATTC_QUEUE_FULL_EVT, gattc_if, ¶m); + break; + } default: LOG_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act); break; From b07a5f03cfc13b6c3b9a4376736bc88869f64ae8 Mon Sep 17 00:00:00 2001 From: Yulong Date: Tue, 14 Nov 2017 07:00:45 -0500 Subject: [PATCH 13/13] component/bt: Change the gattc prepare write callback params. --- components/bt/bluedroid/api/include/esp_gattc_api.h | 1 + components/bt/bluedroid/bta/gatt/bta_gattc_utils.c | 11 +++++++---- components/bt/bluedroid/bta/include/bta_gatt_api.h | 1 + .../bt/bluedroid/btc/profile/std/gatt/btc_gattc.c | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/components/bt/bluedroid/api/include/esp_gattc_api.h b/components/bt/bluedroid/api/include/esp_gattc_api.h index 1bf9d3b9f4..adf3dbda37 100644 --- a/components/bt/bluedroid/api/include/esp_gattc_api.h +++ b/components/bt/bluedroid/api/include/esp_gattc_api.h @@ -146,6 +146,7 @@ typedef union { esp_gatt_status_t status; /*!< Operation status */ uint16_t conn_id; /*!< Connection id */ uint16_t handle; /*!< The Characteristic or descriptor handle */ + uint16_t offset; /*!< The prepare write offset, this value is valid only when prepare write */ } write; /*!< Gatt client callback param of ESP_GATTC_WRITE_DESCR_EVT */ /** diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index 620d08e830..b5409b40b3 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -460,13 +460,16 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) if (p_clcb->p_q_cmd == NULL) { p_clcb->p_q_cmd = p_data; return TRUE; - } else if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT && - p_data->api_write.write_type == BTA_GATTC_WRITE_PREPARE && - p_data->api_write.handle == p_clcb->p_q_cmd->api_write.handle && - bta_gattc_has_prepare_command_in_queue(p_clcb)) { + } else if ((p_data->hdr.event == BTA_GATTC_API_WRITE_EVT && + p_data->api_write.write_type == BTA_GATTC_WRITE_PREPARE) && + ((p_clcb->p_q_cmd->hdr.event == BTA_GATTC_API_WRITE_EVT && + p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE) || + bta_gattc_has_prepare_command_in_queue(p_clcb))) { + APPL_TRACE_DEBUG("%s(), prepare offset = %d", __func__, p_data->api_write.offset); cb_data.write.status = BTA_GATT_CONGESTED; cb_data.write.handle = p_data->api_write.handle; cb_data.write.conn_id = p_clcb->bta_conn_id; + cb_data.write.offset = p_data->api_write.offset; /* write complete, callback */ if (p_clcb->p_rcb->p_cback != NULL) { ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_PREP_WRITE_EVT, (tBTA_GATTC *)&cb_data); diff --git a/components/bt/bluedroid/bta/include/bta_gatt_api.h b/components/bt/bluedroid/bta/include/bta_gatt_api.h index b7dfa855a6..95f6815216 100644 --- a/components/bt/bluedroid/bta/include/bta_gatt_api.h +++ b/components/bt/bluedroid/bta/include/bta_gatt_api.h @@ -299,6 +299,7 @@ typedef struct { UINT16 conn_id; tBTA_GATT_STATUS status; UINT16 handle; + UINT16 offset; }tBTA_GATTC_WRITE; typedef struct { diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c index a1a1c88541..a49f3ed1b7 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -770,6 +770,7 @@ void btc_gattc_cb_handler(btc_msg_t *msg) param.write.conn_id = BTC_GATT_GET_CONN_ID(write->conn_id); param.write.status = write->status; param.write.handle = write->handle; + param.write.offset = write->offset; btc_gattc_cb_to_app(ret_evt, gattc_if, ¶m); break; }