1 /*
2 * Copyright (c) 2019 Oticon A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @brief HCI interface application
9 */
10
11 #include <zephyr/kernel.h>
12
13 #include <zephyr/settings/settings.h>
14
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/debug/stack.h>
17
18 #include <zephyr/net_buf.h>
19
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/l2cap.h>
22 #include <zephyr/bluetooth/hci_vs.h>
23 #include <zephyr/bluetooth/hci_raw.h>
24 #include <zephyr/bluetooth/iso.h>
25
26 #include "edtt_driver.h"
27 #include "bs_tracing.h"
28 #include "commands.h"
29
30 #if defined(CONFIG_BT_HCI_CORE_LOG_LEVEL_DBG)
31 #define LOG_LEVEL LOG_LEVEL_DBG
32 #else
33 #define LOG_LEVEL CONFIG_BT_LOG_LEVEL
34 #endif
35
36 #include <zephyr/logging/log.h>
37 LOG_MODULE_REGISTER(hci_test_app);
38
39 static uint16_t waiting_opcode;
40 static enum commands_t waiting_response;
41 static uint8_t m_events;
42
43 struct EdttIxit {
44 uint8_t refMajor;
45 uint8_t refMinor;
46 uint16_t len;
47 uint8_t *pVal;
48 };
49
50 /*! \brief Implementation eXtra Information for Test (IXIT) definitions */
51 #if defined(CONFIG_BT_CTLR_CONN_ISO_STREAMS_MAX_NSE)
52 const uint8_t TSPX_max_cis_nse = CONFIG_BT_CTLR_CONN_ISO_STREAMS_MAX_NSE;
53 #endif
54
55 /*! \brief Persistent LL IXIT values. */
56 static struct EdttIxit llIxits[] = {
57 #if defined(CONFIG_BT_CTLR_CONN_ISO_STREAMS_MAX_NSE)
58 {7, 14, 1, &TSPX_max_cis_nse},
59 #endif
60 };
61
62 /**
63 * @brief Clean out excess bytes from the input buffer
64 */
read_excess_bytes(uint16_t size)65 static void read_excess_bytes(uint16_t size)
66 {
67 if (size > 0) {
68 uint8_t buffer[size];
69
70 edtt_read((uint8_t *)buffer, size, EDTTT_BLOCK);
71 LOG_ERR("command size wrong! (%u extra bytes removed)", size);
72 }
73 }
74
75 /**
76 * @brief Provide an error response when an HCI command send failed
77 */
error_response(int error)78 static void error_response(int error)
79 {
80 uint16_t response = sys_cpu_to_le16(waiting_response);
81 int le_error = sys_cpu_to_le32(error);
82 uint16_t size = sys_cpu_to_le16(sizeof(le_error));
83
84 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
85 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
86 edtt_write((uint8_t *)&le_error, sizeof(le_error), EDTTT_BLOCK);
87 waiting_response = CMD_NOTHING;
88 waiting_opcode = 0;
89 }
90
91 /**
92 * @brief Allocate buffer for HCI command and fill in opCode for the command
93 */
hci_cmd_create(uint16_t opcode,uint8_t param_len)94 static struct net_buf *hci_cmd_create(uint16_t opcode, uint8_t param_len)
95 {
96 struct bt_hci_cmd_hdr *hdr;
97 struct net_buf *buf;
98
99 buf = bt_buf_get_tx(BT_BUF_CMD, K_FOREVER, NULL, 0);
100 __ASSERT_NO_MSG(buf);
101
102 hdr = net_buf_add(buf, sizeof(*hdr));
103 hdr->opcode = sys_cpu_to_le16(opcode);
104 hdr->param_len = param_len;
105
106 return buf;
107 }
108
109 /**
110 * @brief Allocate buffer for ACL Data Package and fill in Header
111 */
acl_data_create(struct bt_hci_acl_hdr * le_hdr)112 static struct net_buf *acl_data_create(struct bt_hci_acl_hdr *le_hdr)
113 {
114 struct net_buf *buf;
115 struct bt_hci_acl_hdr *hdr;
116
117 buf = bt_buf_get_tx(BT_BUF_ACL_OUT, K_FOREVER, NULL, 0);
118 __ASSERT_NO_MSG(buf);
119
120 hdr = net_buf_add(buf, sizeof(*hdr));
121 *hdr = *le_hdr;
122
123 return buf;
124 }
125
126 #if defined(CONFIG_BT_ISO)
127 /**
128 * @brief Allocate buffer for ISO Data Package and fill in Header
129 */
iso_data_create(struct bt_hci_iso_hdr * le_hdr)130 static struct net_buf *iso_data_create(struct bt_hci_iso_hdr *le_hdr)
131 {
132 struct net_buf *buf;
133 struct bt_hci_iso_hdr *hdr;
134
135 buf = bt_buf_get_tx(BT_BUF_ISO_OUT, K_FOREVER, NULL, 0);
136 __ASSERT_NO_MSG(buf);
137
138 hdr = net_buf_add(buf, sizeof(*hdr));
139 *hdr = *le_hdr;
140
141 return buf;
142 }
143 #endif /* defined(CONFIG_BT_ISO) */
144
145 /**
146 * @brief Allocate buffer for HCI command, fill in parameters and send the
147 * command...
148 */
send_hci_command(uint16_t opcode,uint8_t param_len,uint16_t response)149 static int send_hci_command(uint16_t opcode, uint8_t param_len, uint16_t response)
150 {
151 struct net_buf *buf;
152 void *cp;
153 int err = 0;
154
155 waiting_response = response;
156 buf = hci_cmd_create(waiting_opcode = opcode, param_len);
157 if (buf) {
158 if (param_len) {
159 cp = net_buf_add(buf, param_len);
160 edtt_read((uint8_t *)cp, param_len, EDTTT_BLOCK);
161 }
162 err = bt_send(buf);
163 if (err) {
164 LOG_ERR("Failed to send HCI command %d (err %d)",
165 opcode, err);
166 error_response(err);
167 }
168 } else {
169 LOG_ERR("Failed to create buffer for HCI command 0x%04x",
170 opcode);
171 error_response(-1);
172 }
173 return err;
174 }
175
176 /**
177 * @brief Echo function - echo input received...
178 */
echo(uint16_t size)179 static void echo(uint16_t size)
180 {
181 uint16_t response = sys_cpu_to_le16(CMD_ECHO_RSP);
182 uint16_t le_size = sys_cpu_to_le16(size);
183
184 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
185 edtt_write((uint8_t *)&le_size, sizeof(le_size), EDTTT_BLOCK);
186
187 if (size > 0) {
188 uint8_t buff[size];
189
190 edtt_read(buff, size, EDTTT_BLOCK);
191 edtt_write(buff, size, EDTTT_BLOCK);
192 }
193 }
194
195 NET_BUF_POOL_FIXED_DEFINE(event_pool, 32, BT_BUF_RX_SIZE + 4, 4, NULL);
196 static K_FIFO_DEFINE(event_queue);
197 static K_FIFO_DEFINE(rx_queue);
198 NET_BUF_POOL_FIXED_DEFINE(data_pool, CONFIG_BT_CTLR_RX_BUFFERS + 14,
199 BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_TX_SIZE) + 4, 4, NULL);
200 static K_FIFO_DEFINE(data_queue);
201 #if defined(CONFIG_BT_ISO)
202 NET_BUF_POOL_FIXED_DEFINE(iso_data_pool, CONFIG_BT_ISO_RX_BUF_COUNT + 14,
203 BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_RX_MTU) +
204 sizeof(uint32_t), 8, NULL);
205 static K_FIFO_DEFINE(iso_data_queue);
206 #endif /* CONFIG_BT_ISO */
207
208 /**
209 * @brief Handle Command Complete HCI event...
210 */
command_complete(struct net_buf * buf)211 static void command_complete(struct net_buf *buf)
212 {
213 struct bt_hci_evt_cmd_complete *evt = (void *)buf->data;
214 uint16_t opcode = sys_le16_to_cpu(evt->opcode);
215 uint16_t response = sys_cpu_to_le16(waiting_response);
216 struct net_buf_simple_state state;
217 uint16_t size;
218
219 net_buf_simple_save(&buf->b, &state);
220
221 net_buf_pull(buf, sizeof(*evt));
222 size = sys_cpu_to_le16(buf->len);
223
224 if (opcode == waiting_opcode) {
225 LOG_DBG("Command complete for 0x%04x", waiting_opcode);
226
227 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
228 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
229 edtt_write((uint8_t *)buf->data, buf->len, EDTTT_BLOCK);
230 waiting_opcode = 0;
231 } else {
232 LOG_WRN("Not waiting for 0x(%04x) command status,"
233 " expected 0x(%04x)", opcode, waiting_opcode);
234 }
235
236 net_buf_simple_restore(&buf->b, &state);
237 }
238
239 /**
240 * @brief Handle Command Status HCI event...
241 */
command_status(struct net_buf * buf)242 static void command_status(struct net_buf *buf)
243 {
244 struct bt_hci_evt_cmd_status *evt = (void *)buf->data;
245 uint16_t opcode = sys_le16_to_cpu(evt->opcode);
246 uint16_t response = sys_cpu_to_le16(waiting_response);
247 struct net_buf_simple_state state;
248 uint8_t status = evt->status;
249 uint16_t size;
250
251 net_buf_simple_save(&buf->b, &state);
252
253 net_buf_pull(buf, sizeof(*evt));
254 size = sys_cpu_to_le16(buf->len) + 1;
255
256 if (opcode == waiting_opcode) {
257 LOG_DBG("Command status for 0x%04x", waiting_opcode);
258
259 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
260 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
261 edtt_write((uint8_t *)&status, sizeof(status), EDTTT_BLOCK);
262 edtt_write((uint8_t *)buf->data, buf->len, EDTTT_BLOCK);
263 waiting_opcode = 0;
264 } else {
265 LOG_WRN("Not waiting for 0x(%04x) command status,"
266 " expected 0x(%04x)", opcode, waiting_opcode);
267 }
268
269 net_buf_simple_restore(&buf->b, &state);
270 }
271
272 /**
273 * @brief Remove an event from the event queue
274 */
discard_event(void)275 static void discard_event(void)
276 {
277 struct net_buf *buf = k_fifo_get(&event_queue, K_FOREVER);
278
279 net_buf_unref(buf);
280 m_events--;
281 }
282
283 /**
284 * @brief Allocate and store an event in the event queue
285 */
queue_event(struct net_buf * buf)286 static struct net_buf *queue_event(struct net_buf *buf)
287 {
288 struct net_buf *evt;
289
290 evt = net_buf_alloc(&event_pool, K_NO_WAIT);
291 if (evt) {
292 bt_buf_set_type(evt, BT_BUF_EVT);
293 net_buf_add_le32(evt, sys_cpu_to_le32(k_uptime_get()));
294 net_buf_add_mem(evt, buf->data, buf->len);
295 k_fifo_put(&event_queue, evt);
296 m_events++;
297 }
298 return evt;
299 }
300
301 /**
302 * @brief Thread to service events and ACL/ISO data packets from the HCI input queue
303 */
service_events(void * p1,void * p2,void * p3)304 static void service_events(void *p1, void *p2, void *p3)
305 {
306 struct net_buf *buf, *evt;
307
308 while (1) {
309 buf = k_fifo_get(&rx_queue, K_FOREVER);
310 if (bt_buf_get_type(buf) == BT_BUF_EVT) {
311
312 evt = queue_event(buf);
313 if (!evt) {
314 bs_trace_raw_time(4,
315 "Failed to allocated buffer "
316 "for event!\n");
317 LOG_WRN("No event in queue");
318 }
319
320 struct bt_hci_evt_hdr *hdr = (void *)buf->data;
321
322 net_buf_pull(buf, sizeof(*hdr));
323
324 switch (hdr->evt) {
325 case BT_HCI_EVT_CMD_COMPLETE:
326 if (!evt) {
327 discard_event();
328 evt = queue_event(buf);
329 }
330 command_complete(buf);
331 break;
332 case BT_HCI_EVT_CMD_STATUS:
333 if (!evt) {
334 discard_event();
335 evt = queue_event(buf);
336 }
337 command_status(buf);
338 break;
339 default:
340 break;
341 }
342 } else if (bt_buf_get_type(buf) == BT_BUF_ACL_IN) {
343 struct net_buf *data;
344
345 data = net_buf_alloc(&data_pool, K_NO_WAIT);
346 if (data) {
347 bt_buf_set_type(data, BT_BUF_ACL_IN);
348 net_buf_add_le32(data,
349 sys_cpu_to_le32(k_uptime_get()));
350 net_buf_add_mem(data, buf->data, buf->len);
351 k_fifo_put(&data_queue, data);
352 }
353 #if defined(CONFIG_BT_ISO)
354 } else if (bt_buf_get_type(buf) == BT_BUF_ISO_IN) {
355 struct net_buf *data;
356
357 data = net_buf_alloc(&iso_data_pool, K_NO_WAIT);
358 if (data) {
359 bt_buf_set_type(data, BT_BUF_ISO_IN);
360 net_buf_add_le32(data,
361 sys_cpu_to_le32(k_uptime_get()));
362 net_buf_add_mem(data, buf->data, buf->len);
363 k_fifo_put(&iso_data_queue, data);
364 }
365 #endif /* CONFIG_BT_ISO */
366 }
367 net_buf_unref(buf);
368
369 k_yield();
370 }
371 }
372
373 /**
374 * @brief Flush all HCI events from the input-copy queue
375 */
flush_events(uint16_t size)376 static void flush_events(uint16_t size)
377 {
378 uint16_t response = sys_cpu_to_le16(CMD_FLUSH_EVENTS_RSP);
379 struct net_buf *buf;
380
381 while ((buf = k_fifo_get(&event_queue, K_NO_WAIT))) {
382 net_buf_unref(buf);
383 m_events--;
384 }
385 read_excess_bytes(size);
386 size = 0;
387
388 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
389 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
390 }
391
392 /**
393 * @brief Get next available HCI event from the input-copy queue
394 */
get_event(uint16_t size)395 static void get_event(uint16_t size)
396 {
397 uint16_t response = sys_cpu_to_le16(CMD_GET_EVENT_RSP);
398 struct net_buf *buf;
399
400 read_excess_bytes(size);
401 size = 0;
402
403 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
404 buf = k_fifo_get(&event_queue, K_FOREVER);
405 if (buf) {
406 size = sys_cpu_to_le16(buf->len);
407 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
408 edtt_write((uint8_t *)buf->data, buf->len, EDTTT_BLOCK);
409 net_buf_unref(buf);
410 m_events--;
411 } else {
412 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
413 }
414 }
415
416 /**
417 * @brief Get next available HCI events from the input-copy queue
418 */
get_events(uint16_t size)419 static void get_events(uint16_t size)
420 {
421 uint16_t response = sys_cpu_to_le16(CMD_GET_EVENT_RSP);
422 struct net_buf *buf;
423 uint8_t count = m_events;
424
425 read_excess_bytes(size);
426 size = 0;
427
428 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
429 edtt_write((uint8_t *)&count, sizeof(count), EDTTT_BLOCK);
430 while (count--) {
431 buf = k_fifo_get(&event_queue, K_FOREVER);
432 size = sys_cpu_to_le16(buf->len);
433 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
434 edtt_write((uint8_t *)buf->data, buf->len, EDTTT_BLOCK);
435 net_buf_unref(buf);
436 m_events--;
437 }
438 }
439
440 /**
441 * @brief Check whether an HCI event is available in the input-copy queue
442 */
has_event(uint16_t size)443 static void has_event(uint16_t size)
444 {
445 struct has_event_resp {
446 uint16_t response;
447 uint16_t size;
448 uint8_t count;
449 } __packed;
450 struct has_event_resp le_response = {
451 .response = sys_cpu_to_le16(CMD_HAS_EVENT_RSP),
452 .size = sys_cpu_to_le16(1),
453 .count = m_events
454 };
455
456 if (size > 0) {
457 read_excess_bytes(size);
458 }
459 edtt_write((uint8_t *)&le_response, sizeof(le_response), EDTTT_BLOCK);
460 }
461
462 /**
463 * @brief Flush all ACL Data Packages from the input-copy queue
464 */
le_flush_data(uint16_t size)465 static void le_flush_data(uint16_t size)
466 {
467 uint16_t response = sys_cpu_to_le16(CMD_LE_FLUSH_DATA_RSP);
468 struct net_buf *buf;
469
470 while ((buf = k_fifo_get(&data_queue, K_NO_WAIT))) {
471 net_buf_unref(buf);
472 }
473 read_excess_bytes(size);
474 size = 0;
475
476 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
477 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
478 }
479
480 /**
481 * @brief Check whether an ACL Data Package is available in the input-copy queue
482 */
le_data_ready(uint16_t size)483 static void le_data_ready(uint16_t size)
484 {
485 struct has_data_resp {
486 uint16_t response;
487 uint16_t size;
488 uint8_t empty;
489 } __packed;
490 struct has_data_resp le_response = {
491 .response = sys_cpu_to_le16(CMD_LE_DATA_READY_RSP),
492 .size = sys_cpu_to_le16(1),
493 .empty = 0
494 };
495
496 if (size > 0) {
497 read_excess_bytes(size);
498 }
499 if (k_fifo_is_empty(&data_queue)) {
500 le_response.empty = 1;
501 }
502 edtt_write((uint8_t *)&le_response, sizeof(le_response), EDTTT_BLOCK);
503 }
504
505 /**
506 * @brief Get next available HCI Data Package from the input-copy queue
507 */
le_data_read(uint16_t size)508 static void le_data_read(uint16_t size)
509 {
510 uint16_t response = sys_cpu_to_le16(CMD_LE_DATA_READ_RSP);
511 struct net_buf *buf;
512
513 read_excess_bytes(size);
514 size = 0;
515
516 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
517 buf = k_fifo_get(&data_queue, K_FOREVER);
518 if (buf) {
519 size = sys_cpu_to_le16(buf->len);
520 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
521 edtt_write((uint8_t *)buf->data, buf->len, EDTTT_BLOCK);
522 net_buf_unref(buf);
523 } else {
524 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
525 }
526 }
527
528 /**
529 * @brief Write ACL Data Package to the Controller...
530 */
le_data_write(uint16_t size)531 static void le_data_write(uint16_t size)
532 {
533 struct data_write_resp {
534 uint16_t code;
535 uint16_t size;
536 uint8_t status;
537 } __packed;
538 struct data_write_resp response = {
539 .code = sys_cpu_to_le16(CMD_LE_DATA_WRITE_RSP),
540 .size = sys_cpu_to_le16(1),
541 .status = 0
542 };
543 struct net_buf *buf;
544 struct bt_hci_acl_hdr hdr;
545 int err;
546
547 if (size >= sizeof(hdr)) {
548 edtt_read((uint8_t *)&hdr, sizeof(hdr), EDTTT_BLOCK);
549 size -= sizeof(hdr);
550 buf = acl_data_create(&hdr);
551 if (buf) {
552 uint16_t hdr_length = sys_le16_to_cpu(hdr.len);
553 uint8_t *pdata = net_buf_add(buf, hdr_length);
554
555 if (size >= hdr_length) {
556 edtt_read(pdata, hdr_length, EDTTT_BLOCK);
557 size -= hdr_length;
558 }
559 err = bt_send(buf);
560 if (err) {
561 LOG_ERR("Failed to send ACL Data (err %d)",
562 err);
563 }
564 } else {
565 err = -2; /* Failed to allocate data buffer */
566 LOG_ERR("Failed to create buffer for ACL Data.");
567 }
568 } else {
569 /* Size too small for header (handle and data length) */
570 err = -3;
571 }
572 read_excess_bytes(size);
573
574 response.status = sys_cpu_to_le32(err);
575 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
576 }
577
578 #if defined(CONFIG_BT_ISO)
579 /**
580 * @brief Flush all ISO Data Packages from the input-copy queue
581 */
le_flush_iso_data(uint16_t size)582 static void le_flush_iso_data(uint16_t size)
583 {
584 uint16_t response = sys_cpu_to_le16(CMD_LE_FLUSH_ISO_DATA_RSP);
585 struct net_buf *buf;
586
587 while ((buf = k_fifo_get(&iso_data_queue, K_NO_WAIT))) {
588 net_buf_unref(buf);
589 }
590 read_excess_bytes(size);
591 size = 0;
592
593 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
594 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
595 }
596
597 /**
598 * @brief Check whether an ISO Data Package is available in the input-copy queue
599 */
le_iso_data_ready(uint16_t size)600 static void le_iso_data_ready(uint16_t size)
601 {
602 struct has_iso_data_resp {
603 uint16_t response;
604 uint16_t size;
605 uint8_t empty;
606 } __packed;
607 struct has_iso_data_resp le_response = {
608 .response = sys_cpu_to_le16(CMD_LE_ISO_DATA_READY_RSP),
609 .size = sys_cpu_to_le16(1),
610 .empty = 0
611 };
612
613 if (size > 0) {
614 read_excess_bytes(size);
615 }
616 if (k_fifo_is_empty(&iso_data_queue)) {
617 le_response.empty = 1;
618 }
619 edtt_write((uint8_t *)&le_response, sizeof(le_response), EDTTT_BLOCK);
620 }
621
622 /**
623 * @brief Get next available ISO Data Package from the input-copy queue
624 */
le_iso_data_read(uint16_t size)625 static void le_iso_data_read(uint16_t size)
626 {
627 uint16_t response = sys_cpu_to_le16(CMD_LE_ISO_DATA_READ_RSP);
628 struct net_buf *buf;
629
630 read_excess_bytes(size);
631 size = 0;
632
633 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
634 buf = k_fifo_get(&iso_data_queue, K_FOREVER);
635 if (buf) {
636 size = sys_cpu_to_le16(buf->len);
637 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
638 edtt_write((uint8_t *)buf->data, buf->len, EDTTT_BLOCK);
639 net_buf_unref(buf);
640 } else {
641 edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
642 }
643 }
644
645 /**
646 * @brief Write ISO Data Package to the Controller...
647 */
le_iso_data_write(uint16_t size)648 static void le_iso_data_write(uint16_t size)
649 {
650 struct iso_data_write_resp {
651 uint16_t code;
652 uint16_t size;
653 uint8_t status;
654 } __packed;
655 struct iso_data_write_resp response = {
656 .code = sys_cpu_to_le16(CMD_LE_ISO_DATA_WRITE_RSP),
657 .size = sys_cpu_to_le16(1),
658 .status = 0
659 };
660 struct net_buf *buf;
661 struct bt_hci_iso_hdr hdr;
662 int err;
663
664 if (size >= sizeof(hdr)) {
665 edtt_read((uint8_t *)&hdr, sizeof(hdr), EDTTT_BLOCK);
666 size -= sizeof(hdr);
667 buf = iso_data_create(&hdr);
668 if (buf) {
669 uint16_t hdr_length = sys_le16_to_cpu(hdr.len);
670 uint8_t *pdata = net_buf_add(buf, hdr_length);
671
672 if (size >= hdr_length) {
673 edtt_read(pdata, hdr_length, EDTTT_BLOCK);
674 size -= hdr_length;
675 }
676 err = bt_send(buf);
677 if (err) {
678 LOG_ERR("Failed to send ISO Data (err %d)",
679 err);
680 }
681 } else {
682 err = -2; /* Failed to allocate data buffer */
683 LOG_ERR("Failed to create buffer for ISO Data.");
684 }
685 } else {
686 /* Size too small for header (handle and data length) */
687 err = -3;
688 }
689 read_excess_bytes(size);
690
691 response.status = sys_cpu_to_le32(err);
692 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
693 }
694 #endif /* CONFIG_BT_ISO */
695
696 /**
697 * @brief Read 'Implementation eXtra Information for Test' value
698 */
le_ixit_value_read(uint16_t size)699 static void le_ixit_value_read(uint16_t size)
700 {
701 uint8_t profileId;
702 uint8_t refMajor;
703 uint8_t refMinor;
704 struct EdttIxit *pIxitArray;
705 int ixitArraySize;
706 struct EdttIxit *pIxitElement = NULL;
707
708 /*
709 * CMD_GET_IXIT_VALUE_REQ payload layout
710 *
711 * ...
712 * [ 4] PROFILE_ID[0]
713 * [ 5] IXIT_Reference_Major
714 * [ 6] IXIT_Reference_Minor
715 */
716 edtt_read((uint8_t *)&profileId, sizeof(profileId), EDTTT_BLOCK);
717 edtt_read((uint8_t *)&refMajor, sizeof(refMajor), EDTTT_BLOCK);
718 edtt_read((uint8_t *)&refMinor, sizeof(refMinor), EDTTT_BLOCK);
719
720 switch (profileId) {
721 case PROFILE_ID_LL:
722 pIxitArray = llIxits;
723 ixitArraySize = ARRAY_SIZE(llIxits);
724 break;
725 default:
726 pIxitArray = NULL;
727 ixitArraySize = 0;
728 }
729 for (int i = 0; i < ixitArraySize; i++) {
730 if (pIxitArray[i].refMajor == refMajor && pIxitArray[i].refMinor == refMinor) {
731 pIxitElement = &pIxitArray[i];
732 break;
733 }
734 }
735
736 struct ixit_value_get_resp {
737 uint16_t code;
738 uint16_t size;
739 uint8_t data[];
740 } __packed;
741 struct ixit_value_get_resp response = {
742 .code = sys_cpu_to_le16(CMD_GET_IXIT_VALUE_RSP),
743 .size = sys_cpu_to_le16(pIxitElement ? pIxitElement->len : 0),
744 };
745 edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
746 if (pIxitElement) {
747 edtt_write(pIxitElement->pVal, pIxitElement->len, EDTTT_BLOCK);
748 }
749 }
750
751 static K_THREAD_STACK_DEFINE(service_events_stack,
752 CONFIG_BT_HCI_TX_STACK_SIZE);
753 static struct k_thread service_events_data;
754
755 /**
756 * @brief Zephyr application main entry...
757 */
main(void)758 int main(void)
759 {
760 int err;
761 uint16_t command;
762 uint16_t size;
763 uint16_t opcode;
764 /**
765 * Initialize HCI command opcode and response variables...
766 */
767 waiting_opcode = 0;
768 waiting_response = CMD_NOTHING;
769 m_events = 0;
770 /**
771 * Initialize Bluetooth stack in raw mode...
772 */
773 err = bt_enable_raw(&rx_queue);
774 if (err) {
775 LOG_ERR("Bluetooth initialization failed (err %d)", err);
776 return 0;
777 }
778 /**
779 * Initialize and start EDTT system...
780 */
781 #if defined(CONFIG_ARCH_POSIX)
782 enable_edtt_mode();
783 set_edtt_autoshutdown(true);
784 #endif
785 edtt_start();
786 /**
787 * Initialize and start thread to service HCI events and ACL data...
788 */
789 k_thread_create(&service_events_data, service_events_stack,
790 K_THREAD_STACK_SIZEOF(service_events_stack),
791 service_events, NULL, NULL, NULL, K_PRIO_COOP(7),
792 0, K_NO_WAIT);
793
794 while (1) {
795 /**
796 * Wait for a command to arrive - then read and execute command
797 */
798 edtt_read((uint8_t *)&command, sizeof(command), EDTTT_BLOCK);
799 command = sys_le16_to_cpu(command);
800 edtt_read((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
801 size = sys_le16_to_cpu(size);
802 bs_trace_raw_time(4, "command 0x%04X received (size %u) "
803 "events=%u\n",
804 command, size, m_events);
805
806 switch (command) {
807 case CMD_ECHO_REQ:
808 echo(size);
809 break;
810 case CMD_FLUSH_EVENTS_REQ:
811 flush_events(size);
812 break;
813 case CMD_HAS_EVENT_REQ:
814 has_event(size);
815 break;
816 case CMD_GET_EVENT_REQ:
817 {
818 uint8_t multiple;
819
820 edtt_read((uint8_t *)&multiple, sizeof(multiple),
821 EDTTT_BLOCK);
822 if (multiple) {
823 get_events(--size);
824 } else {
825 get_event(--size);
826 }
827 }
828 break;
829 case CMD_LE_FLUSH_DATA_REQ:
830 le_flush_data(size);
831 break;
832 case CMD_LE_DATA_READY_REQ:
833 le_data_ready(size);
834 break;
835 case CMD_LE_DATA_WRITE_REQ:
836 le_data_write(size);
837 break;
838 case CMD_LE_DATA_READ_REQ:
839 le_data_read(size);
840 break;
841 #if defined(CONFIG_BT_ISO)
842 case CMD_LE_FLUSH_ISO_DATA_REQ:
843 le_flush_iso_data(size);
844 break;
845 case CMD_LE_ISO_DATA_READY_REQ:
846 le_iso_data_ready(size);
847 break;
848 case CMD_LE_ISO_DATA_WRITE_REQ:
849 le_iso_data_write(size);
850 break;
851 case CMD_LE_ISO_DATA_READ_REQ:
852 le_iso_data_read(size);
853 break;
854 #endif /* CONFIG_BT_ISO */
855
856 case CMD_GET_IXIT_VALUE_REQ:
857 le_ixit_value_read(size);
858 break;
859
860 default:
861 if (size >= 2) {
862 edtt_read((uint8_t *)&opcode, sizeof(opcode),
863 EDTTT_BLOCK);
864 send_hci_command(sys_le16_to_cpu(opcode),
865 size - 2, command + 1);
866 }
867 }
868 }
869 return 0;
870 }
871