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