gatt_cl.c revision ccf9c15f52eea21858d994601d71308e84c7c859
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*******************************************************************************/
405void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, 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*******************************************************************************/
448void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
449                                UINT16 len, UINT8 *p_data)
450{
451    tGATT_DISC_RES  result;
452    UINT8   *p = p_data, uuid_len = 0, type;
453
454    if (len < GATT_INFO_RSP_MIN_LEN)
455    {
456        GATT_TRACE_ERROR0("invalid Info Response PDU received, discard.");
457        gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
458        return;
459    }
460    /* unexpected response */
461    if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT)
462        return;
463
464    STREAM_TO_UINT8(type, p);
465    len -= 1;
466
467    if (type == GATT_INFO_TYPE_PAIR_16)
468        uuid_len = LEN_UUID_16;
469    else if (type == GATT_INFO_TYPE_PAIR_128)
470        uuid_len = LEN_UUID_128;
471
472    while (len >= uuid_len + 2)
473    {
474        STREAM_TO_UINT16 (result.handle, p);
475
476        if (uuid_len > 0)
477        {
478            if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p))
479                break;
480        }
481        else
482            memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID));
483
484        len -= (uuid_len + 2);
485
486        if (p_clcb->p_reg->app_cb.p_disc_res_cb)
487            (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
488    }
489
490    p_clcb->s_handle = (result.handle == 0) ? 0 :(result.handle + 1);
491    /* initiate another request */
492    gatt_act_discovery(p_clcb) ;
493}
494/*******************************************************************************
495**
496** Function         gatt_proc_disc_error_rsp
497**
498** Description      This function process the read by type response and send another
499**                  request if needed.
500**
501** Returns          void.
502**
503*******************************************************************************/
504void gatt_proc_disc_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 opcode,
505                              UINT16 handle, UINT8 reason)
506{
507    tGATT_STATUS    status = (tGATT_STATUS) reason;
508
509    GATT_TRACE_DEBUG2("gatt_proc_disc_error_rsp reason: %02x cmd_code %04x", reason, opcode);
510
511    switch (opcode)
512    {
513        case GATT_REQ_READ_BY_GRP_TYPE:
514        case GATT_REQ_FIND_TYPE_VALUE:
515        case GATT_REQ_READ_BY_TYPE:
516        case GATT_REQ_FIND_INFO:
517            if (reason == GATT_NOT_FOUND)
518            {
519                status = GATT_SUCCESS;
520                GATT_TRACE_DEBUG0("Discovery completed");
521            }
522            break;
523        default:
524            GATT_TRACE_ERROR1("Incorrect discovery opcode %04x",   opcode);
525            break;
526    }
527
528    gatt_end_operation(p_clcb, status, NULL);
529}
530
531/*******************************************************************************
532**
533** Function         gatt_process_error_rsp
534**
535** Description      This function is called to handle the error response
536**
537**
538** Returns          void
539**
540*******************************************************************************/
541void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
542                            UINT16 len, UINT8 *p_data)
543{
544    UINT8   opcode, reason, * p= p_data;
545    UINT16  handle;
546    tGATT_VALUE  *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
547
548    GATT_TRACE_DEBUG0("gatt_process_error_rsp ");
549    STREAM_TO_UINT8(opcode, p);
550    STREAM_TO_UINT16(handle, p);
551    STREAM_TO_UINT8(reason, p);
552
553    if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
554    {
555        gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason);
556    }
557    else
558    {
559        if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) &&
560             (p_clcb->op_subtype == GATT_WRITE) &&
561             (opcode == GATT_REQ_PREPARE_WRITE) &&
562             (p_attr) &&
563             (handle == p_attr->handle)  )
564        {
565            p_clcb->status = reason;
566            gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL);
567        }
568        else if ((p_clcb->operation == GATTC_OPTYPE_READ) &&
569                 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) ||
570                  (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) &&
571                 (opcode == GATT_REQ_READ_BLOB) &&
572                 p_clcb->first_read_blob_after_read &&
573                 (reason == GATT_NOT_LONG))
574        {
575            gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
576        }
577        else
578            gatt_end_operation(p_clcb, reason, NULL);
579    }
580}
581/*******************************************************************************
582**
583** Function         gatt_process_prep_write_rsp
584**
585** Description      This function is called to handle the read response
586**
587**
588** Returns          void
589**
590*******************************************************************************/
591void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
592                                  UINT16 len, UINT8 *p_data)
593{
594    tGATT_VALUE  value = {0};
595    UINT8        *p= p_data;
596
597    GATT_TRACE_ERROR2("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);
598
599    if (len < GATT_PREP_WRITE_RSP_MIN_LEN)
600    {
601        GATT_TRACE_ERROR0("illegal prepare write response length, discard");
602        gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
603        return;
604    }
605
606    STREAM_TO_UINT16 (value.handle, p);
607    STREAM_TO_UINT16 (value.offset, p);
608
609    value.len = len - 4;
610
611    memcpy (value.value, p, value.len);
612
613    if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
614    {
615        p_clcb->status = GATT_SUCCESS;
616        /* application should verify handle offset
617           and value are matched or not */
618
619        gatt_end_operation(p_clcb, p_clcb->status, &value);
620    }
621    else if (p_clcb->op_subtype == GATT_WRITE )
622    {
623        if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value))
624            gatt_send_prepare_write(p_tcb, p_clcb);
625    }
626
627}
628/*******************************************************************************
629**
630** Function         gatt_process_notification
631**
632** Description      This function is called to handle the handle value indication
633**                  or handle value notification.
634**
635**
636** Returns          void
637**
638*******************************************************************************/
639void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
640                               UINT16 len, UINT8 *p_data)
641{
642    tGATT_VALUE     value = {0};
643    tGATT_REG       *p_reg;
644    UINT16          conn_id;
645    tGATT_STATUS    encrypt_status;
646    UINT8           *p= p_data, i,
647    event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION;
648
649    GATT_TRACE_DEBUG0("gatt_process_notification ");
650
651    if (len < GATT_NOTIFICATION_MIN_LEN)
652    {
653        GATT_TRACE_ERROR0("illegal notification PDU length, discard");
654        return;
655    }
656
657    STREAM_TO_UINT16 (value.handle, p);
658    value.len = len - 2;
659    memcpy (value.value, p, value.len);
660
661    if (!GATT_HANDLE_IS_VALID(value.handle))
662    {
663        /* illegal handle, send ack now */
664        if (op_code == GATT_HANDLE_VALUE_IND)
665            attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
666        return;
667    }
668
669    if (event == GATTC_OPTYPE_INDICATION)
670    {
671        if (p_tcb->ind_count)
672        {
673            /* this is an error case that receiving an indication but we
674               still has an indication not being acked yet.
675               For now, just log the error reset the counter.
676               Later we need to disconnect the link unconditionally.
677            */
678            GATT_TRACE_ERROR1("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)",  p_tcb->ind_count);
679        }
680        p_tcb->ind_count = 0;
681    }
682
683    /* should notify all registered client with the handle value notificaion/indication
684       Note: need to do the indication count and start timer first then do callback
685     */
686
687    for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
688    {
689        if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION))
690            p_tcb->ind_count++;
691    }
692
693    if (event == GATTC_OPTYPE_INDICATION)
694    {
695        /* start a timer for app confirmation */
696        if (p_tcb->ind_count > 0)
697            gatt_start_ind_ack_timer(p_tcb);
698        else /* no app to indicate, or invalid handle */
699            attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
700    }
701
702    encrypt_status = gatt_get_link_encrypt_status(p_tcb);
703    for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
704    {
705        if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
706        {
707            conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
708            (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
709        }
710    }
711
712}
713
714/*******************************************************************************
715**
716** Function         gatt_process_read_by_type_rsp
717**
718** Description      This function is called to handle the read by type response.
719**                  read by type can be used for discovery, or read by type or
720**                  read characteristic value.
721**
722** Returns          void
723**
724*******************************************************************************/
725void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
726                                    UINT16 len, UINT8 *p_data)
727{
728    tGATT_DISC_RES      result;
729    tGATT_DISC_VALUE    record_value;
730    UINT8               *p = p_data, value_len, handle_len = 2;
731    UINT16              handle = 0;
732
733    /* discovery procedure and no callback function registered */
734    if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
735        return;
736
737    if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN)
738    {
739        GATT_TRACE_ERROR0("Illegal ReadByType/ReadByGroupType Response length, discard");
740        gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
741        return;
742    }
743
744    STREAM_TO_UINT8(value_len, p);
745
746    if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1))  )
747    {
748        /* this is an error case that server's response containing a value length which is larger than MTU-2
749           or value_len > message total length -1 */
750        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)",
751                          op_code, value_len, (p_tcb->payload_size - 2), (len-1));
752        gatt_end_operation(p_clcb, GATT_ERROR, NULL);
753        return;
754    }
755
756    if (op_code == GATT_RSP_READ_BY_GRP_TYPE)
757        handle_len = 4;
758
759    value_len -= handle_len; /* substract the handle pairs bytes */
760    len -= 1;
761
762    while (len >= (handle_len + value_len))
763    {
764        STREAM_TO_UINT16(handle, p);
765
766        if (!GATT_HANDLE_IS_VALID(handle))
767        {
768            gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
769            return;
770        }
771
772        memset(&result, 0, sizeof(tGATT_DISC_RES));
773        memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
774
775        result.handle = handle;
776        result.type.len = 2;
777        result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
778
779        /* discover all services */
780        if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
781            p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
782            op_code == GATT_RSP_READ_BY_GRP_TYPE)
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            else
792            {
793                record_value.group_value.e_handle = handle;
794                if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p))
795                {
796                    GATT_TRACE_ERROR0("discover all service response parsing failure");
797                    break;
798                }
799            }
800        }
801        /* discover included service */
802        else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC)
803        {
804            STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
805            STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
806
807            if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
808                !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle))
809            {
810                gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
811                return;
812            }
813
814            if(value_len == 6)
815            {
816                STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
817                record_value.incl_service.service_type.len = LEN_UUID_16;
818            }
819            else if (value_len == 4)
820            {
821                p_clcb->s_handle = record_value.incl_service.s_handle;
822                p_clcb->read_uuid128.wait_for_read_rsp = TRUE;
823                p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
824                memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
825                memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
826                p_clcb->op_subtype |= 0x90;
827                gatt_act_read(p_clcb, 0);
828                return;
829            }
830            else
831            {
832               GATT_TRACE_ERROR1("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len);
833               gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
834               return;
835            }
836        }
837        /* read by type */
838        else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE)
839        {
840            p_clcb->counter = len - 2;
841            p_clcb->s_handle = handle;
842            if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4))
843            {
844                p_clcb->op_subtype = GATT_READ_BY_HANDLE;
845                if (!p_clcb->p_attr_buf)
846                    p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN);
847                if (p_clcb->p_attr_buf && p_clcb->counter <= GATT_MAX_ATTR_LEN)
848                {
849                    memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
850                    gatt_act_read(p_clcb, p_clcb->counter);
851                }
852                else
853                   gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p);
854            }
855            else
856            {
857                 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
858            }
859            return;
860        }
861        else /* discover characterisitic */
862        {
863            STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
864            STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
865            if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle))
866            {
867                gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
868                return;
869            }
870            if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
871            {
872                gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
873                /* invalid format, and skip the result */
874                return;
875            }
876
877            /* UUID not matching */
878            if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
879            {
880                len -= (value_len + 2);
881                continue; /* skip the result, and look for next one */
882            }
883            else if (p_clcb->operation == GATTC_OPTYPE_READ)
884            /* UUID match for read characteristic value */
885            {
886                /* only read the first matching UUID characteristic value, and
887                  discard the rest results */
888                p_clcb->s_handle = record_value.dclr_value.val_handle;
889                p_clcb->op_subtype |= 0x80;
890                gatt_act_read(p_clcb, 0);
891                return;
892            }
893        }
894        len -= (value_len + handle_len);
895
896        /* result is (handle, 16bits UUID) pairs */
897        memcpy (&result.value, &record_value, sizeof (result.value));
898
899        /* send callback if is discover procedure */
900        if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb)
901            (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
902    }
903
904    p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
905
906    if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
907    {
908        /* initiate another request */
909        gatt_act_discovery(p_clcb) ;
910    }
911    else /* read characteristic value */
912    {
913        gatt_act_read(p_clcb, 0);
914    }
915}
916
917/*******************************************************************************
918**
919** Function         gatt_process_read_rsp
920**
921** Description      This function is called to handle the read BLOB response
922**
923**
924** Returns          void
925**
926*******************************************************************************/
927void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb,  UINT8 op_code,
928                           UINT16 len, UINT8 *p_data)
929{
930    UINT16      offset = p_clcb->counter;
931    UINT8       * p= p_data;
932
933    if (p_clcb->operation == GATTC_OPTYPE_READ)
934    {
935        if (p_clcb->op_subtype != GATT_READ_BY_HANDLE)
936        {
937            p_clcb->counter = len;
938            gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
939        }
940        else
941        {
942
943            /* allocate GKI buffer holding up long attribute value  */
944            if (!p_clcb->p_attr_buf)
945                p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN);
946
947            /* copy attrobute value into cb buffer  */
948            if (p_clcb->p_attr_buf && offset < GATT_MAX_ATTR_LEN)
949            {
950                if ((len + offset) > GATT_MAX_ATTR_LEN)
951                    len = GATT_MAX_ATTR_LEN - offset;
952
953                p_clcb->counter += len;
954
955                memcpy(p_clcb->p_attr_buf + offset, p, len);
956
957                /* send next request if needed  */
958
959                if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */
960                    len + offset < GATT_MAX_ATTR_LEN)
961                {
962                    GATT_TRACE_DEBUG3("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d",
963                                      offset, len, p_clcb->counter);
964                    gatt_act_read(p_clcb, p_clcb->counter);
965                }
966                else /* end of request, send callback */
967                {
968                    gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
969                }
970            }
971            else /* exception, should not happen */
972            {
973                GATT_TRACE_ERROR2("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf);
974                gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf);
975            }
976        }
977    }
978    else
979    {
980        if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
981            p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
982            p_clcb->read_uuid128.wait_for_read_rsp )
983        {
984            p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
985            p_clcb->read_uuid128.wait_for_read_rsp = FALSE;
986            if (len == LEN_UUID_128)
987            {
988
989                memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
990                p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
991                if ( p_clcb->p_reg->app_cb.p_disc_res_cb)
992                    (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
993                gatt_act_discovery(p_clcb) ;
994            }
995            else
996            {
997                gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
998            }
999        }
1000    }
1001
1002}
1003
1004
1005/*******************************************************************************
1006**
1007** Function         gatt_process_handle_rsp
1008**
1009** Description      This function is called to handle the write response
1010**
1011**
1012** Returns          void
1013**
1014*******************************************************************************/
1015void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
1016{
1017    gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
1018}
1019/*******************************************************************************
1020**
1021** Function         gatt_process_mtu_rsp
1022**
1023** Description      This function is called to process the configure MTU response.
1024**
1025**
1026** Returns          void
1027**
1028*******************************************************************************/
1029void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
1030{
1031    UINT16 mtu;
1032    tGATT_STATUS    status = GATT_SUCCESS;
1033
1034    if (len < GATT_MTU_RSP_MIN_LEN)
1035    {
1036        GATT_TRACE_ERROR0("invalid MTU response PDU received, discard.");
1037        status = GATT_INVALID_PDU;
1038    }
1039    else
1040    {
1041    STREAM_TO_UINT16(mtu, p_data);
1042
1043    if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
1044        p_tcb->payload_size = mtu;
1045    }
1046
1047    gatt_end_operation(p_clcb, status, NULL);
1048}
1049/*******************************************************************************
1050**
1051** Function         gatt_cmd_to_rsp_code
1052**
1053** Description      The function convert a ATT command op code into the corresponding
1054**                  response code assume no error occurs.
1055**
1056** Returns          response code.
1057**
1058*******************************************************************************/
1059UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code)
1060{
1061    UINT8   rsp_code  = 0;
1062
1063    if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE)
1064    {
1065        rsp_code = cmd_code + 1;
1066    }
1067    return rsp_code;
1068}
1069/*******************************************************************************
1070**
1071** Function         gatt_cl_send_next_cmd_inq
1072**
1073** Description      Find next command in queue and sent to server
1074**
1075** Returns          TRUE if command sent, otherwise FALSE.
1076**
1077*******************************************************************************/
1078BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
1079{
1080    tGATT_CMD_Q  *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1081    BOOLEAN     sent = FALSE;
1082    UINT8       rsp_code;
1083    tGATT_CLCB   *p_clcb = NULL;
1084
1085    while (!sent &&
1086           p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
1087           p_cmd->to_send && p_cmd->p_cmd != NULL)
1088    {
1089        sent = attp_send_msg_to_L2CAP(p_tcb, p_cmd->p_cmd);
1090
1091        if (sent)
1092        {
1093            p_cmd->to_send = FALSE;
1094            p_cmd->p_cmd = NULL;
1095
1096            /* dequeue the request if is write command or sign write */
1097            if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
1098            {
1099                gatt_start_rsp_timer (p_tcb);
1100            }
1101            else
1102            {
1103                p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1104
1105                /* if no ack needed, keep sending */
1106                sent = FALSE;
1107                p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1108                /* send command complete callback here */
1109                gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
1110            }
1111        }
1112        else
1113        {
1114            GATT_TRACE_ERROR0("gatt_cl_send_next_cmd_inq: L2CAP sent error");
1115
1116            memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
1117            p_tcb->pending_cl_req ++;
1118            p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1119        }
1120
1121    }
1122    return sent;
1123}
1124
1125/*******************************************************************************
1126**
1127** Function         gatt_client_handle_server_rsp
1128**
1129** Description      This function is called to handle the server response to
1130**                  client.
1131**
1132**
1133** Returns          void
1134**
1135*******************************************************************************/
1136void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
1137                                    UINT16 len, UINT8 *p_data)
1138{
1139    tGATT_CLCB   *p_clcb = NULL;
1140    UINT8        rsp_code;
1141
1142    if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1143    {
1144        p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1145
1146        rsp_code = gatt_cmd_to_rsp_code(rsp_code);
1147
1148        if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR))
1149        {
1150            GATT_TRACE_WARNING2 ("ATT - Ignore wrong response. Receives (%02x) \
1151                                Request(%02x) Ignored", op_code, rsp_code);
1152
1153            return;
1154        }
1155        else
1156            btu_stop_timer (&p_tcb->rsp_timer_ent);
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, op_code, len, 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_tcb, p_clcb, op_code, 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, op_code, 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_tcb, 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