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