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