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 "bt_common.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     UINT8 *p = p_data;
    615 
    616     tGATT_VALUE value = {
    617         .conn_id = p_clcb->conn_id,
    618         .auth_req = GATT_AUTH_REQ_NONE,
    619     };
    620 
    621     GATT_TRACE_ERROR("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);
    622 
    623     if (len < GATT_PREP_WRITE_RSP_MIN_LEN)
    624     {
    625         GATT_TRACE_ERROR("illegal prepare write response length, discard");
    626         gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
    627         return;
    628     }
    629 
    630     STREAM_TO_UINT16 (value.handle, p);
    631     STREAM_TO_UINT16 (value.offset, p);
    632 
    633     value.len = len - 4;
    634 
    635     memcpy (value.value, p, value.len);
    636 
    637     if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
    638     {
    639         p_clcb->status = GATT_SUCCESS;
    640         /* application should verify handle offset
    641            and value are matched or not */
    642 
    643         gatt_end_operation(p_clcb, p_clcb->status, &value);
    644     }
    645     else if (p_clcb->op_subtype == GATT_WRITE )
    646     {
    647         if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value))
    648             gatt_send_prepare_write(p_tcb, p_clcb);
    649     }
    650 
    651 }
    652 /*******************************************************************************
    653 **
    654 ** Function         gatt_process_notification
    655 **
    656 ** Description      This function is called to handle the handle value indication
    657 **                  or handle value notification.
    658 **
    659 **
    660 ** Returns          void
    661 **
    662 *******************************************************************************/
    663 void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
    664                                UINT16 len, UINT8 *p_data)
    665 {
    666     tGATT_VALUE     value;
    667     tGATT_REG       *p_reg;
    668     UINT16          conn_id;
    669     tGATT_STATUS    encrypt_status;
    670     UINT8           *p= p_data, i,
    671     event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION;
    672 
    673     GATT_TRACE_DEBUG("gatt_process_notification ");
    674 
    675     if (len < GATT_NOTIFICATION_MIN_LEN)
    676     {
    677         GATT_TRACE_ERROR("illegal notification PDU length, discard");
    678         return;
    679     }
    680 
    681     memset(&value, 0, sizeof(value));
    682     STREAM_TO_UINT16(value.handle, p);
    683     value.len = len - 2;
    684     memcpy (value.value, p, value.len);
    685 
    686     if (!GATT_HANDLE_IS_VALID(value.handle))
    687     {
    688         /* illegal handle, send ack now */
    689         if (op_code == GATT_HANDLE_VALUE_IND)
    690             attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
    691         return;
    692     }
    693 
    694     if (event == GATTC_OPTYPE_INDICATION)
    695     {
    696         if (p_tcb->ind_count)
    697         {
    698             /* this is an error case that receiving an indication but we
    699                still has an indication not being acked yet.
    700                For now, just log the error reset the counter.
    701                Later we need to disconnect the link unconditionally.
    702             */
    703             GATT_TRACE_ERROR("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)",  p_tcb->ind_count);
    704         }
    705         p_tcb->ind_count = 0;
    706     }
    707 
    708     /* should notify all registered client with the handle value notificaion/indication
    709        Note: need to do the indication count and start timer first then do callback
    710      */
    711 
    712     for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
    713     {
    714         if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION))
    715             p_tcb->ind_count++;
    716     }
    717 
    718     if (event == GATTC_OPTYPE_INDICATION)
    719     {
    720         /* start a timer for app confirmation */
    721         if (p_tcb->ind_count > 0)
    722             gatt_start_ind_ack_timer(p_tcb);
    723         else /* no app to indicate, or invalid handle */
    724             attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
    725     }
    726 
    727     encrypt_status = gatt_get_link_encrypt_status(p_tcb);
    728     for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
    729     {
    730         if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
    731         {
    732             conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
    733             (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
    734         }
    735     }
    736 
    737 }
    738 
    739 /*******************************************************************************
    740 **
    741 ** Function         gatt_process_read_by_type_rsp
    742 **
    743 ** Description      This function is called to handle the read by type response.
    744 **                  read by type can be used for discovery, or read by type or
    745 **                  read characteristic value.
    746 **
    747 ** Returns          void
    748 **
    749 *******************************************************************************/
    750 void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
    751                                     UINT16 len, UINT8 *p_data)
    752 {
    753     tGATT_DISC_RES      result;
    754     tGATT_DISC_VALUE    record_value;
    755     UINT8               *p = p_data, value_len, handle_len = 2;
    756     UINT16              handle = 0;
    757 
    758     /* discovery procedure and no callback function registered */
    759     if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
    760         return;
    761 
    762     if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN)
    763     {
    764         GATT_TRACE_ERROR("Illegal ReadByType/ReadByGroupType Response length, discard");
    765         gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
    766         return;
    767     }
    768 
    769     STREAM_TO_UINT8(value_len, p);
    770 
    771     if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1))  )
    772     {
    773         /* this is an error case that server's response containing a value length which is larger than MTU-2
    774            or value_len > message total length -1 */
    775         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)",
    776                           op_code, value_len, (p_tcb->payload_size - 2), (len-1));
    777         gatt_end_operation(p_clcb, GATT_ERROR, NULL);
    778         return;
    779     }
    780 
    781     if (op_code == GATT_RSP_READ_BY_GRP_TYPE)
    782         handle_len = 4;
    783 
    784     value_len -= handle_len; /* substract the handle pairs bytes */
    785     len -= 1;
    786 
    787     while (len >= (handle_len + value_len))
    788     {
    789         STREAM_TO_UINT16(handle, p);
    790 
    791         if (!GATT_HANDLE_IS_VALID(handle))
    792         {
    793             gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
    794             return;
    795         }
    796 
    797         memset(&result, 0, sizeof(tGATT_DISC_RES));
    798         memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
    799 
    800         result.handle = handle;
    801         result.type.len = 2;
    802         result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
    803 
    804         /* discover all services */
    805         if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
    806             p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
    807             op_code == GATT_RSP_READ_BY_GRP_TYPE)
    808         {
    809             STREAM_TO_UINT16(handle, p);
    810 
    811             if (!GATT_HANDLE_IS_VALID(handle))
    812             {
    813                 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
    814                 return;
    815             }
    816             else
    817             {
    818                 record_value.group_value.e_handle = handle;
    819                 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p))
    820                 {
    821                     GATT_TRACE_ERROR("discover all service response parsing failure");
    822                     break;
    823                 }
    824             }
    825         }
    826         /* discover included service */
    827         else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC)
    828         {
    829             STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
    830             STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
    831 
    832             if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
    833                 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle))
    834             {
    835                 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
    836                 return;
    837             }
    838 
    839             if(value_len == 6)
    840             {
    841                 STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
    842                 record_value.incl_service.service_type.len = LEN_UUID_16;
    843             }
    844             else if (value_len == 4)
    845             {
    846                 p_clcb->s_handle = record_value.incl_service.s_handle;
    847                 p_clcb->read_uuid128.wait_for_read_rsp = TRUE;
    848                 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
    849                 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
    850                 memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
    851                 p_clcb->op_subtype |= 0x90;
    852                 gatt_act_read(p_clcb, 0);
    853                 return;
    854             }
    855             else
    856             {
    857                GATT_TRACE_ERROR("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len);
    858                gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
    859                return;
    860             }
    861         }
    862         /* read by type */
    863         else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE)
    864         {
    865             p_clcb->counter = len - 2;
    866             p_clcb->s_handle = handle;
    867             if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4))
    868             {
    869                 p_clcb->op_subtype = GATT_READ_BY_HANDLE;
    870                 if (!p_clcb->p_attr_buf)
    871                     p_clcb->p_attr_buf = (UINT8 *)osi_malloc(GATT_MAX_ATTR_LEN);
    872                 if (p_clcb->counter <= GATT_MAX_ATTR_LEN) {
    873                     memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
    874                     gatt_act_read(p_clcb, p_clcb->counter);
    875                 } else {
    876                     gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p);
    877                 }
    878             }
    879             else
    880             {
    881                  gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
    882             }
    883             return;
    884         }
    885         else /* discover characterisitic */
    886         {
    887             STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
    888             STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
    889             if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle))
    890             {
    891                 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
    892                 return;
    893             }
    894             if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
    895             {
    896                 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
    897                 /* invalid format, and skip the result */
    898                 return;
    899             }
    900 
    901             /* UUID not matching */
    902             if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
    903             {
    904                 len -= (value_len + 2);
    905                 continue; /* skip the result, and look for next one */
    906             }
    907             else if (p_clcb->operation == GATTC_OPTYPE_READ)
    908             /* UUID match for read characteristic value */
    909             {
    910                 /* only read the first matching UUID characteristic value, and
    911                   discard the rest results */
    912                 p_clcb->s_handle = record_value.dclr_value.val_handle;
    913                 p_clcb->op_subtype |= 0x80;
    914                 gatt_act_read(p_clcb, 0);
    915                 return;
    916             }
    917         }
    918         len -= (value_len + handle_len);
    919 
    920         /* result is (handle, 16bits UUID) pairs */
    921         memcpy (&result.value, &record_value, sizeof (result.value));
    922 
    923         /* send callback if is discover procedure */
    924         if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb)
    925             (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
    926     }
    927 
    928     p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
    929 
    930     if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
    931     {
    932         /* initiate another request */
    933         gatt_act_discovery(p_clcb) ;
    934     }
    935     else /* read characteristic value */
    936     {
    937         gatt_act_read(p_clcb, 0);
    938     }
    939 }
    940 
    941 /*******************************************************************************
    942 **
    943 ** Function         gatt_process_read_rsp
    944 **
    945 ** Description      This function is called to handle the read BLOB response
    946 **
    947 **
    948 ** Returns          void
    949 **
    950 *******************************************************************************/
    951 void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb,  UINT8 op_code,
    952                            UINT16 len, UINT8 *p_data)
    953 {
    954     UINT16      offset = p_clcb->counter;
    955     UINT8       * p= p_data;
    956 
    957     UNUSED(op_code);
    958 
    959     if (p_clcb->operation == GATTC_OPTYPE_READ)
    960     {
    961         if (p_clcb->op_subtype != GATT_READ_BY_HANDLE)
    962         {
    963             p_clcb->counter = len;
    964             gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
    965         }
    966         else
    967         {
    968 
    969             /* allocate GKI buffer holding up long attribute value  */
    970             if (!p_clcb->p_attr_buf)
    971                 p_clcb->p_attr_buf = (UINT8 *)osi_malloc(GATT_MAX_ATTR_LEN);
    972 
    973             /* copy attrobute value into cb buffer  */
    974             if (offset < GATT_MAX_ATTR_LEN) {
    975                 if ((len + offset) > GATT_MAX_ATTR_LEN)
    976                     len = GATT_MAX_ATTR_LEN - offset;
    977 
    978                 p_clcb->counter += len;
    979 
    980                 memcpy(p_clcb->p_attr_buf + offset, p, len);
    981 
    982                 /* send next request if needed  */
    983 
    984                 if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */
    985                     len + offset < GATT_MAX_ATTR_LEN)
    986                 {
    987                     GATT_TRACE_DEBUG("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d",
    988                                       offset, len, p_clcb->counter);
    989                     gatt_act_read(p_clcb, p_clcb->counter);
    990                 }
    991                 else /* end of request, send callback */
    992                 {
    993                     gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
    994                 }
    995             }
    996             else /* exception, should not happen */
    997             {
    998                 GATT_TRACE_ERROR("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf);
    999                 gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf);
   1000             }
   1001         }
   1002     }
   1003     else
   1004     {
   1005         if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
   1006             p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
   1007             p_clcb->read_uuid128.wait_for_read_rsp )
   1008         {
   1009             p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
   1010             p_clcb->read_uuid128.wait_for_read_rsp = FALSE;
   1011             if (len == LEN_UUID_128)
   1012             {
   1013 
   1014                 memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
   1015                 p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
   1016                 if ( p_clcb->p_reg->app_cb.p_disc_res_cb)
   1017                     (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
   1018                 gatt_act_discovery(p_clcb) ;
   1019             }
   1020             else
   1021             {
   1022                 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
   1023             }
   1024         }
   1025     }
   1026 
   1027 }
   1028 
   1029 
   1030 /*******************************************************************************
   1031 **
   1032 ** Function         gatt_process_handle_rsp
   1033 **
   1034 ** Description      This function is called to handle the write response
   1035 **
   1036 **
   1037 ** Returns          void
   1038 **
   1039 *******************************************************************************/
   1040 void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
   1041 {
   1042     gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
   1043 }
   1044 /*******************************************************************************
   1045 **
   1046 ** Function         gatt_process_mtu_rsp
   1047 **
   1048 ** Description      This function is called to process the configure MTU response.
   1049 **
   1050 **
   1051 ** Returns          void
   1052 **
   1053 *******************************************************************************/
   1054 void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
   1055 {
   1056     UINT16 mtu;
   1057     tGATT_STATUS    status = GATT_SUCCESS;
   1058 
   1059     if (len < GATT_MTU_RSP_MIN_LEN)
   1060     {
   1061         GATT_TRACE_ERROR("invalid MTU response PDU received, discard.");
   1062         status = GATT_INVALID_PDU;
   1063     }
   1064     else
   1065     {
   1066     STREAM_TO_UINT16(mtu, p_data);
   1067 
   1068     if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
   1069         p_tcb->payload_size = mtu;
   1070     }
   1071 
   1072     l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
   1073     gatt_end_operation(p_clcb, status, NULL);
   1074 }
   1075 /*******************************************************************************
   1076 **
   1077 ** Function         gatt_cmd_to_rsp_code
   1078 **
   1079 ** Description      The function convert a ATT command op code into the corresponding
   1080 **                  response code assume no error occurs.
   1081 **
   1082 ** Returns          response code.
   1083 **
   1084 *******************************************************************************/
   1085 UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code)
   1086 {
   1087     UINT8   rsp_code  = 0;
   1088 
   1089     if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE)
   1090     {
   1091         rsp_code = cmd_code + 1;
   1092     }
   1093     return rsp_code;
   1094 }
   1095 /*******************************************************************************
   1096 **
   1097 ** Function         gatt_cl_send_next_cmd_inq
   1098 **
   1099 ** Description      Find next command in queue and sent to server
   1100 **
   1101 ** Returns          TRUE if command sent, otherwise FALSE.
   1102 **
   1103 *******************************************************************************/
   1104 BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
   1105 {
   1106     tGATT_CMD_Q  *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
   1107     BOOLEAN     sent = FALSE;
   1108     UINT8       rsp_code;
   1109     tGATT_CLCB   *p_clcb = NULL;
   1110     tGATT_STATUS att_ret = GATT_SUCCESS;
   1111 
   1112     while (!sent &&
   1113            p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
   1114            p_cmd->to_send && p_cmd->p_cmd != NULL)
   1115     {
   1116         att_ret = attp_send_msg_to_l2cap(p_tcb, p_cmd->p_cmd);
   1117 
   1118         if (att_ret == GATT_SUCCESS || att_ret == GATT_CONGESTED)
   1119         {
   1120             sent = TRUE;
   1121             p_cmd->to_send = FALSE;
   1122             p_cmd->p_cmd = NULL;
   1123 
   1124             /* dequeue the request if is write command or sign write */
   1125             if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
   1126             {
   1127                 gatt_start_rsp_timer (p_cmd->clcb_idx);
   1128             }
   1129             else
   1130             {
   1131                 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
   1132 
   1133                 /* if no ack needed, keep sending */
   1134                 if (att_ret == GATT_SUCCESS)
   1135                     sent = FALSE;
   1136 
   1137                 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
   1138                 /* send command complete callback here */
   1139                 gatt_end_operation(p_clcb, att_ret, NULL);
   1140             }
   1141         }
   1142         else
   1143         {
   1144             GATT_TRACE_ERROR("gatt_cl_send_next_cmd_inq: L2CAP sent error");
   1145 
   1146             memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
   1147             p_tcb->pending_cl_req ++;
   1148             p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
   1149         }
   1150 
   1151     }
   1152     return sent;
   1153 }
   1154 
   1155 /*******************************************************************************
   1156 **
   1157 ** Function         gatt_client_handle_server_rsp
   1158 **
   1159 ** Description      This function is called to handle the server response to
   1160 **                  client.
   1161 **
   1162 **
   1163 ** Returns          void
   1164 **
   1165 *******************************************************************************/
   1166 void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
   1167                                     UINT16 len, UINT8 *p_data)
   1168 {
   1169     tGATT_CLCB   *p_clcb = NULL;
   1170     UINT8        rsp_code;
   1171 
   1172     if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
   1173     {
   1174         p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
   1175 
   1176         rsp_code = gatt_cmd_to_rsp_code(rsp_code);
   1177 
   1178         if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR))
   1179         {
   1180             GATT_TRACE_WARNING ("ATT - Ignore wrong response. Receives (%02x) \
   1181                                 Request(%02x) Ignored", op_code, rsp_code);
   1182 
   1183             return;
   1184         }
   1185         else
   1186         {
   1187             alarm_cancel(p_clcb->gatt_rsp_timer_ent);
   1188             p_clcb->retry_count = 0;
   1189         }
   1190     }
   1191     /* the size of the message may not be bigger than the local max PDU size*/
   1192     /* The message has to be smaller than the agreed MTU, len does not count op_code */
   1193     if (len >= p_tcb->payload_size)
   1194     {
   1195         GATT_TRACE_ERROR("invalid response/indicate pkt size: %d, PDU size: %d", len + 1, p_tcb->payload_size);
   1196         if (op_code != GATT_HANDLE_VALUE_NOTIF &&
   1197             op_code != GATT_HANDLE_VALUE_IND)
   1198             gatt_end_operation(p_clcb, GATT_ERROR, NULL);
   1199     }
   1200     else
   1201     {
   1202         switch (op_code)
   1203         {
   1204             case GATT_RSP_ERROR:
   1205                 gatt_process_error_rsp(p_tcb, p_clcb, op_code, len, p_data);
   1206                 break;
   1207 
   1208             case GATT_RSP_MTU:       /* 2 bytes mtu */
   1209                 gatt_process_mtu_rsp(p_tcb, p_clcb, len ,p_data);
   1210                 break;
   1211 
   1212             case GATT_RSP_FIND_INFO:
   1213                 gatt_process_read_info_rsp(p_tcb, p_clcb, op_code, len, p_data);
   1214                 break;
   1215 
   1216             case GATT_RSP_READ_BY_TYPE:
   1217             case GATT_RSP_READ_BY_GRP_TYPE:
   1218                 gatt_process_read_by_type_rsp(p_tcb, p_clcb, op_code, len, p_data);
   1219                 break;
   1220 
   1221             case GATT_RSP_READ:
   1222             case GATT_RSP_READ_BLOB:
   1223             case GATT_RSP_READ_MULTI:
   1224                 gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data);
   1225                 break;
   1226 
   1227             case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
   1228                 gatt_process_find_type_value_rsp(p_tcb, p_clcb, len, p_data);
   1229                 break;
   1230 
   1231             case GATT_RSP_WRITE:
   1232                 gatt_process_handle_rsp(p_clcb);
   1233                 break;
   1234 
   1235             case GATT_RSP_PREPARE_WRITE:
   1236                 gatt_process_prep_write_rsp(p_tcb, p_clcb, op_code, len, p_data);
   1237                 break;
   1238 
   1239             case GATT_RSP_EXEC_WRITE:
   1240                 gatt_end_operation(p_clcb, p_clcb->status, NULL);
   1241                 break;
   1242 
   1243             case GATT_HANDLE_VALUE_NOTIF:
   1244             case GATT_HANDLE_VALUE_IND:
   1245                 gatt_process_notification(p_tcb, op_code, len, p_data);
   1246                 break;
   1247 
   1248             default:
   1249                 GATT_TRACE_ERROR("Unknown opcode = %d", op_code);
   1250                 break;
   1251         }
   1252     }
   1253 
   1254     if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
   1255     {
   1256         gatt_cl_send_next_cmd_inq(p_tcb);
   1257     }
   1258 
   1259     return;
   1260 }
   1261 
   1262 #endif  /* BLE_INCLUDED */
   1263