1 /** @file
2  *  @brief Bluetooth Audio shell
3  *
4  */
5 
6 /*
7  * Copyright (c) 2020 Intel Corporation
8  * Copyright (c) 2021 Nordic Semiconductor ASA
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #include <stddef.h>
14 #include <stdlib.h>
15 #include <ctype.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/shell/shell.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/sys/util.h>
20 
21 #include <zephyr/bluetooth/hci.h>
22 #include <zephyr/bluetooth/bluetooth.h>
23 #include <zephyr/bluetooth/conn.h>
24 #include <zephyr/bluetooth/iso.h>
25 
26 #include "host/shell/bt.h"
27 #include "common/bt_shell_private.h"
28 
29 #if defined(CONFIG_BT_ISO_TX)
30 #define DEFAULT_IO_QOS                                                                             \
31 	{                                                                                          \
32 		.sdu = 40u, .phy = BT_GAP_LE_PHY_2M, .rtn = 2u,                                    \
33 	}
34 
35 #define TX_BUF_TIMEOUT K_SECONDS(1)
36 
37 static struct bt_iso_chan_io_qos iso_tx_qos = DEFAULT_IO_QOS;
38 static uint32_t cis_sn_last;
39 static uint32_t bis_sn_last;
40 static int64_t cis_sn_last_updated_ticks;
41 static int64_t bis_sn_last_updated_ticks;
42 
43 /**
44  * @brief Get the next sequence number based on the last used values
45  *
46  * @param last_sn     The last sequence number sent.
47  * @param last_ticks  The uptime ticks since the last sequence number increment.
48  * @param interval_us The SDU interval in microseconds.
49  *
50  * @return The next sequence number to use
51  */
get_next_sn(uint32_t last_sn,int64_t * last_ticks,uint32_t interval_us)52 static uint32_t get_next_sn(uint32_t last_sn, int64_t *last_ticks,
53 			    uint32_t interval_us)
54 {
55 	int64_t uptime_ticks, delta_ticks;
56 	uint64_t delta_us;
57 	uint64_t sn_incr;
58 	uint64_t next_sn;
59 
60 	/* Note: This does not handle wrapping of ticks when they go above
61 	 * 2^(62-1)
62 	 */
63 	uptime_ticks = k_uptime_ticks();
64 	delta_ticks = uptime_ticks - *last_ticks;
65 	*last_ticks = uptime_ticks;
66 
67 	delta_us = k_ticks_to_us_near64((uint64_t)delta_ticks);
68 	sn_incr = delta_us / interval_us;
69 	next_sn = (sn_incr + last_sn);
70 
71 	return (uint32_t)next_sn;
72 }
73 #endif /* CONFIG_BT_ISO_TX */
74 
75 #if defined(CONFIG_BT_ISO_RX)
iso_recv(struct bt_iso_chan * chan,const struct bt_iso_recv_info * info,struct net_buf * buf)76 static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info,
77 		     struct net_buf *buf)
78 {
79 	if (info->flags & BT_ISO_FLAGS_VALID) {
80 		bt_shell_print("Incoming data channel %p len %u, seq: %d, ts: %d",
81 			       chan, buf->len, info->seq_num, info->ts);
82 	}
83 }
84 #endif /* CONFIG_BT_ISO_RX */
85 
iso_connected(struct bt_iso_chan * chan)86 static void iso_connected(struct bt_iso_chan *chan)
87 {
88 	struct bt_iso_info iso_info;
89 	int err;
90 
91 	bt_shell_print("ISO Channel %p connected", chan);
92 
93 	err = bt_iso_chan_get_info(chan, &iso_info);
94 	if (err != 0) {
95 		printk("Failed to get ISO info: %d", err);
96 		return;
97 	}
98 
99 #if defined(CONFIG_BT_ISO_TX)
100 	if (iso_info.type == BT_ISO_CHAN_TYPE_CONNECTED) {
101 		cis_sn_last = 0U;
102 		cis_sn_last_updated_ticks = k_uptime_ticks();
103 	} else {
104 		bis_sn_last = 0U;
105 		bis_sn_last_updated_ticks = k_uptime_ticks();
106 	}
107 #endif /* CONFIG_BT_ISO_TX */
108 }
109 
iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)110 static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
111 {
112 	bt_shell_print("ISO Channel %p disconnected with reason 0x%02x",
113 		       chan, reason);
114 }
115 
116 static struct bt_iso_chan_ops iso_ops = {
117 #if defined(CONFIG_BT_ISO_RX)
118 	.recv = iso_recv,
119 #endif /* CONFIG_BT_ISO_RX */
120 	.connected = iso_connected,
121 	.disconnected = iso_disconnected,
122 };
123 
124 #if defined(CONFIG_BT_ISO_UNICAST)
125 static uint32_t cis_sdu_interval_us;
126 
127 static struct bt_iso_chan_io_qos iso_rx_qos = DEFAULT_IO_QOS;
128 
129 static struct bt_iso_chan_qos cis_iso_qos = {
130 	.tx = &iso_tx_qos,
131 	.rx = &iso_rx_qos,
132 };
133 
134 #define CIS_ISO_CHAN_COUNT 1
135 
136 struct bt_iso_chan iso_chan = {
137 	.ops = &iso_ops,
138 	.qos = &cis_iso_qos,
139 };
140 
141 NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
142 			  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
143 
144 #if defined(CONFIG_BT_ISO_CENTRAL)
145 static struct bt_iso_cig *cig;
146 
parse_interval(const struct shell * sh,const char * interval_str)147 static long parse_interval(const struct shell *sh, const char *interval_str)
148 {
149 	unsigned long interval;
150 	int err;
151 
152 	err = 0;
153 	interval = shell_strtoul(interval_str, 0, &err);
154 	if (err != 0) {
155 		shell_error(sh, "Could not parse interval: %d", err);
156 
157 		return -ENOEXEC;
158 	}
159 
160 	if (!IN_RANGE(interval,
161 		      BT_ISO_SDU_INTERVAL_MIN,
162 		      BT_ISO_SDU_INTERVAL_MAX)) {
163 		shell_error(sh, "Invalid interval %lu", interval);
164 
165 		return -ENOEXEC;
166 	}
167 
168 	return interval;
169 }
170 
parse_latency(const struct shell * sh,const char * latency_str)171 static long parse_latency(const struct shell *sh, const char *latency_str)
172 {
173 	unsigned long latency;
174 	int err;
175 
176 	err = 0;
177 	latency = shell_strtoul(latency_str, 0, &err);
178 	if (err != 0) {
179 		shell_error(sh, "Could not parse latency: %d", err);
180 
181 		return -ENOEXEC;
182 	}
183 
184 	if (!IN_RANGE(latency,
185 		      BT_ISO_LATENCY_MIN,
186 		      BT_ISO_LATENCY_MAX)) {
187 		shell_error(sh, "Invalid latency %lu", latency);
188 
189 		return -ENOEXEC;
190 	}
191 
192 	return latency;
193 }
194 
cmd_cig_create(const struct shell * sh,size_t argc,char * argv[])195 static int cmd_cig_create(const struct shell *sh, size_t argc, char *argv[])
196 {
197 	int err;
198 	struct bt_iso_cig_param param = {0};
199 	struct bt_iso_chan *chans[CIS_ISO_CHAN_COUNT];
200 
201 	if (cig != NULL) {
202 		shell_error(sh, "Already created");
203 		return -ENOEXEC;
204 	}
205 
206 	chans[0] = &iso_chan;
207 
208 	if (argc > 1) {
209 		if (!strcmp("tx", argv[1])) {
210 			chans[0]->qos->tx = &iso_tx_qos;
211 			chans[0]->qos->rx = NULL;
212 		} else if (!strcmp("rx", argv[1])) {
213 			chans[0]->qos->tx = NULL;
214 			chans[0]->qos->rx = &iso_rx_qos;
215 		} else if (!strcmp("txrx", argv[1])) {
216 			chans[0]->qos->tx = &iso_tx_qos;
217 			chans[0]->qos->rx = &iso_rx_qos;
218 		}
219 	}
220 
221 	err = 0;
222 	if (argc > 2) {
223 		long interval;
224 
225 		interval = shell_strtoul(argv[2], 0, &err);
226 		interval = parse_interval(sh, argv[2]);
227 		if (interval < 0) {
228 			return interval;
229 		}
230 
231 		param.c_to_p_interval = interval;
232 	} else {
233 		param.c_to_p_interval = 10000;
234 	}
235 
236 	if (argc > 3) {
237 		long interval;
238 
239 		interval = parse_interval(sh, argv[3]);
240 		if (interval < 0) {
241 			return interval;
242 		}
243 
244 		param.p_to_c_interval = interval;
245 	} else {
246 		param.p_to_c_interval = param.c_to_p_interval;
247 	}
248 
249 	/* cis_sdu_interval_us is used to increase the sequence number.
250 	 * cig_create can be called before an ACL is created, so the role
251 	 * information may not be available.
252 	 * Since we are central however we can safely set the cis_sdu_interval
253 	 * to the Central to Peer interval
254 	 */
255 	cis_sdu_interval_us = param.c_to_p_interval;
256 
257 	if (argc > 4) {
258 		unsigned long packing;
259 
260 		packing = shell_strtoul(argv[4], 0, &err);
261 		if (err != 0) {
262 			shell_error(sh, "Could not parse packing: %d", err);
263 
264 			return -ENOEXEC;
265 		}
266 
267 		if (packing != BT_ISO_PACKING_SEQUENTIAL && packing != BT_ISO_PACKING_INTERLEAVED) {
268 			shell_error(sh, "Invalid packing %lu", packing);
269 
270 			return -ENOEXEC;
271 		}
272 
273 		param.packing = packing;
274 	} else {
275 		param.packing = 0;
276 	}
277 
278 	if (argc > 5) {
279 		unsigned long framing;
280 
281 		framing = shell_strtoul(argv[5], 0, &err);
282 		if (err != 0) {
283 			shell_error(sh, "Could not parse framing: %d", err);
284 
285 			return -ENOEXEC;
286 		}
287 
288 		if (framing != BT_ISO_FRAMING_UNFRAMED && framing != BT_ISO_FRAMING_FRAMED) {
289 			shell_error(sh, "Invalid framing %lu", framing);
290 
291 			return -ENOEXEC;
292 		}
293 
294 		param.framing = framing;
295 	} else {
296 		param.framing = 0;
297 	}
298 
299 	if (argc > 6) {
300 		long latency;
301 
302 		latency = parse_latency(sh, argv[6]);
303 
304 		if (latency < 0) {
305 			return latency;
306 		}
307 
308 		param.c_to_p_latency = latency;
309 	} else {
310 		param.c_to_p_latency = 10;
311 	}
312 
313 	if (argc > 7) {
314 		long latency;
315 
316 		latency = parse_latency(sh, argv[7]);
317 
318 		if (latency < 0) {
319 			return latency;
320 		}
321 
322 		param.p_to_c_latency = latency;
323 	} else {
324 		param.p_to_c_latency = param.c_to_p_latency;
325 	}
326 
327 	if (argc > 7) {
328 		unsigned long sdu;
329 
330 		sdu = shell_strtoul(argv[7], 0, &err);
331 		if (err != 0) {
332 			shell_error(sh, "Could not parse sdu: %d", err);
333 
334 			return -ENOEXEC;
335 		}
336 
337 		if (sdu > BT_ISO_MAX_SDU) {
338 			shell_error(sh, "Invalid sdu %lu", sdu);
339 
340 			return -ENOEXEC;
341 		}
342 
343 		if (chans[0]->qos->tx) {
344 			chans[0]->qos->tx->sdu = sdu;
345 		}
346 
347 		if (chans[0]->qos->rx) {
348 			chans[0]->qos->rx->sdu = sdu;
349 		}
350 	}
351 
352 	if (argc > 8) {
353 		unsigned long phy;
354 
355 		phy = shell_strtoul(argv[8], 0, &err);
356 		if (err != 0) {
357 			shell_error(sh, "Could not parse phy: %d", err);
358 
359 			return -ENOEXEC;
360 		}
361 
362 		if (phy != BT_GAP_LE_PHY_1M &&
363 		    phy != BT_GAP_LE_PHY_2M &&
364 		    phy != BT_GAP_LE_PHY_CODED) {
365 			shell_error(sh, "Invalid phy %lu", phy);
366 
367 			return -ENOEXEC;
368 		}
369 
370 		if (chans[0]->qos->tx) {
371 			chans[0]->qos->tx->phy = phy;
372 		}
373 
374 		if (chans[0]->qos->rx) {
375 			chans[0]->qos->rx->phy = phy;
376 		}
377 	}
378 
379 	if (argc > 9) {
380 		unsigned long rtn;
381 
382 		rtn = shell_strtoul(argv[9], 0, &err);
383 		if (err != 0) {
384 			shell_error(sh, "Could not parse rtn: %d", err);
385 
386 			return -ENOEXEC;
387 		}
388 
389 		if (rtn > BT_ISO_CONNECTED_RTN_MAX) {
390 			shell_error(sh, "Invalid rtn %lu", rtn);
391 
392 			return -ENOEXEC;
393 		}
394 
395 		if (chans[0]->qos->tx) {
396 			chans[0]->qos->tx->rtn = rtn;
397 		}
398 
399 		if (chans[0]->qos->rx) {
400 			chans[0]->qos->rx->rtn = rtn;
401 		}
402 	}
403 
404 	param.sca = BT_GAP_SCA_UNKNOWN;
405 	param.cis_channels = chans;
406 	param.num_cis = ARRAY_SIZE(chans);
407 
408 	err = bt_iso_cig_create(&param, &cig);
409 	if (err) {
410 		shell_error(sh, "Unable to create CIG (err %d)", err);
411 		return 0;
412 	}
413 
414 	shell_print(sh, "CIG created");
415 
416 	return 0;
417 }
418 
cmd_cig_term(const struct shell * sh,size_t argc,char * argv[])419 static int cmd_cig_term(const struct shell *sh, size_t argc, char *argv[])
420 {
421 	int err;
422 
423 	if (cig == NULL) {
424 		shell_error(sh, "CIG not created");
425 		return -ENOEXEC;
426 	}
427 
428 	err = bt_iso_cig_terminate(cig);
429 	if (err) {
430 		shell_error(sh, "Unable to terminate CIG (err %d)", err);
431 		return 0;
432 	}
433 
434 	shell_print(sh, "CIG terminated");
435 	cig = NULL;
436 
437 	return 0;
438 }
439 
cmd_connect(const struct shell * sh,size_t argc,char * argv[])440 static int cmd_connect(const struct shell *sh, size_t argc, char *argv[])
441 {
442 	struct bt_iso_connect_param connect_param = {
443 		.acl = default_conn,
444 		.iso_chan = &iso_chan
445 	};
446 	int err;
447 
448 	if (iso_chan.iso == NULL) {
449 		shell_error(sh, "ISO channel not initialized in a CIG");
450 		return 0;
451 	}
452 
453 #if defined(CONFIG_BT_SMP)
454 	if (argc > 1) {
455 		iso_chan.required_sec_level = *argv[1] - '0';
456 	}
457 #endif /* CONFIG_BT_SMP */
458 
459 	err = bt_iso_chan_connect(&connect_param, 1);
460 	if (err) {
461 		shell_error(sh, "Unable to connect (err %d)", err);
462 		return 0;
463 	}
464 
465 	shell_print(sh, "ISO Connect pending...");
466 
467 	return 0;
468 }
469 #endif /* CONFIG_BT_ISO_CENTRAL */
470 
471 #if defined(CONFIG_BT_ISO_PERIPHERAL)
472 
iso_accept(const struct bt_iso_accept_info * info,struct bt_iso_chan ** chan)473 static int iso_accept(const struct bt_iso_accept_info *info,
474 		      struct bt_iso_chan **chan)
475 {
476 	bt_shell_print("Incoming request from %p with CIG ID 0x%02X and CIS ID 0x%02X",
477 		       info->acl, info->cig_id, info->cis_id);
478 
479 	if (iso_chan.iso) {
480 		bt_shell_print("No channels available");
481 		return -ENOMEM;
482 	}
483 
484 	*chan = &iso_chan;
485 
486 	/* As the peripheral host we do not know the SDU interval, and thus we
487 	 * cannot find the proper interval of incrementing the packet
488 	 * sequence number (PSN). The only way to ensure that we correctly
489 	 * increment the PSN, is by incrementing once per the minimum SDU
490 	 * interval. This should be okay as the spec does not specify how much
491 	 * the PSN may be incremented, and it is thus OK for us to increment
492 	 * it faster than the SDU interval.
493 	 */
494 	cis_sdu_interval_us = BT_ISO_SDU_INTERVAL_MIN;
495 
496 	return 0;
497 }
498 
499 struct bt_iso_server iso_server = {
500 #if defined(CONFIG_BT_SMP)
501 	.sec_level = BT_SECURITY_L1,
502 #endif /* CONFIG_BT_SMP */
503 	.accept = iso_accept,
504 };
505 
cmd_listen(const struct shell * sh,size_t argc,char * argv[])506 static int cmd_listen(const struct shell *sh, size_t argc, char *argv[])
507 {
508 	int err;
509 	static struct bt_iso_chan_io_qos *tx_qos, *rx_qos;
510 
511 	if (!strcmp("tx", argv[1])) {
512 		tx_qos = &iso_tx_qos;
513 		rx_qos = NULL;
514 	} else if (!strcmp("rx", argv[1])) {
515 		tx_qos = NULL;
516 		rx_qos = &iso_rx_qos;
517 	} else if (!strcmp("txrx", argv[1])) {
518 		tx_qos = &iso_tx_qos;
519 		rx_qos = &iso_rx_qos;
520 	} else {
521 		shell_error(sh, "Invalid argument - use tx, rx or txrx");
522 		return -ENOEXEC;
523 	}
524 
525 #if defined(CONFIG_BT_SMP)
526 	if (argc > 2) {
527 		iso_server.sec_level = *argv[2] - '0';
528 	}
529 #endif /* CONFIG_BT_SMP */
530 
531 	err = bt_iso_server_register(&iso_server);
532 	if (err) {
533 		shell_error(sh, "Unable to register ISO cap (err %d)", err);
534 		return err;
535 	}
536 
537 	/* Setup peripheral iso data direction only if register is success */
538 	iso_chan.qos->tx = tx_qos;
539 	iso_chan.qos->rx = rx_qos;
540 	return err;
541 }
542 #endif /* CONFIG_BT_ISO_PERIPHERAL */
543 
cmd_send(const struct shell * sh,size_t argc,char * argv[])544 static int cmd_send(const struct shell *sh, size_t argc, char *argv[])
545 {
546 	static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU] = {
547 		[0 ... (CONFIG_BT_ISO_TX_MTU - 1)] = 0xff
548 	};
549 	unsigned long count = 1;
550 	struct net_buf *buf;
551 	int ret = 0;
552 	int len;
553 
554 	if (argc > 1) {
555 		count = shell_strtoul(argv[1], 0, &ret);
556 		if (ret != 0) {
557 			shell_error(sh, "Could not parse count: %d", ret);
558 
559 			return -ENOEXEC;
560 		}
561 
562 		if (count < 1) {
563 			shell_error(sh, "Cannot send 0 times");
564 
565 			return -ENOEXEC;
566 		}
567 	}
568 
569 	if (!iso_chan.iso) {
570 		shell_error(sh, "Not bound");
571 		return 0;
572 	}
573 
574 	if (!iso_chan.qos->tx) {
575 		shell_error(sh, "Transmission QoS disabled");
576 		return -ENOEXEC;
577 	}
578 
579 	len = MIN(iso_chan.qos->tx->sdu, CONFIG_BT_ISO_TX_MTU);
580 	cis_sn_last = get_next_sn(cis_sn_last, &cis_sn_last_updated_ticks,
581 				  cis_sdu_interval_us);
582 
583 	while (count--) {
584 		buf = net_buf_alloc(&tx_pool, TX_BUF_TIMEOUT);
585 		if (buf == NULL) {
586 			shell_error(sh, "Failed to get buffer...");
587 			return -ENOEXEC;
588 		}
589 
590 		net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
591 
592 		net_buf_add_mem(buf, buf_data, len);
593 		shell_info(sh, "send: %d bytes of data with PSN %u", len, cis_sn_last);
594 		ret = bt_iso_chan_send(&iso_chan, buf, cis_sn_last);
595 		if (ret < 0) {
596 			shell_print(sh, "Unable to send: %d", -ret);
597 			net_buf_unref(buf);
598 			return -ENOEXEC;
599 		}
600 	}
601 
602 	shell_print(sh, "ISO sending...");
603 
604 	return 0;
605 }
606 
cmd_disconnect(const struct shell * sh,size_t argc,char * argv[])607 static int cmd_disconnect(const struct shell *sh, size_t argc,
608 			  char *argv[])
609 {
610 	int err;
611 
612 	err = bt_iso_chan_disconnect(&iso_chan);
613 	if (err) {
614 		shell_error(sh, "Unable to disconnect (err %d)", err);
615 		return 0;
616 	}
617 
618 	shell_print(sh, "ISO Disconnect pending...");
619 
620 	return 0;
621 }
622 
cmd_tx_sync_read_cis(const struct shell * sh,size_t argc,char * argv[])623 static int cmd_tx_sync_read_cis(const struct shell *sh, size_t argc, char *argv[])
624 {
625 	struct bt_iso_tx_info tx_info;
626 	int err;
627 
628 	if (!iso_chan.iso) {
629 		shell_error(sh, "Not bound");
630 		return 0;
631 	}
632 
633 	err = bt_iso_chan_get_tx_sync(&iso_chan, &tx_info);
634 	if (err) {
635 		shell_error(sh, "Unable to read sync info (err %d)", err);
636 		return 0;
637 	}
638 
639 	shell_print(sh, "TX sync info:\n\tTimestamp=%u\n\tOffset=%u\n\tSequence number=%u",
640 		    tx_info.ts, tx_info.offset, tx_info.seq_num);
641 
642 	return 0;
643 }
644 #endif /* CONFIG_BT_ISO_UNICAST */
645 
646 #if defined(CONFIG_BT_ISO_BROADCAST)
647 #define BIS_ISO_CHAN_COUNT 1
648 static struct bt_iso_big *big;
649 
650 static struct bt_iso_chan_qos bis_iso_qos;
651 
652 static struct bt_iso_chan bis_iso_chan = {
653 	.ops = &iso_ops,
654 	.qos = &bis_iso_qos,
655 };
656 
657 static struct bt_iso_chan *bis_channels[BIS_ISO_CHAN_COUNT] = { &bis_iso_chan };
658 
659 #if defined(CONFIG_BT_ISO_BROADCASTER)
660 static uint32_t bis_sdu_interval_us;
661 
662 NET_BUF_POOL_FIXED_DEFINE(bis_tx_pool, BIS_ISO_CHAN_COUNT,
663 			  BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
664 			  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
665 
cmd_broadcast(const struct shell * sh,size_t argc,char * argv[])666 static int cmd_broadcast(const struct shell *sh, size_t argc, char *argv[])
667 {
668 	static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU] = {
669 		[0 ... (CONFIG_BT_ISO_TX_MTU - 1)] = 0xff
670 	};
671 	unsigned long count = 1;
672 	struct net_buf *buf;
673 	int ret = 0;
674 	int len;
675 
676 	if (argc > 1) {
677 		count = shell_strtoul(argv[1], 0, &ret);
678 		if (ret != 0) {
679 			shell_error(sh, "Could not parse count: %d", ret);
680 
681 			return -ENOEXEC;
682 		}
683 
684 		if (count < 1) {
685 			shell_error(sh, "Cannot send 0 times");
686 
687 			return -ENOEXEC;
688 		}
689 	}
690 
691 	if (!bis_iso_chan.iso) {
692 		shell_error(sh, "BIG not created");
693 		return -ENOEXEC;
694 	}
695 
696 	if (!bis_iso_qos.tx) {
697 		shell_error(sh, "BIG not setup as broadcaster");
698 		return -ENOEXEC;
699 	}
700 
701 	len = MIN(bis_iso_chan.qos->tx->sdu, CONFIG_BT_ISO_TX_MTU);
702 	bis_sn_last = get_next_sn(bis_sn_last, &bis_sn_last_updated_ticks,
703 				  bis_sdu_interval_us);
704 
705 	while (count--) {
706 		buf = net_buf_alloc(&bis_tx_pool, TX_BUF_TIMEOUT);
707 		if (buf == NULL) {
708 			shell_error(sh, "Failed to get buffer...");
709 			return -ENOEXEC;
710 		}
711 
712 		net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
713 
714 		net_buf_add_mem(buf, buf_data, len);
715 		shell_info(sh, "send: %d bytes of data with PSN %u", len, bis_sn_last);
716 		ret = bt_iso_chan_send(&bis_iso_chan, buf, bis_sn_last);
717 		if (ret < 0) {
718 			shell_print(sh, "Unable to broadcast: %d", -ret);
719 			net_buf_unref(buf);
720 			return -ENOEXEC;
721 		}
722 	}
723 
724 	shell_print(sh, "ISO broadcasting...");
725 
726 	return 0;
727 }
728 
cmd_big_create(const struct shell * sh,size_t argc,char * argv[])729 static int cmd_big_create(const struct shell *sh, size_t argc, char *argv[])
730 {
731 	int err;
732 	struct bt_iso_big_create_param param = {0};
733 	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
734 
735 	if (!adv) {
736 		shell_error(sh, "No (periodic) advertising set selected");
737 		return -ENOEXEC;
738 	}
739 
740 	/* TODO: Allow setting QOS from shell */
741 	bis_iso_qos.tx = &iso_tx_qos;
742 	bis_iso_qos.tx->phy = BT_GAP_LE_PHY_2M; /* 2 MBit */
743 	bis_iso_qos.tx->rtn = 2;
744 	bis_iso_qos.tx->sdu = CONFIG_BT_ISO_TX_MTU;
745 
746 	bis_sdu_interval_us = param.interval = 10000;      /* us */
747 	param.latency = 20;          /* ms */
748 	param.bis_channels = bis_channels;
749 	param.num_bis = BIS_ISO_CHAN_COUNT;
750 	param.encryption = false;
751 	param.packing = BT_ISO_PACKING_SEQUENTIAL;
752 	param.framing = BT_ISO_FRAMING_UNFRAMED;
753 
754 	if (argc > 1) {
755 		if (!strcmp(argv[1], "enc")) {
756 			uint8_t bcode_len = hex2bin(argv[1], strlen(argv[1]), param.bcode,
757 						    sizeof(param.bcode));
758 			if (!bcode_len || bcode_len != sizeof(param.bcode)) {
759 				shell_error(sh, "Invalid Broadcast Code Length");
760 				return -ENOEXEC;
761 			}
762 			param.encryption = true;
763 		} else {
764 			shell_help(sh);
765 			return SHELL_CMD_HELP_PRINTED;
766 		}
767 	} else {
768 		memset(param.bcode, 0, sizeof(param.bcode));
769 	}
770 
771 	err = bt_iso_big_create(adv, &param, &big);
772 	if (err) {
773 		shell_error(sh, "Unable to create BIG (err %d)", err);
774 		return 0;
775 	}
776 
777 	shell_print(sh, "BIG created");
778 
779 	return 0;
780 }
781 
cmd_tx_sync_read_bis(const struct shell * sh,size_t argc,char * argv[])782 static int cmd_tx_sync_read_bis(const struct shell *sh, size_t argc, char *argv[])
783 {
784 	struct bt_iso_tx_info tx_info;
785 	int err;
786 
787 	if (!bis_iso_chan.iso) {
788 		shell_error(sh, "BIG not created");
789 		return -ENOEXEC;
790 	}
791 
792 	err = bt_iso_chan_get_tx_sync(&bis_iso_chan, &tx_info);
793 	if (err) {
794 		shell_error(sh, "Unable to read sync info (err %d)", err);
795 		return 0;
796 	}
797 
798 	shell_print(sh, "TX sync info:\n\tTimestamp=%u\n\tOffset=%u\n\tSequence number=%u",
799 		    tx_info.ts, tx_info.offset, tx_info.seq_num);
800 
801 	return 0;
802 }
803 #endif /* CONFIG_BT_ISO_BROADCASTER */
804 
805 #if defined(CONFIG_BT_ISO_SYNC_RECEIVER)
cmd_big_sync(const struct shell * sh,size_t argc,char * argv[])806 static int cmd_big_sync(const struct shell *sh, size_t argc, char *argv[])
807 {
808 	int err;
809 	/* TODO: Add support to select which PA sync to BIG sync to */
810 	struct bt_le_per_adv_sync *pa_sync = per_adv_syncs[0];
811 	struct bt_iso_big_sync_param param;
812 	unsigned long bis_bitfield;
813 
814 	if (!pa_sync) {
815 		shell_error(sh, "No PA sync selected");
816 		return -ENOEXEC;
817 	}
818 
819 	err = 0;
820 	bis_bitfield = shell_strtoul(argv[1], 0, &err);
821 	if (err != 0) {
822 		shell_error(sh, "Could not parse bis_bitfield: %d", err);
823 
824 		return -ENOEXEC;
825 	}
826 
827 	if (bis_bitfield == 0U || bis_bitfield > BIT_MASK(BT_ISO_BIS_INDEX_MAX)) {
828 		shell_error(sh, "Invalid bis_bitfield: %lu", bis_bitfield);
829 
830 		return -ENOEXEC;
831 	}
832 
833 	bis_iso_qos.tx = NULL;
834 	bis_iso_qos.rx = &iso_rx_qos;
835 
836 	param.bis_channels = bis_channels;
837 	param.num_bis = BIS_ISO_CHAN_COUNT;
838 	param.encryption = false;
839 	param.bis_bitfield = bis_bitfield;
840 	param.mse = 0;
841 	param.sync_timeout = 0xFF;
842 
843 	for (size_t i = 2U; i < argc; i++) {
844 		if (!strcmp(argv[i], "mse")) {
845 			unsigned long mse;
846 
847 			i++;
848 			if (i == argc) {
849 				shell_help(sh);
850 				return SHELL_CMD_HELP_PRINTED;
851 			}
852 
853 			mse = shell_strtoul(argv[i], 0, &err);
854 			if (err != 0) {
855 				shell_error(sh, "Could not parse mse: %d", err);
856 
857 				return -ENOEXEC;
858 			}
859 
860 			if (mse != BT_ISO_SYNC_MSE_ANY &&
861 			    !IN_RANGE(mse, BT_ISO_SYNC_MSE_MIN, BT_ISO_SYNC_MSE_MAX)) {
862 				shell_error(sh, "Invalid mse %lu", mse);
863 
864 				return -ENOEXEC;
865 			}
866 
867 			param.mse = mse;
868 		} else if (!strcmp(argv[i], "timeout")) {
869 			unsigned long sync_timeout;
870 
871 			i++;
872 			if (i == argc) {
873 				shell_help(sh);
874 				return SHELL_CMD_HELP_PRINTED;
875 			}
876 
877 			sync_timeout = shell_strtoul(argv[i], 0, &err);
878 			if (err != 0) {
879 				shell_error(sh, "Could not parse sync_timeout: %d", err);
880 
881 				return -ENOEXEC;
882 			}
883 
884 			if (!IN_RANGE(sync_timeout,
885 				      BT_ISO_SYNC_TIMEOUT_MIN,
886 				      BT_ISO_SYNC_TIMEOUT_MAX)) {
887 				shell_error(sh, "Invalid sync_timeout %lu", sync_timeout);
888 
889 				return -ENOEXEC;
890 			}
891 
892 			param.sync_timeout = sync_timeout;
893 		} else if (!strcmp(argv[i], "enc")) {
894 			size_t bcode_len;
895 
896 			i++;
897 			if (i == argc) {
898 				shell_help(sh);
899 				return SHELL_CMD_HELP_PRINTED;
900 			}
901 
902 			memset(param.bcode, 0, sizeof(param.bcode));
903 			bcode_len = hex2bin(argv[i], strlen(argv[i]), param.bcode,
904 					    sizeof(param.bcode));
905 
906 			if (bcode_len == 0) {
907 				shell_error(sh, "Invalid Broadcast Code");
908 
909 				return -ENOEXEC;
910 			}
911 
912 			param.encryption = true;
913 		} else {
914 			shell_help(sh);
915 			return SHELL_CMD_HELP_PRINTED;
916 		}
917 	}
918 
919 	err = bt_iso_big_sync(pa_sync, &param, &big);
920 	if (err) {
921 		shell_error(sh, "Unable to sync to BIG (err %d)", err);
922 		return 0;
923 	}
924 
925 	shell_print(sh, "BIG syncing");
926 
927 	return 0;
928 }
929 #endif /* CONFIG_BT_ISO_SYNC_RECEIVER */
930 
cmd_big_term(const struct shell * sh,size_t argc,char * argv[])931 static int cmd_big_term(const struct shell *sh, size_t argc, char *argv[])
932 {
933 	int err;
934 
935 	err = bt_iso_big_terminate(big);
936 	if (err) {
937 		shell_error(sh, "Unable to terminate BIG (err %d)", err);
938 		return 0;
939 	}
940 
941 	shell_print(sh, "BIG terminated");
942 
943 	return 0;
944 }
945 #endif /* CONFIG_BT_ISO_BROADCAST*/
946 
947 SHELL_STATIC_SUBCMD_SET_CREATE(iso_cmds,
948 #if defined(CONFIG_BT_ISO_UNICAST)
949 #if defined(CONFIG_BT_ISO_CENTRAL)
950 	SHELL_CMD_ARG(cig_create, NULL,
951 		      "[dir=tx,rx,txrx] [C to P interval] [P to C interval] "
952 		      "[packing] [framing] [C to P latency] [P to C latency] [sdu] [phy] [rtn]",
953 		      cmd_cig_create, 1, 10),
954 	SHELL_CMD_ARG(cig_term, NULL, "Terminate the CIG", cmd_cig_term, 1, 0),
955 #if defined(CONFIG_BT_SMP)
956 	SHELL_CMD_ARG(connect, NULL, "Connect ISO Channel [security level]", cmd_connect, 1, 1),
957 #else /* !CONFIG_BT_SMP */
958 	SHELL_CMD_ARG(connect, NULL, "Connect ISO Channel", cmd_connect, 1, 0),
959 #endif /* CONFIG_BT_SMP */
960 #endif /* CONFIG_BT_ISO_CENTRAL */
961 #if defined(CONFIG_BT_ISO_PERIPHERAL)
962 #if defined(CONFIG_BT_SMP)
963 	SHELL_CMD_ARG(listen, NULL, "<dir=tx,rx,txrx> [security level]", cmd_listen, 2, 1),
964 #else /* !CONFIG_BT_SMP */
965 	SHELL_CMD_ARG(listen, NULL, "<dir=tx,rx,txrx>", cmd_listen, 2, 0),
966 #endif /* CONFIG_BT_SMP */
967 #endif /* CONFIG_BT_ISO_PERIPHERAL */
968 #if defined(CONFIG_BT_ISO_TX)
969 	SHELL_CMD_ARG(send, NULL, "Send to ISO Channel [count]", cmd_send, 1, 1),
970 #endif /* CONFIG_BT_ISO_TX */
971 	SHELL_CMD_ARG(disconnect, NULL, "Disconnect ISO Channel", cmd_disconnect, 1, 0),
972 	SHELL_CMD_ARG(tx_sync_read_cis, NULL, "Read CIS TX sync info", cmd_tx_sync_read_cis, 1, 0),
973 #endif /* CONFIG_BT_ISO_UNICAST */
974 #if defined(CONFIG_BT_ISO_BROADCASTER)
975 	SHELL_CMD_ARG(create-big, NULL, "Create a BIG as a broadcaster [enc <broadcast code>]",
976 		      cmd_big_create, 1, 2),
977 	SHELL_CMD_ARG(broadcast, NULL, "Broadcast on ISO channels", cmd_broadcast, 1, 1),
978 	SHELL_CMD_ARG(tx_sync_read_bis, NULL, "Read BIS TX sync info", cmd_tx_sync_read_bis, 1, 0),
979 #endif /* CONFIG_BT_ISO_BROADCASTER */
980 #if defined(CONFIG_BT_ISO_SYNC_RECEIVER)
981 	SHELL_CMD_ARG(sync-big, NULL,
982 		      "Synchronize to a BIG as a receiver <BIS bitfield> [mse] "
983 		      "[timeout] [enc <broadcast code>]",
984 		      cmd_big_sync, 2, 4),
985 #endif /* CONFIG_BT_ISO_SYNC_RECEIVER */
986 #if defined(CONFIG_BT_ISO_BROADCAST)
987 	SHELL_CMD_ARG(term-big, NULL, "Terminate a BIG", cmd_big_term, 1, 0),
988 #endif /* CONFIG_BT_ISO_BROADCAST */
989 	SHELL_SUBCMD_SET_END
990 );
991 
cmd_iso(const struct shell * sh,size_t argc,char ** argv)992 static int cmd_iso(const struct shell *sh, size_t argc, char **argv)
993 {
994 	if (argc == 1) {
995 		shell_help(sh);
996 
997 		return SHELL_CMD_HELP_PRINTED;
998 	}
999 
1000 	shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]);
1001 
1002 	return -EINVAL;
1003 }
1004 
1005 SHELL_CMD_ARG_REGISTER(iso, &iso_cmds, "Bluetooth ISO shell commands",
1006 		       cmd_iso, 1, 1);
1007