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