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