Эх сурвалжийг харах

Merge branch 'bugfix/btdm_gattc_command_queue_fix' into 'master'

Bugfix/btdm gattc command queue fix

See merge request !1317

Jiang Jiang Jian 8 жил өмнө
parent
commit
ec9d93f4fc

+ 11 - 0
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;
 
 
@@ -145,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 */
 
     /**
@@ -214,6 +216,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 */
 
 /**

+ 90 - 16
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,6 +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;
+                bta_gattc_pop_command_to_send(p_clcb);
             }
 
             bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_CONFIG, status, NULL);
@@ -1012,7 +1014,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 +1035,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 +1066,7 @@ 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;
+                bta_gattc_pop_command_to_send(p_clcb);
             }
 
             bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL);
@@ -1102,6 +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;
+                bta_gattc_pop_command_to_send(p_clcb);
             }
 
             bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL);
@@ -1142,6 +1143,7 @@ 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;
+            bta_gattc_pop_command_to_send(p_clcb);
         }
 
         bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_WRITE, status, NULL);
@@ -1166,6 +1168,7 @@ 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;
+                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 +1235,9 @@ 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);
+    bta_gattc_pop_command_to_send(p_clcb);
     /* read complete, callback */
     ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
 
@@ -1265,9 +1268,9 @@ 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);
+    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 +1288,9 @@ 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);
+    bta_gattc_pop_command_to_send(p_clcb);
     p_clcb->status      = BTA_GATT_OK;
 
     /* execute complete, callback */
@@ -1310,10 +1313,9 @@ 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);
+    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,6 +1458,78 @@ 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.
+**                  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.
+**
+*******************************************************************************/
+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);
+        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);
+                }
+
+                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);
+                    }
+                }
+            }
+        }
+    }
+}
+/*******************************************************************************
+**
+** 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)
+{
+    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
+           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;
+    }
+}
 
 /*******************************************************************************
 **

+ 82 - 4
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
@@ -230,6 +232,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);
@@ -305,6 +308,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 {
@@ -421,6 +426,24 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda)
     }
     return p_tcb;
 }
+
+static BOOLEAN bta_gattc_has_prepare_command_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)) {
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
 /*******************************************************************************
 **
 ** Function         bta_gattc_enqueue
@@ -432,15 +455,70 @@ tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda)
 *******************************************************************************/
 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)
-    {
+    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_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);
+        }
+        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;
+        }
+
+        if (p_data->hdr.event == BTA_GATTC_API_WRITE_EVT) {
+            len = p_data->api_write.len;
+            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(), 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(), line = %d, alloc fail, no memery.", __func__, __LINE__);
+                return FALSE;
+            }
+        }
+
+        //store the command to the command list.
+        list_append(p_clcb->p_cmd_list, (void *)cmd_data);
+        return FALSE;
     }
 
-    APPL_TRACE_ERROR ("%s: already has a pending command!!", __func__);
-    /* skip the callback now. ----- need to send callback ? */
     return FALSE;
 }
 

+ 9 - 0
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;
 
@@ -298,6 +299,7 @@ typedef struct {
     UINT16              conn_id;
     tBTA_GATT_STATUS    status;
     UINT16              handle;
+    UINT16              offset;
 }tBTA_GATTC_WRITE;
 
 typedef struct {
@@ -354,6 +356,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 +407,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 */

+ 3 - 1
components/bt/bluedroid/bta/include/bta_gattc_int.h

@@ -310,7 +310,8 @@ 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 */
+    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
@@ -425,6 +426,7 @@ 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_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);

+ 11 - 1
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);
@@ -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, &param);
         break;
     }
@@ -917,6 +918,15 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
         btc_gattc_cb_to_app(ESP_GATTC_SRVC_CHG_EVT, ESP_GATT_IF_NONE, &param);
         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, &param);
+        break;
+    }
     default:
         LOG_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act);
         break;