1 /*
2  * Copyright (c) 2021-2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <errno.h>
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include <zephyr/autoconf.h>
14 #include <zephyr/bluetooth/audio/audio.h>
15 #include <zephyr/bluetooth/audio/bap.h>
16 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
17 #include <zephyr/bluetooth/audio/lc3.h>
18 #include <zephyr/bluetooth/bluetooth.h>
19 #include <zephyr/bluetooth/byteorder.h>
20 #include <zephyr/bluetooth/gap.h>
21 #include <zephyr/bluetooth/iso.h>
22 #include <zephyr/bluetooth/uuid.h>
23 #include <zephyr/kernel.h>
24 #include <zephyr/net_buf.h>
25 #include <zephyr/sys/printk.h>
26 #include <zephyr/sys/util.h>
27 #include <zephyr/sys/util_macro.h>
28 #include <zephyr/toolchain.h>
29 
30 #include "bap_common.h"
31 #include "bap_stream_tx.h"
32 #include "bstests.h"
33 #include "common.h"
34 
35 #define SUPPORTED_CHAN_COUNTS          BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1, 2)
36 #define SUPPORTED_MIN_OCTETS_PER_FRAME 30
37 #define SUPPORTED_MAX_OCTETS_PER_FRAME 155
38 #define SUPPORTED_MAX_FRAMES_PER_SDU   1
39 
40 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
41 CREATE_FLAG(flag_source_started);
42 
43 static struct audio_test_stream broadcast_source_streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
44 static struct bt_bap_lc3_preset preset_16_2_1 = BT_BAP_LC3_BROADCAST_PRESET_16_2_1(
45 	BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
46 static struct bt_bap_lc3_preset preset_16_1_1 = BT_BAP_LC3_BROADCAST_PRESET_16_1_1(
47 	BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
48 
49 static uint8_t bis_codec_data[] = {
50 	BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_CHAN_ALLOC,
51 			    BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_CENTER)),
52 };
53 static unsigned long subgroup_cnt_arg = 1;
54 static unsigned long streams_per_subgroup_cnt_arg = 1;
55 
56 static K_SEM_DEFINE(sem_stream_started, 0U, ARRAY_SIZE(broadcast_source_streams));
57 static K_SEM_DEFINE(sem_stream_stopped, 0U, ARRAY_SIZE(broadcast_source_streams));
58 
validate_stream_codec_cfg(const struct bt_bap_stream * stream)59 static void validate_stream_codec_cfg(const struct bt_bap_stream *stream)
60 {
61 	const struct bt_audio_codec_cfg *codec_cfg = stream->codec_cfg;
62 	const struct bt_audio_codec_cfg *exp_codec_cfg = &preset_16_1_1.codec_cfg;
63 	enum bt_audio_location chan_allocation;
64 	uint8_t frames_blocks_per_sdu;
65 	size_t min_sdu_size_required;
66 	uint16_t octets_per_frame;
67 	uint8_t chan_cnt;
68 	int ret;
69 	int exp_ret;
70 
71 	ret = bt_audio_codec_cfg_get_freq(codec_cfg);
72 	exp_ret = bt_audio_codec_cfg_get_freq(exp_codec_cfg);
73 	if (ret >= 0) {
74 		const int freq = bt_audio_codec_cfg_freq_to_freq_hz(ret);
75 		const int exp_freq = bt_audio_codec_cfg_freq_to_freq_hz(exp_ret);
76 
77 		if (freq != exp_freq) {
78 			FAIL("Invalid frequency: %d Expected: %d\n", freq, exp_freq);
79 
80 			return;
81 		}
82 	} else {
83 		FAIL("Could not get frequency: %d\n", ret);
84 
85 		return;
86 	}
87 
88 	ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg);
89 	exp_ret = bt_audio_codec_cfg_get_frame_dur(exp_codec_cfg);
90 	if (ret >= 0) {
91 		const int frm_dur_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret);
92 		const int exp_frm_dur_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(exp_ret);
93 
94 		if (frm_dur_us != exp_frm_dur_us) {
95 			FAIL("Invalid frame duration: %d Exp: %d\n", frm_dur_us, exp_frm_dur_us);
96 
97 			return;
98 		}
99 	} else {
100 		FAIL("Could not get frame duration: %d\n", ret);
101 
102 		return;
103 	}
104 
105 	/* The broadcast source sets the channel allocation in the BIS to
106 	 * BT_AUDIO_LOCATION_FRONT_CENTER
107 	 */
108 	ret = bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, true);
109 	if (ret == 0) {
110 		if (chan_allocation != BT_AUDIO_LOCATION_FRONT_CENTER) {
111 			FAIL("Unexpected channel allocation: 0x%08X", chan_allocation);
112 
113 			return;
114 		}
115 
116 		chan_cnt = bt_audio_get_chan_count(chan_allocation);
117 	} else {
118 		FAIL("Could not get subgroup channel allocation: %d\n", ret);
119 
120 		return;
121 	}
122 
123 	if (chan_cnt == 0 || (BIT(chan_cnt - 1) & SUPPORTED_CHAN_COUNTS) == 0) {
124 		FAIL("Unsupported channel count: %u\n", chan_cnt);
125 
126 		return;
127 	}
128 
129 	ret = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg);
130 	if (ret > 0) {
131 		octets_per_frame = (uint16_t)ret;
132 	} else {
133 		FAIL("Could not get subgroup octets per frame: %d\n", ret);
134 
135 		return;
136 	}
137 
138 	if (!IN_RANGE(octets_per_frame, SUPPORTED_MIN_OCTETS_PER_FRAME,
139 		      SUPPORTED_MAX_OCTETS_PER_FRAME)) {
140 		FAIL("Unsupported octets per frame: %u\n", octets_per_frame);
141 
142 		return;
143 	}
144 
145 	ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true);
146 	if (ret > 0) {
147 		frames_blocks_per_sdu = (uint8_t)ret;
148 	} else {
149 		FAIL("Could not get frame blocks per SDU: %d\n", ret);
150 
151 		return;
152 	}
153 
154 	/* An SDU can consist of X frame blocks, each with Y frames (one per channel) of size Z in
155 	 * them. The minimum SDU size required for this is X * Y * Z.
156 	 */
157 	min_sdu_size_required = chan_cnt * octets_per_frame * frames_blocks_per_sdu;
158 	if (min_sdu_size_required > stream->qos->sdu) {
159 		FAIL("With %zu channels and %u octets per frame and %u frames per block, SDUs "
160 		     "shall be at minimum %zu, but the stream has been configured for %u\n",
161 		     chan_cnt, octets_per_frame, frames_blocks_per_sdu, min_sdu_size_required,
162 		     stream->qos->sdu);
163 
164 		return;
165 	}
166 }
167 
stream_started_cb(struct bt_bap_stream * stream)168 static void stream_started_cb(struct bt_bap_stream *stream)
169 {
170 	struct audio_test_stream *test_stream = audio_test_stream_from_bap_stream(stream);
171 	struct bt_bap_ep_info info;
172 	int err;
173 
174 	test_stream->seq_num = 0U;
175 	test_stream->tx_cnt = 0U;
176 
177 	err = bt_bap_ep_get_info(stream->ep, &info);
178 	if (err != 0) {
179 		FAIL("Failed to get EP info: %d\n", err);
180 		return;
181 	}
182 
183 	if (info.state != BT_BAP_EP_STATE_STREAMING) {
184 		FAIL("Unexpected EP state: %d\n", info.state);
185 		return;
186 	}
187 
188 	if (info.dir != BT_AUDIO_DIR_SOURCE) {
189 		FAIL("Unexpected info.dir: %d\n", info.dir);
190 		return;
191 	}
192 
193 	if (!info.can_send) {
194 		FAIL("info.can_send is false\n");
195 		return;
196 	}
197 
198 	if (info.can_recv) {
199 		FAIL("info.can_recv is true\n");
200 		return;
201 	}
202 
203 	if (info.paired_ep != NULL) {
204 		FAIL("Unexpected info.paired_ep: %p\n", info.paired_ep);
205 		return;
206 	}
207 
208 	err = bap_stream_tx_register(stream);
209 	if (err != 0) {
210 		FAIL("Failed to register stream %p for TX: %d\n", stream, err);
211 		return;
212 	}
213 
214 	printk("Stream %p started\n", stream);
215 	validate_stream_codec_cfg(stream);
216 	k_sem_give(&sem_stream_started);
217 }
218 
steam_stopped_cb(struct bt_bap_stream * stream,uint8_t reason)219 static void steam_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
220 {
221 	int err;
222 
223 	printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
224 
225 	err = bap_stream_tx_unregister(stream);
226 	if (err != 0) {
227 		FAIL("Failed to unregister stream %p for TX: %d\n", stream, err);
228 		return;
229 	}
230 
231 	k_sem_give(&sem_stream_stopped);
232 }
233 
234 static struct bt_bap_stream_ops stream_ops = {
235 	.started = stream_started_cb,
236 	.stopped = steam_stopped_cb,
237 	.sent = bap_stream_tx_sent_cb,
238 };
239 
source_started_cb(struct bt_bap_broadcast_source * source)240 static void source_started_cb(struct bt_bap_broadcast_source *source)
241 {
242 	printk("Broadcast source %p started\n", source);
243 	SET_FLAG(flag_source_started);
244 }
245 
source_stopped_cb(struct bt_bap_broadcast_source * source,uint8_t reason)246 static void source_stopped_cb(struct bt_bap_broadcast_source *source, uint8_t reason)
247 {
248 	printk("Broadcast source %p stopped with reason 0x%02X\n", source, reason);
249 	UNSET_FLAG(flag_source_started);
250 }
251 
setup_broadcast_source(struct bt_bap_broadcast_source ** source,bool encryption)252 static int setup_broadcast_source(struct bt_bap_broadcast_source **source, bool encryption)
253 {
254 	struct bt_bap_broadcast_source_stream_param
255 		stream_params[ARRAY_SIZE(broadcast_source_streams)];
256 	struct bt_bap_broadcast_source_subgroup_param
257 		subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
258 	const unsigned long stream_cnt = subgroup_cnt_arg * streams_per_subgroup_cnt_arg;
259 	struct bt_bap_broadcast_source_param create_param;
260 	int err;
261 
262 	if (stream_cnt > ARRAY_SIZE(stream_params)) {
263 		printk("Unable to create broadcast source with %lu subgroups with %lu streams each "
264 		       "(%lu total)\n",
265 		       subgroup_cnt_arg, streams_per_subgroup_cnt_arg, stream_cnt);
266 		return -ENOMEM;
267 	}
268 
269 	(void)memset(broadcast_source_streams, 0,
270 		     sizeof(broadcast_source_streams));
271 
272 	for (size_t i = 0; i < stream_cnt; i++) {
273 		stream_params[i].stream =
274 			bap_stream_from_audio_test_stream(&broadcast_source_streams[i]);
275 		bt_bap_stream_cb_register(stream_params[i].stream,
276 					    &stream_ops);
277 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
278 		stream_params[i].data_len = ARRAY_SIZE(bis_codec_data);
279 		stream_params[i].data = bis_codec_data;
280 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
281 	}
282 
283 	for (size_t i = 0U; i < subgroup_cnt_arg; i++) {
284 		subgroup_params[i].params_count = streams_per_subgroup_cnt_arg;
285 		subgroup_params[i].params = &stream_params[i * streams_per_subgroup_cnt_arg];
286 		subgroup_params[i].codec_cfg = &preset_16_1_1.codec_cfg;
287 	}
288 
289 	create_param.params_count = subgroup_cnt_arg;
290 	create_param.params = subgroup_params;
291 	create_param.qos = &preset_16_2_1.qos;
292 	create_param.packing = BT_ISO_PACKING_SEQUENTIAL;
293 	create_param.encryption = encryption;
294 	if (encryption) {
295 		memcpy(create_param.broadcast_code, BROADCAST_CODE, sizeof(BROADCAST_CODE));
296 	}
297 
298 	printk("Creating broadcast source with %lu subgroups and %lu streams\n", subgroup_cnt_arg,
299 	       stream_cnt);
300 	err = bt_bap_broadcast_source_create(&create_param, source);
301 	if (err != 0) {
302 		printk("Unable to create broadcast source: %d\n", err);
303 		return err;
304 	}
305 
306 	for (size_t i = 0U; i < stream_cnt; i++) {
307 		struct audio_test_stream *test_stream = &broadcast_source_streams[i];
308 
309 		test_stream->tx_sdu_size = preset_16_1_1.qos.sdu;
310 	}
311 
312 	return 0;
313 }
314 
test_broadcast_source_get_base(struct bt_bap_broadcast_source * source,struct net_buf_simple * base_buf)315 static void test_broadcast_source_get_base(struct bt_bap_broadcast_source *source,
316 					   struct net_buf_simple *base_buf)
317 {
318 	int err;
319 
320 	err = bt_bap_broadcast_source_get_base(source, base_buf);
321 	if (err != 0) {
322 		FAIL("Failed to get encoded BASE: %d\n", err);
323 		return;
324 	}
325 }
326 
setup_extended_adv(struct bt_bap_broadcast_source * source,struct bt_le_ext_adv ** adv)327 static int setup_extended_adv(struct bt_bap_broadcast_source *source, struct bt_le_ext_adv **adv)
328 {
329 	/* Broadcast Audio Streaming Endpoint advertising data */
330 	NET_BUF_SIMPLE_DEFINE(ad_buf,
331 			      BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE);
332 	struct bt_le_adv_param adv_param = BT_LE_ADV_PARAM_INIT(
333 		BT_LE_ADV_OPT_EXT_ADV, 0x80, 0x80, NULL);
334 	NET_BUF_SIMPLE_DEFINE(base_buf, 128);
335 	struct bt_data ext_ad;
336 	struct bt_data per_ad;
337 	uint32_t broadcast_id;
338 	int err;
339 
340 	/* Create a non-connectable advertising set */
341 	err = bt_le_ext_adv_create(&adv_param, NULL, adv);
342 	if (err != 0) {
343 		printk("Unable to create extended advertising set: %d\n", err);
344 		return err;
345 	}
346 
347 	/* Set periodic advertising parameters */
348 	err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT);
349 	if (err) {
350 		printk("Failed to set periodic advertising parameters: %d\n",
351 		       err);
352 		return err;
353 	}
354 
355 	err = bt_rand(&broadcast_id, BT_AUDIO_BROADCAST_ID_SIZE);
356 	if (err) {
357 		printk("Unable to generate broadcast ID: %d\n", err);
358 		return err;
359 	}
360 
361 	/* Setup extended advertising data */
362 	net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL);
363 	net_buf_simple_add_le24(&ad_buf, broadcast_id);
364 	ext_ad.type = BT_DATA_SVC_DATA16;
365 	ext_ad.data_len = ad_buf.len;
366 	ext_ad.data = ad_buf.data;
367 	err = bt_le_ext_adv_set_data(*adv, &ext_ad, 1, NULL, 0);
368 	if (err != 0) {
369 		printk("Failed to set extended advertising data: %d\n", err);
370 		return err;
371 	}
372 
373 	/* Setup periodic advertising data */
374 	test_broadcast_source_get_base(source, &base_buf);
375 
376 	per_ad.type = BT_DATA_SVC_DATA16;
377 	per_ad.data_len = base_buf.len;
378 	per_ad.data = base_buf.data;
379 	err = bt_le_per_adv_set_data(*adv, &per_ad, 1);
380 	if (err != 0) {
381 		printk("Failed to set periodic advertising data: %d\n", err);
382 		return err;
383 	}
384 
385 	/* Start extended advertising */
386 	err = bt_le_ext_adv_start(*adv, BT_LE_EXT_ADV_START_DEFAULT);
387 	if (err) {
388 		printk("Failed to start extended advertising: %d\n", err);
389 		return err;
390 	}
391 
392 	/* Enable Periodic Advertising */
393 	err = bt_le_per_adv_start(*adv);
394 	if (err) {
395 		printk("Failed to enable periodic advertising: %d\n", err);
396 		return err;
397 	}
398 
399 	return 0;
400 }
401 
test_broadcast_source_reconfig(struct bt_bap_broadcast_source * source)402 static void test_broadcast_source_reconfig(struct bt_bap_broadcast_source *source)
403 {
404 	struct bt_bap_broadcast_source_stream_param
405 		stream_params[ARRAY_SIZE(broadcast_source_streams)];
406 	struct bt_bap_broadcast_source_subgroup_param
407 		subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
408 	const unsigned long stream_cnt = subgroup_cnt_arg * streams_per_subgroup_cnt_arg;
409 	struct bt_bap_broadcast_source_param reconfig_param;
410 	int err;
411 
412 	for (size_t i = 0; i < stream_cnt; i++) {
413 		stream_params[i].stream =
414 			bap_stream_from_audio_test_stream(&broadcast_source_streams[i]);
415 		stream_params[i].data_len = ARRAY_SIZE(bis_codec_data);
416 		stream_params[i].data = bis_codec_data;
417 	}
418 
419 	for (size_t i = 0U; i < subgroup_cnt_arg; i++) {
420 		subgroup_params[i].params_count = streams_per_subgroup_cnt_arg;
421 		subgroup_params[i].params = &stream_params[i * streams_per_subgroup_cnt_arg];
422 		subgroup_params[i].codec_cfg = &preset_16_1_1.codec_cfg;
423 	}
424 
425 	reconfig_param.params_count = subgroup_cnt_arg;
426 	reconfig_param.params = subgroup_params;
427 	reconfig_param.qos = &preset_16_1_1.qos;
428 	reconfig_param.packing = BT_ISO_PACKING_SEQUENTIAL;
429 	reconfig_param.encryption = false;
430 
431 	printk("Reconfiguring broadcast source\n");
432 	err = bt_bap_broadcast_source_reconfig(source, &reconfig_param);
433 	if (err != 0) {
434 		FAIL("Unable to reconfigure broadcast source: %d\n", err);
435 		return;
436 	}
437 
438 	for (size_t i = 0U; i < stream_cnt; i++) {
439 		struct audio_test_stream *test_stream = &broadcast_source_streams[i];
440 
441 		test_stream->tx_sdu_size = preset_16_1_1.qos.sdu;
442 	}
443 }
444 
test_broadcast_source_start(struct bt_bap_broadcast_source * source,struct bt_le_ext_adv * adv)445 static void test_broadcast_source_start(struct bt_bap_broadcast_source *source,
446 					struct bt_le_ext_adv *adv)
447 {
448 	const unsigned long stream_cnt = subgroup_cnt_arg * streams_per_subgroup_cnt_arg;
449 	int err;
450 
451 	printk("Starting broadcast source\n");
452 	err = bt_bap_broadcast_source_start(source, adv);
453 	if (err != 0) {
454 		FAIL("Unable to start broadcast source: %d\n", err);
455 		return;
456 	}
457 
458 	/* Wait for all to be started */
459 	printk("Waiting for %lu streams to be started\n", stream_cnt);
460 	for (size_t i = 0U; i < stream_cnt; i++) {
461 		k_sem_take(&sem_stream_started, K_FOREVER);
462 	}
463 
464 	WAIT_FOR_FLAG(flag_source_started);
465 }
466 
test_broadcast_source_update_metadata(struct bt_bap_broadcast_source * source,struct bt_le_ext_adv * adv)467 static void test_broadcast_source_update_metadata(struct bt_bap_broadcast_source *source,
468 						  struct bt_le_ext_adv *adv)
469 {
470 	uint8_t new_metadata[] = BT_AUDIO_CODEC_CFG_LC3_META(BT_AUDIO_CONTEXT_TYPE_ALERTS);
471 	struct bt_data per_ad;
472 	int err;
473 
474 	NET_BUF_SIMPLE_DEFINE(base_buf, 128);
475 
476 	printk("Updating metadata\n");
477 	err = bt_bap_broadcast_source_update_metadata(source, new_metadata,
478 						      ARRAY_SIZE(new_metadata));
479 	if (err != 0) {
480 		FAIL("Failed to update metadata broadcast source: %d\n", err);
481 		return;
482 	}
483 
484 	/* Get the new BASE */
485 	test_broadcast_source_get_base(source, &base_buf);
486 
487 	/* Update the periodic advertising data with the new BASE */
488 	per_ad.type = BT_DATA_SVC_DATA16;
489 	per_ad.data_len = base_buf.len;
490 	per_ad.data = base_buf.data;
491 	err = bt_le_per_adv_set_data(adv, &per_ad, 1);
492 	if (err != 0) {
493 		FAIL("Failed to set periodic advertising data: %d\n", err);
494 	}
495 }
496 
test_broadcast_source_stop(struct bt_bap_broadcast_source * source)497 static void test_broadcast_source_stop(struct bt_bap_broadcast_source *source)
498 {
499 	const unsigned long stream_cnt = subgroup_cnt_arg * streams_per_subgroup_cnt_arg;
500 	int err;
501 
502 	printk("Stopping broadcast source\n");
503 
504 	err = bt_bap_broadcast_source_stop(source);
505 	if (err != 0) {
506 		FAIL("Unable to stop broadcast source: %d\n", err);
507 		return;
508 	}
509 
510 	/* Wait for all to be stopped */
511 	printk("Waiting for %lu streams to be stopped\n", stream_cnt);
512 	for (size_t i = 0U; i < stream_cnt; i++) {
513 		k_sem_take(&sem_stream_stopped, K_FOREVER);
514 	}
515 
516 	WAIT_FOR_UNSET_FLAG(flag_source_started);
517 }
518 
test_broadcast_source_delete(struct bt_bap_broadcast_source * source)519 static void test_broadcast_source_delete(struct bt_bap_broadcast_source *source)
520 {
521 	int err;
522 
523 	printk("Deleting broadcast source\n");
524 
525 	err = bt_bap_broadcast_source_delete(source);
526 	if (err != 0) {
527 		FAIL("Unable to stop broadcast source: %d\n", err);
528 		return;
529 	}
530 }
531 
stop_extended_adv(struct bt_le_ext_adv * adv)532 static int stop_extended_adv(struct bt_le_ext_adv *adv)
533 {
534 	int err;
535 
536 	err = bt_le_per_adv_stop(adv);
537 	if (err) {
538 		printk("Failed to stop periodic advertising: %d\n", err);
539 		return err;
540 	}
541 
542 	err = bt_le_ext_adv_stop(adv);
543 	if (err) {
544 		printk("Failed to stop extended advertising: %d\n", err);
545 		return err;
546 	}
547 
548 	err = bt_le_ext_adv_delete(adv);
549 	if (err) {
550 		printk("Failed to delete extended advertising: %d\n", err);
551 		return err;
552 	}
553 
554 	return 0;
555 }
556 
init(void)557 static void init(void)
558 {
559 	static struct bt_bap_broadcast_source_cb broadcast_source_cb = {
560 		.started = source_started_cb,
561 		.stopped = source_stopped_cb,
562 	};
563 	int err;
564 
565 	err = bt_enable(NULL);
566 	if (err) {
567 		FAIL("Bluetooth init failed (err %d)\n", err);
568 		return;
569 	}
570 
571 	printk("Bluetooth initialized\n");
572 	bap_stream_tx_init();
573 
574 	err = bt_bap_broadcast_source_register_cb(&broadcast_source_cb);
575 	if (err != 0) {
576 		FAIL("Failed to register broadcast source callbacks (err %d)\n", err);
577 		return;
578 	}
579 }
580 
test_main(void)581 static void test_main(void)
582 {
583 	struct bt_bap_broadcast_source *source;
584 	struct bt_le_ext_adv *adv;
585 	int err;
586 
587 	init();
588 
589 	err = setup_broadcast_source(&source, false);
590 	if (err != 0) {
591 		FAIL("Unable to setup broadcast source: %d\n", err);
592 		return;
593 	}
594 
595 	err = setup_extended_adv(source, &adv);
596 	if (err != 0) {
597 		FAIL("Failed to setup extended advertising: %d\n", err);
598 		return;
599 	}
600 
601 	test_broadcast_source_reconfig(source);
602 
603 	test_broadcast_source_start(source, adv);
604 
605 	/* Wait for other devices to have received what they wanted */
606 	backchannel_sync_wait_any();
607 
608 	/* Update metadata while streaming */
609 	test_broadcast_source_update_metadata(source, adv);
610 
611 	/* Wait for other devices to have received what they wanted */
612 	backchannel_sync_wait_any();
613 
614 	/* Wait for other devices to let us know when we can stop the source */
615 	backchannel_sync_wait_any();
616 
617 	test_broadcast_source_stop(source);
618 
619 	test_broadcast_source_delete(source);
620 	source = NULL;
621 
622 	err = stop_extended_adv(adv);
623 	if (err != 0) {
624 		FAIL("Unable to stop extended advertising: %d\n", err);
625 		return;
626 	}
627 	adv = NULL;
628 
629 	/* Recreate broadcast source to verify that it's possible */
630 	printk("Recreating broadcast source\n");
631 	err = setup_broadcast_source(&source, false);
632 	if (err != 0) {
633 		FAIL("Unable to setup broadcast source: %d\n", err);
634 		return;
635 	}
636 
637 	printk("Deleting broadcast source\n");
638 	test_broadcast_source_delete(source);
639 	source = NULL;
640 
641 	PASS("Broadcast source passed\n");
642 }
643 
test_main_encrypted(void)644 static void test_main_encrypted(void)
645 {
646 	struct bt_bap_broadcast_source *source;
647 	struct bt_le_ext_adv *adv;
648 	int err;
649 
650 	init();
651 
652 	err = setup_broadcast_source(&source, true);
653 	if (err != 0) {
654 		FAIL("Unable to setup broadcast source: %d\n", err);
655 		return;
656 	}
657 
658 	err = setup_extended_adv(source, &adv);
659 	if (err != 0) {
660 		FAIL("Failed to setup extended advertising: %d\n", err);
661 		return;
662 	}
663 
664 	test_broadcast_source_start(source, adv);
665 
666 	/* Wait for other devices to have received data */
667 	backchannel_sync_wait_any();
668 
669 	/* Wait for other devices to let us know when we can stop the source */
670 	backchannel_sync_wait_any();
671 
672 	test_broadcast_source_stop(source);
673 
674 	test_broadcast_source_delete(source);
675 	source = NULL;
676 
677 	err = stop_extended_adv(adv);
678 	if (err != 0) {
679 		FAIL("Unable to stop extended advertising: %d\n", err);
680 		return;
681 	}
682 	adv = NULL;
683 
684 	PASS("Broadcast source encrypted passed\n");
685 }
686 
test_args(int argc,char * argv[])687 static void test_args(int argc, char *argv[])
688 {
689 	for (size_t argn = 0; argn < argc; argn++) {
690 		const char *arg = argv[argn];
691 
692 		if (strcmp(arg, "subgroup_cnt") == 0) {
693 			arg = argv[++argn];
694 			subgroup_cnt_arg = strtoul(arg, NULL, 10);
695 
696 			if (!IN_RANGE(subgroup_cnt_arg, 1,
697 				      CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT)) {
698 				FAIL("Invalid number of subgroups: %lu\n", subgroup_cnt_arg);
699 			}
700 		} else if (strcmp(arg, "streams_per_subgroup_cnt") == 0) {
701 			arg = argv[++argn];
702 			streams_per_subgroup_cnt_arg = strtoul(arg, NULL, 10);
703 
704 			if (!IN_RANGE(streams_per_subgroup_cnt_arg, 1,
705 				      CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT)) {
706 				FAIL("Invalid number of streams per subgroup: %lu\n",
707 				     streams_per_subgroup_cnt_arg);
708 			}
709 		} else {
710 			FAIL("Invalid arg: %s\n", arg);
711 		}
712 	}
713 }
714 
715 static const struct bst_test_instance test_broadcast_source[] = {
716 	{
717 		.test_id = "broadcast_source",
718 		.test_pre_init_f = test_init,
719 		.test_tick_f = test_tick,
720 		.test_main_f = test_main,
721 		.test_args_f = test_args,
722 	},
723 	{
724 		.test_id = "broadcast_source_encrypted",
725 		.test_pre_init_f = test_init,
726 		.test_tick_f = test_tick,
727 		.test_main_f = test_main_encrypted,
728 		.test_args_f = test_args,
729 	},
730 	BSTEST_END_MARKER,
731 };
732 
test_broadcast_source_install(struct bst_test_list * tests)733 struct bst_test_list *test_broadcast_source_install(struct bst_test_list *tests)
734 {
735 	return bst_add_tests(tests, test_broadcast_source);
736 }
737 
738 #else /* CONFIG_BT_BAP_BROADCAST_SOURCE */
739 
test_broadcast_source_install(struct bst_test_list * tests)740 struct bst_test_list *test_broadcast_source_install(struct bst_test_list *tests)
741 {
742 	return tests;
743 }
744 
745 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
746