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