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