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 terminate = 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 terminate = 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) terminate = true;
319 }
320 }
321 if (terminate && p_clcb->op_subtype != GATT_WRITE_PREPARE) {
322 gatt_send_queue_write_cancel(tcb, p_clcb, flag);
323 }
324 return terminate;
325 }
326
327 /** Send prepare write */
gatt_send_prepare_write(tGATT_TCB & tcb,tGATT_CLCB * p_clcb)328 void gatt_send_prepare_write(tGATT_TCB& tcb, tGATT_CLCB* p_clcb) {
329 tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
330 uint8_t type = p_clcb->op_subtype;
331
332 VLOG(1) << __func__ << StringPrintf(" type=0x%x", type);
333 uint16_t to_send = p_attr->len - p_attr->offset;
334
335 if (to_send > (tcb.payload_size -
336 GATT_WRITE_LONG_HDR_SIZE)) /* 2 = uint16_t offset bytes */
337 to_send = tcb.payload_size - GATT_WRITE_LONG_HDR_SIZE;
338
339 p_clcb->s_handle = p_attr->handle;
340
341 uint16_t offset = p_attr->offset;
342 if (type == GATT_WRITE_PREPARE) {
343 offset += p_clcb->start_offset;
344 }
345
346 VLOG(1) << StringPrintf("offset =0x%x len=%d", offset, to_send);
347
348 uint8_t rt = gatt_send_write_msg(tcb, p_clcb, GATT_REQ_PREPARE_WRITE,
349 p_attr->handle, to_send, /* length */
350 offset, /* used as offset */
351 p_attr->value + p_attr->offset); /* data */
352
353 /* remember the write long attribute length */
354 p_clcb->counter = to_send;
355
356 if (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED && rt != GATT_CONGESTED) {
357 gatt_end_operation(p_clcb, rt, NULL);
358 }
359 }
360
361 /*******************************************************************************
362 *
363 * Function gatt_process_find_type_value_rsp
364 *
365 * Description This function handles the find by type value response.
366 *
367 *
368 * Returns void
369 *
370 ******************************************************************************/
gatt_process_find_type_value_rsp(UNUSED_ATTR tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint16_t len,uint8_t * p_data)371 void gatt_process_find_type_value_rsp(UNUSED_ATTR tGATT_TCB& tcb,
372 tGATT_CLCB* p_clcb, uint16_t len,
373 uint8_t* p_data) {
374 tGATT_DISC_RES result;
375 uint8_t* p = p_data;
376
377 VLOG(1) << __func__;
378 /* unexpected response */
379 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY ||
380 p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
381 return;
382
383 memset(&result, 0, sizeof(tGATT_DISC_RES));
384 result.type = bluetooth::Uuid::From16Bit(GATT_UUID_PRI_SERVICE);
385
386 /* returns a series of handle ranges */
387 while (len >= 4) {
388 STREAM_TO_UINT16(result.handle, p);
389 STREAM_TO_UINT16(result.value.group_value.e_handle, p);
390 result.value.group_value.service_type = p_clcb->uuid;
391
392 len -= 4;
393
394 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
395 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
396 p_clcb->op_subtype, &result);
397 }
398
399 /* last handle + 1 */
400 p_clcb->s_handle = (result.value.group_value.e_handle == 0)
401 ? 0
402 : (result.value.group_value.e_handle + 1);
403 /* initiate another request */
404 gatt_act_discovery(p_clcb);
405 }
406 /*******************************************************************************
407 *
408 * Function gatt_process_read_info_rsp
409 *
410 * Description This function is called to handle the read information
411 * response.
412 *
413 *
414 * Returns void
415 *
416 ******************************************************************************/
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)417 void gatt_process_read_info_rsp(UNUSED_ATTR tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
418 UNUSED_ATTR uint8_t op_code, uint16_t len,
419 uint8_t* p_data) {
420 tGATT_DISC_RES result;
421 uint8_t *p = p_data, uuid_len = 0, type;
422
423 if (len < GATT_INFO_RSP_MIN_LEN) {
424 LOG(ERROR) << "invalid Info Response PDU received, discard.";
425 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
426 return;
427 }
428 /* unexpected response */
429 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY ||
430 p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT)
431 return;
432
433 STREAM_TO_UINT8(type, p);
434 len -= 1;
435
436 if (type == GATT_INFO_TYPE_PAIR_16)
437 uuid_len = Uuid::kNumBytes16;
438 else if (type == GATT_INFO_TYPE_PAIR_128)
439 uuid_len = Uuid::kNumBytes128;
440
441 while (len >= uuid_len + 2) {
442 STREAM_TO_UINT16(result.handle, p);
443
444 if (uuid_len > 0) {
445 if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p)) break;
446 } else
447 result.type = p_clcb->uuid;
448
449 len -= (uuid_len + 2);
450
451 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
452 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
453 p_clcb->op_subtype, &result);
454 }
455
456 p_clcb->s_handle = (result.handle == 0) ? 0 : (result.handle + 1);
457 /* initiate another request */
458 gatt_act_discovery(p_clcb);
459 }
460 /*******************************************************************************
461 *
462 * Function gatt_proc_disc_error_rsp
463 *
464 * Description Process the read by type response and send another request
465 * if needed.
466 *
467 * Returns void.
468 *
469 ******************************************************************************/
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)470 void gatt_proc_disc_error_rsp(UNUSED_ATTR tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
471 uint8_t opcode, UNUSED_ATTR uint16_t handle,
472 uint8_t reason) {
473 tGATT_STATUS status = (tGATT_STATUS)reason;
474
475 VLOG(1) << __func__
476 << StringPrintf("reason: %02x cmd_code %04x", reason, opcode);
477
478 switch (opcode) {
479 case GATT_REQ_READ_BY_GRP_TYPE:
480 case GATT_REQ_FIND_TYPE_VALUE:
481 case GATT_REQ_READ_BY_TYPE:
482 case GATT_REQ_FIND_INFO:
483 if (reason == GATT_NOT_FOUND) {
484 status = GATT_SUCCESS;
485 VLOG(1) << "Discovery completed";
486 }
487 break;
488 default:
489 LOG(ERROR) << StringPrintf("Incorrect discovery opcode %04x", opcode);
490 break;
491 }
492
493 gatt_end_operation(p_clcb, status, NULL);
494 }
495
496 /*******************************************************************************
497 *
498 * Function gatt_process_error_rsp
499 *
500 * Description This function is called to handle the error response
501 *
502 *
503 * Returns void
504 *
505 ******************************************************************************/
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)506 void gatt_process_error_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
507 UNUSED_ATTR uint8_t op_code,
508 UNUSED_ATTR uint16_t len, uint8_t* p_data) {
509 uint8_t opcode, reason, *p = p_data;
510 uint16_t handle;
511 tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
512
513 VLOG(1) << __func__;
514
515 if (len < 4) {
516 android_errorWriteLog(0x534e4554, "79591688");
517 LOG(ERROR) << "Error response too short";
518 // Specification does not clearly define what should happen if error
519 // response is too short. General rule in BT Spec 5.0 Vol 3, Part F 3.4.1.1
520 // is: "If an error code is received in the Error Response that is not
521 // understood by the client, for example an error code that was reserved for
522 // future use that is now being used in a future version of this
523 // specification, then the Error Response shall still be considered to state
524 // that the given request cannot be performed for an unknown reason."
525 opcode = handle = 0;
526 reason = 0x7F;
527 } else {
528 STREAM_TO_UINT8(opcode, p);
529 STREAM_TO_UINT16(handle, p);
530 STREAM_TO_UINT8(reason, p);
531 }
532
533 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) {
534 gatt_proc_disc_error_rsp(tcb, p_clcb, opcode, handle, reason);
535 } else {
536 if ((p_clcb->operation == GATTC_OPTYPE_WRITE) &&
537 (p_clcb->op_subtype == GATT_WRITE) &&
538 (opcode == GATT_REQ_PREPARE_WRITE) && (p_attr) &&
539 (handle == p_attr->handle)) {
540 p_clcb->status = reason;
541 gatt_send_queue_write_cancel(tcb, p_clcb, GATT_PREP_WRITE_CANCEL);
542 } else if ((p_clcb->operation == GATTC_OPTYPE_READ) &&
543 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) ||
544 (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) &&
545 (opcode == GATT_REQ_READ_BLOB) &&
546 p_clcb->first_read_blob_after_read &&
547 (reason == GATT_NOT_LONG)) {
548 gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p_clcb->p_attr_buf);
549 } else
550 gatt_end_operation(p_clcb, reason, NULL);
551 }
552 }
553 /*******************************************************************************
554 *
555 * Function gatt_process_prep_write_rsp
556 *
557 * Description This function is called to handle the read response
558 *
559 *
560 * Returns void
561 *
562 ******************************************************************************/
gatt_process_prep_write_rsp(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint8_t op_code,uint16_t len,uint8_t * p_data)563 void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
564 uint8_t op_code, uint16_t len,
565 uint8_t* p_data) {
566 uint8_t* p = p_data;
567
568 tGATT_VALUE value = {
569 .conn_id = p_clcb->conn_id, .auth_req = GATT_AUTH_REQ_NONE,
570 };
571
572 LOG(ERROR) << StringPrintf("value resp op_code = %s len = %d",
573 gatt_dbg_op_name(op_code), len);
574
575 if (len < GATT_PREP_WRITE_RSP_MIN_LEN) {
576 LOG(ERROR) << "illegal prepare write response length, discard";
577 gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
578 return;
579 }
580
581 STREAM_TO_UINT16(value.handle, p);
582 STREAM_TO_UINT16(value.offset, p);
583
584 value.len = len - 4;
585
586 memcpy(value.value, p, value.len);
587
588 if (!gatt_check_write_long_terminate(tcb, p_clcb, &value)) {
589 gatt_send_prepare_write(tcb, p_clcb);
590 return;
591 }
592
593 if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
594 /* application should verify handle offset
595 and value are matched or not */
596 gatt_end_operation(p_clcb, p_clcb->status, &value);
597 }
598 }
599 /*******************************************************************************
600 *
601 * Function gatt_process_notification
602 *
603 * Description Handle the handle value indication/notification.
604 *
605 * Returns void
606 *
607 ******************************************************************************/
gatt_process_notification(tGATT_TCB & tcb,uint8_t op_code,uint16_t len,uint8_t * p_data)608 void gatt_process_notification(tGATT_TCB& tcb, uint8_t op_code, uint16_t len,
609 uint8_t* p_data) {
610 tGATT_VALUE value;
611 tGATT_REG* p_reg;
612 uint16_t conn_id;
613 tGATT_STATUS encrypt_status;
614 uint8_t* p = p_data;
615 uint8_t i;
616 uint8_t event = (op_code == GATT_HANDLE_VALUE_NOTIF)
617 ? GATTC_OPTYPE_NOTIFICATION
618 : GATTC_OPTYPE_INDICATION;
619
620 VLOG(1) << __func__;
621
622 if (len < GATT_NOTIFICATION_MIN_LEN) {
623 LOG(ERROR) << "illegal notification PDU length, discard";
624 return;
625 }
626
627 memset(&value, 0, sizeof(value));
628 STREAM_TO_UINT16(value.handle, p);
629 value.len = len - 2;
630 if (value.len > GATT_MAX_ATTR_LEN) {
631 LOG(ERROR) << "value.len larger than GATT_MAX_ATTR_LEN, discard";
632 return;
633 }
634 memcpy(value.value, p, value.len);
635
636 if (!GATT_HANDLE_IS_VALID(value.handle)) {
637 /* illegal handle, send ack now */
638 if (op_code == GATT_HANDLE_VALUE_IND)
639 attp_send_cl_msg(tcb, nullptr, GATT_HANDLE_VALUE_CONF, NULL);
640 return;
641 }
642
643 if (event == GATTC_OPTYPE_INDICATION) {
644 if (tcb.ind_count) {
645 /* this is an error case that receiving an indication but we
646 still has an indication not being acked yet.
647 For now, just log the error reset the counter.
648 Later we need to disconnect the link unconditionally.
649 */
650 LOG(ERROR) << __func__ << " rcv Ind. but ind_count=" << tcb.ind_count
651 << " (will reset ind_count)";
652 }
653 tcb.ind_count = 0;
654 }
655
656 /* should notify all registered client with the handle value
657 notificaion/indication
658 Note: need to do the indication count and start timer first then do
659 callback
660 */
661
662 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
663 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb &&
664 (event == GATTC_OPTYPE_INDICATION))
665 tcb.ind_count++;
666 }
667
668 if (event == GATTC_OPTYPE_INDICATION) {
669 /* start a timer for app confirmation */
670 if (tcb.ind_count > 0)
671 gatt_start_ind_ack_timer(tcb);
672 else /* no app to indicate, or invalid handle */
673 attp_send_cl_msg(tcb, nullptr, GATT_HANDLE_VALUE_CONF, NULL);
674 }
675
676 encrypt_status = gatt_get_link_encrypt_status(tcb);
677 tGATT_CL_COMPLETE gatt_cl_complete;
678 gatt_cl_complete.att_value = value;
679 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
680 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
681 conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, p_reg->gatt_if);
682 (*p_reg->app_cb.p_cmpl_cb)(conn_id, event, encrypt_status,
683 &gatt_cl_complete);
684 }
685 }
686 }
687
688 /*******************************************************************************
689 *
690 * Function gatt_process_read_by_type_rsp
691 *
692 * Description This function is called to handle the read by type response.
693 * read by type can be used for discovery, or read by type or
694 * read characteristic value.
695 *
696 * Returns void
697 *
698 ******************************************************************************/
gatt_process_read_by_type_rsp(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint8_t op_code,uint16_t len,uint8_t * p_data)699 void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
700 uint8_t op_code, uint16_t len,
701 uint8_t* p_data) {
702 tGATT_DISC_RES result;
703 tGATT_DISC_VALUE record_value;
704 uint8_t *p = p_data, value_len, handle_len = 2;
705 uint16_t handle = 0;
706
707 /* discovery procedure and no callback function registered */
708 if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) &&
709 (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
710 return;
711
712 if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN) {
713 LOG(ERROR) << "Illegal ReadByType/ReadByGroupType Response length, discard";
714 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
715 return;
716 }
717
718 STREAM_TO_UINT8(value_len, p);
719
720 if ((value_len > (tcb.payload_size - 2)) || (value_len > (len - 1))) {
721 /* this is an error case that server's response containing a value length
722 which is larger than MTU-2
723 or value_len > message total length -1 */
724 LOG(ERROR) << __func__
725 << StringPrintf(
726 ": Discard response op_code=%d "
727 "vale_len=%d > (MTU-2=%d or msg_len-1=%d)",
728 op_code, value_len, (tcb.payload_size - 2), (len - 1));
729 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
730 return;
731 }
732
733 if (op_code == GATT_RSP_READ_BY_GRP_TYPE) handle_len = 4;
734
735 value_len -= handle_len; /* substract the handle pairs bytes */
736 len -= 1;
737
738 while (len >= (handle_len + value_len)) {
739 STREAM_TO_UINT16(handle, p);
740
741 if (!GATT_HANDLE_IS_VALID(handle)) {
742 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
743 return;
744 }
745
746 memset(&result, 0, sizeof(tGATT_DISC_RES));
747 memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
748
749 result.handle = handle;
750 result.type =
751 bluetooth::Uuid::From16Bit(disc_type_to_uuid[p_clcb->op_subtype]);
752
753 /* discover all services */
754 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
755 p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
756 op_code == GATT_RSP_READ_BY_GRP_TYPE) {
757 STREAM_TO_UINT16(handle, p);
758
759 if (!GATT_HANDLE_IS_VALID(handle)) {
760 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
761 return;
762 } else {
763 record_value.group_value.e_handle = handle;
764 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type,
765 value_len, &p)) {
766 LOG(ERROR) << "discover all service response parsing failure";
767 break;
768 }
769 }
770 }
771 /* discover included service */
772 else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
773 p_clcb->op_subtype == GATT_DISC_INC_SRVC) {
774 if (value_len < 4) {
775 android_errorWriteLog(0x534e4554, "158833854");
776 LOG(ERROR) << __func__ << " Illegal Response length, must be at least 4.";
777 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
778 return;
779 }
780 STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
781 STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
782
783 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
784 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle)) {
785 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
786 return;
787 }
788
789 if (value_len == 6) {
790 uint16_t tmp;
791 STREAM_TO_UINT16(tmp, p);
792 record_value.incl_service.service_type =
793 bluetooth::Uuid::From16Bit(tmp);
794 } else if (value_len == 4) {
795 p_clcb->s_handle = record_value.incl_service.s_handle;
796 p_clcb->read_uuid128.wait_for_read_rsp = true;
797 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
798 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
799 memcpy(&p_clcb->read_uuid128.result.value, &record_value,
800 sizeof(result.value));
801 p_clcb->op_subtype |= 0x90;
802 gatt_act_read(p_clcb, 0);
803 return;
804 } else {
805 LOG(ERROR) << __func__
806 << ": INCL_SRVC failed with invalid data value_len="
807 << +value_len;
808 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void*)p);
809 return;
810 }
811 }
812 /* read by type */
813 else if (p_clcb->operation == GATTC_OPTYPE_READ &&
814 p_clcb->op_subtype == GATT_READ_BY_TYPE) {
815 p_clcb->counter = len - 2;
816 p_clcb->s_handle = handle;
817 if (p_clcb->counter == (p_clcb->p_tcb->payload_size - 4)) {
818 p_clcb->op_subtype = GATT_READ_BY_HANDLE;
819 if (!p_clcb->p_attr_buf)
820 p_clcb->p_attr_buf = (uint8_t*)osi_malloc(GATT_MAX_ATTR_LEN);
821 if (p_clcb->counter <= GATT_MAX_ATTR_LEN) {
822 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
823 gatt_act_read(p_clcb, p_clcb->counter);
824 } else {
825 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void*)p);
826 }
827 } else {
828 gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p);
829 }
830 return;
831 } else /* discover characterisitic */
832 {
833 if (value_len < 3) {
834 android_errorWriteLog(0x534e4554, "158778659");
835 LOG(ERROR) << __func__ << " Illegal Response length, must be at least 3.";
836 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
837 return;
838 }
839 STREAM_TO_UINT8(record_value.dclr_value.char_prop, p);
840 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
841 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle)) {
842 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
843 return;
844 }
845 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid,
846 (uint16_t)(value_len - 3), &p)) {
847 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
848 /* invalid format, and skip the result */
849 return;
850 }
851
852 /* UUID not matching */
853 if (!p_clcb->uuid.IsEmpty() &&
854 !record_value.dclr_value.char_uuid.IsEmpty() &&
855 record_value.dclr_value.char_uuid != p_clcb->uuid) {
856 len -= (value_len + 2);
857 continue; /* skip the result, and look for next one */
858 }
859
860 if (p_clcb->operation == GATTC_OPTYPE_READ)
861 /* UUID match for read characteristic value */
862 {
863 /* only read the first matching UUID characteristic value, and
864 discard the rest results */
865 p_clcb->s_handle = record_value.dclr_value.val_handle;
866 p_clcb->op_subtype |= 0x80;
867 gatt_act_read(p_clcb, 0);
868 return;
869 }
870 }
871 len -= (value_len + handle_len);
872
873 /* result is (handle, 16bits UUID) pairs */
874 memcpy(&result.value, &record_value, sizeof(result.value));
875
876 /* send callback if is discover procedure */
877 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
878 p_clcb->p_reg->app_cb.p_disc_res_cb)
879 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
880 p_clcb->op_subtype, &result);
881 }
882
883 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
884
885 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) {
886 /* initiate another request */
887 gatt_act_discovery(p_clcb);
888 } else /* read characteristic value */
889 {
890 gatt_act_read(p_clcb, 0);
891 }
892 }
893
894 /*******************************************************************************
895 *
896 * Function gatt_process_read_rsp
897 *
898 * Description This function is called to handle the read BLOB response
899 *
900 *
901 * Returns void
902 *
903 ******************************************************************************/
gatt_process_read_rsp(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,UNUSED_ATTR uint8_t op_code,uint16_t len,uint8_t * p_data)904 void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
905 UNUSED_ATTR uint8_t op_code, uint16_t len,
906 uint8_t* p_data) {
907 uint16_t offset = p_clcb->counter;
908 uint8_t* p = p_data;
909
910 if (p_clcb->operation == GATTC_OPTYPE_READ) {
911 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE) {
912 p_clcb->counter = len;
913 gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p);
914 } else {
915 /* allocate GKI buffer holding up long attribute value */
916 if (!p_clcb->p_attr_buf)
917 p_clcb->p_attr_buf = (uint8_t*)osi_malloc(GATT_MAX_ATTR_LEN);
918
919 /* copy attrobute value into cb buffer */
920 if (offset < GATT_MAX_ATTR_LEN) {
921 if ((len + offset) > GATT_MAX_ATTR_LEN)
922 len = GATT_MAX_ATTR_LEN - offset;
923
924 p_clcb->counter += len;
925
926 memcpy(p_clcb->p_attr_buf + offset, p, len);
927
928 /* send next request if needed */
929
930 if (len == (tcb.payload_size -
931 1) && /* full packet for read or read blob rsp */
932 len + offset < GATT_MAX_ATTR_LEN) {
933 VLOG(1) << StringPrintf(
934 "full pkt issue read blob for remianing bytes old offset=%d "
935 "len=%d new offset=%d",
936 offset, len, p_clcb->counter);
937 gatt_act_read(p_clcb, p_clcb->counter);
938 } else /* end of request, send callback */
939 {
940 gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p_clcb->p_attr_buf);
941 }
942 } else /* exception, should not happen */
943 {
944 LOG(ERROR) << "attr offset = " << +offset
945 << " p_attr_buf = " << p_clcb->p_attr_buf;
946 gatt_end_operation(p_clcb, GATT_NO_RESOURCES,
947 (void*)p_clcb->p_attr_buf);
948 }
949 }
950 } else {
951 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
952 p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
953 p_clcb->read_uuid128.wait_for_read_rsp) {
954 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
955 p_clcb->read_uuid128.wait_for_read_rsp = false;
956 if (len == Uuid::kNumBytes128) {
957 p_clcb->read_uuid128.result.value.incl_service.service_type =
958 bluetooth::Uuid::From128BitLE(p);
959 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
960 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
961 p_clcb->op_subtype,
962 &p_clcb->read_uuid128.result);
963 gatt_act_discovery(p_clcb);
964 } else {
965 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void*)p);
966 }
967 }
968 }
969 }
970
971 /*******************************************************************************
972 *
973 * Function gatt_process_handle_rsp
974 *
975 * Description This function is called to handle the write response
976 *
977 *
978 * Returns void
979 *
980 ******************************************************************************/
gatt_process_handle_rsp(tGATT_CLCB * p_clcb)981 void gatt_process_handle_rsp(tGATT_CLCB* p_clcb) {
982 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
983 }
984 /*******************************************************************************
985 *
986 * Function gatt_process_mtu_rsp
987 *
988 * Description Process the configure MTU response.
989 *
990 *
991 * Returns void
992 *
993 ******************************************************************************/
gatt_process_mtu_rsp(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint16_t len,uint8_t * p_data)994 void gatt_process_mtu_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint16_t len,
995 uint8_t* p_data) {
996 uint16_t mtu;
997 tGATT_STATUS status = GATT_SUCCESS;
998
999 if (len < GATT_MTU_RSP_MIN_LEN) {
1000 LOG(ERROR) << "invalid MTU response PDU received, discard.";
1001 status = GATT_INVALID_PDU;
1002 } else {
1003 STREAM_TO_UINT16(mtu, p_data);
1004
1005 if (mtu < tcb.payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
1006 tcb.payload_size = mtu;
1007 }
1008
1009 l2cble_set_fixed_channel_tx_data_length(tcb.peer_bda, L2CAP_ATT_CID,
1010 tcb.payload_size);
1011 gatt_end_operation(p_clcb, status, NULL);
1012 }
1013 /*******************************************************************************
1014 *
1015 * Function gatt_cmd_to_rsp_code
1016 *
1017 * Description Convert an ATT command op code into the corresponding
1018 * response code assume no error occurs.
1019 *
1020 * Returns response code.
1021 *
1022 ******************************************************************************/
gatt_cmd_to_rsp_code(uint8_t cmd_code)1023 uint8_t gatt_cmd_to_rsp_code(uint8_t cmd_code) {
1024 uint8_t rsp_code = 0;
1025
1026 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE) {
1027 rsp_code = cmd_code + 1;
1028 }
1029 return rsp_code;
1030 }
1031
1032 /** Find next command in queue and sent to server */
gatt_cl_send_next_cmd_inq(tGATT_TCB & tcb)1033 bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) {
1034 while (!tcb.cl_cmd_q.empty()) {
1035 tGATT_CMD_Q& cmd = tcb.cl_cmd_q.front();
1036 if (!cmd.to_send || cmd.p_cmd == NULL) return false;
1037
1038 tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, cmd.p_cmd);
1039 if (att_ret != GATT_SUCCESS && att_ret != GATT_CONGESTED) {
1040 LOG(ERROR) << __func__ << ": L2CAP sent error";
1041 tcb.cl_cmd_q.pop();
1042 continue;
1043 }
1044
1045 cmd.to_send = false;
1046 cmd.p_cmd = NULL;
1047
1048 if (cmd.op_code == GATT_CMD_WRITE || cmd.op_code == GATT_SIGN_CMD_WRITE) {
1049 /* dequeue the request if is write command or sign write */
1050 uint8_t rsp_code;
1051 tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &rsp_code);
1052
1053 /* send command complete callback here */
1054 gatt_end_operation(p_clcb, att_ret, NULL);
1055
1056 /* if no ack needed, keep sending */
1057 if (att_ret == GATT_SUCCESS) continue;
1058
1059 return true;
1060 }
1061
1062 gatt_start_rsp_timer(cmd.p_clcb);
1063 return true;
1064 }
1065
1066 return false;
1067 }
1068
1069 /** 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)1070 void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint8_t op_code,
1071 uint16_t len, uint8_t* p_data) {
1072 if (op_code == GATT_HANDLE_VALUE_IND || op_code == GATT_HANDLE_VALUE_NOTIF) {
1073 if (len >= tcb.payload_size) {
1074 LOG(ERROR) << StringPrintf(
1075 "%s: invalid indicate pkt size: %d, PDU size: %d", __func__, len + 1,
1076 tcb.payload_size);
1077 return;
1078 }
1079
1080 gatt_process_notification(tcb, op_code, len, p_data);
1081 return;
1082 }
1083
1084 uint8_t cmd_code = 0;
1085 tGATT_CLCB* p_clcb = gatt_cmd_dequeue(tcb, &cmd_code);
1086 uint8_t rsp_code = gatt_cmd_to_rsp_code(cmd_code);
1087 if (!p_clcb || (rsp_code != op_code && op_code != GATT_RSP_ERROR)) {
1088 LOG(WARNING) << StringPrintf(
1089 "ATT - Ignore wrong response. Receives (%02x) Request(%02x) Ignored",
1090 op_code, rsp_code);
1091 return;
1092 }
1093
1094 if (!p_clcb->in_use) {
1095 LOG(WARNING) << "ATT - clcb already not in use, ignoring response";
1096 gatt_cl_send_next_cmd_inq(tcb);
1097 return;
1098 }
1099
1100 alarm_cancel(p_clcb->gatt_rsp_timer_ent);
1101 p_clcb->retry_count = 0;
1102
1103 /* the size of the message may not be bigger than the local max PDU size*/
1104 /* The message has to be smaller than the agreed MTU, len does not count
1105 * op_code */
1106 if (len >= tcb.payload_size) {
1107 LOG(ERROR) << StringPrintf(
1108 "%s: invalid response pkt size: %d, PDU size: %d", __func__, len + 1,
1109 tcb.payload_size);
1110 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1111 } else {
1112 switch (op_code) {
1113 case GATT_RSP_ERROR:
1114 gatt_process_error_rsp(tcb, p_clcb, op_code, len, p_data);
1115 break;
1116
1117 case GATT_RSP_MTU: /* 2 bytes mtu */
1118 gatt_process_mtu_rsp(tcb, p_clcb, len, p_data);
1119 break;
1120
1121 case GATT_RSP_FIND_INFO:
1122 gatt_process_read_info_rsp(tcb, p_clcb, op_code, len, p_data);
1123 break;
1124
1125 case GATT_RSP_READ_BY_TYPE:
1126 case GATT_RSP_READ_BY_GRP_TYPE:
1127 gatt_process_read_by_type_rsp(tcb, p_clcb, op_code, len, p_data);
1128 break;
1129
1130 case GATT_RSP_READ:
1131 case GATT_RSP_READ_BLOB:
1132 case GATT_RSP_READ_MULTI:
1133 gatt_process_read_rsp(tcb, p_clcb, op_code, len, p_data);
1134 break;
1135
1136 case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
1137 gatt_process_find_type_value_rsp(tcb, p_clcb, len, p_data);
1138 break;
1139
1140 case GATT_RSP_WRITE:
1141 gatt_process_handle_rsp(p_clcb);
1142 break;
1143
1144 case GATT_RSP_PREPARE_WRITE:
1145 gatt_process_prep_write_rsp(tcb, p_clcb, op_code, len, p_data);
1146 break;
1147
1148 case GATT_RSP_EXEC_WRITE:
1149 gatt_end_operation(p_clcb, p_clcb->status, NULL);
1150 break;
1151
1152 default:
1153 LOG(ERROR) << __func__ << ": Unknown opcode = " << std::hex << op_code;
1154 break;
1155 }
1156 }
1157
1158 gatt_cl_send_next_cmd_inq(tcb);
1159 }
1160