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