Home | History | Annotate | Download | only in gatt
      1 /******************************************************************************
      2  *
      3  *  Copyright 1999-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  this file contains the main GATT client functions
     22  *
     23  ******************************************************************************/
     24 
     25 #include "bt_target.h"
     26 
     27 #include <string.h>
     28 #include "bt_common.h"
     29 #include "bt_utils.h"
     30 #include "gatt_int.h"
     31 #include "l2c_int.h"
     32 #include "log/log.h"
     33 #include "osi/include/osi.h"
     34 
     35 #define GATT_WRITE_LONG_HDR_SIZE 5 /* 1 opcode + 2 handle + 2 offset */
     36 #define GATT_READ_CHAR_VALUE_HDL (GATT_READ_CHAR_VALUE | 0x80)
     37 #define GATT_READ_INC_SRV_UUID128 (GATT_DISC_INC_SRVC | 0x90)
     38 
     39 #define GATT_PREP_WRITE_RSP_MIN_LEN 4
     40 #define GATT_NOTIFICATION_MIN_LEN 2
     41 #define GATT_WRITE_RSP_MIN_LEN 2
     42 #define GATT_INFO_RSP_MIN_LEN 1
     43 #define GATT_MTU_RSP_MIN_LEN 2
     44 #define GATT_READ_BY_TYPE_RSP_MIN_LEN 1
     45 
     46 using base::StringPrintf;
     47 using bluetooth::Uuid;
     48 
     49 /*******************************************************************************
     50  *                      G L O B A L      G A T T       D A T A                 *
     51  ******************************************************************************/
     52 void gatt_send_prepare_write(tGATT_TCB& tcb, tGATT_CLCB* p_clcb);
     53 
     54 uint8_t disc_type_to_att_opcode[GATT_DISC_MAX] = {
     55     0,
     56     GATT_REQ_READ_BY_GRP_TYPE, /*  GATT_DISC_SRVC_ALL = 1, */
     57     GATT_REQ_FIND_TYPE_VALUE,  /*  GATT_DISC_SRVC_BY_UUID,  */
     58     GATT_REQ_READ_BY_TYPE,     /*  GATT_DISC_INC_SRVC,      */
     59     GATT_REQ_READ_BY_TYPE,     /*  GATT_DISC_CHAR,          */
     60     GATT_REQ_FIND_INFO         /*  GATT_DISC_CHAR_DSCPT,    */
     61 };
     62 
     63 uint16_t disc_type_to_uuid[GATT_DISC_MAX] = {
     64     0,                         /* reserved */
     65     GATT_UUID_PRI_SERVICE,     /* <service> DISC_SRVC_ALL */
     66     GATT_UUID_PRI_SERVICE,     /* <service> for DISC_SERVC_BY_UUID */
     67     GATT_UUID_INCLUDE_SERVICE, /* <include_service> for DISC_INC_SRVC */
     68     GATT_UUID_CHAR_DECLARE,    /* <characteristic> for DISC_CHAR */
     69     0                          /* no type filtering for DISC_CHAR_DSCPT */
     70 };
     71 
     72 /*******************************************************************************
     73  *
     74  * Function         gatt_act_discovery
     75  *
     76  * Description      GATT discovery operation.
     77  *
     78  * Returns          void.
     79  *
     80  ******************************************************************************/
     81 void gatt_act_discovery(tGATT_CLCB* p_clcb) {
     82   uint8_t op_code = disc_type_to_att_opcode[p_clcb->op_subtype];
     83 
     84   if (p_clcb->s_handle > p_clcb->e_handle || p_clcb->s_handle == 0) {
     85     /* end of handle range */
     86     gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
     87     return;
     88   }
     89 
     90   tGATT_CL_MSG cl_req;
     91   memset(&cl_req, 0, sizeof(tGATT_CL_MSG));
     92 
     93   cl_req.browse.s_handle = p_clcb->s_handle;
     94   cl_req.browse.e_handle = p_clcb->e_handle;
     95 
     96   if (disc_type_to_uuid[p_clcb->op_subtype] != 0) {
     97     cl_req.browse.uuid =
     98         bluetooth::Uuid::From16Bit(disc_type_to_uuid[p_clcb->op_subtype]);
     99   }
    100 
    101   if (p_clcb->op_subtype ==
    102       GATT_DISC_SRVC_BY_UUID) /* fill in the FindByTypeValue request info*/
    103   {
    104     cl_req.find_type_value.uuid =
    105         bluetooth::Uuid::From16Bit(disc_type_to_uuid[p_clcb->op_subtype]);
    106     cl_req.find_type_value.s_handle = p_clcb->s_handle;
    107     cl_req.find_type_value.e_handle = p_clcb->e_handle;
    108 
    109     size_t size = p_clcb->uuid.GetShortestRepresentationSize();
    110     cl_req.find_type_value.value_len = size;
    111     if (size == Uuid::kNumBytes16) {
    112       uint8_t* p = cl_req.find_type_value.value;
    113       UINT16_TO_STREAM(p, p_clcb->uuid.As16Bit());
    114     } else if (size == Uuid::kNumBytes32) {
    115       /* if service type is 32 bits UUID, convert it now */
    116       memcpy(cl_req.find_type_value.value, p_clcb->uuid.To128BitLE().data(),
    117             Uuid::kNumBytes128);
    118       cl_req.find_type_value.value_len = Uuid::kNumBytes128;
    119     } else
    120       memcpy(cl_req.find_type_value.value, p_clcb->uuid.To128BitLE().data(),
    121              size);
    122   }
    123 
    124   tGATT_STATUS st = attp_send_cl_msg(*p_clcb->p_tcb, p_clcb, op_code, &cl_req);
    125   if (st != GATT_SUCCESS && st != GATT_CMD_STARTED) {
    126     gatt_end_operation(p_clcb, GATT_ERROR, NULL);
    127   }
    128 }
    129 
    130 /*******************************************************************************
    131  *
    132  * Function         gatt_act_read
    133  *
    134  * Description      GATT read operation.
    135  *
    136  * Returns          void.
    137  *
    138  ******************************************************************************/
    139 void gatt_act_read(tGATT_CLCB* p_clcb, uint16_t offset) {
    140   tGATT_TCB& tcb = *p_clcb->p_tcb;
    141   uint8_t rt = GATT_INTERNAL_ERROR;
    142   tGATT_CL_MSG msg;
    143   uint8_t op_code = 0;
    144 
    145   memset(&msg, 0, sizeof(tGATT_CL_MSG));
    146 
    147   switch (p_clcb->op_subtype) {
    148     case GATT_READ_CHAR_VALUE:
    149     case GATT_READ_BY_TYPE:
    150       op_code = GATT_REQ_READ_BY_TYPE;
    151       msg.browse.s_handle = p_clcb->s_handle;
    152       msg.browse.e_handle = p_clcb->e_handle;
    153       if (p_clcb->op_subtype == GATT_READ_BY_TYPE)
    154         msg.browse.uuid = p_clcb->uuid;
    155       else {
    156         msg.browse.uuid = bluetooth::Uuid::From16Bit(GATT_UUID_CHAR_DECLARE);
    157       }
    158       break;
    159 
    160     case GATT_READ_CHAR_VALUE_HDL:
    161     case GATT_READ_BY_HANDLE:
    162       if (!p_clcb->counter) {
    163         op_code = GATT_REQ_READ;
    164         msg.handle = p_clcb->s_handle;
    165       } else {
    166         if (!p_clcb->first_read_blob_after_read)
    167           p_clcb->first_read_blob_after_read = true;
    168         else
    169           p_clcb->first_read_blob_after_read = false;
    170 
    171         VLOG(1) << __func__ << ": first_read_blob_after_read="
    172                 << p_clcb->first_read_blob_after_read;
    173         op_code = GATT_REQ_READ_BLOB;
    174         msg.read_blob.offset = offset;
    175         msg.read_blob.handle = p_clcb->s_handle;
    176       }
    177       p_clcb->op_subtype &= ~0x80;
    178       break;
    179 
    180     case GATT_READ_PARTIAL:
    181       op_code = GATT_REQ_READ_BLOB;
    182       msg.read_blob.handle = p_clcb->s_handle;
    183       msg.read_blob.offset = offset;
    184       break;
    185 
    186     case GATT_READ_MULTIPLE:
    187       op_code = GATT_REQ_READ_MULTI;
    188       memcpy(&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI));
    189       break;
    190 
    191     case GATT_READ_INC_SRV_UUID128:
    192       op_code = GATT_REQ_READ;
    193       msg.handle = p_clcb->s_handle;
    194       p_clcb->op_subtype &= ~0x90;
    195       break;
    196 
    197     default:
    198       LOG(ERROR) << "Unknown read type:" << +p_clcb->op_subtype;
    199       break;
    200   }
    201 
    202   if (op_code != 0) rt = attp_send_cl_msg(tcb, p_clcb, op_code, &msg);
    203 
    204   if (op_code == 0 || (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED)) {
    205     gatt_end_operation(p_clcb, rt, NULL);
    206   }
    207 }
    208 
    209 /** GATT write operation */
    210 void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act) {
    211   tGATT_TCB& tcb = *p_clcb->p_tcb;
    212 
    213   CHECK(p_clcb->p_attr_buf);
    214   tGATT_VALUE& attr = *((tGATT_VALUE*)p_clcb->p_attr_buf);
    215 
    216   switch (p_clcb->op_subtype) {
    217     case GATT_WRITE_NO_RSP: {
    218       p_clcb->s_handle = attr.handle;
    219       uint8_t op_code = (sec_act == GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE
    220                                                         : GATT_CMD_WRITE;
    221       uint8_t rt = gatt_send_write_msg(tcb, p_clcb, op_code, attr.handle,
    222                                        attr.len, 0, attr.value);
    223       if (rt != GATT_CMD_STARTED) {
    224         if (rt != GATT_SUCCESS) {
    225           LOG(ERROR) << StringPrintf(
    226               "gatt_act_write() failed op_code=0x%x rt=%d", op_code, rt);
    227         }
    228         gatt_end_operation(p_clcb, rt, NULL);
    229       }
    230       return;
    231     }
    232 
    233     case GATT_WRITE: {
    234       if (attr.len <= (tcb.payload_size - GATT_HDR_SIZE)) {
    235         p_clcb->s_handle = attr.handle;
    236 
    237         uint8_t rt = gatt_send_write_msg(tcb, p_clcb, GATT_REQ_WRITE,
    238                                          attr.handle, attr.len, 0, attr.value);
    239         if (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED &&
    240             rt != GATT_CONGESTED) {
    241           if (rt != GATT_SUCCESS) {
    242             LOG(ERROR) << StringPrintf(
    243                 "gatt_act_write() failed op_code=0x%x rt=%d", GATT_REQ_WRITE,
    244                 rt);
    245           }
    246           gatt_end_operation(p_clcb, rt, NULL);
    247         }
    248 
    249       } else {
    250         /* prepare write for long attribute */
    251         gatt_send_prepare_write(tcb, p_clcb);
    252       }
    253       return;
    254     }
    255 
    256     case GATT_WRITE_PREPARE:
    257       gatt_send_prepare_write(tcb, p_clcb);
    258       return;
    259 
    260     default:
    261       CHECK(false) << "Unknown write type" << p_clcb->op_subtype;
    262       return;
    263   }
    264 }
    265 /*******************************************************************************
    266  *
    267  * Function         gatt_send_queue_write_cancel
    268  *
    269  * Description      send queue write cancel
    270  *
    271  * Returns          void.
    272  *
    273  ******************************************************************************/
    274 void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    275                                   tGATT_EXEC_FLAG flag) {
    276   uint8_t rt;
    277 
    278   VLOG(1) << __func__;
    279 
    280   tGATT_CL_MSG gatt_cl_msg;
    281   gatt_cl_msg.exec_write = flag;
    282   rt = attp_send_cl_msg(tcb, p_clcb, GATT_REQ_EXEC_WRITE, &gatt_cl_msg);
    283 
    284   if (rt != GATT_SUCCESS) {
    285     gatt_end_operation(p_clcb, rt, NULL);
    286   }
    287 }
    288 /*******************************************************************************
    289  *
    290  * Function         gatt_check_write_long_terminate
    291  *
    292  * Description      To terminate write long or not.
    293  *
    294  * Returns          true: write long is terminated; false keep sending.
    295  *
    296  ******************************************************************************/
    297 bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    298                                      tGATT_VALUE* p_rsp_value) {
    299   tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
    300   bool exec = false;
    301   tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC;
    302 
    303   VLOG(1) << __func__;
    304   /* check the first write response status */
    305   if (p_rsp_value != NULL) {
    306     if (p_rsp_value->handle != p_attr->handle ||
    307         p_rsp_value->len != p_clcb->counter ||
    308         memcmp(p_rsp_value->value, p_attr->value + p_attr->offset,
    309                p_rsp_value->len)) {
    310       /* data does not match    */
    311       p_clcb->status = GATT_ERROR;
    312       flag = GATT_PREP_WRITE_CANCEL;
    313       exec = true;
    314     } else /* response checking is good */
    315     {
    316       p_clcb->status = GATT_SUCCESS;
    317       /* update write offset and check if end of attribute value */
    318       if ((p_attr->offset += p_rsp_value->len) >= p_attr->len) exec = true;
    319     }
    320   }
    321   if (exec) {
    322     gatt_send_queue_write_cancel(tcb, p_clcb, flag);
    323     return true;
    324   }
    325   return false;
    326 }
    327 
    328 /** Send prepare write */
    329 void gatt_send_prepare_write(tGATT_TCB& tcb, tGATT_CLCB* p_clcb) {
    330   tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
    331   uint8_t type = p_clcb->op_subtype;
    332 
    333   VLOG(1) << __func__ << StringPrintf(" type=0x%x", type);
    334   uint16_t to_send = p_attr->len - p_attr->offset;
    335 
    336   if (to_send > (tcb.payload_size -
    337                  GATT_WRITE_LONG_HDR_SIZE)) /* 2 = uint16_t offset bytes  */
    338     to_send = tcb.payload_size - GATT_WRITE_LONG_HDR_SIZE;
    339 
    340   p_clcb->s_handle = p_attr->handle;
    341 
    342   uint16_t offset = p_attr->offset;
    343   if (type == GATT_WRITE_PREPARE) {
    344     offset += p_clcb->start_offset;
    345   }
    346 
    347   VLOG(1) << StringPrintf("offset =0x%x len=%d", offset, to_send);
    348 
    349   uint8_t rt = gatt_send_write_msg(tcb, p_clcb, GATT_REQ_PREPARE_WRITE,
    350                                    p_attr->handle, to_send, /* length */
    351                                    offset,                  /* used as offset */
    352                                    p_attr->value + p_attr->offset); /* data */
    353 
    354   /* remember the write long attribute length */
    355   p_clcb->counter = to_send;
    356 
    357   if (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED && rt != GATT_CONGESTED) {
    358     gatt_end_operation(p_clcb, rt, NULL);
    359   }
    360 }
    361 
    362 /*******************************************************************************
    363  *
    364  * Function         gatt_process_find_type_value_rsp
    365  *
    366  * Description      This function handles the find by type value response.
    367  *
    368  *
    369  * Returns          void
    370  *
    371  ******************************************************************************/
    372 void gatt_process_find_type_value_rsp(UNUSED_ATTR tGATT_TCB& tcb,
    373                                       tGATT_CLCB* p_clcb, uint16_t len,
    374                                       uint8_t* p_data) {
    375   tGATT_DISC_RES result;
    376   uint8_t* p = p_data;
    377 
    378   VLOG(1) << __func__;
    379   /* unexpected response */
    380   if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY ||
    381       p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
    382     return;
    383 
    384   memset(&result, 0, sizeof(tGATT_DISC_RES));
    385   result.type = bluetooth::Uuid::From16Bit(GATT_UUID_PRI_SERVICE);
    386 
    387   /* returns a series of handle ranges */
    388   while (len >= 4) {
    389     STREAM_TO_UINT16(result.handle, p);
    390     STREAM_TO_UINT16(result.value.group_value.e_handle, p);
    391     result.value.group_value.service_type = p_clcb->uuid;
    392 
    393     len -= 4;
    394 
    395     if (p_clcb->p_reg->app_cb.p_disc_res_cb)
    396       (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
    397                                              p_clcb->op_subtype, &result);
    398   }
    399 
    400   /* last handle  + 1 */
    401   p_clcb->s_handle = (result.value.group_value.e_handle == 0)
    402                          ? 0
    403                          : (result.value.group_value.e_handle + 1);
    404   /* initiate another request */
    405   gatt_act_discovery(p_clcb);
    406 }
    407 /*******************************************************************************
    408  *
    409  * Function         gatt_process_read_info_rsp
    410  *
    411  * Description      This function is called to handle the read information
    412  *                  response.
    413  *
    414  *
    415  * Returns          void
    416  *
    417  ******************************************************************************/
    418 void gatt_process_read_info_rsp(UNUSED_ATTR tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    419                                 UNUSED_ATTR uint8_t op_code, uint16_t len,
    420                                 uint8_t* p_data) {
    421   tGATT_DISC_RES result;
    422   uint8_t *p = p_data, uuid_len = 0, type;
    423 
    424   if (len < GATT_INFO_RSP_MIN_LEN) {
    425     LOG(ERROR) << "invalid Info Response PDU received, discard.";
    426     gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
    427     return;
    428   }
    429   /* unexpected response */
    430   if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY ||
    431       p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT)
    432     return;
    433 
    434   STREAM_TO_UINT8(type, p);
    435   len -= 1;
    436 
    437   if (type == GATT_INFO_TYPE_PAIR_16)
    438     uuid_len = Uuid::kNumBytes16;
    439   else if (type == GATT_INFO_TYPE_PAIR_128)
    440     uuid_len = Uuid::kNumBytes128;
    441 
    442   while (len >= uuid_len + 2) {
    443     STREAM_TO_UINT16(result.handle, p);
    444 
    445     if (uuid_len > 0) {
    446       if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p)) break;
    447     } else
    448       result.type = p_clcb->uuid;
    449 
    450     len -= (uuid_len + 2);
    451 
    452     if (p_clcb->p_reg->app_cb.p_disc_res_cb)
    453       (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
    454                                              p_clcb->op_subtype, &result);
    455   }
    456 
    457   p_clcb->s_handle = (result.handle == 0) ? 0 : (result.handle + 1);
    458   /* initiate another request */
    459   gatt_act_discovery(p_clcb);
    460 }
    461 /*******************************************************************************
    462  *
    463  * Function         gatt_proc_disc_error_rsp
    464  *
    465  * Description      Process the read by type response and send another request
    466  *                  if needed.
    467  *
    468  * Returns          void.
    469  *
    470  ******************************************************************************/
    471 void gatt_proc_disc_error_rsp(UNUSED_ATTR tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    472                               uint8_t opcode, UNUSED_ATTR uint16_t handle,
    473                               uint8_t reason) {
    474   tGATT_STATUS status = (tGATT_STATUS)reason;
    475 
    476   VLOG(1) << __func__
    477           << StringPrintf("reason: %02x cmd_code %04x", reason, opcode);
    478 
    479   switch (opcode) {
    480     case GATT_REQ_READ_BY_GRP_TYPE:
    481     case GATT_REQ_FIND_TYPE_VALUE:
    482     case GATT_REQ_READ_BY_TYPE:
    483     case GATT_REQ_FIND_INFO:
    484       if (reason == GATT_NOT_FOUND) {
    485         status = GATT_SUCCESS;
    486         VLOG(1) << "Discovery completed";
    487       }
    488       break;
    489     default:
    490       LOG(ERROR) << StringPrintf("Incorrect discovery opcode %04x", opcode);
    491       break;
    492   }
    493 
    494   gatt_end_operation(p_clcb, status, NULL);
    495 }
    496 
    497 /*******************************************************************************
    498  *
    499  * Function         gatt_process_error_rsp
    500  *
    501  * Description      This function is called to handle the error response
    502  *
    503  *
    504  * Returns          void
    505  *
    506  ******************************************************************************/
    507 void gatt_process_error_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    508                             UNUSED_ATTR uint8_t op_code,
    509                             UNUSED_ATTR uint16_t len, uint8_t* p_data) {
    510   uint8_t opcode, reason, *p = p_data;
    511   uint16_t handle;
    512   tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
    513 
    514   VLOG(1) << __func__;
    515 
    516   if (len < 4) {
    517     android_errorWriteLog(0x534e4554, "79591688");
    518     LOG(ERROR) << "Error response too short";
    519     // Specification does not clearly define what should happen if error
    520     // response is too short. General rule in BT Spec 5.0 Vol 3, Part F 3.4.1.1
    521     // is: "If an error code is received in the Error Response that is not
    522     // understood by the client, for example an error code that was reserved for
    523     // future use that is now being used in a future version of this
    524     // specification, then the Error Response shall still be considered to state
    525     // that the given request cannot be performed for an unknown reason."
    526     opcode = handle = 0;
    527     reason = 0x7F;
    528   } else {
    529     STREAM_TO_UINT8(opcode, p);
    530     STREAM_TO_UINT16(handle, p);
    531     STREAM_TO_UINT8(reason, p);
    532   }
    533 
    534   if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) {
    535     gatt_proc_disc_error_rsp(tcb, p_clcb, opcode, handle, reason);
    536   } else {
    537     if ((p_clcb->operation == GATTC_OPTYPE_WRITE) &&
    538         (p_clcb->op_subtype == GATT_WRITE) &&
    539         (opcode == GATT_REQ_PREPARE_WRITE) && (p_attr) &&
    540         (handle == p_attr->handle)) {
    541       p_clcb->status = reason;
    542       gatt_send_queue_write_cancel(tcb, p_clcb, GATT_PREP_WRITE_CANCEL);
    543     } else if ((p_clcb->operation == GATTC_OPTYPE_READ) &&
    544                ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) ||
    545                 (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) &&
    546                (opcode == GATT_REQ_READ_BLOB) &&
    547                p_clcb->first_read_blob_after_read &&
    548                (reason == GATT_NOT_LONG)) {
    549       gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p_clcb->p_attr_buf);
    550     } else
    551       gatt_end_operation(p_clcb, reason, NULL);
    552   }
    553 }
    554 /*******************************************************************************
    555  *
    556  * Function         gatt_process_prep_write_rsp
    557  *
    558  * Description      This function is called to handle the read response
    559  *
    560  *
    561  * Returns          void
    562  *
    563  ******************************************************************************/
    564 void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    565                                  uint8_t op_code, uint16_t len,
    566                                  uint8_t* p_data) {
    567   uint8_t* p = p_data;
    568 
    569   tGATT_VALUE value = {
    570       .conn_id = p_clcb->conn_id, .auth_req = GATT_AUTH_REQ_NONE,
    571   };
    572 
    573   LOG(ERROR) << StringPrintf("value resp op_code = %s len = %d",
    574                              gatt_dbg_op_name(op_code), len);
    575 
    576   if (len < GATT_PREP_WRITE_RSP_MIN_LEN) {
    577     LOG(ERROR) << "illegal prepare write response length, discard";
    578     gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
    579     return;
    580   }
    581 
    582   STREAM_TO_UINT16(value.handle, p);
    583   STREAM_TO_UINT16(value.offset, p);
    584 
    585   value.len = len - 4;
    586 
    587   memcpy(value.value, p, value.len);
    588 
    589   if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
    590     p_clcb->status = GATT_SUCCESS;
    591     /* application should verify handle offset
    592        and value are matched or not */
    593 
    594     gatt_end_operation(p_clcb, p_clcb->status, &value);
    595   } else if (p_clcb->op_subtype == GATT_WRITE) {
    596     if (!gatt_check_write_long_terminate(tcb, p_clcb, &value))
    597       gatt_send_prepare_write(tcb, p_clcb);
    598   }
    599 }
    600 /*******************************************************************************
    601  *
    602  * Function         gatt_process_notification
    603  *
    604  * Description      Handle the handle value indication/notification.
    605  *
    606  * Returns          void
    607  *
    608  ******************************************************************************/
    609 void gatt_process_notification(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
    610                                uint8_t* p_data) {
    611   tGATT_VALUE value;
    612   tGATT_REG* p_reg;
    613   uint16_t conn_id;
    614   tGATT_STATUS encrypt_status;
    615   uint8_t* p = p_data;
    616   uint8_t i;
    617   uint8_t event = (op_code == GATT_HANDLE_VALUE_NOTIF)
    618                       ? GATTC_OPTYPE_NOTIFICATION
    619                       : GATTC_OPTYPE_INDICATION;
    620 
    621   VLOG(1) << __func__;
    622 
    623   if (len < GATT_NOTIFICATION_MIN_LEN) {
    624     LOG(ERROR) << "illegal notification PDU length, discard";
    625     return;
    626   }
    627 
    628   memset(&value, 0, sizeof(value));
    629   STREAM_TO_UINT16(value.handle, p);
    630   value.len = len - 2;
    631   memcpy(value.value, p, value.len);
    632 
    633   if (!GATT_HANDLE_IS_VALID(value.handle)) {
    634     /* illegal handle, send ack now */
    635     if (op_code == GATT_HANDLE_VALUE_IND)
    636       attp_send_cl_msg(tcb, nullptr, GATT_HANDLE_VALUE_CONF, NULL);
    637     return;
    638   }
    639 
    640   if (event == GATTC_OPTYPE_INDICATION) {
    641     if (tcb.ind_count) {
    642       /* this is an error case that receiving an indication but we
    643          still has an indication not being acked yet.
    644          For now, just log the error reset the counter.
    645          Later we need to disconnect the link unconditionally.
    646       */
    647       LOG(ERROR) << __func__ << " rcv Ind. but ind_count=" << tcb.ind_count
    648                  << " (will reset ind_count)";
    649     }
    650     tcb.ind_count = 0;
    651   }
    652 
    653   /* should notify all registered client with the handle value
    654      notificaion/indication
    655      Note: need to do the indication count and start timer first then do
    656      callback
    657    */
    658 
    659   for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
    660     if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb &&
    661         (event == GATTC_OPTYPE_INDICATION))
    662       tcb.ind_count++;
    663   }
    664 
    665   if (event == GATTC_OPTYPE_INDICATION) {
    666     /* start a timer for app confirmation */
    667     if (tcb.ind_count > 0)
    668       gatt_start_ind_ack_timer(tcb);
    669     else /* no app to indicate, or invalid handle */
    670       attp_send_cl_msg(tcb, nullptr, GATT_HANDLE_VALUE_CONF, NULL);
    671   }
    672 
    673   encrypt_status = gatt_get_link_encrypt_status(tcb);
    674   tGATT_CL_COMPLETE gatt_cl_complete;
    675   gatt_cl_complete.att_value = value;
    676   for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
    677     if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
    678       conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, p_reg->gatt_if);
    679       (*p_reg->app_cb.p_cmpl_cb)(conn_id, event, encrypt_status,
    680                                  &gatt_cl_complete);
    681     }
    682   }
    683 }
    684 
    685 /*******************************************************************************
    686  *
    687  * Function         gatt_process_read_by_type_rsp
    688  *
    689  * Description      This function is called to handle the read by type response.
    690  *                  read by type can be used for discovery, or read by type or
    691  *                  read characteristic value.
    692  *
    693  * Returns          void
    694  *
    695  ******************************************************************************/
    696 void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    697                                    uint8_t op_code, uint16_t len,
    698                                    uint8_t* p_data) {
    699   tGATT_DISC_RES result;
    700   tGATT_DISC_VALUE record_value;
    701   uint8_t *p = p_data, value_len, handle_len = 2;
    702   uint16_t handle = 0;
    703 
    704   /* discovery procedure and no callback function registered */
    705   if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) &&
    706       (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
    707     return;
    708 
    709   if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN) {
    710     LOG(ERROR) << "Illegal ReadByType/ReadByGroupType Response length, discard";
    711     gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
    712     return;
    713   }
    714 
    715   STREAM_TO_UINT8(value_len, p);
    716 
    717   if ((value_len > (tcb.payload_size - 2)) || (value_len > (len - 1))) {
    718     /* this is an error case that server's response containing a value length
    719        which is larger than MTU-2
    720        or value_len > message total length -1 */
    721     LOG(ERROR) << __func__
    722                << StringPrintf(
    723                       ": Discard response op_code=%d "
    724                       "vale_len=%d > (MTU-2=%d or msg_len-1=%d)",
    725                       op_code, value_len, (tcb.payload_size - 2), (len - 1));
    726     gatt_end_operation(p_clcb, GATT_ERROR, NULL);
    727     return;
    728   }
    729 
    730   if (op_code == GATT_RSP_READ_BY_GRP_TYPE) handle_len = 4;
    731 
    732   value_len -= handle_len; /* substract the handle pairs bytes */
    733   len -= 1;
    734 
    735   while (len >= (handle_len + value_len)) {
    736     STREAM_TO_UINT16(handle, p);
    737 
    738     if (!GATT_HANDLE_IS_VALID(handle)) {
    739       gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
    740       return;
    741     }
    742 
    743     memset(&result, 0, sizeof(tGATT_DISC_RES));
    744     memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
    745 
    746     result.handle = handle;
    747     result.type =
    748         bluetooth::Uuid::From16Bit(disc_type_to_uuid[p_clcb->op_subtype]);
    749 
    750     /* discover all services */
    751     if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
    752         p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
    753         op_code == GATT_RSP_READ_BY_GRP_TYPE) {
    754       STREAM_TO_UINT16(handle, p);
    755 
    756       if (!GATT_HANDLE_IS_VALID(handle)) {
    757         gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
    758         return;
    759       } else {
    760         record_value.group_value.e_handle = handle;
    761         if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type,
    762                                       value_len, &p)) {
    763           LOG(ERROR) << "discover all service response parsing failure";
    764           break;
    765         }
    766       }
    767     }
    768     /* discover included service */
    769     else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
    770              p_clcb->op_subtype == GATT_DISC_INC_SRVC) {
    771       STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
    772       STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
    773 
    774       if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
    775           !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle)) {
    776         gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
    777         return;
    778       }
    779 
    780       if (value_len == 6) {
    781         uint16_t tmp;
    782         STREAM_TO_UINT16(tmp, p);
    783         record_value.incl_service.service_type =
    784             bluetooth::Uuid::From16Bit(tmp);
    785       } else if (value_len == 4) {
    786         p_clcb->s_handle = record_value.incl_service.s_handle;
    787         p_clcb->read_uuid128.wait_for_read_rsp = true;
    788         p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
    789         memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
    790         memcpy(&p_clcb->read_uuid128.result.value, &record_value,
    791                sizeof(result.value));
    792         p_clcb->op_subtype |= 0x90;
    793         gatt_act_read(p_clcb, 0);
    794         return;
    795       } else {
    796         LOG(ERROR) << __func__
    797                    << ": INCL_SRVC failed with invalid data value_len="
    798                    << +value_len;
    799         gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void*)p);
    800         return;
    801       }
    802     }
    803     /* read by type */
    804     else if (p_clcb->operation == GATTC_OPTYPE_READ &&
    805              p_clcb->op_subtype == GATT_READ_BY_TYPE) {
    806       p_clcb->counter = len - 2;
    807       p_clcb->s_handle = handle;
    808       if (p_clcb->counter == (p_clcb->p_tcb->payload_size - 4)) {
    809         p_clcb->op_subtype = GATT_READ_BY_HANDLE;
    810         if (!p_clcb->p_attr_buf)
    811           p_clcb->p_attr_buf = (uint8_t*)osi_malloc(GATT_MAX_ATTR_LEN);
    812         if (p_clcb->counter <= GATT_MAX_ATTR_LEN) {
    813           memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
    814           gatt_act_read(p_clcb, p_clcb->counter);
    815         } else {
    816           gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void*)p);
    817         }
    818       } else {
    819         gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p);
    820       }
    821       return;
    822     } else /* discover characterisitic */
    823     {
    824       STREAM_TO_UINT8(record_value.dclr_value.char_prop, p);
    825       STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
    826       if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle)) {
    827         gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
    828         return;
    829       }
    830       if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid,
    831                                     (uint16_t)(value_len - 3), &p)) {
    832         gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
    833         /* invalid format, and skip the result */
    834         return;
    835       }
    836 
    837       /* UUID not matching */
    838       if (!p_clcb->uuid.IsEmpty() &&
    839           !record_value.dclr_value.char_uuid.IsEmpty() &&
    840           record_value.dclr_value.char_uuid != p_clcb->uuid) {
    841         len -= (value_len + 2);
    842         continue; /* skip the result, and look for next one */
    843       }
    844 
    845       if (p_clcb->operation == GATTC_OPTYPE_READ)
    846       /* UUID match for read characteristic value */
    847       {
    848         /* only read the first matching UUID characteristic value, and
    849           discard the rest results */
    850         p_clcb->s_handle = record_value.dclr_value.val_handle;
    851         p_clcb->op_subtype |= 0x80;
    852         gatt_act_read(p_clcb, 0);
    853         return;
    854       }
    855     }
    856     len -= (value_len + handle_len);
    857 
    858     /* result is (handle, 16bits UUID) pairs */
    859     memcpy(&result.value, &record_value, sizeof(result.value));
    860 
    861     /* send callback if is discover procedure */
    862     if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
    863         p_clcb->p_reg->app_cb.p_disc_res_cb)
    864       (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
    865                                              p_clcb->op_subtype, &result);
    866   }
    867 
    868   p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
    869 
    870   if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) {
    871     /* initiate another request */
    872     gatt_act_discovery(p_clcb);
    873   } else /* read characteristic value */
    874   {
    875     gatt_act_read(p_clcb, 0);
    876   }
    877 }
    878 
    879 /*******************************************************************************
    880  *
    881  * Function         gatt_process_read_rsp
    882  *
    883  * Description      This function is called to handle the read BLOB response
    884  *
    885  *
    886  * Returns          void
    887  *
    888  ******************************************************************************/
    889 void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    890                            UNUSED_ATTR uint8_t op_code, uint16_t len,
    891                            uint8_t* p_data) {
    892   uint16_t offset = p_clcb->counter;
    893   uint8_t* p = p_data;
    894 
    895   if (p_clcb->operation == GATTC_OPTYPE_READ) {
    896     if (p_clcb->op_subtype != GATT_READ_BY_HANDLE) {
    897       p_clcb->counter = len;
    898       gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p);
    899     } else {
    900       /* allocate GKI buffer holding up long attribute value  */
    901       if (!p_clcb->p_attr_buf)
    902         p_clcb->p_attr_buf = (uint8_t*)osi_malloc(GATT_MAX_ATTR_LEN);
    903 
    904       /* copy attrobute value into cb buffer  */
    905       if (offset < GATT_MAX_ATTR_LEN) {
    906         if ((len + offset) > GATT_MAX_ATTR_LEN)
    907           len = GATT_MAX_ATTR_LEN - offset;
    908 
    909         p_clcb->counter += len;
    910 
    911         memcpy(p_clcb->p_attr_buf + offset, p, len);
    912 
    913         /* send next request if needed  */
    914 
    915         if (len == (tcb.payload_size -
    916                     1) && /* full packet for read or read blob rsp */
    917             len + offset < GATT_MAX_ATTR_LEN) {
    918           VLOG(1) << StringPrintf(
    919               "full pkt issue read blob for remianing bytes old offset=%d "
    920               "len=%d new offset=%d",
    921               offset, len, p_clcb->counter);
    922           gatt_act_read(p_clcb, p_clcb->counter);
    923         } else /* end of request, send callback */
    924         {
    925           gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p_clcb->p_attr_buf);
    926         }
    927       } else /* exception, should not happen */
    928       {
    929         LOG(ERROR) << "attr offset = " << +offset
    930                    << " p_attr_buf = " << p_clcb->p_attr_buf;
    931         gatt_end_operation(p_clcb, GATT_NO_RESOURCES,
    932                            (void*)p_clcb->p_attr_buf);
    933       }
    934     }
    935   } else {
    936     if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
    937         p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
    938         p_clcb->read_uuid128.wait_for_read_rsp) {
    939       p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
    940       p_clcb->read_uuid128.wait_for_read_rsp = false;
    941       if (len == Uuid::kNumBytes128) {
    942         p_clcb->read_uuid128.result.value.incl_service.service_type =
    943             bluetooth::Uuid::From128BitLE(p);
    944         if (p_clcb->p_reg->app_cb.p_disc_res_cb)
    945           (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
    946                                                  p_clcb->op_subtype,
    947                                                  &p_clcb->read_uuid128.result);
    948         gatt_act_discovery(p_clcb);
    949       } else {
    950         gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void*)p);
    951       }
    952     }
    953   }
    954 }
    955 
    956 /*******************************************************************************
    957  *
    958  * Function         gatt_process_handle_rsp
    959  *
    960  * Description      This function is called to handle the write response
    961  *
    962  *
    963  * Returns          void
    964  *
    965  ******************************************************************************/
    966 void gatt_process_handle_rsp(tGATT_CLCB* p_clcb) {
    967   gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
    968 }
    969 /*******************************************************************************
    970  *
    971  * Function         gatt_process_mtu_rsp
    972  *
    973  * Description      Process the configure MTU response.
    974  *
    975  *
    976  * Returns          void
    977  *
    978  ******************************************************************************/
    979 void gatt_process_mtu_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint16_t len,
    980                           uint8_t* p_data) {
    981   uint16_t mtu;
    982   tGATT_STATUS status = GATT_SUCCESS;
    983 
    984   if (len < GATT_MTU_RSP_MIN_LEN) {
    985     LOG(ERROR) << "invalid MTU response PDU received, discard.";
    986     status = GATT_INVALID_PDU;
    987   } else {
    988     STREAM_TO_UINT16(mtu, p_data);
    989 
    990     if (mtu < tcb.payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
    991       tcb.payload_size = mtu;
    992   }
    993 
    994   l2cble_set_fixed_channel_tx_data_length(tcb.peer_bda, L2CAP_ATT_CID,
    995                                           tcb.payload_size);
    996   gatt_end_operation(p_clcb, status, NULL);
    997 }
    998 /*******************************************************************************
    999  *
   1000  * Function         gatt_cmd_to_rsp_code
   1001  *
   1002  * Description      Convert an ATT command op code into the corresponding
   1003  *                  response code assume no error occurs.
   1004  *
   1005  * Returns          response code.
   1006  *
   1007  ******************************************************************************/
   1008 uint8_t gatt_cmd_to_rsp_code(uint8_t cmd_code) {
   1009   uint8_t rsp_code = 0;
   1010 
   1011   if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE) {
   1012     rsp_code = cmd_code + 1;
   1013   }
   1014   return rsp_code;
   1015 }
   1016 
   1017 /** Find next command in queue and sent to server */
   1018 bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) {
   1019   while (!tcb.cl_cmd_q.empty()) {
   1020     tGATT_CMD_Q& cmd = tcb.cl_cmd_q.front();
   1021     if (!cmd.to_send || cmd.p_cmd == NULL) return false;
   1022 
   1023     tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, cmd.p_cmd);
   1024     if (att_ret != GATT_SUCCESS && att_ret != GATT_CONGESTED) {
   1025       LOG(ERROR) << __func__ << ": L2CAP sent error";
   1026       tcb.cl_cmd_q.pop();
   1027       continue;
   1028     }
   1029 
   1030     cmd.to_send = false;
   1031     cmd.p_cmd = NULL;
   1032 
   1033     if (cmd.op_code == GATT_CMD_WRITE || cmd.op_code == GATT_SIGN_CMD_WRITE) {
   1034       /* dequeue the request if is write command or sign write */
   1035       uint8_t rsp_code;
   1036       tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &rsp_code);
   1037 
   1038       /* send command complete callback here */
   1039       gatt_end_operation(p_clcb, att_ret, NULL);
   1040 
   1041       /* if no ack needed, keep sending */
   1042       if (att_ret == GATT_SUCCESS) continue;
   1043 
   1044       return true;
   1045     }
   1046 
   1047     gatt_start_rsp_timer(cmd.p_clcb);
   1048     return true;
   1049   }
   1050 
   1051   return false;
   1052 }
   1053 
   1054 /** This function is called to handle the server response to client */
   1055 void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code,
   1056                                    uint16_t len, uint8_t* p_data) {
   1057   if (op_code == GATT_HANDLE_VALUE_IND || op_code == GATT_HANDLE_VALUE_NOTIF) {
   1058     if (len >= tcb.payload_size) {
   1059       LOG(ERROR) << StringPrintf(
   1060           "%s: invalid indicate pkt size: %d, PDU size: %d", __func__, len + 1,
   1061           tcb.payload_size);
   1062       return;
   1063     }
   1064 
   1065     gatt_process_notification(tcb, op_code, len, p_data);
   1066     return;
   1067   }
   1068 
   1069   uint8_t cmd_code = 0;
   1070   tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &cmd_code);
   1071   uint8_t rsp_code = gatt_cmd_to_rsp_code(cmd_code);
   1072   if (!p_clcb || (rsp_code != op_code && op_code != GATT_RSP_ERROR)) {
   1073     LOG(WARNING) << StringPrintf(
   1074         "ATT - Ignore wrong response. Receives (%02x) Request(%02x) Ignored",
   1075         op_code, rsp_code);
   1076     return;
   1077   }
   1078 
   1079   if (!p_clcb->in_use) {
   1080     LOG(WARNING) << "ATT - clcb already not in use, ignoring response";
   1081     gatt_cl_send_next_cmd_inq(tcb);
   1082     return;
   1083   }
   1084 
   1085   alarm_cancel(p_clcb->gatt_rsp_timer_ent);
   1086   p_clcb->retry_count = 0;
   1087 
   1088   /* the size of the message may not be bigger than the local max PDU size*/
   1089   /* The message has to be smaller than the agreed MTU, len does not count
   1090    * op_code */
   1091   if (len >= tcb.payload_size) {
   1092     LOG(ERROR) << StringPrintf(
   1093         "%s: invalid response pkt size: %d, PDU size: %d", __func__, len + 1,
   1094         tcb.payload_size);
   1095     gatt_end_operation(p_clcb, GATT_ERROR, NULL);
   1096   } else {
   1097     switch (op_code) {
   1098       case GATT_RSP_ERROR:
   1099         gatt_process_error_rsp(tcb, p_clcb, op_code, len, p_data);
   1100         break;
   1101 
   1102       case GATT_RSP_MTU: /* 2 bytes mtu */
   1103         gatt_process_mtu_rsp(tcb, p_clcb, len, p_data);
   1104         break;
   1105 
   1106       case GATT_RSP_FIND_INFO:
   1107         gatt_process_read_info_rsp(tcb, p_clcb, op_code, len, p_data);
   1108         break;
   1109 
   1110       case GATT_RSP_READ_BY_TYPE:
   1111       case GATT_RSP_READ_BY_GRP_TYPE:
   1112         gatt_process_read_by_type_rsp(tcb, p_clcb, op_code, len, p_data);
   1113         break;
   1114 
   1115       case GATT_RSP_READ:
   1116       case GATT_RSP_READ_BLOB:
   1117       case GATT_RSP_READ_MULTI:
   1118         gatt_process_read_rsp(tcb, p_clcb, op_code, len, p_data);
   1119         break;
   1120 
   1121       case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
   1122         gatt_process_find_type_value_rsp(tcb, p_clcb, len, p_data);
   1123         break;
   1124 
   1125       case GATT_RSP_WRITE:
   1126         gatt_process_handle_rsp(p_clcb);
   1127         break;
   1128 
   1129       case GATT_RSP_PREPARE_WRITE:
   1130         gatt_process_prep_write_rsp(tcb, p_clcb, op_code, len, p_data);
   1131         break;
   1132 
   1133       case GATT_RSP_EXEC_WRITE:
   1134         gatt_end_operation(p_clcb, p_clcb->status, NULL);
   1135         break;
   1136 
   1137       default:
   1138         LOG(ERROR) << __func__ << ": Unknown opcode = " << std::hex << op_code;
   1139         break;
   1140     }
   1141   }
   1142 
   1143   gatt_cl_send_next_cmd_inq(tcb);
   1144 }
   1145