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