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 ******************************************************************************/
gatt_act_discovery(tGATT_CLCB * p_clcb)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 ******************************************************************************/
gatt_act_read(tGATT_CLCB * p_clcb,uint16_t offset)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 */
gatt_act_write(tGATT_CLCB * p_clcb,uint8_t sec_act)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 ******************************************************************************/
gatt_send_queue_write_cancel(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,tGATT_EXEC_FLAG flag)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 ******************************************************************************/
gatt_check_write_long_terminate(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,tGATT_VALUE * p_rsp_value)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 */
gatt_send_prepare_write(tGATT_TCB & tcb,tGATT_CLCB * p_clcb)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 ******************************************************************************/
gatt_process_find_type_value_rsp(UNUSED_ATTR tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint16_t len,uint8_t * p_data)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 ******************************************************************************/
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)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 ******************************************************************************/
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)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 ******************************************************************************/
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)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 ******************************************************************************/
gatt_process_prep_write_rsp(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint8_t op_code,uint16_t len,uint8_t * p_data)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 ******************************************************************************/
gatt_process_notification(tGATT_TCB & tcb,uint8_t op_code,uint16_t len,uint8_t * p_data)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 ******************************************************************************/
gatt_process_read_by_type_rsp(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint8_t op_code,uint16_t len,uint8_t * p_data)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 if (value_len < 4) {
772 android_errorWriteLog(0x534e4554, "158833854");
773 LOG(ERROR) << __func__ << " Illegal Response length, must be at least 4.";
774 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
775 return;
776 }
777 STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
778 STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
779
780 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
781 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle)) {
782 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
783 return;
784 }
785
786 if (value_len == 6) {
787 uint16_t tmp;
788 STREAM_TO_UINT16(tmp, p);
789 record_value.incl_service.service_type =
790 bluetooth::Uuid::From16Bit(tmp);
791 } else if (value_len == 4) {
792 p_clcb->s_handle = record_value.incl_service.s_handle;
793 p_clcb->read_uuid128.wait_for_read_rsp = true;
794 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
795 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
796 memcpy(&p_clcb->read_uuid128.result.value, &record_value,
797 sizeof(result.value));
798 p_clcb->op_subtype |= 0x90;
799 gatt_act_read(p_clcb, 0);
800 return;
801 } else {
802 LOG(ERROR) << __func__
803 << ": INCL_SRVC failed with invalid data value_len="
804 << +value_len;
805 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void*)p);
806 return;
807 }
808 }
809 /* read by type */
810 else if (p_clcb->operation == GATTC_OPTYPE_READ &&
811 p_clcb->op_subtype == GATT_READ_BY_TYPE) {
812 p_clcb->counter = len - 2;
813 p_clcb->s_handle = handle;
814 if (p_clcb->counter == (p_clcb->p_tcb->payload_size - 4)) {
815 p_clcb->op_subtype = GATT_READ_BY_HANDLE;
816 if (!p_clcb->p_attr_buf)
817 p_clcb->p_attr_buf = (uint8_t*)osi_malloc(GATT_MAX_ATTR_LEN);
818 if (p_clcb->counter <= GATT_MAX_ATTR_LEN) {
819 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
820 gatt_act_read(p_clcb, p_clcb->counter);
821 } else {
822 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void*)p);
823 }
824 } else {
825 gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p);
826 }
827 return;
828 } else /* discover characterisitic */
829 {
830 if (value_len < 3) {
831 android_errorWriteLog(0x534e4554, "158778659");
832 LOG(ERROR) << __func__ << " Illegal Response length, must be at least 3.";
833 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
834 return;
835 }
836 STREAM_TO_UINT8(record_value.dclr_value.char_prop, p);
837 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
838 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle)) {
839 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
840 return;
841 }
842 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid,
843 (uint16_t)(value_len - 3), &p)) {
844 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
845 /* invalid format, and skip the result */
846 return;
847 }
848
849 /* UUID not matching */
850 if (!p_clcb->uuid.IsEmpty() &&
851 !record_value.dclr_value.char_uuid.IsEmpty() &&
852 record_value.dclr_value.char_uuid != p_clcb->uuid) {
853 len -= (value_len + 2);
854 continue; /* skip the result, and look for next one */
855 }
856
857 if (p_clcb->operation == GATTC_OPTYPE_READ)
858 /* UUID match for read characteristic value */
859 {
860 /* only read the first matching UUID characteristic value, and
861 discard the rest results */
862 p_clcb->s_handle = record_value.dclr_value.val_handle;
863 p_clcb->op_subtype |= 0x80;
864 gatt_act_read(p_clcb, 0);
865 return;
866 }
867 }
868 len -= (value_len + handle_len);
869
870 /* result is (handle, 16bits UUID) pairs */
871 memcpy(&result.value, &record_value, sizeof(result.value));
872
873 /* send callback if is discover procedure */
874 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
875 p_clcb->p_reg->app_cb.p_disc_res_cb)
876 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
877 p_clcb->op_subtype, &result);
878 }
879
880 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
881
882 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) {
883 /* initiate another request */
884 gatt_act_discovery(p_clcb);
885 } else /* read characteristic value */
886 {
887 gatt_act_read(p_clcb, 0);
888 }
889 }
890
891 /*******************************************************************************
892 *
893 * Function gatt_process_read_rsp
894 *
895 * Description This function is called to handle the read BLOB response
896 *
897 *
898 * Returns void
899 *
900 ******************************************************************************/
gatt_process_read_rsp(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,UNUSED_ATTR uint8_t op_code,uint16_t len,uint8_t * p_data)901 void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
902 UNUSED_ATTR uint8_t op_code, uint16_t len,
903 uint8_t* p_data) {
904 uint16_t offset = p_clcb->counter;
905 uint8_t* p = p_data;
906
907 if (p_clcb->operation == GATTC_OPTYPE_READ) {
908 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE) {
909 p_clcb->counter = len;
910 gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p);
911 } else {
912 /* allocate GKI buffer holding up long attribute value */
913 if (!p_clcb->p_attr_buf)
914 p_clcb->p_attr_buf = (uint8_t*)osi_malloc(GATT_MAX_ATTR_LEN);
915
916 /* copy attrobute value into cb buffer */
917 if (offset < GATT_MAX_ATTR_LEN) {
918 if ((len + offset) > GATT_MAX_ATTR_LEN)
919 len = GATT_MAX_ATTR_LEN - offset;
920
921 p_clcb->counter += len;
922
923 memcpy(p_clcb->p_attr_buf + offset, p, len);
924
925 /* send next request if needed */
926
927 if (len == (tcb.payload_size -
928 1) && /* full packet for read or read blob rsp */
929 len + offset < GATT_MAX_ATTR_LEN) {
930 VLOG(1) << StringPrintf(
931 "full pkt issue read blob for remianing bytes old offset=%d "
932 "len=%d new offset=%d",
933 offset, len, p_clcb->counter);
934 gatt_act_read(p_clcb, p_clcb->counter);
935 } else /* end of request, send callback */
936 {
937 gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p_clcb->p_attr_buf);
938 }
939 } else /* exception, should not happen */
940 {
941 LOG(ERROR) << "attr offset = " << +offset
942 << " p_attr_buf = " << p_clcb->p_attr_buf;
943 gatt_end_operation(p_clcb, GATT_NO_RESOURCES,
944 (void*)p_clcb->p_attr_buf);
945 }
946 }
947 } else {
948 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
949 p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
950 p_clcb->read_uuid128.wait_for_read_rsp) {
951 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
952 p_clcb->read_uuid128.wait_for_read_rsp = false;
953 if (len == Uuid::kNumBytes128) {
954 p_clcb->read_uuid128.result.value.incl_service.service_type =
955 bluetooth::Uuid::From128BitLE(p);
956 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
957 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
958 p_clcb->op_subtype,
959 &p_clcb->read_uuid128.result);
960 gatt_act_discovery(p_clcb);
961 } else {
962 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void*)p);
963 }
964 }
965 }
966 }
967
968 /*******************************************************************************
969 *
970 * Function gatt_process_handle_rsp
971 *
972 * Description This function is called to handle the write response
973 *
974 *
975 * Returns void
976 *
977 ******************************************************************************/
gatt_process_handle_rsp(tGATT_CLCB * p_clcb)978 void gatt_process_handle_rsp(tGATT_CLCB* p_clcb) {
979 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
980 }
981 /*******************************************************************************
982 *
983 * Function gatt_process_mtu_rsp
984 *
985 * Description Process the configure MTU response.
986 *
987 *
988 * Returns void
989 *
990 ******************************************************************************/
gatt_process_mtu_rsp(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint16_t len,uint8_t * p_data)991 void gatt_process_mtu_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint16_t len,
992 uint8_t* p_data) {
993 uint16_t mtu;
994 tGATT_STATUS status = GATT_SUCCESS;
995
996 if (len < GATT_MTU_RSP_MIN_LEN) {
997 LOG(ERROR) << "invalid MTU response PDU received, discard.";
998 status = GATT_INVALID_PDU;
999 } else {
1000 STREAM_TO_UINT16(mtu, p_data);
1001
1002 if (mtu < tcb.payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
1003 tcb.payload_size = mtu;
1004 }
1005
1006 l2cble_set_fixed_channel_tx_data_length(tcb.peer_bda, L2CAP_ATT_CID,
1007 tcb.payload_size);
1008 gatt_end_operation(p_clcb, status, NULL);
1009 }
1010 /*******************************************************************************
1011 *
1012 * Function gatt_cmd_to_rsp_code
1013 *
1014 * Description Convert an ATT command op code into the corresponding
1015 * response code assume no error occurs.
1016 *
1017 * Returns response code.
1018 *
1019 ******************************************************************************/
gatt_cmd_to_rsp_code(uint8_t cmd_code)1020 uint8_t gatt_cmd_to_rsp_code(uint8_t cmd_code) {
1021 uint8_t rsp_code = 0;
1022
1023 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE) {
1024 rsp_code = cmd_code + 1;
1025 }
1026 return rsp_code;
1027 }
1028
1029 /** Find next command in queue and sent to server */
gatt_cl_send_next_cmd_inq(tGATT_TCB & tcb)1030 bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) {
1031 while (!tcb.cl_cmd_q.empty()) {
1032 tGATT_CMD_Q& cmd = tcb.cl_cmd_q.front();
1033 if (!cmd.to_send || cmd.p_cmd == NULL) return false;
1034
1035 tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, cmd.p_cmd);
1036 if (att_ret != GATT_SUCCESS && att_ret != GATT_CONGESTED) {
1037 LOG(ERROR) << __func__ << ": L2CAP sent error";
1038 tcb.cl_cmd_q.pop();
1039 continue;
1040 }
1041
1042 cmd.to_send = false;
1043 cmd.p_cmd = NULL;
1044
1045 if (cmd.op_code == GATT_CMD_WRITE || cmd.op_code == GATT_SIGN_CMD_WRITE) {
1046 /* dequeue the request if is write command or sign write */
1047 uint8_t rsp_code;
1048 tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &rsp_code);
1049
1050 /* send command complete callback here */
1051 gatt_end_operation(p_clcb, att_ret, NULL);
1052
1053 /* if no ack needed, keep sending */
1054 if (att_ret == GATT_SUCCESS) continue;
1055
1056 return true;
1057 }
1058
1059 gatt_start_rsp_timer(cmd.p_clcb);
1060 return true;
1061 }
1062
1063 return false;
1064 }
1065
1066 /** 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)1067 void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code,
1068 uint16_t len, uint8_t* p_data) {
1069 if (op_code == GATT_HANDLE_VALUE_IND || op_code == GATT_HANDLE_VALUE_NOTIF) {
1070 if (len >= tcb.payload_size) {
1071 LOG(ERROR) << StringPrintf(
1072 "%s: invalid indicate pkt size: %d, PDU size: %d", __func__, len + 1,
1073 tcb.payload_size);
1074 return;
1075 }
1076
1077 gatt_process_notification(tcb, op_code, len, p_data);
1078 return;
1079 }
1080
1081 uint8_t cmd_code = 0;
1082 tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &cmd_code);
1083 uint8_t rsp_code = gatt_cmd_to_rsp_code(cmd_code);
1084 if (!p_clcb || (rsp_code != op_code && op_code != GATT_RSP_ERROR)) {
1085 LOG(WARNING) << StringPrintf(
1086 "ATT - Ignore wrong response. Receives (%02x) Request(%02x) Ignored",
1087 op_code, rsp_code);
1088 return;
1089 }
1090
1091 if (!p_clcb->in_use) {
1092 LOG(WARNING) << "ATT - clcb already not in use, ignoring response";
1093 gatt_cl_send_next_cmd_inq(tcb);
1094 return;
1095 }
1096
1097 alarm_cancel(p_clcb->gatt_rsp_timer_ent);
1098 p_clcb->retry_count = 0;
1099
1100 /* the size of the message may not be bigger than the local max PDU size*/
1101 /* The message has to be smaller than the agreed MTU, len does not count
1102 * op_code */
1103 if (len >= tcb.payload_size) {
1104 LOG(ERROR) << StringPrintf(
1105 "%s: invalid response pkt size: %d, PDU size: %d", __func__, len + 1,
1106 tcb.payload_size);
1107 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1108 } else {
1109 switch (op_code) {
1110 case GATT_RSP_ERROR:
1111 gatt_process_error_rsp(tcb, p_clcb, op_code, len, p_data);
1112 break;
1113
1114 case GATT_RSP_MTU: /* 2 bytes mtu */
1115 gatt_process_mtu_rsp(tcb, p_clcb, len, p_data);
1116 break;
1117
1118 case GATT_RSP_FIND_INFO:
1119 gatt_process_read_info_rsp(tcb, p_clcb, op_code, len, p_data);
1120 break;
1121
1122 case GATT_RSP_READ_BY_TYPE:
1123 case GATT_RSP_READ_BY_GRP_TYPE:
1124 gatt_process_read_by_type_rsp(tcb, p_clcb, op_code, len, p_data);
1125 break;
1126
1127 case GATT_RSP_READ:
1128 case GATT_RSP_READ_BLOB:
1129 case GATT_RSP_READ_MULTI:
1130 gatt_process_read_rsp(tcb, p_clcb, op_code, len, p_data);
1131 break;
1132
1133 case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
1134 gatt_process_find_type_value_rsp(tcb, p_clcb, len, p_data);
1135 break;
1136
1137 case GATT_RSP_WRITE:
1138 gatt_process_handle_rsp(p_clcb);
1139 break;
1140
1141 case GATT_RSP_PREPARE_WRITE:
1142 gatt_process_prep_write_rsp(tcb, p_clcb, op_code, len, p_data);
1143 break;
1144
1145 case GATT_RSP_EXEC_WRITE:
1146 gatt_end_operation(p_clcb, p_clcb->status, NULL);
1147 break;
1148
1149 default:
1150 LOG(ERROR) << __func__ << ": Unknown opcode = " << std::hex << op_code;
1151 break;
1152 }
1153 }
1154
1155 gatt_cl_send_next_cmd_inq(tcb);
1156 }
1157