/* 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);
}
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);
* 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);
}
}
/*******************************************************************************
/* 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);
/* 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);
/* 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);
/* 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);
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);
} 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);
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 */
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;
{
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;
+ }
}
/*******************************************************************************
}
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 {
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;
}