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 "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 *********************************************************************************/
     48 void gatt_send_prepare_write(tGATT_TCB  *p_tcb, tGATT_CLCB *p_clcb);
     49 
     50 UINT8   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 
     60 UINT16 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 *******************************************************************************/
     80 void 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 *******************************************************************************/
    136 void 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 *******************************************************************************/
    224 void 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 rt=%d", op_code, rt);
    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 *******************************************************************************/
    297 void 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 *******************************************************************************/
    319 BOOLEAN 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 *******************************************************************************/
    362 void 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 *******************************************************************************/
    413 void 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 *******************************************************************************/
    458 void 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 *******************************************************************************/
    517 void 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 *******************************************************************************/
    557 void 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 *******************************************************************************/
    610 void 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 *******************************************************************************/
    658 void 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 *******************************************************************************/
    744 void 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 *******************************************************************************/
    946 void 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 *******************************************************************************/
   1036 void 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 *******************************************************************************/
   1050 void 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 *******************************************************************************/
   1080 UINT8 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 *******************************************************************************/
   1099 BOOLEAN 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 *******************************************************************************/
   1161 void 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