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