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 "host/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_bap_qos_cfg_pref qos_pref =
623 	BT_BAP_QOS_CFG_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_bap_qos_cfg_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_bap_qos_cfg_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_bap_qos_cfg_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_bap_qos_cfg_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_bap_qos_cfg * qos,struct bt_bap_ascs_rsp * rsp)681 static int lc3_qos(struct bt_bap_stream *stream, const struct bt_bap_qos_cfg *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_bap_qos_cfg *snk_qos[BAP_UNICAST_AC_MAX_SNK];
826 	struct bt_bap_qos_cfg *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_bap_qos_cfg *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 
set_group_param(const struct shell * sh,struct bt_bap_unicast_group_param * group_param,struct bt_bap_unicast_group_stream_pair_param pair_param[ARRAY_SIZE (unicast_streams)],struct bt_bap_unicast_group_stream_param stream_params[ARRAY_SIZE (unicast_streams)])1440 static int set_group_param(
1441 	const struct shell *sh, struct bt_bap_unicast_group_param *group_param,
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 {
1445 	size_t source_cnt = 0;
1446 	size_t sink_cnt = 0;
1447 	size_t cnt = 0;
1448 
1449 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
1450 		struct bt_bap_stream *stream = bap_stream_from_shell_stream(&unicast_streams[i]);
1451 		struct shell_stream *uni_stream = &unicast_streams[i];
1452 
1453 		if (stream->ep != NULL) {
1454 			struct bt_bap_unicast_group_stream_param *stream_param;
1455 
1456 			stream_param = &stream_params[cnt];
1457 
1458 			stream_param->stream = stream;
1459 			if (stream_dir(stream) == BT_AUDIO_DIR_SINK) {
1460 				stream_param->qos = &uni_stream->qos;
1461 				pair_param[sink_cnt++].tx_param = stream_param;
1462 			} else {
1463 				stream_param->qos = &uni_stream->qos;
1464 				pair_param[source_cnt++].rx_param = stream_param;
1465 			}
1466 
1467 			cnt++;
1468 		}
1469 	}
1470 
1471 	if (cnt == 0U) {
1472 		shell_error(sh, "Stream cnt is 0");
1473 
1474 		return -ENOEXEC;
1475 	}
1476 
1477 	group_param->packing = BT_ISO_PACKING_SEQUENTIAL;
1478 	group_param->params = pair_param;
1479 	group_param->params_count = MAX(source_cnt, sink_cnt);
1480 
1481 	return 0;
1482 }
1483 
create_unicast_group(const struct shell * sh)1484 static int create_unicast_group(const struct shell *sh)
1485 {
1486 	struct bt_bap_unicast_group_stream_pair_param pair_param[ARRAY_SIZE(unicast_streams)] = {0};
1487 	struct bt_bap_unicast_group_stream_param stream_params[ARRAY_SIZE(unicast_streams)] = {0};
1488 	struct bt_bap_unicast_group_param group_param = {0};
1489 	int err;
1490 
1491 	err = set_group_param(sh, &group_param, pair_param, stream_params);
1492 	if (err != 0) {
1493 		return err;
1494 	}
1495 
1496 	err = bt_bap_unicast_group_create(&group_param, &default_unicast_group);
1497 	if (err != 0) {
1498 		shell_error(sh, "Unable to create default unicast group: %d", err);
1499 
1500 		return -ENOEXEC;
1501 	}
1502 
1503 	return 0;
1504 }
1505 
reconfig_unicast_group(const struct shell * sh)1506 static int reconfig_unicast_group(const struct shell *sh)
1507 {
1508 	struct bt_bap_unicast_group_stream_pair_param pair_param[ARRAY_SIZE(unicast_streams)] = {0};
1509 	struct bt_bap_unicast_group_stream_param stream_params[ARRAY_SIZE(unicast_streams)] = {0};
1510 	struct bt_bap_unicast_group_param group_param = {0};
1511 	int err;
1512 
1513 	err = set_group_param(sh, &group_param, pair_param, stream_params);
1514 	if (err != 0) {
1515 		return err;
1516 	}
1517 
1518 	err = bt_bap_unicast_group_reconfig(default_unicast_group, &group_param);
1519 	if (err != 0) {
1520 		shell_error(sh, "Unable to create default unicast group: %d", err);
1521 
1522 		return -ENOEXEC;
1523 	}
1524 
1525 	return 0;
1526 }
1527 
cmd_qos(const struct shell * sh,size_t argc,char * argv[])1528 static int cmd_qos(const struct shell *sh, size_t argc, char *argv[])
1529 {
1530 	int err;
1531 
1532 	if (default_stream == NULL) {
1533 		shell_print(sh, "No stream selected");
1534 		return -ENOEXEC;
1535 	}
1536 
1537 	if (default_conn == NULL) {
1538 		shell_error(sh, "Not connected");
1539 		return -ENOEXEC;
1540 	}
1541 
1542 	if (default_unicast_group == NULL) {
1543 		err = create_unicast_group(sh);
1544 		if (err != 0) {
1545 			return err;
1546 		}
1547 	} else {
1548 		err = reconfig_unicast_group(sh);
1549 		if (err != 0) {
1550 			return err;
1551 		}
1552 	}
1553 
1554 	err = bt_bap_stream_qos(default_conn, default_unicast_group);
1555 	if (err) {
1556 		shell_error(sh, "Unable to setup QoS: %d", err);
1557 		return -ENOEXEC;
1558 	}
1559 
1560 	return 0;
1561 }
1562 
cmd_enable(const struct shell * sh,size_t argc,char * argv[])1563 static int cmd_enable(const struct shell *sh, size_t argc, char *argv[])
1564 {
1565 	struct bt_audio_codec_cfg *codec_cfg;
1566 	int err;
1567 
1568 	if (default_stream == NULL) {
1569 		shell_error(sh, "No stream selected");
1570 		return -ENOEXEC;
1571 	}
1572 
1573 	codec_cfg = default_stream->codec_cfg;
1574 
1575 	if (argc > 1) {
1576 		err = set_metadata(codec_cfg, argv[1]);
1577 		if (err != 0) {
1578 			shell_error(sh, "Unable to handle metadata update: %d", err);
1579 			return err;
1580 		}
1581 	}
1582 
1583 	err = bt_bap_stream_enable(default_stream, codec_cfg->meta, codec_cfg->meta_len);
1584 	if (err) {
1585 		shell_error(sh, "Unable to enable Channel");
1586 		return -ENOEXEC;
1587 	}
1588 
1589 	return 0;
1590 }
1591 
cmd_stop(const struct shell * sh,size_t argc,char * argv[])1592 static int cmd_stop(const struct shell *sh, size_t argc, char *argv[])
1593 {
1594 	int err;
1595 
1596 	if (default_stream == NULL) {
1597 		shell_error(sh, "No stream selected");
1598 		return -ENOEXEC;
1599 	}
1600 
1601 	err = bt_bap_stream_stop(default_stream);
1602 	if (err) {
1603 		shell_error(sh, "Unable to stop Channel");
1604 		return -ENOEXEC;
1605 	}
1606 
1607 	return 0;
1608 }
1609 
cmd_connect(const struct shell * sh,size_t argc,char * argv[])1610 static int cmd_connect(const struct shell *sh, size_t argc, char *argv[])
1611 {
1612 	int err;
1613 
1614 	if (default_stream == NULL) {
1615 		shell_error(sh, "No stream selected");
1616 		return -ENOEXEC;
1617 	}
1618 
1619 	err = bt_bap_stream_connect(default_stream);
1620 	if (err) {
1621 		shell_error(sh, "Unable to connect stream");
1622 		return -ENOEXEC;
1623 	}
1624 
1625 	return 0;
1626 }
1627 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1628 
cmd_metadata(const struct shell * sh,size_t argc,char * argv[])1629 static int cmd_metadata(const struct shell *sh, size_t argc, char *argv[])
1630 {
1631 	struct bt_audio_codec_cfg *codec_cfg;
1632 	int err;
1633 
1634 	if (default_stream == NULL) {
1635 		shell_error(sh, "No stream selected");
1636 		return -ENOEXEC;
1637 	}
1638 
1639 	codec_cfg = default_stream->codec_cfg;
1640 
1641 	if (argc > 1) {
1642 		err = set_metadata(codec_cfg, argv[1]);
1643 		if (err != 0) {
1644 			shell_error(sh, "Unable to handle metadata update: %d", err);
1645 			return err;
1646 		}
1647 	}
1648 
1649 	err = bt_bap_stream_metadata(default_stream, codec_cfg->meta, codec_cfg->meta_len);
1650 	if (err) {
1651 		shell_error(sh, "Unable to set Channel metadata");
1652 		return -ENOEXEC;
1653 	}
1654 
1655 	return 0;
1656 }
1657 
cmd_start(const struct shell * sh,size_t argc,char * argv[])1658 static int cmd_start(const struct shell *sh, size_t argc, char *argv[])
1659 {
1660 	int err;
1661 
1662 	if (default_stream == NULL) {
1663 		shell_error(sh, "No stream selected");
1664 		return -ENOEXEC;
1665 	}
1666 
1667 	err = bt_bap_stream_start(default_stream);
1668 	if (err) {
1669 		shell_error(sh, "Unable to start Channel");
1670 		return -ENOEXEC;
1671 	}
1672 
1673 	return 0;
1674 }
1675 
cmd_disable(const struct shell * sh,size_t argc,char * argv[])1676 static int cmd_disable(const struct shell *sh, size_t argc, char *argv[])
1677 {
1678 	int err;
1679 
1680 	if (default_stream == NULL) {
1681 		shell_error(sh, "No stream selected");
1682 		return -ENOEXEC;
1683 	}
1684 
1685 	err = bt_bap_stream_disable(default_stream);
1686 	if (err) {
1687 		shell_error(sh, "Unable to disable Channel");
1688 		return -ENOEXEC;
1689 	}
1690 
1691 	return 0;
1692 }
1693 
1694 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
conn_list_eps(struct bt_conn * conn,void * data)1695 static void conn_list_eps(struct bt_conn *conn, void *data)
1696 {
1697 	const struct shell *sh = (const struct shell *)data;
1698 	uint8_t conn_index = bt_conn_index(conn);
1699 
1700 	shell_print(sh, "Conn: %p", conn);
1701 	shell_print(sh, "  Sinks:");
1702 
1703 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
1704 	for (size_t i = 0U; i < ARRAY_SIZE(snks[conn_index]); i++) {
1705 		const struct bt_bap_ep *ep = snks[conn_index][i];
1706 
1707 		if (ep != NULL) {
1708 			struct bt_bap_ep_info ep_info;
1709 			int err;
1710 
1711 			err = bt_bap_ep_get_info(ep, &ep_info);
1712 			if (err == 0) {
1713 				shell_print(sh, "    #%u: ep %p (state: %d)", i, ep, ep_info.state);
1714 			}
1715 		}
1716 	}
1717 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
1718 
1719 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
1720 	shell_print(sh, "  Sources:");
1721 
1722 	for (size_t i = 0U; i < ARRAY_SIZE(srcs[conn_index]); i++) {
1723 		const struct bt_bap_ep *ep = srcs[conn_index][i];
1724 
1725 		if (ep != NULL) {
1726 			struct bt_bap_ep_info ep_info;
1727 			int err;
1728 
1729 			err = bt_bap_ep_get_info(ep, &ep_info);
1730 			if (err == 0) {
1731 				shell_print(sh, "    #%u: ep %p (state: %d)", i, ep, ep_info.state);
1732 			}
1733 		}
1734 	}
1735 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
1736 }
1737 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1738 
1739 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
cmd_list(const struct shell * sh,size_t argc,char * argv[])1740 static int cmd_list(const struct shell *sh, size_t argc, char *argv[])
1741 {
1742 	shell_print(sh, "Configured Channels:");
1743 
1744 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
1745 		struct bt_bap_stream *stream = &unicast_streams[i].stream.bap_stream;
1746 
1747 		if (stream != NULL && stream->conn != NULL) {
1748 			shell_print(sh, "  %s#%u: stream %p dir 0x%02x group %p",
1749 				    stream == default_stream ? "*" : " ", i, stream,
1750 				    stream_dir(stream), stream->group);
1751 		}
1752 	}
1753 
1754 	bt_conn_foreach(BT_CONN_TYPE_LE, conn_list_eps, (void *)sh);
1755 
1756 	return 0;
1757 }
1758 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1759 
cmd_release(const struct shell * sh,size_t argc,char * argv[])1760 static int cmd_release(const struct shell *sh, size_t argc, char *argv[])
1761 {
1762 	int err;
1763 
1764 	if (default_stream == NULL) {
1765 		shell_print(sh, "No stream selected");
1766 		return -ENOEXEC;
1767 	}
1768 
1769 	err = bt_bap_stream_release(default_stream);
1770 	if (err) {
1771 		shell_error(sh, "Unable to release Channel");
1772 		return -ENOEXEC;
1773 	}
1774 
1775 	return 0;
1776 }
1777 #endif /* CONFIG_BT_BAP_UNICAST */
1778 
1779 #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)1780 static ssize_t parse_config_data_args(const struct shell *sh, size_t argn, size_t argc,
1781 				      char *argv[], struct bt_audio_codec_cfg *codec_cfg)
1782 {
1783 	for (; argn < argc; argn++) {
1784 		const char *arg = argv[argn];
1785 		unsigned long val;
1786 		int err = 0;
1787 
1788 		if (strcmp(arg, "freq") == 0) {
1789 			if (++argn == argc) {
1790 				shell_help(sh);
1791 
1792 				return -1;
1793 			}
1794 
1795 			arg = argv[argn];
1796 
1797 			val = shell_strtoul(arg, 0, &err);
1798 			if (err != 0) {
1799 				shell_error(sh, "Failed to parse freq from %s: %d", arg, err);
1800 
1801 				return -1;
1802 			}
1803 
1804 			if (val > UINT8_MAX) {
1805 				shell_error(sh, "Invalid freq value: %lu", val);
1806 
1807 				return -1;
1808 			}
1809 
1810 			err = bt_audio_codec_cfg_set_freq(codec_cfg,
1811 							  (enum bt_audio_codec_cfg_freq)val);
1812 			if (err < 0) {
1813 				shell_error(sh, "Failed to set freq with value %lu: %d", val, err);
1814 
1815 				return -1;
1816 			}
1817 		} else if (strcmp(arg, "dur") == 0) {
1818 			if (++argn == argc) {
1819 				shell_help(sh);
1820 
1821 				return -1;
1822 			}
1823 
1824 			arg = argv[argn];
1825 
1826 			val = shell_strtoul(arg, 0, &err);
1827 			if (err != 0) {
1828 				shell_error(sh, "Failed to parse dur from %s: %d", arg, err);
1829 
1830 				return -1;
1831 			}
1832 
1833 			if (val > UINT8_MAX) {
1834 				shell_error(sh, "Invalid dur value: %lu", val);
1835 
1836 				return -1;
1837 			}
1838 
1839 			err = bt_audio_codec_cfg_set_frame_dur(
1840 				codec_cfg, (enum bt_audio_codec_cfg_frame_dur)val);
1841 			if (err < 0) {
1842 				shell_error(sh, "Failed to set dur with value %lu: %d", val, err);
1843 
1844 				return -1;
1845 			}
1846 		} else if (strcmp(arg, "chan_alloc") == 0) {
1847 			if (++argn == argc) {
1848 				shell_help(sh);
1849 
1850 				return -1;
1851 			}
1852 
1853 			arg = argv[argn];
1854 
1855 			val = shell_strtoul(arg, 0, &err);
1856 			if (err != 0) {
1857 				shell_error(sh, "Failed to parse chan alloc from %s: %d", arg, err);
1858 
1859 				return -1;
1860 			}
1861 
1862 			if (val > UINT32_MAX) {
1863 				shell_error(sh, "Invalid chan alloc value: %lu", val);
1864 
1865 				return -1;
1866 			}
1867 
1868 			err = bt_audio_codec_cfg_set_chan_allocation(codec_cfg,
1869 								     (enum bt_audio_location)val);
1870 			if (err < 0) {
1871 				shell_error(sh, "Failed to set chan alloc with value %lu: %d", val,
1872 					    err);
1873 
1874 				return -1;
1875 			}
1876 		} else if (strcmp(arg, "frame_len") == 0) {
1877 			if (++argn == argc) {
1878 				shell_help(sh);
1879 
1880 				return -1;
1881 			}
1882 
1883 			arg = argv[argn];
1884 
1885 			val = shell_strtoul(arg, 0, &err);
1886 			if (err != 0) {
1887 				shell_error(sh, "Failed to frame len from %s: %d", arg, err);
1888 
1889 				return -1;
1890 			}
1891 
1892 			if (val > UINT16_MAX) {
1893 				shell_error(sh, "Invalid frame len value: %lu", val);
1894 
1895 				return -1;
1896 			}
1897 
1898 			err = bt_audio_codec_cfg_set_octets_per_frame(codec_cfg, (uint16_t)val);
1899 			if (err < 0) {
1900 				shell_error(sh, "Failed to set frame len with value %lu: %d", val,
1901 					    err);
1902 
1903 				return -1;
1904 			}
1905 		} else if (strcmp(arg, "frame_blks") == 0) {
1906 			if (++argn == argc) {
1907 				shell_help(sh);
1908 
1909 				return -1;
1910 			}
1911 
1912 			arg = argv[argn];
1913 
1914 			val = shell_strtoul(arg, 0, &err);
1915 			if (err != 0) {
1916 				shell_error(sh, "Failed to parse frame blks from %s: %d", arg, err);
1917 
1918 				return -1;
1919 			}
1920 
1921 			if (val > UINT8_MAX) {
1922 				shell_error(sh, "Invalid frame blks value: %lu", val);
1923 
1924 				return -1;
1925 			}
1926 
1927 			err = bt_audio_codec_cfg_set_frame_blocks_per_sdu(codec_cfg, (uint8_t)val);
1928 			if (err < 0) {
1929 				shell_error(sh, "Failed to set frame blks with value %lu: %d", val,
1930 					    err);
1931 
1932 				return -1;
1933 			}
1934 		} else { /* we are no longer parsing codec config values */
1935 			/* Decrement to return taken argument */
1936 			argn--;
1937 			break;
1938 		}
1939 	}
1940 
1941 	return argn;
1942 }
1943 
parse_config_meta_args(const struct shell * sh,size_t argn,size_t argc,char * argv[],struct bt_audio_codec_cfg * codec_cfg)1944 static ssize_t parse_config_meta_args(const struct shell *sh, size_t argn, size_t argc,
1945 				      char *argv[], struct bt_audio_codec_cfg *codec_cfg)
1946 {
1947 	for (; argn < argc; argn++) {
1948 		const char *arg = argv[argn];
1949 		unsigned long val;
1950 		int err = 0;
1951 
1952 		if (strcmp(arg, "pref_ctx") == 0) {
1953 			if (++argn == argc) {
1954 				shell_help(sh);
1955 
1956 				return -1;
1957 			}
1958 
1959 			arg = argv[argn];
1960 
1961 			val = shell_strtoul(arg, 0, &err);
1962 			if (err != 0) {
1963 				shell_error(sh, "Failed to parse pref ctx from %s: %d", arg, err);
1964 
1965 				return -1;
1966 			}
1967 
1968 			if (val > UINT16_MAX) {
1969 				shell_error(sh, "Invalid pref ctx value: %lu", val);
1970 
1971 				return -1;
1972 			}
1973 
1974 			err = bt_audio_codec_cfg_meta_set_pref_context(codec_cfg,
1975 								       (enum bt_audio_context)val);
1976 			if (err < 0) {
1977 				shell_error(sh, "Failed to set pref ctx with value %lu: %d", val,
1978 					    err);
1979 
1980 				return -1;
1981 			}
1982 		} else if (strcmp(arg, "stream_ctx") == 0) {
1983 			if (++argn == argc) {
1984 				shell_help(sh);
1985 
1986 				return -1;
1987 			}
1988 
1989 			arg = argv[argn];
1990 
1991 			val = shell_strtoul(arg, 0, &err);
1992 			if (err != 0) {
1993 				shell_error(sh, "Failed to parse stream ctx from %s: %d", arg, err);
1994 
1995 				return -1;
1996 			}
1997 
1998 			if (val > UINT16_MAX) {
1999 				shell_error(sh, "Invalid stream ctx value: %lu", val);
2000 
2001 				return -1;
2002 			}
2003 
2004 			err = bt_audio_codec_cfg_meta_set_stream_context(
2005 				codec_cfg, (enum bt_audio_context)val);
2006 			if (err < 0) {
2007 				shell_error(sh, "Failed to set stream ctx with value %lu: %d", val,
2008 					    err);
2009 
2010 				return -1;
2011 			}
2012 		} else if (strcmp(arg, "program_info") == 0) {
2013 			if (++argn == argc) {
2014 				shell_help(sh);
2015 
2016 				return -1;
2017 			}
2018 
2019 			arg = argv[argn];
2020 
2021 			err = bt_audio_codec_cfg_meta_set_program_info(codec_cfg, arg, strlen(arg));
2022 			if (err != 0) {
2023 				shell_error(sh, "Failed to set program info with value %s: %d", arg,
2024 					    err);
2025 
2026 				return -1;
2027 			}
2028 		} else if (strcmp(arg, "lang") == 0) {
2029 			if (++argn == argc) {
2030 				shell_help(sh);
2031 
2032 				return -1;
2033 			}
2034 
2035 			arg = argv[argn];
2036 
2037 			if (strlen(arg) != BT_AUDIO_LANG_SIZE) {
2038 				shell_error(sh, "Failed to parse lang from %s", arg);
2039 
2040 				return -1;
2041 			}
2042 
2043 			err = bt_audio_codec_cfg_meta_set_lang(codec_cfg, arg);
2044 			if (err < 0) {
2045 				shell_error(sh, "Failed to set lang with value %s: %d", arg, err);
2046 
2047 				return -1;
2048 			}
2049 		} else if (strcmp(arg, "ccid_list") == 0) {
2050 			uint8_t ccid_list[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE];
2051 			size_t ccid_list_len;
2052 
2053 			if (++argn == argc) {
2054 				shell_help(sh);
2055 
2056 				return -1;
2057 			}
2058 
2059 			arg = argv[argn];
2060 
2061 			ccid_list_len = hex2bin(arg, strlen(arg), ccid_list, sizeof(ccid_list));
2062 			if (ccid_list_len == 0) {
2063 				shell_error(sh, "Failed to parse ccid list from %s", arg);
2064 
2065 				return -1;
2066 			}
2067 
2068 			err = bt_audio_codec_cfg_meta_set_ccid_list(codec_cfg, ccid_list,
2069 								    ccid_list_len);
2070 			if (err < 0) {
2071 				shell_error(sh, "Failed to set ccid list with value %s: %d", arg,
2072 					    err);
2073 
2074 				return -1;
2075 			}
2076 		} else if (strcmp(arg, "parental_rating") == 0) {
2077 			if (++argn == argc) {
2078 				shell_help(sh);
2079 
2080 				return -1;
2081 			}
2082 
2083 			arg = argv[argn];
2084 
2085 			val = shell_strtoul(arg, 0, &err);
2086 			if (err != 0) {
2087 				shell_error(sh, "Failed to parse parental rating from %s: %d", arg,
2088 					    err);
2089 
2090 				return -1;
2091 			}
2092 
2093 			if (val > UINT8_MAX) {
2094 				shell_error(sh, "Invalid parental rating value: %lu", val);
2095 
2096 				return -1;
2097 			}
2098 
2099 			err = bt_audio_codec_cfg_meta_set_parental_rating(
2100 				codec_cfg, (enum bt_audio_parental_rating)val);
2101 			if (err < 0) {
2102 				shell_error(sh, "Failed to set parental rating with value %lu: %d",
2103 					    val, err);
2104 
2105 				return -1;
2106 			}
2107 		} else if (strcmp(arg, "program_info_uri") == 0) {
2108 			if (++argn == argc) {
2109 				shell_help(sh);
2110 
2111 				return -1;
2112 			}
2113 
2114 			arg = argv[argn];
2115 
2116 			err = bt_audio_codec_cfg_meta_set_program_info_uri(codec_cfg, arg,
2117 									   strlen(arg));
2118 			if (err < 0) {
2119 				shell_error(sh, "Failed to set program info URI with value %s: %d",
2120 					    arg, err);
2121 
2122 				return -1;
2123 			}
2124 		} else if (strcmp(arg, "audio_active_state") == 0) {
2125 			if (++argn == argc) {
2126 				shell_help(sh);
2127 
2128 				return -1;
2129 			}
2130 
2131 			arg = argv[argn];
2132 
2133 			val = shell_strtoul(arg, 0, &err);
2134 			if (err != 0) {
2135 				shell_error(sh, "Failed to parse audio active state from %s: %d",
2136 					    arg, err);
2137 
2138 				return -1;
2139 			}
2140 
2141 			if (val > UINT8_MAX) {
2142 				shell_error(sh, "Invalid audio active state value: %lu", val);
2143 
2144 				return -1;
2145 			}
2146 
2147 			err = bt_audio_codec_cfg_meta_set_audio_active_state(
2148 				codec_cfg, (enum bt_audio_active_state)val);
2149 			if (err < 0) {
2150 				shell_error(sh,
2151 					    "Failed to set audio active state with value %lu: %d",
2152 					    val, err);
2153 
2154 				return -1;
2155 			}
2156 		} else if (strcmp(arg, "bcast_flag") == 0) {
2157 			err = bt_audio_codec_cfg_meta_set_bcast_audio_immediate_rend_flag(
2158 				codec_cfg);
2159 			if (err < 0) {
2160 				shell_error(sh, "Failed to set audio active state: %d", err);
2161 
2162 				return -1;
2163 			}
2164 		} else if (strcmp(arg, "extended") == 0) {
2165 			uint8_t extended[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE];
2166 			size_t extended_len;
2167 
2168 			if (++argn == argc) {
2169 				shell_help(sh);
2170 
2171 				return -1;
2172 			}
2173 
2174 			arg = argv[argn];
2175 
2176 			extended_len = hex2bin(arg, strlen(arg), extended, sizeof(extended));
2177 			if (extended_len == 0) {
2178 				shell_error(sh, "Failed to parse extended meta from %s", arg);
2179 
2180 				return -1;
2181 			}
2182 
2183 			err = bt_audio_codec_cfg_meta_set_extended(codec_cfg, extended,
2184 								   extended_len);
2185 			if (err < 0) {
2186 				shell_error(sh, "Failed to set extended meta with value %s: %d",
2187 					    arg, err);
2188 
2189 				return -1;
2190 			}
2191 		} else if (strcmp(arg, "vendor") == 0) {
2192 			uint8_t vendor[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE];
2193 			size_t vendor_len;
2194 
2195 			if (++argn == argc) {
2196 				shell_help(sh);
2197 
2198 				return -1;
2199 			}
2200 
2201 			arg = argv[argn];
2202 
2203 			vendor_len = hex2bin(arg, strlen(arg), vendor, sizeof(vendor));
2204 			if (vendor_len == 0) {
2205 				shell_error(sh, "Failed to parse vendor meta from %s", arg);
2206 
2207 				return -1;
2208 			}
2209 
2210 			err = bt_audio_codec_cfg_meta_set_vendor(codec_cfg, vendor, vendor_len);
2211 			if (err < 0) {
2212 				shell_error(sh, "Failed to set vendor meta with value %s: %d", arg,
2213 					    err);
2214 
2215 				return -1;
2216 			}
2217 		} else { /* we are no longer parsing codec config meta values */
2218 			/* Decrement to return taken argument */
2219 			argn--;
2220 			break;
2221 		}
2222 	}
2223 
2224 	return argn;
2225 }
2226 
cmd_preset(const struct shell * sh,size_t argc,char * argv[])2227 static int cmd_preset(const struct shell *sh, size_t argc, char *argv[])
2228 {
2229 	const struct named_lc3_preset *named_preset;
2230 	enum bt_audio_dir dir;
2231 	bool unicast = true;
2232 
2233 	if (!strcmp(argv[1], "sink")) {
2234 		dir = BT_AUDIO_DIR_SINK;
2235 		named_preset = &default_sink_preset;
2236 	} else if (!strcmp(argv[1], "source")) {
2237 		dir = BT_AUDIO_DIR_SOURCE;
2238 		named_preset = &default_source_preset;
2239 	} else if (!strcmp(argv[1], "broadcast")) {
2240 		unicast = false;
2241 		dir = BT_AUDIO_DIR_SOURCE;
2242 
2243 		named_preset = &default_broadcast_source_preset;
2244 	} else {
2245 		shell_error(sh, "Unsupported dir: %s", argv[1]);
2246 		return -ENOEXEC;
2247 	}
2248 
2249 	if (argc > 2) {
2250 		struct bt_audio_codec_cfg *codec_cfg;
2251 
2252 		named_preset = bap_get_named_preset(unicast, dir, argv[2]);
2253 		if (named_preset == NULL) {
2254 			shell_error(sh, "Unable to parse named_preset %s", argv[2]);
2255 			return -ENOEXEC;
2256 		}
2257 
2258 		if (!strcmp(argv[1], "sink")) {
2259 			named_preset = memcpy(&default_sink_preset, named_preset,
2260 					      sizeof(default_sink_preset));
2261 			codec_cfg = &default_sink_preset.preset.codec_cfg;
2262 		} else if (!strcmp(argv[1], "source")) {
2263 			named_preset = memcpy(&default_source_preset, named_preset,
2264 					      sizeof(default_sink_preset));
2265 			codec_cfg = &default_source_preset.preset.codec_cfg;
2266 		} else if (!strcmp(argv[1], "broadcast")) {
2267 			named_preset = memcpy(&default_broadcast_source_preset, named_preset,
2268 					      sizeof(default_sink_preset));
2269 			codec_cfg = &default_broadcast_source_preset.preset.codec_cfg;
2270 		} else {
2271 			shell_error(sh, "Invalid dir: %s", argv[1]);
2272 
2273 			return -ENOEXEC;
2274 		}
2275 
2276 		if (argc > 3) {
2277 			struct bt_audio_codec_cfg codec_cfg_backup;
2278 
2279 			memcpy(&codec_cfg_backup, codec_cfg, sizeof(codec_cfg_backup));
2280 
2281 			for (size_t argn = 3; argn < argc; argn++) {
2282 				const char *arg = argv[argn];
2283 
2284 				if (strcmp(arg, "config") == 0) {
2285 					ssize_t ret;
2286 
2287 					if (++argn == argc) {
2288 						shell_help(sh);
2289 
2290 						memcpy(codec_cfg, &codec_cfg_backup,
2291 						       sizeof(codec_cfg_backup));
2292 
2293 						return SHELL_CMD_HELP_PRINTED;
2294 					}
2295 
2296 					ret = parse_config_data_args(sh, argn, argc, argv,
2297 								     codec_cfg);
2298 					if (ret < 0) {
2299 						memcpy(codec_cfg, &codec_cfg_backup,
2300 						       sizeof(codec_cfg_backup));
2301 
2302 						return -ENOEXEC;
2303 					}
2304 
2305 					argn = ret;
2306 				} else if (strcmp(arg, "meta") == 0) {
2307 					ssize_t ret;
2308 
2309 					if (++argn == argc) {
2310 						shell_help(sh);
2311 
2312 						memcpy(codec_cfg, &codec_cfg_backup,
2313 						       sizeof(codec_cfg_backup));
2314 
2315 						return SHELL_CMD_HELP_PRINTED;
2316 					}
2317 
2318 					ret = parse_config_meta_args(sh, argn, argc, argv,
2319 								     codec_cfg);
2320 					if (ret < 0) {
2321 						memcpy(codec_cfg, &codec_cfg_backup,
2322 						       sizeof(codec_cfg_backup));
2323 
2324 						return -ENOEXEC;
2325 					}
2326 
2327 					argn = ret;
2328 				} else {
2329 					shell_error(sh, "Invalid argument: %s", arg);
2330 					shell_help(sh);
2331 
2332 					return -ENOEXEC;
2333 				}
2334 			}
2335 		}
2336 	}
2337 
2338 	shell_print(sh, "%s", named_preset->name);
2339 
2340 	print_codec_cfg(ctx_shell, 0, &named_preset->preset.codec_cfg);
2341 	print_qos(ctx_shell, &named_preset->preset.qos);
2342 
2343 	return 0;
2344 }
2345 #endif /* IS_BAP_INITIATOR */
2346 
2347 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
2348 #define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 20 /* Set the timeout relative to interval */
2349 #define PA_SYNC_SKIP         5
2350 
2351 struct bt_broadcast_info {
2352 	uint32_t broadcast_id;
2353 	char broadcast_name[BT_AUDIO_BROADCAST_NAME_LEN_MAX + 1];
2354 };
2355 
2356 static struct broadcast_sink_auto_scan {
2357 	struct broadcast_sink *broadcast_sink;
2358 	struct bt_broadcast_info broadcast_info;
2359 	struct bt_le_per_adv_sync **out_sync;
2360 } auto_scan = {
2361 	.broadcast_info = {
2362 		.broadcast_id = BT_BAP_INVALID_BROADCAST_ID,
2363 	},
2364 };
2365 
clear_auto_scan(void)2366 static void clear_auto_scan(void)
2367 {
2368 	memset(&auto_scan, 0, sizeof(auto_scan));
2369 	auto_scan.broadcast_info.broadcast_id = BT_BAP_INVALID_BROADCAST_ID;
2370 }
2371 
interval_to_sync_timeout(uint16_t interval)2372 static uint16_t interval_to_sync_timeout(uint16_t interval)
2373 {
2374 	uint32_t interval_us;
2375 	uint32_t timeout;
2376 
2377 	/* Add retries and convert to unit in 10's of ms */
2378 	interval_us = BT_GAP_PER_ADV_INTERVAL_TO_US(interval);
2379 	timeout =
2380 		BT_GAP_US_TO_PER_ADV_SYNC_TIMEOUT(interval_us) * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO;
2381 
2382 	/* Enforce restraints */
2383 	timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT);
2384 
2385 	return (uint16_t)timeout;
2386 }
2387 
scan_check_and_sync_broadcast(struct bt_data * data,void * user_data)2388 static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data)
2389 {
2390 	struct bt_broadcast_info *sr_info = (struct bt_broadcast_info *)user_data;
2391 	struct bt_uuid_16 adv_uuid;
2392 
2393 	switch (data->type) {
2394 	case BT_DATA_SVC_DATA16:
2395 		if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) {
2396 			return true;
2397 		}
2398 
2399 		if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) {
2400 			return true;
2401 		}
2402 
2403 		if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO) != 0) {
2404 			return true;
2405 		}
2406 
2407 		sr_info->broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16);
2408 		return true;
2409 	case BT_DATA_BROADCAST_NAME:
2410 		if (!IN_RANGE(data->data_len, BT_AUDIO_BROADCAST_NAME_LEN_MIN,
2411 			      BT_AUDIO_BROADCAST_NAME_LEN_MAX)) {
2412 			return false;
2413 		}
2414 
2415 		memcpy(sr_info->broadcast_name, data->data, data->data_len);
2416 		sr_info->broadcast_name[data->data_len] = '\0';
2417 		return true;
2418 	default:
2419 		return true;
2420 	}
2421 }
2422 
broadcast_scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * ad)2423 static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad)
2424 {
2425 	struct bt_broadcast_info sr_info = {0};
2426 	char addr_str[BT_ADDR_LE_STR_LEN];
2427 	bool identified_broadcast = false;
2428 
2429 	sr_info.broadcast_id = BT_BAP_INVALID_BROADCAST_ID;
2430 
2431 	if ((auto_scan.broadcast_info.broadcast_id == BT_BAP_INVALID_BROADCAST_ID) &&
2432 	    (strlen(auto_scan.broadcast_info.broadcast_name) == 0U)) {
2433 		/* no op */
2434 		return;
2435 	}
2436 
2437 	if (!passes_scan_filter(info, ad)) {
2438 		return;
2439 	}
2440 
2441 	bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)&sr_info);
2442 
2443 	/* Verify that it is a BAP broadcaster*/
2444 	if (sr_info.broadcast_id == BT_BAP_INVALID_BROADCAST_ID) {
2445 		return;
2446 	}
2447 
2448 	bt_addr_le_to_str(info->addr, addr_str, sizeof(addr_str));
2449 
2450 	if (sr_info.broadcast_id == auto_scan.broadcast_info.broadcast_id) {
2451 		identified_broadcast = true;
2452 	} else if ((strlen(auto_scan.broadcast_info.broadcast_name) != 0U) &&
2453 		   is_substring(auto_scan.broadcast_info.broadcast_name, sr_info.broadcast_name)) {
2454 		auto_scan.broadcast_info.broadcast_id = sr_info.broadcast_id;
2455 		identified_broadcast = true;
2456 
2457 		shell_print(ctx_shell, "Found matched broadcast name '%s' with address %s",
2458 			    sr_info.broadcast_name, addr_str);
2459 	}
2460 
2461 	if (identified_broadcast && (auto_scan.broadcast_sink != NULL) &&
2462 	    (auto_scan.broadcast_sink->pa_sync == NULL)) {
2463 		struct bt_le_per_adv_sync_param create_params = {0};
2464 		int err;
2465 
2466 		shell_print(ctx_shell,
2467 			    "Found broadcaster with ID 0x%06X and addr %s and sid 0x%02X ",
2468 			    sr_info.broadcast_id, addr_str, info->sid);
2469 
2470 		err = bt_le_scan_stop();
2471 		if (err != 0) {
2472 			shell_error(ctx_shell, "Could not stop scan: %d", err);
2473 		}
2474 
2475 		bt_addr_le_copy(&create_params.addr, info->addr);
2476 		create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE;
2477 		create_params.sid = info->sid;
2478 		create_params.skip = PA_SYNC_SKIP;
2479 		create_params.timeout = interval_to_sync_timeout(info->interval);
2480 
2481 		shell_print(ctx_shell, "Attempting to PA sync to the broadcaster");
2482 		err = bt_le_per_adv_sync_create(&create_params, auto_scan.out_sync);
2483 		if (err != 0) {
2484 			shell_error(ctx_shell, "Could not create Broadcast PA sync: %d", err);
2485 		} else {
2486 			auto_scan.broadcast_sink->pa_sync = *auto_scan.out_sync;
2487 		}
2488 	}
2489 }
2490 
base_recv(struct bt_bap_broadcast_sink * sink,const struct bt_bap_base * base,size_t base_size)2491 static void base_recv(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base,
2492 		      size_t base_size)
2493 {
2494 	/* Don't print duplicates */
2495 	if (base_size != default_broadcast_sink.base_size ||
2496 	    memcmp(base, &default_broadcast_sink.received_base, base_size) != 0) {
2497 		shell_print(ctx_shell, "Received BASE from sink %p:", sink);
2498 		(void)memcpy(&default_broadcast_sink.received_base, base, base_size);
2499 		default_broadcast_sink.base_size = base_size;
2500 
2501 		print_base(base);
2502 	}
2503 }
2504 
syncable(struct bt_bap_broadcast_sink * sink,const struct bt_iso_biginfo * biginfo)2505 static void syncable(struct bt_bap_broadcast_sink *sink, const struct bt_iso_biginfo *biginfo)
2506 {
2507 	if (default_broadcast_sink.bap_sink == sink) {
2508 		if (default_broadcast_sink.syncable) {
2509 			return;
2510 		}
2511 
2512 		shell_print(ctx_shell, "Sink %p is ready to sync %s encryption", sink,
2513 			    biginfo->encryption ? "with" : "without");
2514 		default_broadcast_sink.syncable = true;
2515 	}
2516 }
2517 
bap_pa_sync_synced_cb(struct bt_le_per_adv_sync * sync,struct bt_le_per_adv_sync_synced_info * info)2518 static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync,
2519 				  struct bt_le_per_adv_sync_synced_info *info)
2520 {
2521 	if (auto_scan.broadcast_sink != NULL && auto_scan.out_sync != NULL &&
2522 	    sync == *auto_scan.out_sync) {
2523 		shell_print(ctx_shell, "PA synced to broadcast with broadcast ID 0x%06x",
2524 			    auto_scan.broadcast_info.broadcast_id);
2525 
2526 		if (auto_scan.broadcast_sink->bap_sink == NULL) {
2527 			shell_print(ctx_shell, "Attempting to create the sink");
2528 			int err;
2529 
2530 			err = bt_bap_broadcast_sink_create(sync,
2531 							   auto_scan.broadcast_info.broadcast_id,
2532 							   &auto_scan.broadcast_sink->bap_sink);
2533 			if (err != 0) {
2534 				shell_error(ctx_shell, "Could not create broadcast sink: %d", err);
2535 			}
2536 		} else {
2537 			shell_print(ctx_shell, "Sink is already created");
2538 		}
2539 	}
2540 
2541 	clear_auto_scan();
2542 }
2543 
bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_term_info * info)2544 static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync,
2545 				      const struct bt_le_per_adv_sync_term_info *info)
2546 {
2547 	if (default_broadcast_sink.pa_sync == sync) {
2548 		default_broadcast_sink.syncable = false;
2549 		(void)memset(&default_broadcast_sink.received_base, 0,
2550 			     sizeof(default_broadcast_sink.received_base));
2551 	}
2552 
2553 	clear_auto_scan();
2554 }
2555 
broadcast_scan_timeout_cb(void)2556 static void broadcast_scan_timeout_cb(void)
2557 {
2558 	shell_print(ctx_shell, "Scan timeout");
2559 
2560 	clear_auto_scan();
2561 }
2562 
2563 static struct bt_bap_broadcast_sink_cb sink_cbs = {
2564 	.base_recv = base_recv,
2565 	.syncable = syncable,
2566 };
2567 
2568 static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = {
2569 	.synced = bap_pa_sync_synced_cb,
2570 	.term = bap_pa_sync_terminated_cb,
2571 };
2572 
2573 static struct bt_le_scan_cb bap_scan_cb = {
2574 	.timeout = broadcast_scan_timeout_cb,
2575 	.recv = broadcast_scan_recv,
2576 };
2577 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
2578 
2579 #if defined(CONFIG_BT_AUDIO_RX)
2580 static size_t rx_streaming_cnt;
2581 
bap_get_rx_streaming_cnt(void)2582 size_t bap_get_rx_streaming_cnt(void)
2583 {
2584 	return rx_streaming_cnt;
2585 }
2586 
2587 #if defined(CONFIG_LIBLC3)
2588 struct lc3_data {
2589 	void *fifo_reserved; /* 1st word reserved for use by FIFO */
2590 	struct net_buf *buf;
2591 	struct shell_stream *sh_stream;
2592 	uint32_t ts;
2593 	bool do_plc;
2594 };
2595 
2596 K_MEM_SLAB_DEFINE(lc3_data_slab, sizeof(struct lc3_data), CONFIG_BT_ISO_RX_BUF_COUNT,
2597 		  __alignof__(struct lc3_data));
2598 
2599 static int16_t lc3_rx_buf[LC3_MAX_NUM_SAMPLES_MONO];
2600 static K_FIFO_DEFINE(lc3_in_fifo);
2601 
2602 /* We only want to send USB to left/right from a single stream. If we have 2 left streams, the
2603  * outgoing audio is going to be terrible.
2604  * Since a stream can contain stereo data, both of these may be the same stream.
2605  */
2606 static struct shell_stream *usb_left_stream;
2607 static struct shell_stream *usb_right_stream;
2608 
init_lc3_decoder(struct shell_stream * sh_stream)2609 static int init_lc3_decoder(struct shell_stream *sh_stream)
2610 {
2611 	if (sh_stream == NULL) {
2612 		shell_error(ctx_shell, "NULL stream to init LC3 decoder");
2613 		return -EINVAL;
2614 	}
2615 
2616 	if (!sh_stream->is_rx) {
2617 		shell_error(ctx_shell, "Invalid stream to init LC3 decoder");
2618 		return -EINVAL;
2619 	}
2620 
2621 	if (sh_stream->rx.lc3_decoder != NULL) {
2622 		shell_error(ctx_shell, "Already initialized");
2623 		return -EALREADY;
2624 	}
2625 
2626 	if (sh_stream->lc3_freq_hz == 0 || sh_stream->lc3_frame_duration_us == 0) {
2627 		shell_error(ctx_shell, "Invalid freq (%u) or frame duration (%u)",
2628 			    sh_stream->lc3_freq_hz, sh_stream->lc3_frame_duration_us);
2629 
2630 		return -EINVAL;
2631 	}
2632 
2633 	shell_print(ctx_shell,
2634 		    "Initializing the LC3 decoder with %u us duration and %u Hz frequency",
2635 		    sh_stream->lc3_frame_duration_us, sh_stream->lc3_freq_hz);
2636 	/* Create the decoder instance. This shall complete before stream_started() is called. */
2637 	sh_stream->rx.lc3_decoder =
2638 		lc3_setup_decoder(sh_stream->lc3_frame_duration_us, sh_stream->lc3_freq_hz,
2639 				  IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) ? USB_SAMPLE_RATE : 0,
2640 				  &sh_stream->rx.lc3_decoder_mem);
2641 	if (sh_stream->rx.lc3_decoder == NULL) {
2642 		shell_error(ctx_shell, "Failed to setup LC3 decoder - wrong parameters?\n");
2643 		return -EINVAL;
2644 	}
2645 
2646 	return 0;
2647 }
2648 
decode_frame(struct lc3_data * data,size_t frame_cnt)2649 static bool decode_frame(struct lc3_data *data, size_t frame_cnt)
2650 {
2651 	const struct shell_stream *sh_stream = data->sh_stream;
2652 	const size_t total_frames = sh_stream->lc3_chan_cnt * sh_stream->lc3_frame_blocks_per_sdu;
2653 	const uint16_t octets_per_frame = sh_stream->lc3_octets_per_frame;
2654 	struct net_buf *buf = data->buf;
2655 	void *iso_data;
2656 	int err;
2657 
2658 	if (data->do_plc) {
2659 		iso_data = NULL; /* perform PLC */
2660 
2661 		if ((sh_stream->rx.decoded_cnt % bap_stats_interval) == 0) {
2662 			shell_print(ctx_shell, "[%zu]: Performing PLC", sh_stream->rx.decoded_cnt);
2663 		}
2664 
2665 		data->do_plc = false; /* clear flag */
2666 	} else {
2667 		iso_data = net_buf_pull_mem(data->buf, octets_per_frame);
2668 
2669 		if ((sh_stream->rx.decoded_cnt % bap_stats_interval) == 0) {
2670 			shell_print(ctx_shell, "[%zu]: Decoding frame of size %u (%u/%u)",
2671 				    sh_stream->rx.decoded_cnt, octets_per_frame, frame_cnt + 1,
2672 				    total_frames);
2673 		}
2674 	}
2675 
2676 	err = lc3_decode(sh_stream->rx.lc3_decoder, iso_data, octets_per_frame, LC3_PCM_FORMAT_S16,
2677 			 lc3_rx_buf, 1);
2678 	if (err < 0) {
2679 		shell_error(ctx_shell, "Failed to decode LC3 data (%u/%u - %u/%u)", frame_cnt + 1,
2680 			    total_frames, octets_per_frame * frame_cnt, buf->len);
2681 		return false;
2682 	}
2683 
2684 	return true;
2685 }
2686 
decode_frame_block(struct lc3_data * data,size_t frame_cnt)2687 static size_t decode_frame_block(struct lc3_data *data, size_t frame_cnt)
2688 {
2689 	const struct shell_stream *sh_stream = data->sh_stream;
2690 	const uint8_t chan_cnt = sh_stream->lc3_chan_cnt;
2691 	size_t decoded_frames = 0U;
2692 
2693 	for (uint8_t i = 0U; i < chan_cnt; i++) {
2694 		/* We provide the total number of decoded frames to `decode_frame` for logging
2695 		 * purposes
2696 		 */
2697 		if (decode_frame(data, frame_cnt + decoded_frames)) {
2698 			decoded_frames++;
2699 
2700 			if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
2701 				enum bt_audio_location chan_alloc;
2702 				int err;
2703 
2704 				err = get_lc3_chan_alloc_from_index(sh_stream, i, &chan_alloc);
2705 				if (err != 0) {
2706 					/* Not suitable for USB */
2707 					continue;
2708 				}
2709 
2710 				/* We only want to left or right from one stream to USB */
2711 				if ((chan_alloc == BT_AUDIO_LOCATION_FRONT_LEFT &&
2712 				     sh_stream != usb_left_stream) ||
2713 				    (chan_alloc == BT_AUDIO_LOCATION_FRONT_RIGHT &&
2714 				     sh_stream != usb_right_stream)) {
2715 					continue;
2716 				}
2717 
2718 				err = bap_usb_add_frame_to_usb(chan_alloc, lc3_rx_buf,
2719 							       sizeof(lc3_rx_buf), data->ts);
2720 				if (err == -EINVAL) {
2721 					continue;
2722 				}
2723 			}
2724 		} else {
2725 			/* If decoding failed, we clear the data to USB as it would contain
2726 			 * invalid data
2727 			 */
2728 			if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
2729 				bap_usb_clear_frames_to_usb();
2730 			}
2731 
2732 			break;
2733 		}
2734 	}
2735 
2736 	return decoded_frames;
2737 }
2738 
do_lc3_decode(struct lc3_data * data)2739 static void do_lc3_decode(struct lc3_data *data)
2740 {
2741 	struct shell_stream *sh_stream = data->sh_stream;
2742 
2743 	if (sh_stream->is_rx && sh_stream->rx.lc3_decoder != NULL) {
2744 		const uint8_t frame_blocks_per_sdu = sh_stream->lc3_frame_blocks_per_sdu;
2745 		size_t frame_cnt;
2746 
2747 		frame_cnt = 0;
2748 		for (uint8_t i = 0U; i < frame_blocks_per_sdu; i++) {
2749 			const size_t decoded_frames = decode_frame_block(data, frame_cnt);
2750 
2751 			if (decoded_frames == 0) {
2752 				break;
2753 			}
2754 
2755 			frame_cnt += decoded_frames;
2756 		}
2757 
2758 		sh_stream->rx.decoded_cnt++;
2759 	}
2760 
2761 	net_buf_unref(data->buf);
2762 }
2763 
lc3_decoder_thread_func(void * arg1,void * arg2,void * arg3)2764 static void lc3_decoder_thread_func(void *arg1, void *arg2, void *arg3)
2765 {
2766 	while (true) {
2767 		struct lc3_data *data = k_fifo_get(&lc3_in_fifo, K_FOREVER);
2768 		struct shell_stream *sh_stream = data->sh_stream;
2769 
2770 		if (sh_stream->is_rx && sh_stream->rx.lc3_decoder == NULL) {
2771 			shell_warn(ctx_shell, "Decoder is NULL, discarding data from FIFO");
2772 			k_mem_slab_free(&lc3_data_slab, (void *)data);
2773 			continue; /* Wait for new data */
2774 		}
2775 
2776 		do_lc3_decode(data);
2777 
2778 		k_mem_slab_free(&lc3_data_slab, (void *)data);
2779 	}
2780 }
2781 
2782 #endif /* CONFIG_LIBLC3*/
2783 
audio_recv(struct bt_bap_stream * stream,const struct bt_iso_recv_info * info,struct net_buf * buf)2784 static void audio_recv(struct bt_bap_stream *stream,
2785 		       const struct bt_iso_recv_info *info,
2786 		       struct net_buf *buf)
2787 {
2788 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(stream);
2789 
2790 	if (!sh_stream->is_rx) {
2791 		return;
2792 	}
2793 
2794 	sh_stream->rx.rx_cnt++;
2795 
2796 	if (info->ts == sh_stream->rx.last_info.ts) {
2797 		sh_stream->rx.dup_ts++;
2798 	}
2799 
2800 	if (info->seq_num == sh_stream->rx.last_info.seq_num) {
2801 		sh_stream->rx.dup_psn++;
2802 	}
2803 
2804 	if ((info->flags & BT_ISO_FLAGS_VALID) != 0) {
2805 		if (buf->len == 0U) {
2806 			sh_stream->rx.empty_sdu_pkts++;
2807 		} else {
2808 			sh_stream->rx.valid_sdu_pkts++;
2809 		}
2810 	}
2811 
2812 	if (info->flags & BT_ISO_FLAGS_ERROR) {
2813 		sh_stream->rx.err_pkts++;
2814 	}
2815 
2816 	if (info->flags & BT_ISO_FLAGS_LOST) {
2817 		sh_stream->rx.lost_pkts++;
2818 	}
2819 
2820 	if ((sh_stream->rx.rx_cnt % bap_stats_interval) == 0) {
2821 		shell_print(ctx_shell,
2822 			    "[%zu]: Incoming audio on stream %p len %u ts %u seq_num %u flags %u "
2823 			    "(valid %zu, dup ts %zu, dup psn %zu, err_pkts %zu, lost_pkts %zu, "
2824 			    "empty SDUs %zu)",
2825 			    sh_stream->rx.rx_cnt, stream, buf->len, info->ts, info->seq_num,
2826 			    info->flags, sh_stream->rx.valid_sdu_pkts, sh_stream->rx.dup_ts,
2827 			    sh_stream->rx.dup_psn, sh_stream->rx.err_pkts, sh_stream->rx.lost_pkts,
2828 			    sh_stream->rx.empty_sdu_pkts);
2829 	}
2830 
2831 	(void)memcpy(&sh_stream->rx.last_info, info, sizeof(sh_stream->rx.last_info));
2832 
2833 #if defined(CONFIG_LIBLC3)
2834 	if (sh_stream->rx.lc3_decoder != NULL) {
2835 		const uint8_t frame_blocks_per_sdu = sh_stream->lc3_frame_blocks_per_sdu;
2836 		const uint16_t octets_per_frame = sh_stream->lc3_octets_per_frame;
2837 		const uint8_t chan_cnt = sh_stream->lc3_chan_cnt;
2838 		struct lc3_data *data;
2839 
2840 		/* Allocate a context that holds both the buffer and the stream so that we can
2841 		 * send both of these values to the LC3 decoder thread as a single struct
2842 		 * in a FIFO
2843 		 */
2844 		if (k_mem_slab_alloc(&lc3_data_slab, (void **)&data, K_NO_WAIT)) {
2845 			shell_warn(ctx_shell, "Could not allocate LC3 data item");
2846 
2847 			return;
2848 		}
2849 
2850 		if ((info->flags & BT_ISO_FLAGS_VALID) == 0) {
2851 			data->do_plc = true;
2852 		} else if (buf->len != (octets_per_frame * chan_cnt * frame_blocks_per_sdu)) {
2853 			if (buf->len != 0U) {
2854 				shell_error(
2855 					ctx_shell,
2856 					"Expected %u frame blocks with %u channels of size %u, but "
2857 					"length is %u",
2858 					frame_blocks_per_sdu, chan_cnt, octets_per_frame, buf->len);
2859 			}
2860 
2861 			data->do_plc = true;
2862 		}
2863 
2864 		data->buf = net_buf_ref(buf);
2865 		data->sh_stream = sh_stream;
2866 		if (info->flags & BT_ISO_FLAGS_TS) {
2867 			data->ts = info->ts;
2868 		} else {
2869 			data->ts = 0U;
2870 		}
2871 
2872 		k_fifo_put(&lc3_in_fifo, data);
2873 	}
2874 #endif /* CONFIG_LIBLC3 */
2875 }
2876 #endif /* CONFIG_BT_AUDIO_RX */
2877 
2878 #if defined(CONFIG_BT_BAP_UNICAST)
stream_enabled_cb(struct bt_bap_stream * stream)2879 static void stream_enabled_cb(struct bt_bap_stream *stream)
2880 {
2881 	shell_print(ctx_shell, "Stream %p enabled", stream);
2882 
2883 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER)) {
2884 		struct bt_bap_ep_info ep_info;
2885 		struct bt_conn_info conn_info;
2886 		int err;
2887 
2888 		err = bt_conn_get_info(stream->conn, &conn_info);
2889 		if (err != 0) {
2890 			shell_error(ctx_shell, "Failed to get conn info: %d", err);
2891 			return;
2892 		}
2893 
2894 		if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
2895 			return; /* We also want to autonomously start the stream as the server */
2896 		}
2897 
2898 		err = bt_bap_ep_get_info(stream->ep, &ep_info);
2899 		if (err != 0) {
2900 			shell_error(ctx_shell, "Failed to get ep info: %d", err);
2901 			return;
2902 		}
2903 
2904 		if (ep_info.dir == BT_AUDIO_DIR_SINK) {
2905 			/* Automatically do the receiver start ready operation */
2906 			err = bt_bap_stream_start(stream);
2907 
2908 			if (err != 0) {
2909 				shell_error(ctx_shell, "Failed to start stream: %d", err);
2910 				return;
2911 			}
2912 		}
2913 	}
2914 }
2915 #endif /* CONFIG_BT_BAP_UNICAST */
2916 
stream_started_cb(struct bt_bap_stream * bap_stream)2917 static void stream_started_cb(struct bt_bap_stream *bap_stream)
2918 {
2919 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(bap_stream);
2920 	struct bt_bap_ep_info info = {0};
2921 	int ret;
2922 
2923 	printk("Stream %p started\n", bap_stream);
2924 
2925 	ret = bt_bap_ep_get_info(bap_stream->ep, &info);
2926 	if (ret != 0) {
2927 		shell_error(ctx_shell, "Failed to get EP info: %d", ret);
2928 		return;
2929 	}
2930 
2931 	sh_stream->is_rx = info.can_recv;
2932 	sh_stream->is_tx = info.can_send;
2933 
2934 #if defined(CONFIG_LIBLC3)
2935 	const struct bt_audio_codec_cfg *codec_cfg = bap_stream->codec_cfg;
2936 
2937 	if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
2938 		if (sh_stream->is_tx) {
2939 			atomic_set(&sh_stream->tx.lc3_enqueue_cnt, PRIME_COUNT);
2940 			sh_stream->tx.lc3_sdu_cnt = 0U;
2941 		}
2942 
2943 		ret = bt_audio_codec_cfg_get_freq(codec_cfg);
2944 		if (ret >= 0) {
2945 			ret = bt_audio_codec_cfg_freq_to_freq_hz(ret);
2946 
2947 			if (ret > 0) {
2948 				if (ret == 8000 || ret == 16000 || ret == 24000 || ret == 32000 ||
2949 				    ret == 48000) {
2950 					sh_stream->lc3_freq_hz = (uint32_t)ret;
2951 				} else {
2952 					shell_error(ctx_shell, "Unsupported frequency for LC3: %d",
2953 						    ret);
2954 					sh_stream->lc3_freq_hz = 0U;
2955 				}
2956 			} else {
2957 				shell_error(ctx_shell, "Invalid frequency: %d", ret);
2958 				sh_stream->lc3_freq_hz = 0U;
2959 			}
2960 		} else {
2961 			shell_error(ctx_shell, "Could not get frequency: %d", ret);
2962 			sh_stream->lc3_freq_hz = 0U;
2963 		}
2964 
2965 		ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg);
2966 		if (ret >= 0) {
2967 			ret = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret);
2968 			if (ret > 0) {
2969 				sh_stream->lc3_frame_duration_us = (uint32_t)ret;
2970 			} else {
2971 				shell_error(ctx_shell, "Invalid frame duration: %d", ret);
2972 				sh_stream->lc3_frame_duration_us = 0U;
2973 			}
2974 		} else {
2975 			shell_error(ctx_shell, "Could not get frame duration: %d", ret);
2976 			sh_stream->lc3_frame_duration_us = 0U;
2977 		}
2978 
2979 		ret = bt_audio_codec_cfg_get_chan_allocation(
2980 			codec_cfg, &sh_stream->lc3_chan_allocation, false);
2981 		if (ret == 0) {
2982 			sh_stream->lc3_chan_cnt =
2983 				bt_audio_get_chan_count(sh_stream->lc3_chan_allocation);
2984 		} else {
2985 			shell_error(ctx_shell, "Could not get channel allocation: %d", ret);
2986 			sh_stream->lc3_chan_allocation = BT_AUDIO_LOCATION_MONO_AUDIO;
2987 			sh_stream->lc3_chan_cnt = 1U;
2988 		}
2989 
2990 		ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true);
2991 		if (ret >= 0) {
2992 			sh_stream->lc3_frame_blocks_per_sdu = (uint8_t)ret;
2993 		} else {
2994 			shell_error(ctx_shell, "Could not get frame blocks per SDU: %d", ret);
2995 			sh_stream->lc3_frame_blocks_per_sdu = 0U;
2996 		}
2997 
2998 		ret = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg);
2999 		if (ret >= 0) {
3000 			sh_stream->lc3_octets_per_frame = (uint16_t)ret;
3001 		} else {
3002 			shell_error(ctx_shell, "Could not get octets per frame: %d", ret);
3003 			sh_stream->lc3_octets_per_frame = 0U;
3004 		}
3005 
3006 #if defined(CONFIG_BT_AUDIO_TX)
3007 		if (sh_stream->is_tx && sh_stream->tx.lc3_encoder == NULL) {
3008 			const int err = init_lc3_encoder(sh_stream);
3009 
3010 			if (err != 0) {
3011 				shell_error(ctx_shell, "Failed to init LC3 encoder: %d", err);
3012 
3013 				return;
3014 			}
3015 
3016 			if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
3017 				/* Always mark as active when using USB */
3018 				sh_stream->tx.active = true;
3019 			}
3020 		}
3021 #endif /* CONFIG_BT_AUDIO_TX */
3022 
3023 #if defined(CONFIG_BT_AUDIO_RX)
3024 		if (sh_stream->is_rx) {
3025 			if (sh_stream->rx.lc3_decoder == NULL) {
3026 				const int err = init_lc3_decoder(sh_stream);
3027 
3028 				if (err != 0) {
3029 					shell_error(ctx_shell, "Failed to init LC3 decoder: %d",
3030 						    err);
3031 
3032 					return;
3033 				}
3034 			}
3035 
3036 			sh_stream->rx.decoded_cnt = 0U;
3037 
3038 			if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
3039 				if ((sh_stream->lc3_chan_allocation &
3040 				     BT_AUDIO_LOCATION_FRONT_LEFT) != 0) {
3041 					if (usb_left_stream == NULL) {
3042 						shell_info(ctx_shell,
3043 							   "Setting USB left stream to %p",
3044 							   sh_stream);
3045 						usb_left_stream = sh_stream;
3046 					} else {
3047 						shell_warn(ctx_shell,
3048 							   "Multiple left streams started");
3049 					}
3050 				}
3051 
3052 				if ((sh_stream->lc3_chan_allocation &
3053 				     BT_AUDIO_LOCATION_FRONT_RIGHT) != 0) {
3054 					if (usb_right_stream == NULL) {
3055 						shell_info(ctx_shell,
3056 							   "Setting USB right stream to %p",
3057 							   sh_stream);
3058 						usb_right_stream = sh_stream;
3059 					} else {
3060 						shell_warn(ctx_shell,
3061 							   "Multiple right streams started");
3062 					}
3063 				}
3064 			}
3065 		}
3066 #endif /* CONFIG_BT_AUDIO_RX */
3067 	}
3068 #endif /* CONFIG_LIBLC3 */
3069 
3070 #if defined(CONFIG_BT_AUDIO_TX)
3071 	if (sh_stream->is_tx) {
3072 		sh_stream->tx.connected_at_ticks = k_uptime_ticks();
3073 	}
3074 #endif /* CONFIG_BT_AUDIO_TX */
3075 
3076 #if defined(CONFIG_BT_AUDIO_RX)
3077 	if (sh_stream->is_rx) {
3078 		sh_stream->rx.empty_sdu_pkts = 0U;
3079 		sh_stream->rx.valid_sdu_pkts = 0U;
3080 		sh_stream->rx.lost_pkts = 0U;
3081 		sh_stream->rx.err_pkts = 0U;
3082 		sh_stream->rx.dup_psn = 0U;
3083 		sh_stream->rx.rx_cnt = 0U;
3084 		sh_stream->rx.dup_ts = 0U;
3085 
3086 		rx_streaming_cnt++;
3087 	}
3088 #endif
3089 }
3090 
3091 #if defined(CONFIG_LIBLC3)
update_usb_streams_cb(struct shell_stream * sh_stream,void * user_data)3092 static void update_usb_streams_cb(struct shell_stream *sh_stream, void *user_data)
3093 {
3094 	if (sh_stream->is_rx) {
3095 		if (usb_left_stream == NULL &&
3096 		    (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0) {
3097 			shell_info(ctx_shell, "Setting new USB left stream to %p", sh_stream);
3098 			usb_left_stream = sh_stream;
3099 		}
3100 
3101 		if (usb_right_stream == NULL &&
3102 		    (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0) {
3103 			shell_info(ctx_shell, "Setting new USB right stream to %p", sh_stream);
3104 			usb_right_stream = sh_stream;
3105 		}
3106 	}
3107 }
3108 
update_usb_streams(struct shell_stream * sh_stream)3109 static void update_usb_streams(struct shell_stream *sh_stream)
3110 {
3111 	if (sh_stream->is_rx) {
3112 		if (sh_stream == usb_left_stream) {
3113 			shell_info(ctx_shell, "Clearing USB left stream (%p)", usb_left_stream);
3114 			usb_left_stream = NULL;
3115 		}
3116 
3117 		if (sh_stream == usb_right_stream) {
3118 			shell_info(ctx_shell, "Clearing USB right stream (%p)", usb_right_stream);
3119 			usb_right_stream = NULL;
3120 		}
3121 
3122 		bap_foreach_stream(update_usb_streams_cb, NULL);
3123 	}
3124 }
3125 #endif /* CONFIG_LIBLC3 */
3126 
clear_stream_data(struct shell_stream * sh_stream)3127 static void clear_stream_data(struct shell_stream *sh_stream)
3128 {
3129 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
3130 	if (IS_ARRAY_ELEMENT(broadcast_sink_streams, sh_stream)) {
3131 		if (default_broadcast_sink.stream_cnt != 0) {
3132 			default_broadcast_sink.stream_cnt--;
3133 		}
3134 
3135 		if (default_broadcast_sink.stream_cnt == 0) {
3136 			/* All streams in the broadcast sink has been terminated */
3137 			memset(&default_broadcast_sink.received_base, 0,
3138 			       sizeof(default_broadcast_sink.received_base));
3139 			default_broadcast_sink.broadcast_id = 0;
3140 			default_broadcast_sink.syncable = false;
3141 		}
3142 	}
3143 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
3144 
3145 #if defined(CONFIG_BT_AUDIO_RX)
3146 	if (sh_stream->is_rx) {
3147 		rx_streaming_cnt--;
3148 		memset(&sh_stream->rx, 0, sizeof(sh_stream->rx));
3149 	}
3150 #endif
3151 
3152 #if defined(CONFIG_BT_AUDIO_TX)
3153 	if (sh_stream->is_tx) {
3154 		memset(&sh_stream->tx, 0, sizeof(sh_stream->tx));
3155 	}
3156 #endif
3157 
3158 	sh_stream->is_rx = sh_stream->is_tx = false;
3159 
3160 #if defined(CONFIG_LIBLC3)
3161 	if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
3162 		update_usb_streams(sh_stream);
3163 	}
3164 #endif /* CONFIG_LIBLC3 */
3165 }
3166 
stream_stopped_cb(struct bt_bap_stream * stream,uint8_t reason)3167 static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
3168 {
3169 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(stream);
3170 
3171 	printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
3172 
3173 	clear_stream_data(sh_stream);
3174 }
3175 
3176 #if defined(CONFIG_BT_BAP_UNICAST)
stream_configured_cb(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg_pref * pref)3177 static void stream_configured_cb(struct bt_bap_stream *stream,
3178 				 const struct bt_bap_qos_cfg_pref *pref)
3179 {
3180 	shell_print(ctx_shell, "Stream %p configured\n", stream);
3181 }
3182 
stream_released_cb(struct bt_bap_stream * stream)3183 static void stream_released_cb(struct bt_bap_stream *stream)
3184 {
3185 	struct shell_stream *sh_stream = shell_stream_from_bap_stream(stream);
3186 
3187 	shell_print(ctx_shell, "Stream %p released\n", stream);
3188 
3189 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
3190 	if (default_unicast_group != NULL) {
3191 		bool group_can_be_deleted = true;
3192 
3193 		for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
3194 			const struct bt_bap_stream *bap_stream =
3195 				bap_stream_from_shell_stream(&unicast_streams[i]);
3196 
3197 			if (bap_stream->ep != NULL) {
3198 				struct bt_bap_ep_info ep_info;
3199 				int err;
3200 
3201 				err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
3202 				if (err == 0 && ep_info.state != BT_BAP_EP_STATE_CODEC_CONFIGURED &&
3203 				    ep_info.state != BT_BAP_EP_STATE_IDLE) {
3204 					group_can_be_deleted = false;
3205 					break;
3206 				}
3207 			}
3208 		}
3209 
3210 		if (group_can_be_deleted) {
3211 			int err;
3212 
3213 			shell_print(ctx_shell, "All streams released, deleting group\n");
3214 
3215 			err = bt_bap_unicast_group_delete(default_unicast_group);
3216 
3217 			if (err != 0) {
3218 				shell_error(ctx_shell, "Failed to delete unicast group: %d", err);
3219 			} else {
3220 				default_unicast_group = NULL;
3221 			}
3222 		}
3223 	}
3224 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
3225 
3226 	clear_stream_data(sh_stream);
3227 }
3228 #endif /* CONFIG_BT_BAP_UNICAST */
3229 
3230 static struct bt_bap_stream_ops stream_ops = {
3231 #if defined(CONFIG_BT_AUDIO_RX)
3232 	.recv = audio_recv,
3233 #endif /* CONFIG_BT_AUDIO_RX */
3234 #if defined(CONFIG_BT_BAP_UNICAST)
3235 	.configured = stream_configured_cb,
3236 	.released = stream_released_cb,
3237 	.enabled = stream_enabled_cb,
3238 #endif /* CONFIG_BT_BAP_UNICAST */
3239 	.started = stream_started_cb,
3240 	.stopped = stream_stopped_cb,
3241 #if defined(CONFIG_LIBLC3) && defined(CONFIG_BT_AUDIO_TX)
3242 	.sent = lc3_sent_cb,
3243 #endif
3244 };
3245 
3246 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
cmd_select_broadcast_source(const struct shell * sh,size_t argc,char * argv[])3247 static int cmd_select_broadcast_source(const struct shell *sh, size_t argc,
3248 				       char *argv[])
3249 {
3250 	unsigned long index;
3251 	int err = 0;
3252 
3253 	index = shell_strtoul(argv[1], 0, &err);
3254 	if (err != 0) {
3255 		shell_error(sh, "Could not parse index: %d", err);
3256 
3257 		return -ENOEXEC;
3258 	}
3259 
3260 	if (index > ARRAY_SIZE(broadcast_source_streams)) {
3261 		shell_error(sh, "Invalid index: %lu", index);
3262 
3263 		return -ENOEXEC;
3264 	}
3265 
3266 	default_stream = bap_stream_from_shell_stream(&broadcast_source_streams[index]);
3267 
3268 	return 0;
3269 }
3270 
cmd_create_broadcast(const struct shell * sh,size_t argc,char * argv[])3271 static int cmd_create_broadcast(const struct shell *sh, size_t argc,
3272 				char *argv[])
3273 {
3274 	struct bt_bap_broadcast_source_stream_param
3275 		stream_params[ARRAY_SIZE(broadcast_source_streams)];
3276 	struct bt_bap_broadcast_source_subgroup_param subgroup_param;
3277 	struct bt_bap_broadcast_source_param create_param = {0};
3278 	const struct named_lc3_preset *named_preset;
3279 	int err;
3280 
3281 	if (default_source.bap_source != NULL) {
3282 		shell_info(sh, "Broadcast source already created");
3283 		return -ENOEXEC;
3284 	}
3285 
3286 	named_preset = &default_broadcast_source_preset;
3287 
3288 	for (size_t i = 1U; i < argc; i++) {
3289 		char *arg = argv[i];
3290 
3291 		if (strcmp(arg, "enc") == 0) {
3292 			if (argc > i) {
3293 				size_t bcode_len;
3294 
3295 				i++;
3296 				arg = argv[i];
3297 
3298 				bcode_len = hex2bin(arg, strlen(arg),
3299 						    create_param.broadcast_code,
3300 						    sizeof(create_param.broadcast_code));
3301 
3302 				if (bcode_len != sizeof(create_param.broadcast_code)) {
3303 					shell_error(sh, "Invalid Broadcast Code Length: %zu",
3304 						    bcode_len);
3305 
3306 					return -ENOEXEC;
3307 				}
3308 
3309 				create_param.encryption = true;
3310 			} else {
3311 				shell_help(sh);
3312 
3313 				return SHELL_CMD_HELP_PRINTED;
3314 			}
3315 		} else if (strcmp(arg, "preset") == 0) {
3316 			if (argc > i) {
3317 
3318 				i++;
3319 				arg = argv[i];
3320 
3321 				named_preset = bap_get_named_preset(false, BT_AUDIO_DIR_SOURCE,
3322 								    arg);
3323 				if (named_preset == NULL) {
3324 					shell_error(sh, "Unable to parse named_preset %s",
3325 						    arg);
3326 
3327 					return -ENOEXEC;
3328 				}
3329 			} else {
3330 				shell_help(sh);
3331 
3332 				return SHELL_CMD_HELP_PRINTED;
3333 			}
3334 		}
3335 	}
3336 
3337 	copy_broadcast_source_preset(&default_source, named_preset);
3338 
3339 	(void)memset(stream_params, 0, sizeof(stream_params));
3340 	for (size_t i = 0; i < ARRAY_SIZE(stream_params); i++) {
3341 		stream_params[i].stream =
3342 			bap_stream_from_shell_stream(&broadcast_source_streams[i]);
3343 	}
3344 	subgroup_param.params_count = ARRAY_SIZE(stream_params);
3345 	subgroup_param.params = stream_params;
3346 	subgroup_param.codec_cfg = &default_source.codec_cfg;
3347 	create_param.params_count = 1U;
3348 	create_param.params = &subgroup_param;
3349 	create_param.qos = &default_source.qos;
3350 
3351 	err = bt_bap_broadcast_source_create(&create_param, &default_source.bap_source);
3352 	if (err != 0) {
3353 		shell_error(sh, "Unable to create broadcast source: %d", err);
3354 		return err;
3355 	}
3356 
3357 	shell_print(sh, "Broadcast source created: preset %s",
3358 		    named_preset->name);
3359 
3360 	if (default_stream == NULL) {
3361 		default_stream = bap_stream_from_shell_stream(&broadcast_source_streams[0]);
3362 	}
3363 
3364 	return 0;
3365 }
3366 
cmd_start_broadcast(const struct shell * sh,size_t argc,char * argv[])3367 static int cmd_start_broadcast(const struct shell *sh, size_t argc,
3368 			       char *argv[])
3369 {
3370 	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
3371 	int err;
3372 
3373 	if (adv == NULL) {
3374 		shell_info(sh, "Extended advertising set is NULL");
3375 		return -ENOEXEC;
3376 	}
3377 
3378 	if (default_source.bap_source == NULL || default_source.is_cap) {
3379 		shell_info(sh, "Broadcast source not created");
3380 		return -ENOEXEC;
3381 	}
3382 
3383 	err = bt_bap_broadcast_source_start(default_source.bap_source, adv_sets[selected_adv]);
3384 	if (err != 0) {
3385 		shell_error(sh, "Unable to start broadcast source: %d", err);
3386 		return err;
3387 	}
3388 
3389 	return 0;
3390 }
3391 
cmd_stop_broadcast(const struct shell * sh,size_t argc,char * argv[])3392 static int cmd_stop_broadcast(const struct shell *sh, size_t argc, char *argv[])
3393 {
3394 	int err;
3395 
3396 	if (default_source.bap_source == NULL || default_source.is_cap) {
3397 		shell_info(sh, "Broadcast source not created");
3398 		return -ENOEXEC;
3399 	}
3400 
3401 	err = bt_bap_broadcast_source_stop(default_source.bap_source);
3402 	if (err != 0) {
3403 		shell_error(sh, "Unable to stop broadcast source: %d", err);
3404 		return err;
3405 	}
3406 
3407 	return 0;
3408 }
3409 
cmd_delete_broadcast(const struct shell * sh,size_t argc,char * argv[])3410 static int cmd_delete_broadcast(const struct shell *sh, size_t argc,
3411 				char *argv[])
3412 {
3413 	int err;
3414 
3415 	if (default_source.bap_source == NULL || default_source.is_cap) {
3416 		shell_info(sh, "Broadcast source not created");
3417 		return -ENOEXEC;
3418 	}
3419 
3420 	err = bt_bap_broadcast_source_delete(default_source.bap_source);
3421 	if (err != 0) {
3422 		shell_error(sh, "Unable to delete broadcast source: %d", err);
3423 		return err;
3424 	}
3425 	default_source.bap_source = NULL;
3426 
3427 	return 0;
3428 }
3429 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
3430 
3431 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
cmd_create_broadcast_sink(const struct shell * sh,size_t argc,char * argv[])3432 static int cmd_create_broadcast_sink(const struct shell *sh, size_t argc, char *argv[])
3433 {
3434 	struct bt_le_per_adv_sync *per_adv_sync = per_adv_syncs[selected_per_adv_sync];
3435 	unsigned long broadcast_id;
3436 	int err = 0;
3437 
3438 	broadcast_id = shell_strtoul(argv[1], 0, &err);
3439 	if (err != 0) {
3440 		shell_error(sh, "Could not parse broadcast_id: %d", err);
3441 
3442 		return -ENOEXEC;
3443 	}
3444 
3445 	if (broadcast_id > BT_AUDIO_BROADCAST_ID_MAX) {
3446 		shell_error(sh, "Invalid broadcast_id: %lu", broadcast_id);
3447 
3448 		return -ENOEXEC;
3449 	}
3450 
3451 	if (per_adv_sync == NULL) {
3452 		const struct bt_le_scan_param param = {
3453 			.type = BT_LE_SCAN_TYPE_PASSIVE,
3454 			.options = BT_LE_SCAN_OPT_NONE,
3455 			.interval = BT_GAP_SCAN_FAST_INTERVAL,
3456 			.window = BT_GAP_SCAN_FAST_WINDOW,
3457 			.timeout = 1000, /* 10ms units -> 10 second timeout */
3458 		};
3459 
3460 		shell_print(sh, "No PA sync available, starting scanning for broadcast_id");
3461 
3462 		err = bt_le_scan_start(&param, NULL);
3463 		if (err) {
3464 			shell_print(sh, "Fail to start scanning: %d", err);
3465 
3466 			return -ENOEXEC;
3467 		}
3468 
3469 		auto_scan.broadcast_sink = &default_broadcast_sink;
3470 		auto_scan.broadcast_info.broadcast_id = broadcast_id;
3471 		auto_scan.out_sync = &per_adv_syncs[selected_per_adv_sync];
3472 	} else {
3473 		shell_print(sh, "Creating broadcast sink with broadcast ID 0x%06X",
3474 			    (uint32_t)broadcast_id);
3475 
3476 		err = bt_bap_broadcast_sink_create(per_adv_sync, (uint32_t)broadcast_id,
3477 						   &default_broadcast_sink.bap_sink);
3478 
3479 		if (err != 0) {
3480 			shell_error(sh, "Failed to create broadcast sink: %d", err);
3481 
3482 			return -ENOEXEC;
3483 		}
3484 	}
3485 
3486 	return 0;
3487 }
3488 
cmd_create_sink_by_name(const struct shell * sh,size_t argc,char * argv[])3489 static int cmd_create_sink_by_name(const struct shell *sh, size_t argc, char *argv[])
3490 {
3491 	const struct bt_le_scan_param param = {
3492 		.type = BT_LE_SCAN_TYPE_PASSIVE,
3493 		.options = BT_LE_SCAN_OPT_NONE,
3494 		.interval = BT_GAP_SCAN_FAST_INTERVAL,
3495 		.window = BT_GAP_SCAN_FAST_WINDOW,
3496 		.timeout = 1000, /* 10ms units -> 10 second timeout */
3497 	};
3498 	char *broadcast_name;
3499 	int err = 0;
3500 
3501 	broadcast_name = argv[1];
3502 	if (!IN_RANGE(strlen(broadcast_name), BT_AUDIO_BROADCAST_NAME_LEN_MIN,
3503 		      BT_AUDIO_BROADCAST_NAME_LEN_MAX)) {
3504 		shell_error(sh, "Broadcast name should be minimum %d and maximum %d characters",
3505 			    BT_AUDIO_BROADCAST_NAME_LEN_MIN, BT_AUDIO_BROADCAST_NAME_LEN_MAX);
3506 
3507 		return -ENOEXEC;
3508 	}
3509 
3510 	shell_print(sh, "Starting scanning for broadcast_name");
3511 
3512 	err = bt_le_scan_start(&param, NULL);
3513 	if (err) {
3514 		shell_print(sh, "Fail to start scanning: %d", err);
3515 
3516 		return -ENOEXEC;
3517 	}
3518 
3519 	memcpy(auto_scan.broadcast_info.broadcast_name, broadcast_name, strlen(broadcast_name));
3520 	auto_scan.broadcast_info.broadcast_name[strlen(broadcast_name)] = '\0';
3521 
3522 	auto_scan.broadcast_info.broadcast_id = BT_BAP_INVALID_BROADCAST_ID;
3523 	auto_scan.broadcast_sink = &default_broadcast_sink;
3524 	auto_scan.out_sync = &per_adv_syncs[selected_per_adv_sync];
3525 
3526 	return 0;
3527 }
3528 
cmd_sync_broadcast(const struct shell * sh,size_t argc,char * argv[])3529 static int cmd_sync_broadcast(const struct shell *sh, size_t argc, char *argv[])
3530 {
3531 	struct bt_bap_stream *streams[ARRAY_SIZE(broadcast_sink_streams)];
3532 	uint8_t bcode[BT_ISO_BROADCAST_CODE_SIZE] = {0};
3533 	bool bcode_set = false;
3534 	uint32_t bis_bitfield;
3535 	size_t stream_cnt;
3536 	int err = 0;
3537 
3538 	bis_bitfield = 0;
3539 	stream_cnt = 0U;
3540 	for (size_t argn = 1U; argn < argc; argn++) {
3541 		const char *arg = argv[argn];
3542 
3543 		if (strcmp(argv[argn], "bcode") == 0) {
3544 			size_t len;
3545 
3546 			if (++argn == argc) {
3547 				shell_help(sh);
3548 
3549 				return SHELL_CMD_HELP_PRINTED;
3550 			}
3551 
3552 			arg = argv[argn];
3553 
3554 			len = hex2bin(arg, strlen(arg), bcode, sizeof(bcode));
3555 			if (len == 0) {
3556 				shell_print(sh, "Invalid broadcast code: %s", arg);
3557 
3558 				return -ENOEXEC;
3559 			}
3560 
3561 			bcode_set = true;
3562 		} else if (strcmp(argv[argn], "bcode_str") == 0) {
3563 			if (++argn == argc) {
3564 				shell_help(sh);
3565 
3566 				return SHELL_CMD_HELP_PRINTED;
3567 			}
3568 
3569 			arg = argv[argn];
3570 
3571 			if (strlen(arg) == 0U || strlen(arg) > sizeof(bcode)) {
3572 				shell_print(sh, "Invalid broadcast code: %s", arg);
3573 
3574 				return -ENOEXEC;
3575 			}
3576 
3577 			memcpy(bcode, arg, strlen(arg));
3578 			bcode_set = true;
3579 		} else {
3580 			unsigned long val;
3581 
3582 			val = shell_strtoul(arg, 0, &err);
3583 			if (err != 0) {
3584 				shell_error(sh, "Could not parse BIS index val: %d", err);
3585 
3586 				return -ENOEXEC;
3587 			}
3588 
3589 			if (!IN_RANGE(val, BT_ISO_BIS_INDEX_MIN, BT_ISO_BIS_INDEX_MAX)) {
3590 				shell_error(sh, "Invalid index: %lu", val);
3591 
3592 				return -ENOEXEC;
3593 			}
3594 
3595 			bis_bitfield |= BT_ISO_BIS_INDEX_BIT(val);
3596 			stream_cnt++;
3597 		}
3598 	}
3599 
3600 	if (default_broadcast_sink.bap_sink == NULL) {
3601 		shell_error(sh, "No sink available");
3602 		return -ENOEXEC;
3603 	}
3604 
3605 	(void)memset(streams, 0, sizeof(streams));
3606 	for (size_t i = 0; i < ARRAY_SIZE(streams); i++) {
3607 		streams[i] = bap_stream_from_shell_stream(&broadcast_sink_streams[i]);
3608 	}
3609 
3610 	err = bt_bap_broadcast_sink_sync(default_broadcast_sink.bap_sink, bis_bitfield, streams,
3611 					 bcode_set ? bcode : NULL);
3612 	if (err != 0) {
3613 		shell_error(sh, "Failed to sync to broadcast: %d", err);
3614 		return err;
3615 	}
3616 
3617 	default_broadcast_sink.stream_cnt = stream_cnt;
3618 
3619 	return 0;
3620 }
3621 
cmd_stop_broadcast_sink(const struct shell * sh,size_t argc,char * argv[])3622 static int cmd_stop_broadcast_sink(const struct shell *sh, size_t argc,
3623 				   char *argv[])
3624 {
3625 	int err;
3626 
3627 	if (default_broadcast_sink.bap_sink == NULL) {
3628 		shell_error(sh, "No sink available");
3629 		return -ENOEXEC;
3630 	}
3631 
3632 	err = bt_bap_broadcast_sink_stop(default_broadcast_sink.bap_sink);
3633 	if (err != 0) {
3634 		shell_error(sh, "Failed to stop sink: %d", err);
3635 		return err;
3636 	}
3637 
3638 	return err;
3639 }
3640 
cmd_term_broadcast_sink(const struct shell * sh,size_t argc,char * argv[])3641 static int cmd_term_broadcast_sink(const struct shell *sh, size_t argc,
3642 				   char *argv[])
3643 {
3644 	int err;
3645 
3646 	if (default_broadcast_sink.bap_sink == NULL) {
3647 		shell_error(sh, "No sink available");
3648 		return -ENOEXEC;
3649 	}
3650 
3651 	err = bt_bap_broadcast_sink_delete(default_broadcast_sink.bap_sink);
3652 	if (err != 0) {
3653 		shell_error(sh, "Failed to term sink: %d", err);
3654 		return err;
3655 	}
3656 
3657 	default_broadcast_sink.bap_sink = NULL;
3658 	default_broadcast_sink.syncable = false;
3659 
3660 	return err;
3661 }
3662 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
3663 
cmd_set_loc(const struct shell * sh,size_t argc,char * argv[])3664 static int cmd_set_loc(const struct shell *sh, size_t argc, char *argv[])
3665 {
3666 	int err = 0;
3667 	enum bt_audio_dir dir;
3668 	enum bt_audio_location loc;
3669 	unsigned long loc_val;
3670 
3671 	if (!strcmp(argv[1], "sink")) {
3672 		dir = BT_AUDIO_DIR_SINK;
3673 	} else if (!strcmp(argv[1], "source")) {
3674 		dir = BT_AUDIO_DIR_SOURCE;
3675 	} else {
3676 		shell_error(sh, "Unsupported dir: %s", argv[1]);
3677 		return -ENOEXEC;
3678 	}
3679 
3680 	loc_val = shell_strtoul(argv[2], 16, &err);
3681 	if (err != 0) {
3682 		shell_error(sh, "Could not parse loc_val: %d", err);
3683 
3684 		return -ENOEXEC;
3685 	}
3686 
3687 	if (loc_val > BT_AUDIO_LOCATION_ANY) {
3688 		shell_error(sh, "Invalid location: %lu", loc_val);
3689 
3690 		return -ENOEXEC;
3691 	}
3692 
3693 	loc = loc_val;
3694 
3695 	err = bt_pacs_set_location(dir, loc);
3696 	if (err) {
3697 		shell_error(ctx_shell, "Set available contexts err %d", err);
3698 		return -ENOEXEC;
3699 	}
3700 
3701 	return 0;
3702 }
3703 
cmd_context(const struct shell * sh,size_t argc,char * argv[])3704 static int cmd_context(const struct shell *sh, size_t argc, char *argv[])
3705 {
3706 	int err = 0;
3707 	enum bt_audio_dir dir;
3708 	enum bt_audio_context ctx;
3709 	unsigned long ctx_val;
3710 
3711 	if (!strcmp(argv[1], "sink")) {
3712 		dir = BT_AUDIO_DIR_SINK;
3713 	} else if (!strcmp(argv[1], "source")) {
3714 		dir = BT_AUDIO_DIR_SOURCE;
3715 	} else {
3716 		shell_error(sh, "Unsupported dir: %s", argv[1]);
3717 		return -ENOEXEC;
3718 	}
3719 
3720 	ctx_val = shell_strtoul(argv[2], 16, &err);
3721 	if (err) {
3722 		shell_error(sh, "Could not parse context: %d", err);
3723 
3724 		return err;
3725 	}
3726 
3727 	if (ctx_val > BT_AUDIO_CONTEXT_TYPE_ANY) {
3728 		shell_error(sh, "Invalid context: %lu", ctx_val);
3729 
3730 		return -ENOEXEC;
3731 	}
3732 
3733 	ctx = ctx_val;
3734 
3735 	if (!strcmp(argv[3], "supported")) {
3736 		if (ctx_val == BT_AUDIO_CONTEXT_TYPE_PROHIBITED) {
3737 			shell_error(sh, "Invalid context: %lu", ctx_val);
3738 
3739 			return -ENOEXEC;
3740 		}
3741 
3742 		err = bt_pacs_set_supported_contexts(dir, ctx);
3743 		if (err) {
3744 			shell_error(ctx_shell, "Set supported contexts err %d", err);
3745 			return err;
3746 		}
3747 	} else if (!strcmp(argv[3], "available")) {
3748 		err = bt_pacs_set_available_contexts(dir, ctx);
3749 		if (err) {
3750 			shell_error(ctx_shell, "Set available contexts err %d", err);
3751 			return err;
3752 		}
3753 	} else {
3754 		shell_error(sh, "Unsupported context type: %s", argv[3]);
3755 		return -ENOEXEC;
3756 	}
3757 
3758 	return 0;
3759 }
3760 
cmd_init(const struct shell * sh,size_t argc,char * argv[])3761 static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
3762 {
3763 	int err, i;
3764 
3765 	ctx_shell = sh;
3766 
3767 	if (initialized) {
3768 		shell_print(sh, "Already initialized");
3769 		return -ENOEXEC;
3770 	}
3771 
3772 	if (argc != 1 && (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && argc != 3)) {
3773 		shell_error(sh, "Invalid argument count");
3774 		shell_help(sh);
3775 
3776 		return SHELL_CMD_HELP_PRINTED;
3777 	}
3778 
3779 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
3780 	unsigned long snk_cnt, src_cnt;
3781 	struct bt_bap_unicast_server_register_param unicast_server_param = {
3782 		CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT,
3783 		CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT
3784 	};
3785 
3786 
3787 	if (argc == 3) {
3788 		snk_cnt = shell_strtoul(argv[1], 0, &err);
3789 		if (snk_cnt > CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT) {
3790 			shell_error(sh, "Invalid Sink ASE count: %lu. Valid interval: [0, %u]",
3791 				    snk_cnt, CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT);
3792 
3793 			return -ENOEXEC;
3794 		}
3795 
3796 		unicast_server_param.snk_cnt = snk_cnt;
3797 
3798 		src_cnt = shell_strtoul(argv[2], 0, &err);
3799 		if (src_cnt > CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT) {
3800 			shell_error(sh, "Invalid Source ASE count: %lu. Valid interval: [0, %u]",
3801 				    src_cnt, CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT);
3802 
3803 			return -ENOEXEC;
3804 		}
3805 
3806 		unicast_server_param.src_cnt = src_cnt;
3807 	} else {
3808 		snk_cnt = CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT;
3809 		src_cnt = CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT;
3810 	}
3811 
3812 	bt_bap_unicast_server_register(&unicast_server_param);
3813 	bt_bap_unicast_server_register_cb(&unicast_server_cb);
3814 #endif /* CONFIG_BT_BAP_UNICAST_SERVER */
3815 
3816 #if defined(CONFIG_BT_PAC_SNK)
3817 	bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink);
3818 #endif /* CONFIG_BT_PAC_SNK */
3819 #if defined(CONFIG_BT_PAC_SRC)
3820 	bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap_source);
3821 #endif /* CONFIG_BT_PAC_SNK */
3822 
3823 	if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) {
3824 		err = bt_pacs_set_location(BT_AUDIO_DIR_SINK, LOCATION);
3825 		__ASSERT(err == 0, "Failed to set sink location: %d", err);
3826 
3827 		err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK,
3828 						     CONTEXT);
3829 		__ASSERT(err == 0, "Failed to set sink supported contexts: %d",
3830 			 err);
3831 
3832 		err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK,
3833 						     CONTEXT);
3834 		__ASSERT(err == 0, "Failed to set sink available contexts: %d",
3835 			 err);
3836 	}
3837 
3838 	if (IS_ENABLED(CONFIG_BT_PAC_SRC_LOC)) {
3839 		err = bt_pacs_set_location(BT_AUDIO_DIR_SOURCE, LOCATION);
3840 		__ASSERT(err == 0, "Failed to set source location: %d", err);
3841 
3842 		err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE,
3843 						     CONTEXT);
3844 		__ASSERT(err == 0, "Failed to set sink supported contexts: %d",
3845 			 err);
3846 
3847 		err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE,
3848 						     CONTEXT);
3849 		__ASSERT(err == 0,
3850 			 "Failed to set source available contexts: %d",
3851 			 err);
3852 	}
3853 
3854 #if defined(CONFIG_BT_BAP_UNICAST)
3855 	for (i = 0; i < ARRAY_SIZE(unicast_streams); i++) {
3856 		bt_bap_stream_cb_register(bap_stream_from_shell_stream(&unicast_streams[i]),
3857 					  &stream_ops);
3858 
3859 		if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
3860 		    IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
3861 			/* If we use the cap initiator, we need to register the callbacks for CAP
3862 			 * as well, as CAP will override and use the BAP callbacks if doing a CAP
3863 			 * procedure
3864 			 */
3865 			bt_cap_stream_ops_register(&unicast_streams[i].stream, &stream_ops);
3866 		}
3867 	}
3868 #endif /* CONFIG_BT_BAP_UNICAST */
3869 
3870 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
3871 	bt_bap_broadcast_sink_register_cb(&sink_cbs);
3872 	bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb);
3873 	bt_le_scan_cb_register(&bap_scan_cb);
3874 
3875 	for (i = 0; i < ARRAY_SIZE(broadcast_sink_streams); i++) {
3876 		bt_bap_stream_cb_register(bap_stream_from_shell_stream(&broadcast_sink_streams[i]),
3877 					  &stream_ops);
3878 	}
3879 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
3880 
3881 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
3882 	for (i = 0; i < ARRAY_SIZE(broadcast_source_streams); i++) {
3883 		bt_bap_stream_cb_register(
3884 			bap_stream_from_shell_stream(&broadcast_source_streams[i]), &stream_ops);
3885 	}
3886 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
3887 
3888 #if defined(CONFIG_LIBLC3)
3889 #if defined(CONFIG_BT_AUDIO_RX)
3890 	static K_KERNEL_STACK_DEFINE(lc3_decoder_thread_stack, 4096);
3891 	const int lc3_decoder_thread_prio = K_PRIO_PREEMPT(5);
3892 	static struct k_thread lc3_decoder_thread;
3893 
3894 	k_thread_create(&lc3_decoder_thread, lc3_decoder_thread_stack,
3895 			K_KERNEL_STACK_SIZEOF(lc3_decoder_thread_stack), lc3_decoder_thread_func,
3896 			NULL, NULL, NULL, lc3_decoder_thread_prio, 0, K_NO_WAIT);
3897 	k_thread_name_set(&lc3_decoder_thread, "LC3 Decoder");
3898 #endif /* CONFIG_BT_AUDIO_RX */
3899 
3900 #if defined(CONFIG_BT_AUDIO_TX)
3901 	static K_KERNEL_STACK_DEFINE(lc3_encoder_thread_stack, 4096);
3902 	const int lc3_encoder_thread_prio = K_PRIO_PREEMPT(5);
3903 	static struct k_thread lc3_encoder_thread;
3904 
3905 	k_thread_create(&lc3_encoder_thread, lc3_encoder_thread_stack,
3906 			K_KERNEL_STACK_SIZEOF(lc3_encoder_thread_stack), lc3_encoder_thread_func,
3907 			NULL, NULL, NULL, lc3_encoder_thread_prio, 0, K_NO_WAIT);
3908 	k_thread_name_set(&lc3_encoder_thread, "LC3 Encoder");
3909 
3910 #endif /* CONFIG_BT_AUDIO_TX */
3911 
3912 	if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) &&
3913 	    (IS_ENABLED(CONFIG_BT_AUDIO_RX) || IS_ENABLED(CONFIG_BT_AUDIO_TX))) {
3914 		err = bap_usb_init();
3915 		__ASSERT(err == 0, "Failed to enable USB: %d", err);
3916 	}
3917 #endif /* CONFIG_LIBLC3 */
3918 
3919 	initialized = true;
3920 
3921 	return 0;
3922 }
3923 
3924 #if defined(CONFIG_BT_AUDIO_TX)
3925 
3926 #define DATA_MTU CONFIG_BT_ISO_TX_MTU
3927 NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, DATA_MTU, CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
3928 
cmd_send(const struct shell * sh,size_t argc,char * argv[])3929 static int cmd_send(const struct shell *sh, size_t argc, char *argv[])
3930 {
3931 	static uint8_t data[DATA_MTU - BT_ISO_CHAN_SEND_RESERVE];
3932 	int ret, len;
3933 	struct net_buf *buf;
3934 
3935 	if (default_stream == NULL) {
3936 		shell_error(sh, "Invalid (NULL) stream");
3937 
3938 		return -ENOEXEC;
3939 	}
3940 
3941 	if (default_stream->qos == NULL) {
3942 		shell_error(sh, "NULL stream QoS");
3943 
3944 		return -ENOEXEC;
3945 	}
3946 
3947 	if (argc > 1) {
3948 		len = hex2bin(argv[1], strlen(argv[1]), data, sizeof(data));
3949 		if (len > default_stream->qos->sdu) {
3950 			shell_print(sh, "Unable to send: len %d > %u MTU",
3951 				    len, default_stream->qos->sdu);
3952 
3953 			return -ENOEXEC;
3954 		}
3955 	} else {
3956 		len = MIN(default_stream->qos->sdu, sizeof(data));
3957 		memset(data, 0xff, len);
3958 	}
3959 
3960 	buf = net_buf_alloc(&tx_pool, K_FOREVER);
3961 	net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
3962 
3963 	net_buf_add_mem(buf, data, len);
3964 
3965 	ret = bt_bap_stream_send(default_stream, buf, get_next_seq_num(default_stream));
3966 	if (ret < 0) {
3967 		shell_print(sh, "Unable to send: %d", -ret);
3968 		net_buf_unref(buf);
3969 
3970 		return -ENOEXEC;
3971 	}
3972 
3973 	shell_print(sh, "Sending:");
3974 	shell_hexdump(sh, data, len);
3975 
3976 	return 0;
3977 }
3978 
3979 #if GENERATE_SINE_SUPPORTED
start_sine_stream_cb(struct shell_stream * sh_stream,void * user_data)3980 static void start_sine_stream_cb(struct shell_stream *sh_stream, void *user_data)
3981 {
3982 	if (sh_stream->is_tx) {
3983 		struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream);
3984 		const struct shell *sh = user_data;
3985 		int err;
3986 
3987 		err = init_lc3_encoder(sh_stream);
3988 		if (err != 0) {
3989 			shell_error(sh, "Failed to init LC3 %d for stream %p", err, bap_stream);
3990 
3991 			return;
3992 		}
3993 
3994 		sh_stream->tx.active = true;
3995 		sh_stream->tx.seq_num = get_next_seq_num(bap_stream_from_shell_stream(sh_stream));
3996 
3997 		shell_print(sh, "Started transmitting sine on stream %p", bap_stream);
3998 	}
3999 }
4000 
cmd_start_sine(const struct shell * sh,size_t argc,char * argv[])4001 static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[])
4002 {
4003 	bool start_all = false;
4004 
4005 	if (argc > 1) {
4006 		if (strcmp(argv[1], "all") == 0) {
4007 			start_all = true;
4008 		} else {
4009 			shell_help(sh);
4010 
4011 			return SHELL_CMD_HELP_PRINTED;
4012 		}
4013 	}
4014 
4015 	if (start_all) {
4016 		bap_foreach_stream(start_sine_stream_cb, (void *)sh);
4017 	} else {
4018 		struct shell_stream *sh_stream = shell_stream_from_bap_stream(default_stream);
4019 
4020 		start_sine_stream_cb(sh_stream, (void *)sh);
4021 	}
4022 
4023 	return 0;
4024 }
4025 
stop_sine_stream_cb(struct shell_stream * sh_stream,void * user_data)4026 static void stop_sine_stream_cb(struct shell_stream *sh_stream, void *user_data)
4027 {
4028 	if (sh_stream->is_tx) {
4029 		struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream);
4030 		const struct shell *sh = user_data;
4031 
4032 		shell_print(sh, "Stopped transmitting on stream %p", bap_stream);
4033 
4034 		sh_stream->tx.active = false;
4035 	}
4036 }
4037 
cmd_stop_sine(const struct shell * sh,size_t argc,char * argv[])4038 static int cmd_stop_sine(const struct shell *sh, size_t argc, char *argv[])
4039 {
4040 	bool stop_all = false;
4041 
4042 	if (argc > 1) {
4043 		if (strcmp(argv[1], "all") == 0) {
4044 			stop_all = true;
4045 		} else {
4046 			shell_help(sh);
4047 
4048 			return SHELL_CMD_HELP_PRINTED;
4049 		}
4050 	}
4051 
4052 	if (stop_all) {
4053 		bap_foreach_stream(stop_sine_stream_cb, (void *)sh);
4054 	} else {
4055 		struct shell_stream *sh_stream = shell_stream_from_bap_stream(default_stream);
4056 
4057 		stop_sine_stream_cb(sh_stream, (void *)sh);
4058 	}
4059 
4060 	return 0;
4061 }
4062 #endif /* GENERATE_SINE_SUPPORTED */
4063 #endif /* CONFIG_BT_AUDIO_TX */
4064 
cmd_bap_stats(const struct shell * sh,size_t argc,char * argv[])4065 static int cmd_bap_stats(const struct shell *sh, size_t argc, char *argv[])
4066 {
4067 	if (argc == 1) {
4068 		shell_info(sh, "Current stats interval: %lu", bap_stats_interval);
4069 	} else {
4070 		int err = 0;
4071 		unsigned long interval;
4072 
4073 		interval = shell_strtoul(argv[1], 0, &err);
4074 		if (err != 0) {
4075 			shell_error(sh, "Could not parse interval: %d", err);
4076 
4077 			return -ENOEXEC;
4078 		}
4079 
4080 		if (interval == 0U) {
4081 			shell_error(sh, "Interval cannot be 0");
4082 
4083 			return -ENOEXEC;
4084 		}
4085 
4086 		bap_stats_interval = interval;
4087 	}
4088 
4089 	return 0;
4090 }
4091 
4092 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
print_ase_info(struct bt_bap_ep * ep,void * user_data)4093 static void print_ase_info(struct bt_bap_ep *ep, void *user_data)
4094 {
4095 	struct bt_bap_ep_info info;
4096 	int err;
4097 
4098 	err = bt_bap_ep_get_info(ep, &info);
4099 	if (err == 0) {
4100 		printk("ASE info: id %u state %u dir %u\n", info.id, info.state, info.dir);
4101 	}
4102 }
4103 
cmd_print_ase_info(const struct shell * sh,size_t argc,char * argv[])4104 static int cmd_print_ase_info(const struct shell *sh, size_t argc, char *argv[])
4105 {
4106 	if (!default_conn) {
4107 		shell_error(sh, "Not connected");
4108 		return -ENOEXEC;
4109 	}
4110 
4111 	bt_bap_unicast_server_foreach_ep(default_conn, print_ase_info, NULL);
4112 
4113 	return 0;
4114 }
4115 #endif /* CONFIG_BT_BAP_UNICAST_SERVER */
4116 
4117 /* 31 is a unit separator - without t the tab is seemingly ignored*/
4118 #define HELP_SEP "\n\31\t"
4119 
4120 #define HELP_CFG_DATA                                                                              \
4121 	"\n[config" HELP_SEP "[freq <frequency>]" HELP_SEP "[dur <duration>]" HELP_SEP             \
4122 	"[chan_alloc <location>]" HELP_SEP "[frame_len <frame length>]" HELP_SEP                   \
4123 	"[frame_blks <frame blocks>]]"
4124 
4125 #define HELP_CFG_META                                                                              \
4126 	"\n[meta" HELP_SEP "[pref_ctx <context>]" HELP_SEP "[stream_ctx <context>]" HELP_SEP       \
4127 	"[program_info <program info>]" HELP_SEP "[lang <ISO 639-3 lang>]" HELP_SEP         \
4128 	"[ccid_list <ccids>]" HELP_SEP "[parental_rating <rating>]" HELP_SEP                       \
4129 	"[program_info_uri <URI>]" HELP_SEP "[audio_active_state <state>]" HELP_SEP                \
4130 	"[bcast_flag]" HELP_SEP "[extended <meta>]" HELP_SEP "[vendor <meta>]]"
4131 
4132 SHELL_STATIC_SUBCMD_SET_CREATE(
4133 	bap_cmds,
4134 	SHELL_CMD_ARG(init, NULL, NULL, cmd_init, 1,
4135 		      IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) ? 2 : 0),
4136 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
4137 	SHELL_CMD_ARG(select_broadcast, NULL, "<stream>", cmd_select_broadcast_source, 2, 0),
4138 	SHELL_CMD_ARG(create_broadcast, NULL, "[preset <preset_name>] [enc <broadcast_code>]",
4139 		      cmd_create_broadcast, 1, 2),
4140 	SHELL_CMD_ARG(start_broadcast, NULL, "", cmd_start_broadcast, 1, 0),
4141 	SHELL_CMD_ARG(stop_broadcast, NULL, "", cmd_stop_broadcast, 1, 0),
4142 	SHELL_CMD_ARG(delete_broadcast, NULL, "", cmd_delete_broadcast, 1, 0),
4143 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
4144 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
4145 	SHELL_CMD_ARG(create_broadcast_sink, NULL, "0x<broadcast_id>", cmd_create_broadcast_sink, 2,
4146 		      0),
4147 	SHELL_CMD_ARG(create_sink_by_name, NULL, "<broadcast_name>",
4148 		      cmd_create_sink_by_name, 2, 0),
4149 	SHELL_CMD_ARG(sync_broadcast, NULL,
4150 		      "0x<bis_index> [[[0x<bis_index>] 0x<bis_index>] ...] "
4151 		      "[bcode <broadcast code> || bcode_str <broadcast code as string>]",
4152 		      cmd_sync_broadcast, 2, ARRAY_SIZE(broadcast_sink_streams) + 1),
4153 	SHELL_CMD_ARG(stop_broadcast_sink, NULL, "Stops broadcast sink", cmd_stop_broadcast_sink, 1,
4154 		      0),
4155 	SHELL_CMD_ARG(term_broadcast_sink, NULL, "", cmd_term_broadcast_sink, 1, 0),
4156 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
4157 #if defined(CONFIG_BT_BAP_UNICAST)
4158 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
4159 	SHELL_CMD_ARG(discover, NULL, "[dir: sink, source]", cmd_discover, 1, 1),
4160 	SHELL_CMD_ARG(config, NULL,
4161 		      "<direction: sink, source> <index> [loc <loc_bits>] [preset <preset_name>]",
4162 		      cmd_config, 3, 4),
4163 	SHELL_CMD_ARG(stream_qos, NULL, "interval [framing] [latency] [pd] [sdu] [phy] [rtn]",
4164 		      cmd_stream_qos, 2, 6),
4165 	SHELL_CMD_ARG(connect, NULL, "Connect the CIS of the stream", cmd_connect, 1, 0),
4166 	SHELL_CMD_ARG(qos, NULL, "Send QoS configure for Unicast Group", cmd_qos, 1, 0),
4167 	SHELL_CMD_ARG(enable, NULL, "[context]", cmd_enable, 1, 1),
4168 	SHELL_CMD_ARG(stop, NULL, NULL, cmd_stop, 1, 0),
4169 	SHELL_CMD_ARG(list, NULL, NULL, cmd_list, 1, 0),
4170 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
4171 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
4172 	SHELL_CMD_ARG(print_ase_info, NULL, "Print ASE info for default connection",
4173 		      cmd_print_ase_info, 0, 0),
4174 #endif /* CONFIG_BT_BAP_UNICAST_SERVER */
4175 	SHELL_CMD_ARG(metadata, NULL, "[context]", cmd_metadata, 1, 1),
4176 	SHELL_CMD_ARG(start, NULL, NULL, cmd_start, 1, 0),
4177 	SHELL_CMD_ARG(disable, NULL, NULL, cmd_disable, 1, 0),
4178 	SHELL_CMD_ARG(release, NULL, NULL, cmd_release, 1, 0),
4179 	SHELL_CMD_ARG(select_unicast, NULL, "<stream>", cmd_select_unicast, 2, 0),
4180 #endif /* CONFIG_BT_BAP_UNICAST */
4181 #if IS_BAP_INITIATOR
4182 	SHELL_CMD_ARG(preset, NULL,
4183 		      "<sink, source, broadcast> [preset] " HELP_CFG_DATA " " HELP_CFG_META,
4184 		      cmd_preset, 2, 34),
4185 #endif /* IS_BAP_INITIATOR */
4186 #if defined(CONFIG_BT_AUDIO_TX)
4187 	SHELL_CMD_ARG(send, NULL, "Send to Audio Stream [data]", cmd_send, 1, 1),
4188 #if GENERATE_SINE_SUPPORTED
4189 	SHELL_CMD_ARG(start_sine, NULL, "Start sending a LC3 encoded sine wave [all]",
4190 		      cmd_start_sine, 1, 1),
4191 	SHELL_CMD_ARG(stop_sine, NULL, "Stop sending a LC3 encoded sine wave [all]", cmd_stop_sine,
4192 		      1, 1),
4193 #endif /* GENERATE_SINE_SUPPORTED */
4194 #endif /* CONFIG_BT_AUDIO_TX */
4195 	SHELL_CMD_ARG(bap_stats, NULL,
4196 		      "Sets or gets the statistics reporting interval in # of packets",
4197 		      cmd_bap_stats, 1, 1),
4198 	SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_location, NULL,
4199 			   "<direction: sink, source> <location bitmask>", cmd_set_loc, 3, 0),
4200 	SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_context, NULL,
4201 			   "<direction: sink, source>"
4202 			   "<context bitmask> <type: supported, available>",
4203 			   cmd_context, 4, 0),
4204 	SHELL_SUBCMD_SET_END);
4205 
cmd_bap(const struct shell * sh,size_t argc,char ** argv)4206 static int cmd_bap(const struct shell *sh, size_t argc, char **argv)
4207 {
4208 	if (argc > 1) {
4209 		shell_error(sh, "%s unknown parameter: %s",
4210 			    argv[0], argv[1]);
4211 	} else {
4212 		shell_error(sh, "%s Missing subcommand", argv[0]);
4213 	}
4214 
4215 	return -ENOEXEC;
4216 }
4217 
4218 SHELL_CMD_ARG_REGISTER(bap, &bap_cmds, "Bluetooth BAP shell commands", cmd_bap, 1, 1);
4219 
connectable_ad_data_add(struct bt_data * data_array,size_t data_array_size)4220 static ssize_t connectable_ad_data_add(struct bt_data *data_array,
4221 				       size_t data_array_size)
4222 {
4223 	static const uint8_t ad_ext_uuid16[] = {
4224 		IF_ENABLED(CONFIG_BT_MICP_MIC_DEV, (BT_UUID_16_ENCODE(BT_UUID_MICS_VAL),))
4225 		IF_ENABLED(CONFIG_BT_ASCS, (BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL),))
4226 		IF_ENABLED(CONFIG_BT_BAP_SCAN_DELEGATOR, (BT_UUID_16_ENCODE(BT_UUID_BASS_VAL),))
4227 		IF_ENABLED(CONFIG_BT_PACS, (BT_UUID_16_ENCODE(BT_UUID_PACS_VAL),))
4228 		IF_ENABLED(CONFIG_BT_TBS, (BT_UUID_16_ENCODE(BT_UUID_GTBS_VAL),))
4229 		IF_ENABLED(CONFIG_BT_TBS_BEARER_COUNT, (BT_UUID_16_ENCODE(BT_UUID_TBS_VAL),))
4230 		IF_ENABLED(CONFIG_BT_VCP_VOL_REND, (BT_UUID_16_ENCODE(BT_UUID_VCS_VAL),))
4231 		IF_ENABLED(CONFIG_BT_HAS, (BT_UUID_16_ENCODE(BT_UUID_HAS_VAL),)) /* Shall be last */
4232 	};
4233 	size_t ad_len = 0;
4234 
4235 	if (IS_ENABLED(CONFIG_BT_ASCS)) {
4236 		static uint8_t ad_bap_announcement[8] = {
4237 			BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL),
4238 			BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED,
4239 		};
4240 		enum bt_audio_context snk_context, src_context;
4241 
4242 		snk_context = bt_pacs_get_available_contexts(BT_AUDIO_DIR_SINK);
4243 		sys_put_le16(snk_context, &ad_bap_announcement[3]);
4244 
4245 		src_context = bt_pacs_get_available_contexts(BT_AUDIO_DIR_SOURCE);
4246 		sys_put_le16(src_context, &ad_bap_announcement[5]);
4247 
4248 		/* Metadata length */
4249 		ad_bap_announcement[7] = 0x00;
4250 
4251 		__ASSERT(data_array_size > ad_len, "No space for AD_BAP_ANNOUNCEMENT");
4252 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
4253 		data_array[ad_len].data_len = ARRAY_SIZE(ad_bap_announcement);
4254 		data_array[ad_len].data = &ad_bap_announcement[0];
4255 		ad_len++;
4256 	}
4257 
4258 	if (IS_ENABLED(CONFIG_BT_BAP_SCAN_DELEGATOR)) {
4259 		ad_len += bap_scan_delegator_ad_data_add(&data_array[ad_len],
4260 							 data_array_size - ad_len);
4261 	}
4262 
4263 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR)) {
4264 		ad_len += cap_acceptor_ad_data_add(&data_array[ad_len], data_array_size - ad_len,
4265 						   true);
4266 	}
4267 
4268 	if (IS_ENABLED(CONFIG_BT_GMAP)) {
4269 		ad_len += gmap_ad_data_add(&data_array[ad_len], data_array_size - ad_len);
4270 	}
4271 
4272 	if (ARRAY_SIZE(ad_ext_uuid16) > 0) {
4273 		size_t uuid16_size;
4274 
4275 		if (data_array_size <= ad_len) {
4276 			shell_warn(ctx_shell, "No space for AD_UUID16");
4277 			return ad_len;
4278 		}
4279 
4280 		data_array[ad_len].type = BT_DATA_UUID16_SOME;
4281 
4282 		if (IS_ENABLED(CONFIG_BT_HAS) && IS_ENABLED(CONFIG_BT_PRIVACY)) {
4283 			/* If the HA is in one of the GAP connectable modes and is using a
4284 			 * resolvable private address, the HA shall not include the Hearing Access
4285 			 * Service UUID in the Service UUID AD type field of the advertising data
4286 			 * or scan response.
4287 			 */
4288 			uuid16_size = ARRAY_SIZE(ad_ext_uuid16) - BT_UUID_SIZE_16;
4289 		} else {
4290 			uuid16_size = ARRAY_SIZE(ad_ext_uuid16);
4291 		}
4292 
4293 		/* We can maximum advertise 127 16-bit UUIDs = 254 octets */
4294 		data_array[ad_len].data_len = MIN(uuid16_size, 254);
4295 
4296 		data_array[ad_len].data = &ad_ext_uuid16[0];
4297 		ad_len++;
4298 	}
4299 
4300 	return ad_len;
4301 }
4302 
nonconnectable_ad_data_add(struct bt_data * data_array,const size_t data_array_size)4303 static ssize_t nonconnectable_ad_data_add(struct bt_data *data_array,
4304 					  const size_t data_array_size)
4305 {
4306 	static const uint8_t ad_ext_uuid16[] = {
4307 		IF_ENABLED(CONFIG_BT_PACS, (BT_UUID_16_ENCODE(BT_UUID_PACS_VAL),))
4308 		IF_ENABLED(CONFIG_BT_CAP_ACCEPTOR, (BT_UUID_16_ENCODE(BT_UUID_CAS_VAL),))
4309 	};
4310 	size_t ad_len = 0;
4311 
4312 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR)) {
4313 		static const uint8_t ad_cap_announcement[3] = {
4314 			BT_UUID_16_ENCODE(BT_UUID_CAS_VAL),
4315 			BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED,
4316 		};
4317 
4318 		__ASSERT(data_array_size > ad_len, "No space for AD_CAP_ANNOUNCEMENT");
4319 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
4320 		data_array[ad_len].data_len = ARRAY_SIZE(ad_cap_announcement);
4321 		data_array[ad_len].data = &ad_cap_announcement[0];
4322 		ad_len++;
4323 	}
4324 
4325 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
4326 	if (default_source.bap_source != NULL && !default_source.is_cap) {
4327 		static uint8_t ad_bap_broadcast_announcement[5] = {
4328 			BT_UUID_16_ENCODE(BT_UUID_BROADCAST_AUDIO_VAL),
4329 		};
4330 		uint32_t broadcast_id;
4331 		int err;
4332 
4333 		err = bt_rand(&broadcast_id, BT_AUDIO_BROADCAST_ID_SIZE);
4334 		if (err != 0) {
4335 			printk("Unable to generate broadcast ID: %d\n", err);
4336 
4337 			return -1;
4338 		}
4339 
4340 		sys_put_le24(broadcast_id, &ad_bap_broadcast_announcement[2]);
4341 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
4342 		data_array[ad_len].data_len = ARRAY_SIZE(ad_bap_broadcast_announcement);
4343 		data_array[ad_len].data = ad_bap_broadcast_announcement;
4344 		ad_len++;
4345 	}
4346 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
4347 
4348 	if (ARRAY_SIZE(ad_ext_uuid16) > 0) {
4349 		if (data_array_size <= ad_len) {
4350 			shell_warn(ctx_shell, "No space for AD_UUID16");
4351 			return ad_len;
4352 		}
4353 
4354 		data_array[ad_len].type = BT_DATA_UUID16_SOME;
4355 		data_array[ad_len].data_len = ARRAY_SIZE(ad_ext_uuid16);
4356 		data_array[ad_len].data = &ad_ext_uuid16[0];
4357 		ad_len++;
4358 	}
4359 
4360 	return ad_len;
4361 }
4362 
audio_ad_data_add(struct bt_data * data_array,const size_t data_array_size,const bool discoverable,const bool connectable)4363 ssize_t audio_ad_data_add(struct bt_data *data_array, const size_t data_array_size,
4364 			  const bool discoverable, const bool connectable)
4365 {
4366 	ssize_t ad_len = 0;
4367 
4368 	if (!discoverable) {
4369 		return 0;
4370 	}
4371 
4372 	if (connectable) {
4373 		ad_len += connectable_ad_data_add(data_array, data_array_size);
4374 	} else {
4375 		ad_len += nonconnectable_ad_data_add(data_array, data_array_size);
4376 	}
4377 
4378 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
4379 		ad_len += cap_initiator_ad_data_add(data_array, data_array_size, discoverable,
4380 						    connectable);
4381 	}
4382 
4383 	return ad_len;
4384 }
4385 
audio_pa_data_add(struct bt_data * data_array,const size_t data_array_size)4386 ssize_t audio_pa_data_add(struct bt_data *data_array,
4387 			  const size_t data_array_size)
4388 {
4389 	size_t ad_len = 0;
4390 
4391 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
4392 	if (default_source.bap_source != NULL && !default_source.is_cap) {
4393 		/* Required size of the buffer depends on what has been
4394 		 * configured. We just use the maximum size possible.
4395 		 */
4396 		NET_BUF_SIMPLE_DEFINE_STATIC(base_buf, UINT8_MAX);
4397 		int err;
4398 
4399 		net_buf_simple_reset(&base_buf);
4400 
4401 		err = bt_bap_broadcast_source_get_base(default_source.bap_source, &base_buf);
4402 		if (err != 0) {
4403 			printk("Unable to get BASE: %d\n", err);
4404 
4405 			return -1;
4406 		}
4407 
4408 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
4409 		data_array[ad_len].data_len = base_buf.len;
4410 		data_array[ad_len].data = base_buf.data;
4411 		ad_len++;
4412 	} else if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
4413 		return cap_initiator_pa_data_add(data_array, data_array_size);
4414 	}
4415 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
4416 
4417 	return ad_len;
4418 }
4419