1 /** @file
2  *  @brief Bluetooth Basic Audio Profile shell
3  *
4  */
5 
6 /*
7  * Copyright (c) 2020 Intel Corporation
8  * Copyright (c) 2022-2023 Nordic Semiconductor ASA
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #include <errno.h>
14 #include <stdbool.h>
15 #include <stddef.h>
16 #include <stdint.h>
17 #include <string.h>
18 #include <sys/types.h>
19 
20 #include <zephyr/autoconf.h>
21 #include <zephyr/bluetooth/audio/audio.h>
22 #include <zephyr/bluetooth/audio/bap.h>
23 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
24 #include <zephyr/bluetooth/audio/cap.h>
25 #include <zephyr/bluetooth/audio/gmap.h>
26 #include <zephyr/bluetooth/audio/lc3.h>
27 #include <zephyr/bluetooth/audio/pacs.h>
28 #include <zephyr/bluetooth/addr.h>
29 #include <zephyr/bluetooth/bluetooth.h>
30 #include <zephyr/bluetooth/conn.h>
31 #include <zephyr/bluetooth/gap.h>
32 #include <zephyr/bluetooth/gatt.h>
33 #include <zephyr/bluetooth/hci_types.h>
34 #include <zephyr/bluetooth/iso.h>
35 #include <zephyr/bluetooth/uuid.h>
36 #include <zephyr/kernel.h>
37 #include <zephyr/kernel/thread_stack.h>
38 #include <zephyr/net/buf.h>
39 #include <zephyr/shell/shell.h>
40 #include <zephyr/shell/shell_string_conv.h>
41 #include <zephyr/sys/__assert.h>
42 #include <zephyr/sys/atomic.h>
43 #include <zephyr/sys/printk.h>
44 #include <zephyr/sys/byteorder.h>
45 #include <zephyr/sys/time_units.h>
46 #include <zephyr/sys/util.h>
47 #include <zephyr/sys/util_macro.h>
48 #include <zephyr/sys_clock.h>
49 
50 #include "shell/bt.h"
51 #include "audio.h"
52 
53 /* Determines if we can initiate streaming */
54 #define IS_BAP_INITIATOR                                                                           \
55 	(IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE) || IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT))
56 
57 #define GENERATE_SINE_SUPPORTED (IS_ENABLED(CONFIG_LIBLC3) && !IS_ENABLED(CONFIG_USB_DEVICE_AUDIO))
58 
59 #if defined(CONFIG_BT_BAP_UNICAST)
60 
61 struct shell_stream unicast_streams[CONFIG_BT_MAX_CONN *
62 				    MAX(UNICAST_SERVER_STREAM_COUNT, UNICAST_CLIENT_STREAM_COUNT)];
63 
64 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
65 struct bt_bap_unicast_group *default_unicast_group;
66 static struct bt_bap_unicast_client_cb unicast_client_cbs;
67 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
68 struct bt_bap_ep *snks[CONFIG_BT_MAX_CONN][CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
69 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
70 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
71 struct bt_bap_ep *srcs[CONFIG_BT_MAX_CONN][CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
72 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
73 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
74 #endif /* CONFIG_BT_BAP_UNICAST */
75 
76 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
77 struct shell_stream broadcast_source_streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
78 struct broadcast_source default_source;
79 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
80 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
81 static struct shell_stream broadcast_sink_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
82 static struct broadcast_sink default_broadcast_sink;
83 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
84 
85 #if defined(CONFIG_BT_BAP_UNICAST) || defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
86 static struct bt_bap_stream *default_stream;
87 #endif /* CONFIG_BT_BAP_UNICAST || CONFIG_BT_BAP_BROADCAST_SOURCE */
88 
89 #if IS_BAP_INITIATOR
90 /* Default to 16_2_1 */
91 struct named_lc3_preset default_sink_preset = {"16_2_1",
92 					       BT_BAP_LC3_UNICAST_PRESET_16_2_1(LOCATION, CONTEXT)};
93 struct named_lc3_preset default_source_preset = {
94 	"16_2_1", BT_BAP_LC3_UNICAST_PRESET_16_2_1(LOCATION, CONTEXT)};
95 struct named_lc3_preset default_broadcast_source_preset = {
96 	"16_2_1", BT_BAP_LC3_BROADCAST_PRESET_16_2_1(LOCATION, CONTEXT)};
97 #endif /* IS_BAP_INITIATOR */
98 
99 static const struct named_lc3_preset lc3_unicast_presets[] = {
100 	{"8_1_1", BT_BAP_LC3_UNICAST_PRESET_8_1_1(LOCATION, CONTEXT)},
101 	{"8_2_1", BT_BAP_LC3_UNICAST_PRESET_8_2_1(LOCATION, CONTEXT)},
102 	{"16_1_1", BT_BAP_LC3_UNICAST_PRESET_16_1_1(LOCATION, CONTEXT)},
103 	{"16_2_1", BT_BAP_LC3_UNICAST_PRESET_16_2_1(LOCATION, CONTEXT)},
104 	{"24_1_1", BT_BAP_LC3_UNICAST_PRESET_24_1_1(LOCATION, CONTEXT)},
105 	{"24_2_1", BT_BAP_LC3_UNICAST_PRESET_24_2_1(LOCATION, CONTEXT)},
106 	{"32_1_1", BT_BAP_LC3_UNICAST_PRESET_32_1_1(LOCATION, CONTEXT)},
107 	{"32_2_1", BT_BAP_LC3_UNICAST_PRESET_32_2_1(LOCATION, CONTEXT)},
108 	{"441_1_1", BT_BAP_LC3_UNICAST_PRESET_441_1_1(LOCATION, CONTEXT)},
109 	{"441_2_1", BT_BAP_LC3_UNICAST_PRESET_441_2_1(LOCATION, CONTEXT)},
110 	{"48_1_1", BT_BAP_LC3_UNICAST_PRESET_48_1_1(LOCATION, CONTEXT)},
111 	{"48_2_1", BT_BAP_LC3_UNICAST_PRESET_48_2_1(LOCATION, CONTEXT)},
112 	{"48_3_1", BT_BAP_LC3_UNICAST_PRESET_48_3_1(LOCATION, CONTEXT)},
113 	{"48_4_1", BT_BAP_LC3_UNICAST_PRESET_48_4_1(LOCATION, CONTEXT)},
114 	{"48_5_1", BT_BAP_LC3_UNICAST_PRESET_48_5_1(LOCATION, CONTEXT)},
115 	{"48_6_1", BT_BAP_LC3_UNICAST_PRESET_48_6_1(LOCATION, CONTEXT)},
116 	/* High-reliability presets */
117 	{"8_1_2", BT_BAP_LC3_UNICAST_PRESET_8_1_2(LOCATION, CONTEXT)},
118 	{"8_2_2", BT_BAP_LC3_UNICAST_PRESET_8_2_2(LOCATION, CONTEXT)},
119 	{"16_1_2", BT_BAP_LC3_UNICAST_PRESET_16_1_2(LOCATION, CONTEXT)},
120 	{"16_2_2", BT_BAP_LC3_UNICAST_PRESET_16_2_2(LOCATION, CONTEXT)},
121 	{"24_1_2", BT_BAP_LC3_UNICAST_PRESET_24_1_2(LOCATION, CONTEXT)},
122 	{"24_2_2", BT_BAP_LC3_UNICAST_PRESET_24_2_2(LOCATION, CONTEXT)},
123 	{"32_1_2", BT_BAP_LC3_UNICAST_PRESET_32_1_2(LOCATION, CONTEXT)},
124 	{"32_2_2", BT_BAP_LC3_UNICAST_PRESET_32_2_2(LOCATION, CONTEXT)},
125 	{"441_1_2", BT_BAP_LC3_UNICAST_PRESET_441_1_2(LOCATION, CONTEXT)},
126 	{"441_2_2", BT_BAP_LC3_UNICAST_PRESET_441_2_2(LOCATION, CONTEXT)},
127 	{"48_1_2", BT_BAP_LC3_UNICAST_PRESET_48_1_2(LOCATION, CONTEXT)},
128 	{"48_2_2", BT_BAP_LC3_UNICAST_PRESET_48_2_2(LOCATION, CONTEXT)},
129 	{"48_3_2", BT_BAP_LC3_UNICAST_PRESET_48_3_2(LOCATION, CONTEXT)},
130 	{"48_4_2", BT_BAP_LC3_UNICAST_PRESET_48_4_2(LOCATION, CONTEXT)},
131 	{"48_5_2", BT_BAP_LC3_UNICAST_PRESET_48_5_2(LOCATION, CONTEXT)},
132 	{"48_6_2", BT_BAP_LC3_UNICAST_PRESET_48_6_2(LOCATION, CONTEXT)},
133 };
134 
135 static const struct named_lc3_preset lc3_broadcast_presets[] = {
136 	{"8_1_1", BT_BAP_LC3_BROADCAST_PRESET_8_1_1(LOCATION, CONTEXT)},
137 	{"8_2_1", BT_BAP_LC3_BROADCAST_PRESET_8_2_1(LOCATION, CONTEXT)},
138 	{"16_1_1", BT_BAP_LC3_BROADCAST_PRESET_16_1_1(LOCATION, CONTEXT)},
139 	{"16_2_1", BT_BAP_LC3_BROADCAST_PRESET_16_2_1(LOCATION, CONTEXT)},
140 	{"24_1_1", BT_BAP_LC3_BROADCAST_PRESET_24_1_1(LOCATION, CONTEXT)},
141 	{"24_2_1", BT_BAP_LC3_BROADCAST_PRESET_24_2_1(LOCATION, CONTEXT)},
142 	{"32_1_1", BT_BAP_LC3_BROADCAST_PRESET_32_1_1(LOCATION, CONTEXT)},
143 	{"32_2_1", BT_BAP_LC3_BROADCAST_PRESET_32_2_1(LOCATION, CONTEXT)},
144 	{"441_1_1", BT_BAP_LC3_BROADCAST_PRESET_441_1_1(LOCATION, CONTEXT)},
145 	{"441_2_1", BT_BAP_LC3_BROADCAST_PRESET_441_2_1(LOCATION, CONTEXT)},
146 	{"48_1_1", BT_BAP_LC3_BROADCAST_PRESET_48_1_1(LOCATION, CONTEXT)},
147 	{"48_2_1", BT_BAP_LC3_BROADCAST_PRESET_48_2_1(LOCATION, CONTEXT)},
148 	{"48_3_1", BT_BAP_LC3_BROADCAST_PRESET_48_3_1(LOCATION, CONTEXT)},
149 	{"48_4_1", BT_BAP_LC3_BROADCAST_PRESET_48_4_1(LOCATION, CONTEXT)},
150 	{"48_5_1", BT_BAP_LC3_BROADCAST_PRESET_48_5_1(LOCATION, CONTEXT)},
151 	{"48_6_1", BT_BAP_LC3_BROADCAST_PRESET_48_6_1(LOCATION, CONTEXT)},
152 	/* High-reliability presets */
153 	{"8_1_2", BT_BAP_LC3_BROADCAST_PRESET_8_1_2(LOCATION, CONTEXT)},
154 	{"8_2_2", BT_BAP_LC3_BROADCAST_PRESET_8_2_2(LOCATION, CONTEXT)},
155 	{"16_1_2", BT_BAP_LC3_BROADCAST_PRESET_16_1_2(LOCATION, CONTEXT)},
156 	{"16_2_2", BT_BAP_LC3_BROADCAST_PRESET_16_2_2(LOCATION, CONTEXT)},
157 	{"24_1_2", BT_BAP_LC3_BROADCAST_PRESET_24_1_2(LOCATION, CONTEXT)},
158 	{"24_2_2", BT_BAP_LC3_BROADCAST_PRESET_24_2_2(LOCATION, CONTEXT)},
159 	{"32_1_2", BT_BAP_LC3_BROADCAST_PRESET_32_1_2(LOCATION, CONTEXT)},
160 	{"32_2_2", BT_BAP_LC3_BROADCAST_PRESET_32_2_2(LOCATION, CONTEXT)},
161 	{"441_1_2", BT_BAP_LC3_BROADCAST_PRESET_441_1_2(LOCATION, CONTEXT)},
162 	{"441_2_2", BT_BAP_LC3_BROADCAST_PRESET_441_2_2(LOCATION, CONTEXT)},
163 	{"48_1_2", BT_BAP_LC3_BROADCAST_PRESET_48_1_2(LOCATION, CONTEXT)},
164 	{"48_2_2", BT_BAP_LC3_BROADCAST_PRESET_48_2_2(LOCATION, CONTEXT)},
165 	{"48_3_2", BT_BAP_LC3_BROADCAST_PRESET_48_3_2(LOCATION, CONTEXT)},
166 	{"48_4_2", BT_BAP_LC3_BROADCAST_PRESET_48_4_2(LOCATION, CONTEXT)},
167 	{"48_5_2", BT_BAP_LC3_BROADCAST_PRESET_48_5_2(LOCATION, CONTEXT)},
168 	{"48_6_2", BT_BAP_LC3_BROADCAST_PRESET_48_6_2(LOCATION, CONTEXT)},
169 };
170 
171 static bool initialized;
172 static unsigned long bap_stats_interval = 1000U;
173 
shell_stream_from_bap_stream(struct bt_bap_stream * bap_stream)174 struct shell_stream *shell_stream_from_bap_stream(struct bt_bap_stream *bap_stream)
175 {
176 	struct bt_cap_stream *cap_stream =
177 		CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream);
178 	struct shell_stream *sh_stream = CONTAINER_OF(cap_stream, struct shell_stream, stream);
179 
180 	return sh_stream;
181 }
182 
bap_stream_from_shell_stream(struct shell_stream * sh_stream)183 struct bt_bap_stream *bap_stream_from_shell_stream(struct shell_stream *sh_stream)
184 {
185 	return &sh_stream->stream.bap_stream;
186 }
187 
bap_get_stats_interval(void)188 unsigned long bap_get_stats_interval(void)
189 {
190 	return bap_stats_interval;
191 }
192 
bap_foreach_stream(void (* func)(struct shell_stream * sh_stream,void * data),void * data)193 void bap_foreach_stream(void (*func)(struct shell_stream *sh_stream, void *data), void *data)
194 {
195 #if defined(CONFIG_BT_BAP_UNICAST)
196 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
197 		func(&unicast_streams[i], data);
198 	}
199 #endif /* CONFIG_BT_BAP_UNICAST */
200 
201 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
202 	for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) {
203 		func(&broadcast_source_streams[i], data);
204 	}
205 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
206 
207 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
208 	for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sink_streams); i++) {
209 		func(&broadcast_sink_streams[i], data);
210 	}
211 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
212 }
213 
214 #if defined(CONFIG_LIBLC3)
215 #include <lc3.h>
216 
get_lc3_chan_alloc_from_index(const struct shell_stream * sh_stream,uint8_t index,enum bt_audio_location * chan_alloc)217 static int get_lc3_chan_alloc_from_index(const struct shell_stream *sh_stream, uint8_t index,
218 					 enum bt_audio_location *chan_alloc)
219 {
220 	const bool has_left = (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0;
221 	const bool has_right =
222 		(sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0;
223 	const bool is_mono = sh_stream->lc3_chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO;
224 	const bool is_left = index == 0 && has_left;
225 	const bool is_right = has_right && (index == 0U || (index == 1U && has_left));
226 
227 	/* LC3 is always Left before Right, so we can use the index and the stream channel
228 	 * allocation to determine if index 0 is left or right.
229 	 */
230 	if (is_left) {
231 		*chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT;
232 	} else if (is_right) {
233 		*chan_alloc = BT_AUDIO_LOCATION_FRONT_RIGHT;
234 	} else if (is_mono) {
235 		*chan_alloc = BT_AUDIO_LOCATION_MONO_AUDIO;
236 	} else {
237 		/* Not suitable for USB */
238 		return -EINVAL;
239 	}
240 
241 	return 0;
242 }
243 #endif /* CONFIG_LIBLC3 */
244 
245 #if defined(CONFIG_BT_AUDIO_TX)
246 static size_t tx_streaming_cnt;
247 
bap_get_tx_streaming_cnt(void)248 size_t bap_get_tx_streaming_cnt(void)
249 {
250 	return tx_streaming_cnt;
251 }
252 
get_next_seq_num(struct bt_bap_stream * bap_stream)253 uint16_t get_next_seq_num(struct bt_bap_stream *bap_stream)
254 {
255 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(bap_stream);
256 	const uint32_t interval_us = bap_stream->qos->interval;
257 	int64_t uptime_ticks;
258 	int64_t delta_ticks;
259 	uint64_t delta_us;
260 	uint16_t seq_num;
261 
262 	if (!sh_stream->is_tx) {
263 		return 0;
264 	}
265 
266 	/* Note: This does not handle wrapping of ticks when they go above 2^(62-1) */
267 	uptime_ticks = k_uptime_ticks();
268 	delta_ticks = uptime_ticks - sh_stream->tx.connected_at_ticks;
269 
270 	delta_us = k_ticks_to_us_near64((uint64_t)delta_ticks);
271 	/* Calculate the sequence number by dividing the stream uptime by the SDU interval */
272 	seq_num = (uint16_t)(delta_us / interval_us);
273 
274 	return seq_num;
275 }
276 #endif /* CONFIG_BT_AUDIO_TX */
277 
278 #if defined(CONFIG_LIBLC3) && defined(CONFIG_BT_AUDIO_TX)
279 /* For the first call-back we push multiple audio frames to the buffer to use the
280  * controller ISO buffer to handle jitter.
281  */
282 #define PRIME_COUNT 2U
283 #define SINE_TX_POOL_SIZE (BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU))
284 NET_BUF_POOL_FIXED_DEFINE(sine_tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, SINE_TX_POOL_SIZE,
285 			  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
286 
287 #include "math.h"
288 
289 #define AUDIO_VOLUME            (INT16_MAX - 3000) /* codec does clipping above INT16_MAX - 3000 */
290 #define AUDIO_TONE_FREQUENCY_HZ   400
291 
292 static int16_t lc3_tx_buf[LC3_MAX_NUM_SAMPLES_MONO];
293 
init_lc3_encoder(struct shell_stream * sh_stream)294 static int init_lc3_encoder(struct shell_stream *sh_stream)
295 {
296 	if (sh_stream == NULL) {
297 		shell_error(ctx_shell, "NULL stream to init LC3");
298 		return -EINVAL;
299 	}
300 
301 	if (!sh_stream->is_tx) {
302 		shell_error(ctx_shell, "Invalid stream to init LC3 encoder");
303 		return -EINVAL;
304 	}
305 
306 	if (sh_stream->tx.lc3_encoder != NULL) {
307 		shell_error(ctx_shell, "Already initialized");
308 		return -EALREADY;
309 	}
310 
311 	if (sh_stream->lc3_freq_hz == 0 || sh_stream->lc3_frame_duration_us == 0) {
312 		shell_error(ctx_shell, "Invalid freq (%u) or frame duration (%u)",
313 			    sh_stream->lc3_freq_hz, sh_stream->lc3_frame_duration_us);
314 
315 		return -EINVAL;
316 	}
317 
318 	if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
319 		const size_t frame_size = bap_usb_get_frame_size(sh_stream);
320 
321 		if (frame_size > sizeof(lc3_tx_buf)) {
322 			shell_error(ctx_shell, "Cannot put %u octets in lc3_tx_buf of size %zu",
323 				    frame_size, sizeof(lc3_tx_buf));
324 
325 			return -EINVAL;
326 		}
327 	}
328 
329 	shell_print(ctx_shell,
330 		    "Initializing LC3 encoder for BAP stream %p with %u us duration and %u Hz "
331 		    "frequency",
332 		    bap_stream_from_shell_stream(sh_stream), sh_stream->lc3_frame_duration_us,
333 		    sh_stream->lc3_freq_hz);
334 
335 	sh_stream->tx.lc3_encoder =
336 		lc3_setup_encoder(sh_stream->lc3_frame_duration_us, sh_stream->lc3_freq_hz,
337 				  IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) ? USB_SAMPLE_RATE : 0,
338 				  &sh_stream->tx.lc3_encoder_mem);
339 	if (sh_stream->tx.lc3_encoder == NULL) {
340 		shell_error(ctx_shell, "Failed to setup LC3 encoder - wrong parameters?\n");
341 		return -EINVAL;
342 	}
343 
344 	return 0;
345 }
346 
347 /**
348  * Use the math lib to generate a sine-wave using 16 bit samples into a buffer.
349  *
350  * @param buf Destination buffer
351  * @param length_us Length of the buffer in microseconds
352  * @param frequency_hz frequency in Hz
353  * @param sample_rate_hz sample-rate in Hz.
354  */
fill_lc3_tx_buf_sin(int16_t * buf,int length_us,int frequency_hz,int sample_rate_hz)355 static void fill_lc3_tx_buf_sin(int16_t *buf, int length_us, int frequency_hz, int sample_rate_hz)
356 {
357 	const uint32_t sine_period_samples = sample_rate_hz / frequency_hz;
358 	const size_t num_samples = (length_us * sample_rate_hz) / USEC_PER_SEC;
359 	const float step = 2 * 3.1415 / sine_period_samples;
360 
361 	for (size_t i = 0; i < num_samples; i++) {
362 		const float sample = sinf(i * step);
363 
364 		buf[i] = (int16_t)(AUDIO_VOLUME * sample);
365 	}
366 }
367 
encode_frame(struct shell_stream * sh_stream,uint8_t index,size_t frame_cnt,struct net_buf * out_buf)368 static bool encode_frame(struct shell_stream *sh_stream, uint8_t index, size_t frame_cnt,
369 			 struct net_buf *out_buf)
370 {
371 	const size_t total_frames = sh_stream->lc3_chan_cnt * sh_stream->lc3_frame_blocks_per_sdu;
372 	const uint16_t octets_per_frame = sh_stream->lc3_octets_per_frame;
373 	int lc3_ret;
374 
375 	if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
376 		enum bt_audio_location chan_alloc;
377 		int err;
378 
379 		err = get_lc3_chan_alloc_from_index(sh_stream, index, &chan_alloc);
380 		if (err != 0) {
381 			/* Not suitable for USB */
382 			false;
383 		}
384 
385 		/* TODO: Move the following to a function in bap_usb.c*/
386 		bap_usb_get_frame(sh_stream, chan_alloc, lc3_tx_buf);
387 	} else {
388 		/* Generate sine wave */
389 		fill_lc3_tx_buf_sin(lc3_tx_buf, sh_stream->lc3_frame_duration_us,
390 				    AUDIO_TONE_FREQUENCY_HZ, sh_stream->lc3_freq_hz);
391 	}
392 
393 	if ((sh_stream->tx.encoded_cnt % bap_stats_interval) == 0) {
394 		shell_print(ctx_shell, "[%zu]: Encoding frame of size %u (%u/%u)",
395 			    sh_stream->tx.encoded_cnt, octets_per_frame, frame_cnt + 1,
396 			    total_frames);
397 	}
398 
399 	lc3_ret = lc3_encode(sh_stream->tx.lc3_encoder, LC3_PCM_FORMAT_S16, lc3_tx_buf, 1,
400 			     octets_per_frame, net_buf_tail(out_buf));
401 	if (lc3_ret == -1) {
402 		shell_error(ctx_shell, "LC3 encoder failed - wrong parameters?: %d", lc3_ret);
403 
404 		return false;
405 	}
406 
407 	out_buf->len += octets_per_frame;
408 
409 	return true;
410 }
411 
encode_frame_block(struct shell_stream * sh_stream,size_t frame_cnt,struct net_buf * out_buf)412 static size_t encode_frame_block(struct shell_stream *sh_stream, size_t frame_cnt,
413 				 struct net_buf *out_buf)
414 {
415 	const uint8_t chan_cnt = sh_stream->lc3_chan_cnt;
416 	size_t encoded_frames = 0U;
417 
418 	for (uint8_t i = 0U; i < chan_cnt; i++) {
419 		/* We provide the total number of decoded frames to `decode_frame` for logging
420 		 * purposes
421 		 */
422 		if (encode_frame(sh_stream, i, frame_cnt, out_buf)) {
423 			encoded_frames++;
424 		}
425 	}
426 
427 	return encoded_frames;
428 }
429 
do_lc3_encode(struct shell_stream * sh_stream,struct net_buf * out_buf)430 static void do_lc3_encode(struct shell_stream *sh_stream, struct net_buf *out_buf)
431 {
432 	if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) && !bap_usb_can_get_full_sdu(sh_stream)) {
433 		/* No op - Will just send empty SDU */
434 	} else {
435 		size_t frame_cnt = 0U;
436 
437 		for (uint8_t i = 0U; i < sh_stream->lc3_frame_blocks_per_sdu; i++) {
438 			frame_cnt += encode_frame_block(sh_stream, frame_cnt, out_buf);
439 
440 			sh_stream->tx.encoded_cnt++;
441 		}
442 	}
443 }
444 
lc3_audio_send_data(struct shell_stream * sh_stream)445 static void lc3_audio_send_data(struct shell_stream *sh_stream)
446 {
447 	struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream);
448 	const uint16_t tx_sdu_len = sh_stream->lc3_frame_blocks_per_sdu * sh_stream->lc3_chan_cnt *
449 				    sh_stream->lc3_octets_per_frame;
450 	struct net_buf *buf;
451 	int err;
452 
453 	if (!sh_stream->is_tx || !sh_stream->tx.active) {
454 		/* TX has been aborted */
455 		return;
456 	}
457 
458 	if (sh_stream->tx.lc3_encoder == NULL) {
459 		shell_error(ctx_shell, "LC3 encoder not setup, cannot encode data");
460 		return;
461 	}
462 
463 	if (bap_stream == NULL || bap_stream->qos == NULL) {
464 		shell_error(ctx_shell, "invalid stream, aborting");
465 		return;
466 	}
467 
468 	if (tx_sdu_len == 0U || tx_sdu_len > SINE_TX_POOL_SIZE) {
469 		shell_error(ctx_shell,
470 			    "Cannot send %u length SDU (from frame blocks per sdu %u, channel "
471 			    "count %u and %u octets per frame) for pool size %d",
472 			    tx_sdu_len, sh_stream->lc3_frame_blocks_per_sdu,
473 			    sh_stream->lc3_chan_cnt, sh_stream->lc3_octets_per_frame,
474 			    SINE_TX_POOL_SIZE);
475 		return;
476 	}
477 
478 	if (atomic_get(&sh_stream->tx.lc3_enqueue_cnt) == 0U) {
479 		/* no op */
480 		return;
481 	}
482 
483 	buf = net_buf_alloc(&sine_tx_pool, K_FOREVER);
484 	net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
485 
486 	do_lc3_encode(sh_stream, buf);
487 
488 	err = bt_bap_stream_send(bap_stream, buf, sh_stream->tx.seq_num);
489 	if (err < 0) {
490 		shell_error(ctx_shell, "Failed to send LC3 audio data (%d)", err);
491 		net_buf_unref(buf);
492 
493 		return;
494 	}
495 
496 	if ((sh_stream->tx.lc3_sdu_cnt % bap_stats_interval) == 0U) {
497 		shell_info(ctx_shell, "[%zu]: stream %p : TX LC3: %zu (seq_num %u)",
498 			   sh_stream->tx.lc3_sdu_cnt, bap_stream, tx_sdu_len,
499 			   sh_stream->tx.seq_num);
500 	}
501 
502 	sh_stream->tx.lc3_sdu_cnt++;
503 	sh_stream->tx.seq_num++;
504 	atomic_dec(&sh_stream->tx.lc3_enqueue_cnt);
505 }
506 
lc3_sent_cb(struct bt_bap_stream * bap_stream)507 static void lc3_sent_cb(struct bt_bap_stream *bap_stream)
508 {
509 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(bap_stream);
510 
511 	if (!sh_stream->is_tx) {
512 		return;
513 	}
514 
515 	atomic_inc(&sh_stream->tx.lc3_enqueue_cnt);
516 }
517 
encode_and_send_cb(struct shell_stream * sh_stream,void * user_data)518 static void encode_and_send_cb(struct shell_stream *sh_stream, void *user_data)
519 {
520 	if (sh_stream->is_tx) {
521 		lc3_audio_send_data(sh_stream);
522 	}
523 }
524 
lc3_encoder_thread_func(void * arg1,void * arg2,void * arg3)525 static void lc3_encoder_thread_func(void *arg1, void *arg2, void *arg3)
526 {
527 	/* This will attempt to send on all TX streams.
528 	 * If there are no buffers available or the stream already have PRIME_COUNT outstanding SDUs
529 	 * the stream will not send anything.
530 	 *
531 	 * If USB is enabled it will attempt to read from buffered USB audio data.
532 	 * If there is no data available it will send empty SDUs
533 	 */
534 	while (true) {
535 		bap_foreach_stream(encode_and_send_cb, NULL);
536 		k_sleep(K_MSEC(1));
537 	}
538 }
539 #endif /* CONFIG_LIBLC3 && CONFIG_BT_AUDIO_TX */
540 
bap_get_named_preset(bool is_unicast,enum bt_audio_dir dir,const char * preset_arg)541 const struct named_lc3_preset *bap_get_named_preset(bool is_unicast, enum bt_audio_dir dir,
542 						    const char *preset_arg)
543 {
544 	if (is_unicast) {
545 		for (size_t i = 0U; i < ARRAY_SIZE(lc3_unicast_presets); i++) {
546 			if (!strcmp(preset_arg, lc3_unicast_presets[i].name)) {
547 				return &lc3_unicast_presets[i];
548 			}
549 		}
550 	} else {
551 		for (size_t i = 0U; i < ARRAY_SIZE(lc3_broadcast_presets); i++) {
552 			if (!strcmp(preset_arg, lc3_broadcast_presets[i].name)) {
553 				return &lc3_broadcast_presets[i];
554 			}
555 		}
556 	}
557 
558 	if (IS_ENABLED(CONFIG_BT_GMAP)) {
559 		return gmap_get_named_preset(is_unicast, dir, preset_arg);
560 	}
561 
562 	return NULL;
563 }
564 
565 #if defined(CONFIG_BT_PACS)
566 static const struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3(
567 	BT_AUDIO_CODEC_CAP_FREQ_ANY, BT_AUDIO_CODEC_CAP_DURATION_ANY,
568 	BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1, 2), 30, 240, MAX_CODEC_FRAMES_PER_SDU, CONTEXT);
569 
570 #if defined(CONFIG_BT_PAC_SNK)
571 static struct bt_pacs_cap cap_sink = {
572 	.codec_cap = &lc3_codec_cap,
573 };
574 #endif /* CONFIG_BT_PAC_SNK */
575 
576 #if defined(CONFIG_BT_PAC_SRC)
577 static struct bt_pacs_cap cap_source = {
578 	.codec_cap = &lc3_codec_cap,
579 };
580 #endif /* CONFIG_BT_PAC_SRC */
581 #endif /* CONFIG_BT_PACS */
582 
583 #if defined(CONFIG_BT_BAP_UNICAST)
set_unicast_stream(struct bt_bap_stream * stream)584 static void set_unicast_stream(struct bt_bap_stream *stream)
585 {
586 	default_stream = stream;
587 
588 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
589 		if (stream == bap_stream_from_shell_stream(&unicast_streams[i])) {
590 			shell_print(ctx_shell, "Default stream: %u", i + 1);
591 		}
592 	}
593 }
594 
cmd_select_unicast(const struct shell * sh,size_t argc,char * argv[])595 static int cmd_select_unicast(const struct shell *sh, size_t argc, char *argv[])
596 {
597 	struct bt_bap_stream *stream;
598 	unsigned long index;
599 	int err = 0;
600 
601 	index = shell_strtoul(argv[1], 0, &err);
602 	if (err != 0) {
603 		shell_error(sh, "Could not parse index: %d", err);
604 
605 		return -ENOEXEC;
606 	}
607 
608 	if (index > ARRAY_SIZE(unicast_streams)) {
609 		shell_error(sh, "Invalid index: %lu", index);
610 
611 		return -ENOEXEC;
612 	}
613 
614 	stream = bap_stream_from_shell_stream(&unicast_streams[index]);
615 
616 	set_unicast_stream(stream);
617 
618 	return 0;
619 }
620 
621 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
622 static const struct bt_audio_codec_qos_pref qos_pref =
623 	BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0u, 60u, 10000u, 60000u, 10000u, 60000u);
624 
stream_alloc(void)625 static struct bt_bap_stream *stream_alloc(void)
626 {
627 	for (size_t i = 0; i < ARRAY_SIZE(unicast_streams); i++) {
628 		struct bt_bap_stream *stream = bap_stream_from_shell_stream(&unicast_streams[i]);
629 
630 		if (!stream->conn) {
631 			return stream;
632 		}
633 	}
634 
635 	return NULL;
636 }
637 
lc3_config(struct bt_conn * conn,const struct bt_bap_ep * ep,enum bt_audio_dir dir,const struct bt_audio_codec_cfg * codec_cfg,struct bt_bap_stream ** stream,struct bt_audio_codec_qos_pref * const pref,struct bt_bap_ascs_rsp * rsp)638 static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir,
639 		      const struct bt_audio_codec_cfg *codec_cfg, struct bt_bap_stream **stream,
640 		      struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp)
641 {
642 	shell_print(ctx_shell, "ASE Codec Config: conn %p ep %p dir %u", conn, ep, dir);
643 
644 	print_codec_cfg(ctx_shell, 0, codec_cfg);
645 
646 	*stream = stream_alloc();
647 	if (*stream == NULL) {
648 		shell_print(ctx_shell, "No unicast_streams available");
649 
650 		*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM, BT_BAP_ASCS_REASON_NONE);
651 
652 		return -ENOMEM;
653 	}
654 
655 	shell_print(ctx_shell, "ASE Codec Config stream %p", *stream);
656 
657 	set_unicast_stream(*stream);
658 
659 	*pref = qos_pref;
660 
661 	return 0;
662 }
663 
lc3_reconfig(struct bt_bap_stream * stream,enum bt_audio_dir dir,const struct bt_audio_codec_cfg * codec_cfg,struct bt_audio_codec_qos_pref * const pref,struct bt_bap_ascs_rsp * rsp)664 static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir,
665 			const struct bt_audio_codec_cfg *codec_cfg,
666 			struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp)
667 {
668 	shell_print(ctx_shell, "ASE Codec Reconfig: stream %p", stream);
669 
670 	print_codec_cfg(ctx_shell, 0, codec_cfg);
671 
672 	if (default_stream == NULL) {
673 		set_unicast_stream(stream);
674 	}
675 
676 	*pref = qos_pref;
677 
678 	return 0;
679 }
680 
lc3_qos(struct bt_bap_stream * stream,const struct bt_audio_codec_qos * qos,struct bt_bap_ascs_rsp * rsp)681 static int lc3_qos(struct bt_bap_stream *stream, const struct bt_audio_codec_qos *qos,
682 		   struct bt_bap_ascs_rsp *rsp)
683 {
684 	shell_print(ctx_shell, "QoS: stream %p %p", stream, qos);
685 
686 	print_qos(ctx_shell, qos);
687 
688 	return 0;
689 }
690 
lc3_enable(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len,struct bt_bap_ascs_rsp * rsp)691 static int lc3_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len,
692 		      struct bt_bap_ascs_rsp *rsp)
693 {
694 	shell_print(ctx_shell, "Enable: stream %p meta_len %zu", stream,
695 		    meta_len);
696 
697 	return 0;
698 }
699 
lc3_start(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)700 static int lc3_start(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
701 {
702 	shell_print(ctx_shell, "Start: stream %p", stream);
703 
704 	return 0;
705 }
706 
707 
meta_data_func_cb(struct bt_data * data,void * user_data)708 static bool meta_data_func_cb(struct bt_data *data, void *user_data)
709 {
710 	struct bt_bap_ascs_rsp *rsp = (struct bt_bap_ascs_rsp *)user_data;
711 
712 	if (!BT_AUDIO_METADATA_TYPE_IS_KNOWN(data->type)) {
713 		printk("Invalid metadata type %u or length %u\n", data->type, data->data_len);
714 		*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED, data->type);
715 		return false;
716 	}
717 
718 	return true;
719 }
720 
lc3_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len,struct bt_bap_ascs_rsp * rsp)721 static int lc3_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len,
722 			struct bt_bap_ascs_rsp *rsp)
723 {
724 	shell_print(ctx_shell, "Metadata: stream %p meta_len %zu", stream,
725 		    meta_len);
726 
727 	return bt_audio_data_parse(meta, meta_len, meta_data_func_cb, rsp);
728 }
729 
lc3_disable(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)730 static int lc3_disable(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
731 {
732 	shell_print(ctx_shell, "Disable: stream %p", stream);
733 
734 	return 0;
735 }
736 
lc3_stop(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)737 static int lc3_stop(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
738 {
739 	shell_print(ctx_shell, "Stop: stream %p", stream);
740 
741 	return 0;
742 }
743 
lc3_release(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)744 static int lc3_release(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
745 {
746 	shell_print(ctx_shell, "Release: stream %p", stream);
747 
748 	if (stream == default_stream) {
749 		default_stream = NULL;
750 	}
751 
752 	return 0;
753 }
754 
755 static const struct bt_bap_unicast_server_cb unicast_server_cb = {
756 	.config = lc3_config,
757 	.reconfig = lc3_reconfig,
758 	.qos = lc3_qos,
759 	.enable = lc3_enable,
760 	.start = lc3_start,
761 	.metadata = lc3_metadata,
762 	.disable = lc3_disable,
763 	.stop = lc3_stop,
764 	.release = lc3_release,
765 };
766 #endif /* CONFIG_BT_BAP_UNICAST_SERVER */
767 
strmeta(const char * name)768 static uint16_t strmeta(const char *name)
769 {
770 	if (strcmp(name, "Unspecified") == 0) {
771 		return BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED;
772 	} else if (strcmp(name, "Conversational") == 0) {
773 		return BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL;
774 	} else if (strcmp(name, "Media") == 0) {
775 		return BT_AUDIO_CONTEXT_TYPE_MEDIA;
776 	} else if (strcmp(name, "Game") == 0) {
777 		return BT_AUDIO_CONTEXT_TYPE_GAME;
778 	} else if (strcmp(name, "Instructional") == 0) {
779 		return BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL;
780 	} else if (strcmp(name, "VoiceAssistants") == 0) {
781 		return BT_AUDIO_CONTEXT_TYPE_VOICE_ASSISTANTS;
782 	} else if (strcmp(name, "Live") == 0) {
783 		return BT_AUDIO_CONTEXT_TYPE_LIVE;
784 	} else if (strcmp(name, "SoundEffects") == 0) {
785 		return BT_AUDIO_CONTEXT_TYPE_SOUND_EFFECTS;
786 	} else if (strcmp(name, "Notifications") == 0) {
787 		return BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS;
788 	} else if (strcmp(name, "Ringtone") == 0) {
789 		return BT_AUDIO_CONTEXT_TYPE_RINGTONE;
790 	} else if (strcmp(name, "Alerts") == 0) {
791 		return BT_AUDIO_CONTEXT_TYPE_ALERTS;
792 	} else if (strcmp(name, "EmergencyAlarm") == 0) {
793 		return BT_AUDIO_CONTEXT_TYPE_EMERGENCY_ALARM;
794 	}
795 
796 	return 0u;
797 }
798 
set_metadata(struct bt_audio_codec_cfg * codec_cfg,const char * meta_str)799 static int set_metadata(struct bt_audio_codec_cfg *codec_cfg, const char *meta_str)
800 {
801 	uint16_t context;
802 
803 	context = strmeta(meta_str);
804 	if (context == 0) {
805 		return -ENOEXEC;
806 	}
807 
808 	/* TODO: Check the type and only overwrite the streaming context */
809 	sys_put_le16(context, codec_cfg->meta);
810 
811 	return 0;
812 }
813 
814 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
bap_ac_create_unicast_group(const struct bap_unicast_ac_param * param,struct shell_stream * snk_uni_streams[],size_t snk_cnt,struct shell_stream * src_uni_streams[],size_t src_cnt)815 int bap_ac_create_unicast_group(const struct bap_unicast_ac_param *param,
816 				struct shell_stream *snk_uni_streams[], size_t snk_cnt,
817 				struct shell_stream *src_uni_streams[], size_t src_cnt)
818 {
819 	struct bt_bap_unicast_group_stream_param snk_group_stream_params[BAP_UNICAST_AC_MAX_SNK] = {
820 		0};
821 	struct bt_bap_unicast_group_stream_param src_group_stream_params[BAP_UNICAST_AC_MAX_SRC] = {
822 		0};
823 	struct bt_bap_unicast_group_stream_pair_param pair_params[BAP_UNICAST_AC_MAX_PAIR] = {0};
824 	struct bt_bap_unicast_group_param group_param = {0};
825 	struct bt_audio_codec_qos *snk_qos[BAP_UNICAST_AC_MAX_SNK];
826 	struct bt_audio_codec_qos *src_qos[BAP_UNICAST_AC_MAX_SRC];
827 	size_t snk_stream_cnt = 0U;
828 	size_t src_stream_cnt = 0U;
829 	size_t pair_cnt = 0U;
830 
831 	for (size_t i = 0U; i < snk_cnt; i++) {
832 		snk_qos[i] = &snk_uni_streams[i]->qos;
833 	}
834 
835 	for (size_t i = 0U; i < src_cnt; i++) {
836 		src_qos[i] = &src_uni_streams[i]->qos;
837 	}
838 
839 	/* Create Group
840 	 *
841 	 * First setup the individual stream parameters and then match them in pairs by connection
842 	 * and direction
843 	 */
844 	for (size_t i = 0U; i < snk_cnt; i++) {
845 		snk_group_stream_params[i].qos = snk_qos[i];
846 		snk_group_stream_params[i].stream =
847 			bap_stream_from_shell_stream(snk_uni_streams[i]);
848 	}
849 	for (size_t i = 0U; i < src_cnt; i++) {
850 		src_group_stream_params[i].qos = src_qos[i];
851 		src_group_stream_params[i].stream =
852 			bap_stream_from_shell_stream(src_uni_streams[i]);
853 	}
854 
855 	for (size_t i = 0U; i < param->conn_cnt; i++) {
856 		for (size_t j = 0; j < MAX(param->snk_cnt[i], param->src_cnt[i]); j++) {
857 			if (param->snk_cnt[i] > j) {
858 				pair_params[pair_cnt].tx_param =
859 					&snk_group_stream_params[snk_stream_cnt++];
860 			} else {
861 				pair_params[pair_cnt].tx_param = NULL;
862 			}
863 
864 			if (param->src_cnt[i] > j) {
865 				pair_params[pair_cnt].rx_param =
866 					&src_group_stream_params[src_stream_cnt++];
867 			} else {
868 				pair_params[pair_cnt].rx_param = NULL;
869 			}
870 
871 			pair_cnt++;
872 		}
873 	}
874 
875 	group_param.packing = BT_ISO_PACKING_SEQUENTIAL;
876 	group_param.params = pair_params;
877 	group_param.params_count = pair_cnt;
878 
879 	return bt_bap_unicast_group_create(&group_param, &default_unicast_group);
880 }
881 
stream_dir(const struct bt_bap_stream * stream)882 static uint8_t stream_dir(const struct bt_bap_stream *stream)
883 {
884 	if (stream->conn) {
885 		uint8_t conn_index = bt_conn_index(stream->conn);
886 
887 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
888 		for (size_t i = 0; i < ARRAY_SIZE(snks[conn_index]); i++) {
889 			const struct bt_bap_ep *snk_ep = snks[conn_index][i];
890 
891 			if (snk_ep != NULL && stream->ep == snk_ep) {
892 				return BT_AUDIO_DIR_SINK;
893 			}
894 		}
895 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
896 
897 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
898 		for (size_t i = 0; i < ARRAY_SIZE(srcs[conn_index]); i++) {
899 			const struct bt_bap_ep *src_ep = srcs[conn_index][i];
900 
901 			if (src_ep != NULL && stream->ep == src_ep) {
902 				return BT_AUDIO_DIR_SOURCE;
903 			}
904 		}
905 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
906 	}
907 
908 	__ASSERT(false, "Invalid stream");
909 	return 0;
910 }
911 
print_remote_codec_cap(const struct bt_conn * conn,const struct bt_audio_codec_cap * codec_cap,enum bt_audio_dir dir)912 static void print_remote_codec_cap(const struct bt_conn *conn,
913 				   const struct bt_audio_codec_cap *codec_cap,
914 				   enum bt_audio_dir dir)
915 {
916 	shell_print(ctx_shell, "conn %p: codec_cap %p dir 0x%02x", conn, codec_cap,
917 		    dir);
918 
919 	print_codec_cap(ctx_shell, 0, codec_cap);
920 }
921 
922 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
add_sink(const struct bt_conn * conn,struct bt_bap_ep * ep)923 static void add_sink(const struct bt_conn *conn, struct bt_bap_ep *ep)
924 {
925 	const uint8_t conn_index = bt_conn_index(conn);
926 
927 	for (size_t i = 0U; i < ARRAY_SIZE(snks[conn_index]); i++) {
928 		if (snks[conn_index][i] == NULL) {
929 			shell_print(ctx_shell, "Conn: %p, Sink #%zu: ep %p", conn, i, ep);
930 
931 			snks[conn_index][i] = ep;
932 			return;
933 		}
934 	}
935 
936 	shell_error(ctx_shell, "Could not add more sink endpoints");
937 }
938 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
939 
940 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
add_source(const struct bt_conn * conn,struct bt_bap_ep * ep)941 static void add_source(const struct bt_conn *conn, struct bt_bap_ep *ep)
942 {
943 	const uint8_t conn_index = bt_conn_index(conn);
944 
945 	for (size_t i = 0U; i < ARRAY_SIZE(srcs[conn_index]); i++) {
946 		if (srcs[conn_index][i] == NULL) {
947 			shell_print(ctx_shell, "Conn: %p, Source #%zu: ep %p", conn, i, ep);
948 
949 			srcs[conn_index][i] = ep;
950 			return;
951 		}
952 	}
953 
954 	shell_error(ctx_shell, "Could not add more sink endpoints");
955 }
956 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
957 
pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_audio_codec_cap * codec_cap)958 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir,
959 			  const struct bt_audio_codec_cap *codec_cap)
960 {
961 	print_remote_codec_cap(conn, codec_cap, dir);
962 }
963 
endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)964 static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
965 {
966 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
967 	if (dir == BT_AUDIO_DIR_SINK) {
968 		add_sink(conn, ep);
969 	}
970 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
971 
972 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
973 	if (dir == BT_AUDIO_DIR_SOURCE) {
974 		add_source(conn, ep);
975 	}
976 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0*/
977 }
978 
discover_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)979 static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
980 {
981 	shell_print(ctx_shell, "Discover complete: err %d", err);
982 }
983 
discover_all(struct bt_conn * conn,int err,enum bt_audio_dir dir)984 static void discover_all(struct bt_conn *conn, int err, enum bt_audio_dir dir)
985 {
986 	/* Sinks discovery complete, now discover sources */
987 	if (dir == BT_AUDIO_DIR_SINK) {
988 		dir = BT_AUDIO_DIR_SOURCE;
989 		unicast_client_cbs.discover = discover_cb;
990 
991 		err = bt_bap_unicast_client_discover(default_conn, dir);
992 		if (err) {
993 			shell_error(ctx_shell, "bt_bap_unicast_client_discover err %d", err);
994 		}
995 	}
996 }
997 
unicast_client_location_cb(struct bt_conn * conn,enum bt_audio_dir dir,enum bt_audio_location loc)998 static void unicast_client_location_cb(struct bt_conn *conn,
999 				      enum bt_audio_dir dir,
1000 				      enum bt_audio_location loc)
1001 {
1002 	shell_print(ctx_shell, "dir %u loc %X\n", dir, loc);
1003 }
1004 
available_contexts_cb(struct bt_conn * conn,enum bt_audio_context snk_ctx,enum bt_audio_context src_ctx)1005 static void available_contexts_cb(struct bt_conn *conn,
1006 				  enum bt_audio_context snk_ctx,
1007 				  enum bt_audio_context src_ctx)
1008 {
1009 	shell_print(ctx_shell, "snk ctx %u src ctx %u\n", snk_ctx, src_ctx);
1010 }
1011 
config_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)1012 static void config_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
1013 		      enum bt_bap_ascs_reason reason)
1014 {
1015 	shell_print(ctx_shell, "stream %p config operation rsp_code %u reason %u",
1016 		    stream, rsp_code, reason);
1017 
1018 	if (default_stream == NULL) {
1019 		default_stream = stream;
1020 	}
1021 }
1022 
qos_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)1023 static void qos_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
1024 		   enum bt_bap_ascs_reason reason)
1025 {
1026 	shell_print(ctx_shell, "stream %p qos operation rsp_code %u reason %u",
1027 		    stream, rsp_code, reason);
1028 }
1029 
enable_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)1030 static void enable_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
1031 		      enum bt_bap_ascs_reason reason)
1032 {
1033 	shell_print(ctx_shell, "stream %p enable operation rsp_code %u reason %u",
1034 		    stream, rsp_code, reason);
1035 }
1036 
start_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)1037 static void start_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
1038 		     enum bt_bap_ascs_reason reason)
1039 {
1040 	shell_print(ctx_shell, "stream %p start operation rsp_code %u reason %u",
1041 		    stream, rsp_code, reason);
1042 }
1043 
stop_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)1044 static void stop_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
1045 		    enum bt_bap_ascs_reason reason)
1046 {
1047 	shell_print(ctx_shell, "stream %p stop operation rsp_code %u reason %u",
1048 		    stream, rsp_code, reason);
1049 }
1050 
disable_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)1051 static void disable_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
1052 		       enum bt_bap_ascs_reason reason)
1053 {
1054 	shell_print(ctx_shell, "stream %p disable operation rsp_code %u reason %u",
1055 		    stream, rsp_code, reason);
1056 }
1057 
metadata_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)1058 static void metadata_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
1059 			enum bt_bap_ascs_reason reason)
1060 {
1061 	shell_print(ctx_shell, "stream %p metadata operation rsp_code %u reason %u",
1062 		    stream, rsp_code, reason);
1063 }
1064 
release_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)1065 static void release_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
1066 		       enum bt_bap_ascs_reason reason)
1067 {
1068 	shell_print(ctx_shell, "stream %p release operation rsp_code %u reason %u",
1069 		    stream, rsp_code, reason);
1070 }
1071 
1072 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
1073 	.location = unicast_client_location_cb,
1074 	.available_contexts = available_contexts_cb,
1075 	.config = config_cb,
1076 	.qos = qos_cb,
1077 	.enable = enable_cb,
1078 	.start = start_cb,
1079 	.stop = stop_cb,
1080 	.disable = disable_cb,
1081 	.metadata = metadata_cb,
1082 	.release = release_cb,
1083 	.pac_record = pac_record_cb,
1084 	.endpoint = endpoint_cb,
1085 };
1086 
cmd_discover(const struct shell * sh,size_t argc,char * argv[])1087 static int cmd_discover(const struct shell *sh, size_t argc, char *argv[])
1088 {
1089 	static bool cbs_registered;
1090 	enum bt_audio_dir dir;
1091 	uint8_t conn_index;
1092 	int err;
1093 
1094 	if (!default_conn) {
1095 		shell_error(sh, "Not connected");
1096 		return -ENOEXEC;
1097 	}
1098 
1099 	if (!initialized) {
1100 		shell_error(sh, "Not initialized");
1101 		return -ENOEXEC;
1102 	}
1103 
1104 	if (!cbs_registered) {
1105 		err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
1106 
1107 		if (err != 0) {
1108 			shell_error(sh, "Failed to register unicast client callbacks: %d", err);
1109 			return err;
1110 		}
1111 
1112 		cbs_registered = true;
1113 	}
1114 
1115 	unicast_client_cbs.discover = discover_all;
1116 	dir = BT_AUDIO_DIR_SINK;
1117 
1118 	if (argc > 1) {
1119 		if (!strcmp(argv[1], "sink")) {
1120 			unicast_client_cbs.discover = discover_cb;
1121 		} else if (!strcmp(argv[1], "source")) {
1122 			unicast_client_cbs.discover = discover_cb;
1123 			dir = BT_AUDIO_DIR_SOURCE;
1124 		} else {
1125 			shell_error(sh, "Unsupported dir: %s", argv[1]);
1126 			return -ENOEXEC;
1127 		}
1128 	}
1129 
1130 	err = bt_bap_unicast_client_discover(default_conn, dir);
1131 	if (err != 0) {
1132 		return -ENOEXEC;
1133 	}
1134 
1135 	conn_index = bt_conn_index(default_conn);
1136 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
1137 	memset(srcs[conn_index], 0, sizeof(srcs[conn_index]));
1138 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
1139 
1140 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
1141 	memset(snks[conn_index], 0, sizeof(snks[conn_index]));
1142 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
1143 
1144 	return 0;
1145 }
1146 
cmd_config(const struct shell * sh,size_t argc,char * argv[])1147 static int cmd_config(const struct shell *sh, size_t argc, char *argv[])
1148 {
1149 	enum bt_audio_location location = BT_AUDIO_LOCATION_MONO_AUDIO;
1150 	const struct named_lc3_preset *named_preset;
1151 	struct shell_stream *uni_stream;
1152 	struct bt_bap_stream *bap_stream;
1153 	struct bt_bap_ep *ep = NULL;
1154 	enum bt_audio_dir dir;
1155 	unsigned long index;
1156 	uint8_t conn_index;
1157 	int err = 0;
1158 
1159 	if (!default_conn) {
1160 		shell_error(sh, "Not connected");
1161 		return -ENOEXEC;
1162 	}
1163 	conn_index = bt_conn_index(default_conn);
1164 
1165 	if (default_stream == NULL) {
1166 		bap_stream = bap_stream_from_shell_stream(&unicast_streams[0]);
1167 	} else {
1168 		bap_stream = default_stream;
1169 	}
1170 
1171 	index = shell_strtoul(argv[2], 0, &err);
1172 	if (err != 0) {
1173 		shell_error(sh, "Could not parse index: %d", err);
1174 
1175 		return -ENOEXEC;
1176 	}
1177 
1178 	if (index > ARRAY_SIZE(unicast_streams)) {
1179 		shell_error(sh, "Invalid index: %lu", index);
1180 
1181 		return -ENOEXEC;
1182 	}
1183 
1184 	if (false) {
1185 
1186 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
1187 	} else if (!strcmp(argv[1], "sink")) {
1188 		dir = BT_AUDIO_DIR_SINK;
1189 		ep = snks[conn_index][index];
1190 
1191 		named_preset = &default_sink_preset;
1192 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
1193 
1194 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
1195 	} else if (!strcmp(argv[1], "source")) {
1196 		dir = BT_AUDIO_DIR_SOURCE;
1197 		ep = srcs[conn_index][index];
1198 
1199 		named_preset = &default_source_preset;
1200 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
1201 	} else {
1202 		shell_error(sh, "Unsupported dir: %s", argv[1]);
1203 		return -ENOEXEC;
1204 	}
1205 
1206 	if (!ep) {
1207 		shell_error(sh, "Unable to find endpoint");
1208 		return -ENOEXEC;
1209 	}
1210 
1211 	for (size_t i = 3U; i < argc; i++) {
1212 		const char *arg = argv[i];
1213 
1214 		/* argc needs to be larger than `i` to parse the argument value */
1215 		if (argc <= i) {
1216 			shell_help(sh);
1217 
1218 			return SHELL_CMD_HELP_PRINTED;
1219 		}
1220 
1221 		if (strcmp(arg, "loc") == 0) {
1222 			unsigned long loc_bits;
1223 
1224 			arg = argv[++i];
1225 			loc_bits = shell_strtoul(arg, 0, &err);
1226 			if (err != 0) {
1227 				shell_error(sh, "Could not parse loc_bits: %d", err);
1228 
1229 				return -ENOEXEC;
1230 			}
1231 
1232 			if (loc_bits > BT_AUDIO_LOCATION_ANY) {
1233 				shell_error(sh, "Invalid loc_bits: %lu", loc_bits);
1234 
1235 				return -ENOEXEC;
1236 			}
1237 
1238 			location = (enum bt_audio_location)loc_bits;
1239 		} else if (strcmp(arg, "preset") == 0) {
1240 			if (argc > i) {
1241 				arg = argv[++i];
1242 
1243 				named_preset = bap_get_named_preset(true, dir, arg);
1244 				if (named_preset == NULL) {
1245 					shell_error(sh, "Unable to parse named_preset %s", arg);
1246 					return -ENOEXEC;
1247 				}
1248 			} else {
1249 				shell_help(sh);
1250 
1251 				return SHELL_CMD_HELP_PRINTED;
1252 			}
1253 		} else {
1254 			shell_help(sh);
1255 
1256 			return SHELL_CMD_HELP_PRINTED;
1257 		}
1258 	}
1259 
1260 	uni_stream = shell_stream_from_bap_stream(bap_stream);
1261 	copy_unicast_stream_preset(uni_stream, named_preset);
1262 
1263 	/* If location has been modified, we update the location in the codec configuration */
1264 	struct bt_audio_codec_cfg *codec_cfg = &uni_stream->codec_cfg;
1265 
1266 	for (size_t i = 0U; i < codec_cfg->data_len;) {
1267 		const uint8_t len = codec_cfg->data[i++];
1268 		uint8_t *value;
1269 		uint8_t data_len;
1270 		uint8_t type;
1271 
1272 		if (len == 0 || len > codec_cfg->data_len - i) {
1273 			/* Invalid len field */
1274 			return false;
1275 		}
1276 
1277 		type = codec_cfg->data[i++];
1278 		value = &codec_cfg->data[i];
1279 
1280 		if (type == BT_AUDIO_CODEC_CFG_CHAN_ALLOC) {
1281 			const uint32_t loc_32 = location;
1282 
1283 			sys_put_le32(loc_32, value);
1284 
1285 			shell_print(sh, "Setting location to 0x%08X", location);
1286 			break;
1287 		}
1288 
1289 		data_len = len - sizeof(type);
1290 
1291 		/* Since we are incrementing i by the value_len, we don't need to increment
1292 		 * it further in the `for` statement
1293 		 */
1294 		i += data_len;
1295 	}
1296 
1297 	if (bap_stream->ep == ep) {
1298 		err = bt_bap_stream_reconfig(bap_stream, &uni_stream->codec_cfg);
1299 		if (err != 0) {
1300 			shell_error(sh, "Unable reconfig stream: %d", err);
1301 			return -ENOEXEC;
1302 		}
1303 	} else {
1304 		err = bt_bap_stream_config(default_conn, bap_stream, ep,
1305 					   &uni_stream->codec_cfg);
1306 		if (err != 0) {
1307 			shell_error(sh, "Unable to config stream: %d", err);
1308 			return err;
1309 		}
1310 	}
1311 
1312 	shell_print(sh, "ASE config: preset %s", named_preset->name);
1313 
1314 	return 0;
1315 }
1316 
cmd_stream_qos(const struct shell * sh,size_t argc,char * argv[])1317 static int cmd_stream_qos(const struct shell *sh, size_t argc, char *argv[])
1318 {
1319 	struct bt_audio_codec_qos *qos;
1320 	unsigned long interval;
1321 	int err = 0;
1322 
1323 	if (default_stream == NULL) {
1324 		shell_print(sh, "No stream selected");
1325 		return -ENOEXEC;
1326 	}
1327 
1328 	qos = default_stream->qos;
1329 
1330 	if (qos == NULL) {
1331 		shell_print(sh, "Stream not configured");
1332 		return -ENOEXEC;
1333 	}
1334 
1335 	interval = shell_strtoul(argv[1], 0, &err);
1336 	if (err != 0) {
1337 		return -ENOEXEC;
1338 	}
1339 
1340 	if (!IN_RANGE(interval, BT_ISO_SDU_INTERVAL_MIN, BT_ISO_SDU_INTERVAL_MAX)) {
1341 		return -ENOEXEC;
1342 	}
1343 
1344 	qos->interval = interval;
1345 
1346 	if (argc > 2) {
1347 		unsigned long framing;
1348 
1349 		framing = shell_strtoul(argv[2], 0, &err);
1350 		if (err != 0) {
1351 			return -ENOEXEC;
1352 		}
1353 
1354 		if (framing != BT_ISO_FRAMING_UNFRAMED && framing != BT_ISO_FRAMING_FRAMED) {
1355 			return -ENOEXEC;
1356 		}
1357 
1358 		qos->framing = framing;
1359 	}
1360 
1361 	if (argc > 3) {
1362 		unsigned long latency;
1363 
1364 		latency = shell_strtoul(argv[3], 0, &err);
1365 		if (err != 0) {
1366 			return -ENOEXEC;
1367 		}
1368 
1369 		if (!IN_RANGE(latency, BT_ISO_LATENCY_MIN, BT_ISO_LATENCY_MAX)) {
1370 			return -ENOEXEC;
1371 		}
1372 
1373 		qos->latency = latency;
1374 	}
1375 
1376 	if (argc > 4) {
1377 		unsigned long pd;
1378 
1379 		pd = shell_strtoul(argv[4], 0, &err);
1380 		if (err != 0) {
1381 			return -ENOEXEC;
1382 		}
1383 
1384 		if (pd > BT_AUDIO_PD_MAX) {
1385 			return -ENOEXEC;
1386 		}
1387 
1388 		qos->pd = pd;
1389 	}
1390 
1391 	if (argc > 5) {
1392 		unsigned long sdu;
1393 
1394 		sdu = shell_strtoul(argv[5], 0, &err);
1395 		if (err != 0) {
1396 			return -ENOEXEC;
1397 		}
1398 
1399 		if (sdu > BT_ISO_MAX_SDU) {
1400 			return -ENOEXEC;
1401 		}
1402 
1403 		qos->sdu = sdu;
1404 	}
1405 
1406 	if (argc > 6) {
1407 		unsigned long phy;
1408 
1409 		phy = shell_strtoul(argv[6], 0, &err);
1410 		if (err != 0) {
1411 			return -ENOEXEC;
1412 		}
1413 
1414 		if (phy != BT_GAP_LE_PHY_1M && phy != BT_GAP_LE_PHY_2M &&
1415 		    phy != BT_GAP_LE_PHY_CODED) {
1416 			return -ENOEXEC;
1417 		}
1418 
1419 		qos->phy = phy;
1420 	}
1421 
1422 	if (argc > 7) {
1423 		unsigned long rtn;
1424 
1425 		rtn = shell_strtoul(argv[7], 0, &err);
1426 		if (err != 0) {
1427 			return -ENOEXEC;
1428 		}
1429 
1430 		if (rtn > BT_ISO_CONNECTED_RTN_MAX) {
1431 			return -ENOEXEC;
1432 		}
1433 
1434 		qos->rtn = rtn;
1435 	}
1436 
1437 	return 0;
1438 }
1439 
create_unicast_group(const struct shell * sh)1440 static int create_unicast_group(const struct shell *sh)
1441 {
1442 	struct bt_bap_unicast_group_stream_pair_param pair_param[ARRAY_SIZE(unicast_streams)];
1443 	struct bt_bap_unicast_group_stream_param stream_params[ARRAY_SIZE(unicast_streams)];
1444 	struct bt_bap_unicast_group_param group_param;
1445 	size_t source_cnt = 0;
1446 	size_t sink_cnt = 0;
1447 	size_t cnt = 0;
1448 	int err;
1449 
1450 	memset(pair_param, 0, sizeof(pair_param));
1451 	memset(stream_params, 0, sizeof(stream_params));
1452 	memset(&group_param, 0, sizeof(group_param));
1453 
1454 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
1455 		struct bt_bap_stream *stream = bap_stream_from_shell_stream(&unicast_streams[i]);
1456 		struct shell_stream *uni_stream = &unicast_streams[i];
1457 
1458 		if (stream->ep != NULL) {
1459 			struct bt_bap_unicast_group_stream_param *stream_param;
1460 
1461 			stream_param = &stream_params[cnt];
1462 
1463 			stream_param->stream = stream;
1464 			if (stream_dir(stream) == BT_AUDIO_DIR_SINK) {
1465 				stream_param->qos = &uni_stream->qos;
1466 				pair_param[sink_cnt++].tx_param = stream_param;
1467 			} else {
1468 				stream_param->qos = &uni_stream->qos;
1469 				pair_param[source_cnt++].rx_param = stream_param;
1470 			}
1471 
1472 			cnt++;
1473 		}
1474 	}
1475 
1476 	if (cnt == 0U) {
1477 		shell_error(sh, "Stream cnt is 0");
1478 
1479 		return -ENOEXEC;
1480 	}
1481 
1482 	group_param.packing = BT_ISO_PACKING_SEQUENTIAL;
1483 	group_param.params = pair_param;
1484 	group_param.params_count = MAX(source_cnt, sink_cnt);
1485 
1486 	err = bt_bap_unicast_group_create(&group_param,
1487 					    &default_unicast_group);
1488 	if (err != 0) {
1489 		shell_error(sh,
1490 			    "Unable to create default unicast group: %d",
1491 			    err);
1492 
1493 		return -ENOEXEC;
1494 	}
1495 
1496 	return 0;
1497 }
1498 
cmd_qos(const struct shell * sh,size_t argc,char * argv[])1499 static int cmd_qos(const struct shell *sh, size_t argc, char *argv[])
1500 {
1501 	int err;
1502 
1503 	if (default_stream == NULL) {
1504 		shell_print(sh, "No stream selected");
1505 		return -ENOEXEC;
1506 	}
1507 
1508 	if (default_conn == NULL) {
1509 		shell_error(sh, "Not connected");
1510 		return -ENOEXEC;
1511 	}
1512 
1513 	if (default_unicast_group == NULL) {
1514 		err = create_unicast_group(sh);
1515 		if (err != 0) {
1516 			return err;
1517 		}
1518 	}
1519 
1520 	err = bt_bap_stream_qos(default_conn, default_unicast_group);
1521 	if (err) {
1522 		shell_error(sh, "Unable to setup QoS: %d", err);
1523 		return -ENOEXEC;
1524 	}
1525 
1526 	return 0;
1527 }
1528 
cmd_enable(const struct shell * sh,size_t argc,char * argv[])1529 static int cmd_enable(const struct shell *sh, size_t argc, char *argv[])
1530 {
1531 	struct bt_audio_codec_cfg *codec_cfg;
1532 	int err;
1533 
1534 	if (default_stream == NULL) {
1535 		shell_error(sh, "No stream selected");
1536 		return -ENOEXEC;
1537 	}
1538 
1539 	codec_cfg = default_stream->codec_cfg;
1540 
1541 	if (argc > 1) {
1542 		err = set_metadata(codec_cfg, argv[1]);
1543 		if (err != 0) {
1544 			shell_error(sh, "Unable to handle metadata update: %d", err);
1545 			return err;
1546 		}
1547 	}
1548 
1549 	err = bt_bap_stream_enable(default_stream, codec_cfg->meta, codec_cfg->meta_len);
1550 	if (err) {
1551 		shell_error(sh, "Unable to enable Channel");
1552 		return -ENOEXEC;
1553 	}
1554 
1555 	return 0;
1556 }
1557 
cmd_stop(const struct shell * sh,size_t argc,char * argv[])1558 static int cmd_stop(const struct shell *sh, size_t argc, char *argv[])
1559 {
1560 	int err;
1561 
1562 	if (default_stream == NULL) {
1563 		shell_error(sh, "No stream selected");
1564 		return -ENOEXEC;
1565 	}
1566 
1567 	err = bt_bap_stream_stop(default_stream);
1568 	if (err) {
1569 		shell_error(sh, "Unable to stop Channel");
1570 		return -ENOEXEC;
1571 	}
1572 
1573 	return 0;
1574 }
1575 
cmd_connect(const struct shell * sh,size_t argc,char * argv[])1576 static int cmd_connect(const struct shell *sh, size_t argc, char *argv[])
1577 {
1578 	int err;
1579 
1580 	if (default_stream == NULL) {
1581 		shell_error(sh, "No stream selected");
1582 		return -ENOEXEC;
1583 	}
1584 
1585 	err = bt_bap_stream_connect(default_stream);
1586 	if (err) {
1587 		shell_error(sh, "Unable to connect stream");
1588 		return -ENOEXEC;
1589 	}
1590 
1591 	return 0;
1592 }
1593 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1594 
cmd_metadata(const struct shell * sh,size_t argc,char * argv[])1595 static int cmd_metadata(const struct shell *sh, size_t argc, char *argv[])
1596 {
1597 	struct bt_audio_codec_cfg *codec_cfg;
1598 	int err;
1599 
1600 	if (default_stream == NULL) {
1601 		shell_error(sh, "No stream selected");
1602 		return -ENOEXEC;
1603 	}
1604 
1605 	codec_cfg = default_stream->codec_cfg;
1606 
1607 	if (argc > 1) {
1608 		err = set_metadata(codec_cfg, argv[1]);
1609 		if (err != 0) {
1610 			shell_error(sh, "Unable to handle metadata update: %d", err);
1611 			return err;
1612 		}
1613 	}
1614 
1615 	err = bt_bap_stream_metadata(default_stream, codec_cfg->meta, codec_cfg->meta_len);
1616 	if (err) {
1617 		shell_error(sh, "Unable to set Channel metadata");
1618 		return -ENOEXEC;
1619 	}
1620 
1621 	return 0;
1622 }
1623 
cmd_start(const struct shell * sh,size_t argc,char * argv[])1624 static int cmd_start(const struct shell *sh, size_t argc, char *argv[])
1625 {
1626 	int err;
1627 
1628 	if (default_stream == NULL) {
1629 		shell_error(sh, "No stream selected");
1630 		return -ENOEXEC;
1631 	}
1632 
1633 	err = bt_bap_stream_start(default_stream);
1634 	if (err) {
1635 		shell_error(sh, "Unable to start Channel");
1636 		return -ENOEXEC;
1637 	}
1638 
1639 	return 0;
1640 }
1641 
cmd_disable(const struct shell * sh,size_t argc,char * argv[])1642 static int cmd_disable(const struct shell *sh, size_t argc, char *argv[])
1643 {
1644 	int err;
1645 
1646 	if (default_stream == NULL) {
1647 		shell_error(sh, "No stream selected");
1648 		return -ENOEXEC;
1649 	}
1650 
1651 	err = bt_bap_stream_disable(default_stream);
1652 	if (err) {
1653 		shell_error(sh, "Unable to disable Channel");
1654 		return -ENOEXEC;
1655 	}
1656 
1657 	return 0;
1658 }
1659 
1660 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
conn_list_eps(struct bt_conn * conn,void * data)1661 static void conn_list_eps(struct bt_conn *conn, void *data)
1662 {
1663 	const struct shell *sh = (const struct shell *)data;
1664 	uint8_t conn_index = bt_conn_index(conn);
1665 
1666 	shell_print(sh, "Conn: %p", conn);
1667 	shell_print(sh, "  Sinks:");
1668 
1669 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
1670 	for (size_t i = 0U; i < ARRAY_SIZE(snks[conn_index]); i++) {
1671 		const struct bt_bap_ep *ep = snks[conn_index][i];
1672 
1673 		if (ep != NULL) {
1674 			struct bt_bap_ep_info ep_info;
1675 			int err;
1676 
1677 			err = bt_bap_ep_get_info(ep, &ep_info);
1678 			if (err == 0) {
1679 				shell_print(sh, "    #%u: ep %p (state: %d)", i, ep, ep_info.state);
1680 			}
1681 		}
1682 	}
1683 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
1684 
1685 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
1686 	shell_print(sh, "  Sources:");
1687 
1688 	for (size_t i = 0U; i < ARRAY_SIZE(srcs[conn_index]); i++) {
1689 		const struct bt_bap_ep *ep = srcs[conn_index][i];
1690 
1691 		if (ep != NULL) {
1692 			struct bt_bap_ep_info ep_info;
1693 			int err;
1694 
1695 			err = bt_bap_ep_get_info(ep, &ep_info);
1696 			if (err == 0) {
1697 				shell_print(sh, "    #%u: ep %p (state: %d)", i, ep, ep_info.state);
1698 			}
1699 		}
1700 	}
1701 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
1702 }
1703 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1704 
1705 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
cmd_list(const struct shell * sh,size_t argc,char * argv[])1706 static int cmd_list(const struct shell *sh, size_t argc, char *argv[])
1707 {
1708 	shell_print(sh, "Configured Channels:");
1709 
1710 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
1711 		struct bt_bap_stream *stream = &unicast_streams[i].stream.bap_stream;
1712 
1713 		if (stream != NULL && stream->conn != NULL) {
1714 			shell_print(sh, "  %s#%u: stream %p dir 0x%02x group %p",
1715 				    stream == default_stream ? "*" : " ", i, stream,
1716 				    stream_dir(stream), stream->group);
1717 		}
1718 	}
1719 
1720 	bt_conn_foreach(BT_CONN_TYPE_LE, conn_list_eps, (void *)sh);
1721 
1722 	return 0;
1723 }
1724 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1725 
cmd_release(const struct shell * sh,size_t argc,char * argv[])1726 static int cmd_release(const struct shell *sh, size_t argc, char *argv[])
1727 {
1728 	int err;
1729 
1730 	if (default_stream == NULL) {
1731 		shell_print(sh, "No stream selected");
1732 		return -ENOEXEC;
1733 	}
1734 
1735 	err = bt_bap_stream_release(default_stream);
1736 	if (err) {
1737 		shell_error(sh, "Unable to release Channel");
1738 		return -ENOEXEC;
1739 	}
1740 
1741 	return 0;
1742 }
1743 #endif /* CONFIG_BT_BAP_UNICAST */
1744 
1745 #if IS_BAP_INITIATOR
parse_config_data_args(const struct shell * sh,size_t argn,size_t argc,char * argv[],struct bt_audio_codec_cfg * codec_cfg)1746 static ssize_t parse_config_data_args(const struct shell *sh, size_t argn, size_t argc,
1747 				      char *argv[], struct bt_audio_codec_cfg *codec_cfg)
1748 {
1749 	for (; argn < argc; argn++) {
1750 		const char *arg = argv[argn];
1751 		unsigned long val;
1752 		int err = 0;
1753 
1754 		if (strcmp(arg, "freq") == 0) {
1755 			if (++argn == argc) {
1756 				shell_help(sh);
1757 
1758 				return -1;
1759 			}
1760 
1761 			arg = argv[argn];
1762 
1763 			val = shell_strtoul(arg, 0, &err);
1764 			if (err != 0) {
1765 				shell_error(sh, "Failed to parse freq from %s: %d", arg, err);
1766 
1767 				return -1;
1768 			}
1769 
1770 			if (val > UINT8_MAX) {
1771 				shell_error(sh, "Invalid freq value: %lu", val);
1772 
1773 				return -1;
1774 			}
1775 
1776 			err = bt_audio_codec_cfg_set_freq(codec_cfg,
1777 							  (enum bt_audio_codec_cfg_freq)val);
1778 			if (err < 0) {
1779 				shell_error(sh, "Failed to set freq with value %lu: %d", val, err);
1780 
1781 				return -1;
1782 			}
1783 		} else if (strcmp(arg, "dur") == 0) {
1784 			if (++argn == argc) {
1785 				shell_help(sh);
1786 
1787 				return -1;
1788 			}
1789 
1790 			arg = argv[argn];
1791 
1792 			val = shell_strtoul(arg, 0, &err);
1793 			if (err != 0) {
1794 				shell_error(sh, "Failed to parse dur from %s: %d", arg, err);
1795 
1796 				return -1;
1797 			}
1798 
1799 			if (val > UINT8_MAX) {
1800 				shell_error(sh, "Invalid dur value: %lu", val);
1801 
1802 				return -1;
1803 			}
1804 
1805 			err = bt_audio_codec_cfg_set_frame_dur(
1806 				codec_cfg, (enum bt_audio_codec_cfg_frame_dur)val);
1807 			if (err < 0) {
1808 				shell_error(sh, "Failed to set dur with value %lu: %d", val, err);
1809 
1810 				return -1;
1811 			}
1812 		} else if (strcmp(arg, "chan_alloc") == 0) {
1813 			if (++argn == argc) {
1814 				shell_help(sh);
1815 
1816 				return -1;
1817 			}
1818 
1819 			arg = argv[argn];
1820 
1821 			val = shell_strtoul(arg, 0, &err);
1822 			if (err != 0) {
1823 				shell_error(sh, "Failed to parse chan alloc from %s: %d", arg, err);
1824 
1825 				return -1;
1826 			}
1827 
1828 			if (val > UINT32_MAX) {
1829 				shell_error(sh, "Invalid chan alloc value: %lu", val);
1830 
1831 				return -1;
1832 			}
1833 
1834 			err = bt_audio_codec_cfg_set_chan_allocation(codec_cfg,
1835 								     (enum bt_audio_location)val);
1836 			if (err < 0) {
1837 				shell_error(sh, "Failed to set chan alloc with value %lu: %d", val,
1838 					    err);
1839 
1840 				return -1;
1841 			}
1842 		} else if (strcmp(arg, "frame_len") == 0) {
1843 			if (++argn == argc) {
1844 				shell_help(sh);
1845 
1846 				return -1;
1847 			}
1848 
1849 			arg = argv[argn];
1850 
1851 			val = shell_strtoul(arg, 0, &err);
1852 			if (err != 0) {
1853 				shell_error(sh, "Failed to frame len from %s: %d", arg, err);
1854 
1855 				return -1;
1856 			}
1857 
1858 			if (val > UINT16_MAX) {
1859 				shell_error(sh, "Invalid frame len value: %lu", val);
1860 
1861 				return -1;
1862 			}
1863 
1864 			err = bt_audio_codec_cfg_set_octets_per_frame(codec_cfg, (uint16_t)val);
1865 			if (err < 0) {
1866 				shell_error(sh, "Failed to set frame len with value %lu: %d", val,
1867 					    err);
1868 
1869 				return -1;
1870 			}
1871 		} else if (strcmp(arg, "frame_blks") == 0) {
1872 			if (++argn == argc) {
1873 				shell_help(sh);
1874 
1875 				return -1;
1876 			}
1877 
1878 			arg = argv[argn];
1879 
1880 			val = shell_strtoul(arg, 0, &err);
1881 			if (err != 0) {
1882 				shell_error(sh, "Failed to parse frame blks from %s: %d", arg, err);
1883 
1884 				return -1;
1885 			}
1886 
1887 			if (val > UINT8_MAX) {
1888 				shell_error(sh, "Invalid frame blks value: %lu", val);
1889 
1890 				return -1;
1891 			}
1892 
1893 			err = bt_audio_codec_cfg_set_frame_blocks_per_sdu(codec_cfg, (uint8_t)val);
1894 			if (err < 0) {
1895 				shell_error(sh, "Failed to set frame blks with value %lu: %d", val,
1896 					    err);
1897 
1898 				return -1;
1899 			}
1900 		} else { /* we are no longer parsing codec config values */
1901 			/* Decrement to return taken argument */
1902 			argn--;
1903 			break;
1904 		}
1905 	}
1906 
1907 	return argn;
1908 }
1909 
parse_config_meta_args(const struct shell * sh,size_t argn,size_t argc,char * argv[],struct bt_audio_codec_cfg * codec_cfg)1910 static ssize_t parse_config_meta_args(const struct shell *sh, size_t argn, size_t argc,
1911 				      char *argv[], struct bt_audio_codec_cfg *codec_cfg)
1912 {
1913 	for (; argn < argc; argn++) {
1914 		const char *arg = argv[argn];
1915 		unsigned long val;
1916 		int err = 0;
1917 
1918 		if (strcmp(arg, "pref_ctx") == 0) {
1919 			if (++argn == argc) {
1920 				shell_help(sh);
1921 
1922 				return -1;
1923 			}
1924 
1925 			arg = argv[argn];
1926 
1927 			val = shell_strtoul(arg, 0, &err);
1928 			if (err != 0) {
1929 				shell_error(sh, "Failed to parse pref ctx from %s: %d", arg, err);
1930 
1931 				return -1;
1932 			}
1933 
1934 			if (val > UINT16_MAX) {
1935 				shell_error(sh, "Invalid pref ctx value: %lu", val);
1936 
1937 				return -1;
1938 			}
1939 
1940 			err = bt_audio_codec_cfg_meta_set_pref_context(codec_cfg,
1941 								       (enum bt_audio_context)val);
1942 			if (err < 0) {
1943 				shell_error(sh, "Failed to set pref ctx with value %lu: %d", val,
1944 					    err);
1945 
1946 				return -1;
1947 			}
1948 		} else if (strcmp(arg, "stream_ctx") == 0) {
1949 			if (++argn == argc) {
1950 				shell_help(sh);
1951 
1952 				return -1;
1953 			}
1954 
1955 			arg = argv[argn];
1956 
1957 			val = shell_strtoul(arg, 0, &err);
1958 			if (err != 0) {
1959 				shell_error(sh, "Failed to parse stream ctx from %s: %d", arg, err);
1960 
1961 				return -1;
1962 			}
1963 
1964 			if (val > UINT16_MAX) {
1965 				shell_error(sh, "Invalid stream ctx value: %lu", val);
1966 
1967 				return -1;
1968 			}
1969 
1970 			err = bt_audio_codec_cfg_meta_set_stream_context(
1971 				codec_cfg, (enum bt_audio_context)val);
1972 			if (err < 0) {
1973 				shell_error(sh, "Failed to set stream ctx with value %lu: %d", val,
1974 					    err);
1975 
1976 				return -1;
1977 			}
1978 		} else if (strcmp(arg, "program_info") == 0) {
1979 			if (++argn == argc) {
1980 				shell_help(sh);
1981 
1982 				return -1;
1983 			}
1984 
1985 			arg = argv[argn];
1986 
1987 			err = bt_audio_codec_cfg_meta_set_program_info(codec_cfg, arg, strlen(arg));
1988 			if (err != 0) {
1989 				shell_error(sh, "Failed to set program info with value %s: %d", arg,
1990 					    err);
1991 
1992 				return -1;
1993 			}
1994 		} else if (strcmp(arg, "lang") == 0) {
1995 			if (++argn == argc) {
1996 				shell_help(sh);
1997 
1998 				return -1;
1999 			}
2000 
2001 			arg = argv[argn];
2002 
2003 			if (strlen(arg) != BT_AUDIO_LANG_SIZE) {
2004 				shell_error(sh, "Failed to parse lang from %s", arg);
2005 
2006 				return -1;
2007 			}
2008 
2009 			err = bt_audio_codec_cfg_meta_set_lang(codec_cfg, arg);
2010 			if (err < 0) {
2011 				shell_error(sh, "Failed to set lang with value %s: %d", arg, err);
2012 
2013 				return -1;
2014 			}
2015 		} else if (strcmp(arg, "ccid_list") == 0) {
2016 			uint8_t ccid_list[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE];
2017 			size_t ccid_list_len;
2018 
2019 			if (++argn == argc) {
2020 				shell_help(sh);
2021 
2022 				return -1;
2023 			}
2024 
2025 			arg = argv[argn];
2026 
2027 			ccid_list_len = hex2bin(arg, strlen(arg), ccid_list, sizeof(ccid_list));
2028 			if (ccid_list_len == 0) {
2029 				shell_error(sh, "Failed to parse ccid list from %s", arg);
2030 
2031 				return -1;
2032 			}
2033 
2034 			err = bt_audio_codec_cfg_meta_set_ccid_list(codec_cfg, ccid_list,
2035 								    ccid_list_len);
2036 			if (err < 0) {
2037 				shell_error(sh, "Failed to set ccid list with value %s: %d", arg,
2038 					    err);
2039 
2040 				return -1;
2041 			}
2042 		} else if (strcmp(arg, "parental_rating") == 0) {
2043 			if (++argn == argc) {
2044 				shell_help(sh);
2045 
2046 				return -1;
2047 			}
2048 
2049 			arg = argv[argn];
2050 
2051 			val = shell_strtoul(arg, 0, &err);
2052 			if (err != 0) {
2053 				shell_error(sh, "Failed to parse parental rating from %s: %d", arg,
2054 					    err);
2055 
2056 				return -1;
2057 			}
2058 
2059 			if (val > UINT8_MAX) {
2060 				shell_error(sh, "Invalid parental rating value: %lu", val);
2061 
2062 				return -1;
2063 			}
2064 
2065 			err = bt_audio_codec_cfg_meta_set_parental_rating(
2066 				codec_cfg, (enum bt_audio_parental_rating)val);
2067 			if (err < 0) {
2068 				shell_error(sh, "Failed to set parental rating with value %lu: %d",
2069 					    val, err);
2070 
2071 				return -1;
2072 			}
2073 		} else if (strcmp(arg, "program_info_uri") == 0) {
2074 			if (++argn == argc) {
2075 				shell_help(sh);
2076 
2077 				return -1;
2078 			}
2079 
2080 			arg = argv[argn];
2081 
2082 			err = bt_audio_codec_cfg_meta_set_program_info_uri(codec_cfg, arg,
2083 									   strlen(arg));
2084 			if (err < 0) {
2085 				shell_error(sh, "Failed to set program info URI with value %s: %d",
2086 					    arg, err);
2087 
2088 				return -1;
2089 			}
2090 		} else if (strcmp(arg, "audio_active_state") == 0) {
2091 			if (++argn == argc) {
2092 				shell_help(sh);
2093 
2094 				return -1;
2095 			}
2096 
2097 			arg = argv[argn];
2098 
2099 			val = shell_strtoul(arg, 0, &err);
2100 			if (err != 0) {
2101 				shell_error(sh, "Failed to parse audio active state from %s: %d",
2102 					    arg, err);
2103 
2104 				return -1;
2105 			}
2106 
2107 			if (val > UINT8_MAX) {
2108 				shell_error(sh, "Invalid audio active state value: %lu", val);
2109 
2110 				return -1;
2111 			}
2112 
2113 			err = bt_audio_codec_cfg_meta_set_audio_active_state(
2114 				codec_cfg, (enum bt_audio_active_state)val);
2115 			if (err < 0) {
2116 				shell_error(sh,
2117 					    "Failed to set audio active state with value %lu: %d",
2118 					    val, err);
2119 
2120 				return -1;
2121 			}
2122 		} else if (strcmp(arg, "bcast_flag") == 0) {
2123 			err = bt_audio_codec_cfg_meta_set_bcast_audio_immediate_rend_flag(
2124 				codec_cfg);
2125 			if (err < 0) {
2126 				shell_error(sh, "Failed to set audio active state: %d", err);
2127 
2128 				return -1;
2129 			}
2130 		} else if (strcmp(arg, "extended") == 0) {
2131 			uint8_t extended[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE];
2132 			size_t extended_len;
2133 
2134 			if (++argn == argc) {
2135 				shell_help(sh);
2136 
2137 				return -1;
2138 			}
2139 
2140 			arg = argv[argn];
2141 
2142 			extended_len = hex2bin(arg, strlen(arg), extended, sizeof(extended));
2143 			if (extended_len == 0) {
2144 				shell_error(sh, "Failed to parse extended meta from %s", arg);
2145 
2146 				return -1;
2147 			}
2148 
2149 			err = bt_audio_codec_cfg_meta_set_extended(codec_cfg, extended,
2150 								   extended_len);
2151 			if (err < 0) {
2152 				shell_error(sh, "Failed to set extended meta with value %s: %d",
2153 					    arg, err);
2154 
2155 				return -1;
2156 			}
2157 		} else if (strcmp(arg, "vendor") == 0) {
2158 			uint8_t vendor[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE];
2159 			size_t vendor_len;
2160 
2161 			if (++argn == argc) {
2162 				shell_help(sh);
2163 
2164 				return -1;
2165 			}
2166 
2167 			arg = argv[argn];
2168 
2169 			vendor_len = hex2bin(arg, strlen(arg), vendor, sizeof(vendor));
2170 			if (vendor_len == 0) {
2171 				shell_error(sh, "Failed to parse vendor meta from %s", arg);
2172 
2173 				return -1;
2174 			}
2175 
2176 			err = bt_audio_codec_cfg_meta_set_vendor(codec_cfg, vendor, vendor_len);
2177 			if (err < 0) {
2178 				shell_error(sh, "Failed to set vendor meta with value %s: %d", arg,
2179 					    err);
2180 
2181 				return -1;
2182 			}
2183 		} else { /* we are no longer parsing codec config meta values */
2184 			/* Decrement to return taken argument */
2185 			argn--;
2186 			break;
2187 		}
2188 	}
2189 
2190 	return argn;
2191 }
2192 
cmd_preset(const struct shell * sh,size_t argc,char * argv[])2193 static int cmd_preset(const struct shell *sh, size_t argc, char *argv[])
2194 {
2195 	const struct named_lc3_preset *named_preset;
2196 	enum bt_audio_dir dir;
2197 	bool unicast = true;
2198 
2199 	if (!strcmp(argv[1], "sink")) {
2200 		dir = BT_AUDIO_DIR_SINK;
2201 		named_preset = &default_sink_preset;
2202 	} else if (!strcmp(argv[1], "source")) {
2203 		dir = BT_AUDIO_DIR_SOURCE;
2204 		named_preset = &default_source_preset;
2205 	} else if (!strcmp(argv[1], "broadcast")) {
2206 		unicast = false;
2207 		dir = BT_AUDIO_DIR_SOURCE;
2208 
2209 		named_preset = &default_broadcast_source_preset;
2210 	} else {
2211 		shell_error(sh, "Unsupported dir: %s", argv[1]);
2212 		return -ENOEXEC;
2213 	}
2214 
2215 	if (argc > 2) {
2216 		struct bt_audio_codec_cfg *codec_cfg;
2217 
2218 		named_preset = bap_get_named_preset(unicast, dir, argv[2]);
2219 		if (named_preset == NULL) {
2220 			shell_error(sh, "Unable to parse named_preset %s", argv[2]);
2221 			return -ENOEXEC;
2222 		}
2223 
2224 		if (!strcmp(argv[1], "sink")) {
2225 			named_preset = memcpy(&default_sink_preset, named_preset,
2226 					      sizeof(default_sink_preset));
2227 			codec_cfg = &default_sink_preset.preset.codec_cfg;
2228 		} else if (!strcmp(argv[1], "source")) {
2229 			named_preset = memcpy(&default_source_preset, named_preset,
2230 					      sizeof(default_sink_preset));
2231 			codec_cfg = &default_source_preset.preset.codec_cfg;
2232 		} else if (!strcmp(argv[1], "broadcast")) {
2233 			named_preset = memcpy(&default_broadcast_source_preset, named_preset,
2234 					      sizeof(default_sink_preset));
2235 			codec_cfg = &default_broadcast_source_preset.preset.codec_cfg;
2236 		} else {
2237 			shell_error(sh, "Invalid dir: %s", argv[1]);
2238 
2239 			return -ENOEXEC;
2240 		}
2241 
2242 		if (argc > 3) {
2243 			struct bt_audio_codec_cfg codec_cfg_backup;
2244 
2245 			memcpy(&codec_cfg_backup, codec_cfg, sizeof(codec_cfg_backup));
2246 
2247 			for (size_t argn = 3; argn < argc; argn++) {
2248 				const char *arg = argv[argn];
2249 
2250 				if (strcmp(arg, "config") == 0) {
2251 					ssize_t ret;
2252 
2253 					if (++argn == argc) {
2254 						shell_help(sh);
2255 
2256 						memcpy(codec_cfg, &codec_cfg_backup,
2257 						       sizeof(codec_cfg_backup));
2258 
2259 						return SHELL_CMD_HELP_PRINTED;
2260 					}
2261 
2262 					ret = parse_config_data_args(sh, argn, argc, argv,
2263 								     codec_cfg);
2264 					if (ret < 0) {
2265 						memcpy(codec_cfg, &codec_cfg_backup,
2266 						       sizeof(codec_cfg_backup));
2267 
2268 						return -ENOEXEC;
2269 					}
2270 
2271 					argn = ret;
2272 				} else if (strcmp(arg, "meta") == 0) {
2273 					ssize_t ret;
2274 
2275 					if (++argn == argc) {
2276 						shell_help(sh);
2277 
2278 						memcpy(codec_cfg, &codec_cfg_backup,
2279 						       sizeof(codec_cfg_backup));
2280 
2281 						return SHELL_CMD_HELP_PRINTED;
2282 					}
2283 
2284 					ret = parse_config_meta_args(sh, argn, argc, argv,
2285 								     codec_cfg);
2286 					if (ret < 0) {
2287 						memcpy(codec_cfg, &codec_cfg_backup,
2288 						       sizeof(codec_cfg_backup));
2289 
2290 						return -ENOEXEC;
2291 					}
2292 
2293 					argn = ret;
2294 				} else {
2295 					shell_error(sh, "Invalid argument: %s", arg);
2296 					shell_help(sh);
2297 
2298 					return -ENOEXEC;
2299 				}
2300 			}
2301 		}
2302 	}
2303 
2304 	shell_print(sh, "%s", named_preset->name);
2305 
2306 	print_codec_cfg(ctx_shell, 0, &named_preset->preset.codec_cfg);
2307 	print_qos(ctx_shell, &named_preset->preset.qos);
2308 
2309 	return 0;
2310 }
2311 #endif /* IS_BAP_INITIATOR */
2312 
2313 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
2314 #define INVALID_BROADCAST_ID (BT_AUDIO_BROADCAST_ID_MAX + 1)
2315 #define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 20 /* Set the timeout relative to interval */
2316 #define PA_SYNC_SKIP         5
2317 
2318 static struct broadcast_sink_auto_scan {
2319 	struct broadcast_sink *broadcast_sink;
2320 	uint32_t broadcast_id;
2321 	struct bt_le_per_adv_sync **out_sync;
2322 } auto_scan = {
2323 	.broadcast_id = INVALID_BROADCAST_ID,
2324 };
2325 
clear_auto_scan(void)2326 static void clear_auto_scan(void)
2327 {
2328 	if (auto_scan.broadcast_id != INVALID_BROADCAST_ID) {
2329 		memset(&auto_scan, 0, sizeof(auto_scan));
2330 		auto_scan.broadcast_id = INVALID_BROADCAST_ID;
2331 	}
2332 }
2333 
interval_to_sync_timeout(uint16_t interval)2334 static uint16_t interval_to_sync_timeout(uint16_t interval)
2335 {
2336 	uint32_t interval_ms;
2337 	uint32_t timeout;
2338 
2339 	/* Add retries and convert to unit in 10's of ms */
2340 	interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(interval);
2341 	timeout = (interval_ms * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO) / 10;
2342 
2343 	/* Enforce restraints */
2344 	timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT);
2345 
2346 	return (uint16_t)timeout;
2347 }
2348 
scan_check_and_sync_broadcast(struct bt_data * data,void * user_data)2349 static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data)
2350 {
2351 	const struct bt_le_scan_recv_info *info = user_data;
2352 	char le_addr[BT_ADDR_LE_STR_LEN];
2353 	struct bt_uuid_16 adv_uuid;
2354 	uint32_t broadcast_id;
2355 
2356 	if (data->type != BT_DATA_SVC_DATA16) {
2357 		return true;
2358 	}
2359 
2360 	if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) {
2361 		return true;
2362 	}
2363 
2364 	if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) {
2365 		return true;
2366 	}
2367 
2368 	if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) {
2369 		return true;
2370 	}
2371 
2372 	broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16);
2373 
2374 	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
2375 
2376 	shell_print(ctx_shell,
2377 		    "Found broadcaster with ID 0x%06X and addr %s and sid 0x%02X (looking for "
2378 		    "0x%06X)",
2379 		    broadcast_id, le_addr, info->sid, auto_scan.broadcast_id);
2380 
2381 	if (auto_scan.broadcast_id == broadcast_id && auto_scan.broadcast_sink != NULL &&
2382 	    auto_scan.broadcast_sink->pa_sync == NULL) {
2383 		struct bt_le_per_adv_sync_param create_params = {0};
2384 		int err;
2385 
2386 		err = bt_le_scan_stop();
2387 		if (err != 0) {
2388 			shell_error(ctx_shell, "Could not stop scan: %d", err);
2389 		}
2390 
2391 		bt_addr_le_copy(&create_params.addr, info->addr);
2392 		create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE;
2393 		create_params.sid = info->sid;
2394 		create_params.skip = PA_SYNC_SKIP;
2395 		create_params.timeout = interval_to_sync_timeout(info->interval);
2396 
2397 		shell_print(ctx_shell, "Attempting to PA sync to the broadcaster");
2398 		err = bt_le_per_adv_sync_create(&create_params, auto_scan.out_sync);
2399 		if (err != 0) {
2400 			shell_error(ctx_shell, "Could not create Broadcast PA sync: %d", err);
2401 		} else {
2402 			auto_scan.broadcast_sink->pa_sync = *auto_scan.out_sync;
2403 		}
2404 	}
2405 
2406 	/* Stop parsing */
2407 	return false;
2408 }
2409 
broadcast_scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * ad)2410 static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad)
2411 {
2412 	if (passes_scan_filter(info, ad)) {
2413 		bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)info);
2414 	}
2415 }
2416 
base_recv(struct bt_bap_broadcast_sink * sink,const struct bt_bap_base * base,size_t base_size)2417 static void base_recv(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base,
2418 		      size_t base_size)
2419 {
2420 	/* Don't print duplicates */
2421 	if (base_size != default_broadcast_sink.base_size ||
2422 	    memcmp(base, &default_broadcast_sink.received_base, base_size) != 0) {
2423 		shell_print(ctx_shell, "Received BASE from sink %p:", sink);
2424 		(void)memcpy(&default_broadcast_sink.received_base, base, base_size);
2425 		default_broadcast_sink.base_size = base_size;
2426 
2427 		print_base(base);
2428 	}
2429 }
2430 
syncable(struct bt_bap_broadcast_sink * sink,const struct bt_iso_biginfo * biginfo)2431 static void syncable(struct bt_bap_broadcast_sink *sink, const struct bt_iso_biginfo *biginfo)
2432 {
2433 	if (default_broadcast_sink.bap_sink == sink) {
2434 		if (default_broadcast_sink.syncable) {
2435 			return;
2436 		}
2437 
2438 		shell_print(ctx_shell, "Sink %p is ready to sync %s encryption", sink,
2439 			    biginfo->encryption ? "with" : "without");
2440 		default_broadcast_sink.syncable = true;
2441 	}
2442 }
2443 
bap_pa_sync_synced_cb(struct bt_le_per_adv_sync * sync,struct bt_le_per_adv_sync_synced_info * info)2444 static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync,
2445 				  struct bt_le_per_adv_sync_synced_info *info)
2446 {
2447 	if (auto_scan.broadcast_sink != NULL && auto_scan.out_sync != NULL &&
2448 	    sync == *auto_scan.out_sync) {
2449 		shell_print(ctx_shell, "PA synced to broadcast with broadcast ID 0x%06x",
2450 			    auto_scan.broadcast_id);
2451 
2452 		if (auto_scan.broadcast_sink->bap_sink == NULL) {
2453 			shell_print(ctx_shell, "Attempting to create the sink");
2454 			int err;
2455 
2456 			err = bt_bap_broadcast_sink_create(sync, auto_scan.broadcast_id,
2457 							   &auto_scan.broadcast_sink->bap_sink);
2458 			if (err != 0) {
2459 				shell_error(ctx_shell, "Could not create broadcast sink: %d", err);
2460 			}
2461 		} else {
2462 			shell_print(ctx_shell, "Sink is already created");
2463 		}
2464 	}
2465 
2466 	clear_auto_scan();
2467 }
2468 
bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_term_info * info)2469 static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync,
2470 				      const struct bt_le_per_adv_sync_term_info *info)
2471 {
2472 	if (default_broadcast_sink.pa_sync == sync) {
2473 		default_broadcast_sink.syncable = false;
2474 		(void)memset(&default_broadcast_sink.received_base, 0,
2475 			     sizeof(default_broadcast_sink.received_base));
2476 	}
2477 
2478 	clear_auto_scan();
2479 }
2480 
broadcast_scan_timeout_cb(void)2481 static void broadcast_scan_timeout_cb(void)
2482 {
2483 	shell_print(ctx_shell, "Scan timeout");
2484 
2485 	clear_auto_scan();
2486 }
2487 
2488 static struct bt_bap_broadcast_sink_cb sink_cbs = {
2489 	.base_recv = base_recv,
2490 	.syncable = syncable,
2491 };
2492 
2493 static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = {
2494 	.synced = bap_pa_sync_synced_cb,
2495 	.term = bap_pa_sync_terminated_cb,
2496 };
2497 
2498 static struct bt_le_scan_cb bap_scan_cb = {
2499 	.timeout = broadcast_scan_timeout_cb,
2500 	.recv = broadcast_scan_recv,
2501 };
2502 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
2503 
2504 #if defined(CONFIG_BT_AUDIO_RX)
2505 static size_t rx_streaming_cnt;
2506 
bap_get_rx_streaming_cnt(void)2507 size_t bap_get_rx_streaming_cnt(void)
2508 {
2509 	return rx_streaming_cnt;
2510 }
2511 
2512 #if defined(CONFIG_LIBLC3)
2513 struct lc3_data {
2514 	void *fifo_reserved; /* 1st word reserved for use by FIFO */
2515 	struct net_buf *buf;
2516 	struct shell_stream *sh_stream;
2517 	uint32_t ts;
2518 	bool do_plc;
2519 };
2520 
2521 K_MEM_SLAB_DEFINE(lc3_data_slab, sizeof(struct lc3_data), CONFIG_BT_ISO_RX_BUF_COUNT,
2522 		  __alignof__(struct lc3_data));
2523 
2524 static int16_t lc3_rx_buf[LC3_MAX_NUM_SAMPLES_MONO];
2525 static K_FIFO_DEFINE(lc3_in_fifo);
2526 
2527 /* We only want to send USB to left/right from a single stream. If we have 2 left streams, the
2528  * outgoing audio is going to be terrible.
2529  * Since a stream can contain stereo data, both of these may be the same stream.
2530  */
2531 static struct shell_stream *usb_left_stream;
2532 static struct shell_stream *usb_right_stream;
2533 
init_lc3_decoder(struct shell_stream * sh_stream)2534 static int init_lc3_decoder(struct shell_stream *sh_stream)
2535 {
2536 	if (sh_stream == NULL) {
2537 		shell_error(ctx_shell, "NULL stream to init LC3 decoder");
2538 		return -EINVAL;
2539 	}
2540 
2541 	if (!sh_stream->is_rx) {
2542 		shell_error(ctx_shell, "Invalid stream to init LC3 decoder");
2543 		return -EINVAL;
2544 	}
2545 
2546 	if (sh_stream->rx.lc3_decoder != NULL) {
2547 		shell_error(ctx_shell, "Already initialized");
2548 		return -EALREADY;
2549 	}
2550 
2551 	if (sh_stream->lc3_freq_hz == 0 || sh_stream->lc3_frame_duration_us == 0) {
2552 		shell_error(ctx_shell, "Invalid freq (%u) or frame duration (%u)",
2553 			    sh_stream->lc3_freq_hz, sh_stream->lc3_frame_duration_us);
2554 
2555 		return -EINVAL;
2556 	}
2557 
2558 	shell_print(ctx_shell,
2559 		    "Initializing the LC3 decoder with %u us duration and %u Hz frequency",
2560 		    sh_stream->lc3_frame_duration_us, sh_stream->lc3_freq_hz);
2561 	/* Create the decoder instance. This shall complete before stream_started() is called. */
2562 	sh_stream->rx.lc3_decoder =
2563 		lc3_setup_decoder(sh_stream->lc3_frame_duration_us, sh_stream->lc3_freq_hz,
2564 				  IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) ? USB_SAMPLE_RATE : 0,
2565 				  &sh_stream->rx.lc3_decoder_mem);
2566 	if (sh_stream->rx.lc3_decoder == NULL) {
2567 		shell_error(ctx_shell, "Failed to setup LC3 decoder - wrong parameters?\n");
2568 		return -EINVAL;
2569 	}
2570 
2571 	return 0;
2572 }
2573 
decode_frame(struct lc3_data * data,size_t frame_cnt)2574 static bool decode_frame(struct lc3_data *data, size_t frame_cnt)
2575 {
2576 	const struct shell_stream *sh_stream = data->sh_stream;
2577 	const size_t total_frames = sh_stream->lc3_chan_cnt * sh_stream->lc3_frame_blocks_per_sdu;
2578 	const uint16_t octets_per_frame = sh_stream->lc3_octets_per_frame;
2579 	struct net_buf *buf = data->buf;
2580 	void *iso_data;
2581 	int err;
2582 
2583 	if (data->do_plc) {
2584 		iso_data = NULL; /* perform PLC */
2585 
2586 		if ((sh_stream->rx.decoded_cnt % bap_stats_interval) == 0) {
2587 			shell_print(ctx_shell, "[%zu]: Performing PLC", sh_stream->rx.decoded_cnt);
2588 		}
2589 
2590 		data->do_plc = false; /* clear flag */
2591 	} else {
2592 		iso_data = net_buf_pull_mem(data->buf, octets_per_frame);
2593 
2594 		if ((sh_stream->rx.decoded_cnt % bap_stats_interval) == 0) {
2595 			shell_print(ctx_shell, "[%zu]: Decoding frame of size %u (%u/%u)",
2596 				    sh_stream->rx.decoded_cnt, octets_per_frame, frame_cnt + 1,
2597 				    total_frames);
2598 		}
2599 	}
2600 
2601 	err = lc3_decode(sh_stream->rx.lc3_decoder, iso_data, octets_per_frame, LC3_PCM_FORMAT_S16,
2602 			 lc3_rx_buf, 1);
2603 	if (err < 0) {
2604 		shell_error(ctx_shell, "Failed to decode LC3 data (%u/%u - %u/%u)", frame_cnt + 1,
2605 			    total_frames, octets_per_frame * frame_cnt, buf->len);
2606 		return false;
2607 	}
2608 
2609 	return true;
2610 }
2611 
decode_frame_block(struct lc3_data * data,size_t frame_cnt)2612 static size_t decode_frame_block(struct lc3_data *data, size_t frame_cnt)
2613 {
2614 	const struct shell_stream *sh_stream = data->sh_stream;
2615 	const uint8_t chan_cnt = sh_stream->lc3_chan_cnt;
2616 	size_t decoded_frames = 0U;
2617 
2618 	for (uint8_t i = 0U; i < chan_cnt; i++) {
2619 		/* We provide the total number of decoded frames to `decode_frame` for logging
2620 		 * purposes
2621 		 */
2622 		if (decode_frame(data, frame_cnt + decoded_frames)) {
2623 			decoded_frames++;
2624 
2625 			if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
2626 				enum bt_audio_location chan_alloc;
2627 				int err;
2628 
2629 				err = get_lc3_chan_alloc_from_index(sh_stream, i, &chan_alloc);
2630 				if (err != 0) {
2631 					/* Not suitable for USB */
2632 					continue;
2633 				}
2634 
2635 				/* We only want to left or right from one stream to USB */
2636 				if ((chan_alloc == BT_AUDIO_LOCATION_FRONT_LEFT &&
2637 				     sh_stream != usb_left_stream) ||
2638 				    (chan_alloc == BT_AUDIO_LOCATION_FRONT_RIGHT &&
2639 				     sh_stream != usb_right_stream)) {
2640 					continue;
2641 				}
2642 
2643 				err = bap_usb_add_frame_to_usb(chan_alloc, lc3_rx_buf,
2644 							       sizeof(lc3_rx_buf), data->ts);
2645 				if (err == -EINVAL) {
2646 					continue;
2647 				}
2648 			}
2649 		} else {
2650 			/* If decoding failed, we clear the data to USB as it would contain
2651 			 * invalid data
2652 			 */
2653 			if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
2654 				bap_usb_clear_frames_to_usb();
2655 			}
2656 
2657 			break;
2658 		}
2659 	}
2660 
2661 	return decoded_frames;
2662 }
2663 
do_lc3_decode(struct lc3_data * data)2664 static void do_lc3_decode(struct lc3_data *data)
2665 {
2666 	struct shell_stream *sh_stream = data->sh_stream;
2667 
2668 	if (sh_stream->is_rx && sh_stream->rx.lc3_decoder != NULL) {
2669 		const uint8_t frame_blocks_per_sdu = sh_stream->lc3_frame_blocks_per_sdu;
2670 		size_t frame_cnt;
2671 
2672 		frame_cnt = 0;
2673 		for (uint8_t i = 0U; i < frame_blocks_per_sdu; i++) {
2674 			const size_t decoded_frames = decode_frame_block(data, frame_cnt);
2675 
2676 			if (decoded_frames == 0) {
2677 				break;
2678 			}
2679 
2680 			frame_cnt += decoded_frames;
2681 		}
2682 
2683 		sh_stream->rx.decoded_cnt++;
2684 	}
2685 
2686 	net_buf_unref(data->buf);
2687 }
2688 
lc3_decoder_thread_func(void * arg1,void * arg2,void * arg3)2689 static void lc3_decoder_thread_func(void *arg1, void *arg2, void *arg3)
2690 {
2691 	while (true) {
2692 		struct lc3_data *data = k_fifo_get(&lc3_in_fifo, K_FOREVER);
2693 		struct shell_stream *sh_stream = data->sh_stream;
2694 
2695 		if (sh_stream->is_rx && sh_stream->rx.lc3_decoder == NULL) {
2696 			shell_warn(ctx_shell, "Decoder is NULL, discarding data from FIFO");
2697 			k_mem_slab_free(&lc3_data_slab, (void *)data);
2698 			continue; /* Wait for new data */
2699 		}
2700 
2701 		do_lc3_decode(data);
2702 
2703 		k_mem_slab_free(&lc3_data_slab, (void *)data);
2704 	}
2705 }
2706 
2707 #endif /* CONFIG_LIBLC3*/
2708 
audio_recv(struct bt_bap_stream * stream,const struct bt_iso_recv_info * info,struct net_buf * buf)2709 static void audio_recv(struct bt_bap_stream *stream,
2710 		       const struct bt_iso_recv_info *info,
2711 		       struct net_buf *buf)
2712 {
2713 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(stream);
2714 
2715 	if (!sh_stream->is_rx) {
2716 		return;
2717 	}
2718 
2719 	sh_stream->rx.rx_cnt++;
2720 
2721 	if (info->ts == sh_stream->rx.last_info.ts) {
2722 		sh_stream->rx.dup_ts++;
2723 	}
2724 
2725 	if (info->seq_num == sh_stream->rx.last_info.seq_num) {
2726 		sh_stream->rx.dup_psn++;
2727 	}
2728 
2729 	if ((info->flags & BT_ISO_FLAGS_VALID) != 0) {
2730 		if (buf->len == 0U) {
2731 			sh_stream->rx.empty_sdu_pkts++;
2732 		} else {
2733 			sh_stream->rx.valid_sdu_pkts++;
2734 		}
2735 	}
2736 
2737 	if (info->flags & BT_ISO_FLAGS_ERROR) {
2738 		sh_stream->rx.err_pkts++;
2739 	}
2740 
2741 	if (info->flags & BT_ISO_FLAGS_LOST) {
2742 		sh_stream->rx.lost_pkts++;
2743 	}
2744 
2745 	if ((sh_stream->rx.rx_cnt % bap_stats_interval) == 0) {
2746 		shell_print(ctx_shell,
2747 			    "[%zu]: Incoming audio on stream %p len %u ts %u seq_num %u flags %u "
2748 			    "(valid %zu, dup ts %zu, dup psn %zu, err_pkts %zu, lost_pkts %zu, "
2749 			    "empty SDUs %zu)",
2750 			    sh_stream->rx.rx_cnt, stream, buf->len, info->ts, info->seq_num,
2751 			    info->flags, sh_stream->rx.valid_sdu_pkts, sh_stream->rx.dup_ts,
2752 			    sh_stream->rx.dup_psn, sh_stream->rx.err_pkts, sh_stream->rx.lost_pkts,
2753 			    sh_stream->rx.empty_sdu_pkts);
2754 	}
2755 
2756 	(void)memcpy(&sh_stream->rx.last_info, info, sizeof(sh_stream->rx.last_info));
2757 
2758 #if defined(CONFIG_LIBLC3)
2759 	if (sh_stream->rx.lc3_decoder != NULL) {
2760 		const uint8_t frame_blocks_per_sdu = sh_stream->lc3_frame_blocks_per_sdu;
2761 		const uint16_t octets_per_frame = sh_stream->lc3_octets_per_frame;
2762 		const uint8_t chan_cnt = sh_stream->lc3_chan_cnt;
2763 		struct lc3_data *data;
2764 
2765 		/* Allocate a context that holds both the buffer and the stream so that we can
2766 		 * send both of these values to the LC3 decoder thread as a single struct
2767 		 * in a FIFO
2768 		 */
2769 		if (k_mem_slab_alloc(&lc3_data_slab, (void **)&data, K_NO_WAIT)) {
2770 			shell_warn(ctx_shell, "Could not allocate LC3 data item");
2771 
2772 			return;
2773 		}
2774 
2775 		if ((info->flags & BT_ISO_FLAGS_VALID) == 0) {
2776 			data->do_plc = true;
2777 		} else if (buf->len != (octets_per_frame * chan_cnt * frame_blocks_per_sdu)) {
2778 			if (buf->len != 0U) {
2779 				shell_error(
2780 					ctx_shell,
2781 					"Expected %u frame blocks with %u channels of size %u, but "
2782 					"length is %u",
2783 					frame_blocks_per_sdu, chan_cnt, octets_per_frame, buf->len);
2784 			}
2785 
2786 			data->do_plc = true;
2787 		}
2788 
2789 		data->buf = net_buf_ref(buf);
2790 		data->sh_stream = sh_stream;
2791 		if (info->flags & BT_ISO_FLAGS_TS) {
2792 			data->ts = info->ts;
2793 		} else {
2794 			data->ts = 0U;
2795 		}
2796 
2797 		k_fifo_put(&lc3_in_fifo, data);
2798 	}
2799 #endif /* CONFIG_LIBLC3 */
2800 }
2801 #endif /* CONFIG_BT_AUDIO_RX */
2802 
2803 #if defined(CONFIG_BT_BAP_UNICAST)
stream_enabled_cb(struct bt_bap_stream * stream)2804 static void stream_enabled_cb(struct bt_bap_stream *stream)
2805 {
2806 	shell_print(ctx_shell, "Stream %p enabled", stream);
2807 
2808 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER)) {
2809 		struct bt_bap_ep_info ep_info;
2810 		struct bt_conn_info conn_info;
2811 		int err;
2812 
2813 		err = bt_conn_get_info(stream->conn, &conn_info);
2814 		if (err != 0) {
2815 			shell_error(ctx_shell, "Failed to get conn info: %d", err);
2816 			return;
2817 		}
2818 
2819 		if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
2820 			return; /* We also want to autonomously start the stream as the server */
2821 		}
2822 
2823 		err = bt_bap_ep_get_info(stream->ep, &ep_info);
2824 		if (err != 0) {
2825 			shell_error(ctx_shell, "Failed to get ep info: %d", err);
2826 			return;
2827 		}
2828 
2829 		if (ep_info.dir == BT_AUDIO_DIR_SINK) {
2830 			/* Automatically do the receiver start ready operation */
2831 			err = bt_bap_stream_start(stream);
2832 
2833 			if (err != 0) {
2834 				shell_error(ctx_shell, "Failed to start stream: %d", err);
2835 				return;
2836 			}
2837 		}
2838 	}
2839 }
2840 #endif /* CONFIG_BT_BAP_UNICAST */
2841 
stream_started_cb(struct bt_bap_stream * bap_stream)2842 static void stream_started_cb(struct bt_bap_stream *bap_stream)
2843 {
2844 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(bap_stream);
2845 	struct bt_bap_ep_info info = {0};
2846 	int ret;
2847 
2848 	printk("Stream %p started\n", bap_stream);
2849 
2850 	ret = bt_bap_ep_get_info(bap_stream->ep, &info);
2851 	if (ret != 0) {
2852 		shell_error(ctx_shell, "Failed to get EP info: %d", ret);
2853 		return;
2854 	}
2855 
2856 	sh_stream->is_rx = info.can_recv;
2857 	sh_stream->is_tx = info.can_send;
2858 
2859 #if defined(CONFIG_LIBLC3)
2860 	const struct bt_audio_codec_cfg *codec_cfg = bap_stream->codec_cfg;
2861 
2862 	if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
2863 		if (sh_stream->is_tx) {
2864 			atomic_set(&sh_stream->tx.lc3_enqueue_cnt, PRIME_COUNT);
2865 			sh_stream->tx.lc3_sdu_cnt = 0U;
2866 		}
2867 
2868 		ret = bt_audio_codec_cfg_get_freq(codec_cfg);
2869 		if (ret >= 0) {
2870 			ret = bt_audio_codec_cfg_freq_to_freq_hz(ret);
2871 
2872 			if (ret > 0) {
2873 				if (ret == 8000 || ret == 16000 || ret == 24000 || ret == 32000 ||
2874 				    ret == 48000) {
2875 					sh_stream->lc3_freq_hz = (uint32_t)ret;
2876 				} else {
2877 					shell_error(ctx_shell, "Unsupported frequency for LC3: %d",
2878 						    ret);
2879 					sh_stream->lc3_freq_hz = 0U;
2880 				}
2881 			} else {
2882 				shell_error(ctx_shell, "Invalid frequency: %d", ret);
2883 				sh_stream->lc3_freq_hz = 0U;
2884 			}
2885 		} else {
2886 			shell_error(ctx_shell, "Could not get frequency: %d", ret);
2887 			sh_stream->lc3_freq_hz = 0U;
2888 		}
2889 
2890 		ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg);
2891 		if (ret >= 0) {
2892 			ret = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret);
2893 			if (ret > 0) {
2894 				sh_stream->lc3_frame_duration_us = (uint32_t)ret;
2895 			} else {
2896 				shell_error(ctx_shell, "Invalid frame duration: %d", ret);
2897 				sh_stream->lc3_frame_duration_us = 0U;
2898 			}
2899 		} else {
2900 			shell_error(ctx_shell, "Could not get frame duration: %d", ret);
2901 			sh_stream->lc3_frame_duration_us = 0U;
2902 		}
2903 
2904 		ret = bt_audio_codec_cfg_get_chan_allocation(
2905 			codec_cfg, &sh_stream->lc3_chan_allocation, false);
2906 		if (ret == 0) {
2907 			sh_stream->lc3_chan_cnt =
2908 				bt_audio_get_chan_count(sh_stream->lc3_chan_allocation);
2909 		} else {
2910 			shell_error(ctx_shell, "Could not get channel allocation: %d", ret);
2911 			sh_stream->lc3_chan_allocation = BT_AUDIO_LOCATION_MONO_AUDIO;
2912 			sh_stream->lc3_chan_cnt = 1U;
2913 		}
2914 
2915 		ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true);
2916 		if (ret >= 0) {
2917 			sh_stream->lc3_frame_blocks_per_sdu = (uint8_t)ret;
2918 		} else {
2919 			shell_error(ctx_shell, "Could not get frame blocks per SDU: %d", ret);
2920 			sh_stream->lc3_frame_blocks_per_sdu = 0U;
2921 		}
2922 
2923 		ret = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg);
2924 		if (ret >= 0) {
2925 			sh_stream->lc3_octets_per_frame = (uint16_t)ret;
2926 		} else {
2927 			shell_error(ctx_shell, "Could not get octets per frame: %d", ret);
2928 			sh_stream->lc3_octets_per_frame = 0U;
2929 		}
2930 
2931 #if defined(CONFIG_BT_AUDIO_TX)
2932 		if (sh_stream->is_tx && sh_stream->tx.lc3_encoder == NULL) {
2933 			const int err = init_lc3_encoder(sh_stream);
2934 
2935 			if (err != 0) {
2936 				shell_error(ctx_shell, "Failed to init LC3 encoder: %d", err);
2937 
2938 				return;
2939 			}
2940 
2941 			if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
2942 				/* Always mark as active when using USB */
2943 				sh_stream->tx.active = true;
2944 			}
2945 		}
2946 #endif /* CONFIG_BT_AUDIO_TX */
2947 
2948 #if defined(CONFIG_BT_AUDIO_RX)
2949 		if (sh_stream->is_rx) {
2950 			if (sh_stream->rx.lc3_decoder == NULL) {
2951 				const int err = init_lc3_decoder(sh_stream);
2952 
2953 				if (err != 0) {
2954 					shell_error(ctx_shell, "Failed to init LC3 decoder: %d",
2955 						    err);
2956 
2957 					return;
2958 				}
2959 			}
2960 
2961 			sh_stream->rx.decoded_cnt = 0U;
2962 
2963 			if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
2964 				if ((sh_stream->lc3_chan_allocation &
2965 				     BT_AUDIO_LOCATION_FRONT_LEFT) != 0) {
2966 					if (usb_left_stream == NULL) {
2967 						shell_info(ctx_shell,
2968 							   "Setting USB left stream to %p",
2969 							   sh_stream);
2970 						usb_left_stream = sh_stream;
2971 					} else {
2972 						shell_warn(ctx_shell,
2973 							   "Multiple left streams started");
2974 					}
2975 				}
2976 
2977 				if ((sh_stream->lc3_chan_allocation &
2978 				     BT_AUDIO_LOCATION_FRONT_RIGHT) != 0) {
2979 					if (usb_right_stream == NULL) {
2980 						shell_info(ctx_shell,
2981 							   "Setting USB right stream to %p",
2982 							   sh_stream);
2983 						usb_right_stream = sh_stream;
2984 					} else {
2985 						shell_warn(ctx_shell,
2986 							   "Multiple right streams started");
2987 					}
2988 				}
2989 			}
2990 		}
2991 #endif /* CONFIG_BT_AUDIO_RX */
2992 	}
2993 #endif /* CONFIG_LIBLC3 */
2994 
2995 #if defined(CONFIG_BT_AUDIO_TX)
2996 	if (sh_stream->is_tx) {
2997 		sh_stream->tx.connected_at_ticks = k_uptime_ticks();
2998 	}
2999 #endif /* CONFIG_BT_AUDIO_TX */
3000 
3001 #if defined(CONFIG_BT_AUDIO_RX)
3002 	if (sh_stream->is_rx) {
3003 		sh_stream->rx.empty_sdu_pkts = 0U;
3004 		sh_stream->rx.valid_sdu_pkts = 0U;
3005 		sh_stream->rx.lost_pkts = 0U;
3006 		sh_stream->rx.err_pkts = 0U;
3007 		sh_stream->rx.dup_psn = 0U;
3008 		sh_stream->rx.rx_cnt = 0U;
3009 		sh_stream->rx.dup_ts = 0U;
3010 
3011 		rx_streaming_cnt++;
3012 	}
3013 #endif
3014 }
3015 
3016 #if defined(CONFIG_LIBLC3)
update_usb_streams_cb(struct shell_stream * sh_stream,void * user_data)3017 static void update_usb_streams_cb(struct shell_stream *sh_stream, void *user_data)
3018 {
3019 	if (sh_stream->is_rx) {
3020 		if (usb_left_stream == NULL &&
3021 		    (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0) {
3022 			shell_info(ctx_shell, "Setting new USB left stream to %p", sh_stream);
3023 			usb_left_stream = sh_stream;
3024 		}
3025 
3026 		if (usb_right_stream == NULL &&
3027 		    (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0) {
3028 			shell_info(ctx_shell, "Setting new USB right stream to %p", sh_stream);
3029 			usb_right_stream = sh_stream;
3030 		}
3031 	}
3032 }
3033 
update_usb_streams(struct shell_stream * sh_stream)3034 static void update_usb_streams(struct shell_stream *sh_stream)
3035 {
3036 	if (sh_stream->is_rx) {
3037 		if (sh_stream == usb_left_stream) {
3038 			shell_info(ctx_shell, "Clearing USB left stream (%p)", usb_left_stream);
3039 			usb_left_stream = NULL;
3040 		}
3041 
3042 		if (sh_stream == usb_right_stream) {
3043 			shell_info(ctx_shell, "Clearing USB right stream (%p)", usb_right_stream);
3044 			usb_right_stream = NULL;
3045 		}
3046 
3047 		bap_foreach_stream(update_usb_streams_cb, NULL);
3048 	}
3049 }
3050 #endif /* CONFIG_LIBLC3 */
3051 
clear_stream_data(struct shell_stream * sh_stream)3052 static void clear_stream_data(struct shell_stream *sh_stream)
3053 {
3054 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
3055 	if (IS_ARRAY_ELEMENT(broadcast_sink_streams, sh_stream)) {
3056 		if (default_broadcast_sink.stream_cnt != 0) {
3057 			default_broadcast_sink.stream_cnt--;
3058 		}
3059 
3060 		if (default_broadcast_sink.stream_cnt == 0) {
3061 			/* All streams in the broadcast sink has been terminated */
3062 			memset(&default_broadcast_sink.received_base, 0,
3063 			       sizeof(default_broadcast_sink.received_base));
3064 			default_broadcast_sink.broadcast_id = 0;
3065 			default_broadcast_sink.syncable = false;
3066 		}
3067 	}
3068 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
3069 
3070 #if defined(CONFIG_BT_AUDIO_RX)
3071 	if (sh_stream->is_rx) {
3072 		rx_streaming_cnt--;
3073 		memset(&sh_stream->rx, 0, sizeof(sh_stream->rx));
3074 	}
3075 #endif
3076 
3077 #if defined(CONFIG_BT_AUDIO_TX)
3078 	if (sh_stream->is_tx) {
3079 		memset(&sh_stream->tx, 0, sizeof(sh_stream->tx));
3080 	}
3081 #endif
3082 
3083 	sh_stream->is_rx = sh_stream->is_tx = false;
3084 
3085 #if defined(CONFIG_LIBLC3)
3086 	if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
3087 		update_usb_streams(sh_stream);
3088 	}
3089 #endif /* CONFIG_LIBLC3 */
3090 }
3091 
stream_stopped_cb(struct bt_bap_stream * stream,uint8_t reason)3092 static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
3093 {
3094 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(stream);
3095 
3096 	printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
3097 
3098 	clear_stream_data(sh_stream);
3099 }
3100 
3101 #if defined(CONFIG_BT_BAP_UNICAST)
stream_configured_cb(struct bt_bap_stream * stream,const struct bt_audio_codec_qos_pref * pref)3102 static void stream_configured_cb(struct bt_bap_stream *stream,
3103 				 const struct bt_audio_codec_qos_pref *pref)
3104 {
3105 	shell_print(ctx_shell, "Stream %p configured\n", stream);
3106 }
3107 
stream_released_cb(struct bt_bap_stream * stream)3108 static void stream_released_cb(struct bt_bap_stream *stream)
3109 {
3110 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(stream);
3111 
3112 	shell_print(ctx_shell, "Stream %p released\n", stream);
3113 
3114 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
3115 	if (default_unicast_group != NULL) {
3116 		bool group_can_be_deleted = true;
3117 
3118 		for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
3119 			const struct bt_bap_stream *bap_stream =
3120 				bap_stream_from_shell_stream(&unicast_streams[i]);
3121 
3122 			if (bap_stream->ep != NULL) {
3123 				struct bt_bap_ep_info ep_info;
3124 				int err;
3125 
3126 				err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
3127 				if (err == 0 && ep_info.state != BT_BAP_EP_STATE_CODEC_CONFIGURED &&
3128 				    ep_info.state != BT_BAP_EP_STATE_IDLE) {
3129 					group_can_be_deleted = false;
3130 					break;
3131 				}
3132 			}
3133 		}
3134 
3135 		if (group_can_be_deleted) {
3136 			int err;
3137 
3138 			shell_print(ctx_shell, "All streams released, deleting group\n");
3139 
3140 			err = bt_bap_unicast_group_delete(default_unicast_group);
3141 
3142 			if (err != 0) {
3143 				shell_error(ctx_shell, "Failed to delete unicast group: %d", err);
3144 			} else {
3145 				default_unicast_group = NULL;
3146 			}
3147 		}
3148 	}
3149 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
3150 
3151 	clear_stream_data(sh_stream);
3152 }
3153 #endif /* CONFIG_BT_BAP_UNICAST */
3154 
3155 static struct bt_bap_stream_ops stream_ops = {
3156 #if defined(CONFIG_BT_AUDIO_RX)
3157 	.recv = audio_recv,
3158 #endif /* CONFIG_BT_AUDIO_RX */
3159 #if defined(CONFIG_BT_BAP_UNICAST)
3160 	.configured = stream_configured_cb,
3161 	.released = stream_released_cb,
3162 	.enabled = stream_enabled_cb,
3163 #endif /* CONFIG_BT_BAP_UNICAST */
3164 	.started = stream_started_cb,
3165 	.stopped = stream_stopped_cb,
3166 #if defined(CONFIG_LIBLC3) && defined(CONFIG_BT_AUDIO_TX)
3167 	.sent = lc3_sent_cb,
3168 #endif
3169 };
3170 
3171 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
cmd_select_broadcast_source(const struct shell * sh,size_t argc,char * argv[])3172 static int cmd_select_broadcast_source(const struct shell *sh, size_t argc,
3173 				       char *argv[])
3174 {
3175 	unsigned long index;
3176 	int err = 0;
3177 
3178 	index = shell_strtoul(argv[1], 0, &err);
3179 	if (err != 0) {
3180 		shell_error(sh, "Could not parse index: %d", err);
3181 
3182 		return -ENOEXEC;
3183 	}
3184 
3185 	if (index > ARRAY_SIZE(broadcast_source_streams)) {
3186 		shell_error(sh, "Invalid index: %lu", index);
3187 
3188 		return -ENOEXEC;
3189 	}
3190 
3191 	default_stream = bap_stream_from_shell_stream(&broadcast_source_streams[index]);
3192 
3193 	return 0;
3194 }
3195 
cmd_create_broadcast(const struct shell * sh,size_t argc,char * argv[])3196 static int cmd_create_broadcast(const struct shell *sh, size_t argc,
3197 				char *argv[])
3198 {
3199 	struct bt_bap_broadcast_source_stream_param
3200 		stream_params[ARRAY_SIZE(broadcast_source_streams)];
3201 	struct bt_bap_broadcast_source_subgroup_param subgroup_param;
3202 	struct bt_bap_broadcast_source_param create_param = {0};
3203 	const struct named_lc3_preset *named_preset;
3204 	int err;
3205 
3206 	if (default_source.bap_source != NULL) {
3207 		shell_info(sh, "Broadcast source already created");
3208 		return -ENOEXEC;
3209 	}
3210 
3211 	named_preset = &default_broadcast_source_preset;
3212 
3213 	for (size_t i = 1U; i < argc; i++) {
3214 		char *arg = argv[i];
3215 
3216 		if (strcmp(arg, "enc") == 0) {
3217 			if (argc > i) {
3218 				size_t bcode_len;
3219 
3220 				i++;
3221 				arg = argv[i];
3222 
3223 				bcode_len = hex2bin(arg, strlen(arg),
3224 						    create_param.broadcast_code,
3225 						    sizeof(create_param.broadcast_code));
3226 
3227 				if (bcode_len != sizeof(create_param.broadcast_code)) {
3228 					shell_error(sh, "Invalid Broadcast Code Length: %zu",
3229 						    bcode_len);
3230 
3231 					return -ENOEXEC;
3232 				}
3233 
3234 				create_param.encryption = true;
3235 			} else {
3236 				shell_help(sh);
3237 
3238 				return SHELL_CMD_HELP_PRINTED;
3239 			}
3240 		} else if (strcmp(arg, "preset") == 0) {
3241 			if (argc > i) {
3242 
3243 				i++;
3244 				arg = argv[i];
3245 
3246 				named_preset = bap_get_named_preset(false, BT_AUDIO_DIR_SOURCE,
3247 								    arg);
3248 				if (named_preset == NULL) {
3249 					shell_error(sh, "Unable to parse named_preset %s",
3250 						    arg);
3251 
3252 					return -ENOEXEC;
3253 				}
3254 			} else {
3255 				shell_help(sh);
3256 
3257 				return SHELL_CMD_HELP_PRINTED;
3258 			}
3259 		}
3260 	}
3261 
3262 	copy_broadcast_source_preset(&default_source, named_preset);
3263 
3264 	(void)memset(stream_params, 0, sizeof(stream_params));
3265 	for (size_t i = 0; i < ARRAY_SIZE(stream_params); i++) {
3266 		stream_params[i].stream =
3267 			bap_stream_from_shell_stream(&broadcast_source_streams[i]);
3268 	}
3269 	subgroup_param.params_count = ARRAY_SIZE(stream_params);
3270 	subgroup_param.params = stream_params;
3271 	subgroup_param.codec_cfg = &default_source.codec_cfg;
3272 	create_param.params_count = 1U;
3273 	create_param.params = &subgroup_param;
3274 	create_param.qos = &default_source.qos;
3275 
3276 	err = bt_bap_broadcast_source_create(&create_param, &default_source.bap_source);
3277 	if (err != 0) {
3278 		shell_error(sh, "Unable to create broadcast source: %d", err);
3279 		return err;
3280 	}
3281 
3282 	shell_print(sh, "Broadcast source created: preset %s",
3283 		    named_preset->name);
3284 
3285 	if (default_stream == NULL) {
3286 		default_stream = bap_stream_from_shell_stream(&broadcast_source_streams[0]);
3287 	}
3288 
3289 	return 0;
3290 }
3291 
cmd_start_broadcast(const struct shell * sh,size_t argc,char * argv[])3292 static int cmd_start_broadcast(const struct shell *sh, size_t argc,
3293 			       char *argv[])
3294 {
3295 	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
3296 	int err;
3297 
3298 	if (adv == NULL) {
3299 		shell_info(sh, "Extended advertising set is NULL");
3300 		return -ENOEXEC;
3301 	}
3302 
3303 	if (default_source.bap_source == NULL || default_source.is_cap) {
3304 		shell_info(sh, "Broadcast source not created");
3305 		return -ENOEXEC;
3306 	}
3307 
3308 	err = bt_bap_broadcast_source_start(default_source.bap_source, adv_sets[selected_adv]);
3309 	if (err != 0) {
3310 		shell_error(sh, "Unable to start broadcast source: %d", err);
3311 		return err;
3312 	}
3313 
3314 	return 0;
3315 }
3316 
cmd_stop_broadcast(const struct shell * sh,size_t argc,char * argv[])3317 static int cmd_stop_broadcast(const struct shell *sh, size_t argc, char *argv[])
3318 {
3319 	int err;
3320 
3321 	if (default_source.bap_source == NULL || default_source.is_cap) {
3322 		shell_info(sh, "Broadcast source not created");
3323 		return -ENOEXEC;
3324 	}
3325 
3326 	err = bt_bap_broadcast_source_stop(default_source.bap_source);
3327 	if (err != 0) {
3328 		shell_error(sh, "Unable to stop broadcast source: %d", err);
3329 		return err;
3330 	}
3331 
3332 	return 0;
3333 }
3334 
cmd_delete_broadcast(const struct shell * sh,size_t argc,char * argv[])3335 static int cmd_delete_broadcast(const struct shell *sh, size_t argc,
3336 				char *argv[])
3337 {
3338 	int err;
3339 
3340 	if (default_source.bap_source == NULL || default_source.is_cap) {
3341 		shell_info(sh, "Broadcast source not created");
3342 		return -ENOEXEC;
3343 	}
3344 
3345 	err = bt_bap_broadcast_source_delete(default_source.bap_source);
3346 	if (err != 0) {
3347 		shell_error(sh, "Unable to delete broadcast source: %d", err);
3348 		return err;
3349 	}
3350 	default_source.bap_source = NULL;
3351 
3352 	return 0;
3353 }
3354 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
3355 
3356 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
cmd_create_broadcast_sink(const struct shell * sh,size_t argc,char * argv[])3357 static int cmd_create_broadcast_sink(const struct shell *sh, size_t argc, char *argv[])
3358 {
3359 	struct bt_le_per_adv_sync *per_adv_sync = per_adv_syncs[selected_per_adv_sync];
3360 	unsigned long broadcast_id;
3361 	int err = 0;
3362 
3363 	broadcast_id = shell_strtoul(argv[1], 0, &err);
3364 	if (err != 0) {
3365 		shell_error(sh, "Could not parse broadcast_id: %d", err);
3366 
3367 		return -ENOEXEC;
3368 	}
3369 
3370 	if (broadcast_id > BT_AUDIO_BROADCAST_ID_MAX) {
3371 		shell_error(sh, "Invalid broadcast_id: %lu", broadcast_id);
3372 
3373 		return -ENOEXEC;
3374 	}
3375 
3376 	if (per_adv_sync == NULL) {
3377 		const struct bt_le_scan_param param = {
3378 			.type = BT_LE_SCAN_TYPE_ACTIVE,
3379 			.options = BT_LE_SCAN_OPT_NONE,
3380 			.interval = BT_GAP_SCAN_FAST_INTERVAL,
3381 			.window = BT_GAP_SCAN_FAST_WINDOW,
3382 			.timeout = 1000, /* 10ms units -> 10 second timeout */
3383 		};
3384 
3385 		shell_print(sh, "No PA sync available, starting scanning for broadcast_id");
3386 
3387 		err = bt_le_scan_start(&param, NULL);
3388 		if (err) {
3389 			shell_print(sh, "Fail to start scanning: %d", err);
3390 
3391 			return -ENOEXEC;
3392 		}
3393 
3394 		auto_scan.broadcast_sink = &default_broadcast_sink;
3395 		auto_scan.broadcast_id = broadcast_id;
3396 		auto_scan.out_sync = &per_adv_syncs[selected_per_adv_sync];
3397 	} else {
3398 		shell_print(sh, "Creating broadcast sink with broadcast ID 0x%06X",
3399 			    (uint32_t)broadcast_id);
3400 
3401 		err = bt_bap_broadcast_sink_create(per_adv_sync, (uint32_t)broadcast_id,
3402 						   &default_broadcast_sink.bap_sink);
3403 
3404 		if (err != 0) {
3405 			shell_error(sh, "Failed to create broadcast sink: %d", err);
3406 
3407 			return -ENOEXEC;
3408 		}
3409 	}
3410 
3411 	return 0;
3412 }
3413 
cmd_sync_broadcast(const struct shell * sh,size_t argc,char * argv[])3414 static int cmd_sync_broadcast(const struct shell *sh, size_t argc, char *argv[])
3415 {
3416 	struct bt_bap_stream *streams[ARRAY_SIZE(broadcast_sink_streams)];
3417 	uint8_t bcode[BT_AUDIO_BROADCAST_CODE_SIZE] = {0};
3418 	bool bcode_set = false;
3419 	uint32_t bis_bitfield;
3420 	size_t stream_cnt;
3421 	int err = 0;
3422 
3423 	bis_bitfield = 0;
3424 	stream_cnt = 0U;
3425 	for (size_t argn = 1U; argn < argc; argn++) {
3426 		const char *arg = argv[argn];
3427 
3428 		if (strcmp(argv[argn], "bcode") == 0) {
3429 			size_t len;
3430 
3431 			if (++argn == argc) {
3432 				shell_help(sh);
3433 
3434 				return SHELL_CMD_HELP_PRINTED;
3435 			}
3436 
3437 			arg = argv[argn];
3438 
3439 			len = hex2bin(arg, strlen(arg), bcode, sizeof(bcode));
3440 			if (len == 0) {
3441 				shell_print(sh, "Invalid broadcast code: %s", arg);
3442 
3443 				return -ENOEXEC;
3444 			}
3445 
3446 			bcode_set = true;
3447 		} else if (strcmp(argv[argn], "bcode_str") == 0) {
3448 			if (++argn == argc) {
3449 				shell_help(sh);
3450 
3451 				return SHELL_CMD_HELP_PRINTED;
3452 			}
3453 
3454 			arg = argv[argn];
3455 
3456 			if (strlen(arg) == 0U || strlen(arg) > sizeof(bcode)) {
3457 				shell_print(sh, "Invalid broadcast code: %s", arg);
3458 
3459 				return -ENOEXEC;
3460 			}
3461 
3462 			memcpy(bcode, arg, strlen(arg));
3463 			bcode_set = true;
3464 		} else {
3465 			unsigned long val;
3466 
3467 			val = shell_strtoul(arg, 0, &err);
3468 			if (err != 0) {
3469 				shell_error(sh, "Could not parse BIS index val: %d", err);
3470 
3471 				return -ENOEXEC;
3472 			}
3473 
3474 			if (!IN_RANGE(val, BT_ISO_BIS_INDEX_MIN, BT_ISO_BIS_INDEX_MAX)) {
3475 				shell_error(sh, "Invalid index: %lu", val);
3476 
3477 				return -ENOEXEC;
3478 			}
3479 
3480 			bis_bitfield |= BT_ISO_BIS_INDEX_BIT(val);
3481 			stream_cnt++;
3482 		}
3483 	}
3484 
3485 	if (default_broadcast_sink.bap_sink == NULL) {
3486 		shell_error(sh, "No sink available");
3487 		return -ENOEXEC;
3488 	}
3489 
3490 	(void)memset(streams, 0, sizeof(streams));
3491 	for (size_t i = 0; i < ARRAY_SIZE(streams); i++) {
3492 		streams[i] = bap_stream_from_shell_stream(&broadcast_sink_streams[i]);
3493 	}
3494 
3495 	err = bt_bap_broadcast_sink_sync(default_broadcast_sink.bap_sink, bis_bitfield, streams,
3496 					 bcode_set ? bcode : NULL);
3497 	if (err != 0) {
3498 		shell_error(sh, "Failed to sync to broadcast: %d", err);
3499 		return err;
3500 	}
3501 
3502 	default_broadcast_sink.stream_cnt = stream_cnt;
3503 
3504 	return 0;
3505 }
3506 
cmd_stop_broadcast_sink(const struct shell * sh,size_t argc,char * argv[])3507 static int cmd_stop_broadcast_sink(const struct shell *sh, size_t argc,
3508 				   char *argv[])
3509 {
3510 	int err;
3511 
3512 	if (default_broadcast_sink.bap_sink == NULL) {
3513 		shell_error(sh, "No sink available");
3514 		return -ENOEXEC;
3515 	}
3516 
3517 	err = bt_bap_broadcast_sink_stop(default_broadcast_sink.bap_sink);
3518 	if (err != 0) {
3519 		shell_error(sh, "Failed to stop sink: %d", err);
3520 		return err;
3521 	}
3522 
3523 	return err;
3524 }
3525 
cmd_term_broadcast_sink(const struct shell * sh,size_t argc,char * argv[])3526 static int cmd_term_broadcast_sink(const struct shell *sh, size_t argc,
3527 				   char *argv[])
3528 {
3529 	int err;
3530 
3531 	if (default_broadcast_sink.bap_sink == NULL) {
3532 		shell_error(sh, "No sink available");
3533 		return -ENOEXEC;
3534 	}
3535 
3536 	err = bt_bap_broadcast_sink_delete(default_broadcast_sink.bap_sink);
3537 	if (err != 0) {
3538 		shell_error(sh, "Failed to term sink: %d", err);
3539 		return err;
3540 	}
3541 
3542 	default_broadcast_sink.bap_sink = NULL;
3543 	default_broadcast_sink.syncable = false;
3544 
3545 	return err;
3546 }
3547 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
3548 
cmd_set_loc(const struct shell * sh,size_t argc,char * argv[])3549 static int cmd_set_loc(const struct shell *sh, size_t argc, char *argv[])
3550 {
3551 	int err = 0;
3552 	enum bt_audio_dir dir;
3553 	enum bt_audio_location loc;
3554 	unsigned long loc_val;
3555 
3556 	if (!strcmp(argv[1], "sink")) {
3557 		dir = BT_AUDIO_DIR_SINK;
3558 	} else if (!strcmp(argv[1], "source")) {
3559 		dir = BT_AUDIO_DIR_SOURCE;
3560 	} else {
3561 		shell_error(sh, "Unsupported dir: %s", argv[1]);
3562 		return -ENOEXEC;
3563 	}
3564 
3565 	loc_val = shell_strtoul(argv[2], 16, &err);
3566 	if (err != 0) {
3567 		shell_error(sh, "Could not parse loc_val: %d", err);
3568 
3569 		return -ENOEXEC;
3570 	}
3571 
3572 	if (loc_val > BT_AUDIO_LOCATION_ANY) {
3573 		shell_error(sh, "Invalid location: %lu", loc_val);
3574 
3575 		return -ENOEXEC;
3576 	}
3577 
3578 	loc = loc_val;
3579 
3580 	err = bt_pacs_set_location(dir, loc);
3581 	if (err) {
3582 		shell_error(ctx_shell, "Set available contexts err %d", err);
3583 		return -ENOEXEC;
3584 	}
3585 
3586 	return 0;
3587 }
3588 
cmd_context(const struct shell * sh,size_t argc,char * argv[])3589 static int cmd_context(const struct shell *sh, size_t argc, char *argv[])
3590 {
3591 	int err = 0;
3592 	enum bt_audio_dir dir;
3593 	enum bt_audio_context ctx;
3594 	unsigned long ctx_val;
3595 
3596 	if (!strcmp(argv[1], "sink")) {
3597 		dir = BT_AUDIO_DIR_SINK;
3598 	} else if (!strcmp(argv[1], "source")) {
3599 		dir = BT_AUDIO_DIR_SOURCE;
3600 	} else {
3601 		shell_error(sh, "Unsupported dir: %s", argv[1]);
3602 		return -ENOEXEC;
3603 	}
3604 
3605 	ctx_val = shell_strtoul(argv[2], 16, &err);
3606 	if (err) {
3607 		shell_error(sh, "Could not parse context: %d", err);
3608 
3609 		return err;
3610 	}
3611 
3612 	if (ctx_val == BT_AUDIO_CONTEXT_TYPE_PROHIBITED ||
3613 	    ctx_val > BT_AUDIO_CONTEXT_TYPE_ANY) {
3614 		shell_error(sh, "Invalid context: %lu", ctx_val);
3615 
3616 		return -ENOEXEC;
3617 	}
3618 
3619 	ctx = ctx_val;
3620 
3621 	if (!strcmp(argv[3], "supported")) {
3622 		err = bt_pacs_set_supported_contexts(dir, ctx);
3623 		if (err) {
3624 			shell_error(ctx_shell, "Set supported contexts err %d", err);
3625 			return err;
3626 		}
3627 	} else if (!strcmp(argv[3], "available")) {
3628 		err = bt_pacs_set_available_contexts(dir, ctx);
3629 		if (err) {
3630 			shell_error(ctx_shell, "Set available contexts err %d", err);
3631 			return err;
3632 		}
3633 	} else {
3634 		shell_error(sh, "Unsupported context type: %s", argv[3]);
3635 		return -ENOEXEC;
3636 	}
3637 
3638 	return 0;
3639 }
3640 
cmd_init(const struct shell * sh,size_t argc,char * argv[])3641 static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
3642 {
3643 	int err, i;
3644 
3645 	ctx_shell = sh;
3646 
3647 	if (initialized) {
3648 		shell_print(sh, "Already initialized");
3649 		return -ENOEXEC;
3650 	}
3651 
3652 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
3653 	bt_bap_unicast_server_register_cb(&unicast_server_cb);
3654 #endif /* CONFIG_BT_BAP_UNICAST_SERVER */
3655 
3656 #if defined(CONFIG_BT_PAC_SNK)
3657 	bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink);
3658 #endif /* CONFIG_BT_PAC_SNK */
3659 #if defined(CONFIG_BT_PAC_SRC)
3660 	bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap_source);
3661 #endif /* CONFIG_BT_PAC_SNK */
3662 
3663 	if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) {
3664 		err = bt_pacs_set_location(BT_AUDIO_DIR_SINK, LOCATION);
3665 		__ASSERT(err == 0, "Failed to set sink location: %d", err);
3666 
3667 		err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK,
3668 						     CONTEXT);
3669 		__ASSERT(err == 0, "Failed to set sink supported contexts: %d",
3670 			 err);
3671 
3672 		err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK,
3673 						     CONTEXT);
3674 		__ASSERT(err == 0, "Failed to set sink available contexts: %d",
3675 			 err);
3676 	}
3677 
3678 	if (IS_ENABLED(CONFIG_BT_PAC_SRC_LOC)) {
3679 		err = bt_pacs_set_location(BT_AUDIO_DIR_SOURCE, LOCATION);
3680 		__ASSERT(err == 0, "Failed to set source location: %d", err);
3681 
3682 		err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE,
3683 						     CONTEXT);
3684 		__ASSERT(err == 0, "Failed to set sink supported contexts: %d",
3685 			 err);
3686 
3687 		err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE,
3688 						     CONTEXT);
3689 		__ASSERT(err == 0,
3690 			 "Failed to set source available contexts: %d",
3691 			 err);
3692 	}
3693 
3694 #if defined(CONFIG_BT_BAP_UNICAST)
3695 	for (i = 0; i < ARRAY_SIZE(unicast_streams); i++) {
3696 		bt_bap_stream_cb_register(bap_stream_from_shell_stream(&unicast_streams[i]),
3697 					  &stream_ops);
3698 
3699 		if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
3700 		    IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
3701 			/* If we use the cap initiator, we need to register the callbacks for CAP
3702 			 * as well, as CAP will override and use the BAP callbacks if doing a CAP
3703 			 * procedure
3704 			 */
3705 			bt_cap_stream_ops_register(&unicast_streams[i].stream, &stream_ops);
3706 		}
3707 	}
3708 #endif /* CONFIG_BT_BAP_UNICAST */
3709 
3710 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
3711 	bt_bap_broadcast_sink_register_cb(&sink_cbs);
3712 	bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb);
3713 	bt_le_scan_cb_register(&bap_scan_cb);
3714 
3715 	for (i = 0; i < ARRAY_SIZE(broadcast_sink_streams); i++) {
3716 		bt_bap_stream_cb_register(bap_stream_from_shell_stream(&broadcast_sink_streams[i]),
3717 					  &stream_ops);
3718 	}
3719 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
3720 
3721 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
3722 	for (i = 0; i < ARRAY_SIZE(broadcast_source_streams); i++) {
3723 		bt_bap_stream_cb_register(
3724 			bap_stream_from_shell_stream(&broadcast_source_streams[i]), &stream_ops);
3725 	}
3726 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
3727 
3728 #if defined(CONFIG_LIBLC3)
3729 #if defined(CONFIG_BT_AUDIO_RX)
3730 	static K_KERNEL_STACK_DEFINE(lc3_decoder_thread_stack, 4096);
3731 	const int lc3_decoder_thread_prio = K_PRIO_PREEMPT(5);
3732 	static struct k_thread lc3_decoder_thread;
3733 
3734 	k_thread_create(&lc3_decoder_thread, lc3_decoder_thread_stack,
3735 			K_KERNEL_STACK_SIZEOF(lc3_decoder_thread_stack), lc3_decoder_thread_func,
3736 			NULL, NULL, NULL, lc3_decoder_thread_prio, 0, K_NO_WAIT);
3737 	k_thread_name_set(&lc3_decoder_thread, "LC3 Decoder");
3738 #endif /* CONFIG_BT_AUDIO_RX */
3739 
3740 #if defined(CONFIG_BT_AUDIO_TX)
3741 	static K_KERNEL_STACK_DEFINE(lc3_encoder_thread_stack, 4096);
3742 	const int lc3_encoder_thread_prio = K_PRIO_PREEMPT(5);
3743 	static struct k_thread lc3_encoder_thread;
3744 
3745 	k_thread_create(&lc3_encoder_thread, lc3_encoder_thread_stack,
3746 			K_KERNEL_STACK_SIZEOF(lc3_encoder_thread_stack), lc3_encoder_thread_func,
3747 			NULL, NULL, NULL, lc3_encoder_thread_prio, 0, K_NO_WAIT);
3748 	k_thread_name_set(&lc3_encoder_thread, "LC3 Encoder");
3749 
3750 #endif /* CONFIG_BT_AUDIO_TX */
3751 
3752 	if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) &&
3753 	    (IS_ENABLED(CONFIG_BT_AUDIO_RX) || IS_ENABLED(CONFIG_BT_AUDIO_TX))) {
3754 		err = bap_usb_init();
3755 		__ASSERT(err == 0, "Failed to enable USB: %d", err);
3756 	}
3757 #endif /* CONFIG_LIBLC3 */
3758 
3759 	initialized = true;
3760 
3761 	return 0;
3762 }
3763 
3764 #if defined(CONFIG_BT_AUDIO_TX)
3765 
3766 #define DATA_MTU CONFIG_BT_ISO_TX_MTU
3767 NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, DATA_MTU, CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
3768 
cmd_send(const struct shell * sh,size_t argc,char * argv[])3769 static int cmd_send(const struct shell *sh, size_t argc, char *argv[])
3770 {
3771 	static uint8_t data[DATA_MTU - BT_ISO_CHAN_SEND_RESERVE];
3772 	int ret, len;
3773 	struct net_buf *buf;
3774 
3775 	if (default_stream == NULL) {
3776 		shell_error(sh, "Invalid (NULL) stream");
3777 
3778 		return -ENOEXEC;
3779 	}
3780 
3781 	if (default_stream->qos == NULL) {
3782 		shell_error(sh, "NULL stream QoS");
3783 
3784 		return -ENOEXEC;
3785 	}
3786 
3787 	if (argc > 1) {
3788 		len = hex2bin(argv[1], strlen(argv[1]), data, sizeof(data));
3789 		if (len > default_stream->qos->sdu) {
3790 			shell_print(sh, "Unable to send: len %d > %u MTU",
3791 				    len, default_stream->qos->sdu);
3792 
3793 			return -ENOEXEC;
3794 		}
3795 	} else {
3796 		len = MIN(default_stream->qos->sdu, sizeof(data));
3797 		memset(data, 0xff, len);
3798 	}
3799 
3800 	buf = net_buf_alloc(&tx_pool, K_FOREVER);
3801 	net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
3802 
3803 	net_buf_add_mem(buf, data, len);
3804 
3805 	ret = bt_bap_stream_send(default_stream, buf, get_next_seq_num(default_stream));
3806 	if (ret < 0) {
3807 		shell_print(sh, "Unable to send: %d", -ret);
3808 		net_buf_unref(buf);
3809 
3810 		return -ENOEXEC;
3811 	}
3812 
3813 	shell_print(sh, "Sending:");
3814 	shell_hexdump(sh, data, len);
3815 
3816 	return 0;
3817 }
3818 
3819 #if GENERATE_SINE_SUPPORTED
start_sine_stream_cb(struct shell_stream * sh_stream,void * user_data)3820 static void start_sine_stream_cb(struct shell_stream *sh_stream, void *user_data)
3821 {
3822 	if (sh_stream->is_tx) {
3823 		struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream);
3824 		const struct shell *sh = user_data;
3825 		int err;
3826 
3827 		err = init_lc3_encoder(sh_stream);
3828 		if (err != 0) {
3829 			shell_error(sh, "Failed to init LC3 %d for stream %p", err, bap_stream);
3830 
3831 			return;
3832 		}
3833 
3834 		sh_stream->tx.active = true;
3835 		sh_stream->tx.seq_num = get_next_seq_num(bap_stream_from_shell_stream(sh_stream));
3836 
3837 		shell_print(sh, "Started transmitting sine on stream %p", bap_stream);
3838 	}
3839 }
3840 
cmd_start_sine(const struct shell * sh,size_t argc,char * argv[])3841 static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[])
3842 {
3843 	bool start_all = false;
3844 
3845 	if (argc > 1) {
3846 		if (strcmp(argv[1], "all") == 0) {
3847 			start_all = true;
3848 		} else {
3849 			shell_help(sh);
3850 
3851 			return SHELL_CMD_HELP_PRINTED;
3852 		}
3853 	}
3854 
3855 	if (start_all) {
3856 		bap_foreach_stream(start_sine_stream_cb, (void *)sh);
3857 	} else {
3858 		struct shell_stream *sh_stream = shell_stream_from_bap_stream(default_stream);
3859 
3860 		start_sine_stream_cb(sh_stream, (void *)sh);
3861 	}
3862 
3863 	return 0;
3864 }
3865 
stop_sine_stream_cb(struct shell_stream * sh_stream,void * user_data)3866 static void stop_sine_stream_cb(struct shell_stream *sh_stream, void *user_data)
3867 {
3868 	if (sh_stream->is_tx) {
3869 		struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream);
3870 		const struct shell *sh = user_data;
3871 
3872 		shell_print(sh, "Stopped transmitting on stream %p", bap_stream);
3873 
3874 		sh_stream->tx.active = false;
3875 	}
3876 }
3877 
cmd_stop_sine(const struct shell * sh,size_t argc,char * argv[])3878 static int cmd_stop_sine(const struct shell *sh, size_t argc, char *argv[])
3879 {
3880 	bool stop_all = false;
3881 
3882 	if (argc > 1) {
3883 		if (strcmp(argv[1], "all") == 0) {
3884 			stop_all = true;
3885 		} else {
3886 			shell_help(sh);
3887 
3888 			return SHELL_CMD_HELP_PRINTED;
3889 		}
3890 	}
3891 
3892 	if (stop_all) {
3893 		bap_foreach_stream(stop_sine_stream_cb, (void *)sh);
3894 	} else {
3895 		struct shell_stream *sh_stream = shell_stream_from_bap_stream(default_stream);
3896 
3897 		stop_sine_stream_cb(sh_stream, (void *)sh);
3898 	}
3899 
3900 	return 0;
3901 }
3902 #endif /* GENERATE_SINE_SUPPORTED */
3903 #endif /* CONFIG_BT_AUDIO_TX */
3904 
cmd_bap_stats(const struct shell * sh,size_t argc,char * argv[])3905 static int cmd_bap_stats(const struct shell *sh, size_t argc, char *argv[])
3906 {
3907 	if (argc == 1) {
3908 		shell_info(sh, "Current stats interval: %lu", bap_stats_interval);
3909 	} else {
3910 		int err = 0;
3911 		unsigned long interval;
3912 
3913 		interval = shell_strtoul(argv[1], 0, &err);
3914 		if (err != 0) {
3915 			shell_error(sh, "Could not parse interval: %d", err);
3916 
3917 			return -ENOEXEC;
3918 		}
3919 
3920 		if (interval == 0U) {
3921 			shell_error(sh, "Interval cannot be 0");
3922 
3923 			return -ENOEXEC;
3924 		}
3925 
3926 		bap_stats_interval = interval;
3927 	}
3928 
3929 	return 0;
3930 }
3931 
3932 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
print_ase_info(struct bt_bap_ep * ep,void * user_data)3933 static void print_ase_info(struct bt_bap_ep *ep, void *user_data)
3934 {
3935 	struct bt_bap_ep_info info;
3936 	int err;
3937 
3938 	err = bt_bap_ep_get_info(ep, &info);
3939 	if (err == 0) {
3940 		printk("ASE info: id %u state %u dir %u\n", info.id, info.state, info.dir);
3941 	}
3942 }
3943 
cmd_print_ase_info(const struct shell * sh,size_t argc,char * argv[])3944 static int cmd_print_ase_info(const struct shell *sh, size_t argc, char *argv[])
3945 {
3946 	if (!default_conn) {
3947 		shell_error(sh, "Not connected");
3948 		return -ENOEXEC;
3949 	}
3950 
3951 	bt_bap_unicast_server_foreach_ep(default_conn, print_ase_info, NULL);
3952 
3953 	return 0;
3954 }
3955 #endif /* CONFIG_BT_BAP_UNICAST_SERVER */
3956 
3957 /* 31 is a unit separator - without t the tab is seemingly ignored*/
3958 #define HELP_SEP "\n\31\t"
3959 
3960 #define HELP_CFG_DATA                                                                              \
3961 	"\n[config" HELP_SEP "[freq <frequency>]" HELP_SEP "[dur <duration>]" HELP_SEP             \
3962 	"[chan_alloc <location>]" HELP_SEP "[frame_len <frame length>]" HELP_SEP                   \
3963 	"[frame_blks <frame blocks>]]"
3964 
3965 #define HELP_CFG_META                                                                              \
3966 	"\n[meta" HELP_SEP "[pref_ctx <context>]" HELP_SEP "[stream_ctx <context>]" HELP_SEP       \
3967 	"[program_info <program info>]" HELP_SEP "[lang <ISO 639-3 lang>]" HELP_SEP         \
3968 	"[ccid_list <ccids>]" HELP_SEP "[parental_rating <rating>]" HELP_SEP                       \
3969 	"[program_info_uri <URI>]" HELP_SEP "[audio_active_state <state>]" HELP_SEP                \
3970 	"[bcast_flag]" HELP_SEP "[extended <meta>]" HELP_SEP "[vendor <meta>]]"
3971 
3972 SHELL_STATIC_SUBCMD_SET_CREATE(
3973 	bap_cmds, SHELL_CMD_ARG(init, NULL, NULL, cmd_init, 1, 0),
3974 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
3975 	SHELL_CMD_ARG(select_broadcast, NULL, "<stream>", cmd_select_broadcast_source, 2, 0),
3976 	SHELL_CMD_ARG(create_broadcast, NULL, "[preset <preset_name>] [enc <broadcast_code>]",
3977 		      cmd_create_broadcast, 1, 2),
3978 	SHELL_CMD_ARG(start_broadcast, NULL, "", cmd_start_broadcast, 1, 0),
3979 	SHELL_CMD_ARG(stop_broadcast, NULL, "", cmd_stop_broadcast, 1, 0),
3980 	SHELL_CMD_ARG(delete_broadcast, NULL, "", cmd_delete_broadcast, 1, 0),
3981 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
3982 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
3983 	SHELL_CMD_ARG(create_broadcast_sink, NULL, "0x<broadcast_id>", cmd_create_broadcast_sink, 2,
3984 		      0),
3985 	SHELL_CMD_ARG(sync_broadcast, NULL,
3986 		      "0x<bis_index> [[[0x<bis_index>] 0x<bis_index>] ...] "
3987 		      "[bcode <broadcast code> || bcode_str <broadcast code as string>]",
3988 		      cmd_sync_broadcast, 2, ARRAY_SIZE(broadcast_sink_streams) + 1),
3989 	SHELL_CMD_ARG(stop_broadcast_sink, NULL, "Stops broadcast sink", cmd_stop_broadcast_sink, 1,
3990 		      0),
3991 	SHELL_CMD_ARG(term_broadcast_sink, NULL, "", cmd_term_broadcast_sink, 1, 0),
3992 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
3993 #if defined(CONFIG_BT_BAP_UNICAST)
3994 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
3995 	SHELL_CMD_ARG(discover, NULL, "[dir: sink, source]", cmd_discover, 1, 1),
3996 	SHELL_CMD_ARG(config, NULL,
3997 		      "<direction: sink, source> <index> [loc <loc_bits>] [preset <preset_name>]",
3998 		      cmd_config, 3, 4),
3999 	SHELL_CMD_ARG(stream_qos, NULL, "interval [framing] [latency] [pd] [sdu] [phy] [rtn]",
4000 		      cmd_stream_qos, 2, 6),
4001 	SHELL_CMD_ARG(connect, NULL, "Connect the CIS of the stream", cmd_connect, 1, 0),
4002 	SHELL_CMD_ARG(qos, NULL, "Send QoS configure for Unicast Group", cmd_qos, 1, 0),
4003 	SHELL_CMD_ARG(enable, NULL, "[context]", cmd_enable, 1, 1),
4004 	SHELL_CMD_ARG(stop, NULL, NULL, cmd_stop, 1, 0),
4005 	SHELL_CMD_ARG(list, NULL, NULL, cmd_list, 1, 0),
4006 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
4007 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
4008 	SHELL_CMD_ARG(print_ase_info, NULL, "Print ASE info for default connection",
4009 		      cmd_print_ase_info, 0, 0),
4010 #endif /* CONFIG_BT_BAP_UNICAST_SERVER */
4011 	SHELL_CMD_ARG(metadata, NULL, "[context]", cmd_metadata, 1, 1),
4012 	SHELL_CMD_ARG(start, NULL, NULL, cmd_start, 1, 0),
4013 	SHELL_CMD_ARG(disable, NULL, NULL, cmd_disable, 1, 0),
4014 	SHELL_CMD_ARG(release, NULL, NULL, cmd_release, 1, 0),
4015 	SHELL_CMD_ARG(select_unicast, NULL, "<stream>", cmd_select_unicast, 2, 0),
4016 #endif /* CONFIG_BT_BAP_UNICAST */
4017 #if IS_BAP_INITIATOR
4018 	SHELL_CMD_ARG(preset, NULL,
4019 		      "<sink, source, broadcast> [preset] " HELP_CFG_DATA " " HELP_CFG_META,
4020 		      cmd_preset, 2, 34),
4021 #endif /* IS_BAP_INITIATOR */
4022 #if defined(CONFIG_BT_AUDIO_TX)
4023 	SHELL_CMD_ARG(send, NULL, "Send to Audio Stream [data]", cmd_send, 1, 1),
4024 #if GENERATE_SINE_SUPPORTED
4025 	SHELL_CMD_ARG(start_sine, NULL, "Start sending a LC3 encoded sine wave [all]",
4026 		      cmd_start_sine, 1, 1),
4027 	SHELL_CMD_ARG(stop_sine, NULL, "Stop sending a LC3 encoded sine wave [all]", cmd_stop_sine,
4028 		      1, 1),
4029 #endif /* GENERATE_SINE_SUPPORTED */
4030 #endif /* CONFIG_BT_AUDIO_TX */
4031 	SHELL_CMD_ARG(bap_stats, NULL,
4032 		      "Sets or gets the statistics reporting interval in # of packets",
4033 		      cmd_bap_stats, 1, 1),
4034 	SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_location, NULL,
4035 			   "<direction: sink, source> <location bitmask>", cmd_set_loc, 3, 0),
4036 	SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_context, NULL,
4037 			   "<direction: sink, source>"
4038 			   "<context bitmask> <type: supported, available>",
4039 			   cmd_context, 4, 0),
4040 	SHELL_SUBCMD_SET_END);
4041 
cmd_bap(const struct shell * sh,size_t argc,char ** argv)4042 static int cmd_bap(const struct shell *sh, size_t argc, char **argv)
4043 {
4044 	if (argc > 1) {
4045 		shell_error(sh, "%s unknown parameter: %s",
4046 			    argv[0], argv[1]);
4047 	} else {
4048 		shell_error(sh, "%s Missing subcommand", argv[0]);
4049 	}
4050 
4051 	return -ENOEXEC;
4052 }
4053 
4054 SHELL_CMD_ARG_REGISTER(bap, &bap_cmds, "Bluetooth BAP shell commands", cmd_bap, 1, 1);
4055 
connectable_ad_data_add(struct bt_data * data_array,size_t data_array_size)4056 static ssize_t connectable_ad_data_add(struct bt_data *data_array,
4057 				       size_t data_array_size)
4058 {
4059 	static const uint8_t ad_ext_uuid16[] = {
4060 		IF_ENABLED(CONFIG_BT_MICP_MIC_DEV, (BT_UUID_16_ENCODE(BT_UUID_MICS_VAL),))
4061 		IF_ENABLED(CONFIG_BT_ASCS, (BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL),))
4062 		IF_ENABLED(CONFIG_BT_BAP_SCAN_DELEGATOR, (BT_UUID_16_ENCODE(BT_UUID_BASS_VAL),))
4063 		IF_ENABLED(CONFIG_BT_PACS, (BT_UUID_16_ENCODE(BT_UUID_PACS_VAL),))
4064 		IF_ENABLED(CONFIG_BT_GTBS, (BT_UUID_16_ENCODE(BT_UUID_GTBS_VAL),))
4065 		IF_ENABLED(CONFIG_BT_TBS, (BT_UUID_16_ENCODE(BT_UUID_TBS_VAL),))
4066 		IF_ENABLED(CONFIG_BT_VCP_VOL_REND, (BT_UUID_16_ENCODE(BT_UUID_VCS_VAL),))
4067 		IF_ENABLED(CONFIG_BT_HAS, (BT_UUID_16_ENCODE(BT_UUID_HAS_VAL),)) /* Shall be last */
4068 	};
4069 	size_t ad_len = 0;
4070 
4071 	if (IS_ENABLED(CONFIG_BT_ASCS)) {
4072 		static uint8_t ad_bap_announcement[8] = {
4073 			BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL),
4074 			BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED,
4075 		};
4076 		enum bt_audio_context snk_context, src_context;
4077 
4078 		snk_context = bt_pacs_get_available_contexts(BT_AUDIO_DIR_SINK);
4079 		sys_put_le16(snk_context, &ad_bap_announcement[3]);
4080 
4081 		src_context = bt_pacs_get_available_contexts(BT_AUDIO_DIR_SOURCE);
4082 		sys_put_le16(src_context, &ad_bap_announcement[5]);
4083 
4084 		/* Metadata length */
4085 		ad_bap_announcement[7] = 0x00;
4086 
4087 		__ASSERT(data_array_size > ad_len, "No space for AD_BAP_ANNOUNCEMENT");
4088 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
4089 		data_array[ad_len].data_len = ARRAY_SIZE(ad_bap_announcement);
4090 		data_array[ad_len].data = &ad_bap_announcement[0];
4091 		ad_len++;
4092 	}
4093 
4094 	if (IS_ENABLED(CONFIG_BT_BAP_SCAN_DELEGATOR)) {
4095 		ad_len += bap_scan_delegator_ad_data_add(&data_array[ad_len],
4096 							 data_array_size - ad_len);
4097 	}
4098 
4099 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR)) {
4100 		ad_len += cap_acceptor_ad_data_add(&data_array[ad_len], data_array_size - ad_len,
4101 						   true);
4102 	}
4103 
4104 	if (IS_ENABLED(CONFIG_BT_GMAP)) {
4105 		ad_len += gmap_ad_data_add(&data_array[ad_len], data_array_size - ad_len);
4106 	}
4107 
4108 	if (ARRAY_SIZE(ad_ext_uuid16) > 0) {
4109 		size_t uuid16_size;
4110 
4111 		if (data_array_size <= ad_len) {
4112 			shell_warn(ctx_shell, "No space for AD_UUID16");
4113 			return ad_len;
4114 		}
4115 
4116 		data_array[ad_len].type = BT_DATA_UUID16_SOME;
4117 
4118 		if (IS_ENABLED(CONFIG_BT_HAS) && IS_ENABLED(CONFIG_BT_PRIVACY)) {
4119 			/* If the HA is in one of the GAP connectable modes and is using a
4120 			 * resolvable private address, the HA shall not include the Hearing Access
4121 			 * Service UUID in the Service UUID AD type field of the advertising data
4122 			 * or scan response.
4123 			 */
4124 			uuid16_size = ARRAY_SIZE(ad_ext_uuid16) - BT_UUID_SIZE_16;
4125 		} else {
4126 			uuid16_size = ARRAY_SIZE(ad_ext_uuid16);
4127 		}
4128 
4129 		/* We can maximum advertise 127 16-bit UUIDs = 254 octets */
4130 		data_array[ad_len].data_len = MIN(uuid16_size, 254);
4131 
4132 		data_array[ad_len].data = &ad_ext_uuid16[0];
4133 		ad_len++;
4134 	}
4135 
4136 	return ad_len;
4137 }
4138 
nonconnectable_ad_data_add(struct bt_data * data_array,const size_t data_array_size)4139 static ssize_t nonconnectable_ad_data_add(struct bt_data *data_array,
4140 					  const size_t data_array_size)
4141 {
4142 	static const uint8_t ad_ext_uuid16[] = {
4143 		IF_ENABLED(CONFIG_BT_PACS, (BT_UUID_16_ENCODE(BT_UUID_PACS_VAL),))
4144 		IF_ENABLED(CONFIG_BT_CAP_ACCEPTOR, (BT_UUID_16_ENCODE(BT_UUID_CAS_VAL),))
4145 	};
4146 	size_t ad_len = 0;
4147 
4148 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR)) {
4149 		static const uint8_t ad_cap_announcement[3] = {
4150 			BT_UUID_16_ENCODE(BT_UUID_CAS_VAL),
4151 			BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED,
4152 		};
4153 
4154 		__ASSERT(data_array_size > ad_len, "No space for AD_CAP_ANNOUNCEMENT");
4155 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
4156 		data_array[ad_len].data_len = ARRAY_SIZE(ad_cap_announcement);
4157 		data_array[ad_len].data = &ad_cap_announcement[0];
4158 		ad_len++;
4159 	}
4160 
4161 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
4162 	if (default_source.bap_source != NULL && !default_source.is_cap) {
4163 		static uint8_t ad_bap_broadcast_announcement[5] = {
4164 			BT_UUID_16_ENCODE(BT_UUID_BROADCAST_AUDIO_VAL),
4165 		};
4166 		uint32_t broadcast_id;
4167 		int err;
4168 
4169 		err = bt_bap_broadcast_source_get_id(default_source.bap_source, &broadcast_id);
4170 		if (err != 0) {
4171 			printk("Unable to get broadcast ID: %d\n", err);
4172 
4173 			return -1;
4174 		}
4175 
4176 		sys_put_le24(broadcast_id, &ad_bap_broadcast_announcement[2]);
4177 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
4178 		data_array[ad_len].data_len = ARRAY_SIZE(ad_bap_broadcast_announcement);
4179 		data_array[ad_len].data = ad_bap_broadcast_announcement;
4180 		ad_len++;
4181 	}
4182 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
4183 
4184 	if (ARRAY_SIZE(ad_ext_uuid16) > 0) {
4185 		if (data_array_size <= ad_len) {
4186 			shell_warn(ctx_shell, "No space for AD_UUID16");
4187 			return ad_len;
4188 		}
4189 
4190 		data_array[ad_len].type = BT_DATA_UUID16_SOME;
4191 		data_array[ad_len].data_len = ARRAY_SIZE(ad_ext_uuid16);
4192 		data_array[ad_len].data = &ad_ext_uuid16[0];
4193 		ad_len++;
4194 	}
4195 
4196 	return ad_len;
4197 }
4198 
audio_ad_data_add(struct bt_data * data_array,const size_t data_array_size,const bool discoverable,const bool connectable)4199 ssize_t audio_ad_data_add(struct bt_data *data_array, const size_t data_array_size,
4200 			  const bool discoverable, const bool connectable)
4201 {
4202 	ssize_t ad_len = 0;
4203 
4204 	if (!discoverable) {
4205 		return 0;
4206 	}
4207 
4208 	if (connectable) {
4209 		ad_len += connectable_ad_data_add(data_array, data_array_size);
4210 	} else {
4211 		ad_len += nonconnectable_ad_data_add(data_array, data_array_size);
4212 	}
4213 
4214 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
4215 		ad_len += cap_initiator_ad_data_add(data_array, data_array_size, discoverable,
4216 						    connectable);
4217 	}
4218 
4219 	return ad_len;
4220 }
4221 
audio_pa_data_add(struct bt_data * data_array,const size_t data_array_size)4222 ssize_t audio_pa_data_add(struct bt_data *data_array,
4223 			  const size_t data_array_size)
4224 {
4225 	size_t ad_len = 0;
4226 
4227 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
4228 	if (default_source.bap_source != NULL && !default_source.is_cap) {
4229 		/* Required size of the buffer depends on what has been
4230 		 * configured. We just use the maximum size possible.
4231 		 */
4232 		NET_BUF_SIMPLE_DEFINE_STATIC(base_buf, UINT8_MAX);
4233 		int err;
4234 
4235 		net_buf_simple_reset(&base_buf);
4236 
4237 		err = bt_bap_broadcast_source_get_base(default_source.bap_source, &base_buf);
4238 		if (err != 0) {
4239 			printk("Unable to get BASE: %d\n", err);
4240 
4241 			return -1;
4242 		}
4243 
4244 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
4245 		data_array[ad_len].data_len = base_buf.len;
4246 		data_array[ad_len].data = base_buf.data;
4247 		ad_len++;
4248 	} else if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
4249 		return cap_initiator_pa_data_add(data_array, data_array_size);
4250 	}
4251 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
4252 
4253 	return ad_len;
4254 }
4255