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