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