1 /*
2  * Copyright (c) 2021-2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <ctype.h>
8 #include <stdlib.h>
9 #include <stdint.h>
10 
11 #include <zephyr/bluetooth/gap.h>
12 #include <zephyr/console/console.h>
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/bluetooth/iso.h>
15 #include <zephyr/sys/byteorder.h>
16 
17 #include <zephyr/logging/log.h>
18 #include <zephyr/sys/util.h>
19 #include <zephyr/sys_clock.h>
20 LOG_MODULE_REGISTER(iso_broadcast_broadcaster, LOG_LEVEL_DBG);
21 
22 #define DEFAULT_BIS_RTN           2
23 #define DEFAULT_BIS_INTERVAL_US   7500
24 #define DEFAULT_BIS_LATENCY_MS    10
25 #define DEFAULT_BIS_PHY           BT_GAP_LE_PHY_2M
26 #define DEFAULT_BIS_SDU           CONFIG_BT_ISO_TX_MTU
27 #define DEFAULT_BIS_PACKING       0
28 #define DEFAULT_BIS_FRAMING       0
29 #define DEFAULT_BIS_COUNT         CONFIG_BT_ISO_MAX_CHAN
30 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
31 #define DEFAULT_BIS_NSE           BT_ISO_NSE_MIN
32 #define DEFAULT_BIS_BN            BT_ISO_BN_MIN
33 #define DEFAULT_BIS_PDU_SIZE      CONFIG_BT_ISO_TX_MTU
34 #define DEFAULT_BIS_IRC           BT_ISO_IRC_MIN
35 #define DEFAULT_BIS_PTO           BT_ISO_PTO_MIN
36 #define DEFAULT_BIS_ISO_INTERVAL  DEFAULT_BIS_INTERVAL_US / 1250U /* N * 10 ms */
37 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
38 
39 NET_BUF_POOL_FIXED_DEFINE(bis_tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT,
40 			  BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
41 			  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
42 
43 static K_SEM_DEFINE(sem_big_complete, 0, 1);
44 static K_SEM_DEFINE(sem_big_term, 0, 1);
45 static struct k_work_delayable iso_send_work;
46 static uint32_t iso_send_count;
47 static uint8_t iso_data[CONFIG_BT_ISO_TX_MTU];
48 static uint8_t connected_bis;
49 
50 static struct bt_iso_chan bis_iso_chans[CONFIG_BT_ISO_MAX_CHAN];
51 static struct bt_iso_chan *bis[CONFIG_BT_ISO_MAX_CHAN];
52 /* We use a single seq_num for all the BIS as they share the same SDU interval */
53 static uint16_t seq_num;
54 static struct bt_iso_big_create_param big_create_param = {
55 	.num_bis = DEFAULT_BIS_COUNT,
56 	.bis_channels = bis,
57 	.packing = DEFAULT_BIS_PACKING, /* 0 - sequential, 1 - interleaved */
58 	.framing = DEFAULT_BIS_FRAMING, /* 0 - unframed, 1 - framed */
59 	.interval = DEFAULT_BIS_INTERVAL_US, /* in microseconds */
60 	.latency = DEFAULT_BIS_LATENCY_MS, /* milliseconds */
61 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
62 	.irc = DEFAULT_BIS_IRC,
63 	.pto = DEFAULT_BIS_PTO,
64 	.iso_interval = DEFAULT_BIS_ISO_INTERVAL,
65 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
66 };
67 
68 static const struct bt_data ad[] = {
69 	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
70 };
71 
iso_connected(struct bt_iso_chan * chan)72 static void iso_connected(struct bt_iso_chan *chan)
73 {
74 	LOG_INF("ISO Channel %p connected", chan);
75 
76 	connected_bis++;
77 	if (connected_bis == big_create_param.num_bis) {
78 		seq_num = 0U;
79 		k_sem_give(&sem_big_complete);
80 	}
81 }
82 
iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)83 static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
84 {
85 	LOG_INF("ISO Channel %p disconnected with reason 0x%02x",
86 	       chan, reason);
87 
88 	connected_bis--;
89 	if (connected_bis == big_create_param.num_bis) {
90 		k_sem_give(&sem_big_term);
91 	}
92 }
93 
94 static struct bt_iso_chan_ops iso_ops = {
95 	.connected	= iso_connected,
96 	.disconnected	= iso_disconnected,
97 };
98 
99 static struct bt_iso_chan_io_qos iso_tx_qos = {
100 	.sdu = DEFAULT_BIS_SDU, /* bytes */
101 	.rtn = DEFAULT_BIS_RTN,
102 	.phy = DEFAULT_BIS_PHY,
103 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
104 	.max_pdu = DEFAULT_BIS_PDU_SIZE,
105 	.burst_number = DEFAULT_BIS_BN,
106 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
107 };
108 
109 static struct bt_iso_chan_qos bis_iso_qos = {
110 	.tx = &iso_tx_qos,
111 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
112 	.num_subevents = DEFAULT_BIS_NSE,
113 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
114 };
115 
get_chars(char * buffer,size_t max_size)116 static size_t get_chars(char *buffer, size_t max_size)
117 {
118 	size_t pos = 0;
119 
120 	while (pos < max_size) {
121 		char c = tolower(console_getchar());
122 
123 		if (c == '\n' || c == '\r') {
124 			break;
125 		}
126 		printk("%c", c);
127 		buffer[pos++] = c;
128 	}
129 	printk("\n");
130 	buffer[pos] = '\0';
131 
132 	return pos;
133 }
134 
parse_rtn_arg(void)135 static int parse_rtn_arg(void)
136 {
137 	char buffer[4];
138 	size_t char_count;
139 	uint64_t rtn;
140 
141 	printk("Set RTN (current %u, default %u)\n",
142 	       iso_tx_qos.rtn, DEFAULT_BIS_RTN);
143 
144 	char_count = get_chars(buffer, sizeof(buffer) - 1);
145 	if (char_count == 0) {
146 		return DEFAULT_BIS_RTN;
147 	}
148 
149 	rtn = strtoul(buffer, NULL, 0);
150 	if (rtn > BT_ISO_BROADCAST_RTN_MAX) {
151 		printk("Invalid RTN %llu", rtn);
152 		return -EINVAL;
153 	}
154 
155 	return (int)rtn;
156 }
157 
parse_interval_arg(void)158 static int parse_interval_arg(void)
159 {
160 	char buffer[9];
161 	size_t char_count;
162 	uint64_t interval;
163 
164 	printk("Set interval (us) (current %u, default %u)\n",
165 	       big_create_param.interval, DEFAULT_BIS_INTERVAL_US);
166 
167 	char_count = get_chars(buffer, sizeof(buffer) - 1);
168 	if (char_count == 0) {
169 		return DEFAULT_BIS_INTERVAL_US;
170 	}
171 
172 	interval = strtoul(buffer, NULL, 0);
173 	if (interval < BT_ISO_SDU_INTERVAL_MIN || interval > BT_ISO_SDU_INTERVAL_MAX) {
174 		printk("Invalid interval %llu", interval);
175 		return -EINVAL;
176 	}
177 
178 	return (int)interval;
179 }
180 
parse_latency_arg(void)181 static int parse_latency_arg(void)
182 {
183 	char buffer[6];
184 	size_t char_count;
185 	uint64_t latency;
186 
187 	printk("Set latency (ms) (current %u, default %u)\n",
188 	       big_create_param.latency, DEFAULT_BIS_LATENCY_MS);
189 
190 	char_count = get_chars(buffer, sizeof(buffer) - 1);
191 	if (char_count == 0) {
192 		return DEFAULT_BIS_LATENCY_MS;
193 	}
194 
195 	latency = strtoul(buffer, NULL, 0);
196 	if (latency < BT_ISO_LATENCY_MIN || latency > BT_ISO_LATENCY_MAX) {
197 		printk("Invalid latency %llu", latency);
198 		return -EINVAL;
199 	}
200 
201 	return (int)latency;
202 }
203 
parse_phy_arg(void)204 static int parse_phy_arg(void)
205 {
206 	char buffer[3];
207 	size_t char_count;
208 	uint64_t phy;
209 
210 	printk("Set PHY (current %u, default %u) - %u = 1M, %u = 2M, %u = Coded\n",
211 	       iso_tx_qos.phy, DEFAULT_BIS_PHY, BT_GAP_LE_PHY_1M,
212 	       BT_GAP_LE_PHY_2M, BT_GAP_LE_PHY_CODED);
213 
214 	char_count = get_chars(buffer, sizeof(buffer) - 1);
215 	if (char_count == 0) {
216 		return DEFAULT_BIS_PHY;
217 	}
218 
219 	phy = strtoul(buffer, NULL, 0);
220 	if (phy != BT_GAP_LE_PHY_1M &&
221 	    phy != BT_GAP_LE_PHY_2M &&
222 	    phy != BT_GAP_LE_PHY_CODED) {
223 		printk("Invalid PHY %llu", phy);
224 		return -EINVAL;
225 	}
226 
227 	return (int)phy;
228 }
229 
parse_sdu_arg(void)230 static int parse_sdu_arg(void)
231 {
232 	char buffer[6];
233 	size_t char_count;
234 	uint64_t sdu;
235 
236 	printk("Set SDU (current %u, default %u)\n",
237 	       iso_tx_qos.sdu, DEFAULT_BIS_SDU);
238 
239 	char_count = get_chars(buffer, sizeof(buffer) - 1);
240 	if (char_count == 0) {
241 		return DEFAULT_BIS_SDU;
242 	}
243 
244 	sdu = strtoul(buffer, NULL, 0);
245 	if (sdu > MIN(BT_ISO_MAX_SDU, sizeof(iso_data))) {
246 		printk("Invalid SDU %llu", sdu);
247 		return -EINVAL;
248 	}
249 
250 	return (int)sdu;
251 }
252 
253 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
parse_irc_arg(void)254 static int parse_irc_arg(void)
255 {
256 	size_t char_count;
257 	char buffer[4];
258 	uint64_t irc;
259 
260 	printk("Set IRC (current %u, default %u)\n",
261 	       big_create_param.irc, DEFAULT_BIS_IRC);
262 
263 	char_count = get_chars(buffer, sizeof(buffer) - 1);
264 	if (char_count == 0) {
265 		return DEFAULT_BIS_IRC;
266 	}
267 
268 	irc = strtoul(buffer, NULL, 0);
269 	if (!IN_RANGE(irc, BT_ISO_IRC_MIN, BT_ISO_IRC_MAX)) {
270 		printk("Invalid IRC %llu", irc);
271 
272 		return -EINVAL;
273 	}
274 
275 	return (int)irc;
276 }
277 
parse_pto_arg(void)278 static int parse_pto_arg(void)
279 {
280 	size_t char_count;
281 	char buffer[4];
282 	uint64_t pto;
283 
284 	printk("Set PTO (current %u, default %u)\n",
285 	       big_create_param.pto, DEFAULT_BIS_PTO);
286 
287 	char_count = get_chars(buffer, sizeof(buffer) - 1);
288 	if (char_count == 0) {
289 		return DEFAULT_BIS_PTO;
290 	}
291 
292 	pto = strtoul(buffer, NULL, 0);
293 	if (!IN_RANGE(pto, BT_ISO_PTO_MIN, BT_ISO_PTO_MAX)) {
294 		printk("Invalid PTO %llu", pto);
295 
296 		return -EINVAL;
297 	}
298 
299 	return (int)pto;
300 }
301 
parse_iso_interval_arg(void)302 static int parse_iso_interval_arg(void)
303 {
304 	uint64_t iso_interval;
305 	size_t char_count;
306 	char buffer[8];
307 
308 	printk("Set ISO interval (current %u, default %u)\n",
309 	       big_create_param.iso_interval, DEFAULT_BIS_ISO_INTERVAL);
310 
311 	char_count = get_chars(buffer, sizeof(buffer) - 1);
312 	if (char_count == 0) {
313 		return DEFAULT_BIS_ISO_INTERVAL;
314 	}
315 
316 	iso_interval = strtoul(buffer, NULL, 0);
317 	if (!IN_RANGE(iso_interval, BT_ISO_ISO_INTERVAL_MIN, BT_ISO_ISO_INTERVAL_MAX)) {
318 		printk("Invalid ISO interval %llu", iso_interval);
319 
320 		return -EINVAL;
321 	}
322 
323 	return (int)iso_interval;
324 }
325 
parse_nse_arg(void)326 static int parse_nse_arg(void)
327 {
328 	uint64_t num_subevents;
329 	size_t char_count;
330 	char buffer[4];
331 
332 	printk("Set number of subevents (current %u, default %u)\n",
333 	       bis_iso_qos.num_subevents, DEFAULT_BIS_NSE);
334 
335 	char_count = get_chars(buffer, sizeof(buffer) - 1);
336 	if (char_count == 0) {
337 		return DEFAULT_BIS_NSE;
338 	}
339 
340 	num_subevents = strtoul(buffer, NULL, 0);
341 	if (!IN_RANGE(num_subevents, BT_ISO_NSE_MIN, BT_ISO_NSE_MAX)) {
342 		printk("Invalid number of subevents %llu", num_subevents);
343 
344 		return -EINVAL;
345 	}
346 
347 	return (int)num_subevents;
348 }
349 
parse_max_pdu_arg(void)350 static int parse_max_pdu_arg(void)
351 {
352 	size_t char_count;
353 	uint64_t max_pdu;
354 	char buffer[6];
355 
356 	printk("Set max PDU (current %u, default %u)\n",
357 	       iso_tx_qos.max_pdu, DEFAULT_BIS_PDU_SIZE);
358 
359 	char_count = get_chars(buffer, sizeof(buffer) - 1);
360 	if (char_count == 0) {
361 		return DEFAULT_BIS_PDU_SIZE;
362 	}
363 
364 	max_pdu = strtoul(buffer, NULL, 0);
365 	if (max_pdu > BT_ISO_PDU_MAX) {
366 		printk("Invalid max PDU %llu", max_pdu);
367 
368 		return -EINVAL;
369 	}
370 
371 	return (int)max_pdu;
372 }
373 
parse_bn_arg(void)374 static int parse_bn_arg(void)
375 {
376 	uint64_t burst_number;
377 	size_t char_count;
378 	char buffer[4];
379 
380 	printk("Set burst number (current %u, default %u)\n",
381 	       iso_tx_qos.burst_number, DEFAULT_BIS_BN);
382 
383 	char_count = get_chars(buffer, sizeof(buffer) - 1);
384 	if (char_count == 0) {
385 		return DEFAULT_BIS_PDU_SIZE;
386 	}
387 
388 	burst_number = strtoul(buffer, NULL, 0);
389 	if (!IN_RANGE(burst_number, BT_ISO_BN_MIN, BT_ISO_BN_MAX)) {
390 		printk("Invalid burst number %llu", burst_number);
391 
392 		return -EINVAL;
393 	}
394 
395 	return (int)burst_number;
396 }
397 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
398 
parse_packing_arg(void)399 static int parse_packing_arg(void)
400 {
401 	char buffer[3];
402 	size_t char_count;
403 	uint64_t packing;
404 
405 	printk("Set packing (current %u, default %u)\n",
406 	       big_create_param.packing, DEFAULT_BIS_PACKING);
407 
408 	char_count = get_chars(buffer, sizeof(buffer) - 1);
409 	if (char_count == 0) {
410 		return DEFAULT_BIS_PACKING;
411 	}
412 
413 	packing = strtoul(buffer, NULL, 0);
414 	if (packing != BT_ISO_PACKING_SEQUENTIAL &&
415 	    packing != BT_ISO_PACKING_INTERLEAVED) {
416 		printk("Invalid packing %llu", packing);
417 		return -EINVAL;
418 	}
419 
420 	return (int)packing;
421 }
422 
parse_framing_arg(void)423 static int parse_framing_arg(void)
424 {
425 	char buffer[3];
426 	size_t char_count;
427 	uint64_t framing;
428 
429 	printk("Set framing (current %u, default %u)\n",
430 	       big_create_param.framing, DEFAULT_BIS_FRAMING);
431 
432 	char_count = get_chars(buffer, sizeof(buffer) - 1);
433 	if (char_count == 0) {
434 		return DEFAULT_BIS_FRAMING;
435 	}
436 
437 	framing = strtoul(buffer, NULL, 0);
438 	if (framing != BT_ISO_FRAMING_UNFRAMED &&
439 	    framing != BT_ISO_FRAMING_FRAMED) {
440 		printk("Invalid framing %llu", framing);
441 		return -EINVAL;
442 	}
443 
444 	return (int)framing;
445 }
446 
parse_bis_count_arg(void)447 static int parse_bis_count_arg(void)
448 {
449 	char buffer[4];
450 	size_t char_count;
451 	uint64_t bis_count;
452 
453 	printk("Set BIS count (current %u, default %u)\n",
454 	       big_create_param.num_bis, DEFAULT_BIS_COUNT);
455 
456 	char_count = get_chars(buffer, sizeof(buffer) - 1);
457 	if (char_count == 0) {
458 		return DEFAULT_BIS_COUNT;
459 	}
460 
461 	bis_count = strtoul(buffer, NULL, 0);
462 	if (bis_count > MAX(BT_ISO_MAX_GROUP_ISO_COUNT, CONFIG_BT_ISO_MAX_CHAN)) {
463 		printk("Invalid BIS count %llu", bis_count);
464 		return -EINVAL;
465 	}
466 
467 	return (int)bis_count;
468 }
469 
parse_args(void)470 static int parse_args(void)
471 {
472 	int rtn;
473 	int interval;
474 	int latency;
475 	int phy;
476 	int sdu;
477 	int packing;
478 	int framing;
479 	int bis_count;
480 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
481 	int num_subevents;
482 	int iso_interval;
483 	int burst_number;
484 	int max_pdu;
485 	int irc;
486 	int pto;
487 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
488 
489 	printk("Follow the prompts. Press enter to use default values.\n");
490 
491 	rtn = parse_rtn_arg();
492 	if (rtn < 0) {
493 		return -EINVAL;
494 	}
495 
496 	interval = parse_interval_arg();
497 	if (interval < 0) {
498 		return -EINVAL;
499 	}
500 
501 	latency = parse_latency_arg();
502 	if (latency < 0) {
503 		return -EINVAL;
504 	}
505 
506 	phy = parse_phy_arg();
507 	if (phy < 0) {
508 		return -EINVAL;
509 	}
510 
511 	sdu = parse_sdu_arg();
512 	if (sdu < 0) {
513 		return -EINVAL;
514 	}
515 
516 	packing = parse_packing_arg();
517 	if (packing < 0) {
518 		return -EINVAL;
519 	}
520 
521 	framing = parse_framing_arg();
522 	if (framing < 0) {
523 		return -EINVAL;
524 	}
525 
526 	bis_count = parse_bis_count_arg();
527 	if (bis_count < 0) {
528 		return -EINVAL;
529 	}
530 
531 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
532 	irc = parse_irc_arg();
533 	if (irc < 0) {
534 		return -EINVAL;
535 	}
536 
537 	pto = parse_pto_arg();
538 	if (pto < 0) {
539 		return -EINVAL;
540 	}
541 
542 	iso_interval = parse_iso_interval_arg();
543 	if (iso_interval < 0) {
544 		return -EINVAL;
545 	}
546 
547 	num_subevents = parse_nse_arg();
548 	if (num_subevents < 0) {
549 		return -EINVAL;
550 	}
551 
552 	max_pdu = parse_max_pdu_arg();
553 	if (max_pdu < 0) {
554 		return -EINVAL;
555 	}
556 
557 	burst_number = parse_bn_arg();
558 	if (burst_number < 0) {
559 		return -EINVAL;
560 	}
561 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
562 
563 	iso_tx_qos.rtn = rtn;
564 	iso_tx_qos.phy = phy;
565 	iso_tx_qos.sdu = sdu;
566 	big_create_param.interval = interval;
567 	big_create_param.latency = latency;
568 	big_create_param.packing = packing;
569 	big_create_param.framing = framing;
570 	big_create_param.num_bis = bis_count;
571 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
572 	bis_iso_qos.num_subevents = num_subevents;
573 	iso_tx_qos.max_pdu = max_pdu;
574 	iso_tx_qos.burst_number = burst_number;
575 	big_create_param.irc = irc;
576 	big_create_param.pto = pto;
577 	big_create_param.iso_interval = iso_interval;
578 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
579 
580 	return 0;
581 }
582 
iso_timer_timeout(struct k_work * work)583 static void iso_timer_timeout(struct k_work *work)
584 {
585 	int ret;
586 	struct net_buf *buf;
587 
588 	/* Reschedule as early as possible to reduce time skewing
589 	 * Use the ISO interval minus a few microseconds to keep the buffer
590 	 * full. This might occasionally skip a transmit, i.e. where the host
591 	 * calls `bt_iso_chan_send` but the controller only sending a single
592 	 * ISO packet.
593 	 */
594 	k_work_reschedule(&iso_send_work, K_USEC(big_create_param.interval - 100));
595 
596 	for (int i = 0; i < big_create_param.num_bis; i++) {
597 		buf = net_buf_alloc(&bis_tx_pool, K_NO_WAIT);
598 		if (buf == NULL) {
599 			LOG_ERR("Could not allocate buffer");
600 			return;
601 		}
602 
603 		net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
604 		net_buf_add_mem(buf, iso_data, iso_tx_qos.sdu);
605 		ret = bt_iso_chan_send(&bis_iso_chans[i], buf, seq_num);
606 		if (ret < 0) {
607 			LOG_ERR("Unable to broadcast data: %d", ret);
608 			net_buf_unref(buf);
609 			return;
610 		}
611 		iso_send_count++;
612 
613 		if ((iso_send_count % 100) == 0) {
614 			LOG_INF("Sent %u packets", iso_send_count);
615 		}
616 	}
617 
618 	seq_num++;
619 }
620 
calc_adv_interval(uint32_t sdu_interval_us)621 static uint16_t calc_adv_interval(uint32_t sdu_interval_us)
622 {
623 	/* Default to 6 times the SDU interval and then reduce until we reach a reasonable maximum
624 	 * advertising interval (BT_GAP_PER_ADV_SLOW_INT_MAX)
625 	 * sdu_interval_us can never be larger than 1048ms (BT_ISO_SDU_INTERVAL_MAX)
626 	 * so a multiple of it will always be possible to keep under BT_GAP_PER_ADV_SLOW_INT_MAX
627 	 * (1200ms)
628 	 */
629 
630 	/* Convert from microseconds to advertising interval units (0.625ms)*/
631 	const uint32_t interval = BT_GAP_US_TO_ADV_INTERVAL(sdu_interval_us);
632 	uint32_t adv_interval = interval * 6U;
633 
634 	/* Ensure that the adv interval is between BT_GAP_PER_ADV_FAST_INT_MIN_1 and
635 	 * BT_GAP_PER_ADV_SLOW_INT_MAX for the sake of interopability
636 	 */
637 	while (adv_interval < BT_GAP_PER_ADV_FAST_INT_MIN_1) {
638 		adv_interval += interval;
639 	}
640 
641 	while (adv_interval > BT_GAP_PER_ADV_SLOW_INT_MAX) {
642 		adv_interval -= interval;
643 	}
644 
645 	/* If we cannot convert back then it's not a lossless conversion */
646 	if (big_create_param.framing == BT_ISO_FRAMING_UNFRAMED &&
647 	    BT_GAP_ADV_INTERVAL_TO_US(interval) != sdu_interval_us) {
648 		LOG_INF("Advertising interval of 0x04%x is not a multiple of the advertising "
649 			"interval unit (0.625 ms) and may be subpar. Suggest to adjust SDU "
650 			"interval %u to be a multiple of 0.625 ms",
651 			adv_interval, sdu_interval_us);
652 	}
653 
654 	return adv_interval;
655 }
656 
create_big(struct bt_le_ext_adv ** adv,struct bt_iso_big ** big)657 static int create_big(struct bt_le_ext_adv **adv, struct bt_iso_big **big)
658 {
659 	/* Some controllers work best when Extended Advertising interval is a multiple
660 	 * of the ISO Interval minus 10 ms (max. advertising random delay). This is
661 	 * required to place the AUX_ADV_IND PDUs in a non-overlapping interval with the
662 	 * Broadcast ISO radio events.
663 	 */
664 	const uint16_t adv_interval = calc_adv_interval(big_create_param.interval);
665 	const uint16_t ext_adv_interval = adv_interval - BT_GAP_MS_TO_ADV_INTERVAL(10U);
666 	const struct bt_le_adv_param *ext_adv_param =
667 		BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV, ext_adv_interval, ext_adv_interval, NULL);
668 	const struct bt_le_per_adv_param *per_adv_param =
669 		BT_LE_PER_ADV_PARAM(adv_interval, adv_interval, BT_LE_PER_ADV_OPT_NONE);
670 	int err;
671 
672 	/* Create a non-connectable advertising set */
673 	LOG_INF("Creating Extended Advertising set");
674 	err = bt_le_ext_adv_create(ext_adv_param, NULL, adv);
675 	if (err != 0) {
676 		LOG_ERR("Failed to create advertising set (err %d)", err);
677 		return err;
678 	}
679 
680 	/* Set advertising data to have complete local name set */
681 	err = bt_le_ext_adv_set_data(*adv, ad, ARRAY_SIZE(ad), NULL, 0);
682 	if (err) {
683 		LOG_ERR("Failed to set advertising data (err %d)", err);
684 		return 0;
685 	}
686 
687 	LOG_INF("Setting Periodic Advertising parameters");
688 	/* Set periodic advertising parameters */
689 	err = bt_le_per_adv_set_param(*adv, per_adv_param);
690 	if (err != 0) {
691 		LOG_ERR("Failed to set periodic advertising parameters (err %d)",
692 			err);
693 		return err;
694 	}
695 
696 	/* Enable Periodic Advertising */
697 	LOG_INF("Starting Periodic Advertising");
698 	err = bt_le_per_adv_start(*adv);
699 	if (err != 0) {
700 		LOG_ERR("Failed to enable periodic advertising (err %d)", err);
701 		return err;
702 	}
703 
704 	/* Start extended advertising */
705 	LOG_INF("Starting Extended Advertising set");
706 	err = bt_le_ext_adv_start(*adv, BT_LE_EXT_ADV_START_DEFAULT);
707 	if (err != 0) {
708 		LOG_ERR("Failed to start extended advertising (err %d)", err);
709 		return err;
710 	}
711 
712 	/* Prepare BIG */
713 	for (int i = 0; i < ARRAY_SIZE(bis_iso_chans); i++) {
714 		bis_iso_chans[i].ops = &iso_ops;
715 		bis_iso_chans[i].qos = &bis_iso_qos;
716 		bis[i] = &bis_iso_chans[i];
717 	}
718 
719 	/* Create BIG */
720 	LOG_INF("Creating BIG");
721 	err = bt_iso_big_create(*adv, &big_create_param, big);
722 	if (err != 0) {
723 		LOG_ERR("Failed to create BIG (err %d)", err);
724 		return err;
725 	}
726 
727 	LOG_INF("Waiting for BIG complete");
728 	err = k_sem_take(&sem_big_complete, K_FOREVER);
729 	if (err != 0) {
730 		LOG_ERR("failed to take sem_big_complete (err %d)", err);
731 		return err;
732 	}
733 	LOG_INF("BIG created");
734 
735 	return 0;
736 }
737 
delete_big(struct bt_le_ext_adv ** adv,struct bt_iso_big ** big)738 static int delete_big(struct bt_le_ext_adv **adv, struct bt_iso_big **big)
739 {
740 	int err;
741 
742 	err = bt_iso_big_terminate(*big);
743 	if (err != 0) {
744 		LOG_ERR("Failed to terminate BIG (err %d)", err);
745 		return err;
746 	}
747 	*big = NULL;
748 
749 	err = bt_le_per_adv_stop(*adv);
750 	if (err != 0) {
751 		LOG_ERR("Failed to stop periodic advertising (err %d)", err);
752 		return err;
753 	}
754 
755 	err = bt_le_ext_adv_stop(*adv);
756 	if (err != 0) {
757 		LOG_ERR("Failed to stop advertising (err %d)", err);
758 		return err;
759 	}
760 
761 	err = bt_le_ext_adv_delete(*adv);
762 	if (err != 0) {
763 		LOG_ERR("Failed to delete advertiser (err %d)", err);
764 		return err;
765 	}
766 
767 	*adv = NULL;
768 
769 	return 0;
770 }
771 
reset_sems(void)772 static void reset_sems(void)
773 {
774 	(void)k_sem_reset(&sem_big_complete);
775 	(void)k_sem_reset(&sem_big_term);
776 }
777 
test_run_broadcaster(void)778 int test_run_broadcaster(void)
779 {
780 	struct bt_le_ext_adv *adv;
781 	struct bt_iso_big *big;
782 	int err;
783 	char c;
784 	static bool data_initialized;
785 
786 	reset_sems();
787 
788 	printk("Change settings (y/N)? (Current settings: rtn=%u, interval=%u, "
789 	       "latency=%u, phy=%u, sdu=%u, packing=%u, framing=%u, "
790 	       "bis_count=%u)\n", iso_tx_qos.rtn, big_create_param.interval,
791 	       big_create_param.latency, iso_tx_qos.phy, iso_tx_qos.sdu,
792 	       big_create_param.packing, big_create_param.framing,
793 	       big_create_param.num_bis);
794 
795 	c = tolower(console_getchar());
796 	if (c == 'y') {
797 		err = parse_args();
798 		if (err != 0) {
799 			LOG_ERR("Could not parse args: %d", err);
800 			return err;
801 		}
802 
803 		printk("New settings: rtn=%u, interval=%u, latency=%u, "
804 		       "phy=%u, sdu=%u, packing=%u, framing=%u, bis_count=%u\n",
805 		       iso_tx_qos.rtn, big_create_param.interval,
806 		       big_create_param.latency, iso_tx_qos.phy, iso_tx_qos.sdu,
807 		       big_create_param.packing, big_create_param.framing,
808 		       big_create_param.num_bis);
809 	}
810 
811 	err = create_big(&adv, &big);
812 	if (err) {
813 		LOG_ERR("Could not create BIG: %d", err);
814 		return err;
815 	}
816 
817 	iso_send_count = 0;
818 
819 	if (!data_initialized) {
820 		/* Init data */
821 		for (int i = 0; i < iso_tx_qos.sdu; i++) {
822 			iso_data[i] = (uint8_t)i;
823 		}
824 
825 		data_initialized = true;
826 	}
827 
828 	k_work_init_delayable(&iso_send_work, iso_timer_timeout);
829 	k_work_schedule(&iso_send_work, K_MSEC(0));
830 
831 	while (true) {
832 		printk("Press 'q' to end the broadcast\n");
833 		c = tolower(console_getchar());
834 		if (c == 'q') {
835 			break;
836 		}
837 	}
838 
839 	LOG_INF("Ending broadcast");
840 	(void)k_work_cancel_delayable(&iso_send_work);
841 
842 	err = delete_big(&adv, &big);
843 	if (err) {
844 		LOG_ERR("Could not delete BIG: %d", err);
845 		return err;
846 	}
847 
848 	return 0;
849 }
850