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