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