]> granicus.if.org Git - esp-idf/commitdiff
component/bt: Added the gattc command queue support.
authorYulong <huangyulong@espressif.com>
Mon, 25 Sep 2017 06:27:08 +0000 (02:27 -0400)
committeryulong <huangyulong@espressif.com>
Thu, 9 Nov 2017 06:47:11 +0000 (14:47 +0800)
components/bt/bluedroid/bta/gatt/bta_gattc_act.c
components/bt/bluedroid/bta/gatt/bta_gattc_utils.c
components/bt/bluedroid/bta/include/bta_gattc_int.h

index 8d504f6d7f9810a5cb6d8a5236e6f8559e92ddfd..7093723e8b0d8721dc5f19a044fb3b59309efc7d 100644 (file)
@@ -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;
+    }
 }
 
 /*******************************************************************************
index 196acf0495a716967b397f27e16b0652a3e4d9ff..a91d52329307ff353399f38669851f002576d6be 100644 (file)
@@ -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;
     }
 
index 9903a0a053c7f6c62c65209378bc6d407027d02d..48da7e1168829677a73873aca9cf188413a79fd3 100644 (file)
@@ -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);