1 /** @file
2  *  @brief Bluetooth Basic Audio Profile shell
3  *
4  */
5 
6 /*
7  * Copyright (c) 2020 Intel Corporation
8  * Copyright (c) 2022-2023 Nordic Semiconductor ASA
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/shell/shell.h>
18 #include <zephyr/sys/printk.h>
19 #include <zephyr/sys/byteorder.h>
20 #include <zephyr/sys/util.h>
21 
22 #include <zephyr/bluetooth/gatt.h>
23 #include <zephyr/bluetooth/audio/audio.h>
24 #include <zephyr/bluetooth/audio/bap.h>
25 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
26 #include <zephyr/bluetooth/audio/cap.h>
27 #include <zephyr/bluetooth/audio/pacs.h>
28 
29 #include "shell/bt.h"
30 #include "audio.h"
31 
32 #define LOCATION BT_AUDIO_LOCATION_FRONT_LEFT
33 #define CONTEXT BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA
34 
35 #if defined(CONFIG_BT_BAP_UNICAST)
36 
37 struct unicast_stream unicast_streams[CONFIG_BT_MAX_CONN *
38 				      (UNICAST_SERVER_STREAM_COUNT + UNICAST_CLIENT_STREAM_COUNT)];
39 
40 static const struct bt_codec_qos_pref qos_pref = BT_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0u, 60u,
41 								   20000u, 40000u, 20000u, 40000u);
42 
43 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
44 struct bt_bap_unicast_group *default_unicast_group;
45 static struct bt_bap_unicast_client_cb unicast_client_cbs;
46 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
47 struct bt_bap_ep *snks[CONFIG_BT_MAX_CONN][CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
48 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
49 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
50 struct bt_bap_ep *srcs[CONFIG_BT_MAX_CONN][CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
51 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
52 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
53 #endif /* CONFIG_BT_BAP_UNICAST */
54 
55 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
56 struct broadcast_stream broadcast_source_streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
57 struct broadcast_source default_source;
58 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
59 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
60 static struct bt_bap_stream broadcast_sink_streams[BROADCAST_SNK_STREAM_CNT];
61 static struct bt_bap_broadcast_sink *default_sink;
62 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
63 static struct bt_bap_stream *default_stream;
64 
65 static const struct named_lc3_preset lc3_unicast_presets[] = {
66 	{"8_1_1", BT_BAP_LC3_UNICAST_PRESET_8_1_1(LOCATION, CONTEXT)},
67 	{"8_2_1", BT_BAP_LC3_UNICAST_PRESET_8_2_1(LOCATION, CONTEXT)},
68 	{"16_1_1", BT_BAP_LC3_UNICAST_PRESET_16_1_1(LOCATION, CONTEXT)},
69 	{"16_2_1", BT_BAP_LC3_UNICAST_PRESET_16_2_1(LOCATION, CONTEXT)},
70 	{"24_1_1", BT_BAP_LC3_UNICAST_PRESET_24_1_1(LOCATION, CONTEXT)},
71 	{"24_2_1", BT_BAP_LC3_UNICAST_PRESET_24_2_1(LOCATION, CONTEXT)},
72 	{"32_1_1", BT_BAP_LC3_UNICAST_PRESET_32_1_1(LOCATION, CONTEXT)},
73 	{"32_2_1", BT_BAP_LC3_UNICAST_PRESET_32_2_1(LOCATION, CONTEXT)},
74 	{"441_1_1", BT_BAP_LC3_UNICAST_PRESET_441_1_1(LOCATION, CONTEXT)},
75 	{"441_2_1", BT_BAP_LC3_UNICAST_PRESET_441_2_1(LOCATION, CONTEXT)},
76 	{"48_1_1", BT_BAP_LC3_UNICAST_PRESET_48_1_1(LOCATION, CONTEXT)},
77 	{"48_2_1", BT_BAP_LC3_UNICAST_PRESET_48_2_1(LOCATION, CONTEXT)},
78 	{"48_3_1", BT_BAP_LC3_UNICAST_PRESET_48_3_1(LOCATION, CONTEXT)},
79 	{"48_4_1", BT_BAP_LC3_UNICAST_PRESET_48_4_1(LOCATION, CONTEXT)},
80 	{"48_5_1", BT_BAP_LC3_UNICAST_PRESET_48_5_1(LOCATION, CONTEXT)},
81 	{"48_6_1", BT_BAP_LC3_UNICAST_PRESET_48_6_1(LOCATION, CONTEXT)},
82 	/* High-reliability presets */
83 	{"8_1_2", BT_BAP_LC3_UNICAST_PRESET_8_1_2(LOCATION, CONTEXT)},
84 	{"8_2_2", BT_BAP_LC3_UNICAST_PRESET_8_2_2(LOCATION, CONTEXT)},
85 	{"16_1_2", BT_BAP_LC3_UNICAST_PRESET_16_1_2(LOCATION, CONTEXT)},
86 	{"16_2_2", BT_BAP_LC3_UNICAST_PRESET_16_2_2(LOCATION, CONTEXT)},
87 	{"24_1_2", BT_BAP_LC3_UNICAST_PRESET_24_1_2(LOCATION, CONTEXT)},
88 	{"24_2_2", BT_BAP_LC3_UNICAST_PRESET_24_2_2(LOCATION, CONTEXT)},
89 	{"32_1_2", BT_BAP_LC3_UNICAST_PRESET_32_1_2(LOCATION, CONTEXT)},
90 	{"32_2_2", BT_BAP_LC3_UNICAST_PRESET_32_2_2(LOCATION, CONTEXT)},
91 	{"441_1_2", BT_BAP_LC3_UNICAST_PRESET_441_1_2(LOCATION, CONTEXT)},
92 	{"441_2_2", BT_BAP_LC3_UNICAST_PRESET_441_2_2(LOCATION, CONTEXT)},
93 	{"48_1_2", BT_BAP_LC3_UNICAST_PRESET_48_1_2(LOCATION, CONTEXT)},
94 	{"48_2_2", BT_BAP_LC3_UNICAST_PRESET_48_2_2(LOCATION, CONTEXT)},
95 	{"48_3_2", BT_BAP_LC3_UNICAST_PRESET_48_3_2(LOCATION, CONTEXT)},
96 	{"48_4_2", BT_BAP_LC3_UNICAST_PRESET_48_4_2(LOCATION, CONTEXT)},
97 	{"48_5_2", BT_BAP_LC3_UNICAST_PRESET_48_5_2(LOCATION, CONTEXT)},
98 	{"48_6_2", BT_BAP_LC3_UNICAST_PRESET_48_6_2(LOCATION, CONTEXT)},
99 };
100 
101 static const struct named_lc3_preset lc3_broadcast_presets[] = {
102 	{"8_1_1", BT_BAP_LC3_BROADCAST_PRESET_8_1_1(LOCATION, CONTEXT)},
103 	{"8_2_1", BT_BAP_LC3_BROADCAST_PRESET_8_2_1(LOCATION, CONTEXT)},
104 	{"16_1_1", BT_BAP_LC3_BROADCAST_PRESET_16_1_1(LOCATION, CONTEXT)},
105 	{"16_2_1", BT_BAP_LC3_BROADCAST_PRESET_16_2_1(LOCATION, CONTEXT)},
106 	{"24_1_1", BT_BAP_LC3_BROADCAST_PRESET_24_1_1(LOCATION, CONTEXT)},
107 	{"24_2_1", BT_BAP_LC3_BROADCAST_PRESET_24_2_1(LOCATION, CONTEXT)},
108 	{"32_1_1", BT_BAP_LC3_BROADCAST_PRESET_32_1_1(LOCATION, CONTEXT)},
109 	{"32_2_1", BT_BAP_LC3_BROADCAST_PRESET_32_2_1(LOCATION, CONTEXT)},
110 	{"441_1_1", BT_BAP_LC3_BROADCAST_PRESET_441_1_1(LOCATION, CONTEXT)},
111 	{"441_2_1", BT_BAP_LC3_BROADCAST_PRESET_441_2_1(LOCATION, CONTEXT)},
112 	{"48_1_1", BT_BAP_LC3_BROADCAST_PRESET_48_1_1(LOCATION, CONTEXT)},
113 	{"48_2_1", BT_BAP_LC3_BROADCAST_PRESET_48_2_1(LOCATION, CONTEXT)},
114 	{"48_3_1", BT_BAP_LC3_BROADCAST_PRESET_48_3_1(LOCATION, CONTEXT)},
115 	{"48_4_1", BT_BAP_LC3_BROADCAST_PRESET_48_4_1(LOCATION, CONTEXT)},
116 	{"48_5_1", BT_BAP_LC3_BROADCAST_PRESET_48_5_1(LOCATION, CONTEXT)},
117 	{"48_6_1", BT_BAP_LC3_BROADCAST_PRESET_48_6_1(LOCATION, CONTEXT)},
118 	/* High-reliability presets */
119 	{"8_1_2", BT_BAP_LC3_BROADCAST_PRESET_8_1_2(LOCATION, CONTEXT)},
120 	{"8_2_2", BT_BAP_LC3_BROADCAST_PRESET_8_2_2(LOCATION, CONTEXT)},
121 	{"16_1_2", BT_BAP_LC3_BROADCAST_PRESET_16_1_2(LOCATION, CONTEXT)},
122 	{"16_2_2", BT_BAP_LC3_BROADCAST_PRESET_16_2_2(LOCATION, CONTEXT)},
123 	{"24_1_2", BT_BAP_LC3_BROADCAST_PRESET_24_1_2(LOCATION, CONTEXT)},
124 	{"24_2_2", BT_BAP_LC3_BROADCAST_PRESET_24_2_2(LOCATION, CONTEXT)},
125 	{"32_1_2", BT_BAP_LC3_BROADCAST_PRESET_32_1_2(LOCATION, CONTEXT)},
126 	{"32_2_2", BT_BAP_LC3_BROADCAST_PRESET_32_2_2(LOCATION, CONTEXT)},
127 	{"441_1_2", BT_BAP_LC3_BROADCAST_PRESET_441_1_2(LOCATION, CONTEXT)},
128 	{"441_2_2", BT_BAP_LC3_BROADCAST_PRESET_441_2_2(LOCATION, CONTEXT)},
129 	{"48_1_2", BT_BAP_LC3_BROADCAST_PRESET_48_1_2(LOCATION, CONTEXT)},
130 	{"48_2_2", BT_BAP_LC3_BROADCAST_PRESET_48_2_2(LOCATION, CONTEXT)},
131 	{"48_3_2", BT_BAP_LC3_BROADCAST_PRESET_48_3_2(LOCATION, CONTEXT)},
132 	{"48_4_2", BT_BAP_LC3_BROADCAST_PRESET_48_4_2(LOCATION, CONTEXT)},
133 	{"48_5_2", BT_BAP_LC3_BROADCAST_PRESET_48_5_2(LOCATION, CONTEXT)},
134 	{"48_6_2", BT_BAP_LC3_BROADCAST_PRESET_48_6_2(LOCATION, CONTEXT)},
135 };
136 
137 /* Default to 16_2_1 */
138 const struct named_lc3_preset *default_sink_preset = &lc3_unicast_presets[3];
139 const struct named_lc3_preset *default_source_preset = &lc3_unicast_presets[3];
140 static const struct named_lc3_preset *default_broadcast_source_preset = &lc3_broadcast_presets[3];
141 static bool initialized;
142 
143 #if defined(CONFIG_BT_AUDIO_TX)
144 static struct bt_bap_stream *txing_stream;
145 static uint16_t seq_num;
146 
get_next_seq_num(uint32_t interval_us)147 static uint16_t get_next_seq_num(uint32_t interval_us)
148 {
149 	static int64_t last_ticks;
150 	int64_t uptime_ticks, delta_ticks;
151 	uint64_t delta_us;
152 	uint64_t seq_num_incr;
153 	uint64_t next_seq_num;
154 
155 	/* Note: This does not handle wrapping of ticks when they go above
156 	 * 2^(62-1)
157 	 */
158 	uptime_ticks = k_uptime_ticks();
159 	delta_ticks = uptime_ticks - last_ticks;
160 	last_ticks = uptime_ticks;
161 
162 	delta_us = k_ticks_to_us_near64((uint64_t)delta_ticks);
163 	seq_num_incr = delta_us / interval_us;
164 	next_seq_num = (seq_num_incr + seq_num);
165 
166 	return (uint16_t)next_seq_num;
167 }
168 #endif /* CONFIG_BT_AUDIO_TX */
169 
170 #if defined(CONFIG_LIBLC3) && defined(CONFIG_BT_AUDIO_TX)
171 NET_BUF_POOL_FIXED_DEFINE(sine_tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT,
172 			  BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
173 			  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
174 
175 #include "lc3.h"
176 #include "math.h"
177 
178 #define MAX_SAMPLE_RATE         48000
179 #define MAX_FRAME_DURATION_US   10000
180 #define MAX_NUM_SAMPLES         ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC)
181 #define AUDIO_VOLUME            (INT16_MAX - 3000) /* codec does clipping above INT16_MAX - 3000 */
182 #define AUDIO_TONE_FREQUENCY_HZ   400
183 
184 static int16_t audio_buf[MAX_NUM_SAMPLES];
185 static lc3_encoder_t lc3_encoder;
186 static lc3_encoder_mem_48k_t lc3_encoder_mem;
187 static int freq_hz;
188 static int frame_duration_us;
189 static int frame_duration_100us;
190 static int frames_per_sdu;
191 static int octets_per_frame;
192 static int64_t lc3_start_time;
193 static int32_t lc3_sdu_cnt;
194 
195 /**
196  * Use the math lib to generate a sine-wave using 16 bit samples into a buffer.
197  *
198  * @param buf Destination buffer
199  * @param length_us Length of the buffer in microseconds
200  * @param frequency_hz frequency in Hz
201  * @param sample_rate_hz sample-rate in Hz.
202  */
fill_audio_buf_sin(int16_t * buf,int length_us,int frequency_hz,int sample_rate_hz)203 static void fill_audio_buf_sin(int16_t *buf, int length_us, int frequency_hz, int sample_rate_hz)
204 {
205 	const uint32_t sine_period_samples = sample_rate_hz / frequency_hz;
206 	const size_t num_samples = (length_us * sample_rate_hz) / USEC_PER_SEC;
207 	const float step = 2 * 3.1415 / sine_period_samples;
208 
209 	for (size_t i = 0; i < num_samples; i++) {
210 		const float sample = sin(i * step);
211 
212 		buf[i] = (int16_t)(AUDIO_VOLUME * sample);
213 	}
214 }
215 
init_lc3(const struct bt_bap_stream * stream)216 static void init_lc3(const struct bt_bap_stream *stream)
217 {
218 	size_t num_samples;
219 
220 	if (stream == NULL || stream->codec == NULL) {
221 		shell_error(ctx_shell, "invalid stream to init LC3");
222 		return;
223 	}
224 
225 	freq_hz = bt_codec_cfg_get_freq(stream->codec);
226 	frame_duration_us = bt_codec_cfg_get_frame_duration_us(stream->codec);
227 	octets_per_frame = bt_codec_cfg_get_octets_per_frame(stream->codec);
228 	frames_per_sdu = bt_codec_cfg_get_frame_blocks_per_sdu(stream->codec, true);
229 	octets_per_frame = bt_codec_cfg_get_octets_per_frame(stream->codec);
230 
231 	if (freq_hz < 0) {
232 		printk("Error: Codec frequency not set, cannot start codec.");
233 		return;
234 	}
235 
236 	if (frame_duration_us < 0) {
237 		printk("Error: Frame duration not set, cannot start codec.");
238 		return;
239 	}
240 
241 	if (octets_per_frame < 0) {
242 		printk("Error: Octets per frame not set, cannot start codec.");
243 		return;
244 	}
245 
246 	frame_duration_100us = frame_duration_us / 100;
247 
248 	/* Fill audio buffer with Sine wave only once and repeat encoding the same tone frame */
249 	fill_audio_buf_sin(audio_buf, frame_duration_us, AUDIO_TONE_FREQUENCY_HZ, freq_hz);
250 
251 	num_samples = ((frame_duration_us * freq_hz) / USEC_PER_SEC);
252 	for (size_t i = 0; i < num_samples; i++) {
253 		printk("%zu: %6i\n", i, audio_buf[i]);
254 	}
255 
256 	/* Create the encoder instance. This shall complete before stream_started() is called. */
257 	lc3_encoder = lc3_setup_encoder(frame_duration_us, freq_hz,
258 					0, /* No resampling */
259 					&lc3_encoder_mem);
260 
261 	if (lc3_encoder == NULL) {
262 		printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n");
263 	}
264 }
265 
lc3_audio_send_data(struct k_work * work)266 static void lc3_audio_send_data(struct k_work *work)
267 {
268 	if (lc3_encoder == NULL) {
269 		shell_error(ctx_shell,
270 			    "LC3 encoder not setup, cannot encode data");
271 		return;
272 	}
273 
274 	if (txing_stream == NULL || txing_stream->qos == NULL) {
275 		shell_error(ctx_shell, "invalid stream, aborting");
276 		return;
277 	}
278 
279 	seq_num = get_next_seq_num(txing_stream->qos->interval);
280 
281 	const uint16_t tx_sdu_len = frames_per_sdu * octets_per_frame;
282 	struct net_buf *buf;
283 	uint8_t *net_buffer;
284 	off_t offset = 0;
285 	int err;
286 
287 	buf = net_buf_alloc(&sine_tx_pool, K_FOREVER);
288 	net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
289 
290 	net_buffer = net_buf_tail(buf);
291 	buf->len += tx_sdu_len;
292 
293 	for (int i = 0; i < frames_per_sdu; i++) {
294 		int lc3_ret;
295 
296 		lc3_ret = lc3_encode(lc3_encoder, LC3_PCM_FORMAT_S16,
297 						audio_buf, 1, octets_per_frame,
298 						net_buffer + offset);
299 		offset += octets_per_frame;
300 
301 		if (lc3_ret == -1) {
302 			shell_error(ctx_shell,
303 					"LC3 encoder failed - wrong parameters?: %d",
304 					lc3_ret);
305 			net_buf_unref(buf);
306 			return;
307 		}
308 	}
309 
310 	err = bt_bap_stream_send(txing_stream, buf, seq_num,
311 					BT_ISO_TIMESTAMP_NONE);
312 	if (err < 0) {
313 		shell_error(ctx_shell,
314 				"Failed to send LC3 audio data (%d)\n",
315 				err);
316 		net_buf_unref(buf);
317 		return;
318 	}
319 
320 	if ((lc3_sdu_cnt % 100) == 0) {
321 		shell_info(ctx_shell, "[%zu]: TX LC3: %zu\n",
322 				lc3_sdu_cnt, tx_sdu_len);
323 	}
324 	lc3_sdu_cnt++;
325 	seq_num++;
326 }
327 
328 static K_WORK_DEFINE(audio_send_work, lc3_audio_send_data);
329 
sdu_sent_cb(struct bt_bap_stream * stream)330 void sdu_sent_cb(struct bt_bap_stream *stream)
331 {
332 	if (txing_stream == NULL || txing_stream->qos == NULL) {
333 		return;
334 	}
335 
336 	k_work_submit(&audio_send_work);
337 }
338 #endif /* CONFIG_LIBLC3 && CONFIG_BT_AUDIO_TX */
339 
get_named_preset(bool is_unicast,const char * preset_arg)340 static const struct named_lc3_preset *get_named_preset(bool is_unicast, const char *preset_arg)
341 {
342 	if (is_unicast) {
343 		for (size_t i = 0U; i < ARRAY_SIZE(lc3_unicast_presets); i++) {
344 			if (!strcmp(preset_arg, lc3_unicast_presets[i].name)) {
345 				return &lc3_unicast_presets[i];
346 			}
347 		}
348 	} else {
349 		for (size_t i = 0U; i < ARRAY_SIZE(lc3_broadcast_presets); i++) {
350 			if (!strcmp(preset_arg, lc3_broadcast_presets[i].name)) {
351 				return &lc3_broadcast_presets[i];
352 			}
353 		}
354 	}
355 
356 	return NULL;
357 }
358 
set_unicast_stream(struct bt_bap_stream * stream)359 static void set_unicast_stream(struct bt_bap_stream *stream)
360 {
361 	default_stream = stream;
362 
363 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
364 		if (stream == &unicast_streams[i].stream.bap_stream) {
365 			shell_print(ctx_shell, "Default stream: %u", i + 1);
366 		}
367 	}
368 }
369 
cmd_select_unicast(const struct shell * sh,size_t argc,char * argv[])370 static int cmd_select_unicast(const struct shell *sh, size_t argc, char *argv[])
371 {
372 	struct bt_bap_stream *stream;
373 	unsigned long index;
374 	int err = 0;
375 
376 	index = shell_strtoul(argv[1], 0, &err);
377 	if (err != 0) {
378 		shell_error(sh, "Could not parse index: %d", err);
379 
380 		return -ENOEXEC;
381 	}
382 
383 	if (index > ARRAY_SIZE(unicast_streams)) {
384 		shell_error(sh, "Invalid index: %lu", index);
385 
386 		return -ENOEXEC;
387 	}
388 
389 	stream = &unicast_streams[index].stream.bap_stream;
390 
391 	set_unicast_stream(stream);
392 
393 	return 0;
394 }
395 
stream_alloc(void)396 static struct bt_bap_stream *stream_alloc(void)
397 {
398 	for (size_t i = 0; i < ARRAY_SIZE(unicast_streams); i++) {
399 		struct bt_bap_stream *stream = &unicast_streams[i].stream.bap_stream;
400 
401 		if (!stream->conn) {
402 			return stream;
403 		}
404 	}
405 
406 	return NULL;
407 }
408 
lc3_config(struct bt_conn * conn,const struct bt_bap_ep * ep,enum bt_audio_dir dir,const struct bt_codec * codec,struct bt_bap_stream ** stream,struct bt_codec_qos_pref * const pref,struct bt_bap_ascs_rsp * rsp)409 static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir,
410 		      const struct bt_codec *codec, struct bt_bap_stream **stream,
411 		      struct bt_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp)
412 {
413 	shell_print(ctx_shell, "ASE Codec Config: conn %p ep %p dir %u", conn, ep, dir);
414 
415 	print_codec(ctx_shell, codec);
416 
417 	*stream = stream_alloc();
418 	if (*stream == NULL) {
419 		shell_print(ctx_shell, "No unicast_streams available");
420 
421 		*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM, BT_BAP_ASCS_REASON_NONE);
422 
423 		return -ENOMEM;
424 	}
425 
426 	shell_print(ctx_shell, "ASE Codec Config stream %p", *stream);
427 
428 	set_unicast_stream(*stream);
429 
430 	*pref = qos_pref;
431 
432 	return 0;
433 }
434 
lc3_reconfig(struct bt_bap_stream * stream,enum bt_audio_dir dir,const struct bt_codec * codec,struct bt_codec_qos_pref * const pref,struct bt_bap_ascs_rsp * rsp)435 static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir,
436 			const struct bt_codec *codec, struct bt_codec_qos_pref *const pref,
437 			struct bt_bap_ascs_rsp *rsp)
438 {
439 	shell_print(ctx_shell, "ASE Codec Reconfig: stream %p", stream);
440 
441 	print_codec(ctx_shell, codec);
442 
443 	if (default_stream == NULL) {
444 		set_unicast_stream(stream);
445 	}
446 
447 	*pref = qos_pref;
448 
449 	return 0;
450 }
451 
lc3_qos(struct bt_bap_stream * stream,const struct bt_codec_qos * qos,struct bt_bap_ascs_rsp * rsp)452 static int lc3_qos(struct bt_bap_stream *stream, const struct bt_codec_qos *qos,
453 		   struct bt_bap_ascs_rsp *rsp)
454 {
455 	shell_print(ctx_shell, "QoS: stream %p %p", stream, qos);
456 
457 	print_qos(ctx_shell, qos);
458 
459 	return 0;
460 }
461 
lc3_enable(struct bt_bap_stream * stream,const struct bt_codec_data * meta,size_t meta_count,struct bt_bap_ascs_rsp * rsp)462 static int lc3_enable(struct bt_bap_stream *stream, const struct bt_codec_data *meta,
463 		      size_t meta_count, struct bt_bap_ascs_rsp *rsp)
464 {
465 	shell_print(ctx_shell, "Enable: stream %p meta_count %zu", stream,
466 		    meta_count);
467 
468 	return 0;
469 }
470 
lc3_start(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)471 static int lc3_start(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
472 {
473 	shell_print(ctx_shell, "Start: stream %p", stream);
474 
475 #if defined(CONFIG_BT_AUDIO_TX)
476 	seq_num = 0;
477 #endif /* CONFIG_BT_AUDIO_TX */
478 
479 	return 0;
480 }
481 
482 
valid_metadata_type(uint8_t type,uint8_t len)483 static bool valid_metadata_type(uint8_t type, uint8_t len)
484 {
485 	switch (type) {
486 	case BT_AUDIO_METADATA_TYPE_PREF_CONTEXT:
487 	case BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT:
488 		if (len != 2) {
489 			return false;
490 		}
491 
492 		return true;
493 	case BT_AUDIO_METADATA_TYPE_STREAM_LANG:
494 		if (len != 3) {
495 			return false;
496 		}
497 
498 		return true;
499 	case BT_AUDIO_METADATA_TYPE_PARENTAL_RATING:
500 		if (len != 1) {
501 			return false;
502 		}
503 
504 		return true;
505 	case BT_AUDIO_METADATA_TYPE_EXTENDED: /* 1 - 255 octets */
506 	case BT_AUDIO_METADATA_TYPE_VENDOR: /* 1 - 255 octets */
507 		if (len < 1) {
508 			return false;
509 		}
510 
511 		return true;
512 	case BT_AUDIO_METADATA_TYPE_CCID_LIST: /* 2 - 254 octets */
513 		if (len < 2) {
514 			return false;
515 		}
516 
517 		return true;
518 	case BT_AUDIO_METADATA_TYPE_PROGRAM_INFO: /* 0 - 255 octets */
519 	case BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI: /* 0 - 255 octets */
520 		return true;
521 	default:
522 		return false;
523 	}
524 }
525 
lc3_metadata(struct bt_bap_stream * stream,const struct bt_codec_data * meta,size_t meta_count,struct bt_bap_ascs_rsp * rsp)526 static int lc3_metadata(struct bt_bap_stream *stream, const struct bt_codec_data *meta,
527 			size_t meta_count, struct bt_bap_ascs_rsp *rsp)
528 {
529 	shell_print(ctx_shell, "Metadata: stream %p meta_count %zu", stream,
530 		    meta_count);
531 
532 	for (size_t i = 0; i < meta_count; i++) {
533 		const struct bt_codec_data *data = &meta[i];
534 
535 		if (!valid_metadata_type(data->data.type, data->data.data_len)) {
536 			shell_print(ctx_shell,
537 				    "Invalid metadata type %u or length %u",
538 				    data->data.type, data->data.data_len);
539 			*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED,
540 					       data->data.type);
541 			return -EINVAL;
542 		}
543 	}
544 
545 	return 0;
546 }
547 
lc3_disable(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)548 static int lc3_disable(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
549 {
550 	shell_print(ctx_shell, "Disable: stream %p", stream);
551 
552 	return 0;
553 }
554 
lc3_stop(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)555 static int lc3_stop(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
556 {
557 	shell_print(ctx_shell, "Stop: stream %p", stream);
558 
559 	return 0;
560 }
561 
lc3_release(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)562 static int lc3_release(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
563 {
564 	shell_print(ctx_shell, "Release: stream %p", stream);
565 
566 	if (stream == default_stream) {
567 		default_stream = NULL;
568 	}
569 
570 	return 0;
571 }
572 
573 static struct bt_codec lc3_codec = BT_CODEC_LC3(BT_CODEC_LC3_FREQ_ANY,
574 						BT_CODEC_LC3_DURATION_ANY,
575 						BT_CODEC_LC3_CHAN_COUNT_SUPPORT(1, 2), 30, 240, 2,
576 						(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL |
577 						BT_AUDIO_CONTEXT_TYPE_MEDIA));
578 
579 static const struct bt_bap_unicast_server_cb unicast_server_cb = {
580 	.config = lc3_config,
581 	.reconfig = lc3_reconfig,
582 	.qos = lc3_qos,
583 	.enable = lc3_enable,
584 	.start = lc3_start,
585 	.metadata = lc3_metadata,
586 	.disable = lc3_disable,
587 	.stop = lc3_stop,
588 	.release = lc3_release,
589 };
590 
591 static struct bt_pacs_cap cap_sink = {
592 	.codec = &lc3_codec,
593 };
594 
595 static struct bt_pacs_cap cap_source = {
596 	.codec = &lc3_codec,
597 };
598 #if defined(CONFIG_BT_BAP_UNICAST)
599 
strmeta(const char * name)600 static uint16_t strmeta(const char *name)
601 {
602 	if (strcmp(name, "Unspecified") == 0) {
603 		return BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED;
604 	} else if (strcmp(name, "Conversational") == 0) {
605 		return BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL;
606 	} else if (strcmp(name, "Media") == 0) {
607 		return BT_AUDIO_CONTEXT_TYPE_MEDIA;
608 	} else if (strcmp(name, "Game") == 0) {
609 		return BT_AUDIO_CONTEXT_TYPE_GAME;
610 	} else if (strcmp(name, "Instructional") == 0) {
611 		return BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL;
612 	} else if (strcmp(name, "VoiceAssistants") == 0) {
613 		return BT_AUDIO_CONTEXT_TYPE_VOICE_ASSISTANTS;
614 	} else if (strcmp(name, "Live") == 0) {
615 		return BT_AUDIO_CONTEXT_TYPE_LIVE;
616 	} else if (strcmp(name, "SoundEffects") == 0) {
617 		return BT_AUDIO_CONTEXT_TYPE_SOUND_EFFECTS;
618 	} else if (strcmp(name, "Notifications") == 0) {
619 		return BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS;
620 	} else if (strcmp(name, "Ringtone") == 0) {
621 		return BT_AUDIO_CONTEXT_TYPE_RINGTONE;
622 	} else if (strcmp(name, "Alerts") == 0) {
623 		return BT_AUDIO_CONTEXT_TYPE_ALERTS;
624 	} else if (strcmp(name, "EmergencyAlarm") == 0) {
625 		return BT_AUDIO_CONTEXT_TYPE_EMERGENCY_ALARM;
626 	}
627 
628 	return 0u;
629 }
630 
set_metadata(struct bt_codec * codec,const char * meta_str)631 static int set_metadata(struct bt_codec *codec, const char *meta_str)
632 {
633 	uint16_t context;
634 
635 	context = strmeta(meta_str);
636 	if (context == 0) {
637 		return -ENOEXEC;
638 	}
639 
640 	/* TODO: Check the type and only overwrite the streaming context */
641 	sys_put_le16(context, codec->meta[0].value);
642 
643 	return 0;
644 }
645 
646 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
stream_dir(const struct bt_bap_stream * stream)647 static uint8_t stream_dir(const struct bt_bap_stream *stream)
648 {
649 	if (stream->conn) {
650 		uint8_t conn_index = bt_conn_index(stream->conn);
651 
652 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
653 		for (size_t i = 0; i < ARRAY_SIZE(snks[conn_index]); i++) {
654 			const struct bt_bap_ep *snk_ep = snks[conn_index][i];
655 
656 			if (snk_ep != NULL && stream->ep == snk_ep) {
657 				return BT_AUDIO_DIR_SINK;
658 			}
659 		}
660 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
661 
662 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
663 		for (size_t i = 0; i < ARRAY_SIZE(srcs[conn_index]); i++) {
664 			const struct bt_bap_ep *src_ep = srcs[conn_index][i];
665 
666 			if (src_ep != NULL && stream->ep == src_ep) {
667 				return BT_AUDIO_DIR_SOURCE;
668 			}
669 		}
670 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
671 	}
672 
673 	__ASSERT(false, "Invalid stream");
674 	return 0;
675 }
676 
print_remote_codec(const struct bt_conn * conn,const struct bt_codec * codec,enum bt_audio_dir dir)677 static void print_remote_codec(const struct bt_conn *conn, const struct bt_codec *codec,
678 			       enum bt_audio_dir dir)
679 {
680 	shell_print(ctx_shell, "conn %p: codec %p dir 0x%02x", conn, codec, dir);
681 
682 	print_codec(ctx_shell, codec);
683 }
684 
685 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
add_sink(const struct bt_conn * conn,struct bt_bap_ep * ep)686 static void add_sink(const struct bt_conn *conn, struct bt_bap_ep *ep)
687 {
688 	const uint8_t conn_index = bt_conn_index(conn);
689 
690 	for (size_t i = 0U; i < ARRAY_SIZE(snks[conn_index]); i++) {
691 		if (snks[conn_index][i] == NULL) {
692 			shell_print(ctx_shell, "Conn: %p, Sink #%zu: ep %p", conn, i, ep);
693 
694 			snks[conn_index][i] = ep;
695 			return;
696 		}
697 	}
698 
699 	shell_error(ctx_shell, "Could not add more sink endpoints");
700 }
701 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
702 
703 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
add_source(const struct bt_conn * conn,struct bt_bap_ep * ep)704 static void add_source(const struct bt_conn *conn, struct bt_bap_ep *ep)
705 {
706 	const uint8_t conn_index = bt_conn_index(conn);
707 
708 	for (size_t i = 0U; i < ARRAY_SIZE(srcs[conn_index]); i++) {
709 		if (srcs[conn_index][i] == NULL) {
710 			shell_print(ctx_shell, "Conn: %p, Source #%zu: ep %p", conn, i, ep);
711 
712 			srcs[conn_index][i] = ep;
713 			return;
714 		}
715 	}
716 
717 	shell_error(ctx_shell, "Could not add more sink endpoints");
718 }
719 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
720 
pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_codec * codec)721 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, const struct bt_codec *codec)
722 {
723 	print_remote_codec(conn, codec, dir);
724 }
725 
endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)726 static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
727 {
728 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
729 	if (dir == BT_AUDIO_DIR_SINK) {
730 		add_sink(conn, ep);
731 	}
732 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
733 
734 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
735 	if (dir == BT_AUDIO_DIR_SOURCE) {
736 		add_source(conn, ep);
737 	}
738 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0*/
739 }
740 
discover_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)741 static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
742 {
743 	shell_print(ctx_shell, "Discover complete: err %d", err);
744 }
745 
discover_all(struct bt_conn * conn,int err,enum bt_audio_dir dir)746 static void discover_all(struct bt_conn *conn, int err, enum bt_audio_dir dir)
747 {
748 	/* Sinks discovery complete, now discover sources */
749 	if (dir == BT_AUDIO_DIR_SINK) {
750 		dir = BT_AUDIO_DIR_SOURCE;
751 		unicast_client_cbs.discover = discover_cb;
752 
753 		err = bt_bap_unicast_client_discover(default_conn, dir);
754 		if (err) {
755 			shell_error(ctx_shell, "bt_bap_unicast_client_discover err %d", err);
756 		}
757 	}
758 }
759 
unicast_client_location_cb(struct bt_conn * conn,enum bt_audio_dir dir,enum bt_audio_location loc)760 static void unicast_client_location_cb(struct bt_conn *conn,
761 				      enum bt_audio_dir dir,
762 				      enum bt_audio_location loc)
763 {
764 	shell_print(ctx_shell, "dir %u loc %X\n", dir, loc);
765 }
766 
available_contexts_cb(struct bt_conn * conn,enum bt_audio_context snk_ctx,enum bt_audio_context src_ctx)767 static void available_contexts_cb(struct bt_conn *conn,
768 				  enum bt_audio_context snk_ctx,
769 				  enum bt_audio_context src_ctx)
770 {
771 	shell_print(ctx_shell, "snk ctx %u src ctx %u\n", snk_ctx, src_ctx);
772 }
773 
config_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)774 static void config_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
775 		      enum bt_bap_ascs_reason reason)
776 {
777 	shell_print(ctx_shell, "stream %p config operation rsp_code %u reason %u",
778 		    stream, rsp_code, reason);
779 }
780 
qos_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)781 static void qos_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
782 		   enum bt_bap_ascs_reason reason)
783 {
784 	shell_print(ctx_shell, "stream %p qos operation rsp_code %u reason %u",
785 		    stream, rsp_code, reason);
786 }
787 
enable_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)788 static void enable_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
789 		      enum bt_bap_ascs_reason reason)
790 {
791 	shell_print(ctx_shell, "stream %p enable operation rsp_code %u reason %u",
792 		    stream, rsp_code, reason);
793 }
794 
start_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)795 static void start_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
796 		     enum bt_bap_ascs_reason reason)
797 {
798 	shell_print(ctx_shell, "stream %p start operation rsp_code %u reason %u",
799 		    stream, rsp_code, reason);
800 }
801 
stop_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)802 static void stop_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
803 		    enum bt_bap_ascs_reason reason)
804 {
805 	shell_print(ctx_shell, "stream %p stop operation rsp_code %u reason %u",
806 		    stream, rsp_code, reason);
807 }
808 
disable_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)809 static void disable_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
810 		       enum bt_bap_ascs_reason reason)
811 {
812 	shell_print(ctx_shell, "stream %p disable operation rsp_code %u reason %u",
813 		    stream, rsp_code, reason);
814 }
815 
metadata_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)816 static void metadata_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
817 			enum bt_bap_ascs_reason reason)
818 {
819 	shell_print(ctx_shell, "stream %p metadata operation rsp_code %u reason %u",
820 		    stream, rsp_code, reason);
821 }
822 
release_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)823 static void release_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
824 		       enum bt_bap_ascs_reason reason)
825 {
826 	shell_print(ctx_shell, "stream %p release operation rsp_code %u reason %u",
827 		    stream, rsp_code, reason);
828 }
829 
830 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
831 	.location = unicast_client_location_cb,
832 	.available_contexts = available_contexts_cb,
833 	.config = config_cb,
834 	.qos = qos_cb,
835 	.enable = enable_cb,
836 	.start = start_cb,
837 	.stop = stop_cb,
838 	.disable = disable_cb,
839 	.metadata = metadata_cb,
840 	.release = release_cb,
841 	.pac_record = pac_record_cb,
842 	.endpoint = endpoint_cb,
843 };
844 
cmd_discover(const struct shell * sh,size_t argc,char * argv[])845 static int cmd_discover(const struct shell *sh, size_t argc, char *argv[])
846 {
847 	static bool cbs_registered;
848 	enum bt_audio_dir dir;
849 	uint8_t conn_index;
850 	int err;
851 
852 	if (!default_conn) {
853 		shell_error(sh, "Not connected");
854 		return -ENOEXEC;
855 	}
856 
857 	if (!initialized) {
858 		shell_error(sh, "Not initialized");
859 		return -ENOEXEC;
860 	}
861 
862 	if (!cbs_registered) {
863 		int err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
864 
865 		if (err != 0) {
866 			shell_error(sh, "Failed to register unicast client callbacks: %d", err);
867 			return err;
868 		}
869 
870 		cbs_registered = true;
871 	}
872 
873 	unicast_client_cbs.discover = discover_all;
874 	dir = BT_AUDIO_DIR_SINK;
875 
876 	if (argc > 1) {
877 		if (!strcmp(argv[1], "sink")) {
878 			unicast_client_cbs.discover = discover_cb;
879 		} else if (!strcmp(argv[1], "source")) {
880 			unicast_client_cbs.discover = discover_cb;
881 			dir = BT_AUDIO_DIR_SOURCE;
882 		} else {
883 			shell_error(sh, "Unsupported dir: %s", argv[1]);
884 			return -ENOEXEC;
885 		}
886 	}
887 
888 	err = bt_bap_unicast_client_discover(default_conn, dir);
889 	if (err != 0) {
890 		return -ENOEXEC;
891 	}
892 
893 	conn_index = bt_conn_index(default_conn);
894 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
895 	memset(srcs[conn_index], 0, sizeof(srcs[conn_index]));
896 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
897 
898 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
899 	memset(snks[conn_index], 0, sizeof(snks[conn_index]));
900 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
901 
902 	return 0;
903 }
904 
cmd_config(const struct shell * sh,size_t argc,char * argv[])905 static int cmd_config(const struct shell *sh, size_t argc, char *argv[])
906 {
907 	enum bt_audio_location location = BT_AUDIO_LOCATION_PROHIBITED;
908 	const struct named_lc3_preset *named_preset;
909 	struct unicast_stream *uni_stream;
910 	struct bt_bap_ep *ep = NULL;
911 	unsigned long index;
912 	uint8_t conn_index;
913 	int err = 0;
914 
915 	if (!default_conn) {
916 		shell_error(sh, "Not connected");
917 		return -ENOEXEC;
918 	}
919 	conn_index = bt_conn_index(default_conn);
920 
921 	if (default_stream == NULL) {
922 		default_stream = &unicast_streams[0].stream.bap_stream;
923 	}
924 
925 	index = shell_strtoul(argv[2], 0, &err);
926 	if (err != 0) {
927 		shell_error(sh, "Could not parse index: %d", err);
928 
929 		return -ENOEXEC;
930 	}
931 
932 	if (index > ARRAY_SIZE(unicast_streams)) {
933 		shell_error(sh, "Invalid index: %lu", index);
934 
935 		return -ENOEXEC;
936 	}
937 
938 	if (false) {
939 
940 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
941 	} else if (!strcmp(argv[1], "sink")) {
942 		ep = snks[conn_index][index];
943 
944 		named_preset = default_sink_preset;
945 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
946 
947 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
948 	} else if (!strcmp(argv[1], "source")) {
949 		ep = srcs[conn_index][index];
950 
951 		named_preset = default_source_preset;
952 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
953 	} else {
954 		shell_error(sh, "Unsupported dir: %s", argv[1]);
955 		return -ENOEXEC;
956 	}
957 
958 	if (!ep) {
959 		shell_error(sh, "Unable to find endpoint");
960 		return -ENOEXEC;
961 	}
962 
963 	for (size_t i = 3U; i < argc; i++) {
964 		const char *arg = argv[i];
965 
966 		/* argc needs to be larger than `i` to parse the argument value */
967 		if (argc <= i) {
968 			shell_help(sh);
969 
970 			return SHELL_CMD_HELP_PRINTED;
971 		}
972 
973 		if (strcmp(arg, "loc") == 0) {
974 			unsigned long loc_bits;
975 
976 			arg = argv[++i];
977 			loc_bits = shell_strtoul(arg, 0, &err);
978 			if (err != 0) {
979 				shell_error(sh, "Could not parse loc_bits: %d", err);
980 
981 				return -ENOEXEC;
982 			}
983 
984 			if (loc_bits == BT_AUDIO_LOCATION_PROHIBITED ||
985 			    loc_bits > BT_AUDIO_LOCATION_ANY) {
986 				shell_error(sh, "Invalid loc_bits: %lu", loc_bits);
987 
988 				return -ENOEXEC;
989 			}
990 
991 			location = (enum bt_audio_location)loc_bits;
992 		} else if (strcmp(arg, "preset") == 0) {
993 			if (argc > i) {
994 				arg = argv[++i];
995 
996 				named_preset = get_named_preset(true, arg);
997 				if (named_preset == NULL) {
998 					shell_error(sh, "Unable to parse named_preset %s", arg);
999 					return -ENOEXEC;
1000 				}
1001 			} else {
1002 				shell_help(sh);
1003 
1004 				return SHELL_CMD_HELP_PRINTED;
1005 			}
1006 		} else {
1007 			shell_help(sh);
1008 
1009 			return SHELL_CMD_HELP_PRINTED;
1010 		}
1011 	}
1012 
1013 	uni_stream = CONTAINER_OF(default_stream, struct unicast_stream, stream);
1014 	copy_unicast_stream_preset(uni_stream, named_preset);
1015 
1016 	/* If location has been modifed, we update the location in the codec configuration */
1017 	if (location != BT_AUDIO_LOCATION_PROHIBITED) {
1018 		for (size_t i = 0U; i < uni_stream->codec.data_count; i++) {
1019 			struct bt_codec_data *data = &uni_stream->codec.data[i];
1020 
1021 			/* Overwrite the location value */
1022 			if (data->data.type == BT_CODEC_CONFIG_LC3_CHAN_ALLOC) {
1023 				const uint32_t loc_32 = location;
1024 
1025 				sys_put_le32(loc_32, data->value);
1026 
1027 				shell_print(sh, "Setting location to 0x%08X", location);
1028 				break;
1029 			}
1030 		}
1031 	}
1032 
1033 	if (default_stream->ep == ep) {
1034 		err = bt_bap_stream_reconfig(default_stream, &uni_stream->codec);
1035 		if (err != 0) {
1036 			shell_error(sh, "Unable reconfig stream: %d", err);
1037 			return -ENOEXEC;
1038 		}
1039 	} else {
1040 		err = bt_bap_stream_config(default_conn, default_stream, ep, &uni_stream->codec);
1041 		if (err != 0) {
1042 			shell_error(sh, "Unable to config stream: %d", err);
1043 			return err;
1044 		}
1045 	}
1046 
1047 	shell_print(sh, "ASE config: preset %s", named_preset->name);
1048 
1049 	return 0;
1050 }
1051 
cmd_stream_qos(const struct shell * sh,size_t argc,char * argv[])1052 static int cmd_stream_qos(const struct shell *sh, size_t argc, char *argv[])
1053 {
1054 	struct bt_codec_qos *qos;
1055 	unsigned long interval;
1056 	int err;
1057 
1058 	if (default_stream == NULL) {
1059 		shell_print(sh, "No stream selected");
1060 		return -ENOEXEC;
1061 	}
1062 
1063 	qos = default_stream->qos;
1064 
1065 	if (qos == NULL) {
1066 		shell_print(sh, "Stream not configured");
1067 		return -ENOEXEC;
1068 	}
1069 
1070 	interval = shell_strtoul(argv[1], 0, &err);
1071 	if (err != 0) {
1072 		return -ENOEXEC;
1073 	}
1074 
1075 	if (!IN_RANGE(interval, BT_ISO_SDU_INTERVAL_MIN, BT_ISO_SDU_INTERVAL_MAX)) {
1076 		return -ENOEXEC;
1077 	}
1078 
1079 	qos->interval = interval;
1080 
1081 	if (argc > 2) {
1082 		unsigned long framing;
1083 
1084 		framing = shell_strtoul(argv[2], 0, &err);
1085 		if (err != 0) {
1086 			return -ENOEXEC;
1087 		}
1088 
1089 		if (framing != BT_ISO_FRAMING_UNFRAMED && framing != BT_ISO_FRAMING_FRAMED) {
1090 			return -ENOEXEC;
1091 		}
1092 
1093 		qos->framing = framing;
1094 	}
1095 
1096 	if (argc > 3) {
1097 		unsigned long latency;
1098 
1099 		latency = shell_strtoul(argv[3], 0, &err);
1100 		if (err != 0) {
1101 			return -ENOEXEC;
1102 		}
1103 
1104 		if (!IN_RANGE(latency, BT_ISO_LATENCY_MIN, BT_ISO_LATENCY_MAX)) {
1105 			return -ENOEXEC;
1106 		}
1107 
1108 		qos->latency = latency;
1109 	}
1110 
1111 	if (argc > 4) {
1112 		unsigned long pd;
1113 
1114 		pd = shell_strtoul(argv[4], 0, &err);
1115 		if (err != 0) {
1116 			return -ENOEXEC;
1117 		}
1118 
1119 		if (pd > BT_AUDIO_PD_MAX) {
1120 			return -ENOEXEC;
1121 		}
1122 
1123 		qos->pd = pd;
1124 	}
1125 
1126 	if (argc > 5) {
1127 		unsigned long sdu;
1128 
1129 		sdu = shell_strtoul(argv[5], 0, &err);
1130 		if (err != 0) {
1131 			return -ENOEXEC;
1132 		}
1133 
1134 		if (sdu > BT_ISO_MAX_SDU) {
1135 			return -ENOEXEC;
1136 		}
1137 
1138 		qos->sdu = sdu;
1139 	}
1140 
1141 	if (argc > 6) {
1142 		unsigned long phy;
1143 
1144 		phy = shell_strtoul(argv[6], 0, &err);
1145 		if (err != 0) {
1146 			return -ENOEXEC;
1147 		}
1148 
1149 		if (phy != BT_GAP_LE_PHY_1M && phy != BT_GAP_LE_PHY_2M &&
1150 		    phy != BT_GAP_LE_PHY_CODED) {
1151 			return -ENOEXEC;
1152 		}
1153 
1154 		qos->phy = phy;
1155 	}
1156 
1157 	if (argc > 7) {
1158 		unsigned long rtn;
1159 
1160 		rtn = shell_strtoul(argv[7], 0, &err);
1161 		if (err != 0) {
1162 			return -ENOEXEC;
1163 		}
1164 
1165 		if (rtn > BT_ISO_CONNECTED_RTN_MAX) {
1166 			return -ENOEXEC;
1167 		}
1168 
1169 		qos->rtn = rtn;
1170 	}
1171 
1172 	return 0;
1173 }
1174 
create_unicast_group(const struct shell * sh)1175 static int create_unicast_group(const struct shell *sh)
1176 {
1177 	struct bt_bap_unicast_group_stream_pair_param pair_param[ARRAY_SIZE(unicast_streams)];
1178 	struct bt_bap_unicast_group_stream_param stream_params[ARRAY_SIZE(unicast_streams)];
1179 	struct bt_bap_unicast_group_param group_param;
1180 	size_t source_cnt = 0;
1181 	size_t sink_cnt = 0;
1182 	size_t cnt = 0;
1183 	int err;
1184 
1185 	memset(pair_param, 0, sizeof(pair_param));
1186 	memset(stream_params, 0, sizeof(stream_params));
1187 	memset(&group_param, 0, sizeof(group_param));
1188 
1189 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
1190 		struct bt_bap_stream *stream = &unicast_streams[i].stream.bap_stream;
1191 		struct unicast_stream *uni_stream =
1192 			CONTAINER_OF(stream, struct unicast_stream, stream);
1193 
1194 		if (stream->ep != NULL) {
1195 			struct bt_bap_unicast_group_stream_param *stream_param;
1196 
1197 			stream_param = &stream_params[cnt];
1198 
1199 			stream_param->stream = stream;
1200 			if (stream_dir(stream) == BT_AUDIO_DIR_SINK) {
1201 				stream_param->qos = &uni_stream->qos;
1202 				pair_param[sink_cnt++].tx_param = stream_param;
1203 			} else {
1204 				stream_param->qos = &uni_stream->qos;
1205 				pair_param[source_cnt++].rx_param = stream_param;
1206 			}
1207 
1208 			cnt++;
1209 		}
1210 	}
1211 
1212 	if (cnt == 0U) {
1213 		shell_error(sh, "Stream cnt is 0");
1214 
1215 		return -ENOEXEC;
1216 	}
1217 
1218 	group_param.packing = BT_ISO_PACKING_SEQUENTIAL;
1219 	group_param.params = pair_param;
1220 	group_param.params_count = MAX(source_cnt, sink_cnt);
1221 
1222 	err = bt_bap_unicast_group_create(&group_param,
1223 					    &default_unicast_group);
1224 	if (err != 0) {
1225 		shell_error(sh,
1226 			    "Unable to create default unicast group: %d",
1227 			    err);
1228 
1229 		return -ENOEXEC;
1230 	}
1231 
1232 	return 0;
1233 }
1234 
cmd_qos(const struct shell * sh,size_t argc,char * argv[])1235 static int cmd_qos(const struct shell *sh, size_t argc, char *argv[])
1236 {
1237 	int err;
1238 
1239 	if (default_stream == NULL) {
1240 		shell_print(sh, "No stream selected");
1241 		return -ENOEXEC;
1242 	}
1243 
1244 	if (default_conn == NULL) {
1245 		shell_error(sh, "Not connected");
1246 		return -ENOEXEC;
1247 	}
1248 
1249 	if (default_unicast_group == NULL) {
1250 		err = create_unicast_group(sh);
1251 		if (err != 0) {
1252 			return err;
1253 		}
1254 	}
1255 
1256 	err = bt_bap_stream_qos(default_conn, default_unicast_group);
1257 	if (err) {
1258 		shell_error(sh, "Unable to setup QoS: %d", err);
1259 		return -ENOEXEC;
1260 	}
1261 
1262 	return 0;
1263 }
1264 
cmd_enable(const struct shell * sh,size_t argc,char * argv[])1265 static int cmd_enable(const struct shell *sh, size_t argc, char *argv[])
1266 {
1267 	struct bt_codec *codec;
1268 	int err;
1269 
1270 	if (default_stream == NULL) {
1271 		shell_error(sh, "No stream selected");
1272 		return -ENOEXEC;
1273 	}
1274 
1275 	codec = default_stream->codec;
1276 
1277 	if (argc > 1) {
1278 		err = set_metadata(codec, argv[1]);
1279 		if (err != 0) {
1280 			shell_error(sh, "Unable to handle metadata update: %d", err);
1281 			return err;
1282 		}
1283 	}
1284 
1285 	err = bt_bap_stream_enable(default_stream, codec->meta, codec->meta_count);
1286 	if (err) {
1287 		shell_error(sh, "Unable to enable Channel");
1288 		return -ENOEXEC;
1289 	}
1290 
1291 	return 0;
1292 }
1293 
cmd_stop(const struct shell * sh,size_t argc,char * argv[])1294 static int cmd_stop(const struct shell *sh, size_t argc, char *argv[])
1295 {
1296 	int err;
1297 
1298 	if (default_stream == NULL) {
1299 		shell_error(sh, "No stream selected");
1300 		return -ENOEXEC;
1301 	}
1302 
1303 	err = bt_bap_stream_stop(default_stream);
1304 	if (err) {
1305 		shell_error(sh, "Unable to stop Channel");
1306 		return -ENOEXEC;
1307 	}
1308 
1309 	return 0;
1310 }
1311 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1312 
cmd_preset(const struct shell * sh,size_t argc,char * argv[])1313 static int cmd_preset(const struct shell *sh, size_t argc, char *argv[])
1314 {
1315 	const struct named_lc3_preset *named_preset;
1316 	bool unicast = true;
1317 
1318 	if (!strcmp(argv[1], "sink")) {
1319 		named_preset = default_sink_preset;
1320 	} else if (!strcmp(argv[1], "source")) {
1321 		named_preset = default_source_preset;
1322 	} else if (!strcmp(argv[1], "broadcast")) {
1323 		unicast = false;
1324 
1325 		named_preset = default_broadcast_source_preset;
1326 	} else {
1327 		shell_error(sh, "Unsupported dir: %s", argv[1]);
1328 		return -ENOEXEC;
1329 	}
1330 
1331 	if (argc > 2) {
1332 		named_preset = get_named_preset(unicast, argv[2]);
1333 		if (named_preset == NULL) {
1334 			shell_error(sh, "Unable to parse named_preset %s", argv[2]);
1335 			return -ENOEXEC;
1336 		}
1337 
1338 		if (!strcmp(argv[1], "sink")) {
1339 			default_sink_preset = named_preset;
1340 		} else if (!strcmp(argv[1], "source")) {
1341 			default_source_preset = named_preset;
1342 		} else if (!strcmp(argv[1], "broadcast")) {
1343 			default_broadcast_source_preset = named_preset;
1344 		}
1345 	}
1346 
1347 	shell_print(sh, "%s", named_preset->name);
1348 
1349 	print_codec(ctx_shell, &named_preset->preset.codec);
1350 	print_qos(ctx_shell, &named_preset->preset.qos);
1351 
1352 	return 0;
1353 }
1354 
1355 #define MAX_META_DATA \
1356 	(CONFIG_BT_CODEC_MAX_METADATA_COUNT * sizeof(struct bt_codec_data))
1357 
cmd_metadata(const struct shell * sh,size_t argc,char * argv[])1358 static int cmd_metadata(const struct shell *sh, size_t argc, char *argv[])
1359 {
1360 	struct bt_codec *codec;
1361 	int err;
1362 
1363 	if (default_stream == NULL) {
1364 		shell_error(sh, "No stream selected");
1365 		return -ENOEXEC;
1366 	}
1367 
1368 	codec = default_stream->codec;
1369 
1370 	if (argc > 1) {
1371 		err = set_metadata(codec, argv[1]);
1372 		if (err != 0) {
1373 			shell_error(sh, "Unable to handle metadata update: %d", err);
1374 			return err;
1375 		}
1376 	}
1377 
1378 	err = bt_bap_stream_metadata(default_stream, codec->meta, codec->meta_count);
1379 	if (err) {
1380 		shell_error(sh, "Unable to set Channel metadata");
1381 		return -ENOEXEC;
1382 	}
1383 
1384 	return 0;
1385 }
1386 
cmd_start(const struct shell * sh,size_t argc,char * argv[])1387 static int cmd_start(const struct shell *sh, size_t argc, char *argv[])
1388 {
1389 	int err;
1390 
1391 	if (default_stream == NULL) {
1392 		shell_error(sh, "No stream selected");
1393 		return -ENOEXEC;
1394 	}
1395 
1396 	err = bt_bap_stream_start(default_stream);
1397 	if (err) {
1398 		shell_error(sh, "Unable to start Channel");
1399 		return -ENOEXEC;
1400 	}
1401 
1402 	return 0;
1403 }
1404 
cmd_disable(const struct shell * sh,size_t argc,char * argv[])1405 static int cmd_disable(const struct shell *sh, size_t argc, char *argv[])
1406 {
1407 	int err;
1408 
1409 	if (default_stream == NULL) {
1410 		shell_error(sh, "No stream selected");
1411 		return -ENOEXEC;
1412 	}
1413 
1414 	err = bt_bap_stream_disable(default_stream);
1415 	if (err) {
1416 		shell_error(sh, "Unable to disable Channel");
1417 		return -ENOEXEC;
1418 	}
1419 
1420 	return 0;
1421 }
1422 
1423 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
conn_list_eps(struct bt_conn * conn,void * data)1424 static void conn_list_eps(struct bt_conn *conn, void *data)
1425 {
1426 	const struct shell *sh = (const struct shell *)data;
1427 	uint8_t conn_index = bt_conn_index(conn);
1428 
1429 	shell_print(sh, "Conn: %p", conn);
1430 	shell_print(sh, "  Sinks:");
1431 
1432 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
1433 	for (size_t i = 0U; i < ARRAY_SIZE(snks[conn_index]); i++) {
1434 		const struct bt_bap_ep *ep = snks[conn_index][i];
1435 
1436 		if (ep != NULL) {
1437 			shell_print(sh, "    #%u: ep %p", i, ep);
1438 		}
1439 	}
1440 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
1441 
1442 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
1443 	shell_print(sh, "  Sources:");
1444 
1445 	for (size_t i = 0U; i < ARRAY_SIZE(srcs[conn_index]); i++) {
1446 		const struct bt_bap_ep *ep = srcs[conn_index][i];
1447 
1448 		if (ep != NULL) {
1449 			shell_print(sh, "    #%u: ep %p", i, ep);
1450 		}
1451 	}
1452 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
1453 }
1454 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1455 
1456 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
cmd_list(const struct shell * sh,size_t argc,char * argv[])1457 static int cmd_list(const struct shell *sh, size_t argc, char *argv[])
1458 {
1459 	shell_print(sh, "Configured Channels:");
1460 
1461 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
1462 		struct bt_bap_stream *stream = &unicast_streams[i].stream.bap_stream;
1463 
1464 		if (stream->conn != NULL) {
1465 			shell_print(sh, "  %s#%u: stream %p dir 0x%02x group %p",
1466 				    stream == default_stream ? "*" : " ", i, stream,
1467 				    stream_dir(stream), stream->group);
1468 		}
1469 	}
1470 
1471 	bt_conn_foreach(BT_CONN_TYPE_LE, conn_list_eps, (void *)sh);
1472 
1473 	return 0;
1474 }
1475 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1476 
cmd_release(const struct shell * sh,size_t argc,char * argv[])1477 static int cmd_release(const struct shell *sh, size_t argc, char *argv[])
1478 {
1479 	int err;
1480 
1481 	if (default_stream == NULL) {
1482 		shell_print(sh, "No stream selected");
1483 		return -ENOEXEC;
1484 	}
1485 
1486 	err = bt_bap_stream_release(default_stream);
1487 	if (err) {
1488 		shell_error(sh, "Unable to release Channel");
1489 		return -ENOEXEC;
1490 	}
1491 
1492 	return 0;
1493 }
1494 #endif /* CONFIG_BT_BAP_UNICAST */
1495 
1496 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
1497 static uint32_t accepted_broadcast_id;
1498 static struct bt_bap_base received_base;
1499 static bool sink_syncable;
1500 
broadcast_scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * ad,uint32_t broadcast_id)1501 static bool broadcast_scan_recv(const struct bt_le_scan_recv_info *info,
1502 				struct net_buf_simple *ad,
1503 				uint32_t broadcast_id)
1504 {
1505 	char le_addr[BT_ADDR_LE_STR_LEN];
1506 
1507 	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
1508 
1509 	shell_print(ctx_shell, "Found broadcaster with ID 0x%06X and addr %s",
1510 		    broadcast_id, le_addr);
1511 
1512 	if (broadcast_id == accepted_broadcast_id) {
1513 		shell_print(ctx_shell, "PA syncing to broadcaster");
1514 		accepted_broadcast_id = 0;
1515 		return true;
1516 	}
1517 
1518 	return false;
1519 }
1520 
pa_synced(struct bt_bap_broadcast_sink * sink,struct bt_le_per_adv_sync * sync,uint32_t broadcast_id)1521 static void pa_synced(struct bt_bap_broadcast_sink *sink,
1522 		      struct bt_le_per_adv_sync *sync,
1523 		      uint32_t broadcast_id)
1524 {
1525 	shell_print(ctx_shell,
1526 		    "PA synced to broadcaster with ID 0x%06X as sink %p",
1527 		    broadcast_id, sink);
1528 
1529 	if (default_sink == NULL) {
1530 		default_sink = sink;
1531 
1532 		shell_print(ctx_shell, "Sink %p is set as default", sink);
1533 	}
1534 }
1535 
base_recv(struct bt_bap_broadcast_sink * sink,const struct bt_bap_base * base)1536 static void base_recv(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base)
1537 {
1538 	uint8_t bis_indexes[BROADCAST_SNK_STREAM_CNT] = { 0 };
1539 	/* "0xXX " requires 5 characters */
1540 	char bis_indexes_str[5 * ARRAY_SIZE(bis_indexes) + 1];
1541 	size_t index_count = 0;
1542 
1543 	if (memcmp(base, &received_base, sizeof(received_base)) == 0) {
1544 		/* Don't print duplicates */
1545 		return;
1546 	}
1547 
1548 	shell_print(ctx_shell, "Received BASE from sink %p:", sink);
1549 
1550 	for (int i = 0; i < base->subgroup_count; i++) {
1551 		const struct bt_bap_base_subgroup *subgroup;
1552 
1553 		subgroup = &base->subgroups[i];
1554 
1555 		shell_print(ctx_shell, "Subgroup[%d]:", i);
1556 		print_codec(ctx_shell, &subgroup->codec);
1557 
1558 		for (int j = 0; j < subgroup->bis_count; j++) {
1559 			const struct bt_bap_base_bis_data *bis_data;
1560 
1561 			bis_data = &subgroup->bis_data[j];
1562 
1563 			shell_print(ctx_shell, "BIS[%d] index 0x%02x",
1564 				    i, bis_data->index);
1565 			bis_indexes[index_count++] = bis_data->index;
1566 
1567 			for (int k = 0; k < bis_data->data_count; k++) {
1568 				const struct bt_codec_data *codec_data;
1569 
1570 				codec_data = &bis_data->data[k];
1571 
1572 				shell_print(ctx_shell,
1573 					    "data #%u: type 0x%02x len %u",
1574 					    i, codec_data->data.type,
1575 					    codec_data->data.data_len);
1576 				shell_hexdump(ctx_shell, codec_data->data.data,
1577 					      codec_data->data.data_len -
1578 						sizeof(codec_data->data.type));
1579 			}
1580 		}
1581 	}
1582 
1583 	memset(bis_indexes_str, 0, sizeof(bis_indexes_str));
1584 	/* Create space separated list of indexes as hex values */
1585 	for (int i = 0; i < index_count; i++) {
1586 		char bis_index_str[6];
1587 
1588 		sprintf(bis_index_str, "0x%02x ", bis_indexes[i]);
1589 
1590 		strcat(bis_indexes_str, bis_index_str);
1591 		shell_print(ctx_shell, "[%d]: %s", i, bis_index_str);
1592 	}
1593 
1594 	shell_print(ctx_shell, "Possible indexes: %s", bis_indexes_str);
1595 
1596 	(void)memcpy(&received_base, base, sizeof(received_base));
1597 }
1598 
syncable(struct bt_bap_broadcast_sink * sink,bool encrypted)1599 static void syncable(struct bt_bap_broadcast_sink *sink, bool encrypted)
1600 {
1601 	if (sink_syncable) {
1602 		return;
1603 	}
1604 
1605 	shell_print(ctx_shell, "Sink %p is ready to sync %s encryption",
1606 		    sink, encrypted ? "with" : "without");
1607 	sink_syncable = true;
1608 }
1609 
scan_term(int err)1610 static void scan_term(int err)
1611 {
1612 	shell_print(ctx_shell, "Broadcast scan was terminated: %d", err);
1613 
1614 }
1615 
pa_sync_lost(struct bt_bap_broadcast_sink * sink)1616 static void pa_sync_lost(struct bt_bap_broadcast_sink *sink)
1617 {
1618 	shell_warn(ctx_shell, "Sink %p disconnected", sink);
1619 
1620 	if (default_sink == sink) {
1621 		default_sink = NULL;
1622 		sink_syncable = false;
1623 		(void)memset(&received_base, 0, sizeof(received_base));
1624 	}
1625 }
1626 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
1627 
1628 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
1629 static struct bt_bap_broadcast_sink_cb sink_cbs = {
1630 	.scan_recv = broadcast_scan_recv,
1631 	.pa_synced = pa_synced,
1632 	.base_recv = base_recv,
1633 	.syncable = syncable,
1634 	.scan_term = scan_term,
1635 	.pa_sync_lost = pa_sync_lost,
1636 };
1637 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
1638 
1639 #if defined(CONFIG_BT_AUDIO_RX)
audio_recv(struct bt_bap_stream * stream,const struct bt_iso_recv_info * info,struct net_buf * buf)1640 static void audio_recv(struct bt_bap_stream *stream,
1641 		       const struct bt_iso_recv_info *info,
1642 		       struct net_buf *buf)
1643 {
1644 	static struct bt_iso_recv_info last_info;
1645 	static size_t rx_cnt;
1646 
1647 	/* TODO: Make it possible to only print every X packets, and make X settable by the shell */
1648 	if ((rx_cnt % 100) == 0) {
1649 		shell_print(ctx_shell,
1650 			    "[%zu]: Incoming audio on stream %p len %u ts %u seq_num %u flags %u",
1651 			    rx_cnt, stream, buf->len, info->ts, info->seq_num,
1652 			    info->flags);
1653 	}
1654 
1655 	if (info->ts == last_info.ts) {
1656 		shell_error(ctx_shell, "[%zu]: Duplicate TS: %u",
1657 			    rx_cnt, info->ts);
1658 	}
1659 
1660 	if (info->seq_num == last_info.seq_num) {
1661 		shell_error(ctx_shell, "[%zu]: Duplicate seq_num: %u",
1662 			    rx_cnt, info->seq_num);
1663 	}
1664 
1665 	(void)memcpy(&last_info, info, sizeof(last_info));
1666 
1667 	rx_cnt++;
1668 }
1669 #endif /* CONFIG_BT_AUDIO_RX */
1670 
stream_enabled_cb(struct bt_bap_stream * stream)1671 static void stream_enabled_cb(struct bt_bap_stream *stream)
1672 {
1673 	shell_print(ctx_shell, "Stream %p enabled", stream);
1674 
1675 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER)) {
1676 		struct bt_bap_ep_info ep_info;
1677 		struct bt_conn_info conn_info;
1678 		int err;
1679 
1680 		err = bt_conn_get_info(stream->conn, &conn_info);
1681 		if (err != 0) {
1682 			shell_error(ctx_shell, "Failed to get conn info: %d", err);
1683 			return;
1684 		}
1685 
1686 		if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
1687 			return; /* We also want to autonomously start the stream as the server */
1688 		}
1689 
1690 		err = bt_bap_ep_get_info(stream->ep, &ep_info);
1691 		if (err != 0) {
1692 			shell_error(ctx_shell, "Failed to get ep info: %d", err);
1693 			return;
1694 		}
1695 
1696 		if (ep_info.dir == BT_AUDIO_DIR_SINK) {
1697 			/* Automatically do the receiver start ready operation */
1698 			err = bt_bap_stream_start(stream);
1699 
1700 			if (err != 0) {
1701 				shell_error(ctx_shell, "Failed to start stream: %d", err);
1702 				return;
1703 			}
1704 		}
1705 	}
1706 }
1707 
stream_started_cb(struct bt_bap_stream * stream)1708 static void stream_started_cb(struct bt_bap_stream *stream)
1709 {
1710 	printk("Stream %p started\n", stream);
1711 }
1712 
stream_stopped_cb(struct bt_bap_stream * stream,uint8_t reason)1713 static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
1714 {
1715 	printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
1716 
1717 #if defined(CONFIG_LIBLC3)
1718 	if (stream == default_stream) {
1719 		lc3_start_time = 0;
1720 		lc3_sdu_cnt = 0;
1721 
1722 		k_work_cancel(&audio_send_work);
1723 	}
1724 #endif /* CONFIG_LIBLC3 */
1725 }
1726 
1727 #if defined(CONFIG_BT_BAP_UNICAST)
stream_released_cb(struct bt_bap_stream * stream)1728 static void stream_released_cb(struct bt_bap_stream *stream)
1729 {
1730 	shell_print(ctx_shell, "Stream %p released\n", stream);
1731 
1732 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
1733 	if (default_unicast_group != NULL) {
1734 		bool group_can_be_deleted = true;
1735 
1736 		for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
1737 			const struct bt_bap_stream *stream = &unicast_streams[i].stream.bap_stream;
1738 
1739 			if (stream->ep != NULL) {
1740 				struct bt_bap_ep_info ep_info;
1741 
1742 				bt_bap_ep_get_info(stream->ep, &ep_info);
1743 
1744 				if (ep_info.state != BT_BAP_EP_STATE_CODEC_CONFIGURED &&
1745 				    ep_info.state != BT_BAP_EP_STATE_IDLE) {
1746 					group_can_be_deleted = false;
1747 					break;
1748 				}
1749 			}
1750 		}
1751 
1752 		if (group_can_be_deleted) {
1753 			int err;
1754 
1755 			shell_print(ctx_shell, "All streams released, deleting group\n");
1756 
1757 			err = bt_bap_unicast_group_delete(default_unicast_group);
1758 
1759 			if (err != 0) {
1760 				shell_error(ctx_shell, "Failed to delete unicast group: %d", err);
1761 			} else {
1762 				default_unicast_group = NULL;
1763 			}
1764 		}
1765 	}
1766 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1767 
1768 #if defined(CONFIG_LIBLC3)
1769 	/* stop sending */
1770 	if (stream == default_stream) {
1771 		lc3_start_time = 0;
1772 		lc3_sdu_cnt = 0;
1773 
1774 		k_work_cancel(&audio_send_work);
1775 	}
1776 #endif /* CONFIG_LIBLC3 */
1777 }
1778 #endif /* CONFIG_BT_BAP_UNICAST */
1779 
1780 static struct bt_bap_stream_ops stream_ops = {
1781 #if defined(CONFIG_BT_AUDIO_RX)
1782 	.recv = audio_recv,
1783 #endif /* CONFIG_BT_AUDIO_RX */
1784 #if defined(CONFIG_BT_BAP_UNICAST)
1785 	.released = stream_released_cb,
1786 	.enabled = stream_enabled_cb,
1787 #endif /* CONFIG_BT_BAP_UNICAST */
1788 	.started = stream_started_cb,
1789 	.stopped = stream_stopped_cb,
1790 #if defined(CONFIG_LIBLC3) && defined(CONFIG_BT_AUDIO_TX)
1791 	.sent = sdu_sent_cb,
1792 #endif
1793 };
1794 
1795 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
cmd_select_broadcast_source(const struct shell * sh,size_t argc,char * argv[])1796 static int cmd_select_broadcast_source(const struct shell *sh, size_t argc,
1797 				       char *argv[])
1798 {
1799 	unsigned long index;
1800 	int err = 0;
1801 
1802 	index = shell_strtoul(argv[1], 0, &err);
1803 	if (err != 0) {
1804 		shell_error(sh, "Could not parse index: %d", err);
1805 
1806 		return -ENOEXEC;
1807 	}
1808 
1809 	if (index > ARRAY_SIZE(broadcast_source_streams)) {
1810 		shell_error(sh, "Invalid index: %lu", index);
1811 
1812 		return -ENOEXEC;
1813 	}
1814 
1815 	default_stream = &broadcast_source_streams[index].stream.bap_stream;
1816 
1817 	return 0;
1818 }
1819 
cmd_create_broadcast(const struct shell * sh,size_t argc,char * argv[])1820 static int cmd_create_broadcast(const struct shell *sh, size_t argc,
1821 				char *argv[])
1822 {
1823 	struct bt_bap_broadcast_source_stream_param
1824 		stream_params[ARRAY_SIZE(broadcast_source_streams)];
1825 	struct bt_bap_broadcast_source_subgroup_param subgroup_param;
1826 	struct bt_bap_broadcast_source_create_param create_param = {0};
1827 	const struct named_lc3_preset *named_preset;
1828 	int err;
1829 
1830 	if (default_source.bap_source != NULL) {
1831 		shell_info(sh, "Broadcast source already created");
1832 		return -ENOEXEC;
1833 	}
1834 
1835 	named_preset = default_broadcast_source_preset;
1836 
1837 	for (size_t i = 1U; i < argc; i++) {
1838 		char *arg = argv[i];
1839 
1840 		if (strcmp(arg, "enc") == 0) {
1841 			if (argc > i) {
1842 				size_t bcode_len;
1843 
1844 				i++;
1845 				arg = argv[i];
1846 
1847 				bcode_len = hex2bin(arg, strlen(arg),
1848 						    create_param.broadcast_code,
1849 						    sizeof(create_param.broadcast_code));
1850 
1851 				if (bcode_len != sizeof(create_param.broadcast_code)) {
1852 					shell_error(sh, "Invalid Broadcast Code Length: %zu",
1853 						    bcode_len);
1854 
1855 					return -ENOEXEC;
1856 				}
1857 
1858 				create_param.encryption = true;
1859 			} else {
1860 				shell_help(sh);
1861 
1862 				return SHELL_CMD_HELP_PRINTED;
1863 			}
1864 		} else if (strcmp(arg, "preset") == 0) {
1865 			if (argc > i) {
1866 
1867 				i++;
1868 				arg = argv[i];
1869 
1870 				named_preset = get_named_preset(false, arg);
1871 				if (named_preset == NULL) {
1872 					shell_error(sh, "Unable to parse named_preset %s",
1873 						    arg);
1874 
1875 					return -ENOEXEC;
1876 				}
1877 			} else {
1878 				shell_help(sh);
1879 
1880 				return SHELL_CMD_HELP_PRINTED;
1881 			}
1882 		}
1883 	}
1884 
1885 	copy_broadcast_source_preset(&default_source, named_preset);
1886 
1887 	(void)memset(stream_params, 0, sizeof(stream_params));
1888 	for (size_t i = 0; i < ARRAY_SIZE(stream_params); i++) {
1889 		stream_params[i].stream = &broadcast_source_streams[i].stream.bap_stream;
1890 	}
1891 	subgroup_param.params_count = ARRAY_SIZE(stream_params);
1892 	subgroup_param.params = stream_params;
1893 	subgroup_param.codec = &default_source.codec;
1894 	create_param.params_count = 1U;
1895 	create_param.params = &subgroup_param;
1896 	create_param.qos = &default_source.qos;
1897 
1898 	err = bt_bap_broadcast_source_create(&create_param, &default_source.bap_source);
1899 	if (err != 0) {
1900 		shell_error(sh, "Unable to create broadcast source: %d", err);
1901 		return err;
1902 	}
1903 
1904 	shell_print(sh, "Broadcast source created: preset %s",
1905 		    named_preset->name);
1906 
1907 	if (default_stream == NULL) {
1908 		default_stream = &broadcast_source_streams[0].stream.bap_stream;
1909 	}
1910 
1911 	return 0;
1912 }
1913 
cmd_start_broadcast(const struct shell * sh,size_t argc,char * argv[])1914 static int cmd_start_broadcast(const struct shell *sh, size_t argc,
1915 			       char *argv[])
1916 {
1917 	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
1918 	int err;
1919 
1920 	if (adv == NULL) {
1921 		shell_info(sh, "Extended advertising set is NULL");
1922 		return -ENOEXEC;
1923 	}
1924 
1925 	if (default_source.bap_source == NULL) {
1926 		shell_info(sh, "Broadcast source not created");
1927 		return -ENOEXEC;
1928 	}
1929 
1930 	err = bt_bap_broadcast_source_start(default_source.bap_source, adv_sets[selected_adv]);
1931 	if (err != 0) {
1932 		shell_error(sh, "Unable to start broadcast source: %d", err);
1933 		return err;
1934 	}
1935 
1936 	return 0;
1937 }
1938 
cmd_stop_broadcast(const struct shell * sh,size_t argc,char * argv[])1939 static int cmd_stop_broadcast(const struct shell *sh, size_t argc, char *argv[])
1940 {
1941 	int err;
1942 
1943 	if (default_source.bap_source == NULL) {
1944 		shell_info(sh, "Broadcast source not created");
1945 		return -ENOEXEC;
1946 	}
1947 
1948 	err = bt_bap_broadcast_source_stop(default_source.bap_source);
1949 	if (err != 0) {
1950 		shell_error(sh, "Unable to stop broadcast source: %d", err);
1951 		return err;
1952 	}
1953 
1954 	return 0;
1955 }
1956 
cmd_delete_broadcast(const struct shell * sh,size_t argc,char * argv[])1957 static int cmd_delete_broadcast(const struct shell *sh, size_t argc,
1958 				char *argv[])
1959 {
1960 	int err;
1961 
1962 	if (default_source.bap_source == NULL) {
1963 		shell_info(sh, "Broadcast source not created");
1964 		return -ENOEXEC;
1965 	}
1966 
1967 	err = bt_bap_broadcast_source_delete(default_source.bap_source);
1968 	if (err != 0) {
1969 		shell_error(sh, "Unable to delete broadcast source: %d", err);
1970 		return err;
1971 	}
1972 	default_source.bap_source = NULL;
1973 
1974 	return 0;
1975 }
1976 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
1977 
1978 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
cmd_broadcast_scan(const struct shell * sh,size_t argc,char * argv[])1979 static int cmd_broadcast_scan(const struct shell *sh, size_t argc, char *argv[])
1980 {
1981 	int err;
1982 	struct bt_le_scan_param param = {
1983 			.type       = BT_LE_SCAN_TYPE_ACTIVE,
1984 			.options    = BT_LE_SCAN_OPT_NONE,
1985 			.interval   = BT_GAP_SCAN_FAST_INTERVAL,
1986 			.window     = BT_GAP_SCAN_FAST_WINDOW,
1987 			.timeout    = 0 };
1988 
1989 	if (!initialized) {
1990 		shell_error(sh, "Not initialized");
1991 		return -ENOEXEC;
1992 	}
1993 
1994 	if (strcmp(argv[1], "on") == 0) {
1995 		err =  bt_bap_broadcast_sink_scan_start(&param);
1996 		if (err != 0) {
1997 			shell_error(sh, "Could not start scan: %d", err);
1998 		}
1999 	} else if (strcmp(argv[1], "off") == 0) {
2000 		err = bt_bap_broadcast_sink_scan_stop();
2001 		if (err != 0) {
2002 			shell_error(sh, "Could not stop scan: %d", err);
2003 		}
2004 	} else {
2005 		shell_help(sh);
2006 		err = -ENOEXEC;
2007 	}
2008 
2009 	return err;
2010 }
2011 
cmd_accept_broadcast(const struct shell * sh,size_t argc,char * argv[])2012 static int cmd_accept_broadcast(const struct shell *sh, size_t argc,
2013 				char *argv[])
2014 {
2015 	unsigned long broadcast_id;
2016 	int err = 0;
2017 
2018 	broadcast_id = shell_strtoul(argv[1], 0, &err);
2019 	if (err != 0) {
2020 		shell_error(sh, "Could not parse broadcast_id: %d", err);
2021 
2022 		return -ENOEXEC;
2023 	}
2024 
2025 	if (broadcast_id > BT_AUDIO_BROADCAST_ID_MAX) {
2026 		shell_error(sh, "Invalid broadcast_id: %lu", broadcast_id);
2027 
2028 		return -ENOEXEC;
2029 	}
2030 
2031 	accepted_broadcast_id = broadcast_id;
2032 
2033 	return 0;
2034 }
2035 
cmd_sync_broadcast(const struct shell * sh,size_t argc,char * argv[])2036 static int cmd_sync_broadcast(const struct shell *sh, size_t argc, char *argv[])
2037 {
2038 	struct bt_bap_stream *streams[ARRAY_SIZE(broadcast_sink_streams)];
2039 	uint32_t bis_bitfield;
2040 	int err;
2041 
2042 	bis_bitfield = 0;
2043 	for (int i = 1; i < argc; i++) {
2044 		unsigned long val;
2045 		int err = 0;
2046 
2047 		val = shell_strtoul(argv[i], 0, &err);
2048 		if (err != 0) {
2049 			shell_error(sh, "Could not parse BIS index val: %d",
2050 				    err);
2051 
2052 			return -ENOEXEC;
2053 		}
2054 
2055 		if (!IN_RANGE(val,
2056 			      BT_ISO_BIS_INDEX_MIN,
2057 			      BT_ISO_BIS_INDEX_MAX)) {
2058 			shell_error(sh, "Invalid index: %lu", val);
2059 
2060 			return -ENOEXEC;
2061 		}
2062 
2063 		bis_bitfield |= BIT(val);
2064 	}
2065 
2066 	if (default_sink == NULL) {
2067 		shell_error(sh, "No sink available");
2068 		return -ENOEXEC;
2069 	}
2070 
2071 	(void)memset(streams, 0, sizeof(streams));
2072 	for (size_t i = 0; i < ARRAY_SIZE(streams); i++) {
2073 		streams[i] = &broadcast_sink_streams[i];
2074 	}
2075 
2076 	err = bt_bap_broadcast_sink_sync(default_sink, bis_bitfield, streams, NULL);
2077 	if (err != 0) {
2078 		shell_error(sh, "Failed to sync to broadcast: %d", err);
2079 		return err;
2080 	}
2081 
2082 	return 0;
2083 }
2084 
cmd_stop_broadcast_sink(const struct shell * sh,size_t argc,char * argv[])2085 static int cmd_stop_broadcast_sink(const struct shell *sh, size_t argc,
2086 				   char *argv[])
2087 {
2088 	int err;
2089 
2090 	if (default_sink == NULL) {
2091 		shell_error(sh, "No sink available");
2092 		return -ENOEXEC;
2093 	}
2094 
2095 	err = bt_bap_broadcast_sink_stop(default_sink);
2096 	if (err != 0) {
2097 		shell_error(sh, "Failed to stop sink: %d", err);
2098 		return err;
2099 	}
2100 
2101 	return err;
2102 }
2103 
cmd_term_broadcast_sink(const struct shell * sh,size_t argc,char * argv[])2104 static int cmd_term_broadcast_sink(const struct shell *sh, size_t argc,
2105 				   char *argv[])
2106 {
2107 	int err;
2108 
2109 	if (default_sink == NULL) {
2110 		shell_error(sh, "No sink available");
2111 		return -ENOEXEC;
2112 	}
2113 
2114 	err = bt_bap_broadcast_sink_delete(default_sink);
2115 	if (err != 0) {
2116 		shell_error(sh, "Failed to term sink: %d", err);
2117 		return err;
2118 	}
2119 
2120 	default_sink = NULL;
2121 	sink_syncable = false;
2122 
2123 	return err;
2124 }
2125 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
2126 
cmd_set_loc(const struct shell * sh,size_t argc,char * argv[])2127 static int cmd_set_loc(const struct shell *sh, size_t argc, char *argv[])
2128 {
2129 	int err = 0;
2130 	enum bt_audio_dir dir;
2131 	enum bt_audio_location loc;
2132 	unsigned long loc_val;
2133 
2134 	if (!strcmp(argv[1], "sink")) {
2135 		dir = BT_AUDIO_DIR_SINK;
2136 	} else if (!strcmp(argv[1], "source")) {
2137 		dir = BT_AUDIO_DIR_SOURCE;
2138 	} else {
2139 		shell_error(sh, "Unsupported dir: %s", argv[1]);
2140 		return -ENOEXEC;
2141 	}
2142 
2143 	loc_val = shell_strtoul(argv[2], 16, &err);
2144 	if (err != 0) {
2145 		shell_error(sh, "Could not parse loc_val: %d", err);
2146 
2147 		return -ENOEXEC;
2148 	}
2149 
2150 	if (loc_val == BT_AUDIO_LOCATION_PROHIBITED ||
2151 	    loc_val > BT_AUDIO_LOCATION_ANY) {
2152 		shell_error(sh, "Invalid location: %lu", loc_val);
2153 
2154 		return -ENOEXEC;
2155 	}
2156 
2157 	loc = loc_val;
2158 
2159 	err = bt_pacs_set_location(dir, loc);
2160 	if (err) {
2161 		shell_error(ctx_shell, "Set available contexts err %d", err);
2162 		return -ENOEXEC;
2163 	}
2164 
2165 	return 0;
2166 }
2167 
cmd_context(const struct shell * sh,size_t argc,char * argv[])2168 static int cmd_context(const struct shell *sh, size_t argc, char *argv[])
2169 {
2170 	int err = 0;
2171 	enum bt_audio_dir dir;
2172 	enum bt_audio_context ctx;
2173 	unsigned long ctx_val;
2174 
2175 	if (!strcmp(argv[1], "sink")) {
2176 		dir = BT_AUDIO_DIR_SINK;
2177 	} else if (!strcmp(argv[1], "source")) {
2178 		dir = BT_AUDIO_DIR_SOURCE;
2179 	} else {
2180 		shell_error(sh, "Unsupported dir: %s", argv[1]);
2181 		return -ENOEXEC;
2182 	}
2183 
2184 	ctx_val = shell_strtoul(argv[2], 16, &err);
2185 	if (err) {
2186 		shell_error(sh, "Could not parse context: %d", err);
2187 
2188 		return err;
2189 	}
2190 
2191 	if (ctx_val == BT_AUDIO_CONTEXT_TYPE_PROHIBITED ||
2192 	    ctx_val > BT_AUDIO_CONTEXT_TYPE_ANY) {
2193 		shell_error(sh, "Invalid context: %lu", ctx_val);
2194 
2195 		return -ENOEXEC;
2196 	}
2197 
2198 	ctx = ctx_val;
2199 
2200 	if (!strcmp(argv[3], "supported")) {
2201 		err = bt_pacs_set_supported_contexts(dir, ctx);
2202 		if (err) {
2203 			shell_error(ctx_shell, "Set supported contexts err %d", err);
2204 			return err;
2205 		}
2206 	} else if (!strcmp(argv[3], "available")) {
2207 		err = bt_pacs_set_available_contexts(dir, ctx);
2208 		if (err) {
2209 			shell_error(ctx_shell, "Set available contexts err %d", err);
2210 			return err;
2211 		}
2212 	} else {
2213 		shell_error(sh, "Unsupported context type: %s", argv[3]);
2214 		return -ENOEXEC;
2215 	}
2216 
2217 	return 0;
2218 }
2219 
cmd_init(const struct shell * sh,size_t argc,char * argv[])2220 static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
2221 {
2222 	int err, i;
2223 
2224 	ctx_shell = sh;
2225 
2226 	if (initialized) {
2227 		shell_print(sh, "Already initialized");
2228 		return -ENOEXEC;
2229 	}
2230 
2231 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER)) {
2232 		bt_bap_unicast_server_register_cb(&unicast_server_cb);
2233 	}
2234 
2235 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) ||
2236 	    IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SINK)) {
2237 		bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink);
2238 	}
2239 
2240 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER)) {
2241 		bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap_source);
2242 	}
2243 
2244 	if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) {
2245 		err = bt_pacs_set_location(BT_AUDIO_DIR_SINK, LOCATION);
2246 		__ASSERT(err == 0, "Failed to set sink location: %d", err);
2247 
2248 		err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK,
2249 						     CONTEXT);
2250 		__ASSERT(err == 0, "Failed to set sink supported contexts: %d",
2251 			 err);
2252 
2253 		err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK,
2254 						     CONTEXT);
2255 		__ASSERT(err == 0, "Failed to set sink available contexts: %d",
2256 			 err);
2257 	}
2258 
2259 	if (IS_ENABLED(CONFIG_BT_PAC_SRC_LOC)) {
2260 		err = bt_pacs_set_location(BT_AUDIO_DIR_SOURCE, LOCATION);
2261 		__ASSERT(err == 0, "Failed to set source location: %d", err);
2262 
2263 		err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE,
2264 						     CONTEXT);
2265 		__ASSERT(err == 0, "Failed to set sink supported contexts: %d",
2266 			 err);
2267 
2268 		err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE,
2269 						     CONTEXT);
2270 		__ASSERT(err == 0,
2271 			 "Failed to set source available contexts: %d",
2272 			 err);
2273 	}
2274 
2275 #if defined(CONFIG_BT_BAP_UNICAST)
2276 	for (i = 0; i < ARRAY_SIZE(unicast_streams); i++) {
2277 		bt_bap_stream_cb_register(&unicast_streams[i].stream.bap_stream, &stream_ops);
2278 	}
2279 #endif /* CONFIG_BT_BAP_UNICAST */
2280 
2281 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
2282 	bt_bap_broadcast_sink_register_cb(&sink_cbs);
2283 
2284 	for (i = 0; i < ARRAY_SIZE(broadcast_sink_streams); i++) {
2285 		bt_bap_stream_cb_register(&broadcast_sink_streams[i],
2286 					    &stream_ops);
2287 	}
2288 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
2289 
2290 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
2291 	for (i = 0; i < ARRAY_SIZE(broadcast_source_streams); i++) {
2292 		bt_bap_stream_cb_register(&broadcast_source_streams[i].stream.bap_stream,
2293 					  &stream_ops);
2294 	}
2295 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
2296 
2297 	initialized = true;
2298 
2299 	return 0;
2300 }
2301 
2302 #if defined(CONFIG_BT_AUDIO_TX)
2303 #define DATA_MTU CONFIG_BT_ISO_TX_MTU
2304 NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, DATA_MTU, 8, NULL);
2305 
cmd_send(const struct shell * sh,size_t argc,char * argv[])2306 static int cmd_send(const struct shell *sh, size_t argc, char *argv[])
2307 {
2308 	static uint8_t data[DATA_MTU - BT_ISO_CHAN_SEND_RESERVE];
2309 	int ret, len;
2310 	struct net_buf *buf;
2311 
2312 	if (default_stream == NULL) {
2313 		shell_error(sh, "Invalid (NULL) stream");
2314 
2315 		return -ENOEXEC;
2316 	}
2317 
2318 	if (txing_stream != NULL) {
2319 		shell_error(sh, "A stream %p is already TXing", txing_stream);
2320 
2321 		return -ENOEXEC;
2322 	}
2323 
2324 	if (default_stream->qos == NULL) {
2325 		shell_error(sh, "NULL stream QoS");
2326 
2327 		return -ENOEXEC;
2328 	}
2329 
2330 	if (argc > 1) {
2331 		len = hex2bin(argv[1], strlen(argv[1]), data, sizeof(data));
2332 		if (len > default_stream->qos->sdu) {
2333 			shell_print(sh, "Unable to send: len %d > %u MTU",
2334 				    len, default_stream->qos->sdu);
2335 
2336 			return -ENOEXEC;
2337 		}
2338 	} else {
2339 		len = MIN(default_stream->qos->sdu, sizeof(data));
2340 		memset(data, 0xff, len);
2341 	}
2342 
2343 	buf = net_buf_alloc(&tx_pool, K_FOREVER);
2344 	net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
2345 
2346 	net_buf_add_mem(buf, data, len);
2347 
2348 	seq_num = get_next_seq_num(default_stream->qos->interval);
2349 
2350 	ret = bt_bap_stream_send(default_stream, buf, seq_num,
2351 				 BT_ISO_TIMESTAMP_NONE);
2352 	if (ret < 0) {
2353 		shell_print(sh, "Unable to send: %d", -ret);
2354 		net_buf_unref(buf);
2355 
2356 		return -ENOEXEC;
2357 	}
2358 
2359 	shell_print(sh, "Sending:");
2360 	shell_hexdump(sh, data, len);
2361 
2362 	return 0;
2363 }
2364 
2365 #if defined(CONFIG_LIBLC3)
cmd_start_sine(const struct shell * sh,size_t argc,char * argv[])2366 static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[])
2367 {
2368 	/* For the first call-back we push multiple audio frames to the buffer to use the
2369 	 * controller ISO buffer to handle jitter.
2370 	 */
2371 	const size_t prime_count = 2U;
2372 
2373 	if (default_stream == NULL) {
2374 		shell_error(sh, "Invalid (NULL) stream");
2375 
2376 		return -ENOEXEC;
2377 	}
2378 
2379 	if (txing_stream == NULL) {
2380 		txing_stream = default_stream;
2381 	} else {
2382 		shell_error(sh, "A stream %p is already TXing", txing_stream);
2383 
2384 		return -ENOEXEC;
2385 	}
2386 
2387 	if (txing_stream->qos == NULL) {
2388 		shell_error(ctx_shell, "NULL stream QoS");
2389 
2390 		txing_stream = NULL;
2391 
2392 		return -ENOEXEC;
2393 	}
2394 
2395 	init_lc3(txing_stream);
2396 
2397 	for (size_t i = 0U; i < prime_count; i++) {
2398 		k_work_submit(&audio_send_work);
2399 	}
2400 
2401 	return 0;
2402 }
2403 
cmd_stop_sine(const struct shell * sh,size_t argc,char * argv[])2404 static int cmd_stop_sine(const struct shell *sh, size_t argc, char *argv[])
2405 {
2406 	lc3_start_time = 0;
2407 	lc3_sdu_cnt = 0;
2408 
2409 	k_work_cancel(&audio_send_work);
2410 
2411 	txing_stream = NULL;
2412 
2413 	return 0;
2414 }
2415 #endif /* CONFIG_LIBLC3 */
2416 #endif /* CONFIG_BT_AUDIO_TX */
2417 
2418 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
print_ase_info(struct bt_bap_ep * ep,void * user_data)2419 static void print_ase_info(struct bt_bap_ep *ep, void *user_data)
2420 {
2421 	struct bt_bap_ep_info info;
2422 
2423 	bt_bap_ep_get_info(ep, &info);
2424 	printk("ASE info: id %u state %u dir %u\n", info.id, info.state,
2425 	       info.dir);
2426 }
2427 
cmd_print_ase_info(const struct shell * sh,size_t argc,char * argv[])2428 static int cmd_print_ase_info(const struct shell *sh, size_t argc, char *argv[])
2429 {
2430 	if (!default_conn) {
2431 		shell_error(sh, "Not connected");
2432 		return -ENOEXEC;
2433 	}
2434 
2435 	bt_bap_unicast_server_foreach_ep(default_conn, print_ase_info, NULL);
2436 
2437 	return 0;
2438 }
2439 #endif /* CONFIG_BT_BAP_UNICAST_SERVER */
2440 
2441 SHELL_STATIC_SUBCMD_SET_CREATE(
2442 	bap_cmds, SHELL_CMD_ARG(init, NULL, NULL, cmd_init, 1, 0),
2443 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
2444 	SHELL_CMD_ARG(select_broadcast, NULL, "<stream>", cmd_select_broadcast_source, 2, 0),
2445 	SHELL_CMD_ARG(create_broadcast, NULL, "[preset <preset_name>] [enc <broadcast_code>]",
2446 		      cmd_create_broadcast, 1, 2),
2447 	SHELL_CMD_ARG(start_broadcast, NULL, "", cmd_start_broadcast, 1, 0),
2448 	SHELL_CMD_ARG(stop_broadcast, NULL, "", cmd_stop_broadcast, 1, 0),
2449 	SHELL_CMD_ARG(delete_broadcast, NULL, "", cmd_delete_broadcast, 1, 0),
2450 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
2451 #if defined(CONFIG_BT_BAP_BROADCAST_SINK)
2452 	SHELL_CMD_ARG(broadcast_scan, NULL, "<on, off>", cmd_broadcast_scan, 2, 0),
2453 	SHELL_CMD_ARG(accept_broadcast, NULL, "0x<broadcast_id>", cmd_accept_broadcast, 2, 0),
2454 	SHELL_CMD_ARG(sync_broadcast, NULL, "0x<bis_index> [[[0x<bis_index>] 0x<bis_index>] ...]",
2455 		      cmd_sync_broadcast, 2, ARRAY_SIZE(broadcast_sink_streams) - 1),
2456 	SHELL_CMD_ARG(stop_broadcast_sink, NULL, "Stops broadcast sink", cmd_stop_broadcast_sink, 1,
2457 		      0),
2458 	SHELL_CMD_ARG(term_broadcast_sink, NULL, "", cmd_term_broadcast_sink, 1, 0),
2459 #endif /* CONFIG_BT_BAP_BROADCAST_SINK */
2460 #if defined(CONFIG_BT_BAP_UNICAST)
2461 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
2462 	SHELL_CMD_ARG(discover, NULL, "[dir: sink, source]", cmd_discover, 1, 1),
2463 	SHELL_CMD_ARG(config, NULL,
2464 		      "<direction: sink, source> <index> [loc <loc_bits>] [preset <preset_name>]",
2465 		      cmd_config, 3, 4),
2466 	SHELL_CMD_ARG(stream_qos, NULL, "interval [framing] [latency] [pd] [sdu] [phy] [rtn]",
2467 		      cmd_stream_qos, 2, 6),
2468 	SHELL_CMD_ARG(qos, NULL, "Send QoS configure for Unicast Group", cmd_qos, 1, 0),
2469 	SHELL_CMD_ARG(enable, NULL, "[context]", cmd_enable, 1, 1),
2470 	SHELL_CMD_ARG(stop, NULL, NULL, cmd_stop, 1, 0),
2471 	SHELL_CMD_ARG(list, NULL, NULL, cmd_list, 1, 0),
2472 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
2473 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
2474 	SHELL_CMD_ARG(print_ase_info, NULL, "Print ASE info for default connection",
2475 		      cmd_print_ase_info, 0, 0),
2476 #endif /* CONFIG_BT_BAP_UNICAST_SERVER */
2477 	SHELL_CMD_ARG(metadata, NULL, "[context]", cmd_metadata, 1, 1),
2478 	SHELL_CMD_ARG(start, NULL, NULL, cmd_start, 1, 0),
2479 	SHELL_CMD_ARG(disable, NULL, NULL, cmd_disable, 1, 0),
2480 	SHELL_CMD_ARG(release, NULL, NULL, cmd_release, 1, 0),
2481 	SHELL_CMD_ARG(select_unicast, NULL, "<stream>", cmd_select_unicast, 2, 0),
2482 #endif /* CONFIG_BT_BAP_UNICAST */
2483 	SHELL_CMD_ARG(preset, NULL, "<sink, source, broadcast> [preset]", cmd_preset, 2, 1),
2484 #if defined(CONFIG_BT_AUDIO_TX)
2485 	SHELL_CMD_ARG(send, NULL, "Send to Audio Stream [data]", cmd_send, 1, 1),
2486 #if defined(CONFIG_LIBLC3)
2487 	SHELL_CMD_ARG(start_sine, NULL, "Start sending a LC3 encoded sine wave", cmd_start_sine, 1,
2488 		      0),
2489 	SHELL_CMD_ARG(stop_sine, NULL, "Stop sending a LC3 encoded sine wave", cmd_stop_sine, 1, 0),
2490 #endif /* CONFIG_LIBLC3 */
2491 #endif /* CONFIG_BT_AUDIO_TX */
2492 	SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_location, NULL,
2493 			   "<direction: sink, source> <location bitmask>", cmd_set_loc, 3, 0),
2494 	SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_context, NULL,
2495 			   "<direction: sink, source>"
2496 			   "<context bitmask> <type: supported, available>",
2497 			   cmd_context, 4, 0),
2498 	SHELL_SUBCMD_SET_END);
2499 
cmd_bap(const struct shell * sh,size_t argc,char ** argv)2500 static int cmd_bap(const struct shell *sh, size_t argc, char **argv)
2501 {
2502 	if (argc > 1) {
2503 		shell_error(sh, "%s unknown parameter: %s",
2504 			    argv[0], argv[1]);
2505 	} else {
2506 		shell_error(sh, "%s Missing subcommand", argv[0]);
2507 	}
2508 
2509 	return -ENOEXEC;
2510 }
2511 
2512 SHELL_CMD_ARG_REGISTER(bap, &bap_cmds, "Bluetooth BAP shell commands", cmd_bap, 1, 1);
2513 
connectable_ad_data_add(struct bt_data * data_array,size_t data_array_size)2514 static ssize_t connectable_ad_data_add(struct bt_data *data_array,
2515 				       size_t data_array_size)
2516 {
2517 	static const uint8_t ad_ext_uuid16[] = {
2518 		IF_ENABLED(CONFIG_BT_MICP_MIC_DEV, (BT_UUID_16_ENCODE(BT_UUID_MICS_VAL),))
2519 		IF_ENABLED(CONFIG_BT_ASCS, (BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL),))
2520 		IF_ENABLED(CONFIG_BT_BAP_SCAN_DELEGATOR, (BT_UUID_16_ENCODE(BT_UUID_BASS_VAL),))
2521 		IF_ENABLED(CONFIG_BT_PACS, (BT_UUID_16_ENCODE(BT_UUID_PACS_VAL),))
2522 		IF_ENABLED(CONFIG_BT_GTBS, (BT_UUID_16_ENCODE(BT_UUID_GTBS_VAL),))
2523 		IF_ENABLED(CONFIG_BT_TBS, (BT_UUID_16_ENCODE(BT_UUID_TBS_VAL),))
2524 		IF_ENABLED(CONFIG_BT_VCP_VOL_REND, (BT_UUID_16_ENCODE(BT_UUID_VCS_VAL),))
2525 		IF_ENABLED(CONFIG_BT_HAS, (BT_UUID_16_ENCODE(BT_UUID_HAS_VAL),)) /* Shall be last */
2526 	};
2527 	size_t ad_len = 0;
2528 
2529 	if (IS_ENABLED(CONFIG_BT_ASCS)) {
2530 		static uint8_t ad_bap_announcement[8] = {
2531 			BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL),
2532 			BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED,
2533 		};
2534 		enum bt_audio_context snk_context, src_context;
2535 
2536 		snk_context = bt_pacs_get_available_contexts(BT_AUDIO_DIR_SINK);
2537 		sys_put_le16(snk_context, &ad_bap_announcement[3]);
2538 
2539 		src_context = bt_pacs_get_available_contexts(BT_AUDIO_DIR_SOURCE);
2540 		sys_put_le16(snk_context, &ad_bap_announcement[5]);
2541 
2542 		/* Metadata length */
2543 		ad_bap_announcement[7] = 0x00;
2544 
2545 		__ASSERT(data_array_size > ad_len, "No space for AD_BAP_ANNOUNCEMENT");
2546 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
2547 		data_array[ad_len].data_len = ARRAY_SIZE(ad_bap_announcement);
2548 		data_array[ad_len].data = &ad_bap_announcement[0];
2549 		ad_len++;
2550 	}
2551 
2552 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR)) {
2553 		ad_len += cap_acceptor_ad_data_add(&data_array[ad_len], data_array_size - ad_len,
2554 						   true);
2555 	}
2556 
2557 	if (ARRAY_SIZE(ad_ext_uuid16) > 0) {
2558 		size_t uuid16_size;
2559 
2560 		if (data_array_size <= ad_len) {
2561 			shell_warn(ctx_shell, "No space for AD_UUID16");
2562 			return ad_len;
2563 		}
2564 
2565 		data_array[ad_len].type = BT_DATA_UUID16_SOME;
2566 
2567 		if (IS_ENABLED(CONFIG_BT_HAS) && IS_ENABLED(CONFIG_BT_PRIVACY)) {
2568 			/* If the HA is in one of the GAP connectable modes and is using a
2569 			 * resolvable private address, the HA shall not include the Hearing Access
2570 			 * Service UUID in the Service UUID AD type field of the advertising data
2571 			 * or scan response.
2572 			 */
2573 			uuid16_size = ARRAY_SIZE(ad_ext_uuid16) - BT_UUID_SIZE_16;
2574 		} else {
2575 			uuid16_size = ARRAY_SIZE(ad_ext_uuid16);
2576 		}
2577 
2578 		/* We can maximum advertise 127 16-bit UUIDs = 254 octets */
2579 		data_array[ad_len].data_len = MIN(uuid16_size, 254);
2580 
2581 		data_array[ad_len].data = &ad_ext_uuid16[0];
2582 		ad_len++;
2583 	}
2584 
2585 	return ad_len;
2586 }
2587 
nonconnectable_ad_data_add(struct bt_data * data_array,const size_t data_array_size)2588 static ssize_t nonconnectable_ad_data_add(struct bt_data *data_array,
2589 					  const size_t data_array_size)
2590 {
2591 	static const uint8_t ad_ext_uuid16[] = {
2592 		IF_ENABLED(CONFIG_BT_PACS, (BT_UUID_16_ENCODE(BT_UUID_PACS_VAL),))
2593 		IF_ENABLED(CONFIG_BT_CAP_ACCEPTOR, (BT_UUID_16_ENCODE(BT_UUID_CAS_VAL),))
2594 	};
2595 	size_t ad_len = 0;
2596 
2597 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR)) {
2598 		static const uint8_t ad_cap_announcement[3] = {
2599 			BT_UUID_16_ENCODE(BT_UUID_CAS_VAL),
2600 			BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED,
2601 		};
2602 
2603 		__ASSERT(data_array_size > ad_len, "No space for AD_CAP_ANNOUNCEMENT");
2604 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
2605 		data_array[ad_len].data_len = ARRAY_SIZE(ad_cap_announcement);
2606 		data_array[ad_len].data = &ad_cap_announcement[0];
2607 		ad_len++;
2608 	}
2609 
2610 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
2611 	if (default_source.bap_source) {
2612 		static uint8_t ad_bap_broadcast_announcement[5] = {
2613 			BT_UUID_16_ENCODE(BT_UUID_BROADCAST_AUDIO_VAL),
2614 		};
2615 		uint32_t broadcast_id;
2616 		int err;
2617 
2618 		err = bt_bap_broadcast_source_get_id(default_source.bap_source, &broadcast_id);
2619 		if (err != 0) {
2620 			printk("Unable to get broadcast ID: %d\n", err);
2621 
2622 			return -1;
2623 		}
2624 
2625 		ad_bap_broadcast_announcement[2] = (uint8_t)(broadcast_id >> 16);
2626 		ad_bap_broadcast_announcement[3] = (uint8_t)(broadcast_id >> 8);
2627 		ad_bap_broadcast_announcement[4] = (uint8_t)(broadcast_id >> 0);
2628 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
2629 		data_array[ad_len].data_len = ARRAY_SIZE(ad_bap_broadcast_announcement);
2630 		data_array[ad_len].data = ad_bap_broadcast_announcement;
2631 		ad_len++;
2632 	}
2633 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
2634 
2635 	if (ARRAY_SIZE(ad_ext_uuid16) > 0) {
2636 		if (data_array_size <= ad_len) {
2637 			shell_warn(ctx_shell, "No space for AD_UUID16");
2638 			return ad_len;
2639 		}
2640 
2641 		data_array[ad_len].type = BT_DATA_UUID16_SOME;
2642 		data_array[ad_len].data_len = ARRAY_SIZE(ad_ext_uuid16);
2643 		data_array[ad_len].data = &ad_ext_uuid16[0];
2644 		ad_len++;
2645 	}
2646 
2647 	return ad_len;
2648 }
2649 
audio_ad_data_add(struct bt_data * data_array,const size_t data_array_size,const bool discoverable,const bool connectable)2650 ssize_t audio_ad_data_add(struct bt_data *data_array, const size_t data_array_size,
2651 			  const bool discoverable, const bool connectable)
2652 {
2653 	if (!discoverable) {
2654 		return 0;
2655 	}
2656 
2657 	if (connectable) {
2658 		return connectable_ad_data_add(data_array, data_array_size);
2659 	} else {
2660 		return nonconnectable_ad_data_add(data_array, data_array_size);
2661 	}
2662 }
2663 
audio_pa_data_add(struct bt_data * data_array,const size_t data_array_size)2664 ssize_t audio_pa_data_add(struct bt_data *data_array,
2665 			  const size_t data_array_size)
2666 {
2667 	size_t ad_len = 0;
2668 
2669 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
2670 	if (default_source.bap_source) {
2671 		/* Required size of the buffer depends on what has been
2672 		 * configured. We just use the maximum size possible.
2673 		 */
2674 		NET_BUF_SIMPLE_DEFINE_STATIC(base_buf, UINT8_MAX);
2675 		int err;
2676 
2677 		err = bt_bap_broadcast_source_get_base(default_source.bap_source, &base_buf);
2678 		if (err != 0) {
2679 			printk("Unable to get BASE: %d\n", err);
2680 
2681 			return -1;
2682 		}
2683 
2684 		data_array[ad_len].type = BT_DATA_SVC_DATA16;
2685 		data_array[ad_len].data_len = base_buf.len;
2686 		data_array[ad_len].data = base_buf.data;
2687 		ad_len++;
2688 	}
2689 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
2690 
2691 	return ad_len;
2692 }
2693