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