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