Home | History | Annotate | Download | only in gatt
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2008-2014 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 ATT protocol functions
     22  *
     23  ******************************************************************************/
     24 
     25 #include "bt_target.h"
     26 
     27 #include "gatt_int.h"
     28 #include "l2c_api.h"
     29 
     30 #define GATT_HDR_FIND_TYPE_VALUE_LEN 21
     31 #define GATT_OP_CODE_SIZE 1
     32 #define GATT_START_END_HANDLE_SIZE 4
     33 
     34 using base::StringPrintf;
     35 /**********************************************************************
     36  *   ATT protocl message building utility                              *
     37  **********************************************************************/
     38 /*******************************************************************************
     39  *
     40  * Function         attp_build_mtu_exec_cmd
     41  *
     42  * Description      Build a exchange MTU request
     43  *
     44  * Returns          None.
     45  *
     46  ******************************************************************************/
     47 BT_HDR* attp_build_mtu_cmd(uint8_t op_code, uint16_t rx_mtu) {
     48   uint8_t* p;
     49   BT_HDR* p_buf =
     50       (BT_HDR*)osi_malloc(sizeof(BT_HDR) + GATT_HDR_SIZE + L2CAP_MIN_OFFSET);
     51 
     52   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
     53   UINT8_TO_STREAM(p, op_code);
     54   UINT16_TO_STREAM(p, rx_mtu);
     55 
     56   p_buf->offset = L2CAP_MIN_OFFSET;
     57   p_buf->len = GATT_HDR_SIZE; /* opcode + 2 bytes mtu */
     58 
     59   return p_buf;
     60 }
     61 /*******************************************************************************
     62  *
     63  * Function         attp_build_exec_write_cmd
     64  *
     65  * Description      Build a execute write request or response.
     66  *
     67  * Returns          None.
     68  *
     69  ******************************************************************************/
     70 BT_HDR* attp_build_exec_write_cmd(uint8_t op_code, uint8_t flag) {
     71   BT_HDR* p_buf = (BT_HDR*)osi_malloc(GATT_DATA_BUF_SIZE);
     72   uint8_t* p;
     73 
     74   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
     75 
     76   p_buf->offset = L2CAP_MIN_OFFSET;
     77   p_buf->len = GATT_OP_CODE_SIZE;
     78 
     79   UINT8_TO_STREAM(p, op_code);
     80 
     81   if (op_code == GATT_REQ_EXEC_WRITE) {
     82     flag &= GATT_PREP_WRITE_EXEC;
     83     UINT8_TO_STREAM(p, flag);
     84     p_buf->len += 1;
     85   }
     86 
     87   return p_buf;
     88 }
     89 
     90 /*******************************************************************************
     91  *
     92  * Function         attp_build_err_cmd
     93  *
     94  * Description      Build a exchange MTU request
     95  *
     96  * Returns          None.
     97  *
     98  ******************************************************************************/
     99 BT_HDR* attp_build_err_cmd(uint8_t cmd_code, uint16_t err_handle,
    100                            uint8_t reason) {
    101   uint8_t* p;
    102   BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + 5);
    103 
    104   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
    105   UINT8_TO_STREAM(p, GATT_RSP_ERROR);
    106   UINT8_TO_STREAM(p, cmd_code);
    107   UINT16_TO_STREAM(p, err_handle);
    108   UINT8_TO_STREAM(p, reason);
    109 
    110   p_buf->offset = L2CAP_MIN_OFFSET;
    111   /* GATT_HDR_SIZE (1B ERR_RSP op code+ 2B handle) + 1B cmd_op_code  + 1B status
    112    */
    113   p_buf->len = GATT_HDR_SIZE + 1 + 1;
    114 
    115   return p_buf;
    116 }
    117 /*******************************************************************************
    118  *
    119  * Function         attp_build_browse_cmd
    120  *
    121  * Description      Build a read information request or read by type request
    122  *
    123  * Returns          None.
    124  *
    125  ******************************************************************************/
    126 BT_HDR* attp_build_browse_cmd(uint8_t op_code, uint16_t s_hdl, uint16_t e_hdl,
    127                               tBT_UUID uuid) {
    128   const size_t payload_size =
    129       (GATT_OP_CODE_SIZE) + (GATT_START_END_HANDLE_SIZE) + (LEN_UUID_128);
    130   BT_HDR* p_buf =
    131       (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
    132 
    133   uint8_t* p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
    134   /* Describe the built message location and size */
    135   p_buf->offset = L2CAP_MIN_OFFSET;
    136   p_buf->len = GATT_OP_CODE_SIZE + 4;
    137 
    138   UINT8_TO_STREAM(p, op_code);
    139   UINT16_TO_STREAM(p, s_hdl);
    140   UINT16_TO_STREAM(p, e_hdl);
    141   p_buf->len += gatt_build_uuid_to_stream(&p, uuid);
    142 
    143   return p_buf;
    144 }
    145 
    146 /*******************************************************************************
    147  *
    148  * Function         attp_build_read_handles_cmd
    149  *
    150  * Description      Build a read by type and value request.
    151  *
    152  * Returns          pointer to the command buffer.
    153  *
    154  ******************************************************************************/
    155 BT_HDR* attp_build_read_by_type_value_cmd(uint16_t payload_size,
    156                                           tGATT_FIND_TYPE_VALUE* p_value_type) {
    157   uint8_t* p;
    158   uint16_t len = p_value_type->value_len;
    159   BT_HDR* p_buf =
    160       (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
    161 
    162   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
    163   p_buf->offset = L2CAP_MIN_OFFSET;
    164   p_buf->len = 5; /* opcode + s_handle + e_handle */
    165 
    166   UINT8_TO_STREAM(p, GATT_REQ_FIND_TYPE_VALUE);
    167   UINT16_TO_STREAM(p, p_value_type->s_handle);
    168   UINT16_TO_STREAM(p, p_value_type->e_handle);
    169 
    170   p_buf->len += gatt_build_uuid_to_stream(&p, p_value_type->uuid);
    171 
    172   if (p_value_type->value_len + p_buf->len > payload_size)
    173     len = payload_size - p_buf->len;
    174 
    175   memcpy(p, p_value_type->value, len);
    176   p_buf->len += len;
    177 
    178   return p_buf;
    179 }
    180 
    181 /*******************************************************************************
    182  *
    183  * Function         attp_build_read_multi_cmd
    184  *
    185  * Description      Build a read multiple request
    186  *
    187  * Returns          None.
    188  *
    189  ******************************************************************************/
    190 BT_HDR* attp_build_read_multi_cmd(uint16_t payload_size, uint16_t num_handle,
    191                                   uint16_t* p_handle) {
    192   uint8_t *p, i = 0;
    193   BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + num_handle * 2 + 1 +
    194                                       L2CAP_MIN_OFFSET);
    195 
    196   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
    197   p_buf->offset = L2CAP_MIN_OFFSET;
    198   p_buf->len = 1;
    199 
    200   UINT8_TO_STREAM(p, GATT_REQ_READ_MULTI);
    201 
    202   for (i = 0; i < num_handle && p_buf->len + 2 <= payload_size; i++) {
    203     UINT16_TO_STREAM(p, *(p_handle + i));
    204     p_buf->len += 2;
    205   }
    206 
    207   return p_buf;
    208 }
    209 /*******************************************************************************
    210  *
    211  * Function         attp_build_handle_cmd
    212  *
    213  * Description      Build a read /read blob request
    214  *
    215  * Returns          None.
    216  *
    217  ******************************************************************************/
    218 BT_HDR* attp_build_handle_cmd(uint8_t op_code, uint16_t handle,
    219                               uint16_t offset) {
    220   uint8_t* p;
    221   BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + 5 + L2CAP_MIN_OFFSET);
    222 
    223   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
    224   p_buf->offset = L2CAP_MIN_OFFSET;
    225 
    226   UINT8_TO_STREAM(p, op_code);
    227   p_buf->len = 1;
    228 
    229   UINT16_TO_STREAM(p, handle);
    230   p_buf->len += 2;
    231 
    232   if (op_code == GATT_REQ_READ_BLOB) {
    233     UINT16_TO_STREAM(p, offset);
    234     p_buf->len += 2;
    235   }
    236 
    237   return p_buf;
    238 }
    239 
    240 /*******************************************************************************
    241  *
    242  * Function         attp_build_opcode_cmd
    243  *
    244  * Description      Build a  request/response with opcode only.
    245  *
    246  * Returns          None.
    247  *
    248  ******************************************************************************/
    249 BT_HDR* attp_build_opcode_cmd(uint8_t op_code) {
    250   uint8_t* p;
    251   BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + 1 + L2CAP_MIN_OFFSET);
    252 
    253   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
    254   p_buf->offset = L2CAP_MIN_OFFSET;
    255 
    256   UINT8_TO_STREAM(p, op_code);
    257   p_buf->len = 1;
    258 
    259   return p_buf;
    260 }
    261 
    262 /*******************************************************************************
    263  *
    264  * Function         attp_build_value_cmd
    265  *
    266  * Description      Build a attribute value request
    267  *
    268  * Returns          None.
    269  *
    270  ******************************************************************************/
    271 BT_HDR* attp_build_value_cmd(uint16_t payload_size, uint8_t op_code,
    272                              uint16_t handle, uint16_t offset, uint16_t len,
    273                              uint8_t* p_data) {
    274   uint8_t *p, *pp, pair_len, *p_pair_len;
    275   BT_HDR* p_buf =
    276       (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
    277 
    278   p = pp = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
    279   UINT8_TO_STREAM(p, op_code);
    280   p_buf->offset = L2CAP_MIN_OFFSET;
    281   p_buf->len = 1;
    282 
    283   if (op_code == GATT_RSP_READ_BY_TYPE) {
    284     p_pair_len = p;
    285     pair_len = len + 2;
    286     UINT8_TO_STREAM(p, pair_len);
    287     p_buf->len += 1;
    288   }
    289   if (op_code != GATT_RSP_READ_BLOB && op_code != GATT_RSP_READ) {
    290     UINT16_TO_STREAM(p, handle);
    291     p_buf->len += 2;
    292   }
    293 
    294   if (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_RSP_PREPARE_WRITE) {
    295     UINT16_TO_STREAM(p, offset);
    296     p_buf->len += 2;
    297   }
    298 
    299   if (len > 0 && p_data != NULL) {
    300     /* ensure data not exceed MTU size */
    301     if (payload_size - p_buf->len < len) {
    302       len = payload_size - p_buf->len;
    303       /* update handle value pair length */
    304       if (op_code == GATT_RSP_READ_BY_TYPE) *p_pair_len = (len + 2);
    305 
    306       LOG(WARNING) << StringPrintf(
    307           "attribute value too long, to be truncated to %d", len);
    308     }
    309 
    310     ARRAY_TO_STREAM(p, p_data, len);
    311     p_buf->len += len;
    312   }
    313 
    314   return p_buf;
    315 }
    316 
    317 /*******************************************************************************
    318  *
    319  * Function         attp_send_msg_to_l2cap
    320  *
    321  * Description      Send message to L2CAP.
    322  *
    323  ******************************************************************************/
    324 tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, BT_HDR* p_toL2CAP) {
    325   uint16_t l2cap_ret;
    326 
    327   if (tcb.att_lcid == L2CAP_ATT_CID)
    328     l2cap_ret = L2CA_SendFixedChnlData(L2CAP_ATT_CID, tcb.peer_bda, p_toL2CAP);
    329   else
    330     l2cap_ret = (uint16_t)L2CA_DataWrite(tcb.att_lcid, p_toL2CAP);
    331 
    332   if (l2cap_ret == L2CAP_DW_FAILED) {
    333     LOG(ERROR) << StringPrintf(
    334         "ATT   failed to pass msg:0x%0x to L2CAP",
    335         *((uint8_t*)(p_toL2CAP + 1) + p_toL2CAP->offset));
    336     return GATT_INTERNAL_ERROR;
    337   } else if (l2cap_ret == L2CAP_DW_CONGESTED) {
    338     VLOG(1) << StringPrintf("ATT congested, message accepted");
    339     return GATT_CONGESTED;
    340   }
    341   return GATT_SUCCESS;
    342 }
    343 
    344 /** Build ATT Server PDUs */
    345 BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code,
    346                           tGATT_SR_MSG* p_msg) {
    347   uint16_t offset = 0;
    348 
    349   switch (op_code) {
    350     case GATT_RSP_READ_BLOB:
    351     case GATT_RSP_PREPARE_WRITE:
    352       VLOG(1) << StringPrintf(
    353           "ATT_RSP_READ_BLOB/GATT_RSP_PREPARE_WRITE: len = %d offset = %d",
    354           p_msg->attr_value.len, p_msg->attr_value.offset);
    355       offset = p_msg->attr_value.offset;
    356     /* Coverity: [FALSE-POSITIVE error] intended fall through */
    357     /* Missing break statement between cases in switch statement */
    358     /* fall through */
    359     case GATT_RSP_READ_BY_TYPE:
    360     case GATT_RSP_READ:
    361     case GATT_HANDLE_VALUE_NOTIF:
    362     case GATT_HANDLE_VALUE_IND:
    363       return attp_build_value_cmd(
    364           tcb.payload_size, op_code, p_msg->attr_value.handle, offset,
    365           p_msg->attr_value.len, p_msg->attr_value.value);
    366 
    367     case GATT_RSP_WRITE:
    368       return attp_build_opcode_cmd(op_code);
    369 
    370     case GATT_RSP_ERROR:
    371       return attp_build_err_cmd(p_msg->error.cmd_code, p_msg->error.handle,
    372                                 p_msg->error.reason);
    373 
    374     case GATT_RSP_EXEC_WRITE:
    375       return attp_build_exec_write_cmd(op_code, 0);
    376 
    377     case GATT_RSP_MTU:
    378       return attp_build_mtu_cmd(op_code, p_msg->mtu);
    379 
    380     default:
    381       LOG(FATAL) << "attp_build_sr_msg: unknown op code = " << +op_code;
    382       return nullptr;
    383   }
    384 }
    385 
    386 /*******************************************************************************
    387  *
    388  * Function         attp_send_sr_msg
    389  *
    390  * Description      This function sends the server response or indication
    391  *                  message to client.
    392  *
    393  * Parameter        p_tcb: pointer to the connecton control block.
    394  *                  p_msg: pointer to message parameters structure.
    395  *
    396  * Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
    397  *
    398  *
    399  ******************************************************************************/
    400 tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, BT_HDR* p_msg) {
    401   if (p_msg == NULL) return GATT_NO_RESOURCES;
    402 
    403   p_msg->offset = L2CAP_MIN_OFFSET;
    404   return attp_send_msg_to_l2cap(tcb, p_msg);
    405 }
    406 
    407 /*******************************************************************************
    408  *
    409  * Function         attp_cl_send_cmd
    410  *
    411  * Description      Send a ATT command or enqueue it.
    412  *
    413  * Returns          GATT_SUCCESS if command sent
    414  *                  GATT_CONGESTED if command sent but channel congested
    415  *                  GATT_CMD_STARTED if command queue up in GATT
    416  *                  GATT_ERROR if command sending failure
    417  *
    418  ******************************************************************************/
    419 tGATT_STATUS attp_cl_send_cmd(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    420                               uint8_t cmd_code, BT_HDR* p_cmd) {
    421   cmd_code &= ~GATT_AUTH_SIGN_MASK;
    422 
    423   if (!tcb.cl_cmd_q.empty() && cmd_code != GATT_HANDLE_VALUE_CONF) {
    424     gatt_cmd_enq(tcb, p_clcb, true, cmd_code, p_cmd);
    425     return GATT_CMD_STARTED;
    426   }
    427 
    428   /* no pending request or value confirmation */
    429   tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, p_cmd);
    430   if (att_ret != GATT_CONGESTED && att_ret != GATT_SUCCESS) {
    431     return GATT_INTERNAL_ERROR;
    432   }
    433 
    434   /* do not enq cmd if handle value confirmation or set request */
    435   if (cmd_code == GATT_HANDLE_VALUE_CONF || cmd_code == GATT_CMD_WRITE) {
    436     return att_ret;
    437   }
    438 
    439   gatt_start_rsp_timer(p_clcb);
    440   gatt_cmd_enq(tcb, p_clcb, false, cmd_code, NULL);
    441   return att_ret;
    442 }
    443 
    444 /*******************************************************************************
    445  *
    446  * Function         attp_send_cl_msg
    447  *
    448  * Description      This function sends the client request or confirmation
    449  *                  message to server.
    450  *
    451  * Parameter        p_tcb: pointer to the connectino control block.
    452  *                  p_clcb: clcb
    453  *                  op_code: message op code.
    454  *                  p_msg: pointer to message parameters structure.
    455  *
    456  * Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
    457  *
    458  *
    459  ******************************************************************************/
    460 tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
    461                               uint8_t op_code, tGATT_CL_MSG* p_msg) {
    462   BT_HDR* p_cmd = NULL;
    463   uint16_t offset = 0, handle;
    464   switch (op_code) {
    465     case GATT_REQ_MTU:
    466       if (p_msg->mtu > GATT_MAX_MTU_SIZE) return GATT_ILLEGAL_PARAMETER;
    467 
    468       tcb.payload_size = p_msg->mtu;
    469       p_cmd = attp_build_mtu_cmd(GATT_REQ_MTU, p_msg->mtu);
    470       break;
    471 
    472     case GATT_REQ_FIND_INFO:
    473     case GATT_REQ_READ_BY_TYPE:
    474     case GATT_REQ_READ_BY_GRP_TYPE:
    475       if (!GATT_HANDLE_IS_VALID(p_msg->browse.s_handle) ||
    476           !GATT_HANDLE_IS_VALID(p_msg->browse.e_handle) ||
    477           p_msg->browse.s_handle > p_msg->browse.e_handle)
    478         return GATT_ILLEGAL_PARAMETER;
    479 
    480       p_cmd = attp_build_browse_cmd(op_code, p_msg->browse.s_handle,
    481                                     p_msg->browse.e_handle, p_msg->browse.uuid);
    482       break;
    483 
    484     case GATT_REQ_READ_BLOB:
    485       offset = p_msg->read_blob.offset;
    486     /* fall through */
    487     case GATT_REQ_READ:
    488       handle =
    489           (op_code == GATT_REQ_READ) ? p_msg->handle : p_msg->read_blob.handle;
    490       /*  handle checking */
    491       if (!GATT_HANDLE_IS_VALID(handle)) return GATT_ILLEGAL_PARAMETER;
    492 
    493       p_cmd = attp_build_handle_cmd(op_code, handle, offset);
    494       break;
    495 
    496     case GATT_HANDLE_VALUE_CONF:
    497       p_cmd = attp_build_opcode_cmd(op_code);
    498       break;
    499 
    500     case GATT_REQ_PREPARE_WRITE:
    501       offset = p_msg->attr_value.offset;
    502     /* fall through */
    503     case GATT_REQ_WRITE:
    504     case GATT_CMD_WRITE:
    505     case GATT_SIGN_CMD_WRITE:
    506       if (!GATT_HANDLE_IS_VALID(p_msg->attr_value.handle))
    507         return GATT_ILLEGAL_PARAMETER;
    508 
    509       p_cmd = attp_build_value_cmd(
    510           tcb.payload_size, op_code, p_msg->attr_value.handle, offset,
    511           p_msg->attr_value.len, p_msg->attr_value.value);
    512       break;
    513 
    514     case GATT_REQ_EXEC_WRITE:
    515       p_cmd = attp_build_exec_write_cmd(op_code, p_msg->exec_write);
    516       break;
    517 
    518     case GATT_REQ_FIND_TYPE_VALUE:
    519       p_cmd = attp_build_read_by_type_value_cmd(tcb.payload_size,
    520                                                 &p_msg->find_type_value);
    521       break;
    522 
    523     case GATT_REQ_READ_MULTI:
    524       p_cmd = attp_build_read_multi_cmd(tcb.payload_size,
    525                                         p_msg->read_multi.num_handles,
    526                                         p_msg->read_multi.handles);
    527       break;
    528 
    529     default:
    530       break;
    531   }
    532 
    533   if (p_cmd == NULL) return GATT_NO_RESOURCES;
    534 
    535   return attp_cl_send_cmd(tcb, p_clcb, op_code, p_cmd);
    536 }
    537