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