1 /*
2 * Copyright (c) 2020 Demant
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <soc.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/byteorder.h>
10 #include <zephyr/bluetooth/hci_types.h>
11 #include <zephyr/bluetooth/buf.h>
12
13 #include "hal/cpu.h"
14 #include "hal/ccm.h"
15 #include "hal/ticker.h"
16
17 #include "util/util.h"
18 #include "util/mem.h"
19 #include "util/memq.h"
20 #include "util/mfifo.h"
21 #include "util/mayfly.h"
22 #include "util/dbuf.h"
23
24 #include "pdu_df.h"
25 #include "lll/pdu_vendor.h"
26 #include "pdu.h"
27
28 #include "lll.h"
29 #include "lll/lll_adv_types.h"
30 #include "lll_adv.h"
31 #include "lll/lll_adv_pdu.h"
32 #include "lll_adv_iso.h"
33 #include "lll/lll_df_types.h"
34 #include "lll_sync.h"
35 #include "lll_sync_iso.h"
36 #include "lll_conn.h"
37 #include "lll_conn_iso.h"
38 #include "lll_iso_tx.h"
39
40 #include "ll_sw/ull_tx_queue.h"
41
42 #include "isoal.h"
43
44 #include "ull_adv_types.h"
45 #include "ull_sync_types.h"
46 #include "ull_conn_types.h"
47 #include "ull_iso_types.h"
48 #include "ull_conn_iso_types.h"
49 #include "ull_llcp.h"
50
51 #include "ull_internal.h"
52 #include "ull_adv_internal.h"
53 #include "ull_conn_internal.h"
54 #include "ull_iso_internal.h"
55 #include "ull_sync_iso_internal.h"
56 #include "ull_conn_iso_internal.h"
57
58 #include "ll_feat.h"
59
60 #include "hal/debug.h"
61
62 #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
63 #include <zephyr/logging/log.h>
64 LOG_MODULE_REGISTER(bt_ctlr_ull_iso);
65
66 #if defined(CONFIG_BT_CTLR_CONN_ISO_STREAMS)
67 #define BT_CTLR_CONN_ISO_STREAMS CONFIG_BT_CTLR_CONN_ISO_STREAMS
68 #else /* !CONFIG_BT_CTLR_CONN_ISO_STREAMS */
69 #define BT_CTLR_CONN_ISO_STREAMS 0
70 #endif /* !CONFIG_BT_CTLR_CONN_ISO_STREAMS */
71
72 #if defined(CONFIG_BT_CTLR_ADV_ISO_STREAM_COUNT)
73 #define BT_CTLR_ADV_ISO_STREAMS (CONFIG_BT_CTLR_ADV_ISO_STREAM_COUNT)
74 #else /* !CONFIG_BT_CTLR_ADV_ISO_STREAM_COUNT */
75 #define BT_CTLR_ADV_ISO_STREAMS 0
76 #endif /* CONFIG_BT_CTLR_ADV_ISO_STREAM_COUNT */
77
78 #if defined(CONFIG_BT_CTLR_SYNC_ISO_STREAM_COUNT)
79 #define BT_CTLR_SYNC_ISO_STREAMS (CONFIG_BT_CTLR_SYNC_ISO_STREAM_COUNT)
80 #else /* !CONFIG_BT_CTLR_SYNC_ISO_STREAM_COUNT */
81 #define BT_CTLR_SYNC_ISO_STREAMS 0
82 #endif /* CONFIG_BT_CTLR_SYNC_ISO_STREAM_COUNT */
83
84 static int init_reset(void);
85
86 #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
87 static isoal_status_t ll_iso_pdu_alloc(struct isoal_pdu_buffer *pdu_buffer);
88 static isoal_status_t ll_iso_pdu_write(struct isoal_pdu_buffer *pdu_buffer,
89 const size_t offset,
90 const uint8_t *sdu_payload,
91 const size_t consume_len);
92 static isoal_status_t ll_iso_pdu_emit(struct node_tx_iso *node_tx,
93 const uint16_t handle);
94 static isoal_status_t ll_iso_pdu_release(struct node_tx_iso *node_tx,
95 const uint16_t handle,
96 const isoal_status_t status);
97 #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
98
99 /* Allocate data path pools for RX/TX directions for each stream */
100 #define BT_CTLR_ISO_STREAMS ((2 * (BT_CTLR_CONN_ISO_STREAMS)) + \
101 BT_CTLR_ADV_ISO_STREAMS + \
102 BT_CTLR_SYNC_ISO_STREAMS)
103 #if BT_CTLR_ISO_STREAMS
104 static struct ll_iso_datapath datapath_pool[BT_CTLR_ISO_STREAMS];
105 #endif /* BT_CTLR_ISO_STREAMS */
106
107 static void *datapath_free;
108
109 #if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
110 #define NODE_RX_HEADER_SIZE (offsetof(struct node_rx_pdu, pdu))
111 /* ISO LL conformance tests require a PDU size of maximum 251 bytes + header */
112 #define ISO_RX_BUFFER_SIZE (2 + 251)
113
114 /* Declare the ISO rx node RXFIFO. This is a composite pool-backed MFIFO for
115 * rx_nodes. The declaration constructs the following data structures:
116 * - mfifo_iso_rx: FIFO with pointers to PDU buffers
117 * - mem_iso_rx: Backing data pool for PDU buffer elements
118 * - mem_link_iso_rx: Pool of memq_link_t elements
119 *
120 * One extra rx buffer is reserved for empty ISO PDU reception.
121 * Two extra links are reserved for use by the ll_iso_rx and ull_iso_rx memq.
122 */
123 static RXFIFO_DEFINE(iso_rx, ((NODE_RX_HEADER_SIZE) + (ISO_RX_BUFFER_SIZE)),
124 (CONFIG_BT_CTLR_ISO_RX_BUFFERS + 1U), 2U);
125
126 static MEMQ_DECLARE(ll_iso_rx);
127 #if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH)
128 static MEMQ_DECLARE(ull_iso_rx);
129 static void iso_rx_demux(void *param);
130 #endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */
131 #endif /* CONFIG_BT_CTLR_SYNC_ISO) || CONFIG_BT_CTLR_CONN_ISO */
132
133 #define ISO_TEST_PACKET_COUNTER_SIZE 4U
134
135 #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
136 void ll_iso_link_tx_release(void *link);
137 void ll_iso_tx_mem_release(void *node_tx);
138
139 #define NODE_TX_BUFFER_SIZE MROUND(offsetof(struct node_tx_iso, pdu) + \
140 offsetof(struct pdu_iso, payload) + \
141 MAX(LL_BIS_OCTETS_TX_MAX, \
142 LL_CIS_OCTETS_TX_MAX))
143
144 #define ISO_TEST_TX_BUFFER_SIZE 32U
145
146 static struct {
147 void *free;
148 uint8_t pool[NODE_TX_BUFFER_SIZE * BT_CTLR_ISO_TX_BUFFERS];
149 } mem_iso_tx;
150
151 static struct {
152 void *free;
153 uint8_t pool[sizeof(memq_link_t) * BT_CTLR_ISO_TX_BUFFERS];
154 } mem_link_iso_tx;
155
156 #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
157
ll_read_iso_tx_sync(uint16_t handle,uint16_t * seq,uint32_t * timestamp,uint32_t * offset)158 uint8_t ll_read_iso_tx_sync(uint16_t handle, uint16_t *seq,
159 uint32_t *timestamp, uint32_t *offset)
160 {
161 if (IS_CIS_HANDLE(handle)) {
162 struct ll_iso_datapath *dp = NULL;
163 struct ll_conn_iso_stream *cis;
164
165 cis = ll_conn_iso_stream_get(handle);
166
167 if (cis) {
168 dp = cis->hdr.datapath_in;
169 }
170
171 if (dp &&
172 isoal_tx_get_sync_info(dp->source_hdl, seq,
173 timestamp, offset) == ISOAL_STATUS_OK) {
174 return BT_HCI_ERR_SUCCESS;
175 }
176
177 return BT_HCI_ERR_CMD_DISALLOWED;
178
179 } else if (IS_ADV_ISO_HANDLE(handle)) {
180 const struct lll_adv_iso_stream *adv_stream;
181 uint16_t stream_handle;
182
183 stream_handle = LL_BIS_ADV_IDX_FROM_HANDLE(handle);
184 adv_stream = ull_adv_iso_stream_get(stream_handle);
185 if (!adv_stream || !adv_stream->dp ||
186 isoal_tx_get_sync_info(adv_stream->dp->source_hdl, seq,
187 timestamp, offset) != ISOAL_STATUS_OK) {
188 return BT_HCI_ERR_CMD_DISALLOWED;
189 }
190
191 return BT_HCI_ERR_SUCCESS;
192 }
193
194 return BT_HCI_ERR_UNKNOWN_CONN_ID;
195 }
196
path_is_vendor_specific(uint8_t path_id)197 static inline bool path_is_vendor_specific(uint8_t path_id)
198 {
199 return (path_id >= BT_HCI_DATAPATH_ID_VS &&
200 path_id <= BT_HCI_DATAPATH_ID_VS_END);
201 }
202
ll_setup_iso_path(uint16_t handle,uint8_t path_dir,uint8_t path_id,uint8_t coding_format,uint16_t company_id,uint16_t vs_codec_id,uint32_t controller_delay,uint8_t codec_config_len,uint8_t * codec_config)203 uint8_t ll_setup_iso_path(uint16_t handle, uint8_t path_dir, uint8_t path_id,
204 uint8_t coding_format, uint16_t company_id,
205 uint16_t vs_codec_id, uint32_t controller_delay,
206 uint8_t codec_config_len, uint8_t *codec_config)
207 {
208 struct lll_sync_iso_stream *sync_stream = NULL;
209 struct lll_adv_iso_stream *adv_stream = NULL;
210 struct ll_conn_iso_stream *cis = NULL;
211 struct ll_iso_datapath *dp;
212 uint32_t stream_sync_delay;
213 uint32_t group_sync_delay;
214 uint8_t flush_timeout;
215 uint16_t iso_interval;
216 uint32_t sdu_interval;
217 uint8_t burst_number;
218 uint8_t max_octets;
219 uint8_t framed;
220 uint8_t role;
221
222 ARG_UNUSED(controller_delay);
223 ARG_UNUSED(codec_config);
224
225 if (false) {
226
227 #if defined(CONFIG_BT_CTLR_CONN_ISO)
228 } else if (IS_CIS_HANDLE(handle)) {
229 struct ll_conn_iso_group *cig;
230 struct ll_conn *conn;
231
232 /* If the Host attempts to set a data path with a Connection
233 * Handle that does not exist or that is not for a CIS or a BIS,
234 * the Controller shall return the error code Unknown Connection
235 * Identifier (0x02)
236 */
237 cis = ll_conn_iso_stream_get(handle);
238 if (!cis->group) {
239 /* CIS does not belong to a CIG */
240 return BT_HCI_ERR_UNKNOWN_CONN_ID;
241 }
242
243 conn = ll_connected_get(cis->lll.acl_handle);
244 if (conn) {
245 /* If we're still waiting for accept/response from
246 * host, path setup is premature and we must return
247 * disallowed status.
248 */
249 #if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
250 const uint8_t cis_waiting = ull_cp_cc_awaiting_reply(conn);
251
252 if (cis_waiting) {
253 return BT_HCI_ERR_CMD_DISALLOWED;
254 }
255 #endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
256 }
257
258 if ((path_dir == BT_HCI_DATAPATH_DIR_HOST_TO_CTLR && cis->hdr.datapath_in) ||
259 (path_dir == BT_HCI_DATAPATH_DIR_CTLR_TO_HOST && cis->hdr.datapath_out)) {
260 /* Data path has been set up, can only do setup once */
261 return BT_HCI_ERR_CMD_DISALLOWED;
262 }
263
264 cig = cis->group;
265
266 role = cig->lll.role;
267 iso_interval = cig->iso_interval;
268 group_sync_delay = cig->sync_delay;
269 stream_sync_delay = cis->sync_delay;
270 framed = cis->framed;
271
272 if (path_dir == BT_HCI_DATAPATH_DIR_CTLR_TO_HOST) {
273 /* Create sink for RX data path */
274 burst_number = cis->lll.rx.bn;
275 flush_timeout = cis->lll.rx.ft;
276 max_octets = cis->lll.rx.max_pdu;
277
278 if (role) {
279 /* peripheral */
280 sdu_interval = cig->c_sdu_interval;
281 } else {
282 /* central */
283 sdu_interval = cig->p_sdu_interval;
284 }
285 } else {
286 /* path_dir == BT_HCI_DATAPATH_DIR_HOST_TO_CTLR */
287 burst_number = cis->lll.tx.bn;
288 flush_timeout = cis->lll.tx.ft;
289 max_octets = cis->lll.tx.max_pdu;
290
291 if (role) {
292 /* peripheral */
293 sdu_interval = cig->p_sdu_interval;
294 } else {
295 /* central */
296 sdu_interval = cig->c_sdu_interval;
297 }
298 }
299 #endif /* CONFIG_BT_CTLR_CONN_ISO */
300
301 #if defined(CONFIG_BT_CTLR_ADV_ISO)
302 } else if (IS_ADV_ISO_HANDLE(handle)) {
303 struct ll_adv_iso_set *adv_iso;
304 struct lll_adv_iso *lll_iso;
305 uint16_t stream_handle;
306
307 stream_handle = LL_BIS_ADV_IDX_FROM_HANDLE(handle);
308 adv_stream = ull_adv_iso_stream_get(stream_handle);
309 if (!adv_stream || adv_stream->dp) {
310 return BT_HCI_ERR_CMD_DISALLOWED;
311 }
312
313 adv_iso = ull_adv_iso_by_stream_get(stream_handle);
314 lll_iso = &adv_iso->lll;
315
316 role = ISOAL_ROLE_BROADCAST_SOURCE;
317 iso_interval = lll_iso->iso_interval;
318 sdu_interval = lll_iso->sdu_interval;
319 burst_number = lll_iso->bn;
320 flush_timeout = 0U; /* Not used for Broadcast ISO */
321 group_sync_delay = 0U; /* FIXME: */
322 stream_sync_delay = 0U; /* FIXME: */
323 framed = 0U; /* FIXME: pick the framing value from context */
324 max_octets = lll_iso->max_pdu;
325 #endif /* CONFIG_BT_CTLR_ADV_ISO */
326
327 #if defined(CONFIG_BT_CTLR_SYNC_ISO)
328 } else if (IS_SYNC_ISO_HANDLE(handle)) {
329 struct ll_sync_iso_set *sync_iso;
330 struct lll_sync_iso *lll_iso;
331 uint16_t stream_handle;
332
333 stream_handle = LL_BIS_SYNC_IDX_FROM_HANDLE(handle);
334 sync_stream = ull_sync_iso_stream_get(stream_handle);
335 if (!sync_stream || sync_stream->dp) {
336 return BT_HCI_ERR_CMD_DISALLOWED;
337 }
338
339 sync_iso = ull_sync_iso_by_stream_get(stream_handle);
340 lll_iso = &sync_iso->lll;
341
342 role = ISOAL_ROLE_BROADCAST_SINK;
343 iso_interval = lll_iso->iso_interval;
344 sdu_interval = lll_iso->sdu_interval;
345 burst_number = lll_iso->bn;
346 flush_timeout = 0U; /* Not used for Broadcast ISO */
347 group_sync_delay = 0U; /* FIXME: */
348 stream_sync_delay = 0U; /* FIXME: */
349 framed = 0U; /* FIXME: pick the framing value from context */
350 max_octets = 0U;
351 #endif /* CONFIG_BT_CTLR_SYNC_ISO */
352
353 } else {
354 return BT_HCI_ERR_UNKNOWN_CONN_ID;
355 }
356
357 if (path_is_vendor_specific(path_id) &&
358 (!IS_ENABLED(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH) ||
359 !ll_data_path_configured(path_dir, path_id))) {
360 /* Data path must be configured prior to setup */
361 return BT_HCI_ERR_CMD_DISALLOWED;
362 }
363
364 /* If Codec_Configuration_Length non-zero and Codec_ID set to
365 * transparent air mode, the Controller shall return the error code
366 * Invalid HCI Command Parameters (0x12).
367 */
368 if (codec_config_len &&
369 (vs_codec_id == BT_HCI_CODING_FORMAT_TRANSPARENT)) {
370 return BT_HCI_ERR_INVALID_PARAM;
371 }
372
373 /* Allocate and configure datapath */
374 dp = mem_acquire(&datapath_free);
375 if (!dp) {
376 return BT_HCI_ERR_CMD_DISALLOWED;
377 }
378
379 dp->path_dir = path_dir;
380 dp->path_id = path_id;
381 dp->coding_format = coding_format;
382 dp->company_id = company_id;
383
384 /* TODO dp->sync_delay = controller_delay; ?*/
385
386 if (false) {
387
388 #if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
389 } else if ((path_dir == BT_HCI_DATAPATH_DIR_CTLR_TO_HOST) &&
390 (cis || sync_stream)) {
391 isoal_sink_handle_t sink_handle;
392 isoal_status_t err;
393
394 if (path_id == BT_HCI_DATAPATH_ID_HCI) {
395 /* Not vendor specific, thus alloc and emit functions
396 * known
397 */
398 err = isoal_sink_create(handle, role, framed,
399 burst_number, flush_timeout,
400 sdu_interval, iso_interval,
401 stream_sync_delay,
402 group_sync_delay,
403 sink_sdu_alloc_hci,
404 sink_sdu_emit_hci,
405 sink_sdu_write_hci,
406 &sink_handle);
407 } else {
408 /* Set up vendor specific data path */
409 isoal_sink_sdu_alloc_cb sdu_alloc;
410 isoal_sink_sdu_emit_cb sdu_emit;
411 isoal_sink_sdu_write_cb sdu_write;
412
413 /* Request vendor sink callbacks for path */
414 if (IS_ENABLED(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH) &&
415 ll_data_path_sink_create(handle, dp, &sdu_alloc,
416 &sdu_emit, &sdu_write)) {
417 err = isoal_sink_create(handle, role, framed,
418 burst_number,
419 flush_timeout,
420 sdu_interval,
421 iso_interval,
422 stream_sync_delay,
423 group_sync_delay,
424 sdu_alloc, sdu_emit,
425 sdu_write,
426 &sink_handle);
427 } else {
428 ull_iso_datapath_release(dp);
429
430 return BT_HCI_ERR_CMD_DISALLOWED;
431 }
432 }
433
434 if (!err) {
435 if (cis) {
436 cis->hdr.datapath_out = dp;
437 }
438
439 if (sync_stream) {
440 sync_stream->dp = dp;
441 }
442
443 dp->sink_hdl = sink_handle;
444 isoal_sink_enable(sink_handle);
445 } else {
446 ull_iso_datapath_release(dp);
447
448 return BT_HCI_ERR_CMD_DISALLOWED;
449 }
450 #else /* !CONFIG_BT_CTLR_SYNC_ISO && !CONFIG_BT_CTLR_CONN_ISO */
451 ARG_UNUSED(sync_stream);
452 #endif /* !CONFIG_BT_CTLR_SYNC_ISO && !CONFIG_BT_CTLR_CONN_ISO */
453
454 #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
455 } else if ((path_dir == BT_HCI_DATAPATH_DIR_HOST_TO_CTLR) &&
456 (cis || adv_stream)) {
457 isoal_source_handle_t source_handle;
458 isoal_status_t err;
459
460 /* Create source for TX data path */
461 isoal_source_pdu_alloc_cb pdu_alloc;
462 isoal_source_pdu_write_cb pdu_write;
463 isoal_source_pdu_emit_cb pdu_emit;
464 isoal_source_pdu_release_cb pdu_release;
465
466 if (path_is_vendor_specific(path_id)) {
467 if (!IS_ENABLED(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH) ||
468 !ll_data_path_source_create(handle, dp,
469 &pdu_alloc, &pdu_write,
470 &pdu_emit,
471 &pdu_release)) {
472 ull_iso_datapath_release(dp);
473
474 return BT_HCI_ERR_CMD_DISALLOWED;
475 }
476 } else {
477 /* Set default callbacks when not vendor specific
478 * or that the vendor specific path is the same.
479 */
480 pdu_alloc = ll_iso_pdu_alloc;
481 pdu_write = ll_iso_pdu_write;
482 pdu_emit = ll_iso_pdu_emit;
483 pdu_release = ll_iso_pdu_release;
484 }
485
486 err = isoal_source_create(handle, role, framed, burst_number,
487 flush_timeout, max_octets,
488 sdu_interval, iso_interval,
489 stream_sync_delay, group_sync_delay,
490 pdu_alloc, pdu_write, pdu_emit,
491 pdu_release, &source_handle);
492
493 if (!err) {
494 if (cis) {
495 cis->hdr.datapath_in = dp;
496 }
497
498 if (adv_stream) {
499 adv_stream->dp = dp;
500 }
501
502 dp->source_hdl = source_handle;
503 isoal_source_enable(source_handle);
504 } else {
505 ull_iso_datapath_release(dp);
506
507 return BT_HCI_ERR_CMD_DISALLOWED;
508 }
509
510 #else /* !CONFIG_BT_CTLR_ADV_ISO && !CONFIG_BT_CTLR_CONN_ISO */
511 ARG_UNUSED(adv_stream);
512 #endif /* !CONFIG_BT_CTLR_ADV_ISO && !CONFIG_BT_CTLR_CONN_ISO */
513
514 } else {
515 return BT_HCI_ERR_CMD_DISALLOWED;
516 }
517
518 return BT_HCI_ERR_SUCCESS;
519 }
520
ll_remove_iso_path(uint16_t handle,uint8_t path_dir)521 uint8_t ll_remove_iso_path(uint16_t handle, uint8_t path_dir)
522 {
523 /* If the Host issues this command with a Connection_Handle that does
524 * not exist or is not for a CIS or a BIS, the Controller shall return
525 * the error code Unknown Connection Identifier (0x02).
526 */
527 if (false) {
528
529 #if defined(CONFIG_BT_CTLR_CONN_ISO)
530 } else if (IS_CIS_HANDLE(handle)) {
531 struct ll_conn_iso_stream *cis;
532 struct ll_iso_stream_hdr *hdr;
533 struct ll_iso_datapath *dp;
534
535 cis = ll_conn_iso_stream_get(handle);
536 hdr = &cis->hdr;
537
538 if (path_dir & BIT(BT_HCI_DATAPATH_DIR_HOST_TO_CTLR)) {
539 dp = hdr->datapath_in;
540 if (dp) {
541 isoal_source_destroy(dp->source_hdl);
542
543 hdr->datapath_in = NULL;
544 ull_iso_datapath_release(dp);
545 } else {
546 /* Datapath was not previously set up */
547 return BT_HCI_ERR_CMD_DISALLOWED;
548 }
549 }
550
551 if (path_dir & BIT(BT_HCI_DATAPATH_DIR_CTLR_TO_HOST)) {
552 dp = hdr->datapath_out;
553 if (dp) {
554 isoal_sink_destroy(dp->sink_hdl);
555
556 hdr->datapath_out = NULL;
557 ull_iso_datapath_release(dp);
558 } else {
559 /* Datapath was not previously set up */
560 return BT_HCI_ERR_CMD_DISALLOWED;
561 }
562 }
563 #endif /* CONFIG_BT_CTLR_CONN_ISO */
564
565 #if defined(CONFIG_BT_CTLR_ADV_ISO)
566 } else if (IS_ADV_ISO_HANDLE(handle)) {
567 struct lll_adv_iso_stream *adv_stream;
568 struct ll_iso_datapath *dp;
569 uint16_t stream_handle;
570
571 if (!(path_dir & BIT(BT_HCI_DATAPATH_DIR_HOST_TO_CTLR))) {
572 return BT_HCI_ERR_CMD_DISALLOWED;
573 }
574
575 stream_handle = LL_BIS_ADV_IDX_FROM_HANDLE(handle);
576 adv_stream = ull_adv_iso_stream_get(stream_handle);
577 if (!adv_stream) {
578 return BT_HCI_ERR_CMD_DISALLOWED;
579 }
580
581 dp = adv_stream->dp;
582 if (dp) {
583 adv_stream->dp = NULL;
584 isoal_source_destroy(dp->source_hdl);
585 ull_iso_datapath_release(dp);
586 } else {
587 /* Datapath was not previously set up */
588 return BT_HCI_ERR_CMD_DISALLOWED;
589 }
590 #endif /* CONFIG_BT_CTLR_ADV_ISO */
591
592 #if defined(CONFIG_BT_CTLR_SYNC_ISO)
593 } else if (IS_SYNC_ISO_HANDLE(handle)) {
594 struct lll_sync_iso_stream *sync_stream;
595 struct ll_iso_datapath *dp;
596 uint16_t stream_handle;
597
598 if (!(path_dir & BIT(BT_HCI_DATAPATH_DIR_CTLR_TO_HOST))) {
599 return BT_HCI_ERR_CMD_DISALLOWED;
600 }
601
602 stream_handle = LL_BIS_SYNC_IDX_FROM_HANDLE(handle);
603 sync_stream = ull_sync_iso_stream_get(stream_handle);
604 if (!sync_stream) {
605 return BT_HCI_ERR_CMD_DISALLOWED;
606 }
607
608 dp = sync_stream->dp;
609 if (dp) {
610 sync_stream->dp = NULL;
611 isoal_sink_destroy(dp->sink_hdl);
612 ull_iso_datapath_release(dp);
613 } else {
614 /* Datapath was not previously set up */
615 return BT_HCI_ERR_CMD_DISALLOWED;
616 }
617 #endif /* CONFIG_BT_CTLR_SYNC_ISO */
618
619 } else {
620 return BT_HCI_ERR_CMD_DISALLOWED;
621 }
622
623 return 0;
624 }
625
626 #if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
627 /* The sdu_alloc function is called before combining PDUs into an SDU. Here we
628 * store the paylaod number associated with the first PDU, for unframed usecase.
629 */
ll_iso_test_sdu_alloc(const struct isoal_sink * sink_ctx,const struct isoal_pdu_rx * valid_pdu,struct isoal_sdu_buffer * sdu_buffer)630 static isoal_status_t ll_iso_test_sdu_alloc(const struct isoal_sink *sink_ctx,
631 const struct isoal_pdu_rx *valid_pdu,
632 struct isoal_sdu_buffer *sdu_buffer)
633 {
634 uint16_t handle;
635
636 handle = sink_ctx->session.handle;
637
638 if (IS_CIS_HANDLE(handle)) {
639 if (!sink_ctx->session.framed) {
640 struct ll_conn_iso_stream *cis;
641
642 cis = ll_iso_stream_connected_get(sink_ctx->session.handle);
643 LL_ASSERT(cis);
644
645 /* For unframed, SDU counter is the payload number */
646 cis->hdr.test_mode.rx_sdu_counter =
647 (uint32_t)valid_pdu->meta->payload_number;
648 }
649 } else if (IS_SYNC_ISO_HANDLE(handle)) {
650 /* FIXME: Implement for sync receiver */
651 LL_ASSERT(false);
652 }
653
654 return sink_sdu_alloc_hci(sink_ctx, valid_pdu, sdu_buffer);
655 }
656
657 /* The sdu_emit function is called whenever an SDU is combined and ready to be sent
658 * further in the data path. This injected implementation performs statistics on
659 * the SDU and then discards it.
660 */
ll_iso_test_sdu_emit(const struct isoal_sink * sink_ctx,const struct isoal_emitted_sdu_frag * sdu_frag,const struct isoal_emitted_sdu * sdu)661 static isoal_status_t ll_iso_test_sdu_emit(const struct isoal_sink *sink_ctx,
662 const struct isoal_emitted_sdu_frag *sdu_frag,
663 const struct isoal_emitted_sdu *sdu)
664 {
665 isoal_status_t status;
666 struct net_buf *buf;
667 uint16_t handle;
668
669 handle = sink_ctx->session.handle;
670 buf = (struct net_buf *)sdu_frag->sdu.contents.dbuf;
671
672 if (IS_CIS_HANDLE(handle)) {
673 struct ll_conn_iso_stream *cis;
674 isoal_sdu_len_t length;
675 uint32_t sdu_counter;
676 uint8_t framed;
677
678 cis = ll_iso_stream_connected_get(sink_ctx->session.handle);
679 LL_ASSERT(cis);
680
681 length = sink_ctx->sdu_production.sdu_written;
682 framed = sink_ctx->session.framed;
683
684 /* In BT_HCI_ISO_TEST_ZERO_SIZE_SDU mode, all SDUs must have length 0 and there is
685 * no sdu_counter field. In the other modes, the first 4 bytes must contain a
686 * packet counter, which is used as SDU counter. The sdu_counter is extracted
687 * regardless of mode as a sanity check, unless the length does not allow it.
688 */
689 if (length >= ISO_TEST_PACKET_COUNTER_SIZE) {
690 sdu_counter = sys_get_le32(buf->data);
691 } else {
692 sdu_counter = 0U;
693 }
694
695 switch (sdu_frag->sdu.status) {
696 case ISOAL_SDU_STATUS_VALID:
697 if (framed && cis->hdr.test_mode.rx_sdu_counter == 0U) {
698 /* BT 5.3, Vol 6, Part B, section 7.2:
699 * When using framed PDUs the expected value of the SDU counter
700 * shall be initialized with the value of the SDU counter of the
701 * first valid received SDU.
702 */
703 cis->hdr.test_mode.rx_sdu_counter = sdu_counter;
704 }
705
706 switch (cis->hdr.test_mode.rx_payload_type) {
707 case BT_HCI_ISO_TEST_ZERO_SIZE_SDU:
708 if (length == 0) {
709 cis->hdr.test_mode.received_cnt++;
710 } else {
711 cis->hdr.test_mode.failed_cnt++;
712 }
713 break;
714
715 case BT_HCI_ISO_TEST_VARIABLE_SIZE_SDU:
716 if ((length >= ISO_TEST_PACKET_COUNTER_SIZE) &&
717 (length <= cis->c_max_sdu) &&
718 (sdu_counter == cis->hdr.test_mode.rx_sdu_counter)) {
719 cis->hdr.test_mode.received_cnt++;
720 } else {
721 cis->hdr.test_mode.failed_cnt++;
722 }
723 break;
724
725 case BT_HCI_ISO_TEST_MAX_SIZE_SDU:
726 if ((length == cis->c_max_sdu) &&
727 (sdu_counter == cis->hdr.test_mode.rx_sdu_counter)) {
728 cis->hdr.test_mode.received_cnt++;
729 } else {
730 cis->hdr.test_mode.failed_cnt++;
731 }
732 break;
733
734 default:
735 LL_ASSERT(0);
736 return ISOAL_STATUS_ERR_SDU_EMIT;
737 }
738 break;
739
740 case ISOAL_SDU_STATUS_ERRORS:
741 case ISOAL_SDU_STATUS_LOST_DATA:
742 cis->hdr.test_mode.missed_cnt++;
743 break;
744 }
745
746 /* In framed mode, we may start incrementing the SDU counter when rx_sdu_counter
747 * becomes non zero (initial state), or in case of zero-based counting, if zero
748 * is actually the first valid SDU counter received.
749 */
750 if (framed && (cis->hdr.test_mode.rx_sdu_counter ||
751 (sdu_frag->sdu.status == ISOAL_SDU_STATUS_VALID))) {
752 cis->hdr.test_mode.rx_sdu_counter++;
753 }
754
755 status = ISOAL_STATUS_OK;
756
757 } else if (IS_SYNC_ISO_HANDLE(handle)) {
758 /* FIXME: Implement for sync receiver */
759 status = ISOAL_STATUS_ERR_SDU_EMIT;
760 } else {
761 /* Handle is out of range */
762 status = ISOAL_STATUS_ERR_SDU_EMIT;
763 }
764
765 net_buf_unref(buf);
766
767 return status;
768 }
769
ll_iso_receive_test(uint16_t handle,uint8_t payload_type)770 uint8_t ll_iso_receive_test(uint16_t handle, uint8_t payload_type)
771 {
772 isoal_sink_handle_t sink_handle;
773 struct ll_iso_datapath *dp;
774 uint32_t sdu_interval;
775 isoal_status_t err;
776 uint8_t status;
777
778 status = BT_HCI_ERR_SUCCESS;
779
780 if (IS_CIS_HANDLE(handle)) {
781 struct ll_conn_iso_stream *cis;
782 struct ll_conn_iso_group *cig;
783
784 cis = ll_iso_stream_connected_get(handle);
785 if (!cis) {
786 /* CIS is not connected */
787 return BT_HCI_ERR_UNKNOWN_CONN_ID;
788 }
789
790 if (cis->lll.rx.bn == 0) {
791 /* CIS is not configured for RX */
792 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
793 }
794
795 if (cis->hdr.datapath_out) {
796 /* Data path already set up */
797 return BT_HCI_ERR_CMD_DISALLOWED;
798 }
799
800 if (payload_type > BT_HCI_ISO_TEST_MAX_SIZE_SDU) {
801 return BT_HCI_ERR_INVALID_LL_PARAM;
802 }
803
804 /* Allocate and configure test datapath */
805 dp = mem_acquire(&datapath_free);
806 if (!dp) {
807 return BT_HCI_ERR_CMD_DISALLOWED;
808 }
809
810 dp->path_dir = BT_HCI_DATAPATH_DIR_CTLR_TO_HOST;
811 dp->path_id = BT_HCI_DATAPATH_ID_HCI;
812
813 cis->hdr.datapath_out = dp;
814 cig = cis->group;
815
816 if (cig->lll.role == BT_HCI_ROLE_PERIPHERAL) {
817 /* peripheral */
818 sdu_interval = cig->c_sdu_interval;
819 } else {
820 /* central */
821 sdu_interval = cig->p_sdu_interval;
822 }
823
824 err = isoal_sink_create(handle, cig->lll.role, cis->framed,
825 cis->lll.rx.bn, cis->lll.rx.ft,
826 sdu_interval, cig->iso_interval,
827 cis->sync_delay, cig->sync_delay,
828 ll_iso_test_sdu_alloc,
829 ll_iso_test_sdu_emit,
830 sink_sdu_write_hci, &sink_handle);
831 if (err) {
832 /* Error creating test source - cleanup source and
833 * datapath
834 */
835 isoal_sink_destroy(sink_handle);
836 ull_iso_datapath_release(dp);
837 cis->hdr.datapath_out = NULL;
838
839 return BT_HCI_ERR_CMD_DISALLOWED;
840 }
841
842 dp->sink_hdl = sink_handle;
843 isoal_sink_enable(sink_handle);
844
845 /* Enable Receive Test Mode */
846 cis->hdr.test_mode.rx_enabled = 1;
847 cis->hdr.test_mode.rx_payload_type = payload_type;
848
849 } else if (IS_SYNC_ISO_HANDLE(handle)) {
850 /* FIXME: Implement for sync receiver */
851 status = BT_HCI_ERR_CMD_DISALLOWED;
852 } else {
853 /* Handle is out of range */
854 status = BT_HCI_ERR_UNKNOWN_CONN_ID;
855 }
856
857 return status;
858 }
859
ll_iso_read_test_counters(uint16_t handle,uint32_t * received_cnt,uint32_t * missed_cnt,uint32_t * failed_cnt)860 uint8_t ll_iso_read_test_counters(uint16_t handle, uint32_t *received_cnt,
861 uint32_t *missed_cnt,
862 uint32_t *failed_cnt)
863 {
864 uint8_t status;
865
866 *received_cnt = 0U;
867 *missed_cnt = 0U;
868 *failed_cnt = 0U;
869
870 status = BT_HCI_ERR_SUCCESS;
871
872 if (IS_CIS_HANDLE(handle)) {
873 struct ll_conn_iso_stream *cis;
874
875 cis = ll_iso_stream_connected_get(handle);
876 if (!cis) {
877 /* CIS is not connected */
878 return BT_HCI_ERR_UNKNOWN_CONN_ID;
879 }
880
881 if (!cis->hdr.test_mode.rx_enabled) {
882 /* ISO receive Test is not active */
883 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
884 }
885
886 /* Return SDU statistics */
887 *received_cnt = cis->hdr.test_mode.received_cnt;
888 *missed_cnt = cis->hdr.test_mode.missed_cnt;
889 *failed_cnt = cis->hdr.test_mode.failed_cnt;
890
891 } else if (IS_SYNC_ISO_HANDLE(handle)) {
892 /* FIXME: Implement for sync receiver */
893 status = BT_HCI_ERR_CMD_DISALLOWED;
894 } else {
895 /* Handle is out of range */
896 status = BT_HCI_ERR_UNKNOWN_CONN_ID;
897 }
898
899 return status;
900 }
901
902 #if defined(CONFIG_BT_CTLR_READ_ISO_LINK_QUALITY)
ll_read_iso_link_quality(uint16_t handle,uint32_t * tx_unacked_packets,uint32_t * tx_flushed_packets,uint32_t * tx_last_subevent_packets,uint32_t * retransmitted_packets,uint32_t * crc_error_packets,uint32_t * rx_unreceived_packets,uint32_t * duplicate_packets)903 uint8_t ll_read_iso_link_quality(uint16_t handle,
904 uint32_t *tx_unacked_packets,
905 uint32_t *tx_flushed_packets,
906 uint32_t *tx_last_subevent_packets,
907 uint32_t *retransmitted_packets,
908 uint32_t *crc_error_packets,
909 uint32_t *rx_unreceived_packets,
910 uint32_t *duplicate_packets)
911 {
912 ARG_UNUSED(handle);
913 ARG_UNUSED(tx_unacked_packets);
914 ARG_UNUSED(tx_flushed_packets);
915 ARG_UNUSED(tx_last_subevent_packets);
916 ARG_UNUSED(retransmitted_packets);
917 ARG_UNUSED(crc_error_packets);
918 ARG_UNUSED(rx_unreceived_packets);
919 ARG_UNUSED(duplicate_packets);
920
921 return BT_HCI_ERR_CMD_DISALLOWED;
922 }
923 #endif /* CONFIG_BT_CTLR_READ_ISO_LINK_QUALITY */
924
925 #endif /* CONFIG_BT_CTLR_SYNC_ISO || CONFIG_BT_CTLR_CONN_ISO */
926
927 #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
ll_iso_test_pdu_release(struct node_tx_iso * node_tx,const uint16_t handle,const isoal_status_t status)928 static isoal_status_t ll_iso_test_pdu_release(struct node_tx_iso *node_tx,
929 const uint16_t handle,
930 const isoal_status_t status)
931 {
932 /* Release back to memory pool */
933 if (node_tx->link) {
934 ll_iso_link_tx_release(node_tx->link);
935 }
936 ll_iso_tx_mem_release(node_tx);
937
938 return ISOAL_STATUS_OK;
939 }
940
941 #if defined(CONFIG_BT_CTLR_CONN_ISO)
ll_iso_transmit_test_send_sdu(uint16_t handle,uint32_t ticks_at_expire)942 void ll_iso_transmit_test_send_sdu(uint16_t handle, uint32_t ticks_at_expire)
943 {
944 isoal_source_handle_t source_handle;
945 struct isoal_sdu_tx sdu;
946 isoal_status_t err;
947 uint8_t tx_buffer[ISO_TEST_TX_BUFFER_SIZE];
948 uint64_t next_payload_number;
949 uint16_t remaining_tx;
950 uint32_t sdu_counter;
951
952 if (IS_CIS_HANDLE(handle)) {
953 struct ll_conn_iso_stream *cis;
954 struct ll_conn_iso_group *cig;
955 uint32_t rand_max_sdu;
956 uint8_t event_offset;
957 uint8_t rand_8;
958
959 cis = ll_iso_stream_connected_get(handle);
960 LL_ASSERT(cis);
961
962 if (!cis->hdr.test_mode.tx_enabled) {
963 /* Transmit Test Mode not enabled */
964 return;
965 }
966
967 cig = cis->group;
968 source_handle = cis->hdr.datapath_in->source_hdl;
969
970 switch (cis->hdr.test_mode.tx_payload_type) {
971 case BT_HCI_ISO_TEST_ZERO_SIZE_SDU:
972 remaining_tx = 0;
973 break;
974
975 case BT_HCI_ISO_TEST_VARIABLE_SIZE_SDU:
976 /* Randomize the length [4..p_max_sdu] */
977 lll_rand_get(&rand_8, sizeof(rand_8));
978 rand_max_sdu = rand_8 * (cis->p_max_sdu - ISO_TEST_PACKET_COUNTER_SIZE);
979 remaining_tx = ISO_TEST_PACKET_COUNTER_SIZE + (rand_max_sdu >> 8);
980 break;
981
982 case BT_HCI_ISO_TEST_MAX_SIZE_SDU:
983 LL_ASSERT(cis->p_max_sdu > ISO_TEST_PACKET_COUNTER_SIZE);
984 remaining_tx = cis->p_max_sdu;
985 break;
986
987 default:
988 LL_ASSERT(0);
989 return;
990 }
991
992 if (remaining_tx > ISO_TEST_TX_BUFFER_SIZE) {
993 sdu.sdu_state = BT_ISO_START;
994 } else {
995 sdu.sdu_state = BT_ISO_SINGLE;
996 }
997
998 /* Configure SDU similarly to one delivered via HCI */
999 sdu.packet_sn = 0;
1000 sdu.dbuf = tx_buffer;
1001
1002 /* We must ensure sufficient time for ISO-AL to fragment SDU and
1003 * deliver PDUs to the TX queue. By checking ull_ref_get, we
1004 * know if we are within the subevents of an ISO event. If so,
1005 * we can assume that we have enough time to deliver in the next
1006 * ISO event. If we're not active within the ISO event, we don't
1007 * know if there is enough time to deliver in the next event,
1008 * and for safety we set the target to current event + 2.
1009 *
1010 * For FT > 1, we have the opportunity to retransmit in later
1011 * event(s), in which case we have the option to target an
1012 * earlier event (this or next) because being late does not
1013 * instantly flush the payload.
1014 */
1015 event_offset = ull_ref_get(&cig->ull) ? 1 : 2;
1016 if (cis->lll.tx.ft > 1) {
1017 /* FT > 1, target an earlier event */
1018 event_offset -= 1;
1019 }
1020
1021 sdu.grp_ref_point = isoal_get_wrapped_time_us(cig->cig_ref_point,
1022 (event_offset * cig->iso_interval *
1023 ISO_INT_UNIT_US));
1024 sdu.target_event = cis->lll.event_count + event_offset;
1025 sdu.iso_sdu_length = remaining_tx;
1026
1027 /* Send all SDU fragments */
1028 do {
1029 sdu.time_stamp = HAL_TICKER_TICKS_TO_US(ticks_at_expire);
1030 sdu.size = MIN(remaining_tx, ISO_TEST_TX_BUFFER_SIZE);
1031 memset(tx_buffer, 0, sdu.size);
1032
1033 /* If this is the first fragment of a framed SDU, inject the SDU
1034 * counter.
1035 */
1036 if ((sdu.size >= ISO_TEST_PACKET_COUNTER_SIZE) &&
1037 ((sdu.sdu_state == BT_ISO_START) || (sdu.sdu_state == BT_ISO_SINGLE))) {
1038 if (cis->framed) {
1039 sdu_counter = (uint32_t)cis->hdr.test_mode.tx_sdu_counter;
1040 } else {
1041 /* Unframed. Get the next payload counter.
1042 *
1043 * BT 5.3, Vol 6, Part B, Section 7.1:
1044 * When using unframed PDUs, the SDU counter shall be equal
1045 * to the payload counter.
1046 */
1047 isoal_tx_unframed_get_next_payload_number(source_handle,
1048 &sdu,
1049 &next_payload_number);
1050 sdu_counter = (uint32_t)next_payload_number;
1051 }
1052
1053 sys_put_le32(sdu_counter, tx_buffer);
1054 }
1055
1056 /* Send to ISOAL */
1057 err = isoal_tx_sdu_fragment(source_handle, &sdu);
1058 LL_ASSERT(!err);
1059
1060 remaining_tx -= sdu.size;
1061
1062 if (remaining_tx > ISO_TEST_TX_BUFFER_SIZE) {
1063 sdu.sdu_state = BT_ISO_CONT;
1064 } else {
1065 sdu.sdu_state = BT_ISO_END;
1066 }
1067 } while (remaining_tx);
1068
1069 cis->hdr.test_mode.tx_sdu_counter++;
1070
1071 } else if (IS_ADV_ISO_HANDLE(handle)) {
1072 /* FIXME: Implement for broadcaster */
1073 } else {
1074 LL_ASSERT(0);
1075 }
1076 }
1077 #endif /* CONFIG_BT_CTLR_CONN_ISO */
1078
ll_iso_transmit_test(uint16_t handle,uint8_t payload_type)1079 uint8_t ll_iso_transmit_test(uint16_t handle, uint8_t payload_type)
1080 {
1081 isoal_source_handle_t source_handle;
1082 struct ll_iso_datapath *dp;
1083 uint32_t sdu_interval;
1084 isoal_status_t err;
1085 uint8_t status;
1086
1087 status = BT_HCI_ERR_SUCCESS;
1088
1089 if (IS_CIS_HANDLE(handle)) {
1090 struct ll_conn_iso_stream *cis;
1091 struct ll_conn_iso_group *cig;
1092
1093 cis = ll_iso_stream_connected_get(handle);
1094 if (!cis) {
1095 /* CIS is not connected */
1096 return BT_HCI_ERR_UNKNOWN_CONN_ID;
1097 }
1098
1099 if (cis->lll.tx.bn == 0U) {
1100 /* CIS is not configured for TX */
1101 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
1102 }
1103
1104 if (cis->hdr.datapath_in) {
1105 /* Data path already set up */
1106 return BT_HCI_ERR_CMD_DISALLOWED;
1107 }
1108
1109 if (payload_type > BT_HCI_ISO_TEST_MAX_SIZE_SDU) {
1110 return BT_HCI_ERR_INVALID_LL_PARAM;
1111 }
1112
1113 /* Allocate and configure test datapath */
1114 dp = mem_acquire(&datapath_free);
1115 if (!dp) {
1116 return BT_HCI_ERR_CMD_DISALLOWED;
1117 }
1118
1119 dp->path_dir = BT_HCI_DATAPATH_DIR_HOST_TO_CTLR;
1120 dp->path_id = BT_HCI_DATAPATH_ID_HCI;
1121
1122 cis->hdr.datapath_in = dp;
1123 cig = cis->group;
1124
1125 if (cig->lll.role == BT_HCI_ROLE_PERIPHERAL) {
1126 /* peripheral */
1127 sdu_interval = cig->c_sdu_interval;
1128 } else {
1129 /* central */
1130 sdu_interval = cig->p_sdu_interval;
1131 }
1132
1133 /* Setup the test source */
1134 err = isoal_source_create(handle, cig->lll.role, cis->framed,
1135 cis->lll.rx.bn, cis->lll.rx.ft,
1136 cis->lll.rx.max_pdu, sdu_interval,
1137 cig->iso_interval, cis->sync_delay,
1138 cig->sync_delay, ll_iso_pdu_alloc,
1139 ll_iso_pdu_write, ll_iso_pdu_emit,
1140 ll_iso_test_pdu_release,
1141 &source_handle);
1142
1143 if (err) {
1144 /* Error creating test source - cleanup source and datapath */
1145 isoal_source_destroy(source_handle);
1146 ull_iso_datapath_release(dp);
1147 cis->hdr.datapath_in = NULL;
1148
1149 return BT_HCI_ERR_CMD_DISALLOWED;
1150 }
1151
1152 dp->source_hdl = source_handle;
1153 isoal_source_enable(source_handle);
1154
1155 /* Enable Transmit Test Mode */
1156 cis->hdr.test_mode.tx_enabled = 1;
1157 cis->hdr.test_mode.tx_payload_type = payload_type;
1158
1159 } else if (IS_ADV_ISO_HANDLE(handle)) {
1160 struct lll_adv_iso_stream *stream;
1161 uint16_t stream_handle;
1162
1163 stream_handle = LL_BIS_ADV_IDX_FROM_HANDLE(handle);
1164 stream = ull_adv_iso_stream_get(stream_handle);
1165 if (!stream) {
1166 return BT_HCI_ERR_UNKNOWN_CONN_ID;
1167 }
1168
1169 /* FIXME: Implement use of common header in stream to enable code sharing
1170 * between CIS and BIS for test commands (and other places).
1171 */
1172 status = BT_HCI_ERR_CMD_DISALLOWED;
1173 } else {
1174 /* Handle is out of range */
1175 status = BT_HCI_ERR_UNKNOWN_CONN_ID;
1176 }
1177
1178 return status;
1179 }
1180 #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
1181
ll_iso_test_end(uint16_t handle,uint32_t * received_cnt,uint32_t * missed_cnt,uint32_t * failed_cnt)1182 uint8_t ll_iso_test_end(uint16_t handle, uint32_t *received_cnt,
1183 uint32_t *missed_cnt, uint32_t *failed_cnt)
1184 {
1185 uint8_t status;
1186
1187 *received_cnt = 0U;
1188 *missed_cnt = 0U;
1189 *failed_cnt = 0U;
1190
1191 status = BT_HCI_ERR_SUCCESS;
1192
1193 if (IS_CIS_HANDLE(handle)) {
1194 struct ll_conn_iso_stream *cis;
1195
1196 cis = ll_iso_stream_connected_get(handle);
1197 if (!cis) {
1198 /* CIS is not connected */
1199 return BT_HCI_ERR_UNKNOWN_CONN_ID;
1200 }
1201
1202 if (!cis->hdr.test_mode.rx_enabled && !cis->hdr.test_mode.tx_enabled) {
1203 /* Test Mode is not active */
1204 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
1205 }
1206
1207 if (cis->hdr.test_mode.rx_enabled) {
1208 isoal_sink_destroy(cis->hdr.datapath_out->sink_hdl);
1209 ull_iso_datapath_release(cis->hdr.datapath_out);
1210 cis->hdr.datapath_out = NULL;
1211
1212 /* Return SDU statistics */
1213 *received_cnt = cis->hdr.test_mode.received_cnt;
1214 *missed_cnt = cis->hdr.test_mode.missed_cnt;
1215 *failed_cnt = cis->hdr.test_mode.failed_cnt;
1216 }
1217
1218 if (cis->hdr.test_mode.tx_enabled) {
1219 /* Tear down source and datapath */
1220 isoal_source_destroy(cis->hdr.datapath_in->source_hdl);
1221 ull_iso_datapath_release(cis->hdr.datapath_in);
1222 cis->hdr.datapath_in = NULL;
1223 }
1224
1225 /* Disable Test Mode */
1226 (void)memset(&cis->hdr.test_mode, 0U, sizeof(cis->hdr.test_mode));
1227
1228 } else if (IS_ADV_ISO_HANDLE(handle)) {
1229 /* FIXME: Implement for broadcaster */
1230 status = BT_HCI_ERR_CMD_DISALLOWED;
1231 } else if (IS_SYNC_ISO_HANDLE(handle)) {
1232 /* FIXME: Implement for sync receiver */
1233 status = BT_HCI_ERR_CMD_DISALLOWED;
1234 } else {
1235 /* Handle is out of range */
1236 status = BT_HCI_ERR_UNKNOWN_CONN_ID;
1237 }
1238
1239 return status;
1240 }
1241
1242 #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
ll_iso_tx_mem_acquire(void)1243 void *ll_iso_tx_mem_acquire(void)
1244 {
1245 return mem_acquire(&mem_iso_tx.free);
1246 }
1247
ll_iso_tx_mem_release(void * node_tx)1248 void ll_iso_tx_mem_release(void *node_tx)
1249 {
1250 mem_release(node_tx, &mem_iso_tx.free);
1251 }
1252
ll_iso_tx_mem_enqueue(uint16_t handle,void * node_tx,void * link)1253 int ll_iso_tx_mem_enqueue(uint16_t handle, void *node_tx, void *link)
1254 {
1255 if (IS_ENABLED(CONFIG_BT_CTLR_CONN_ISO) &&
1256 IS_CIS_HANDLE(handle)) {
1257 struct ll_conn_iso_stream *cis;
1258
1259 cis = ll_conn_iso_stream_get(handle);
1260 memq_enqueue(link, node_tx, &cis->lll.memq_tx.tail);
1261
1262 } else if (IS_ENABLED(CONFIG_BT_CTLR_ADV_ISO) &&
1263 IS_ADV_ISO_HANDLE(handle)) {
1264 struct lll_adv_iso_stream *stream;
1265 uint16_t stream_handle;
1266
1267 stream_handle = LL_BIS_ADV_IDX_FROM_HANDLE(handle);
1268 stream = ull_adv_iso_stream_get(stream_handle);
1269 memq_enqueue(link, node_tx, &stream->memq_tx.tail);
1270
1271 } else {
1272 return -EINVAL;
1273 }
1274
1275 return 0;
1276 }
1277 #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
1278
ull_iso_init(void)1279 int ull_iso_init(void)
1280 {
1281 int err;
1282
1283 err = init_reset();
1284 if (err) {
1285 return err;
1286 }
1287
1288 return 0;
1289 }
1290
ull_iso_reset(void)1291 int ull_iso_reset(void)
1292 {
1293 int err;
1294
1295 err = init_reset();
1296 if (err) {
1297 return err;
1298 }
1299
1300 return 0;
1301 }
1302
1303 #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
ull_iso_lll_ack_enqueue(uint16_t handle,struct node_tx_iso * node_tx)1304 void ull_iso_lll_ack_enqueue(uint16_t handle, struct node_tx_iso *node_tx)
1305 {
1306 struct ll_iso_datapath *dp = NULL;
1307
1308 if (IS_ENABLED(CONFIG_BT_CTLR_CONN_ISO) && IS_CIS_HANDLE(handle)) {
1309 struct ll_conn_iso_stream *cis;
1310
1311 cis = ll_conn_iso_stream_get(handle);
1312 dp = cis->hdr.datapath_in;
1313
1314 if (dp) {
1315 isoal_tx_pdu_release(dp->source_hdl, node_tx);
1316 } else {
1317 /* Race with Data Path remove */
1318 /* FIXME: ll_tx_ack_put is not LLL callable as it is
1319 * used by ACL connections in ULL context to dispatch
1320 * ack.
1321 */
1322 ll_tx_ack_put(handle, (void *)node_tx);
1323 ll_rx_sched();
1324 }
1325 } else if (IS_ENABLED(CONFIG_BT_CTLR_ADV_ISO) && IS_ADV_ISO_HANDLE(handle)) {
1326 /* Process as TX ack. TODO: Can be unified with CIS and use
1327 * ISOAL.
1328 */
1329 /* FIXME: ll_tx_ack_put is not LLL callable as it is
1330 * used by ACL connections in ULL context to dispatch
1331 * ack.
1332 */
1333 ll_tx_ack_put(handle, (void *)node_tx);
1334 ll_rx_sched();
1335 } else {
1336 LL_ASSERT(0);
1337 }
1338 }
1339
ull_iso_lll_event_prepare(uint16_t handle,uint64_t event_count)1340 void ull_iso_lll_event_prepare(uint16_t handle, uint64_t event_count)
1341 {
1342 if (IS_CIS_HANDLE(handle)) {
1343 struct ll_iso_datapath *dp = NULL;
1344 struct ll_conn_iso_stream *cis;
1345
1346 cis = ll_iso_stream_connected_get(handle);
1347
1348 if (cis) {
1349 dp = cis->hdr.datapath_in;
1350 }
1351
1352 if (dp) {
1353 isoal_tx_event_prepare(dp->source_hdl, event_count);
1354 }
1355 } else if (IS_ADV_ISO_HANDLE(handle)) {
1356 /* Send event deadline trigger to ISO-AL.
1357 * TODO: Can be unified with CIS implementation.
1358 */
1359 } else {
1360 LL_ASSERT(0);
1361 }
1362 }
1363 #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
1364
1365 #if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
ull_iso_pdu_rx_alloc_peek(uint8_t count)1366 void *ull_iso_pdu_rx_alloc_peek(uint8_t count)
1367 {
1368 if (count > MFIFO_AVAIL_COUNT_GET(iso_rx)) {
1369 return NULL;
1370 }
1371
1372 return MFIFO_DEQUEUE_PEEK(iso_rx);
1373 }
1374
ull_iso_pdu_rx_alloc(void)1375 void *ull_iso_pdu_rx_alloc(void)
1376 {
1377 return MFIFO_DEQUEUE(iso_rx);
1378 }
1379
1380 #if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH)
ull_iso_rx_put(memq_link_t * link,void * rx)1381 void ull_iso_rx_put(memq_link_t *link, void *rx)
1382 {
1383 /* Enqueue the Rx object */
1384 memq_enqueue(link, rx, &memq_ull_iso_rx.tail);
1385 }
1386
ull_iso_rx_sched(void)1387 void ull_iso_rx_sched(void)
1388 {
1389 static memq_link_t link;
1390 static struct mayfly mfy = {0, 0, &link, NULL, iso_rx_demux};
1391
1392 /* Kick the ULL (using the mayfly, tailchain it) */
1393 mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_HIGH, 1, &mfy);
1394 }
1395
1396 #if defined(CONFIG_BT_CTLR_CONN_ISO)
iso_rx_cig_ref_point_update(struct ll_conn_iso_group * cig,const struct ll_conn_iso_stream * cis,const struct node_rx_iso_meta * meta)1397 static void iso_rx_cig_ref_point_update(struct ll_conn_iso_group *cig,
1398 const struct ll_conn_iso_stream *cis,
1399 const struct node_rx_iso_meta *meta)
1400 {
1401 uint32_t cig_sync_delay;
1402 uint32_t cis_sync_delay;
1403 uint64_t event_count;
1404 uint8_t burst_number;
1405 uint8_t role;
1406
1407 role = cig->lll.role;
1408 cig_sync_delay = cig->sync_delay;
1409 cis_sync_delay = cis->sync_delay;
1410 burst_number = cis->lll.rx.bn;
1411 event_count = cis->lll.event_count;
1412
1413 if (role) {
1414 /* Peripheral */
1415
1416 /* Check if this is the first payload received for this cis in
1417 * this event
1418 */
1419 if (meta->payload_number == (burst_number * event_count)) {
1420 /* Update the CIG reference point based on the CIS
1421 * anchor point
1422 */
1423 cig->cig_ref_point = isoal_get_wrapped_time_us(meta->timestamp,
1424 cis_sync_delay - cig_sync_delay);
1425 }
1426 }
1427 }
1428 #endif /* CONFIG_BT_CTLR_CONN_ISO */
1429
iso_rx_demux(void * param)1430 static void iso_rx_demux(void *param)
1431 {
1432 #if defined(CONFIG_BT_CTLR_CONN_ISO)
1433 struct ll_conn_iso_stream *cis;
1434 struct ll_conn_iso_group *cig;
1435 struct ll_iso_datapath *dp;
1436 struct node_rx_pdu *rx_pdu;
1437 #endif /* CONFIG_BT_CTLR_CONN_ISO */
1438 struct node_rx_hdr *rx;
1439 memq_link_t *link;
1440
1441 do {
1442 link = memq_peek(memq_ull_iso_rx.head, memq_ull_iso_rx.tail,
1443 (void **)&rx);
1444 if (link) {
1445 /* Demux Rx objects */
1446 switch (rx->type) {
1447 case NODE_RX_TYPE_RELEASE:
1448 (void)memq_dequeue(memq_ull_iso_rx.tail,
1449 &memq_ull_iso_rx.head, NULL);
1450 ll_iso_rx_put(link, rx);
1451 ll_rx_sched();
1452 break;
1453
1454 case NODE_RX_TYPE_ISO_PDU:
1455 /* Remove from receive-queue; ULL has received this now */
1456 (void)memq_dequeue(memq_ull_iso_rx.tail, &memq_ull_iso_rx.head,
1457 NULL);
1458
1459 #if defined(CONFIG_BT_CTLR_CONN_ISO)
1460 rx_pdu = (struct node_rx_pdu *)rx;
1461 cis = ll_conn_iso_stream_get(rx_pdu->hdr.handle);
1462 cig = cis->group;
1463 dp = cis->hdr.datapath_out;
1464
1465 iso_rx_cig_ref_point_update(cig, cis, &rx_pdu->hdr.rx_iso_meta);
1466
1467 if (dp && dp->path_id != BT_HCI_DATAPATH_ID_HCI) {
1468 /* If vendor specific datapath pass to ISO AL here,
1469 * in case of HCI destination it will be passed in
1470 * HCI context.
1471 */
1472 struct isoal_pdu_rx pckt_meta = {
1473 .meta = &rx_pdu->hdr.rx_iso_meta,
1474 .pdu = (struct pdu_iso *)&rx_pdu->pdu[0]
1475 };
1476
1477 /* Pass the ISO PDU through ISO-AL */
1478 const isoal_status_t err =
1479 isoal_rx_pdu_recombine(dp->sink_hdl, &pckt_meta);
1480
1481 LL_ASSERT(err == ISOAL_STATUS_OK); /* TODO handle err */
1482 }
1483 #endif /* CONFIG_BT_CTLR_CONN_ISO */
1484
1485 /* Let ISO PDU start its long journey upwards */
1486 ll_iso_rx_put(link, rx);
1487 ll_rx_sched();
1488 break;
1489
1490 default:
1491 LL_ASSERT(0);
1492 break;
1493 }
1494 }
1495 } while (link);
1496 }
1497 #endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */
1498
ll_iso_rx_put(memq_link_t * link,void * rx)1499 void ll_iso_rx_put(memq_link_t *link, void *rx)
1500 {
1501 /* Enqueue the Rx object */
1502 memq_enqueue(link, rx, &memq_ll_iso_rx.tail);
1503 }
1504
ll_iso_rx_get(void)1505 void *ll_iso_rx_get(void)
1506 {
1507 struct node_rx_hdr *rx;
1508 memq_link_t *link;
1509
1510 link = memq_peek(memq_ll_iso_rx.head, memq_ll_iso_rx.tail, (void **)&rx);
1511 while (link) {
1512 /* Do not send up buffers to Host thread that are
1513 * marked for release
1514 */
1515 if (rx->type == NODE_RX_TYPE_RELEASE) {
1516 (void)memq_dequeue(memq_ll_iso_rx.tail,
1517 &memq_ll_iso_rx.head, NULL);
1518 mem_release(link, &mem_link_iso_rx.free);
1519 mem_release(rx, &mem_iso_rx.free);
1520 RXFIFO_ALLOC(iso_rx, 1);
1521
1522 link = memq_peek(memq_ll_iso_rx.head, memq_ll_iso_rx.tail, (void **)&rx);
1523 continue;
1524 }
1525 return rx;
1526 }
1527
1528 return NULL;
1529 }
1530
ll_iso_rx_dequeue(void)1531 void ll_iso_rx_dequeue(void)
1532 {
1533 struct node_rx_hdr *rx = NULL;
1534 memq_link_t *link;
1535
1536 link = memq_dequeue(memq_ll_iso_rx.tail, &memq_ll_iso_rx.head,
1537 (void **)&rx);
1538 LL_ASSERT(link);
1539
1540 mem_release(link, &mem_link_iso_rx.free);
1541
1542 /* Handle object specific clean up */
1543 switch (rx->type) {
1544 case NODE_RX_TYPE_ISO_PDU:
1545 break;
1546 default:
1547 LL_ASSERT(0);
1548 break;
1549 }
1550 }
1551
ll_iso_rx_mem_release(void ** node_rx)1552 void ll_iso_rx_mem_release(void **node_rx)
1553 {
1554 struct node_rx_hdr *rx;
1555
1556 rx = *node_rx;
1557 while (rx) {
1558 struct node_rx_hdr *rx_free;
1559
1560 rx_free = rx;
1561 rx = rx->next;
1562
1563 switch (rx_free->type) {
1564 case NODE_RX_TYPE_ISO_PDU:
1565 mem_release(rx_free, &mem_iso_rx.free);
1566 break;
1567 default:
1568 /* Ignore other types as node may have been initialized due to
1569 * race with HCI reset.
1570 */
1571 break;
1572 }
1573 }
1574
1575 *node_rx = rx;
1576
1577 RXFIFO_ALLOC(iso_rx, UINT8_MAX);
1578 }
1579 #endif /* CONFIG_BT_CTLR_SYNC_ISO) || CONFIG_BT_CTLR_CONN_ISO */
1580
ull_iso_datapath_alloc(void)1581 struct ll_iso_datapath *ull_iso_datapath_alloc(void)
1582 {
1583 return mem_acquire(&datapath_free);
1584 }
1585
ull_iso_datapath_release(struct ll_iso_datapath * dp)1586 void ull_iso_datapath_release(struct ll_iso_datapath *dp)
1587 {
1588 mem_release(dp, &datapath_free);
1589 }
1590
1591 #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
ll_iso_link_tx_release(void * link)1592 void ll_iso_link_tx_release(void *link)
1593 {
1594 mem_release(link, &mem_link_iso_tx.free);
1595 }
1596
1597 /**
1598 * Allocate a PDU from the LL and store the details in the given buffer. Allocation
1599 * is not expected to fail as there must always be sufficient PDU buffers. Any
1600 * failure will trigger the assert.
1601 * @param[in] pdu_buffer Buffer to store PDU details in
1602 * @return Error status of operation
1603 */
ll_iso_pdu_alloc(struct isoal_pdu_buffer * pdu_buffer)1604 static isoal_status_t ll_iso_pdu_alloc(struct isoal_pdu_buffer *pdu_buffer)
1605 {
1606 struct node_tx_iso *node_tx;
1607
1608 node_tx = ll_iso_tx_mem_acquire();
1609 if (!node_tx) {
1610 LOG_ERR("Tx Buffer Overflow");
1611 /* TODO: Report overflow to HCI and remove assert
1612 * data_buf_overflow(evt, BT_OVERFLOW_LINK_ISO)
1613 */
1614 LL_ASSERT(0);
1615 return ISOAL_STATUS_ERR_PDU_ALLOC;
1616 }
1617
1618 node_tx->link = NULL;
1619
1620 /* node_tx handle will be required to emit the PDU later */
1621 pdu_buffer->handle = (void *)node_tx;
1622 pdu_buffer->pdu = (void *)node_tx->pdu;
1623
1624 /* Use TX buffer size as the limit here. Actual size will be decided in
1625 * the ISOAL based on the minimum of the buffer size and the respective
1626 * Max_PDU_C_To_P or Max_PDU_P_To_C.
1627 */
1628 pdu_buffer->size = MAX(LL_BIS_OCTETS_TX_MAX, LL_CIS_OCTETS_TX_MAX);
1629
1630 return ISOAL_STATUS_OK;
1631 }
1632
1633 /**
1634 * Write the given SDU payload to the target PDU buffer at the given offset.
1635 * @param[in,out] pdu_buffer Target PDU buffer
1636 * @param[in] pdu_offset Offset / current write position within PDU
1637 * @param[in] sdu_payload Location of source data
1638 * @param[in] consume_len Length of data to copy
1639 * @return Error status of write operation
1640 */
ll_iso_pdu_write(struct isoal_pdu_buffer * pdu_buffer,const size_t pdu_offset,const uint8_t * sdu_payload,const size_t consume_len)1641 static isoal_status_t ll_iso_pdu_write(struct isoal_pdu_buffer *pdu_buffer,
1642 const size_t pdu_offset,
1643 const uint8_t *sdu_payload,
1644 const size_t consume_len)
1645 {
1646 ARG_UNUSED(pdu_offset);
1647 ARG_UNUSED(consume_len);
1648
1649 LL_ASSERT(pdu_buffer);
1650 LL_ASSERT(pdu_buffer->pdu);
1651 LL_ASSERT(sdu_payload);
1652
1653 if ((pdu_offset + consume_len) > pdu_buffer->size) {
1654 /* Exceeded PDU buffer */
1655 return ISOAL_STATUS_ERR_UNSPECIFIED;
1656 }
1657
1658 /* Copy source to destination at given offset */
1659 memcpy(&pdu_buffer->pdu->payload[pdu_offset], sdu_payload, consume_len);
1660
1661 return ISOAL_STATUS_OK;
1662 }
1663
1664 /**
1665 * Emit the encoded node to the transmission queue
1666 * @param node_tx TX node to enqueue
1667 * @param handle CIS/BIS handle
1668 * @return Error status of enqueue operation
1669 */
ll_iso_pdu_emit(struct node_tx_iso * node_tx,const uint16_t handle)1670 static isoal_status_t ll_iso_pdu_emit(struct node_tx_iso *node_tx,
1671 const uint16_t handle)
1672 {
1673 memq_link_t *link;
1674
1675 link = mem_acquire(&mem_link_iso_tx.free);
1676 LL_ASSERT(link);
1677
1678 if (ll_iso_tx_mem_enqueue(handle, node_tx, link)) {
1679 return ISOAL_STATUS_ERR_PDU_EMIT;
1680 }
1681
1682 return ISOAL_STATUS_OK;
1683 }
1684
1685 #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
1686 /**
1687 * Release the given payload back to the memory pool.
1688 * @param node_tx TX node to release or forward
1689 * @param handle CIS/BIS handle
1690 * @param status Reason for release
1691 * @return Error status of release operation
1692 */
ll_iso_pdu_release(struct node_tx_iso * node_tx,const uint16_t handle,const isoal_status_t status)1693 static isoal_status_t ll_iso_pdu_release(struct node_tx_iso *node_tx,
1694 const uint16_t handle,
1695 const isoal_status_t status)
1696 {
1697 if (status == ISOAL_STATUS_OK) {
1698 /* Process as TX ack, we are in LLL execution context here.
1699 * status == ISOAL_STATUS_OK when an ISO PDU has been acked.
1700 *
1701 * Call Path:
1702 * ull_iso_lll_ack_enqueue() --> isoal_tx_pdu_release() -->
1703 * pdu_release() == ll_iso_pdu_release() (this function).
1704 */
1705 /* FIXME: ll_tx_ack_put is not LLL callable as it is used by
1706 * ACL connections in ULL context to dispatch ack.
1707 */
1708 ll_tx_ack_put(handle, (void *)node_tx);
1709 ll_rx_sched();
1710 } else {
1711 /* Release back to memory pool, we are in Thread context
1712 * Callers:
1713 * isoal_source_deallocate() with ISOAL_STATUS_ERR_PDU_EMIT
1714 * isoal_tx_pdu_emit with status != ISOAL_STATUS_OK
1715 */
1716 if (node_tx->link) {
1717 ll_iso_link_tx_release(node_tx->link);
1718 }
1719 ll_iso_tx_mem_release(node_tx);
1720 }
1721
1722 return ISOAL_STATUS_OK;
1723 }
1724 #endif /* CONFIG_BT_CTLR_CONN_ISO */
1725 #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
1726
init_reset(void)1727 static int init_reset(void)
1728 {
1729 #if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
1730 memq_link_t *link;
1731
1732 RXFIFO_INIT(iso_rx);
1733
1734 /* Acquire a link to initialize ull rx memq */
1735 link = mem_acquire(&mem_link_iso_rx.free);
1736 LL_ASSERT(link);
1737
1738 #if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH)
1739 /* Initialize ull rx memq */
1740 MEMQ_INIT(ull_iso_rx, link);
1741 #endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */
1742
1743 /* Acquire a link to initialize ll_iso_rx memq */
1744 link = mem_acquire(&mem_link_iso_rx.free);
1745 LL_ASSERT(link);
1746
1747 /* Initialize ll_iso_rx memq */
1748 MEMQ_INIT(ll_iso_rx, link);
1749
1750 RXFIFO_ALLOC(iso_rx, UINT8_MAX);
1751 #endif /* CONFIG_BT_CTLR_SYNC_ISO) || CONFIG_BT_CTLR_CONN_ISO */
1752
1753 #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
1754 /* Initialize tx pool. */
1755 mem_init(mem_iso_tx.pool, NODE_TX_BUFFER_SIZE, BT_CTLR_ISO_TX_BUFFERS,
1756 &mem_iso_tx.free);
1757
1758 /* Initialize tx link pool. */
1759 mem_init(mem_link_iso_tx.pool, sizeof(memq_link_t),
1760 BT_CTLR_ISO_TX_BUFFERS, &mem_link_iso_tx.free);
1761 #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
1762
1763 #if BT_CTLR_ISO_STREAMS
1764 /* Initialize ISO Datapath pool */
1765 mem_init(datapath_pool, sizeof(struct ll_iso_datapath),
1766 sizeof(datapath_pool) / sizeof(struct ll_iso_datapath), &datapath_free);
1767 #endif /* BT_CTLR_ISO_STREAMS */
1768
1769 /* Initialize ISO Adaptation Layer */
1770 isoal_init();
1771
1772 return 0;
1773 }
1774