OSDN Git Service

stack/gatt: Extend calls with CID
authorŁukasz Rymanowski <lukasz.rymanowski@codecoup.pl>
Fri, 1 May 2020 00:40:58 +0000 (02:40 +0200)
committerJakub Pawlowski <jpawlowski@google.com>
Wed, 2 Sep 2020 17:49:39 +0000 (19:49 +0200)
This is preparation for EATT

Tag: #feature
Bug: 159786353
Sponsor: jpawlowski@
Test: atest net_test_stack
Change-Id: Ie209b705f6cc458286e9566919280ed5e2de60c9

stack/gatt/att_protocol.cc
stack/gatt/gatt_api.cc
stack/gatt/gatt_auth.cc
stack/gatt/gatt_cl.cc
stack/gatt/gatt_db.cc
stack/gatt/gatt_int.h
stack/gatt/gatt_main.cc
stack/gatt/gatt_sr.cc
stack/gatt/gatt_utils.cc
stack/test/gatt/gatt_sr_test.cc

index 5d3d4a8..00ebe1f 100644 (file)
@@ -322,13 +322,14 @@ BT_HDR* attp_build_value_cmd(uint16_t payload_size, uint8_t op_code,
  * Description      Send message to L2CAP.
  *
  ******************************************************************************/
-tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, BT_HDR* p_toL2CAP) {
+tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, uint16_t lcid,
+                                    BT_HDR* p_toL2CAP) {
   uint16_t l2cap_ret;
 
-  if (tcb.att_lcid == L2CAP_ATT_CID)
-    l2cap_ret = L2CA_SendFixedChnlData(L2CAP_ATT_CID, tcb.peer_bda, p_toL2CAP);
+  if (lcid == L2CAP_ATT_CID)
+    l2cap_ret = L2CA_SendFixedChnlData(lcid, tcb.peer_bda, p_toL2CAP);
   else
-    l2cap_ret = (uint16_t)L2CA_DataWrite(tcb.att_lcid, p_toL2CAP);
+    l2cap_ret = (uint16_t)L2CA_DataWrite(lcid, p_toL2CAP);
 
   if (l2cap_ret == L2CAP_DW_FAILED) {
     LOG(ERROR) << __func__ << ": failed to write data to L2CAP";
@@ -394,11 +395,11 @@ BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code,
  *
  *
  ******************************************************************************/
-tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, BT_HDR* p_msg) {
+tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_msg) {
   if (p_msg == NULL) return GATT_NO_RESOURCES;
 
   p_msg->offset = L2CAP_MIN_OFFSET;
-  return attp_send_msg_to_l2cap(tcb, p_msg);
+  return attp_send_msg_to_l2cap(tcb, cid, p_msg);
 }
 
 /*******************************************************************************
@@ -417,13 +418,14 @@ tGATT_STATUS attp_cl_send_cmd(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
                               uint8_t cmd_code, BT_HDR* p_cmd) {
   cmd_code &= ~GATT_AUTH_SIGN_MASK;
 
-  if (!tcb.cl_cmd_q.empty() && cmd_code != GATT_HANDLE_VALUE_CONF) {
+  if (gatt_tcb_is_cid_busy(tcb, p_clcb->cid) &&
+      cmd_code != GATT_HANDLE_VALUE_CONF) {
     gatt_cmd_enq(tcb, p_clcb, true, cmd_code, p_cmd);
     return GATT_CMD_STARTED;
   }
 
   /* no pending request or value confirmation */
-  tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, p_cmd);
+  tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, p_clcb->cid, p_cmd);
   if (att_ret != GATT_CONGESTED && att_ret != GATT_SUCCESS) {
     return GATT_INTERNAL_ERROR;
   }
@@ -458,6 +460,8 @@ tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
                               uint8_t op_code, tGATT_CL_MSG* p_msg) {
   BT_HDR* p_cmd = NULL;
   uint16_t offset = 0, handle;
+  uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, p_clcb->cid);
+
   switch (op_code) {
     case GATT_REQ_MTU:
       if (p_msg->mtu > GATT_MAX_MTU_SIZE) return GATT_ILLEGAL_PARAMETER;
@@ -504,7 +508,7 @@ tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
         return GATT_ILLEGAL_PARAMETER;
 
       p_cmd = attp_build_value_cmd(
-          tcb.payload_size, op_code, p_msg->attr_value.handle, offset,
+          payload_size, op_code, p_msg->attr_value.handle, offset,
           p_msg->attr_value.len, p_msg->attr_value.value);
       break;
 
@@ -513,14 +517,14 @@ tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
       break;
 
     case GATT_REQ_FIND_TYPE_VALUE:
-      p_cmd = attp_build_read_by_type_value_cmd(tcb.payload_size,
+      p_cmd = attp_build_read_by_type_value_cmd(payload_size,
                                                 &p_msg->find_type_value);
       break;
 
     case GATT_REQ_READ_MULTI:
-      p_cmd = attp_build_read_multi_cmd(tcb.payload_size,
-                                        p_msg->read_multi.num_handles,
-                                        p_msg->read_multi.handles);
+      p_cmd =
+          attp_build_read_multi_cmd(payload_size, p_msg->read_multi.num_handles,
+                                    p_msg->read_multi.handles);
       break;
 
     default:
index fd025da..8240e74 100644 (file)
@@ -431,7 +431,11 @@ tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle,
   memcpy(indication.value, p_val, val_len);
   indication.auth_req = GATT_AUTH_REQ_NONE;
 
-  if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) {
+  uint16_t* indicate_handle_p = NULL;
+  uint16_t cid;
+
+  if (!gatt_tcb_get_cid_available_for_indication(p_tcb, p_reg->eatt_support,
+                                                 &indicate_handle_p, &cid)) {
     VLOG(1) << "Add a pending indication";
     gatt_add_pending_ind(p_tcb, &indication);
     return GATT_SUCCESS;
@@ -443,9 +447,9 @@ tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle,
       attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_IND, &gatt_sr_msg);
   if (!p_msg) return GATT_NO_RESOURCES;
 
-  tGATT_STATUS cmd_status = attp_send_sr_msg(*p_tcb, p_msg);
+  tGATT_STATUS cmd_status = attp_send_sr_msg(*p_tcb, cid, p_msg);
   if (cmd_status == GATT_SUCCESS || cmd_status == GATT_CONGESTED) {
-    p_tcb->indicate_handle = indication.handle;
+    *indicate_handle_p = indication.handle;
     gatt_start_conf_timer(p_tcb);
   }
   return cmd_status;
@@ -494,10 +498,13 @@ tGATT_STATUS GATTS_HandleValueNotification(uint16_t conn_id,
   tGATT_STATUS cmd_sent;
   tGATT_SR_MSG gatt_sr_msg;
   gatt_sr_msg.attr_value = notif;
+
+  uint16_t cid = gatt_tcb_get_att_cid(*p_tcb);
+
   BT_HDR* p_buf =
       attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_NOTIF, &gatt_sr_msg);
   if (p_buf != NULL) {
-    cmd_sent = attp_send_sr_msg(*p_tcb, p_buf);
+    cmd_sent = attp_send_sr_msg(*p_tcb, cid, p_buf);
   } else
     cmd_sent = GATT_NO_RESOURCES;
   return cmd_sent;
@@ -519,7 +526,6 @@ tGATT_STATUS GATTS_HandleValueNotification(uint16_t conn_id,
  ******************************************************************************/
 tGATT_STATUS GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id,
                            tGATT_STATUS status, tGATTS_RSP* p_msg) {
-  tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER;
   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
@@ -533,16 +539,17 @@ tGATT_STATUS GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id,
     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
   }
 
-  if (p_tcb->sr_cmd.trans_id != trans_id) {
+  tGATT_SR_CMD* sr_res_p = gatt_sr_get_cmd_by_trans_id(p_tcb, trans_id);
+
+  if (!sr_res_p) {
     LOG(ERROR) << "conn_id=" << loghex(conn_id)
-               << " waiting for op_code=" << loghex(p_tcb->sr_cmd.op_code);
+               << " waiting for other op_code ";
     return (GATT_WRONG_STATE);
   }
-  /* Process App response */
-  cmd_sent = gatt_sr_process_app_rsp(*p_tcb, gatt_if, trans_id,
-                                     p_tcb->sr_cmd.op_code, status, p_msg);
 
-  return cmd_sent;
+  /* Process App response */
+  return gatt_sr_process_app_rsp(*p_tcb, gatt_if, trans_id, sr_res_p->op_code,
+                                 status, p_msg, sr_res_p);
 }
 
 /******************************************************************************/
@@ -593,6 +600,8 @@ tGATT_STATUS GATTC_ConfigureMTU(uint16_t conn_id, uint16_t mtu) {
   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
   if (!p_clcb) return GATT_NO_RESOURCES;
 
+  /* For this request only ATT CID is valid */
+  p_clcb->cid = L2CAP_ATT_CID;
   p_clcb->p_tcb->payload_size = mtu;
   p_clcb->operation = GATTC_OPTYPE_CONFIG;
   tGATT_CL_MSG gatt_cl_msg;
@@ -709,7 +718,8 @@ tGATT_STATUS GATTC_Read(uint16_t conn_id, tGATT_READ_TYPE type,
   p_clcb->op_subtype = type;
   p_clcb->auth_req = p_read->by_handle.auth_req;
   p_clcb->counter = 0;
-  p_clcb->read_req_current_mtu = p_tcb->payload_size;
+  p_clcb->read_req_current_mtu =
+      gatt_tcb_get_payload_size_tx(*p_tcb, p_clcb->cid);
 
   switch (type) {
     case GATT_READ_BY_TYPE:
index f3cb56f..e932987 100644 (file)
@@ -94,7 +94,7 @@ static bool gatt_sign_data(tGATT_CLCB* p_clcb) {
  * Returns
  *
  ******************************************************************************/
-void gatt_verify_signature(tGATT_TCB& tcb, BT_HDR* p_buf) {
+void gatt_verify_signature(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf) {
   uint16_t cmd_len;
   uint8_t op_code;
   uint8_t *p, *p_orig = (uint8_t*)(p_buf + 1) + p_buf->offset;
@@ -116,7 +116,7 @@ void gatt_verify_signature(tGATT_TCB& tcb, BT_HDR* p_buf) {
   }
 
   STREAM_TO_UINT8(op_code, p_orig);
-  gatt_server_handle_client_req(tcb, op_code, (uint16_t)(p_buf->len - 1),
+  gatt_server_handle_client_req(tcb, cid, op_code, (uint16_t)(p_buf->len - 1),
                                 p_orig);
 }
 /*******************************************************************************
index be6eca3..6ad0b5e 100644 (file)
  *
  ******************************************************************************/
 
-#include "bt_target.h"
-
 #include <string.h>
+
 #include "bt_common.h"
+#include "bt_target.h"
 #include "bt_utils.h"
 #include "gatt_int.h"
 #include "l2c_api.h"
@@ -213,6 +213,8 @@ void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act) {
   CHECK(p_clcb->p_attr_buf);
   tGATT_VALUE& attr = *((tGATT_VALUE*)p_clcb->p_attr_buf);
 
+  uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, p_clcb->cid);
+
   switch (p_clcb->op_subtype) {
     case GATT_WRITE_NO_RSP: {
       p_clcb->s_handle = attr.handle;
@@ -231,7 +233,7 @@ void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act) {
     }
 
     case GATT_WRITE: {
-      if (attr.len <= (tcb.payload_size - GATT_HDR_SIZE)) {
+      if (attr.len <= (payload_size - GATT_HDR_SIZE)) {
         p_clcb->s_handle = attr.handle;
 
         uint8_t rt = gatt_send_write_msg(tcb, p_clcb, GATT_REQ_WRITE,
@@ -332,9 +334,10 @@ void gatt_send_prepare_write(tGATT_TCB& tcb, tGATT_CLCB* p_clcb) {
   VLOG(1) << __func__ << StringPrintf(" type=0x%x", type);
   uint16_t to_send = p_attr->len - p_attr->offset;
 
-  if (to_send > (tcb.payload_size -
+  uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, p_clcb->cid);
+  if (to_send > (payload_size -
                  GATT_WRITE_LONG_HDR_SIZE)) /* 2 = uint16_t offset bytes  */
-    to_send = tcb.payload_size - GATT_WRITE_LONG_HDR_SIZE;
+    to_send = payload_size - GATT_WRITE_LONG_HDR_SIZE;
 
   p_clcb->s_handle = p_attr->handle;
 
@@ -716,8 +719,8 @@ void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
   }
 
   STREAM_TO_UINT8(value_len, p);
-
-  if ((value_len > (tcb.payload_size - 2)) || (value_len > (len - 1))) {
+  uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, p_clcb->cid);
+  if ((value_len > (payload_size - 2)) || (value_len > (len - 1))) {
     /* this is an error case that server's response containing a value length
        which is larger than MTU-2
        or value_len > message total length -1 */
@@ -725,7 +728,7 @@ void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
                << StringPrintf(
                       ": Discard response op_code=%d "
                       "vale_len=%d > (MTU-2=%d or msg_len-1=%d)",
-                      op_code, value_len, (tcb.payload_size - 2), (len - 1));
+                      op_code, value_len, (payload_size - 2), (len - 1));
     gatt_end_operation(p_clcb, GATT_ERROR, NULL);
     return;
   }
@@ -808,7 +811,7 @@ void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
              p_clcb->op_subtype == GATT_READ_BY_TYPE) {
       p_clcb->counter = len - 2;
       p_clcb->s_handle = handle;
-      if (p_clcb->counter == (p_clcb->p_tcb->payload_size - 4)) {
+      if (p_clcb->counter == (payload_size - 4)) {
         p_clcb->op_subtype = GATT_READ_BY_HANDLE;
         if (!p_clcb->p_attr_buf)
           p_clcb->p_attr_buf = (uint8_t*)osi_malloc(GATT_MAX_ATTR_LEN);
@@ -895,6 +898,8 @@ void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
   uint16_t offset = p_clcb->counter;
   uint8_t* p = p_data;
 
+  uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, p_clcb->cid);
+
   if (p_clcb->operation == GATTC_OPTYPE_READ) {
     if (p_clcb->op_subtype != GATT_READ_BY_HANDLE) {
       p_clcb->counter = len;
@@ -915,12 +920,12 @@ void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
 
         /* full packet for read or read blob rsp */
         bool packet_is_full;
-        if (tcb.payload_size == p_clcb->read_req_current_mtu) {
-          packet_is_full = (len == (tcb.payload_size - 1));
+        if (payload_size == p_clcb->read_req_current_mtu) {
+          packet_is_full = (len == (payload_size - 1));
         } else {
           packet_is_full = (len == (p_clcb->read_req_current_mtu - 1) ||
-                            len == (tcb.payload_size - 1));
-          p_clcb->read_req_current_mtu = tcb.payload_size;
+                            len == (payload_size - 1));
+          p_clcb->read_req_current_mtu = payload_size;
         }
 
         /* send next request if needed  */
@@ -1026,14 +1031,24 @@ uint8_t gatt_cmd_to_rsp_code(uint8_t cmd_code) {
 
 /** Find next command in queue and sent to server */
 bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) {
+  std::queue<tGATT_CMD_Q>* cl_cmd_q;
+
   while (!tcb.cl_cmd_q.empty()) {
-    tGATT_CMD_Q& cmd = tcb.cl_cmd_q.front();
-    if (!cmd.to_send || cmd.p_cmd == NULL) return false;
+    if (!tcb.cl_cmd_q.empty()) {
+      cl_cmd_q = &tcb.cl_cmd_q;
+    }
+
+    tGATT_CMD_Q& cmd = cl_cmd_q->front();
+    if (!cmd.to_send || cmd.p_cmd == NULL) {
+      return false;
+    }
+
+    tGATT_STATUS att_ret;
+    att_ret = attp_send_msg_to_l2cap(tcb, cmd.cid, cmd.p_cmd);
 
-    tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, cmd.p_cmd);
     if (att_ret != GATT_SUCCESS && att_ret != GATT_CONGESTED) {
       LOG(ERROR) << __func__ << ": L2CAP sent error";
-      tcb.cl_cmd_q.pop();
+      cl_cmd_q->pop();
       continue;
     }
 
@@ -1043,7 +1058,7 @@ bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) {
     if (cmd.op_code == GATT_CMD_WRITE || cmd.op_code == GATT_SIGN_CMD_WRITE) {
       /* dequeue the request if is write command or sign write */
       uint8_t rsp_code;
-      tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &rsp_code);
+      tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, cmd.cid, &rsp_code);
 
       /* send command complete callback here */
       gatt_end_operation(p_clcb, att_ret, NULL);
@@ -1062,13 +1077,18 @@ bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) {
 }
 
 /** This function is called to handle the server response to client */
-void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code,
-                                   uint16_t len, uint8_t* p_data) {
+void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid,
+                                   uint8_t op_code, uint16_t len,
+                                   uint8_t* p_data) {
+  VLOG(1) << __func__ << " opcode: " << loghex(op_code);
+
+  uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, cid);
+
   if (op_code == GATT_HANDLE_VALUE_IND || op_code == GATT_HANDLE_VALUE_NOTIF) {
-    if (len >= tcb.payload_size) {
+    if (len >= payload_size) {
       LOG(ERROR) << StringPrintf(
           "%s: invalid indicate pkt size: %d, PDU size: %d", __func__, len + 1,
-          tcb.payload_size);
+          payload_size);
       return;
     }
 
@@ -1077,7 +1097,7 @@ void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code,
   }
 
   uint8_t cmd_code = 0;
-  tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &cmd_code);
+  tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, cid, &cmd_code);
   uint8_t rsp_code = gatt_cmd_to_rsp_code(cmd_code);
   if (!p_clcb || (rsp_code != op_code && op_code != GATT_RSP_ERROR)) {
     LOG(WARNING) << StringPrintf(
@@ -1092,16 +1112,16 @@ void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code,
     return;
   }
 
-  alarm_cancel(p_clcb->gatt_rsp_timer_ent);
+  gatt_stop_rsp_timer(p_clcb);
   p_clcb->retry_count = 0;
 
   /* the size of the message may not be bigger than the local max PDU size*/
   /* The message has to be smaller than the agreed MTU, len does not count
    * op_code */
-  if (len >= tcb.payload_size) {
+  if (len >= payload_size) {
     LOG(ERROR) << StringPrintf(
         "%s: invalid response pkt size: %d, PDU size: %d", __func__, len + 1,
-        tcb.payload_size);
+        payload_size);
     gatt_end_operation(p_clcb, GATT_ERROR, NULL);
   } else {
     switch (op_code) {
index 4807f94..c3385a2 100644 (file)
@@ -45,8 +45,8 @@ using bluetooth::Uuid;
 static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const Uuid& uuid,
                                        tGATT_PERM perm);
 static tGATT_STATUS gatts_send_app_read_request(
-    tGATT_TCB& tcb, uint8_t op_code, uint16_t handle, uint16_t offset,
-    uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type);
+    tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t handle,
+    uint16_t offset, uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type);
 
 /**
  * Initialize a memory space to be a service database.
@@ -254,10 +254,10 @@ static tGATT_STATUS read_attr_value(tGATT_ATTR& attr16, uint16_t offset,
  *
  ******************************************************************************/
 tGATT_STATUS gatts_db_read_attr_value_by_type(
-    tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp,
-    uint16_t s_handle, uint16_t e_handle, const Uuid& type, uint16_t* p_len,
-    tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id,
-    uint16_t* p_cur_handle) {
+    tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code,
+    BT_HDR* p_rsp, uint16_t s_handle, uint16_t e_handle, const Uuid& type,
+    uint16_t* p_len, tGATT_SEC_FLAG sec_flag, uint8_t key_size,
+    uint32_t trans_id, uint16_t* p_cur_handle) {
   tGATT_STATUS status = GATT_NOT_FOUND;
   uint16_t len = 0;
   uint8_t* p = (uint8_t*)(p_rsp + 1) + p_rsp->len + L2CAP_MIN_OFFSET;
@@ -276,8 +276,8 @@ tGATT_STATUS gatts_db_read_attr_value_by_type(
                                  &len, sec_flag, key_size);
 
         if (status == GATT_PENDING) {
-          status = gatts_send_app_read_request(tcb, op_code, attr.handle, 0,
-                                               trans_id, attr.gatt_type);
+          status = gatts_send_app_read_request(tcb, cid, op_code, attr.handle,
+                                               0, trans_id, attr.gatt_type);
 
           /* one callback at a time */
           break;
@@ -442,9 +442,10 @@ tGATT_ATTR* find_attr_by_handle(tGATT_SVC_DB* p_db, uint16_t handle) {
  *
  ******************************************************************************/
 tGATT_STATUS gatts_read_attr_value_by_handle(
-    tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle,
-    uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu,
-    tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id) {
+    tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code,
+    uint16_t handle, uint16_t offset, uint8_t* p_value, uint16_t* p_len,
+    uint16_t mtu, tGATT_SEC_FLAG sec_flag, uint8_t key_size,
+    uint32_t trans_id) {
   tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle);
   if (!p_attr) return GATT_NOT_FOUND;
 
@@ -454,8 +455,8 @@ tGATT_STATUS gatts_read_attr_value_by_handle(
                                         mtu, p_len, sec_flag, key_size);
 
   if (status == GATT_PENDING) {
-    status = gatts_send_app_read_request(tcb, op_code, p_attr->handle, offset,
-                                         trans_id, p_attr->gatt_type);
+    status = gatts_send_app_read_request(tcb, cid, op_code, p_attr->handle,
+                                         offset, trans_id, p_attr->gatt_type);
   }
   return status;
 }
@@ -678,14 +679,14 @@ static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const Uuid& uuid,
  *
  ******************************************************************************/
 static tGATT_STATUS gatts_send_app_read_request(
-    tGATT_TCB& tcb, uint8_t op_code, uint16_t handle, uint16_t offset,
-    uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type) {
+    tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t handle,
+    uint16_t offset, uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type) {
   tGATT_SRV_LIST_ELEM& el = *gatt_sr_find_i_rcb_by_handle(handle);
   uint16_t conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, el.gatt_if);
 
   if (trans_id == 0) {
-    trans_id = gatt_sr_enqueue_cmd(tcb, op_code, handle);
-    gatt_sr_update_cback_cnt(tcb, el.gatt_if, true, true);
+    trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, handle);
+    gatt_sr_update_cback_cnt(tcb, cid, el.gatt_if, true, true);
   }
 
   if (trans_id != 0) {
index ab82839..6bdd97a 100644 (file)
@@ -205,6 +205,7 @@ typedef struct {
   tGATT_CLCB* p_clcb;
   uint8_t op_code;
   bool to_send;
+  uint16_t cid;
 } tGATT_CMD_Q;
 
 #if GATT_MAX_SR_PROFILES <= 8
@@ -225,6 +226,7 @@ typedef struct {
   uint8_t op_code;
   uint8_t status;
   uint8_t cback_cnt[GATT_MAX_APPS];
+  uint16_t cid;
 } tGATT_SR_CMD;
 
 #define GATT_CH_CLOSE 0
@@ -327,6 +329,7 @@ struct tGATT_CLCB {
   uint8_t retry_count;
   uint16_t read_req_current_mtu; /* This is the MTU value that the read was
                                     initiated with */
+  uint16_t cid;
 };
 
 typedef struct {
@@ -414,7 +417,7 @@ extern bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr,
 extern bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb,
                          tBT_TRANSPORT transport, uint8_t initiating_phys,
                          tGATT_IF gatt_if);
-extern void gatt_data_process(tGATT_TCB& p_tcb, BT_HDR* p_buf);
+extern void gatt_data_process(tGATT_TCB& p_tcb, uint16_t cid, BT_HDR* p_buf);
 extern void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB* p_tcb,
                                           bool is_add, bool check_acl_link);
 
@@ -439,8 +442,10 @@ extern tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
                                      uint8_t op_code, tGATT_CL_MSG* p_msg);
 extern BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code,
                                  tGATT_SR_MSG* p_msg);
-extern tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, BT_HDR* p_msg);
-extern tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, BT_HDR* p_toL2CAP);
+extern tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, uint16_t cid,
+                                     BT_HDR* p_msg);
+extern tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, uint16_t cid,
+                                           BT_HDR* p_toL2CAP);
 
 /* utility functions */
 extern uint8_t* gatt_dbg_op_name(uint8_t op_code);
@@ -455,14 +460,15 @@ extern void gatt_sr_get_sec_info(const RawAddress& rem_bda,
                                  tBT_TRANSPORT transport, uint8_t* p_sec_flag,
                                  uint8_t* p_key_size);
 extern void gatt_start_rsp_timer(tGATT_CLCB* p_clcb);
+extern void gatt_stop_rsp_timer(tGATT_CLCB* p_clcb);
 extern void gatt_start_conf_timer(tGATT_TCB* p_tcb);
 extern void gatt_rsp_timeout(void* data);
 extern void gatt_indication_confirmation_timeout(void* data);
 extern void gatt_ind_ack_timeout(void* data);
 extern void gatt_start_ind_ack_timer(tGATT_TCB& tcb);
-extern tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint8_t err_code,
-                                        uint8_t op_code, uint16_t handle,
-                                        bool deq);
+extern tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint16_t cid,
+                                        uint8_t err_code, uint8_t op_code,
+                                        uint16_t handle, bool deq);
 
 extern bool gatt_is_srv_chg_ind_pending(tGATT_TCB* p_tcb);
 extern tGATTS_SRV_CHG* gatt_is_bda_in_the_srv_chg_clt_list(
@@ -494,30 +500,47 @@ extern std::list<tGATT_SRV_LIST_ELEM>::iterator gatt_sr_find_i_rcb_by_handle(
 extern tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if,
                                             uint32_t trans_id, uint8_t op_code,
                                             tGATT_STATUS status,
-                                            tGATTS_RSP* p_msg);
-extern void gatt_server_handle_client_req(tGATT_TCB& p_tcb, uint8_t op_code,
-                                          uint16_t len, uint8_t* p_data);
+                                            tGATTS_RSP* p_msg,
+                                            tGATT_SR_CMD* sr_res_p);
+extern void gatt_server_handle_client_req(tGATT_TCB& p_tcb, uint16_t cid,
+                                          uint8_t op_code, uint16_t len,
+                                          uint8_t* p_data);
 extern void gatt_sr_send_req_callback(uint16_t conn_id, uint32_t trans_id,
                                       uint8_t op_code, tGATTS_DATA* p_req_data);
-extern uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint8_t op_code,
-                                    uint16_t handle);
+extern uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint16_t cid,
+                                    uint8_t op_code, uint16_t handle);
 extern bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda);
 extern void gatt_notify_phy_updated(uint8_t status, uint16_t handle,
                                     uint8_t tx_phy, uint8_t rx_phy);
 /*   */
 
+extern bool gatt_tcb_is_cid_busy(tGATT_TCB& tcb, uint16_t cid);
+
 extern tGATT_REG* gatt_get_regcb(tGATT_IF gatt_if);
 extern bool gatt_is_clcb_allocated(uint16_t conn_id);
 extern tGATT_CLCB* gatt_clcb_alloc(uint16_t conn_id);
+
+extern bool gatt_tcb_get_cid_available_for_indication(
+    tGATT_TCB* p_tcb, bool eatt_support, uint16_t** indicate_handle_p,
+    uint16_t* cid_p);
+extern bool gatt_tcb_find_indicate_handle(tGATT_TCB& tcb, uint16_t cid,
+                                          uint16_t* indicated_handle_p);
+extern uint16_t gatt_tcb_get_att_cid(tGATT_TCB& tcb);
+extern uint16_t gatt_tcb_get_payload_size_tx(tGATT_TCB& tcb, uint16_t cid);
+extern uint16_t gatt_tcb_get_payload_size_rx(tGATT_TCB& tcb, uint16_t cid);
 extern void gatt_clcb_dealloc(tGATT_CLCB* p_clcb);
 
 extern void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB& p_tcb);
 extern bool gatt_sr_is_cback_cnt_zero(tGATT_TCB& p_tcb);
 extern bool gatt_sr_is_prep_cnt_zero(tGATT_TCB& p_tcb);
-extern void gatt_sr_reset_cback_cnt(tGATT_TCB& p_tcb);
+extern void gatt_sr_reset_cback_cnt(tGATT_TCB& p_tcb, uint16_t cid);
 extern void gatt_sr_reset_prep_cnt(tGATT_TCB& tcb);
-extern void gatt_sr_update_cback_cnt(tGATT_TCB& p_tcb, tGATT_IF gatt_if,
-                                     bool is_inc, bool is_reset_first);
+extern tGATT_SR_CMD* gatt_sr_get_cmd_by_trans_id(tGATT_TCB* p_tcb,
+                                                 uint32_t trans_id);
+extern tGATT_SR_CMD* gatt_sr_get_cmd_by_cid(tGATT_TCB& tcb, uint16_t cid);
+extern void gatt_sr_update_cback_cnt(tGATT_TCB& p_tcb, uint16_t cid,
+                                     tGATT_IF gatt_if, bool is_inc,
+                                     bool is_reset_first);
 extern void gatt_sr_update_prep_cnt(tGATT_TCB& tcb, tGATT_IF gatt_if,
                                     bool is_inc, bool is_reset_first);
 
@@ -545,17 +568,19 @@ extern void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status,
 extern void gatt_act_discovery(tGATT_CLCB* p_clcb);
 extern void gatt_act_read(tGATT_CLCB* p_clcb, uint16_t offset);
 extern void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act);
-extern tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint8_t* p_opcode);
+extern tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint16_t cid,
+                                    uint8_t* p_opcode);
 extern void gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send,
                          uint8_t op_code, BT_HDR* p_buf);
-extern void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code,
-                                          uint16_t len, uint8_t* p_data);
+extern void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid,
+                                          uint8_t op_code, uint16_t len,
+                                          uint8_t* p_data);
 extern void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
                                          tGATT_EXEC_FLAG flag);
 
 /* gatt_auth.cc */
 extern bool gatt_security_check_start(tGATT_CLCB* p_clcb);
-extern void gatt_verify_signature(tGATT_TCB& tcb, BT_HDR* p_buf);
+extern void gatt_verify_signature(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf);
 extern tGATT_STATUS gatt_get_link_encrypt_status(tGATT_TCB& tcb);
 extern tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB* p_tcb);
 extern void gatt_set_sec_act(tGATT_TCB* p_tcb, tGATT_SEC_ACTION sec_act);
@@ -573,14 +598,14 @@ extern uint16_t gatts_add_characteristic(tGATT_SVC_DB& db, tGATT_PERM perm,
 extern uint16_t gatts_add_char_descr(tGATT_SVC_DB& db, tGATT_PERM perm,
                                      const bluetooth::Uuid& dscp_uuid);
 extern tGATT_STATUS gatts_db_read_attr_value_by_type(
-    tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp,
-    uint16_t s_handle, uint16_t e_handle, const bluetooth::Uuid& type,
-    uint16_t* p_len, tGATT_SEC_FLAG sec_flag, uint8_t key_size,
-    uint32_t trans_id, uint16_t* p_cur_handle);
+    tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code,
+    BT_HDR* p_rsp, uint16_t s_handle, uint16_t e_handle,
+    const bluetooth::Uuid& type, uint16_t* p_len, tGATT_SEC_FLAG sec_flag,
+    uint8_t key_size, uint32_t trans_id, uint16_t* p_cur_handle);
 extern tGATT_STATUS gatts_read_attr_value_by_handle(
-    tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle,
-    uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu,
-    tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id);
+    tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code,
+    uint16_t handle, uint16_t offset, uint8_t* p_value, uint16_t* p_len,
+    uint16_t mtu, tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id);
 extern tGATT_STATUS gatts_write_attr_perm_check(
     tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle, uint16_t offset,
     uint8_t* p_data, uint16_t len, tGATT_SEC_FLAG sec_flag, uint8_t key_size);
index fff9f75..f524d41 100644 (file)
@@ -543,7 +543,7 @@ static void gatt_le_data_ind(uint16_t chan, const RawAddress& bd_addr,
       LOG(WARNING) << "ATT - Ignored L2CAP data while in state: "
                    << +gatt_get_ch_state(p_tcb);
     } else
-      gatt_data_process(*p_tcb, p_buf);
+      gatt_data_process(*p_tcb, L2CAP_ATT_CID, p_buf);
   }
 
   osi_free(p_buf);
@@ -773,7 +773,7 @@ static void gatt_l2cif_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) {
   tGATT_TCB* p_tcb = gatt_find_tcb_by_cid(lcid);
   if (p_tcb && gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
     /* process the data */
-    gatt_data_process(*p_tcb, p_buf);
+    gatt_data_process(*p_tcb, lcid, p_buf);
   }
 
   osi_free(p_buf);
@@ -838,7 +838,7 @@ static void gatt_send_conn_cback(tGATT_TCB* p_tcb) {
  * Returns          void
  *
  ******************************************************************************/
-void gatt_data_process(tGATT_TCB& tcb, BT_HDR* p_buf) {
+void gatt_data_process(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf) {
   uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
   uint8_t op_code, pseudo_op_code;
 
@@ -858,18 +858,18 @@ void gatt_data_process(tGATT_TCB& tcb, BT_HDR* p_buf) {
      */
     LOG(ERROR) << __func__
                << ": ATT - Rcvd L2CAP data, unknown cmd: " << loghex(op_code);
-    gatt_send_error_rsp(tcb, GATT_REQ_NOT_SUPPORTED, op_code, 0, false);
+    gatt_send_error_rsp(tcb, cid, GATT_REQ_NOT_SUPPORTED, op_code, 0, false);
     return;
   }
 
   if (op_code == GATT_SIGN_CMD_WRITE) {
-    gatt_verify_signature(tcb, p_buf);
+    gatt_verify_signature(tcb, cid, p_buf);
   } else {
     /* message from client */
     if ((op_code % 2) == 0)
-      gatt_server_handle_client_req(tcb, op_code, msg_len, p);
+      gatt_server_handle_client_req(tcb, cid, op_code, msg_len, p);
     else
-      gatt_client_handle_server_rsp(tcb, op_code, msg_len, p);
+      gatt_client_handle_server_rsp(tcb, cid, op_code, msg_len, p);
   }
 }
 
index 6336ada..0346b40 100644 (file)
@@ -21,7 +21,6 @@
  *  this file contains the GATT server functions
  *
  ******************************************************************************/
-
 #include "bt_target.h"
 #include "osi/include/osi.h"
 
@@ -46,10 +45,14 @@ using bluetooth::Uuid;
  * Returns          void
  *
  ******************************************************************************/
-uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint8_t op_code, uint16_t handle) {
+uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
+                             uint16_t handle) {
   tGATT_SR_CMD* p_cmd = &tcb.sr_cmd;
+
   uint32_t trans_id = 0;
 
+  p_cmd->cid = cid;
+
   if ((p_cmd->op_code == 0) ||
       (op_code == GATT_HANDLE_VALUE_CONF)) /* no pending request */
   {
@@ -228,42 +231,44 @@ static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
 tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if,
                                      UNUSED_ATTR uint32_t trans_id,
                                      uint8_t op_code, tGATT_STATUS status,
-                                     tGATTS_RSP* p_msg) {
+                                     tGATTS_RSP* p_msg,
+                                     tGATT_SR_CMD* sr_res_p) {
   tGATT_STATUS ret_code = GATT_SUCCESS;
+  uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, sr_res_p->cid);
 
   VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
 
-  gatt_sr_update_cback_cnt(tcb, gatt_if, false, false);
+  gatt_sr_update_cback_cnt(tcb, sr_res_p->cid, gatt_if, false, false);
 
   if (op_code == GATT_REQ_READ_MULTI) {
     /* If no error and still waiting, just return */
-    if (!process_read_multi_rsp(&tcb.sr_cmd, status, p_msg, tcb.payload_size))
+    if (!process_read_multi_rsp(sr_res_p, status, p_msg, payload_size))
       return (GATT_SUCCESS);
   } else {
     if (op_code == GATT_REQ_PREPARE_WRITE && status == GATT_SUCCESS)
       gatt_sr_update_prep_cnt(tcb, gatt_if, true, false);
 
     if (op_code == GATT_REQ_EXEC_WRITE && status != GATT_SUCCESS)
-      gatt_sr_reset_cback_cnt(tcb);
+      gatt_sr_reset_cback_cnt(tcb, sr_res_p->cid);
 
-    tcb.sr_cmd.status = status;
+    sr_res_p->status = status;
 
     if (gatt_sr_is_cback_cnt_zero(tcb) && status == GATT_SUCCESS) {
-      if (tcb.sr_cmd.p_rsp_msg == NULL) {
-        tcb.sr_cmd.p_rsp_msg = attp_build_sr_msg(tcb, (uint8_t)(op_code + 1),
-                                                 (tGATT_SR_MSG*)p_msg);
+      if (sr_res_p->p_rsp_msg == NULL) {
+        sr_res_p->p_rsp_msg = attp_build_sr_msg(tcb, (uint8_t)(op_code + 1),
+                                                (tGATT_SR_MSG*)p_msg);
       } else {
         LOG(ERROR) << "Exception!!! already has respond message";
       }
     }
   }
   if (gatt_sr_is_cback_cnt_zero(tcb)) {
-    if ((tcb.sr_cmd.status == GATT_SUCCESS) && (tcb.sr_cmd.p_rsp_msg)) {
-      ret_code = attp_send_sr_msg(tcb, tcb.sr_cmd.p_rsp_msg);
-      tcb.sr_cmd.p_rsp_msg = NULL;
+    if ((sr_res_p->status == GATT_SUCCESS) && (sr_res_p->p_rsp_msg)) {
+      ret_code = attp_send_sr_msg(tcb, sr_res_p->cid, sr_res_p->p_rsp_msg);
+      sr_res_p->p_rsp_msg = NULL;
     } else {
-      ret_code =
-          gatt_send_error_rsp(tcb, status, op_code, tcb.sr_cmd.handle, false);
+      ret_code = gatt_send_error_rsp(tcb, sr_res_p->cid, status, op_code,
+                                     sr_res_p->handle, false);
     }
 
     gatt_dequeue_sr_cmd(tcb);
@@ -284,8 +289,8 @@ tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if,
  * Returns          void
  *
  ******************************************************************************/
-void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
-                                 uint8_t* p_data) {
+void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
+                                 uint16_t len, uint8_t* p_data) {
   uint8_t *p = p_data, flag, i = 0;
   uint32_t trans_id = 0;
   tGATT_IF gatt_if;
@@ -297,7 +302,7 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
         << "Conformance tst: forced err rspv for Execute Write: error status="
         << +gatt_cb.err_status;
 
-    gatt_send_error_rsp(tcb, gatt_cb.err_status, gatt_cb.req_op_code,
+    gatt_send_error_rsp(tcb, cid, gatt_cb.err_status, gatt_cb.req_op_code,
                         gatt_cb.handle, false);
 
     return;
@@ -307,7 +312,8 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
   if (len < sizeof(flag)) {
     android_errorWriteLog(0x534e4554, "73172115");
     LOG(ERROR) << __func__ << "invalid length";
-    gatt_send_error_rsp(tcb, GATT_INVALID_PDU, GATT_REQ_EXEC_WRITE, 0, false);
+    gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, GATT_REQ_EXEC_WRITE, 0,
+                        false);
     return;
   }
 
@@ -318,7 +324,7 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
 
   /* no prep write is queued */
   if (!gatt_sr_is_prep_cnt_zero(tcb)) {
-    trans_id = gatt_sr_enqueue_cmd(tcb, op_code, 0);
+    trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, 0);
     gatt_sr_copy_prep_cnt_to_cback_cnt(tcb);
 
     for (i = 0; i < GATT_MAX_APPS; i++) {
@@ -335,7 +341,7 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
   } else /* nothing needs to be executed , send response now */
   {
     LOG(ERROR) << "gatt_process_exec_write_req: no prepare write pending";
-    gatt_send_error_rsp(tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, false);
+    gatt_send_error_rsp(tcb, cid, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, false);
   }
 }
 
@@ -349,8 +355,8 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
  * Returns          void
  *
  ******************************************************************************/
-void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
-                                 uint8_t* p_data) {
+void gatt_process_read_multi_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
+                                 uint16_t len, uint8_t* p_data) {
   uint32_t trans_id;
   uint16_t handle = 0, ll = len;
   uint8_t* p = p_data;
@@ -369,8 +375,8 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
 
     STREAM_TO_UINT16(handle, p);
 
-    gatt_send_error_rsp(tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle,
-                        false);
+    gatt_send_error_rsp(tcb, cid, gatt_cb.err_status, gatt_cb.req_op_code,
+                        handle, false);
 
     return;
   }
@@ -407,9 +413,12 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
 
   if (err == GATT_SUCCESS) {
     trans_id =
-        gatt_sr_enqueue_cmd(tcb, op_code, tcb.sr_cmd.multi_req.handles[0]);
+        gatt_sr_enqueue_cmd(tcb, cid, op_code, tcb.sr_cmd.multi_req.handles[0]);
     if (trans_id != 0) {
-      gatt_sr_reset_cback_cnt(tcb); /* read multiple use multi_rsp_q's count*/
+      tGATT_SR_CMD* sr_cmd_p = gatt_sr_get_cmd_by_cid(tcb, cid);
+
+      gatt_sr_reset_cback_cnt(tcb,
+                              cid); /* read multiple use multi_rsp_q's count*/
 
       for (ll = 0; ll < tcb.sr_cmd.multi_req.num_handles; ll++) {
         tGATTS_RSP* p_msg = (tGATTS_RSP*)osi_calloc(sizeof(tGATTS_RSP));
@@ -418,13 +427,13 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
 
         p_msg->attr_value.handle = handle;
         err = gatts_read_attr_value_by_handle(
-            tcb, it->p_db, op_code, handle, 0, p_msg->attr_value.value,
+            tcb, cid, it->p_db, op_code, handle, 0, p_msg->attr_value.value,
             &p_msg->attr_value.len, GATT_MAX_ATTR_LEN, sec_flag, key_size,
             trans_id);
 
         if (err == GATT_SUCCESS) {
           gatt_sr_process_app_rsp(tcb, it->gatt_if, trans_id, op_code,
-                                  GATT_SUCCESS, p_msg);
+                                  GATT_SUCCESS, p_msg, sr_cmd_p);
         }
         /* either not using or done using the buffer, release it now */
         osi_free(p_msg);
@@ -436,7 +445,7 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
   /* in theroy BUSY is not possible(should already been checked), protected
    * check */
   if (err != GATT_SUCCESS && err != GATT_PENDING && err != GATT_BUSY)
-    gatt_send_error_rsp(tcb, err, op_code, handle, false);
+    gatt_send_error_rsp(tcb, cid, err, op_code, handle, false);
 }
 
 /*******************************************************************************
@@ -450,13 +459,16 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
  *
  ******************************************************************************/
 static tGATT_STATUS gatt_build_primary_service_rsp(
-    BT_HDR* p_msg, tGATT_TCB& tcb, uint8_t op_code, uint16_t s_hdl,
-    uint16_t e_hdl, UNUSED_ATTR uint8_t* p_data, const Uuid& value) {
+    BT_HDR* p_msg, tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
+    uint16_t s_hdl, uint16_t e_hdl, UNUSED_ATTR uint8_t* p_data,
+    const Uuid& value) {
   tGATT_STATUS status = GATT_NOT_FOUND;
   uint8_t handle_len = 4;
 
   uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
 
+  uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid);
+
   for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info) {
     if (el.s_hdl < s_hdl || el.s_hdl > e_hdl ||
         el.type != GATT_UUID_PRI_SERVICE) {
@@ -481,7 +493,7 @@ static tGATT_STATUS gatt_build_primary_service_rsp(
       }
     }
 
-    if (p_msg->len + p_msg->offset > tcb.payload_size ||
+    if (p_msg->len + p_msg->offset > payload_size ||
         handle_len != p_msg->offset) {
       break;
     }
@@ -613,28 +625,30 @@ static tGATT_STATUS gatts_validate_packet_format(uint8_t op_code, uint16_t& len,
  * Returns          void
  *
  ******************************************************************************/
-void gatts_process_primary_service_req(tGATT_TCB& tcb, uint8_t op_code,
-                                       uint16_t len, uint8_t* p_data) {
+void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid,
+                                       uint8_t op_code, uint16_t len,
+                                       uint8_t* p_data) {
   uint16_t s_hdl = 0, e_hdl = 0;
   Uuid uuid = Uuid::kEmpty;
 
   uint8_t reason =
       gatts_validate_packet_format(op_code, len, p_data, &uuid, s_hdl, e_hdl);
   if (reason != GATT_SUCCESS) {
-    gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false);
+    gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false);
     return;
   }
 
   if (uuid != Uuid::From16Bit(GATT_UUID_PRI_SERVICE)) {
     if (op_code == GATT_REQ_READ_BY_GRP_TYPE) {
-      gatt_send_error_rsp(tcb, GATT_UNSUPPORT_GRP_TYPE, op_code, s_hdl, false);
+      gatt_send_error_rsp(tcb, cid, GATT_UNSUPPORT_GRP_TYPE, op_code, s_hdl,
+                          false);
       VLOG(1) << StringPrintf("unexpected ReadByGrpType Group: %s",
                               uuid.ToString().c_str());
       return;
     }
 
     // we do not support ReadByTypeValue with any non-primamry_service type
-    gatt_send_error_rsp(tcb, GATT_NOT_FOUND, op_code, s_hdl, false);
+    gatt_send_error_rsp(tcb, cid, GATT_NOT_FOUND, op_code, s_hdl, false);
     VLOG(1) << StringPrintf("unexpected ReadByTypeValue type: %s",
                             uuid.ToString().c_str());
     return;
@@ -644,22 +658,24 @@ void gatts_process_primary_service_req(tGATT_TCB& tcb, uint8_t op_code,
   Uuid value = Uuid::kEmpty;
   if (op_code == GATT_REQ_FIND_TYPE_VALUE) {
     if (!gatt_parse_uuid_from_cmd(&value, len, &p_data)) {
-      gatt_send_error_rsp(tcb, GATT_INVALID_PDU, op_code, s_hdl, false);
+      gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, op_code, s_hdl, false);
     }
   }
 
+  uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid);
+
   uint16_t msg_len =
-      (uint16_t)(sizeof(BT_HDR) + tcb.payload_size + L2CAP_MIN_OFFSET);
+      (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
   BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len);
-  reason = gatt_build_primary_service_rsp(p_msg, tcb, op_code, s_hdl, e_hdl,
-                                          p_data, value);
+  reason = gatt_build_primary_service_rsp(p_msg, tcb, cid, op_code, s_hdl,
+                                          e_hdl, p_data, value);
   if (reason != GATT_SUCCESS) {
     osi_free(p_msg);
-    gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false);
+    gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false);
     return;
   }
 
-  attp_send_sr_msg(tcb, p_msg);
+  attp_send_sr_msg(tcb, cid, p_msg);
 }
 
 /*******************************************************************************
@@ -672,17 +688,19 @@ void gatts_process_primary_service_req(tGATT_TCB& tcb, uint8_t op_code,
  * Returns          void
  *
  ******************************************************************************/
-static void gatts_process_find_info(tGATT_TCB& tcb, uint8_t op_code,
-                                    uint16_t len, uint8_t* p_data) {
+static void gatts_process_find_info(tGATT_TCB& tcb, uint16_t cid,
+                                    uint8_t op_code, uint16_t len,
+                                    uint8_t* p_data) {
   uint16_t s_hdl = 0, e_hdl = 0;
   uint8_t reason = read_handles(len, p_data, s_hdl, e_hdl);
   if (reason != GATT_SUCCESS) {
-    gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false);
+    gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false);
     return;
   }
 
+  uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid);
   uint16_t buf_len =
-      (uint16_t)(sizeof(BT_HDR) + tcb.payload_size + L2CAP_MIN_OFFSET);
+      (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
 
   BT_HDR* p_msg = (BT_HDR*)osi_calloc(buf_len);
   reason = GATT_NOT_FOUND;
@@ -691,7 +709,7 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint8_t op_code,
   *p++ = op_code + 1;
   p_msg->len = 2;
 
-  buf_len = tcb.payload_size - 2;
+  buf_len = payload_size - 2;
 
   for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info) {
     if (el.s_hdl <= e_hdl && el.e_hdl >= s_hdl) {
@@ -709,9 +727,9 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint8_t op_code,
 
   if (reason != GATT_SUCCESS) {
     osi_free(p_msg);
-    gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false);
+    gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false);
   } else
-    attp_send_sr_msg(tcb, p_msg);
+    attp_send_sr_msg(tcb, cid, p_msg);
 }
 
 /*******************************************************************************
@@ -724,17 +742,18 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint8_t op_code,
  * Returns          void
  *
  ******************************************************************************/
-static void gatts_process_mtu_req(tGATT_TCB& tcb, uint16_t len,
+static void gatts_process_mtu_req(tGATT_TCB& tcb, uint16_t cid, uint16_t len,
                                   uint8_t* p_data) {
   /* BR/EDR conenction, send error response */
-  if (tcb.att_lcid != L2CAP_ATT_CID) {
-    gatt_send_error_rsp(tcb, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, false);
+  if (cid != L2CAP_ATT_CID) {
+    gatt_send_error_rsp(tcb, cid, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0,
+                        false);
     return;
   }
 
   if (len < GATT_MTU_REQ_MIN_LEN) {
     LOG(ERROR) << "invalid MTU request PDU received.";
-    gatt_send_error_rsp(tcb, GATT_INVALID_PDU, GATT_REQ_MTU, 0, false);
+    gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, GATT_REQ_MTU, 0, false);
     return;
   }
 
@@ -757,7 +776,7 @@ static void gatts_process_mtu_req(tGATT_TCB& tcb, uint16_t len,
   tGATT_SR_MSG gatt_sr_msg;
   gatt_sr_msg.mtu = tcb.payload_size;
   BT_HDR* p_buf = attp_build_sr_msg(tcb, GATT_RSP_MTU, &gatt_sr_msg);
-  attp_send_sr_msg(tcb, p_buf);
+  attp_send_sr_msg(tcb, cid, p_buf);
 
   tGATTS_DATA gatts_data;
   gatts_data.mtu = tcb.payload_size;
@@ -787,8 +806,9 @@ static void gatts_process_mtu_req(tGATT_TCB& tcb, uint16_t len,
  * Returns          void
  *
  ******************************************************************************/
-void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint8_t op_code,
-                                    uint16_t len, uint8_t* p_data) {
+void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint16_t cid,
+                                    uint8_t op_code, uint16_t len,
+                                    uint8_t* p_data) {
   Uuid uuid = Uuid::kEmpty;
   uint16_t s_hdl = 0, e_hdl = 0, err_hdl = 0;
   tGATT_STATUS reason =
@@ -799,26 +819,28 @@ void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint8_t op_code,
     VLOG(1) << "Conformance tst: forced err rsp for ReadByType: error status="
             << +gatt_cb.err_status;
 
-    gatt_send_error_rsp(tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl,
-                        false);
+    gatt_send_error_rsp(tcb, cid, gatt_cb.err_status, gatt_cb.req_op_code,
+                        s_hdl, false);
 
     return;
   }
 #endif
 
   if (reason != GATT_SUCCESS) {
-    gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false);
+    gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false);
     return;
   }
 
-  size_t msg_len = sizeof(BT_HDR) + tcb.payload_size + L2CAP_MIN_OFFSET;
+  uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid);
+
+  size_t msg_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET;
   BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len);
   uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
 
   *p++ = op_code + 1;
   /* reserve length byte */
   p_msg->len = 2;
-  uint16_t buf_len = tcb.payload_size - 2;
+  uint16_t buf_len = payload_size - 2;
 
   reason = GATT_NOT_FOUND;
   for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info) {
@@ -827,8 +849,8 @@ void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint8_t op_code,
       gatt_sr_get_sec_info(tcb.peer_bda, tcb.transport, &sec_flag, &key_size);
 
       tGATT_STATUS ret = gatts_db_read_attr_value_by_type(
-          tcb, el.p_db, op_code, p_msg, s_hdl, e_hdl, uuid, &buf_len, sec_flag,
-          key_size, 0, &err_hdl);
+          tcb, cid, el.p_db, op_code, p_msg, s_hdl, e_hdl, uuid, &buf_len,
+          sec_flag, key_size, 0, &err_hdl);
       if (ret != GATT_NOT_FOUND) {
         reason = ret;
         if (ret == GATT_NO_RESOURCES) reason = GATT_SUCCESS;
@@ -849,20 +871,21 @@ void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint8_t op_code,
     /* in theroy BUSY is not possible(should already been checked), protected
      * check */
     if (reason != GATT_PENDING && reason != GATT_BUSY)
-      gatt_send_error_rsp(tcb, reason, op_code, s_hdl, false);
+      gatt_send_error_rsp(tcb, cid, reason, op_code, s_hdl, false);
 
     return;
   }
 
-  attp_send_sr_msg(tcb, p_msg);
+  attp_send_sr_msg(tcb, cid, p_msg);
 }
 
 /**
  * This function is called to process the write request from client.
  */
-static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
-                                    uint16_t handle, uint8_t op_code,
-                                    uint16_t len, uint8_t* p_data,
+static void gatts_process_write_req(tGATT_TCB& tcb, uint16_t cid,
+                                    tGATT_SRV_LIST_ELEM& el, uint16_t handle,
+                                    uint8_t op_code, uint16_t len,
+                                    uint8_t* p_data,
                                     bt_gatt_db_attribute_type_t gatt_type) {
   tGATTS_DATA sr_data;
   uint32_t trans_id;
@@ -878,7 +901,7 @@ static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
         LOG(ERROR) << __func__
                    << ": Prepare write request was invalid - missing offset, "
                       "sending error response";
-        gatt_send_error_rsp(tcb, GATT_INVALID_PDU, op_code, handle, false);
+        gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, op_code, handle, false);
         return;
       }
       sr_data.write_req.is_prep = true;
@@ -911,7 +934,7 @@ static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
                                        sec_flag, key_size);
 
   if (status == GATT_SUCCESS) {
-    trans_id = gatt_sr_enqueue_cmd(tcb, op_code, handle);
+    trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, handle);
     if (trans_id != 0) {
       conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, el.gatt_if);
 
@@ -941,7 +964,7 @@ static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
    * check */
   if (status != GATT_PENDING && status != GATT_BUSY &&
       (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE)) {
-    gatt_send_error_rsp(tcb, status, op_code, handle, false);
+    gatt_send_error_rsp(tcb, cid, status, op_code, handle, false);
   }
   return;
 }
@@ -949,10 +972,13 @@ static void gatts_process_write_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
 /**
  * This function is called to process the read request from client.
  */
-static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
-                                   uint8_t op_code, uint16_t handle,
-                                   uint16_t len, uint8_t* p_data) {
-  size_t buf_len = sizeof(BT_HDR) + tcb.payload_size + L2CAP_MIN_OFFSET;
+static void gatts_process_read_req(tGATT_TCB& tcb, uint16_t cid,
+                                   tGATT_SRV_LIST_ELEM& el, uint8_t op_code,
+                                   uint16_t handle, uint16_t len,
+                                   uint8_t* p_data) {
+  uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid);
+
+  size_t buf_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET;
   uint16_t offset = 0;
 
   if (op_code == GATT_REQ_READ_BLOB && len < sizeof(uint16_t)) {
@@ -960,7 +986,7 @@ static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
     LOG(ERROR) << __func__ << ": packet length=" << len
                << " too short. min=" << sizeof(uint16_t);
     android_errorWriteWithInfoLog(0x534e4554, "73172115", -1, NULL, 0);
-    gatt_send_error_rsp(tcb, GATT_INVALID_PDU, op_code, 0, false);
+    gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, op_code, 0, false);
     return;
   }
 
@@ -971,15 +997,15 @@ static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
   uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
   *p++ = op_code + 1;
   p_msg->len = 1;
-  buf_len = tcb.payload_size - 1;
+  buf_len = payload_size - 1;
 
   uint8_t sec_flag, key_size;
   gatt_sr_get_sec_info(tcb.peer_bda, tcb.transport, &sec_flag, &key_size);
 
   uint16_t value_len = 0;
   tGATT_STATUS reason = gatts_read_attr_value_by_handle(
-      tcb, el.p_db, op_code, handle, offset, p, &value_len, (uint16_t)buf_len,
-      sec_flag, key_size, 0);
+      tcb, cid, el.p_db, op_code, handle, offset, p, &value_len,
+      (uint16_t)buf_len, sec_flag, key_size, 0);
   p_msg->len += value_len;
 
   if (reason != GATT_SUCCESS) {
@@ -988,12 +1014,12 @@ static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
     /* in theory BUSY is not possible(should already been checked), protected
      * check */
     if (reason != GATT_PENDING && reason != GATT_BUSY)
-      gatt_send_error_rsp(tcb, reason, op_code, handle, false);
+      gatt_send_error_rsp(tcb, cid, reason, op_code, handle, false);
 
     return;
   }
 
-  attp_send_sr_msg(tcb, p_msg);
+  attp_send_sr_msg(tcb, cid, p_msg);
 }
 
 /*******************************************************************************
@@ -1006,8 +1032,8 @@ static void gatts_process_read_req(tGATT_TCB& tcb, tGATT_SRV_LIST_ELEM& el,
  * Returns          void
  *
  ******************************************************************************/
-void gatts_process_attribute_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
-                                 uint8_t* p_data) {
+void gatts_process_attribute_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
+                                 uint16_t len, uint8_t* p_data) {
   uint16_t handle = 0;
   uint8_t* p = p_data;
   tGATT_STATUS status = GATT_INVALID_HANDLE;
@@ -1026,8 +1052,8 @@ void gatts_process_attribute_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
     VLOG(1) << "Conformance tst: forced err rsp: error status="
             << +gatt_cb.err_status;
 
-    gatt_send_error_rsp(tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle,
-                        false);
+    gatt_send_error_rsp(tcb, cid, gatt_cb.err_status, cid, gatt_cb.req_op_code,
+                        handle, false);
 
     return;
   }
@@ -1041,14 +1067,14 @@ void gatts_process_attribute_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
             switch (op_code) {
               case GATT_REQ_READ: /* read char/char descriptor value */
               case GATT_REQ_READ_BLOB:
-                gatts_process_read_req(tcb, el, op_code, handle, len, p);
+                gatts_process_read_req(tcb, cid, el, op_code, handle, len, p);
                 break;
 
               case GATT_REQ_WRITE: /* write char/char descriptor value */
               case GATT_CMD_WRITE:
               case GATT_SIGN_CMD_WRITE:
               case GATT_REQ_PREPARE_WRITE:
-                gatts_process_write_req(tcb, el, handle, op_code, len, p,
+                gatts_process_write_req(tcb, cid, el, handle, op_code, len, p,
                                         attr.gatt_type);
                 break;
               default:
@@ -1065,7 +1091,7 @@ void gatts_process_attribute_req(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
 
   if (status != GATT_SUCCESS && op_code != GATT_CMD_WRITE &&
       op_code != GATT_SIGN_CMD_WRITE)
-    gatt_send_error_rsp(tcb, status, op_code, handle, false);
+    gatt_send_error_rsp(tcb, cid, status, op_code, handle, false);
 }
 
 /*******************************************************************************
@@ -1152,16 +1178,16 @@ static bool gatts_proc_ind_ack(tGATT_TCB& tcb, uint16_t ack_handle) {
  * Returns          void
  *
  ******************************************************************************/
-void gatts_process_value_conf(tGATT_TCB& tcb, uint8_t op_code) {
-  uint16_t handle = tcb.indicate_handle;
+void gatts_process_value_conf(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code) {
+  uint16_t handle;
 
-  alarm_cancel(tcb.conf_timer);
-  if (!GATT_HANDLE_IS_VALID(handle)) {
+  if (gatt_tcb_find_indicate_handle(tcb, cid, &handle)) {
     LOG(ERROR) << "unexpected handle value confirmation";
     return;
   }
 
-  tcb.indicate_handle = 0;
+  alarm_cancel(tcb.conf_timer);
+
   bool continue_processing = gatts_proc_ind_ack(tcb, handle);
 
   if (continue_processing) {
@@ -1169,7 +1195,7 @@ void gatts_process_value_conf(tGATT_TCB& tcb, uint8_t op_code) {
     gatts_data.handle = handle;
     for (auto& el : *gatt_cb.srv_list_info) {
       if (el.s_hdl <= handle && el.e_hdl >= handle) {
-        uint32_t trans_id = gatt_sr_enqueue_cmd(tcb, op_code, handle);
+        uint32_t trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, handle);
         uint16_t conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, el.gatt_if);
         gatt_sr_send_req_callback(conn_id, trans_id, GATTS_REQ_TYPE_CONF,
                                   &gatts_data);
@@ -1179,38 +1205,41 @@ void gatts_process_value_conf(tGATT_TCB& tcb, uint8_t op_code) {
 }
 
 /** This function is called to handle the client requests to server */
-void gatt_server_handle_client_req(tGATT_TCB& tcb, uint8_t op_code,
-                                   uint16_t len, uint8_t* p_data) {
+void gatt_server_handle_client_req(tGATT_TCB& tcb, uint16_t cid,
+                                   uint8_t op_code, uint16_t len,
+                                   uint8_t* p_data) {
   /* there is pending command, discard this one */
   if (!gatt_sr_cmd_empty(tcb) && op_code != GATT_HANDLE_VALUE_CONF) return;
 
   /* the size of the message may not be bigger than the local max PDU size*/
   /* The message has to be smaller than the agreed MTU, len does not include op
    * code */
-  if (len >= tcb.payload_size) {
+
+  uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, cid);
+  if (len >= payload_size) {
     LOG(ERROR) << StringPrintf("server receive invalid PDU size:%d pdu size:%d",
-                               len + 1, tcb.payload_size);
+                               len + 1, payload_size);
     /* for invalid request expecting response, send it now */
     if (op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE &&
         op_code != GATT_HANDLE_VALUE_CONF) {
-      gatt_send_error_rsp(tcb, GATT_INVALID_PDU, op_code, 0, false);
+      gatt_send_error_rsp(tcb, cid, GATT_INVALID_PDU, op_code, 0, false);
     }
     /* otherwise, ignore the pkt */
   } else {
     switch (op_code) {
       case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
       case GATT_REQ_FIND_TYPE_VALUE:  /* discover service by UUID */
-        gatts_process_primary_service_req(tcb, op_code, len, p_data);
+        gatts_process_primary_service_req(tcb, cid, op_code, len, p_data);
         break;
 
       case GATT_REQ_FIND_INFO: /* discover char descrptor */
-        gatts_process_find_info(tcb, op_code, len, p_data);
+        gatts_process_find_info(tcb, cid, op_code, len, p_data);
         break;
 
       case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor
                                      value */
         /* discover characteristic, discover char by UUID */
-        gatts_process_read_by_type_req(tcb, op_code, len, p_data);
+        gatts_process_read_by_type_req(tcb, cid, op_code, len, p_data);
         break;
 
       case GATT_REQ_READ: /* read char/char descriptor value */
@@ -1219,23 +1248,23 @@ void gatt_server_handle_client_req(tGATT_TCB& tcb, uint8_t op_code,
       case GATT_CMD_WRITE:
       case GATT_SIGN_CMD_WRITE:
       case GATT_REQ_PREPARE_WRITE:
-        gatts_process_attribute_req(tcb, op_code, len, p_data);
+        gatts_process_attribute_req(tcb, cid, op_code, len, p_data);
         break;
 
       case GATT_HANDLE_VALUE_CONF:
-        gatts_process_value_conf(tcb, op_code);
+        gatts_process_value_conf(tcb, cid, op_code);
         break;
 
       case GATT_REQ_MTU:
-        gatts_process_mtu_req(tcb, len, p_data);
+        gatts_process_mtu_req(tcb, cid, len, p_data);
         break;
 
       case GATT_REQ_EXEC_WRITE:
-        gatt_process_exec_write_req(tcb, op_code, len, p_data);
+        gatt_process_exec_write_req(tcb, cid, op_code, len, p_data);
         break;
 
       case GATT_REQ_READ_MULTI:
-        gatt_process_read_multi_req(tcb, op_code, len, p_data);
+        gatt_process_read_multi_req(tcb, cid, op_code, len, p_data);
         break;
 
       default:
index f06369e..c2184d0 100644 (file)
@@ -537,6 +537,19 @@ void gatt_start_rsp_timer(tGATT_CLCB* p_clcb) {
 
 /*******************************************************************************
  *
+ * Function         gatt_stop_rsp_timer
+ *
+ * Description      Stops a GATT response timer.
+ *
+ * Returns          void
+ *
+ ******************************************************************************/
+void gatt_stop_rsp_timer(tGATT_CLCB* p_clcb) {
+  alarm_cancel(p_clcb->gatt_rsp_timer_ent);
+}
+
+/*******************************************************************************
+ *
  * Function         gatt_start_conf_timer
  *
  * Description      Start a wait_for_confirmation timer.
@@ -585,7 +598,7 @@ void gatt_rsp_timeout(void* data) {
       p_clcb->retry_count < GATT_REQ_RETRY_LIMIT) {
     uint8_t rsp_code;
     LOG(WARNING) << __func__ << " retry discovery primary service";
-    if (p_clcb != gatt_cmd_dequeue(*p_clcb->p_tcb, &rsp_code)) {
+    if (p_clcb != gatt_cmd_dequeue(*p_clcb->p_tcb, p_clcb->cid, &rsp_code)) {
       LOG(ERROR) << __func__ << " command queue out of sync, disconnect";
     } else {
       p_clcb->retry_count++;
@@ -732,7 +745,7 @@ void gatt_sr_send_req_callback(uint16_t conn_id, uint32_t trans_id,
  * Returns          void
  *
  ******************************************************************************/
-tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint8_t err_code,
+tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint16_t cid, uint8_t err_code,
                                  uint8_t op_code, uint16_t handle, bool deq) {
   tGATT_STATUS status;
   BT_HDR* p_buf;
@@ -744,7 +757,7 @@ tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint8_t err_code,
 
   p_buf = attp_build_sr_msg(tcb, GATT_RSP_ERROR, &msg);
   if (p_buf != NULL) {
-    status = attp_send_sr_msg(tcb, p_buf);
+    status = attp_send_sr_msg(tcb, cid, p_buf);
   } else
     status = GATT_INSUF_RESOURCE;
 
@@ -891,6 +904,19 @@ bool gatt_is_clcb_allocated(uint16_t conn_id) {
 
 /*******************************************************************************
  *
+ * Function         gatt_tcb_is_cid_busy
+ *
+ * Description      The function check if channel with given cid is busy
+ *
+ * Returns          True when busy
+ *
+ ******************************************************************************/
+
+bool gatt_tcb_is_cid_busy(tGATT_TCB& tcb, uint16_t cid) {
+  return !tcb.cl_cmd_q.empty();
+}
+/*******************************************************************************
+ *
  * Function         gatt_clcb_alloc
  *
  * Description      The function allocates a GATT  connection link control block
@@ -915,6 +941,7 @@ tGATT_CLCB* gatt_clcb_alloc(uint16_t conn_id) {
       p_clcb->conn_id = conn_id;
       p_clcb->p_reg = p_reg;
       p_clcb->p_tcb = p_tcb;
+      p_clcb->cid = gatt_tcb_get_att_cid(*p_tcb);
       break;
     }
   }
@@ -924,6 +951,87 @@ tGATT_CLCB* gatt_clcb_alloc(uint16_t conn_id) {
 
 /*******************************************************************************
  *
+ * Function         gatt_tcb_get_cid_available_for_indication
+ *
+ * Description      This function checks if indication can be send
+ *
+ * Returns         None
+ *
+ ******************************************************************************/
+bool gatt_tcb_get_cid_available_for_indication(tGATT_TCB* p_tcb,
+                                               bool eatt_support,
+                                               uint16_t** indicated_handle_p,
+                                               uint16_t* cid_p) {
+  if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) {
+    return false;
+  }
+
+  *indicated_handle_p = &p_tcb->indicate_handle;
+  *cid_p = p_tcb->att_lcid;
+  return true;
+}
+
+/*******************************************************************************
+ *
+ * Function         gatt_tcb_find_indicate_handle
+ *
+ * Description      This function checks if indication can be send
+ *
+ * Returns          true when indication handle found, false otherwise
+ *
+ ******************************************************************************/
+bool gatt_tcb_find_indicate_handle(tGATT_TCB& tcb, uint16_t cid,
+                                   uint16_t* indicated_handle_p) {
+  if (cid == tcb.att_lcid) {
+    *indicated_handle_p = tcb.indicate_handle;
+    tcb.indicate_handle = 0;
+    return true;
+  }
+
+  return false;
+}
+
+/*******************************************************************************
+ *
+ * Function         gatt_tcb_get_att_cid
+ *
+ * Description      This function gets cid for the GATT operation
+ *
+ * Returns          Available CID
+ *
+ ******************************************************************************/
+
+uint16_t gatt_tcb_get_att_cid(tGATT_TCB& tcb) { return tcb.att_lcid; }
+
+/*******************************************************************************
+ *
+ * Function         gatt_tcb_get_payload_size_tx
+ *
+ * Description      This function gets payload size for the GATT operation
+ *
+ * Returns          Payload size for sending data
+ *
+ ******************************************************************************/
+uint16_t gatt_tcb_get_payload_size_tx(tGATT_TCB& tcb, uint16_t cid) {
+  return tcb.payload_size;
+}
+
+/*******************************************************************************
+ *
+ * Function         gatt_tcb_get_payload_size_rx
+ *
+ * Description      This function gets payload size for the GATT operation
+ *
+ * Returns          Payload size for receiving data
+ *
+ ******************************************************************************/
+
+uint16_t gatt_tcb_get_payload_size_rx(tGATT_TCB& tcb, uint16_t cid) {
+  return tcb.payload_size;
+}
+
+/*******************************************************************************
+ *
  * Function         gatt_clcb_dealloc
  *
  * Description      The function de-allocates a GATT connection link control
@@ -988,6 +1096,12 @@ void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB& tcb) {
   }
 }
 
+/* Get outstanding server command pointer by the transaction id */
+tGATT_SR_CMD* gatt_sr_get_cmd_by_trans_id(tGATT_TCB* p_tcb, uint32_t trans_id) {
+  if (p_tcb->sr_cmd.trans_id == trans_id) return &p_tcb->sr_cmd;
+
+  return nullptr;
+}
 /*******************************************************************************
  *
  * Function         gatt_sr_is_cback_cnt_zero
@@ -1033,9 +1147,11 @@ bool gatt_sr_is_prep_cnt_zero(tGATT_TCB& tcb) {
  * Returns         None
  *
  ******************************************************************************/
-void gatt_sr_reset_cback_cnt(tGATT_TCB& tcb) {
+void gatt_sr_reset_cback_cnt(tGATT_TCB& tcb, uint16_t cid) {
   for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
-    tcb.sr_cmd.cback_cnt[i] = 0;
+    if (cid == tcb.att_lcid) {
+      tcb.sr_cmd.cback_cnt[i] = 0;
+    }
   }
 }
 
@@ -1054,6 +1170,10 @@ void gatt_sr_reset_prep_cnt(tGATT_TCB& tcb) {
   }
 }
 
+/* Get pointer to server command on given cid */
+tGATT_SR_CMD* gatt_sr_get_cmd_by_cid(tGATT_TCB& tcb, uint16_t cid) {
+  return &tcb.sr_cmd;
+}
 /*******************************************************************************
  *
  * Function         gatt_sr_update_cback_cnt
@@ -1063,18 +1183,19 @@ void gatt_sr_reset_prep_cnt(tGATT_TCB& tcb) {
  * Returns           None
  *
  ******************************************************************************/
-void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, tGATT_IF gatt_if, bool is_inc,
-                              bool is_reset_first) {
+void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, uint16_t cid, tGATT_IF gatt_if,
+                              bool is_inc, bool is_reset_first) {
   uint8_t idx = ((uint8_t)gatt_if) - 1;
+  tGATT_SR_CMD* sr_cmd_p = &tcb.sr_cmd;
 
   if (is_reset_first) {
-    gatt_sr_reset_cback_cnt(tcb);
+    gatt_sr_reset_cback_cnt(tcb, cid);
   }
   if (is_inc) {
-    tcb.sr_cmd.cback_cnt[idx]++;
+    sr_cmd_p->cback_cnt[idx]++;
   } else {
-    if (tcb.sr_cmd.cback_cnt[idx]) {
-      tcb.sr_cmd.cback_cnt[idx]--;
+    if (sr_cmd_p->cback_cnt[idx]) {
+      sr_cmd_p->cback_cnt[idx]--;
     }
   }
 }
@@ -1134,23 +1255,22 @@ void gatt_cmd_enq(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, bool to_send,
   cmd.op_code = op_code;
   cmd.p_cmd = p_buf;
   cmd.p_clcb = p_clcb;
-
-  if (!to_send) {
-    // TODO: WTF why do we clear the queue here ?!
-    tcb.cl_cmd_q = std::queue<tGATT_CMD_Q>();
-  }
+  cmd.cid = p_clcb->cid;
 
   tcb.cl_cmd_q.push(cmd);
 }
 
 /** dequeue the command in the client CCB command queue */
-tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint8_t* p_op_code) {
-  if (tcb.cl_cmd_q.empty()) return nullptr;
+tGATT_CLCB* gatt_cmd_dequeue(tGATT_TCB& tcb, uint16_t cid, uint8_t* p_op_code) {
+  std::queue<tGATT_CMD_Q>* cl_cmd_q_p = &tcb.cl_cmd_q;
 
-  tGATT_CMD_Q cmd = tcb.cl_cmd_q.front();
+  if (cl_cmd_q_p->empty()) return nullptr;
+
+  tGATT_CMD_Q cmd = cl_cmd_q_p->front();
   tGATT_CLCB* p_clcb = cmd.p_clcb;
   *p_op_code = cmd.op_code;
-  tcb.cl_cmd_q.pop();
+  p_clcb->cid = cid;
+  cl_cmd_q_p->pop();
 
   return p_clcb;
 }
@@ -1227,7 +1347,7 @@ void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) {
 
   operation = p_clcb->operation;
   conn_id = p_clcb->conn_id;
-  alarm_cancel(p_clcb->gatt_rsp_timer_ent);
+  gatt_stop_rsp_timer(p_clcb);
 
   gatt_clcb_dealloc(p_clcb);
 
@@ -1255,7 +1375,7 @@ void gatt_cleanup_upon_disc(const RawAddress& bda, uint16_t reason,
     tGATT_CLCB* p_clcb = &gatt_cb.clcb[i];
     if (!p_clcb->in_use || p_clcb->p_tcb != p_tcb) continue;
 
-    alarm_cancel(p_clcb->gatt_rsp_timer_ent);
+    gatt_stop_rsp_timer(p_clcb);
     VLOG(1) << "found p_clcb conn_id=" << +p_clcb->conn_id;
     if (p_clcb->operation == GATTC_OPTYPE_NONE) {
       gatt_clcb_dealloc(p_clcb);
index a5fe4cd..d50db26 100644 (file)
@@ -68,7 +68,9 @@ tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
                               uint8_t op_code, tGATT_CL_MSG* p_msg) {
   return 0;
 }
-tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, BT_HDR* p_msg) { return 0; }
+tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_msg) {
+  return 0;
+}
 uint8_t btm_ble_read_sec_key_size(const RawAddress& bd_addr) { return 0; }
 bool BTM_GetSecurityFlagsByTransport(const RawAddress& bd_addr,
                                      uint8_t* p_sec_flags,
@@ -79,10 +81,10 @@ void gatt_act_discovery(tGATT_CLCB* p_clcb) {}
 bool gatt_disconnect(tGATT_TCB* p_tcb) { return false; }
 tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB* p_tcb) { return 0; }
 tGATT_STATUS gatts_db_read_attr_value_by_type(
-    tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp,
-    uint16_t s_handle, uint16_t e_handle, const Uuid& type, uint16_t* p_len,
-    tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id,
-    uint16_t* p_cur_handle) {
+    tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code,
+    BT_HDR* p_rsp, uint16_t s_handle, uint16_t e_handle, const Uuid& type,
+    uint16_t* p_len, tGATT_SEC_FLAG sec_flag, uint8_t key_size,
+    uint32_t trans_id, uint16_t* p_cur_handle) {
   return 0;
 }
 void gatt_set_ch_state(tGATT_TCB* p_tcb, tGATT_CH_STATE ch_state) {}
@@ -98,9 +100,10 @@ tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long,
   return GATT_SUCCESS;
 }
 tGATT_STATUS gatts_read_attr_value_by_handle(
-    tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle,
-    uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu,
-    tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id) {
+    tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, uint8_t op_code,
+    uint16_t handle, uint16_t offset, uint8_t* p_value, uint16_t* p_len,
+    uint16_t mtu, tGATT_SEC_FLAG sec_flag, uint8_t key_size,
+    uint32_t trans_id) {
   return GATT_SUCCESS;
 }
 tGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* p_db, uint8_t op_code,
@@ -176,28 +179,32 @@ class GattSrTest : public AllocationTestHarness {
 };
 
 TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_no_data) {
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, 0,
-                          nullptr, kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle,
+                          GATT_REQ_PREPARE_WRITE, 0, nullptr,
+                          kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest,
        gatts_process_write_req_request_prepare_write_max_len_no_data) {
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE,
-                          MAX_UINT16, nullptr, kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle,
+                          GATT_REQ_PREPARE_WRITE, MAX_UINT16, nullptr,
+                          kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest,
        gatts_process_write_req_request_prepare_write_zero_len_max_data) {
   uint8_t max_mem[MAX_UINT16];
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, 0,
-                          max_mem, kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle,
+                          GATT_REQ_PREPARE_WRITE, 0, max_mem,
+                          kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_typical) {
   uint8_t p_data[2] = {0x34, 0x12};
   uint16_t length = static_cast<uint16_t>(sizeof(p_data) / sizeof(p_data[0]));
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, length,
-                          p_data, kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle,
+                          GATT_REQ_PREPARE_WRITE, length, p_data,
+                          kGattCharacteristicType);
 
   CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1);
   CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if);
@@ -212,20 +219,23 @@ TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_typical) {
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_no_data) {
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, 0, nullptr,
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle,
+                          GATT_SIGN_CMD_WRITE, 0, nullptr,
                           kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest,
        gatts_process_write_req_signed_command_write_max_len_no_data) {
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, MAX_UINT16,
-                          nullptr, kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle,
+                          GATT_SIGN_CMD_WRITE, MAX_UINT16, nullptr,
+                          kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest,
        gatts_process_write_req_signed_command_write_zero_len_max_data) {
   uint8_t max_mem[MAX_UINT16];
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, 0, max_mem,
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle,
+                          GATT_SIGN_CMD_WRITE, 0, max_mem,
                           kGattCharacteristicType);
 }
 
@@ -235,8 +245,9 @@ TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_typical) {
       0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
       0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01};
   uint16_t length = static_cast<uint16_t>(sizeof(p_data) / sizeof(p_data[0]));
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, length,
-                          p_data, kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle,
+                          GATT_SIGN_CMD_WRITE, length, p_data,
+                          kGattCharacteristicType);
 
   CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1);
   CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if);
@@ -251,27 +262,27 @@ TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_typical) {
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_command_write_no_data) {
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, 0, nullptr,
-                          kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_CMD_WRITE, 0,
+                          nullptr, kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_command_write_max_len_no_data) {
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, MAX_UINT16,
-                          nullptr, kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_CMD_WRITE,
+                          MAX_UINT16, nullptr, kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_command_write_zero_len_max_data) {
   uint8_t max_mem[MAX_UINT16];
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, 0, max_mem,
-                          kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_CMD_WRITE, 0,
+                          max_mem, kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_command_write_typical) {
   uint8_t p_data[16] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
                         0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01};
   uint16_t length = static_cast<uint16_t>(sizeof(p_data) / sizeof(p_data[0]));
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, length, p_data,
-                          kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_CMD_WRITE,
+                          length, p_data, kGattCharacteristicType);
 
   CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1);
   CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if);
@@ -285,19 +296,19 @@ TEST_F(GattSrTest, gatts_process_write_req_command_write_typical) {
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_request_write_no_data) {
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, 0, nullptr,
-                          kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_REQ_WRITE, 0,
+                          nullptr, kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_request_write_max_len_no_data) {
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, MAX_UINT16,
-                          nullptr, kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_REQ_WRITE,
+                          MAX_UINT16, nullptr, kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_request_write_zero_len_max_data) {
   uint8_t max_mem[MAX_UINT16];
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, 0, max_mem,
-                          kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_REQ_WRITE, 0,
+                          max_mem, kGattCharacteristicType);
 }
 
 TEST_F(GattSrTest, gatts_process_write_req_request_write_typical) {
@@ -305,8 +316,8 @@ TEST_F(GattSrTest, gatts_process_write_req_request_write_typical) {
                         0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01};
   uint16_t length = static_cast<uint16_t>(sizeof(p_data) / sizeof(p_data[0]));
 
-  gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, length, p_data,
-                          kGattCharacteristicType);
+  gatts_process_write_req(tcb_, L2CAP_ATT_CID, el_, kHandle, GATT_REQ_WRITE,
+                          length, p_data, kGattCharacteristicType);
 
   CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1);
   CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if);