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 <bluetooth/log.h>
26
27 #include "gatt_int.h"
28 #include "internal_include/bt_target.h"
29 #include "l2c_api.h"
30 #include "osi/include/allocator.h"
31 #include "stack/include/bt_hdr.h"
32 #include "stack/include/bt_types.h"
33 #include "stack/include/l2cdefs.h"
34 #include "types/bluetooth/uuid.h"
35
36 #define GATT_HDR_FIND_TYPE_VALUE_LEN 21
37 #define GATT_OP_CODE_SIZE 1
38 #define GATT_START_END_HANDLE_SIZE 4
39
40 using base::StringPrintf;
41 using bluetooth::Uuid;
42 using namespace bluetooth;
43
44 /**********************************************************************
45 * ATT protocol message building utility *
46 **********************************************************************/
47 /*******************************************************************************
48 *
49 * Function attp_build_mtu_exec_cmd
50 *
51 * Description Build a exchange MTU request
52 *
53 * Returns None.
54 *
55 ******************************************************************************/
attp_build_mtu_cmd(uint8_t op_code,uint16_t rx_mtu)56 static BT_HDR* attp_build_mtu_cmd(uint8_t op_code, uint16_t rx_mtu) {
57 uint8_t* p;
58 BT_HDR* p_buf =
59 (BT_HDR*)osi_malloc(sizeof(BT_HDR) + GATT_HDR_SIZE + L2CAP_MIN_OFFSET);
60
61 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
62 UINT8_TO_STREAM(p, op_code);
63 UINT16_TO_STREAM(p, rx_mtu);
64
65 p_buf->offset = L2CAP_MIN_OFFSET;
66 p_buf->len = GATT_HDR_SIZE; /* opcode + 2 bytes mtu */
67
68 return p_buf;
69 }
70 /*******************************************************************************
71 *
72 * Function attp_build_exec_write_cmd
73 *
74 * Description Build a execute write request or response.
75 *
76 * Returns None.
77 *
78 ******************************************************************************/
attp_build_exec_write_cmd(uint8_t op_code,uint8_t flag)79 static BT_HDR* attp_build_exec_write_cmd(uint8_t op_code, uint8_t flag) {
80 BT_HDR* p_buf = (BT_HDR*)osi_malloc(GATT_DATA_BUF_SIZE);
81 uint8_t* p;
82
83 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
84
85 p_buf->offset = L2CAP_MIN_OFFSET;
86 p_buf->len = GATT_OP_CODE_SIZE;
87
88 UINT8_TO_STREAM(p, op_code);
89
90 if (op_code == GATT_REQ_EXEC_WRITE) {
91 flag &= GATT_PREP_WRITE_EXEC;
92 UINT8_TO_STREAM(p, flag);
93 p_buf->len += 1;
94 }
95
96 return p_buf;
97 }
98
99 /*******************************************************************************
100 *
101 * Function attp_build_err_cmd
102 *
103 * Description Build a exchange MTU request
104 *
105 * Returns None.
106 *
107 ******************************************************************************/
attp_build_err_cmd(uint8_t cmd_code,uint16_t err_handle,uint8_t reason)108 static BT_HDR* attp_build_err_cmd(uint8_t cmd_code, uint16_t err_handle,
109 uint8_t reason) {
110 uint8_t* p;
111 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + 5);
112
113 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
114 UINT8_TO_STREAM(p, GATT_RSP_ERROR);
115 UINT8_TO_STREAM(p, cmd_code);
116 UINT16_TO_STREAM(p, err_handle);
117 UINT8_TO_STREAM(p, reason);
118
119 p_buf->offset = L2CAP_MIN_OFFSET;
120 /* GATT_HDR_SIZE (1B ERR_RSP op code+ 2B handle) + 1B cmd_op_code + 1B status
121 */
122 p_buf->len = GATT_HDR_SIZE + 1 + 1;
123
124 return p_buf;
125 }
126 /*******************************************************************************
127 *
128 * Function attp_build_browse_cmd
129 *
130 * Description Build a read information request or read by type request
131 *
132 * Returns None.
133 *
134 ******************************************************************************/
attp_build_browse_cmd(uint8_t op_code,uint16_t s_hdl,uint16_t e_hdl,const bluetooth::Uuid & uuid)135 static BT_HDR* attp_build_browse_cmd(uint8_t op_code, uint16_t s_hdl,
136 uint16_t e_hdl,
137 const bluetooth::Uuid& uuid) {
138 const size_t payload_size =
139 (GATT_OP_CODE_SIZE) + (GATT_START_END_HANDLE_SIZE) + (Uuid::kNumBytes128);
140 BT_HDR* p_buf =
141 (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
142
143 uint8_t* p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
144 /* Describe the built message location and size */
145 p_buf->offset = L2CAP_MIN_OFFSET;
146 p_buf->len = GATT_OP_CODE_SIZE + 4;
147
148 UINT8_TO_STREAM(p, op_code);
149 UINT16_TO_STREAM(p, s_hdl);
150 UINT16_TO_STREAM(p, e_hdl);
151 p_buf->len += gatt_build_uuid_to_stream(&p, uuid);
152
153 return p_buf;
154 }
155
156 /*******************************************************************************
157 *
158 * Function attp_build_read_handles_cmd
159 *
160 * Description Build a read by type and value request.
161 *
162 * Returns pointer to the command buffer.
163 *
164 ******************************************************************************/
attp_build_read_by_type_value_cmd(uint16_t payload_size,tGATT_FIND_TYPE_VALUE * p_value_type)165 static BT_HDR* attp_build_read_by_type_value_cmd(
166 uint16_t payload_size, tGATT_FIND_TYPE_VALUE* p_value_type) {
167 uint8_t* p;
168 uint16_t len = p_value_type->value_len;
169 BT_HDR* p_buf = nullptr;
170
171 if (payload_size < 5) {
172 return nullptr;
173 }
174
175 p_buf =
176 (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
177
178 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
179 p_buf->offset = L2CAP_MIN_OFFSET;
180 p_buf->len = 5; /* opcode + s_handle + e_handle */
181
182 UINT8_TO_STREAM(p, GATT_REQ_FIND_TYPE_VALUE);
183 UINT16_TO_STREAM(p, p_value_type->s_handle);
184 UINT16_TO_STREAM(p, p_value_type->e_handle);
185
186 p_buf->len += gatt_build_uuid_to_stream(&p, p_value_type->uuid);
187
188 if (p_value_type->value_len + p_buf->len > payload_size)
189 len = payload_size - p_buf->len;
190
191 memcpy(p, p_value_type->value, len);
192 p_buf->len += len;
193
194 return p_buf;
195 }
196
197 /*******************************************************************************
198 *
199 * Function attp_build_read_multi_cmd
200 *
201 * Description Build a read multiple request
202 *
203 * Returns None.
204 *
205 ******************************************************************************/
attp_build_read_multi_cmd(uint8_t op_code,uint16_t payload_size,uint16_t num_handle,uint16_t * p_handle)206 static BT_HDR* attp_build_read_multi_cmd(uint8_t op_code, uint16_t payload_size,
207 uint16_t num_handle,
208 uint16_t* p_handle) {
209 uint8_t* p;
210 uint16_t i = 0;
211 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + num_handle * 2 + 1 +
212 L2CAP_MIN_OFFSET);
213
214 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
215 p_buf->offset = L2CAP_MIN_OFFSET;
216 p_buf->len = 1;
217
218 UINT8_TO_STREAM(p, op_code);
219
220 for (i = 0; i < num_handle && p_buf->len + 2 <= payload_size; i++) {
221 UINT16_TO_STREAM(p, *(p_handle + i));
222 p_buf->len += 2;
223 }
224
225 return p_buf;
226 }
227 /*******************************************************************************
228 *
229 * Function attp_build_handle_cmd
230 *
231 * Description Build a read /read blob request
232 *
233 * Returns None.
234 *
235 ******************************************************************************/
attp_build_handle_cmd(uint8_t op_code,uint16_t handle,uint16_t offset)236 static BT_HDR* attp_build_handle_cmd(uint8_t op_code, uint16_t handle,
237 uint16_t offset) {
238 uint8_t* p;
239 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + 5 + L2CAP_MIN_OFFSET);
240
241 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
242 p_buf->offset = L2CAP_MIN_OFFSET;
243
244 UINT8_TO_STREAM(p, op_code);
245 p_buf->len = 1;
246
247 UINT16_TO_STREAM(p, handle);
248 p_buf->len += 2;
249
250 if (op_code == GATT_REQ_READ_BLOB) {
251 UINT16_TO_STREAM(p, offset);
252 p_buf->len += 2;
253 }
254
255 return p_buf;
256 }
257
258 /*******************************************************************************
259 *
260 * Function attp_build_opcode_cmd
261 *
262 * Description Build a request/response with opcode only.
263 *
264 * Returns None.
265 *
266 ******************************************************************************/
attp_build_opcode_cmd(uint8_t op_code)267 static BT_HDR* attp_build_opcode_cmd(uint8_t op_code) {
268 uint8_t* p;
269 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + 1 + L2CAP_MIN_OFFSET);
270
271 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
272 p_buf->offset = L2CAP_MIN_OFFSET;
273
274 UINT8_TO_STREAM(p, op_code);
275 p_buf->len = 1;
276
277 return p_buf;
278 }
279
280 /*******************************************************************************
281 *
282 * Function attp_build_value_cmd
283 *
284 * Description Build a attribute value request
285 *
286 * Returns None.
287 *
288 ******************************************************************************/
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)289 static BT_HDR* attp_build_value_cmd(uint16_t payload_size, uint8_t op_code,
290 uint16_t handle, uint16_t offset,
291 uint16_t len, uint8_t* p_data) {
292 uint8_t *p, *pp, *p_pair_len;
293 size_t pair_len;
294 size_t size_now = 1;
295
296 #define CHECK_SIZE() \
297 do { \
298 if (size_now > payload_size) { \
299 log::error("payload size too small"); \
300 osi_free(p_buf); \
301 return nullptr; \
302 } \
303 } while (false)
304
305 BT_HDR* p_buf =
306 (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
307
308 p = pp = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
309
310 CHECK_SIZE();
311 UINT8_TO_STREAM(p, op_code);
312 p_buf->offset = L2CAP_MIN_OFFSET;
313
314 if (op_code == GATT_RSP_READ_BY_TYPE) {
315 p_pair_len = p++;
316 pair_len = len + 2;
317 size_now += 1;
318 CHECK_SIZE();
319 // this field will be backfilled in the end of this function
320 }
321
322 if (op_code != GATT_RSP_READ_BLOB && op_code != GATT_RSP_READ) {
323 size_now += 2;
324 CHECK_SIZE();
325 UINT16_TO_STREAM(p, handle);
326 }
327
328 if (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_RSP_PREPARE_WRITE) {
329 size_now += 2;
330 CHECK_SIZE();
331 UINT16_TO_STREAM(p, offset);
332 }
333
334 if (len > 0 && p_data != NULL) {
335 /* ensure data not exceed MTU size */
336 if (payload_size - size_now < len) {
337 len = payload_size - size_now;
338 /* update handle value pair length */
339 if (op_code == GATT_RSP_READ_BY_TYPE) {
340 pair_len = (len + 2);
341 }
342
343 log::warn("attribute value too long, to be truncated to {}", len);
344 }
345
346 size_now += len;
347 CHECK_SIZE();
348 ARRAY_TO_STREAM(p, p_data, len);
349 }
350
351 // backfill pair len field
352 if (op_code == GATT_RSP_READ_BY_TYPE) {
353 if (pair_len > UINT8_MAX) {
354 log::error("pair_len greater than {}", UINT8_MAX);
355 osi_free(p_buf);
356 return nullptr;
357 }
358
359 *p_pair_len = (uint8_t)pair_len;
360 }
361
362 #undef CHECK_SIZE
363
364 p_buf->len = (uint16_t)size_now;
365 return p_buf;
366 }
367
368 /*******************************************************************************
369 *
370 * Function attp_send_msg_to_l2cap
371 *
372 * Description Send message to L2CAP.
373 *
374 ******************************************************************************/
attp_send_msg_to_l2cap(tGATT_TCB & tcb,uint16_t lcid,BT_HDR * p_toL2CAP)375 tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, uint16_t lcid,
376 BT_HDR* p_toL2CAP) {
377 uint16_t l2cap_ret;
378
379 if (lcid == L2CAP_ATT_CID) {
380 log::debug("Sending ATT message on att fixed channel");
381 l2cap_ret = L2CA_SendFixedChnlData(lcid, tcb.peer_bda, p_toL2CAP);
382 } else {
383 log::debug("Sending ATT message on lcid:{}", lcid);
384 l2cap_ret = (uint16_t)L2CA_DataWrite(lcid, p_toL2CAP);
385 }
386
387 if (l2cap_ret == L2CAP_DW_FAILED) {
388 log::error("failed to write data to L2CAP");
389 return GATT_INTERNAL_ERROR;
390 } else if (l2cap_ret == L2CAP_DW_CONGESTED) {
391 log::verbose("ATT congested, message accepted");
392 return GATT_CONGESTED;
393 }
394 return GATT_SUCCESS;
395 }
396
397 /** Build ATT Server PDUs */
attp_build_sr_msg(tGATT_TCB & tcb,uint8_t op_code,tGATT_SR_MSG * p_msg,uint16_t payload_size)398 BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code, tGATT_SR_MSG* p_msg,
399 uint16_t payload_size) {
400 uint16_t offset = 0;
401
402 if (payload_size == 0) {
403 log::error(
404 "Cannot send response (op: 0x{:02x}) due to payload size = 0, {}",
405 op_code, tcb.peer_bda);
406 return nullptr;
407 }
408
409 switch (op_code) {
410 case GATT_RSP_READ_BLOB:
411 case GATT_RSP_PREPARE_WRITE:
412 log::verbose(
413 "ATT_RSP_READ_BLOB/GATT_RSP_PREPARE_WRITE: len = {} offset = {}",
414 p_msg->attr_value.len, p_msg->attr_value.offset);
415 offset = p_msg->attr_value.offset;
416 FALLTHROUGH_INTENDED; /* FALLTHROUGH */
417 case GATT_RSP_READ_BY_TYPE:
418 case GATT_RSP_READ:
419 case GATT_HANDLE_VALUE_NOTIF:
420 case GATT_HANDLE_VALUE_IND:
421 return attp_build_value_cmd(
422 payload_size, op_code, p_msg->attr_value.handle, offset,
423 p_msg->attr_value.len, p_msg->attr_value.value);
424
425 case GATT_RSP_WRITE:
426 return attp_build_opcode_cmd(op_code);
427
428 case GATT_RSP_ERROR:
429 return attp_build_err_cmd(p_msg->error.cmd_code, p_msg->error.handle,
430 p_msg->error.reason);
431
432 case GATT_RSP_EXEC_WRITE:
433 return attp_build_exec_write_cmd(op_code, 0);
434
435 case GATT_RSP_MTU:
436 return attp_build_mtu_cmd(op_code, p_msg->mtu);
437
438 default:
439 log::fatal("attp_build_sr_msg: unknown op code = {}", op_code);
440 return nullptr;
441 }
442 }
443
444 /*******************************************************************************
445 *
446 * Function attp_send_sr_msg
447 *
448 * Description This function sends the server response or indication
449 * message to client.
450 *
451 * Parameter p_tcb: pointer to the connection control block.
452 * p_msg: pointer to message parameters structure.
453 *
454 * Returns GATT_SUCCESS if successfully sent; otherwise error code.
455 *
456 ******************************************************************************/
attp_send_sr_msg(tGATT_TCB & tcb,uint16_t cid,BT_HDR * p_msg)457 tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_msg) {
458 if (p_msg == NULL) {
459 log::warn("Unable to send empty message");
460 return GATT_NO_RESOURCES;
461 }
462
463 log::debug("Sending server response or indication message to client");
464 p_msg->offset = L2CAP_MIN_OFFSET;
465 return attp_send_msg_to_l2cap(tcb, cid, p_msg);
466 }
467
468 /*******************************************************************************
469 *
470 * Function attp_cl_send_cmd
471 *
472 * Description Send a ATT command or enqueue it.
473 *
474 * Returns GATT_SUCCESS if command sent
475 * GATT_CONGESTED if command sent but channel congested
476 * GATT_CMD_STARTED if command queue up in GATT
477 * GATT_ERROR if command sending failure
478 *
479 ******************************************************************************/
attp_cl_send_cmd(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint8_t cmd_code,BT_HDR * p_cmd)480 static tGATT_STATUS attp_cl_send_cmd(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
481 uint8_t cmd_code, BT_HDR* p_cmd) {
482 cmd_code &= ~GATT_AUTH_SIGN_MASK;
483
484 if (gatt_tcb_is_cid_busy(tcb, p_clcb->cid) &&
485 cmd_code != GATT_HANDLE_VALUE_CONF) {
486 if (gatt_cmd_enq(tcb, p_clcb, true, cmd_code, p_cmd)) {
487 log::debug("Enqueued ATT command {} conn_id=0x{:04x}, cid={}",
488 fmt::ptr(p_clcb), p_clcb->conn_id, p_clcb->cid);
489 return GATT_CMD_STARTED;
490 }
491
492 log::error("{}, cid 0x{:02x} already disconnected", tcb.peer_bda,
493 p_clcb->cid);
494 return GATT_INTERNAL_ERROR;
495 }
496
497 log::debug(
498 "Sending ATT command to l2cap cid:0x{:04x} eatt_channels:{} transport:{}",
499 p_clcb->cid, tcb.eatt, bt_transport_text(tcb.transport));
500 tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, p_clcb->cid, p_cmd);
501 if (att_ret != GATT_CONGESTED && att_ret != GATT_SUCCESS) {
502 log::warn(
503 "Unable to send ATT command to l2cap layer {} conn_id=0x{:04x}, cid={}",
504 fmt::ptr(p_clcb), p_clcb->conn_id, p_clcb->cid);
505 return GATT_INTERNAL_ERROR;
506 }
507
508 if (cmd_code == GATT_HANDLE_VALUE_CONF || cmd_code == GATT_CMD_WRITE) {
509 return att_ret;
510 }
511
512 log::debug("Starting ATT response timer {} conn_id=0x{:04x}, cid={}",
513 fmt::ptr(p_clcb), p_clcb->conn_id, p_clcb->cid);
514 gatt_start_rsp_timer(p_clcb);
515 if (!gatt_cmd_enq(tcb, p_clcb, false, cmd_code, NULL)) {
516 log::error(
517 "Could not queue sent request. {}, cid 0x{:02x} already disconnected",
518 tcb.peer_bda, p_clcb->cid);
519 return GATT_INTERNAL_ERROR;
520 }
521
522 return att_ret;
523 }
524
525 /*******************************************************************************
526 *
527 * Function attp_send_cl_confirmation_msg
528 *
529 * Description This function sends the client confirmation
530 * message to server.
531 *
532 * Parameter p_tcb: pointer to the connection control block.
533 * cid: channel id
534 *
535 * Returns GATT_SUCCESS if successfully sent; otherwise error code.
536 *
537 *
538 ******************************************************************************/
attp_send_cl_confirmation_msg(tGATT_TCB & tcb,uint16_t cid)539 tGATT_STATUS attp_send_cl_confirmation_msg(tGATT_TCB& tcb, uint16_t cid) {
540 BT_HDR* p_cmd = NULL;
541 p_cmd = attp_build_opcode_cmd(GATT_HANDLE_VALUE_CONF);
542
543 if (p_cmd == NULL) return GATT_NO_RESOURCES;
544
545 /* no pending request or value confirmation */
546 tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, cid, p_cmd);
547 if (att_ret != GATT_CONGESTED && att_ret != GATT_SUCCESS) {
548 return GATT_INTERNAL_ERROR;
549 }
550
551 return att_ret;
552 }
553
554 /*******************************************************************************
555 *
556 * Function attp_send_cl_msg
557 *
558 * Description This function sends the client request or confirmation
559 * message to server.
560 *
561 * Parameter p_tcb: pointer to the connection control block.
562 * p_clcb: clcb
563 * op_code: message op code.
564 * p_msg: pointer to message parameters structure.
565 *
566 * Returns GATT_SUCCESS if successfully sent; otherwise error code.
567 *
568 *
569 ******************************************************************************/
attp_send_cl_msg(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint8_t op_code,tGATT_CL_MSG * p_msg)570 tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
571 uint8_t op_code, tGATT_CL_MSG* p_msg) {
572 BT_HDR* p_cmd = NULL;
573 uint16_t offset = 0, handle;
574
575 if (!p_clcb) {
576 log::error("Missing p_clcb");
577 return GATT_ILLEGAL_PARAMETER;
578 }
579
580 uint16_t payload_size = gatt_tcb_get_payload_size(tcb, p_clcb->cid);
581 if (payload_size == 0) {
582 log::error("Cannot send request (op: 0x{:02x}) due to payload size = 0, {}",
583 op_code, tcb.peer_bda);
584 return GATT_NO_RESOURCES;
585 }
586
587 switch (op_code) {
588 case GATT_REQ_MTU:
589 if (p_msg->mtu > GATT_MAX_MTU_SIZE) {
590 log::warn(
591 "GATT message MTU is larger than max GATT MTU size op_code:{}",
592 op_code);
593 return GATT_ILLEGAL_PARAMETER;
594 }
595 p_cmd = attp_build_mtu_cmd(GATT_REQ_MTU, p_msg->mtu);
596 break;
597
598 case GATT_REQ_FIND_INFO:
599 case GATT_REQ_READ_BY_TYPE:
600 case GATT_REQ_READ_BY_GRP_TYPE:
601 if (!GATT_HANDLE_IS_VALID(p_msg->browse.s_handle) ||
602 !GATT_HANDLE_IS_VALID(p_msg->browse.e_handle) ||
603 p_msg->browse.s_handle > p_msg->browse.e_handle) {
604 log::warn("GATT message has invalid handle op_code:{}", op_code);
605 return GATT_ILLEGAL_PARAMETER;
606 }
607
608 p_cmd = attp_build_browse_cmd(op_code, p_msg->browse.s_handle,
609 p_msg->browse.e_handle, p_msg->browse.uuid);
610 break;
611
612 case GATT_REQ_READ_BLOB:
613 offset = p_msg->read_blob.offset;
614 FALLTHROUGH_INTENDED; /* FALLTHROUGH */
615 case GATT_REQ_READ:
616 handle =
617 (op_code == GATT_REQ_READ) ? p_msg->handle : p_msg->read_blob.handle;
618 /* handle checking */
619 if (!GATT_HANDLE_IS_VALID(handle)) {
620 log::warn("GATT message has invalid handle op_code:{}", op_code);
621 return GATT_ILLEGAL_PARAMETER;
622 }
623
624 p_cmd = attp_build_handle_cmd(op_code, handle, offset);
625 break;
626
627 case GATT_REQ_PREPARE_WRITE:
628 offset = p_msg->attr_value.offset;
629 FALLTHROUGH_INTENDED; /* FALLTHROUGH */
630 case GATT_REQ_WRITE:
631 case GATT_CMD_WRITE:
632 case GATT_SIGN_CMD_WRITE:
633 if (!GATT_HANDLE_IS_VALID(p_msg->attr_value.handle)) {
634 log::warn("GATT message has invalid handle op_code:{}", op_code);
635 return GATT_ILLEGAL_PARAMETER;
636 }
637
638 p_cmd = attp_build_value_cmd(
639 payload_size, op_code, p_msg->attr_value.handle, offset,
640 p_msg->attr_value.len, p_msg->attr_value.value);
641 break;
642
643 case GATT_REQ_EXEC_WRITE:
644 p_cmd = attp_build_exec_write_cmd(op_code, p_msg->exec_write);
645 break;
646
647 case GATT_REQ_FIND_TYPE_VALUE:
648 p_cmd = attp_build_read_by_type_value_cmd(payload_size,
649 &p_msg->find_type_value);
650 break;
651
652 case GATT_REQ_READ_MULTI:
653 case GATT_REQ_READ_MULTI_VAR:
654 p_cmd = attp_build_read_multi_cmd(op_code, payload_size,
655 p_msg->read_multi.num_handles,
656 p_msg->read_multi.handles);
657 break;
658
659 default:
660 break;
661 }
662
663 if (p_cmd == NULL) {
664 log::warn(
665 "Unable to build proper GATT message to send to peer device op_code:{}",
666 op_code);
667 return GATT_NO_RESOURCES;
668 }
669
670 return attp_cl_send_cmd(tcb, p_clcb, op_code, p_cmd);
671 }
672
673 namespace bluetooth {
674 namespace legacy {
675 namespace testing {
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)676 BT_HDR* attp_build_value_cmd(uint16_t payload_size, uint8_t op_code,
677 uint16_t handle, uint16_t offset, uint16_t len,
678 uint8_t* p_data) {
679 return ::attp_build_value_cmd(payload_size, op_code, handle, offset, len,
680 p_data);
681 }
682 } // namespace testing
683 } // namespace legacy
684 } // namespace bluetooth
685