gatt_cl.c revision 258c2538e3b62a8cdb403f2730c45d721e5292b4
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    tGATT_VALUE  value = {0};
615    UINT8        *p= p_data;
616
617    GATT_TRACE_ERROR("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);
618
619    if (len < GATT_PREP_WRITE_RSP_MIN_LEN)
620    {
621        GATT_TRACE_ERROR("illegal prepare write response length, discard");
622        gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
623        return;
624    }
625
626    STREAM_TO_UINT16 (value.handle, p);
627    STREAM_TO_UINT16 (value.offset, p);
628
629    value.len = len - 4;
630
631    memcpy (value.value, p, value.len);
632
633    if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
634    {
635        p_clcb->status = GATT_SUCCESS;
636        /* application should verify handle offset
637           and value are matched or not */
638
639        gatt_end_operation(p_clcb, p_clcb->status, &value);
640    }
641    else if (p_clcb->op_subtype == GATT_WRITE )
642    {
643        if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value))
644            gatt_send_prepare_write(p_tcb, p_clcb);
645    }
646
647}
648/*******************************************************************************
649**
650** Function         gatt_process_notification
651**
652** Description      This function is called to handle the handle value indication
653**                  or handle value notification.
654**
655**
656** Returns          void
657**
658*******************************************************************************/
659void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
660                               UINT16 len, UINT8 *p_data)
661{
662    tGATT_VALUE     value = {0};
663    tGATT_REG       *p_reg;
664    UINT16          conn_id;
665    tGATT_STATUS    encrypt_status;
666    UINT8           *p= p_data, i,
667    event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION;
668
669    GATT_TRACE_DEBUG("gatt_process_notification ");
670
671    if (len < GATT_NOTIFICATION_MIN_LEN)
672    {
673        GATT_TRACE_ERROR("illegal notification PDU length, discard");
674        return;
675    }
676
677    STREAM_TO_UINT16 (value.handle, p);
678    value.len = len - 2;
679    memcpy (value.value, p, value.len);
680
681    if (!GATT_HANDLE_IS_VALID(value.handle))
682    {
683        /* illegal handle, send ack now */
684        if (op_code == GATT_HANDLE_VALUE_IND)
685            attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
686        return;
687    }
688
689    if (event == GATTC_OPTYPE_INDICATION)
690    {
691        if (p_tcb->ind_count)
692        {
693            /* this is an error case that receiving an indication but we
694               still has an indication not being acked yet.
695               For now, just log the error reset the counter.
696               Later we need to disconnect the link unconditionally.
697            */
698            GATT_TRACE_ERROR("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)",  p_tcb->ind_count);
699        }
700        p_tcb->ind_count = 0;
701    }
702
703    /* should notify all registered client with the handle value notificaion/indication
704       Note: need to do the indication count and start timer first then do callback
705     */
706
707    for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
708    {
709        if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION))
710            p_tcb->ind_count++;
711    }
712
713    if (event == GATTC_OPTYPE_INDICATION)
714    {
715        /* start a timer for app confirmation */
716        if (p_tcb->ind_count > 0)
717            gatt_start_ind_ack_timer(p_tcb);
718        else /* no app to indicate, or invalid handle */
719            attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
720    }
721
722    encrypt_status = gatt_get_link_encrypt_status(p_tcb);
723    for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
724    {
725        if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
726        {
727            conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
728            (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
729        }
730    }
731
732}
733
734/*******************************************************************************
735**
736** Function         gatt_process_read_by_type_rsp
737**
738** Description      This function is called to handle the read by type response.
739**                  read by type can be used for discovery, or read by type or
740**                  read characteristic value.
741**
742** Returns          void
743**
744*******************************************************************************/
745void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
746                                    UINT16 len, UINT8 *p_data)
747{
748    tGATT_DISC_RES      result;
749    tGATT_DISC_VALUE    record_value;
750    UINT8               *p = p_data, value_len, handle_len = 2;
751    UINT16              handle = 0;
752
753    /* discovery procedure and no callback function registered */
754    if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
755        return;
756
757    if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN)
758    {
759        GATT_TRACE_ERROR("Illegal ReadByType/ReadByGroupType Response length, discard");
760        gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
761        return;
762    }
763
764    STREAM_TO_UINT8(value_len, p);
765
766    if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1))  )
767    {
768        /* this is an error case that server's response containing a value length which is larger than MTU-2
769           or value_len > message total length -1 */
770        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)",
771                          op_code, value_len, (p_tcb->payload_size - 2), (len-1));
772        gatt_end_operation(p_clcb, GATT_ERROR, NULL);
773        return;
774    }
775
776    if (op_code == GATT_RSP_READ_BY_GRP_TYPE)
777        handle_len = 4;
778
779    value_len -= handle_len; /* substract the handle pairs bytes */
780    len -= 1;
781
782    while (len >= (handle_len + value_len))
783    {
784        STREAM_TO_UINT16(handle, p);
785
786        if (!GATT_HANDLE_IS_VALID(handle))
787        {
788            gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
789            return;
790        }
791
792        memset(&result, 0, sizeof(tGATT_DISC_RES));
793        memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
794
795        result.handle = handle;
796        result.type.len = 2;
797        result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
798
799        /* discover all services */
800        if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
801            p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
802            op_code == GATT_RSP_READ_BY_GRP_TYPE)
803        {
804            STREAM_TO_UINT16(handle, p);
805
806            if (!GATT_HANDLE_IS_VALID(handle))
807            {
808                gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
809                return;
810            }
811            else
812            {
813                record_value.group_value.e_handle = handle;
814                if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p))
815                {
816                    GATT_TRACE_ERROR("discover all service response parsing failure");
817                    break;
818                }
819            }
820        }
821        /* discover included service */
822        else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC)
823        {
824            STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
825            STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
826
827            if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
828                !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle))
829            {
830                gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
831                return;
832            }
833
834            if(value_len == 6)
835            {
836                STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
837                record_value.incl_service.service_type.len = LEN_UUID_16;
838            }
839            else if (value_len == 4)
840            {
841                p_clcb->s_handle = record_value.incl_service.s_handle;
842                p_clcb->read_uuid128.wait_for_read_rsp = TRUE;
843                p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
844                memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
845                memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
846                p_clcb->op_subtype |= 0x90;
847                gatt_act_read(p_clcb, 0);
848                return;
849            }
850            else
851            {
852               GATT_TRACE_ERROR("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len);
853               gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
854               return;
855            }
856        }
857        /* read by type */
858        else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE)
859        {
860            p_clcb->counter = len - 2;
861            p_clcb->s_handle = handle;
862            if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4))
863            {
864                p_clcb->op_subtype = GATT_READ_BY_HANDLE;
865                if (!p_clcb->p_attr_buf)
866                    p_clcb->p_attr_buf = (UINT8 *)osi_getbuf(GATT_MAX_ATTR_LEN);
867                if (p_clcb->p_attr_buf && p_clcb->counter <= GATT_MAX_ATTR_LEN)
868                {
869                    memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
870                    gatt_act_read(p_clcb, p_clcb->counter);
871                }
872                else
873                   gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p);
874            }
875            else
876            {
877                 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
878            }
879            return;
880        }
881        else /* discover characterisitic */
882        {
883            STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
884            STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
885            if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle))
886            {
887                gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
888                return;
889            }
890            if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
891            {
892                gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
893                /* invalid format, and skip the result */
894                return;
895            }
896
897            /* UUID not matching */
898            if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
899            {
900                len -= (value_len + 2);
901                continue; /* skip the result, and look for next one */
902            }
903            else if (p_clcb->operation == GATTC_OPTYPE_READ)
904            /* UUID match for read characteristic value */
905            {
906                /* only read the first matching UUID characteristic value, and
907                  discard the rest results */
908                p_clcb->s_handle = record_value.dclr_value.val_handle;
909                p_clcb->op_subtype |= 0x80;
910                gatt_act_read(p_clcb, 0);
911                return;
912            }
913        }
914        len -= (value_len + handle_len);
915
916        /* result is (handle, 16bits UUID) pairs */
917        memcpy (&result.value, &record_value, sizeof (result.value));
918
919        /* send callback if is discover procedure */
920        if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb)
921            (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
922    }
923
924    p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
925
926    if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
927    {
928        /* initiate another request */
929        gatt_act_discovery(p_clcb) ;
930    }
931    else /* read characteristic value */
932    {
933        gatt_act_read(p_clcb, 0);
934    }
935}
936
937/*******************************************************************************
938**
939** Function         gatt_process_read_rsp
940**
941** Description      This function is called to handle the read BLOB response
942**
943**
944** Returns          void
945**
946*******************************************************************************/
947void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb,  UINT8 op_code,
948                           UINT16 len, UINT8 *p_data)
949{
950    UINT16      offset = p_clcb->counter;
951    UINT8       * p= p_data;
952
953    UNUSED(op_code);
954
955    if (p_clcb->operation == GATTC_OPTYPE_READ)
956    {
957        if (p_clcb->op_subtype != GATT_READ_BY_HANDLE)
958        {
959            p_clcb->counter = len;
960            gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
961        }
962        else
963        {
964
965            /* allocate GKI buffer holding up long attribute value  */
966            if (!p_clcb->p_attr_buf)
967                p_clcb->p_attr_buf = (UINT8 *)osi_getbuf(GATT_MAX_ATTR_LEN);
968
969            /* copy attrobute value into cb buffer  */
970            if (p_clcb->p_attr_buf && offset < GATT_MAX_ATTR_LEN)
971            {
972                if ((len + offset) > GATT_MAX_ATTR_LEN)
973                    len = GATT_MAX_ATTR_LEN - offset;
974
975                p_clcb->counter += len;
976
977                memcpy(p_clcb->p_attr_buf + offset, p, len);
978
979                /* send next request if needed  */
980
981                if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */
982                    len + offset < GATT_MAX_ATTR_LEN)
983                {
984                    GATT_TRACE_DEBUG("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d",
985                                      offset, len, p_clcb->counter);
986                    gatt_act_read(p_clcb, p_clcb->counter);
987                }
988                else /* end of request, send callback */
989                {
990                    gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
991                }
992            }
993            else /* exception, should not happen */
994            {
995                GATT_TRACE_ERROR("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf);
996                gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf);
997            }
998        }
999    }
1000    else
1001    {
1002        if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
1003            p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
1004            p_clcb->read_uuid128.wait_for_read_rsp )
1005        {
1006            p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
1007            p_clcb->read_uuid128.wait_for_read_rsp = FALSE;
1008            if (len == LEN_UUID_128)
1009            {
1010
1011                memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
1012                p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
1013                if ( p_clcb->p_reg->app_cb.p_disc_res_cb)
1014                    (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
1015                gatt_act_discovery(p_clcb) ;
1016            }
1017            else
1018            {
1019                gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
1020            }
1021        }
1022    }
1023
1024}
1025
1026
1027/*******************************************************************************
1028**
1029** Function         gatt_process_handle_rsp
1030**
1031** Description      This function is called to handle the write response
1032**
1033**
1034** Returns          void
1035**
1036*******************************************************************************/
1037void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
1038{
1039    gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
1040}
1041/*******************************************************************************
1042**
1043** Function         gatt_process_mtu_rsp
1044**
1045** Description      This function is called to process the configure MTU response.
1046**
1047**
1048** Returns          void
1049**
1050*******************************************************************************/
1051void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
1052{
1053    UINT16 mtu;
1054    tGATT_STATUS    status = GATT_SUCCESS;
1055
1056    if (len < GATT_MTU_RSP_MIN_LEN)
1057    {
1058        GATT_TRACE_ERROR("invalid MTU response PDU received, discard.");
1059        status = GATT_INVALID_PDU;
1060    }
1061    else
1062    {
1063    STREAM_TO_UINT16(mtu, p_data);
1064
1065    if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
1066        p_tcb->payload_size = mtu;
1067    }
1068
1069    l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
1070    gatt_end_operation(p_clcb, status, NULL);
1071}
1072/*******************************************************************************
1073**
1074** Function         gatt_cmd_to_rsp_code
1075**
1076** Description      The function convert a ATT command op code into the corresponding
1077**                  response code assume no error occurs.
1078**
1079** Returns          response code.
1080**
1081*******************************************************************************/
1082UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code)
1083{
1084    UINT8   rsp_code  = 0;
1085
1086    if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE)
1087    {
1088        rsp_code = cmd_code + 1;
1089    }
1090    return rsp_code;
1091}
1092/*******************************************************************************
1093**
1094** Function         gatt_cl_send_next_cmd_inq
1095**
1096** Description      Find next command in queue and sent to server
1097**
1098** Returns          TRUE if command sent, otherwise FALSE.
1099**
1100*******************************************************************************/
1101BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
1102{
1103    tGATT_CMD_Q  *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1104    BOOLEAN     sent = FALSE;
1105    UINT8       rsp_code;
1106    tGATT_CLCB   *p_clcb = NULL;
1107    tGATT_STATUS att_ret = GATT_SUCCESS;
1108
1109    while (!sent &&
1110           p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
1111           p_cmd->to_send && p_cmd->p_cmd != NULL)
1112    {
1113        att_ret = attp_send_msg_to_l2cap(p_tcb, p_cmd->p_cmd);
1114
1115        if (att_ret == GATT_SUCCESS || att_ret == GATT_CONGESTED)
1116        {
1117            sent = TRUE;
1118            p_cmd->to_send = FALSE;
1119            p_cmd->p_cmd = NULL;
1120
1121            /* dequeue the request if is write command or sign write */
1122            if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
1123            {
1124                gatt_start_rsp_timer (p_cmd->clcb_idx);
1125            }
1126            else
1127            {
1128                p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1129
1130                /* if no ack needed, keep sending */
1131                if (att_ret == GATT_SUCCESS)
1132                    sent = FALSE;
1133
1134                p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1135                /* send command complete callback here */
1136                gatt_end_operation(p_clcb, att_ret, NULL);
1137            }
1138        }
1139        else
1140        {
1141            GATT_TRACE_ERROR("gatt_cl_send_next_cmd_inq: L2CAP sent error");
1142
1143            memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
1144            p_tcb->pending_cl_req ++;
1145            p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1146        }
1147
1148    }
1149    return sent;
1150}
1151
1152/*******************************************************************************
1153**
1154** Function         gatt_client_handle_server_rsp
1155**
1156** Description      This function is called to handle the server response to
1157**                  client.
1158**
1159**
1160** Returns          void
1161**
1162*******************************************************************************/
1163void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
1164                                    UINT16 len, UINT8 *p_data)
1165{
1166    tGATT_CLCB   *p_clcb = NULL;
1167    UINT8        rsp_code;
1168
1169    if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1170    {
1171        p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1172
1173        rsp_code = gatt_cmd_to_rsp_code(rsp_code);
1174
1175        if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR))
1176        {
1177            GATT_TRACE_WARNING ("ATT - Ignore wrong response. Receives (%02x) \
1178                                Request(%02x) Ignored", op_code, rsp_code);
1179
1180            return;
1181        }
1182        else
1183        {
1184            btu_stop_timer (&p_clcb->rsp_timer_ent);
1185            p_clcb->retry_count = 0;
1186        }
1187    }
1188    /* the size of the message may not be bigger than the local max PDU size*/
1189    /* The message has to be smaller than the agreed MTU, len does not count op_code */
1190    if (len >= p_tcb->payload_size)
1191    {
1192        GATT_TRACE_ERROR("invalid response/indicate pkt size: %d, PDU size: %d", len + 1, p_tcb->payload_size);
1193        if (op_code != GATT_HANDLE_VALUE_NOTIF &&
1194            op_code != GATT_HANDLE_VALUE_IND)
1195            gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1196    }
1197    else
1198    {
1199        switch (op_code)
1200        {
1201            case GATT_RSP_ERROR:
1202                gatt_process_error_rsp(p_tcb, p_clcb, op_code, len, p_data);
1203                break;
1204
1205            case GATT_RSP_MTU:       /* 2 bytes mtu */
1206                gatt_process_mtu_rsp(p_tcb, p_clcb, len ,p_data);
1207                break;
1208
1209            case GATT_RSP_FIND_INFO:
1210                gatt_process_read_info_rsp(p_tcb, p_clcb, op_code, len, p_data);
1211                break;
1212
1213            case GATT_RSP_READ_BY_TYPE:
1214            case GATT_RSP_READ_BY_GRP_TYPE:
1215                gatt_process_read_by_type_rsp(p_tcb, p_clcb, op_code, len, p_data);
1216                break;
1217
1218            case GATT_RSP_READ:
1219            case GATT_RSP_READ_BLOB:
1220            case GATT_RSP_READ_MULTI:
1221                gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data);
1222                break;
1223
1224            case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
1225                gatt_process_find_type_value_rsp(p_tcb, p_clcb, len, p_data);
1226                break;
1227
1228            case GATT_RSP_WRITE:
1229                gatt_process_handle_rsp(p_clcb);
1230                break;
1231
1232            case GATT_RSP_PREPARE_WRITE:
1233                gatt_process_prep_write_rsp(p_tcb, p_clcb, op_code, len, p_data);
1234                break;
1235
1236            case GATT_RSP_EXEC_WRITE:
1237                gatt_end_operation(p_clcb, p_clcb->status, NULL);
1238                break;
1239
1240            case GATT_HANDLE_VALUE_NOTIF:
1241            case GATT_HANDLE_VALUE_IND:
1242                gatt_process_notification(p_tcb, op_code, len, p_data);
1243                break;
1244
1245            default:
1246                GATT_TRACE_ERROR("Unknown opcode = %d", op_code);
1247                break;
1248        }
1249    }
1250
1251    if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1252    {
1253        gatt_cl_send_next_cmd_inq(p_tcb);
1254    }
1255
1256    return;
1257}
1258
1259#endif  /* BLE_INCLUDED */
1260