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