Home | History | Annotate | Download | only in gatt
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2008-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 GATT server functions
     22  *
     23  ******************************************************************************/
     24 
     25 #include "bt_target.h"
     26 #include "bt_utils.h"
     27 
     28 #if BLE_INCLUDED == TRUE
     29 #include <string.h>
     30 #include "gatt_int.h"
     31 #include "l2c_api.h"
     32 
     33 #define GATT_MTU_REQ_MIN_LEN        2
     34 
     35 
     36 /*******************************************************************************
     37 **
     38 ** Function         gatt_sr_enqueue_cmd
     39 **
     40 ** Description      This function enqueue the request from client which needs a
     41 **                  application response, and update the transaction ID.
     42 **
     43 ** Returns          void
     44 **
     45 *******************************************************************************/
     46 UINT32 gatt_sr_enqueue_cmd (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 handle)
     47 {
     48     tGATT_SR_CMD   *p_cmd = &p_tcb->sr_cmd;
     49     UINT32          trans_id = 0;
     50 
     51     if ( (p_cmd->op_code == 0) ||
     52          (op_code == GATT_HANDLE_VALUE_CONF)) /* no pending request */
     53     {
     54         if (op_code == GATT_CMD_WRITE ||
     55             op_code == GATT_SIGN_CMD_WRITE  ||
     56             op_code == GATT_REQ_MTU ||
     57             op_code == GATT_HANDLE_VALUE_CONF)
     58         {
     59             trans_id = ++p_tcb->trans_id;
     60         }
     61         else
     62         {
     63             p_cmd->trans_id   = ++p_tcb->trans_id;
     64             p_cmd->op_code    = op_code;
     65             p_cmd->handle     = handle;
     66             p_cmd->status     = GATT_NOT_FOUND;
     67             p_tcb->trans_id %= GATT_TRANS_ID_MAX;
     68             trans_id = p_cmd->trans_id;
     69         }
     70     }
     71 
     72     return trans_id;
     73 }
     74 
     75 /*******************************************************************************
     76 **
     77 ** Function         gatt_sr_cmd_empty
     78 **
     79 ** Description      This function check the server command queue is empty or not.
     80 **
     81 ** Returns          TRUE if empty, FALSE if there is pending command.
     82 **
     83 *******************************************************************************/
     84 BOOLEAN gatt_sr_cmd_empty (tGATT_TCB *p_tcb)
     85 {
     86     return(p_tcb->sr_cmd.op_code == 0);
     87 }
     88 
     89 /*******************************************************************************
     90 **
     91 ** Function         gatt_dequeue_sr_cmd
     92 **
     93 ** Description      This function dequeue the request from command queue.
     94 **
     95 ** Returns          void
     96 **
     97 *******************************************************************************/
     98 void gatt_dequeue_sr_cmd (tGATT_TCB *p_tcb)
     99 {
    100     /* Double check in case any buffers are queued */
    101     GATT_TRACE_DEBUG("gatt_dequeue_sr_cmd" );
    102     if (p_tcb->sr_cmd.p_rsp_msg)
    103     {
    104         GATT_TRACE_ERROR("free p_tcb->sr_cmd.p_rsp_msg = %d", p_tcb->sr_cmd.p_rsp_msg);
    105 
    106         GKI_freebuf (p_tcb->sr_cmd.p_rsp_msg);
    107     }
    108 
    109     while (p_tcb->sr_cmd.multi_rsp_q.p_first)
    110         GKI_freebuf (GKI_dequeue (&p_tcb->sr_cmd.multi_rsp_q));
    111     memset( &p_tcb->sr_cmd, 0, sizeof(tGATT_SR_CMD));
    112 }
    113 
    114 /*******************************************************************************
    115 **
    116 ** Function         process_read_multi_rsp
    117 **
    118 ** Description      This function check the read multiple response.
    119 **
    120 ** Returns          BOOLEAN if all replies have been received
    121 **
    122 *******************************************************************************/
    123 static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status,
    124                                        tGATTS_RSP *p_msg, UINT16 mtu)
    125 {
    126     tGATTS_RSP       *p_rsp;
    127     UINT16          ii, total_len, len;
    128     BT_HDR          *p_buf = (BT_HDR *)GKI_getbuf((UINT16)sizeof(tGATTS_RSP));
    129     UINT8           *p;
    130     BOOLEAN         is_overflow = FALSE;
    131 
    132     GATT_TRACE_DEBUG ("process_read_multi_rsp status=%d mtu=%d", status, mtu);
    133 
    134     if (p_buf == NULL)
    135     {
    136         p_cmd->status = GATT_INSUF_RESOURCE;
    137         return FALSE;
    138     }
    139 
    140     /* Enqueue the response */
    141     memcpy((void *)p_buf, (const void *)p_msg, sizeof(tGATTS_RSP));
    142     GKI_enqueue (&p_cmd->multi_rsp_q, p_buf);
    143 
    144     p_cmd->status = status;
    145     if (status == GATT_SUCCESS)
    146     {
    147         GATT_TRACE_DEBUG ("Multi read count=%d num_hdls=%d",
    148                            p_cmd->multi_rsp_q.count, p_cmd->multi_req.num_handles);
    149         /* Wait till we get all the responses */
    150         if (p_cmd->multi_rsp_q.count == p_cmd->multi_req.num_handles)
    151         {
    152             len = sizeof(BT_HDR) + L2CAP_MIN_OFFSET + mtu;
    153             if ((p_buf = (BT_HDR *)GKI_getbuf(len)) == NULL)
    154             {
    155                 p_cmd->status = GATT_INSUF_RESOURCE;
    156                 return(TRUE);
    157             }
    158 
    159             memset(p_buf, 0, len);
    160             p_buf->offset = L2CAP_MIN_OFFSET;
    161             p = (UINT8 *)(p_buf + 1) + p_buf->offset;
    162 
    163             /* First byte in the response is the opcode */
    164             *p++ = GATT_RSP_READ_MULTI;
    165             p_buf->len = 1;
    166 
    167             /* Now walk through the buffers puting the data into the response in order */
    168             for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++)
    169             {
    170                 if (ii==0)
    171                 {
    172                     p_rsp = (tGATTS_RSP *)GKI_getfirst (&p_cmd->multi_rsp_q);
    173                 }
    174                 else
    175                 {
    176                     p_rsp = (tGATTS_RSP *)GKI_getnext (p_rsp);
    177                 }
    178 
    179                 if (p_rsp != NULL)
    180                 {
    181 
    182                     total_len = (p_buf->len + p_rsp->attr_value.len);
    183 
    184                     if (total_len >  mtu)
    185                     {
    186                         /* just send the partial response for the overflow case */
    187                         len = p_rsp->attr_value.len - (total_len - mtu);
    188                         is_overflow = TRUE;
    189                         GATT_TRACE_DEBUG ("multi read overflow available len=%d val_len=%d", len, p_rsp->attr_value.len );
    190                     }
    191                     else
    192                     {
    193                         len = p_rsp->attr_value.len;
    194                     }
    195 
    196                     if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii])
    197                     {
    198                         memcpy (p, p_rsp->attr_value.value, len);
    199                         if (!is_overflow)
    200                             p += len;
    201                         p_buf->len += len;
    202                     }
    203                     else
    204                     {
    205                         p_cmd->status        = GATT_NOT_FOUND;
    206                         break;
    207                     }
    208 
    209                     if (is_overflow)
    210                         break;
    211 
    212                 }
    213                 else
    214                 {
    215                     p_cmd->status        = GATT_NOT_FOUND;
    216                     break;
    217                 }
    218 
    219             } /* loop through all handles*/
    220 
    221 
    222             /* Sanity check on the buffer length */
    223             if (p_buf->len == 0)
    224             {
    225                 GATT_TRACE_ERROR("process_read_multi_rsp - nothing found!!");
    226                 p_cmd->status = GATT_NOT_FOUND;
    227                 GKI_freebuf (p_buf);
    228                 GATT_TRACE_DEBUG(" GKI_freebuf (p_buf)");
    229             }
    230             else if (p_cmd->p_rsp_msg != NULL)
    231             {
    232                 GKI_freebuf (p_buf);
    233             }
    234             else
    235             {
    236                 p_cmd->p_rsp_msg = p_buf;
    237             }
    238 
    239             return(TRUE);
    240         }
    241     }
    242     else    /* any handle read exception occurs, return error */
    243     {
    244         return(TRUE);
    245     }
    246 
    247     /* If here, still waiting */
    248     return(FALSE);
    249 }
    250 
    251 /*******************************************************************************
    252 **
    253 ** Function         gatt_sr_process_app_rsp
    254 **
    255 ** Description      This function checks whether the response message from application
    256 **                  match any pending request or not.
    257 **
    258 ** Returns          void
    259 **
    260 *******************************************************************************/
    261 tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
    262                                       UINT32 trans_id, UINT8 op_code,
    263                                       tGATT_STATUS status, tGATTS_RSP *p_msg)
    264 {
    265     tGATT_STATUS    ret_code = GATT_SUCCESS;
    266     UNUSED(trans_id);
    267 
    268     GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d", gatt_if);
    269 
    270     gatt_sr_update_cback_cnt(p_tcb, gatt_if, FALSE, FALSE);
    271 
    272     if (op_code == GATT_REQ_READ_MULTI)
    273     {
    274         /* If no error and still waiting, just return */
    275         if (!process_read_multi_rsp (&p_tcb->sr_cmd, status, p_msg, p_tcb->payload_size))
    276             return(GATT_SUCCESS);
    277     }
    278     else
    279     {
    280         if (op_code == GATT_REQ_PREPARE_WRITE && status == GATT_SUCCESS)
    281             gatt_sr_update_prep_cnt(p_tcb, gatt_if, TRUE, FALSE);
    282 
    283         if (op_code == GATT_REQ_EXEC_WRITE && status != GATT_SUCCESS)
    284             gatt_sr_reset_cback_cnt(p_tcb);
    285 
    286         p_tcb->sr_cmd.status = status;
    287 
    288         if (gatt_sr_is_cback_cnt_zero(p_tcb)
    289             && status == GATT_SUCCESS)
    290         {
    291             if (p_tcb->sr_cmd.p_rsp_msg == NULL)
    292             {
    293                 p_tcb->sr_cmd.p_rsp_msg = attp_build_sr_msg (p_tcb, (UINT8)(op_code + 1), (tGATT_SR_MSG *)p_msg);
    294             }
    295             else
    296             {
    297                 GATT_TRACE_ERROR("Exception!!! already has respond message");
    298             }
    299         }
    300     }
    301     if (gatt_sr_is_cback_cnt_zero(p_tcb))
    302     {
    303         if ( (p_tcb->sr_cmd.status == GATT_SUCCESS) && (p_tcb->sr_cmd.p_rsp_msg) )
    304         {
    305             ret_code = attp_send_sr_msg (p_tcb, p_tcb->sr_cmd.p_rsp_msg);
    306             p_tcb->sr_cmd.p_rsp_msg = NULL;
    307         }
    308         else
    309         {
    310             ret_code = gatt_send_error_rsp (p_tcb, status, op_code, p_tcb->sr_cmd.handle, FALSE);
    311         }
    312 
    313         gatt_dequeue_sr_cmd(p_tcb);
    314     }
    315 
    316     GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d", ret_code);
    317 
    318     return ret_code;
    319 }
    320 
    321 /*******************************************************************************
    322 **
    323 ** Function         gatt_process_exec_write_req
    324 **
    325 ** Description      This function is called to process the execute write request
    326 **                  from client.
    327 **
    328 ** Returns          void
    329 **
    330 *******************************************************************************/
    331 void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
    332 {
    333     UINT8   *p = p_data, flag, i = 0;
    334     UINT32  trans_id = 0;
    335     BT_HDR  *p_buf;
    336     tGATT_IF gatt_if;
    337     UINT16  conn_id;
    338 
    339     UNUSED(len);
    340 
    341 #if GATT_CONFORMANCE_TESTING == TRUE
    342     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
    343     {
    344         GATT_TRACE_DEBUG("Conformance tst: forced err rspv for Execute Write: error status=%d",
    345         gatt_cb.err_status);
    346 
    347         gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, gatt_cb.handle, FALSE);
    348 
    349         return;
    350     }
    351 #endif
    352 
    353     STREAM_TO_UINT8(flag, p);
    354 
    355     /* mask the flag */
    356     flag &= GATT_PREP_WRITE_EXEC;
    357 
    358 
    359     /* no prep write is queued */
    360     if (!gatt_sr_is_prep_cnt_zero(p_tcb))
    361     {
    362         trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
    363         gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
    364 
    365         for (i=0; i<GATT_MAX_APPS; i++)
    366         {
    367             if (p_tcb->prep_cnt[i])
    368             {
    369                 gatt_if = (tGATT_IF) (i+1);
    370                 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
    371                 gatt_sr_send_req_callback(conn_id,
    372                                           trans_id,
    373                                           GATTS_REQ_TYPE_WRITE_EXEC,
    374                                           (tGATTS_DATA *)&flag);
    375                 p_tcb->prep_cnt[i]= 0;
    376             }
    377         }
    378     }
    379     else /* nothing needs to be executed , send response now */
    380     {
    381         GATT_TRACE_ERROR("gatt_process_exec_write_req: no prepare write pending");
    382         gatt_send_error_rsp(p_tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, FALSE);
    383     }
    384 }
    385 
    386 /*******************************************************************************
    387 **
    388 ** Function         gatt_process_read_multi_req
    389 **
    390 ** Description      This function is called to process the read multiple request
    391 **                  from client.
    392 **
    393 ** Returns          void
    394 **
    395 *******************************************************************************/
    396 void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
    397 {
    398     UINT32          trans_id;
    399     UINT16          handle = 0, ll = len;
    400     UINT8           *p = p_data, i_rcb;
    401     tGATT_STATUS    err = GATT_SUCCESS;
    402     UINT8           sec_flag, key_size;
    403     tGATTS_RSP       *p_msg;
    404 
    405     GATT_TRACE_DEBUG("gatt_process_read_multi_req" );
    406     p_tcb->sr_cmd.multi_req.num_handles = 0;
    407 
    408     gatt_sr_get_sec_info(p_tcb->peer_bda,
    409                          p_tcb->transport,
    410                          &sec_flag,
    411                          &key_size);
    412 
    413 #if GATT_CONFORMANCE_TESTING == TRUE
    414     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
    415     {
    416         GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d", gatt_cb.err_status);
    417 
    418         STREAM_TO_UINT16(handle, p);
    419 
    420         gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE);
    421 
    422         return;
    423     }
    424 #endif
    425 
    426     while (ll >= 2 && p_tcb->sr_cmd.multi_req.num_handles < GATT_MAX_READ_MULTI_HANDLES)
    427     {
    428         STREAM_TO_UINT16(handle, p);
    429 
    430         if ((i_rcb = gatt_sr_find_i_rcb_by_handle(handle)) < GATT_MAX_SR_PROFILES)
    431         {
    432             p_tcb->sr_cmd.multi_req.handles[p_tcb->sr_cmd.multi_req.num_handles++] = handle;
    433 
    434             /* check read permission */
    435             if ((err = gatts_read_attr_perm_check(   gatt_cb.sr_reg[i_rcb].p_db,
    436                                                      FALSE,
    437                                                      handle,
    438                                                      sec_flag,
    439                                                      key_size))
    440                 != GATT_SUCCESS)
    441             {
    442                 GATT_TRACE_DEBUG("read permission denied : 0x%02x", err);
    443                 break;
    444             }
    445         }
    446         else
    447         {
    448             /* invalid handle */
    449             err = GATT_INVALID_HANDLE;
    450             break;
    451         }
    452         ll -= 2;
    453     }
    454 
    455     if (ll != 0)
    456     {
    457         GATT_TRACE_ERROR("max attribute handle reached in ReadMultiple Request.");
    458     }
    459 
    460     if (p_tcb->sr_cmd.multi_req.num_handles == 0)
    461         err = GATT_INVALID_HANDLE;
    462 
    463     if (err == GATT_SUCCESS)
    464     {
    465         if ((trans_id = gatt_sr_enqueue_cmd (p_tcb, op_code, p_tcb->sr_cmd.multi_req.handles[0])) != 0)
    466         {
    467             gatt_sr_reset_cback_cnt(p_tcb); /* read multiple use multi_rsp_q's count*/
    468 
    469             for (ll = 0; ll < p_tcb->sr_cmd.multi_req.num_handles; ll ++)
    470             {
    471                 if ((p_msg = (tGATTS_RSP *)GKI_getbuf(sizeof(tGATTS_RSP))) != NULL)
    472                 {
    473                     memset(p_msg, 0, sizeof(tGATTS_RSP))
    474                     ;
    475                     handle = p_tcb->sr_cmd.multi_req.handles[ll];
    476                     i_rcb = gatt_sr_find_i_rcb_by_handle(handle);
    477 
    478                     p_msg->attr_value.handle = handle;
    479                     err = gatts_read_attr_value_by_handle(p_tcb,
    480                                                           gatt_cb.sr_reg[i_rcb].p_db,
    481                                                           op_code,
    482                                                           handle,
    483                                                           0,
    484                                                           p_msg->attr_value.value,
    485                                                           &p_msg->attr_value.len,
    486                                                           GATT_MAX_ATTR_LEN,
    487                                                           sec_flag,
    488                                                           key_size,
    489                                                           trans_id);
    490 
    491                     if (err == GATT_SUCCESS)
    492                     {
    493                         gatt_sr_process_app_rsp(p_tcb, gatt_cb.sr_reg[i_rcb].gatt_if ,trans_id, op_code, GATT_SUCCESS, p_msg);
    494                     }
    495                     /* either not using or done using the buffer, release it now */
    496                     GKI_freebuf(p_msg);
    497                 }
    498                 else
    499                 {
    500                     err = GATT_NO_RESOURCES;
    501                     gatt_dequeue_sr_cmd(p_tcb);
    502                     break;
    503                 }
    504             }
    505         }
    506         else
    507             err = GATT_NO_RESOURCES;
    508     }
    509 
    510     /* in theroy BUSY is not possible(should already been checked), protected check */
    511     if (err != GATT_SUCCESS && err != GATT_PENDING && err != GATT_BUSY)
    512         gatt_send_error_rsp(p_tcb, err, op_code, handle, FALSE);
    513 }
    514 
    515 /*******************************************************************************
    516 **
    517 ** Function         gatt_build_primary_service_rsp
    518 **
    519 ** Description      Primamry service request processed internally. Theretically
    520 **                  only deal with ReadByTypeVAlue and ReadByGroupType.
    521 **
    522 ** Returns          void
    523 **
    524 *******************************************************************************/
    525 static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_tcb,
    526                                                     UINT8 op_code, UINT16 s_hdl,
    527                                                     UINT16 e_hdl, UINT8 *p_data, tBT_UUID value)
    528 {
    529     tGATT_STATUS    status = GATT_NOT_FOUND;
    530     UINT8           handle_len =4, *p ;
    531     tGATT_SR_REG    *p_rcb;
    532     tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
    533     tGATT_SRV_LIST_ELEM  *p_srv=NULL;
    534     tBT_UUID       *p_uuid;
    535 
    536     UNUSED(p_data);
    537 
    538     p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
    539 
    540     p_srv = p_list->p_first;
    541 
    542     while (p_srv)
    543     {
    544         p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
    545 
    546         if (p_rcb->in_use &&
    547             p_rcb->s_hdl >= s_hdl &&
    548             p_rcb->s_hdl <= e_hdl &&
    549             p_rcb->type == GATT_UUID_PRI_SERVICE)
    550         {
    551             if ((p_uuid = gatts_get_service_uuid (p_rcb->p_db)) != NULL)
    552             {
    553                 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
    554                     handle_len = 4 + p_uuid->len;
    555 
    556                 /* get the length byte in the repsonse */
    557                 if (p_msg->offset ==0)
    558                 {
    559                     *p ++ = op_code + 1;
    560                     p_msg->len ++;
    561                     p_msg->offset = handle_len;
    562 
    563                     if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
    564                     {
    565                         *p ++ =  (UINT8)p_msg->offset; /* length byte */
    566                         p_msg->len ++;
    567                     }
    568                 }
    569 
    570                 if (p_msg->len + p_msg->offset <= p_tcb->payload_size &&
    571                     handle_len == p_msg->offset)
    572                 {
    573                     if (op_code != GATT_REQ_FIND_TYPE_VALUE ||
    574                         gatt_uuid_compare(value, *p_uuid))
    575                     {
    576                         UINT16_TO_STREAM(p, p_rcb->s_hdl);
    577 
    578                         if (p_list->p_last_primary == p_srv &&
    579                             p_list->p_last_primary == p_list->p_last)
    580                         {
    581                             GATT_TRACE_DEBUG("Use 0xFFFF for the last primary attribute");
    582                             UINT16_TO_STREAM(p, 0xFFFF); /* see GATT ERRATA 4065, 4063, ATT ERRATA 4062 */
    583                         }
    584                         else
    585                         {
    586                             UINT16_TO_STREAM(p, p_rcb->e_hdl);
    587                         }
    588 
    589                         if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
    590                             gatt_build_uuid_to_stream(&p, *p_uuid);
    591 
    592                         status = GATT_SUCCESS;
    593                         p_msg->len += p_msg->offset;
    594                     }
    595                 }
    596                 else
    597                     break;
    598             }
    599         }
    600         p_srv = p_srv->p_next;
    601     }
    602     p_msg->offset = L2CAP_MIN_OFFSET;
    603 
    604     return status;
    605 }
    606 
    607 /*******************************************************************************
    608 **
    609 ** Function         gatt_build_find_info_rsp
    610 **
    611 ** Description      fill the find information response information in the given
    612 **                  buffer.
    613 **
    614 ** Returns          TRUE: if data filled sucessfully.
    615 **                  FALSE: packet full, or format mismatch.
    616 **
    617 *******************************************************************************/
    618 static tGATT_STATUS gatt_build_find_info_rsp(tGATT_SR_REG *p_rcb, BT_HDR *p_msg, UINT16 *p_len,
    619                                              UINT16 s_hdl, UINT16 e_hdl)
    620 {
    621     tGATT_STATUS        status = GATT_NOT_FOUND;
    622     UINT8               *p;
    623     UINT16              len = *p_len;
    624     tGATT_ATTR16        *p_attr = NULL;
    625     UINT8               info_pair_len[2] = {4, 18};
    626 
    627     if (!p_rcb->p_db || !p_rcb->p_db->p_attr_list)
    628         return status;
    629 
    630     /* check the attribute database */
    631     p_attr = (tGATT_ATTR16 *) p_rcb->p_db->p_attr_list;
    632 
    633     p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET + p_msg->len;
    634 
    635     while (p_attr)
    636     {
    637         if (p_attr->handle > e_hdl)
    638         {
    639             break;
    640         }
    641 
    642         if (p_attr->handle >= s_hdl)
    643         {
    644             if (p_msg->offset == 0)
    645                 p_msg->offset = (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) ? GATT_INFO_TYPE_PAIR_16 : GATT_INFO_TYPE_PAIR_128;
    646 
    647             if (len >= info_pair_len[p_msg->offset - 1])
    648             {
    649                 if (p_msg->offset == GATT_INFO_TYPE_PAIR_16 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16)
    650                 {
    651                     UINT16_TO_STREAM(p, p_attr->handle);
    652                     UINT16_TO_STREAM(p, p_attr->uuid);
    653                 }
    654                 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_128  )
    655                 {
    656                     UINT16_TO_STREAM(p, p_attr->handle);
    657                     ARRAY_TO_STREAM (p, ((tGATT_ATTR128 *) p_attr)->uuid, LEN_UUID_128);
    658                 }
    659                 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_32)
    660                 {
    661                     UINT16_TO_STREAM(p, p_attr->handle);
    662                     gatt_convert_uuid32_to_uuid128(p, ((tGATT_ATTR32 *) p_attr)->uuid);
    663                     p += LEN_UUID_128;
    664                 }
    665                 else
    666                 {
    667                     GATT_TRACE_ERROR("format mismatch");
    668                     status = GATT_NO_RESOURCES;
    669                     break;
    670                     /* format mismatch */
    671                 }
    672                 p_msg->len += info_pair_len[p_msg->offset - 1];
    673                 len -= info_pair_len[p_msg->offset - 1];
    674                 status = GATT_SUCCESS;
    675 
    676             }
    677             else
    678             {
    679                 status = GATT_NO_RESOURCES;
    680                 break;
    681             }
    682         }
    683         p_attr = (tGATT_ATTR16 *)p_attr->p_next;
    684     }
    685 
    686     *p_len = len;
    687     return status;
    688 }
    689 
    690 /*******************************************************************************
    691 **
    692 ** Function         gatts_internal_read_by_type_req
    693 **
    694 ** Description      check to see if the ReadByType request can be handled internally.
    695 **
    696 ** Returns          void
    697 **
    698 *******************************************************************************/
    699 static tGATT_STATUS gatts_validate_packet_format(UINT8 op_code, UINT16 *p_len,
    700                                                  UINT8 **p_data, tBT_UUID *p_uuid_filter,
    701                                                  UINT16 *p_s_hdl, UINT16 *p_e_hdl)
    702 {
    703     tGATT_STATUS    reason = GATT_SUCCESS;
    704     UINT16          uuid_len, s_hdl = 0, e_hdl = 0;
    705     UINT16          len = *p_len;
    706     UINT8           *p = *p_data;
    707 
    708     if (len >= 4)
    709     {
    710         /* obtain starting handle, and ending handle */
    711         STREAM_TO_UINT16(s_hdl, p);
    712         STREAM_TO_UINT16(e_hdl, p);
    713         len -= 4;
    714 
    715         if (s_hdl > e_hdl || !GATT_HANDLE_IS_VALID(s_hdl) || !GATT_HANDLE_IS_VALID(e_hdl))
    716         {
    717             reason = GATT_INVALID_HANDLE;
    718         }
    719         /* for these PDUs, uuid filter must present */
    720         else if (op_code == GATT_REQ_READ_BY_GRP_TYPE ||
    721                  op_code == GATT_REQ_FIND_TYPE_VALUE ||
    722                  op_code == GATT_REQ_READ_BY_TYPE)
    723         {
    724             if (len >= 2 && p_uuid_filter != NULL)
    725             {
    726                 uuid_len = (op_code == GATT_REQ_FIND_TYPE_VALUE) ? 2 : len;
    727 
    728                 /* parse uuid now */
    729                 if (gatt_parse_uuid_from_cmd (p_uuid_filter, uuid_len, &p) == FALSE ||
    730                     p_uuid_filter->len == 0)
    731                 {
    732                     GATT_TRACE_DEBUG("UUID filter does not exsit");
    733                     reason = GATT_INVALID_PDU;
    734                 }
    735                 else
    736                     len -= p_uuid_filter->len;
    737             }
    738             else
    739                 reason = GATT_INVALID_PDU;
    740         }
    741     }
    742     else
    743         reason = GATT_INVALID_PDU;
    744 
    745     *p_data     = p;
    746     *p_len      = len;
    747     *p_s_hdl    = s_hdl;
    748     *p_e_hdl    = e_hdl;
    749 
    750     return reason;
    751 }
    752 
    753 /*******************************************************************************
    754 **
    755 ** Function         gatts_process_primary_service_req
    756 **
    757 ** Description      process ReadByGroupType/ReadByTypeValue request, for discover
    758 **                  all primary services or discover primary service by UUID request.
    759 **
    760 ** Returns          void
    761 **
    762 *******************************************************************************/
    763 void gatts_process_primary_service_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
    764 {
    765     UINT8           reason = GATT_INVALID_PDU;
    766     UINT16          s_hdl = 0, e_hdl = 0;
    767     tBT_UUID        uuid, value, primary_service = {LEN_UUID_16, {GATT_UUID_PRI_SERVICE}};
    768     BT_HDR          *p_msg = NULL;
    769     UINT16          msg_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
    770 
    771     memset (&value, 0, sizeof(tBT_UUID));
    772     reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
    773 
    774     if (reason == GATT_SUCCESS)
    775     {
    776         if (gatt_uuid_compare(uuid, primary_service))
    777         {
    778             if (op_code == GATT_REQ_FIND_TYPE_VALUE)
    779             {
    780                 if (gatt_parse_uuid_from_cmd(&value, len, &p_data) == FALSE)
    781                     reason = GATT_INVALID_PDU;
    782             }
    783 
    784             if (reason == GATT_SUCCESS)
    785             {
    786                 if ((p_msg =  (BT_HDR *)GKI_getbuf(msg_len)) == NULL)
    787                 {
    788                     GATT_TRACE_ERROR("gatts_process_primary_service_req failed. no resources.");
    789                     reason = GATT_NO_RESOURCES;
    790                 }
    791                 else
    792                 {
    793                     memset(p_msg, 0, msg_len);
    794                     reason = gatt_build_primary_service_rsp (p_msg, p_tcb, op_code, s_hdl, e_hdl, p_data, value);
    795                 }
    796             }
    797         }
    798         else
    799         {
    800             if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
    801             {
    802                 reason = GATT_UNSUPPORT_GRP_TYPE;
    803                 GATT_TRACE_DEBUG("unexpected ReadByGrpType Group: 0x%04x", uuid.uu.uuid16);
    804             }
    805             else
    806             {
    807                 /* we do not support ReadByTypeValue with any non-primamry_service type */
    808                 reason = GATT_NOT_FOUND;
    809                 GATT_TRACE_DEBUG("unexpected ReadByTypeValue type: 0x%04x", uuid.uu.uuid16);
    810             }
    811         }
    812     }
    813 
    814     if (reason != GATT_SUCCESS)
    815     {
    816         if (p_msg) GKI_freebuf(p_msg);
    817         gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE);
    818     }
    819     else
    820         attp_send_sr_msg(p_tcb, p_msg);
    821 
    822 }
    823 
    824 /*******************************************************************************
    825 **
    826 ** Function         gatts_process_find_info
    827 **
    828 ** Description      process find information request, for discover character
    829 **                  descriptors.
    830 **
    831 ** Returns          void
    832 **
    833 *******************************************************************************/
    834 static void gatts_process_find_info(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
    835 {
    836     UINT8           reason = GATT_INVALID_PDU, *p;
    837     UINT16          s_hdl = 0, e_hdl = 0, buf_len;
    838     BT_HDR          *p_msg = NULL;
    839     tGATT_SR_REG    *p_rcb;
    840     tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
    841     tGATT_SRV_LIST_ELEM  *p_srv=NULL;
    842 
    843     reason = gatts_validate_packet_format(op_code, &len, &p_data, NULL, &s_hdl, &e_hdl);
    844 
    845     if (reason == GATT_SUCCESS)
    846     {
    847         buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
    848 
    849         if ((p_msg =  (BT_HDR *)GKI_getbuf(buf_len)) == NULL)
    850         {
    851             reason = GATT_NO_RESOURCES;
    852         }
    853         else
    854         {
    855             reason = GATT_NOT_FOUND;
    856 
    857             memset(p_msg, 0, buf_len);
    858             p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
    859             *p ++ = op_code + 1;
    860             p_msg->len = 2;
    861 
    862             buf_len = p_tcb->payload_size - 2;
    863 
    864             p_srv = p_list->p_first;
    865 
    866             while (p_srv)
    867             {
    868                 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
    869 
    870                 if (p_rcb->in_use &&
    871                     !(p_rcb->s_hdl > e_hdl ||
    872                       p_rcb->e_hdl < s_hdl))
    873                 {
    874                     reason = gatt_build_find_info_rsp(p_rcb, p_msg, &buf_len, s_hdl, e_hdl);
    875                     if (reason == GATT_NO_RESOURCES)
    876                     {
    877                         reason = GATT_SUCCESS;
    878                         break;
    879                     }
    880                 }
    881                 p_srv = p_srv->p_next;
    882             }
    883             *p = (UINT8)p_msg->offset;
    884 
    885             p_msg->offset = L2CAP_MIN_OFFSET;
    886         }
    887     }
    888 
    889     if (reason != GATT_SUCCESS)
    890     {
    891         if (p_msg)  GKI_freebuf(p_msg);
    892         gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE);
    893     }
    894     else
    895         attp_send_sr_msg(p_tcb, p_msg);
    896 
    897 }
    898 
    899 /*******************************************************************************
    900 **
    901 ** Function         gatts_process_mtu_req
    902 **
    903 ** Description      This function is called to process excahnge MTU request.
    904 **                  Only used on LE.
    905 **
    906 ** Returns          void
    907 **
    908 *******************************************************************************/
    909 static void gatts_process_mtu_req (tGATT_TCB *p_tcb, UINT16 len, UINT8 *p_data)
    910 {
    911     UINT16        mtu = 0;
    912     UINT8         *p = p_data, i;
    913     BT_HDR        *p_buf;
    914     UINT16   conn_id;
    915 
    916     /* BR/EDR conenction, send error response */
    917     if (p_tcb->att_lcid != L2CAP_ATT_CID)
    918     {
    919         gatt_send_error_rsp (p_tcb, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, FALSE);
    920     }
    921     else if (len < GATT_MTU_REQ_MIN_LEN)
    922     {
    923         GATT_TRACE_ERROR("invalid MTU request PDU received.");
    924         gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, GATT_REQ_MTU, 0, FALSE);
    925     }
    926     else
    927     {
    928         STREAM_TO_UINT16 (mtu, p);
    929         /* mtu must be greater than default MTU which is 23/48 */
    930         if (mtu < GATT_DEF_BLE_MTU_SIZE)
    931             p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
    932         else if (mtu > GATT_MAX_MTU_SIZE)
    933             p_tcb->payload_size = GATT_MAX_MTU_SIZE;
    934         else
    935             p_tcb->payload_size = mtu;
    936 
    937         GATT_TRACE_ERROR("MTU request PDU with MTU size %d", p_tcb->payload_size);
    938 
    939         if ((p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_MTU, (tGATT_SR_MSG *) &p_tcb->payload_size)) != NULL)
    940         {
    941             attp_send_sr_msg (p_tcb, p_buf);
    942 
    943             /* Notify all registered applicaiton with new MTU size. Us a transaction ID */
    944             /* of 0, as no response is allowed from applcations                    */
    945 
    946             for (i = 0; i < GATT_MAX_APPS; i ++)
    947             {
    948                 if (gatt_cb.cl_rcb[i].in_use )
    949                 {
    950                     conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_cb.cl_rcb[i].gatt_if);
    951                     gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU,
    952                                               (tGATTS_DATA *)&p_tcb->payload_size);
    953                 }
    954             }
    955 
    956         }
    957     }
    958 }
    959 
    960 /*******************************************************************************
    961 **
    962 ** Function         gatts_process_read_by_type_req
    963 **
    964 ** Description      process Read By type request.
    965 **                  This PDU can be used to perform:
    966 **                  - read characteristic value
    967 **                  - read characteristic descriptor value
    968 **                  - discover characteristic
    969 **                  - discover characteristic by UUID
    970 **                  - relationship discovery
    971 **
    972 ** Returns          void
    973 **
    974 *******************************************************************************/
    975 void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
    976 {
    977     tBT_UUID            uuid;
    978     tGATT_SR_REG        *p_rcb;
    979     UINT16              msg_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET),
    980                                   buf_len,
    981                                   s_hdl, e_hdl, err_hdl = 0;
    982     BT_HDR              *p_msg = NULL;
    983     tGATT_STATUS        reason, ret;
    984     UINT8               *p;
    985     UINT8               sec_flag, key_size;
    986     tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
    987     tGATT_SRV_LIST_ELEM  *p_srv=NULL;
    988 
    989     reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
    990 
    991 #if GATT_CONFORMANCE_TESTING == TRUE
    992     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
    993     {
    994         GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d", gatt_cb.err_status);
    995 
    996         gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, FALSE);
    997 
    998         return;
    999     }
   1000 #endif
   1001 
   1002     if (reason == GATT_SUCCESS)
   1003     {
   1004         if ((p_msg =  (BT_HDR *)GKI_getbuf(msg_len)) == NULL)
   1005         {
   1006             GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.");
   1007 
   1008             reason = GATT_NO_RESOURCES;
   1009         }
   1010         else
   1011         {
   1012             memset(p_msg, 0, msg_len);
   1013             p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
   1014 
   1015             *p ++ = op_code + 1;
   1016             /* reserve length byte */
   1017             p_msg->len = 2;
   1018             buf_len = p_tcb->payload_size - 2;
   1019 
   1020             reason = GATT_NOT_FOUND;
   1021 
   1022             p_srv = p_list->p_first;
   1023 
   1024             while (p_srv)
   1025             {
   1026                 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
   1027 
   1028                 if (p_rcb->in_use &&
   1029                     !(p_rcb->s_hdl > e_hdl ||
   1030                       p_rcb->e_hdl < s_hdl))
   1031                 {
   1032                     gatt_sr_get_sec_info(p_tcb->peer_bda,
   1033                                          p_tcb->transport,
   1034                                          &sec_flag,
   1035                                          &key_size);
   1036 
   1037                     ret = gatts_db_read_attr_value_by_type(p_tcb,
   1038                                                            p_rcb->p_db,
   1039                                                            op_code,
   1040                                                            p_msg,
   1041                                                            s_hdl,
   1042                                                            e_hdl,
   1043                                                            uuid,
   1044                                                            &buf_len,
   1045                                                            sec_flag,
   1046                                                            key_size,
   1047                                                            0,
   1048                                                            &err_hdl);
   1049                     if (ret != GATT_NOT_FOUND)
   1050                     {
   1051                         reason = ret;
   1052 
   1053                         if (ret == GATT_NO_RESOURCES)
   1054                             reason = GATT_SUCCESS;
   1055                     }
   1056                     if (ret != GATT_SUCCESS && ret != GATT_NOT_FOUND)
   1057                     {
   1058                         s_hdl = err_hdl;
   1059                         break;
   1060                     }
   1061                 }
   1062                 p_srv = p_srv->p_next;
   1063             }
   1064             *p              = (UINT8)p_msg->offset;
   1065             p_msg->offset   = L2CAP_MIN_OFFSET;
   1066         }
   1067     }
   1068     if (reason != GATT_SUCCESS)
   1069     {
   1070         if (p_msg)  GKI_freebuf(p_msg);
   1071 
   1072         /* in theroy BUSY is not possible(should already been checked), protected check */
   1073         if (reason != GATT_PENDING && reason != GATT_BUSY)
   1074             gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE);
   1075     }
   1076     else
   1077         attp_send_sr_msg(p_tcb, p_msg);
   1078 
   1079 }
   1080 
   1081 /*******************************************************************************
   1082 **
   1083 ** Function         gatts_process_write_req
   1084 **
   1085 ** Description      This function is called to process the write request
   1086 **                  from client.
   1087 **
   1088 ** Returns          void
   1089 **
   1090 *******************************************************************************/
   1091 void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
   1092                               UINT8 op_code, UINT16 len, UINT8 *p_data)
   1093 {
   1094     tGATTS_DATA     sr_data;
   1095     UINT32          trans_id;
   1096     tGATT_STATUS    status;
   1097     UINT8           sec_flag, key_size, *p = p_data;
   1098     tGATT_SR_REG    *p_sreg;
   1099     UINT16          conn_id;
   1100 
   1101     memset(&sr_data, 0, sizeof(tGATTS_DATA));
   1102 
   1103     switch (op_code)
   1104     {
   1105         case GATT_REQ_PREPARE_WRITE:
   1106             sr_data.write_req.is_prep = TRUE;
   1107             STREAM_TO_UINT16(sr_data.write_req.offset, p);
   1108             len -= 2;
   1109             /* fall through */
   1110         case GATT_SIGN_CMD_WRITE:
   1111             if (op_code == GATT_SIGN_CMD_WRITE)
   1112             {
   1113                 GATT_TRACE_DEBUG("Write CMD with data sigining" );
   1114                 len -= GATT_AUTH_SIGN_LEN;
   1115             }
   1116             /* fall through */
   1117         case GATT_CMD_WRITE:
   1118         case GATT_REQ_WRITE:
   1119             if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE)
   1120                 sr_data.write_req.need_rsp = TRUE;
   1121             sr_data.write_req.handle = handle;
   1122             sr_data.write_req.len = len;
   1123             memcpy (sr_data.write_req.value, p, len);
   1124             break;
   1125     }
   1126 
   1127     gatt_sr_get_sec_info(p_tcb->peer_bda,
   1128                          p_tcb->transport,
   1129                          &sec_flag,
   1130                          &key_size);
   1131 
   1132     status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db,
   1133                                           op_code,
   1134                                           handle,
   1135                                           sr_data.write_req.offset,
   1136                                           p,
   1137                                           len,
   1138                                           sec_flag,
   1139                                           key_size);
   1140 
   1141     if (status == GATT_SUCCESS)
   1142     {
   1143         if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0)
   1144         {
   1145             p_sreg = &gatt_cb.sr_reg[i_rcb];
   1146             conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
   1147             gatt_sr_send_req_callback(conn_id,
   1148                                       trans_id,
   1149                                       GATTS_REQ_TYPE_WRITE,
   1150                                       &sr_data);
   1151 
   1152             status = GATT_PENDING;
   1153         }
   1154         else
   1155         {
   1156             GATT_TRACE_ERROR("max pending command, send error");
   1157             status = GATT_BUSY; /* max pending command, application error */
   1158         }
   1159     }
   1160 
   1161     /* in theroy BUSY is not possible(should already been checked), protected check */
   1162     if (status != GATT_PENDING && status != GATT_BUSY &&
   1163         (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE))
   1164     {
   1165         gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
   1166     }
   1167     return;
   1168 }
   1169 
   1170 /*******************************************************************************
   1171 **
   1172 ** Function         gatts_process_read_req
   1173 **
   1174 ** Description      This function is called to process the read request
   1175 **                  from client.
   1176 **
   1177 ** Returns          void
   1178 **
   1179 *******************************************************************************/
   1180 static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 op_code,
   1181                                    UINT16 handle, UINT16 len, UINT8 *p_data)
   1182 {
   1183     UINT16          buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
   1184     tGATT_STATUS    reason;
   1185     BT_HDR          *p_msg = NULL;
   1186     UINT8           sec_flag, key_size, *p;
   1187     UINT16          offset = 0, value_len = 0;
   1188 
   1189     UNUSED (len);
   1190     if ((p_msg =  (BT_HDR *)GKI_getbuf(buf_len)) == NULL)
   1191     {
   1192         GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.");
   1193 
   1194         reason = GATT_NO_RESOURCES;
   1195     }
   1196     else
   1197     {
   1198         if (op_code == GATT_REQ_READ_BLOB)
   1199             STREAM_TO_UINT16(offset, p_data);
   1200 
   1201         memset(p_msg, 0, buf_len);
   1202         p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
   1203         *p ++ = op_code + 1;
   1204         p_msg->len = 1;
   1205         buf_len = p_tcb->payload_size - 1;
   1206 
   1207         gatt_sr_get_sec_info(p_tcb->peer_bda,
   1208                              p_tcb->transport,
   1209                              &sec_flag,
   1210                              &key_size);
   1211 
   1212         reason = gatts_read_attr_value_by_handle(p_tcb,
   1213                                                  p_rcb->p_db,
   1214                                                  op_code,
   1215                                                  handle,
   1216                                                  offset,
   1217                                                  p,
   1218                                                  &value_len,
   1219                                                  buf_len,
   1220                                                  sec_flag,
   1221                                                  key_size,
   1222                                                  0);
   1223 
   1224         p_msg->len += value_len;
   1225     }
   1226 
   1227     if (reason != GATT_SUCCESS)
   1228     {
   1229         if (p_msg)  GKI_freebuf(p_msg);
   1230 
   1231         /* in theroy BUSY is not possible(should already been checked), protected check */
   1232         if (reason != GATT_PENDING && reason != GATT_BUSY)
   1233             gatt_send_error_rsp (p_tcb, reason, op_code, handle, FALSE);
   1234     }
   1235     else
   1236         attp_send_sr_msg(p_tcb, p_msg);
   1237 
   1238 }
   1239 
   1240 /*******************************************************************************
   1241 **
   1242 ** Function         gatts_process_attribute_req
   1243 **
   1244 ** Description      This function is called to process the per attribute handle request
   1245 **                  from client.
   1246 **
   1247 ** Returns          void
   1248 **
   1249 *******************************************************************************/
   1250 void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
   1251                                   UINT16 len, UINT8 *p_data)
   1252 {
   1253     UINT16          handle = 0;
   1254     UINT8           *p = p_data, i;
   1255     tGATT_SR_REG    *p_rcb = gatt_cb.sr_reg;
   1256     tGATT_STATUS    status = GATT_INVALID_HANDLE;
   1257     tGATT_ATTR16    *p_attr;
   1258 
   1259     if (len < 2)
   1260     {
   1261         GATT_TRACE_ERROR("Illegal PDU length, discard request");
   1262         status = GATT_INVALID_PDU;
   1263     }
   1264     else
   1265     {
   1266         STREAM_TO_UINT16(handle, p);
   1267         len -= 2;
   1268     }
   1269 
   1270 #if GATT_CONFORMANCE_TESTING == TRUE
   1271     gatt_cb.handle = handle;
   1272     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
   1273     {
   1274         GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status);
   1275 
   1276         gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE);
   1277 
   1278         return;
   1279     }
   1280 #endif
   1281 
   1282     if (GATT_HANDLE_IS_VALID(handle))
   1283     {
   1284         for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
   1285         {
   1286             if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
   1287             {
   1288                 p_attr = (tGATT_ATTR16 *)p_rcb->p_db->p_attr_list;
   1289 
   1290                 while (p_attr)
   1291                 {
   1292                     if (p_attr->handle == handle)
   1293                     {
   1294                         switch (op_code)
   1295                         {
   1296                             case GATT_REQ_READ: /* read char/char descriptor value */
   1297                             case GATT_REQ_READ_BLOB:
   1298                                 gatts_process_read_req(p_tcb, p_rcb, op_code, handle, len, p);
   1299                                 break;
   1300 
   1301                             case GATT_REQ_WRITE: /* write char/char descriptor value */
   1302                             case GATT_CMD_WRITE:
   1303                             case GATT_SIGN_CMD_WRITE:
   1304                             case GATT_REQ_PREPARE_WRITE:
   1305                                 gatts_process_write_req(p_tcb, i, handle, op_code, len, p);
   1306                                 break;
   1307                             default:
   1308                                 break;
   1309                         }
   1310                         status = GATT_SUCCESS;
   1311                         break;
   1312                     }
   1313                     p_attr = (tGATT_ATTR16 *)p_attr->p_next;
   1314                 }
   1315                 break;
   1316             }
   1317         }
   1318     }
   1319 
   1320     if (status != GATT_SUCCESS && op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE)
   1321         gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
   1322 }
   1323 
   1324 /*******************************************************************************
   1325 **
   1326 ** Function         gatts_proc_srv_chg_ind_ack
   1327 **
   1328 ** Description      This function process the service changed indicaiton ACK
   1329 **
   1330 ** Returns          void
   1331 **
   1332 *******************************************************************************/
   1333 static void gatts_proc_srv_chg_ind_ack(tGATT_TCB *p_tcb )
   1334 {
   1335     tGATTS_SRV_CHG_REQ  req;
   1336     tGATTS_SRV_CHG      *p_buf = NULL;
   1337 
   1338     GATT_TRACE_DEBUG("gatts_proc_srv_chg_ind_ack");
   1339 
   1340     if ((p_buf = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL)
   1341     {
   1342         GATT_TRACE_DEBUG("NV update set srv chg = FALSE");
   1343         p_buf->srv_changed = FALSE;
   1344         memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG));
   1345         if (gatt_cb.cb_info.p_srv_chg_callback)
   1346             (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,&req, NULL);
   1347     }
   1348 }
   1349 
   1350 /*******************************************************************************
   1351 **
   1352 ** Function         gatts_chk_pending_ind
   1353 **
   1354 ** Description      This function check any pending indication needs to be sent if
   1355 **                  there is a pending indication then sent the indication
   1356 **
   1357 ** Returns          void
   1358 **
   1359 *******************************************************************************/
   1360 static void gatts_chk_pending_ind(tGATT_TCB *p_tcb )
   1361 {
   1362     tGATT_VALUE *p_buf = (tGATT_VALUE *)GKI_getfirst(&p_tcb->pending_ind_q);
   1363     GATT_TRACE_DEBUG("gatts_chk_pending_ind");
   1364 
   1365     if (p_buf )
   1366     {
   1367         GATTS_HandleValueIndication (p_buf->conn_id,
   1368                                      p_buf->handle,
   1369                                      p_buf->len,
   1370                                      p_buf->value);
   1371         GKI_freebuf(GKI_remove_from_queue (&p_tcb->pending_ind_q, p_buf));
   1372     }
   1373 }
   1374 
   1375 /*******************************************************************************
   1376 **
   1377 ** Function         gatts_proc_ind_ack
   1378 **
   1379 ** Description      This function process the Indication ack
   1380 **
   1381 ** Returns          TRUE continue to process the indication ack by the aaplication
   1382 **                  if the ACk is not a Service Changed Indication Ack
   1383 **
   1384 *******************************************************************************/
   1385 static BOOLEAN gatts_proc_ind_ack(tGATT_TCB *p_tcb, UINT16 ack_handle)
   1386 {
   1387     BOOLEAN continue_processing = TRUE;
   1388 
   1389     GATT_TRACE_DEBUG ("gatts_proc_ind_ack ack handle=%d", ack_handle);
   1390 
   1391     if (ack_handle == gatt_cb.handle_of_h_r)
   1392     {
   1393         gatts_proc_srv_chg_ind_ack(p_tcb);
   1394         /* there is no need to inform the application since srv chg is handled internally by GATT */
   1395         continue_processing = FALSE;
   1396     }
   1397 
   1398     gatts_chk_pending_ind(p_tcb);
   1399     return continue_processing;
   1400 }
   1401 
   1402 /*******************************************************************************
   1403 **
   1404 ** Function         gatts_process_value_conf
   1405 **
   1406 ** Description      This function is called to process the handle value confirmation.
   1407 **
   1408 ** Returns          void
   1409 **
   1410 *******************************************************************************/
   1411 void gatts_process_value_conf(tGATT_TCB *p_tcb, UINT8 op_code)
   1412 {
   1413     UINT16          handle = p_tcb->indicate_handle;
   1414     UINT32          trans_id;
   1415     UINT8           i;
   1416     tGATT_SR_REG    *p_rcb = gatt_cb.sr_reg;
   1417     BOOLEAN         continue_processing;
   1418     UINT16          conn_id;
   1419 
   1420     btu_stop_timer (&p_tcb->conf_timer_ent);
   1421     if (GATT_HANDLE_IS_VALID(handle))
   1422     {
   1423         p_tcb->indicate_handle = 0;
   1424         continue_processing = gatts_proc_ind_ack(p_tcb, handle);
   1425 
   1426         if (continue_processing)
   1427         {
   1428             for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
   1429             {
   1430                 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
   1431                 {
   1432                     trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle);
   1433                     conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_rcb->gatt_if);
   1434                     gatt_sr_send_req_callback(conn_id,
   1435                                               trans_id, GATTS_REQ_TYPE_CONF, (tGATTS_DATA *)&handle);
   1436                 }
   1437             }
   1438         }
   1439     }
   1440     else
   1441     {
   1442         GATT_TRACE_ERROR("unexpected handle value confirmation");
   1443     }
   1444 }
   1445 
   1446 /*******************************************************************************
   1447 **
   1448 ** Function         gatt_server_handle_client_req
   1449 **
   1450 ** Description      This function is called to handle the client requests to
   1451 **                  server.
   1452 **
   1453 **
   1454 ** Returns          void
   1455 **
   1456 *******************************************************************************/
   1457 void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code,
   1458                                     UINT16 len, UINT8 *p_data)
   1459 {
   1460     /* there is pending command, discard this one */
   1461     if (!gatt_sr_cmd_empty(p_tcb) && op_code != GATT_HANDLE_VALUE_CONF)
   1462         return;
   1463 
   1464     /* the size of the message may not be bigger than the local max PDU size*/
   1465     /* The message has to be smaller than the agreed MTU, len does not include op code */
   1466     if (len >= p_tcb->payload_size)
   1467     {
   1468         GATT_TRACE_ERROR("server receive invalid PDU size:%d pdu size:%d", len + 1, p_tcb->payload_size );
   1469         /* for invalid request expecting response, send it now */
   1470         if (op_code != GATT_CMD_WRITE &&
   1471             op_code != GATT_SIGN_CMD_WRITE &&
   1472             op_code != GATT_HANDLE_VALUE_CONF)
   1473         {
   1474             gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, op_code, 0, FALSE);
   1475         }
   1476         /* otherwise, ignore the pkt */
   1477     }
   1478     else
   1479     {
   1480         switch (op_code)
   1481         {
   1482             case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
   1483             case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */
   1484                 gatts_process_primary_service_req (p_tcb, op_code, len, p_data);
   1485                 break;
   1486 
   1487             case GATT_REQ_FIND_INFO:/* discover char descrptor */
   1488                 gatts_process_find_info(p_tcb, op_code, len, p_data);
   1489                 break;
   1490 
   1491             case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */
   1492                 /* discover characteristic, discover char by UUID */
   1493                 gatts_process_read_by_type_req(p_tcb, op_code, len, p_data);
   1494                 break;
   1495 
   1496 
   1497             case GATT_REQ_READ: /* read char/char descriptor value */
   1498             case GATT_REQ_READ_BLOB:
   1499             case GATT_REQ_WRITE: /* write char/char descriptor value */
   1500             case GATT_CMD_WRITE:
   1501             case GATT_SIGN_CMD_WRITE:
   1502             case GATT_REQ_PREPARE_WRITE:
   1503                 gatts_process_attribute_req (p_tcb, op_code, len, p_data);
   1504                 break;
   1505 
   1506             case GATT_HANDLE_VALUE_CONF:
   1507                 gatts_process_value_conf (p_tcb, op_code);
   1508                 break;
   1509 
   1510             case GATT_REQ_MTU:
   1511                 gatts_process_mtu_req (p_tcb, len, p_data);
   1512                 break;
   1513 
   1514             case GATT_REQ_EXEC_WRITE:
   1515                 gatt_process_exec_write_req (p_tcb, op_code, len, p_data);
   1516                 break;
   1517 
   1518             case GATT_REQ_READ_MULTI:
   1519                 gatt_process_read_multi_req (p_tcb, op_code, len, p_data);
   1520                 break;
   1521 
   1522             default:
   1523                 break;
   1524         }
   1525     }
   1526 }
   1527 
   1528 #endif /* BLE_INCLUDED */
   1529