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