1 /*
2 * Copyright (c) 2021-2025 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h>
11
12 #include <zephyr/autoconf.h>
13 #include <zephyr/bluetooth/addr.h>
14 #include <zephyr/bluetooth/audio/audio.h>
15 #include <zephyr/bluetooth/audio/bap.h>
16 #include <zephyr/bluetooth/bluetooth.h>
17 #include <zephyr/bluetooth/byteorder.h>
18 #include <zephyr/bluetooth/gap.h>
19 #include <zephyr/bluetooth/iso.h>
20 #include <zephyr/bluetooth/uuid.h>
21 #include <zephyr/kernel.h>
22 #include <zephyr/net_buf.h>
23 #include <zephyr/sys/byteorder.h>
24 #include <zephyr/sys/printk.h>
25 #include <zephyr/sys/util.h>
26 #include <zephyr/sys/util_macro.h>
27
28 #include "bstests.h"
29 #include "common.h"
30
31 #ifdef CONFIG_BT_BAP_SCAN_DELEGATOR
32 extern enum bst_result_t bst_result;
33
34 #define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 20 /* Set the timeout relative to interval */
35 #define PA_SYNC_SKIP 5
36
37 CREATE_FLAG(flag_pa_synced);
38 CREATE_FLAG(flag_pa_terminated);
39 CREATE_FLAG(flag_broadcast_code_received);
40 CREATE_FLAG(flag_recv_state_updated);
41 CREATE_FLAG(flag_bis_sync_requested);
42 CREATE_FLAG(flag_bis_sync_term_requested);
43 static volatile uint32_t g_broadcast_id;
44
45 struct sync_state {
46 uint8_t src_id;
47 const struct bt_bap_scan_delegator_recv_state *recv_state;
48 bool pa_syncing;
49 struct k_work_delayable pa_timer;
50 struct bt_le_per_adv_sync *pa_sync;
51 uint8_t broadcast_code[BT_ISO_BROADCAST_CODE_SIZE];
52 uint32_t bis_sync_req[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS];
53 } sync_states[CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT];
54
sync_state_get(const struct bt_bap_scan_delegator_recv_state * recv_state)55 static struct sync_state *sync_state_get(const struct bt_bap_scan_delegator_recv_state *recv_state)
56 {
57 for (size_t i = 0U; i < ARRAY_SIZE(sync_states); i++) {
58 if (sync_states[i].recv_state == recv_state) {
59 return &sync_states[i];
60 }
61 }
62
63 return NULL;
64 }
65
sync_state_get_or_new(const struct bt_bap_scan_delegator_recv_state * recv_state)66 static struct sync_state *sync_state_get_or_new(
67 const struct bt_bap_scan_delegator_recv_state *recv_state)
68 {
69 struct sync_state *free_state = NULL;
70
71 for (size_t i = 0U; i < ARRAY_SIZE(sync_states); i++) {
72 if (sync_states[i].recv_state == NULL &&
73 free_state == NULL) {
74 free_state = &sync_states[i];
75
76 if (recv_state == NULL) {
77 return free_state;
78 }
79 }
80
81 if (sync_states[i].recv_state == recv_state) {
82 return &sync_states[i];
83 }
84 }
85
86 return free_state;
87 }
88
sync_state_get_by_pa(struct bt_le_per_adv_sync * sync)89 static struct sync_state *sync_state_get_by_pa(struct bt_le_per_adv_sync *sync)
90 {
91 for (size_t i = 0U; i < ARRAY_SIZE(sync_states); i++) {
92 if (sync_states[i].pa_sync == sync) {
93 return &sync_states[i];
94 }
95 }
96
97 return NULL;
98 }
99
sync_state_get_by_src_id(uint8_t src_id)100 static struct sync_state *sync_state_get_by_src_id(uint8_t src_id)
101 {
102 for (size_t i = 0U; i < ARRAY_SIZE(sync_states); i++) {
103 if (sync_states[i].src_id == src_id) {
104 return &sync_states[i];
105 }
106 }
107
108 return NULL;
109 }
110
pa_timer_handler(struct k_work * work)111 static void pa_timer_handler(struct k_work *work)
112 {
113 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
114 struct sync_state *state = CONTAINER_OF(dwork, struct sync_state, pa_timer);
115
116 state->pa_syncing = false;
117
118 if (state->recv_state != NULL) {
119 enum bt_bap_pa_state pa_state;
120
121 if (state->recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) {
122 pa_state = BT_BAP_PA_STATE_NO_PAST;
123 } else {
124 pa_state = BT_BAP_PA_STATE_FAILED;
125 }
126
127 bt_bap_scan_delegator_set_pa_state(state->recv_state->src_id,
128 pa_state);
129 }
130
131 FAIL("PA timeout\n");
132 }
133
pa_sync_past(struct bt_conn * conn,struct sync_state * state,uint16_t pa_interval)134 static int pa_sync_past(struct bt_conn *conn,
135 struct sync_state *state,
136 uint16_t pa_interval)
137 {
138 struct bt_le_per_adv_sync_transfer_param param = { 0 };
139 int err;
140
141 param.options = BT_LE_PER_ADV_SYNC_TRANSFER_OPT_FILTER_DUPLICATES;
142 param.skip = PA_SYNC_SKIP;
143 param.timeout = interval_to_sync_timeout(pa_interval);
144
145 err = bt_le_per_adv_sync_transfer_subscribe(conn, ¶m);
146 if (err != 0) {
147 printk("Could not do PAST subscribe: %d\n", err);
148 } else {
149 printk("Syncing with PAST: %d\n", err);
150 state->pa_syncing = true;
151 k_work_init_delayable(&state->pa_timer, pa_timer_handler);
152 (void)k_work_reschedule(&state->pa_timer,
153 K_MSEC(param.timeout * 10));
154 }
155
156 return err;
157 }
158
pa_sync_no_past(struct sync_state * state,uint16_t pa_interval)159 static int pa_sync_no_past(struct sync_state *state,
160 uint16_t pa_interval)
161 {
162 const struct bt_bap_scan_delegator_recv_state *recv_state;
163 struct bt_le_per_adv_sync_param param = { 0 };
164 int err;
165
166 recv_state = state->recv_state;
167 state->src_id = recv_state->src_id;
168
169 bt_addr_le_copy(¶m.addr, &recv_state->addr);
170 param.sid = recv_state->adv_sid;
171 param.skip = PA_SYNC_SKIP;
172 param.timeout = interval_to_sync_timeout(pa_interval);
173
174 /* TODO: Validate that the advertise is broadcasting the same
175 * broadcast_id that the receive state has
176 */
177 err = bt_le_per_adv_sync_create(¶m, &state->pa_sync);
178 if (err != 0) {
179 printk("Could not sync per adv: %d\n", err);
180 } else {
181 char addr_str[BT_ADDR_LE_STR_LEN];
182
183 bt_addr_le_to_str(&recv_state->addr, addr_str, sizeof(addr_str));
184 printk("PA sync pending for addr %s\n", addr_str);
185 state->pa_syncing = true;
186 k_work_init_delayable(&state->pa_timer, pa_timer_handler);
187 (void)k_work_reschedule(&state->pa_timer,
188 K_MSEC(param.timeout * 10));
189 }
190
191 return err;
192 }
193
pa_sync_term(struct sync_state * state)194 static int pa_sync_term(struct sync_state *state)
195 {
196 int err;
197
198 (void)k_work_cancel_delayable(&state->pa_timer);
199
200 if (state->pa_sync == NULL) {
201 return -1;
202 }
203
204 printk("Deleting PA sync\n");
205
206 err = bt_le_per_adv_sync_delete(state->pa_sync);
207 if (err != 0) {
208 FAIL("Could not delete per adv sync: %d\n", err);
209 } else {
210 state->pa_syncing = false;
211 state->pa_sync = NULL;
212 }
213
214 return err;
215 }
216
recv_state_updated_cb(struct bt_conn * conn,const struct bt_bap_scan_delegator_recv_state * recv_state)217 static void recv_state_updated_cb(struct bt_conn *conn,
218 const struct bt_bap_scan_delegator_recv_state *recv_state)
219 {
220 struct sync_state *state;
221
222 printk("Receive state with ID %u updated\n", recv_state->src_id);
223
224 state = sync_state_get_by_src_id(recv_state->src_id);
225 if (state == NULL) {
226 FAIL("Could not get state");
227 return;
228 }
229
230 if (state->recv_state != NULL) {
231 if (state->recv_state != recv_state) {
232 FAIL("Sync state receive state mismatch: %p - %p",
233 state->recv_state, recv_state);
234 return;
235 }
236 } else {
237 state->recv_state = recv_state;
238 }
239
240 SET_FLAG(flag_recv_state_updated);
241 }
242
pa_sync_req_cb(struct bt_conn * conn,const struct bt_bap_scan_delegator_recv_state * recv_state,bool past_avail,uint16_t pa_interval)243 static int pa_sync_req_cb(struct bt_conn *conn,
244 const struct bt_bap_scan_delegator_recv_state *recv_state,
245 bool past_avail, uint16_t pa_interval)
246 {
247 struct sync_state *state;
248 int err;
249
250 printk("PA Sync request: past_avail %u, pa_interval 0x%04x\n: %p",
251 past_avail, pa_interval, recv_state);
252
253 state = sync_state_get_or_new(recv_state);
254 if (state == NULL) {
255 FAIL("Could not get state");
256 return -1;
257 }
258
259 state->recv_state = recv_state;
260 state->src_id = recv_state->src_id;
261
262 if (recv_state->pa_sync_state == BT_BAP_PA_STATE_SYNCED ||
263 recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) {
264 /* Already syncing */
265 /* TODO: Terminate existing sync and then sync to new?*/
266 return -1;
267 }
268
269 if (past_avail) {
270 err = pa_sync_past(conn, state, pa_interval);
271 if (err == 0) {
272 err = bt_bap_scan_delegator_set_pa_state(state->recv_state->src_id,
273 BT_BAP_PA_STATE_INFO_REQ);
274 if (err != 0) {
275 printk("Failed to set INFO_REQ state: %d", err);
276 }
277 }
278 } else {
279 err = pa_sync_no_past(state, pa_interval);
280 }
281
282 return err;
283 }
284
pa_sync_term_req_cb(struct bt_conn * conn,const struct bt_bap_scan_delegator_recv_state * recv_state)285 static int pa_sync_term_req_cb(struct bt_conn *conn,
286 const struct bt_bap_scan_delegator_recv_state *recv_state)
287 {
288 struct sync_state *state;
289
290 printk("PA Sync term request for %p\n", recv_state);
291
292 state = sync_state_get(recv_state);
293 if (state == NULL) {
294 FAIL("Could not get state\n");
295 return -1;
296 }
297
298 return pa_sync_term(state);
299 }
300
broadcast_code_cb(struct bt_conn * conn,const struct bt_bap_scan_delegator_recv_state * recv_state,const uint8_t broadcast_code[BT_ISO_BROADCAST_CODE_SIZE])301 static void broadcast_code_cb(struct bt_conn *conn,
302 const struct bt_bap_scan_delegator_recv_state *recv_state,
303 const uint8_t broadcast_code[BT_ISO_BROADCAST_CODE_SIZE])
304 {
305 struct sync_state *state;
306
307 printk("Broadcast code received for %p\n", recv_state);
308
309 state = sync_state_get(recv_state);
310 if (state == NULL) {
311 FAIL("Could not get state\n");
312 return;
313 }
314
315 (void)memcpy(state->broadcast_code, broadcast_code, BT_ISO_BROADCAST_CODE_SIZE);
316
317 SET_FLAG(flag_broadcast_code_received);
318 }
319
bis_sync_req_cb(struct bt_conn * conn,const struct bt_bap_scan_delegator_recv_state * recv_state,const uint32_t bis_sync_req[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS])320 static int bis_sync_req_cb(struct bt_conn *conn,
321 const struct bt_bap_scan_delegator_recv_state *recv_state,
322 const uint32_t bis_sync_req[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS])
323 {
324 struct sync_state *state;
325 bool sync_bis;
326
327 printk("BIS sync request received for %p\n", recv_state);
328 for (int i = 0; i < CONFIG_BT_BAP_BASS_MAX_SUBGROUPS; i++) {
329 if (bis_sync_req[i]) {
330 sync_bis = true;
331 }
332
333 printk(" [%d]: 0x%08x\n", i, bis_sync_req[i]);
334 }
335
336 state = sync_state_get(recv_state);
337 if (state == NULL) {
338 FAIL("Could not get state\n");
339 return -1;
340 }
341
342 (void)memcpy(state->bis_sync_req, bis_sync_req,
343 sizeof(state->bis_sync_req));
344
345 if (sync_bis) {
346 SET_FLAG(flag_bis_sync_requested);
347 } else {
348 SET_FLAG(flag_bis_sync_term_requested);
349 }
350
351 return 0;
352 }
353
354 static struct bt_bap_scan_delegator_cb scan_delegator_cb = {
355 .recv_state_updated = recv_state_updated_cb,
356 .pa_sync_req = pa_sync_req_cb,
357 .pa_sync_term_req = pa_sync_term_req_cb,
358 .broadcast_code = broadcast_code_cb,
359 .bis_sync_req = bis_sync_req_cb,
360 };
361
pa_synced_cb(struct bt_le_per_adv_sync * sync,struct bt_le_per_adv_sync_synced_info * info)362 static void pa_synced_cb(struct bt_le_per_adv_sync *sync,
363 struct bt_le_per_adv_sync_synced_info *info)
364 {
365 struct sync_state *state;
366
367 printk("PA %p synced\n", sync);
368
369 if (info->conn) { /* if from PAST */
370 for (size_t i = 0U; i < ARRAY_SIZE(sync_states); i++) {
371 if (!sync_states[i].pa_sync) {
372 sync_states[i].pa_sync = sync;
373 }
374 }
375 }
376
377 state = sync_state_get_by_pa(sync);
378 if (state == NULL) {
379 FAIL("Could not get sync state from PA sync %p\n", sync);
380 return;
381 }
382
383 k_work_cancel_delayable(&state->pa_timer);
384
385 SET_FLAG(flag_pa_synced);
386 }
387
pa_term_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_term_info * info)388 static void pa_term_cb(struct bt_le_per_adv_sync *sync,
389 const struct bt_le_per_adv_sync_term_info *info)
390 {
391 struct sync_state *state;
392
393 printk("PA %p sync terminated\n", sync);
394
395 state = sync_state_get_by_pa(sync);
396 if (state == NULL) {
397 FAIL("Could not get sync state from PA sync %p\n", sync);
398 return;
399 }
400
401 k_work_cancel_delayable(&state->pa_timer);
402
403 SET_FLAG(flag_pa_terminated);
404 }
405
406 static struct bt_le_per_adv_sync_cb pa_sync_cb = {
407 .synced = pa_synced_cb,
408 .term = pa_term_cb,
409 };
410
broadcast_source_found(struct bt_data * data,void * user_data)411 static bool broadcast_source_found(struct bt_data *data, void *user_data)
412 {
413 struct bt_le_per_adv_sync_param sync_create_param = { 0 };
414 const struct bt_le_scan_recv_info *info = user_data;
415 char addr_str[BT_ADDR_LE_STR_LEN];
416 struct bt_uuid_16 adv_uuid;
417 struct sync_state *state;
418 int err;
419
420
421 if (data->type != BT_DATA_SVC_DATA16) {
422 return true;
423 }
424
425 if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) {
426 return true;
427 }
428
429 if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) {
430 return true;
431 }
432
433 if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO) != 0) {
434 return true;
435 }
436
437 g_broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16);
438 bt_addr_le_to_str(info->addr, addr_str, sizeof(addr_str));
439
440 printk("Found BAP broadcast source with address %s and ID 0x%06X\n",
441 addr_str, g_broadcast_id);
442
443 state = sync_state_get_or_new(NULL);
444 if (state == NULL) {
445 FAIL("Failed to get sync state");
446 return true;
447 }
448
449 printk("Creating Periodic Advertising Sync\n");
450 bt_addr_le_copy(&sync_create_param.addr, info->addr);
451 sync_create_param.sid = info->sid;
452 sync_create_param.timeout = 0xa;
453
454 err = bt_le_per_adv_sync_create(&sync_create_param,
455 &state->pa_sync);
456 if (err != 0) {
457 FAIL("Could not create PA sync (err %d)\n", err);
458 return true;
459 }
460
461 state->pa_syncing = true;
462
463 return false;
464 }
465
scan_recv_cb(const struct bt_le_scan_recv_info * info,struct net_buf_simple * ad)466 static void scan_recv_cb(const struct bt_le_scan_recv_info *info,
467 struct net_buf_simple *ad)
468 {
469 /* We are only interested in non-connectable periodic advertisers */
470 if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0 ||
471 info->interval == 0) {
472 return;
473 }
474
475 bt_data_parse(ad, broadcast_source_found, (void *)info);
476 }
477
478 static struct bt_le_scan_cb scan_cb = {
479 .recv = scan_recv_cb
480 };
481
add_source(struct sync_state * state)482 static int add_source(struct sync_state *state)
483 {
484 struct bt_bap_scan_delegator_add_src_param param;
485 struct bt_le_per_adv_sync_info sync_info;
486 int res;
487
488 UNSET_FLAG(flag_recv_state_updated);
489
490 res = bt_le_per_adv_sync_get_info(state->pa_sync, &sync_info);
491 if (res != 0) {
492 FAIL("Failed to get PA sync info: %d)\n", res);
493 return true;
494 }
495
496 bt_addr_le_copy(¶m.addr, &sync_info.addr);
497 param.sid = sync_info.sid;
498 param.encrypt_state = BT_BAP_BIG_ENC_STATE_NO_ENC;
499 param.broadcast_id = g_broadcast_id;
500 param.num_subgroups = 1U;
501
502 for (uint8_t i = 0U; i < param.num_subgroups; i++) {
503 struct bt_bap_bass_subgroup *subgroup_param = ¶m.subgroups[i];
504
505 subgroup_param->bis_sync = BT_BAP_BIS_SYNC_NO_PREF;
506 subgroup_param->metadata_len = 0U;
507 (void)memset(subgroup_param->metadata, 0, sizeof(subgroup_param->metadata));
508 }
509
510 res = bt_bap_scan_delegator_add_src(¶m);
511 if (res < 0) {
512 return res;
513 }
514
515 state->src_id = (uint8_t)res;
516
517 WAIT_FOR_FLAG(flag_recv_state_updated);
518
519 return res;
520 }
521
add_all_sources(void)522 static void add_all_sources(void)
523 {
524 for (size_t i = 0U; i < ARRAY_SIZE(sync_states); i++) {
525 struct sync_state *state = &sync_states[i];
526
527 if (state->pa_sync != NULL) {
528 int res;
529
530 printk("[%zu]: Adding source\n", i);
531
532 res = add_source(state);
533 if (res < 0) {
534 FAIL("[%zu]: Add source failed (err %d)\n", i, res);
535 return;
536 }
537
538 printk("[%zu]: Source added with id %u\n",
539 i, state->src_id);
540 }
541 }
542 }
543
mod_source(struct sync_state * state)544 static int mod_source(struct sync_state *state)
545 {
546 const uint16_t pref_context = BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL;
547 struct bt_bap_scan_delegator_mod_src_param param;
548 const uint8_t pref_context_metadata[] = {
549 BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT,
550 BT_BYTES_LIST_LE16(pref_context)),
551 };
552 int err;
553
554 UNSET_FLAG(flag_recv_state_updated);
555
556 param.src_id = state->src_id;
557 param.encrypt_state = BT_BAP_BIG_ENC_STATE_NO_ENC;
558 param.broadcast_id = g_broadcast_id;
559 param.num_subgroups = 1U;
560
561 for (uint8_t i = 0U; i < param.num_subgroups; i++) {
562 struct bt_bap_bass_subgroup *subgroup_param = ¶m.subgroups[i];
563
564 subgroup_param->bis_sync = 0U;
565 subgroup_param->metadata_len = sizeof(pref_context_metadata);
566 (void)memcpy(subgroup_param->metadata, pref_context_metadata,
567 subgroup_param->metadata_len);
568 }
569
570 err = bt_bap_scan_delegator_mod_src(¶m);
571 if (err < 0) {
572 return err;
573 }
574
575 WAIT_FOR_FLAG(flag_recv_state_updated);
576
577 return 0;
578 }
579
mod_all_sources(void)580 static void mod_all_sources(void)
581 {
582 for (size_t i = 0U; i < ARRAY_SIZE(sync_states); i++) {
583 struct sync_state *state = &sync_states[i];
584
585 if (state->pa_sync != NULL) {
586 int err;
587
588 printk("[%zu]: Modifying source\n", i);
589
590 err = mod_source(state);
591 if (err < 0) {
592 FAIL("[%zu]: Modify source failed (err %d)\n", i, err);
593 return;
594 }
595
596 printk("[%zu]: Source id modifed %u\n",
597 i, state->src_id);
598 }
599 }
600 }
601
remove_source(struct sync_state * state)602 static int remove_source(struct sync_state *state)
603 {
604 int err;
605
606 UNSET_FLAG(flag_recv_state_updated);
607
608 /* We don't actually need to sync to the BIG/BISes */
609 err = bt_bap_scan_delegator_rem_src(state->src_id);
610 if (err) {
611 return err;
612 }
613
614 WAIT_FOR_FLAG(flag_recv_state_updated);
615
616 return 0;
617 }
618
remove_all_sources(void)619 static void remove_all_sources(void)
620 {
621 for (size_t i = 0U; i < ARRAY_SIZE(sync_states); i++) {
622 struct sync_state *state = &sync_states[i];
623
624 if (state->recv_state != NULL) {
625 int err;
626
627 printk("[%zu]: Removing source\n", i);
628
629 err = remove_source(state);
630 if (err) {
631 FAIL("[%zu]: Remove source failed (err %d)\n", err);
632 return;
633 }
634
635 printk("[%zu]: Source removed with id %u\n",
636 i, state->src_id);
637
638 printk("Terminating PA sync\n");
639 err = pa_sync_term(state);
640 if (err) {
641 FAIL("[%zu]: PA sync term failed (err %d)\n", err);
642 return;
643 }
644 }
645 }
646 }
647
sync_broadcast(struct sync_state * state)648 static int sync_broadcast(struct sync_state *state)
649 {
650 int err;
651
652 UNSET_FLAG(flag_recv_state_updated);
653
654 if (!TEST_FLAG(flag_bis_sync_requested)) {
655 /* If we have not received a sync request, set a value ourselves */
656 for (size_t i = 0U; i < ARRAY_SIZE(state->bis_sync_req); i++) {
657 state->bis_sync_req[i] = BIT(i);
658 }
659 }
660
661 /* We don't actually need to sync to the BIG/BISes */
662 err = bt_bap_scan_delegator_set_bis_sync_state(state->src_id, state->bis_sync_req);
663 if (err) {
664 return err;
665 }
666
667 WAIT_FOR_FLAG(flag_recv_state_updated);
668
669 return 0;
670 }
671
sync_all_broadcasts(void)672 static void sync_all_broadcasts(void)
673 {
674 for (size_t i = 0U; i < ARRAY_SIZE(sync_states); i++) {
675 struct sync_state *state = &sync_states[i];
676
677 if (state->pa_sync != NULL) {
678 int res;
679
680 printk("[%zu]: Setting broadcast sync state\n", i);
681
682 res = sync_broadcast(state);
683 if (res < 0) {
684 FAIL("[%zu]: Broadcast sync state set failed (err %d)\n", i, res);
685 return;
686 }
687
688 printk("[%zu]: Broadcast sync state set\n", i);
689 }
690 }
691 }
692
common_init(void)693 static int common_init(void)
694 {
695 struct bt_le_ext_adv *ext_adv;
696 int err;
697
698 err = bt_enable(NULL);
699 if (err) {
700 FAIL("Bluetooth init failed (err %d)\n", err);
701 return err;
702 }
703
704 printk("Bluetooth initialized\n");
705
706 err = bt_bap_scan_delegator_register(&scan_delegator_cb);
707 if (err) {
708 FAIL("Scan delegator register failed (err %d)\n", err);
709 return err;
710 }
711
712 bt_le_per_adv_sync_cb_register(&pa_sync_cb);
713
714 setup_connectable_adv(&ext_adv);
715
716 WAIT_FOR_FLAG(flag_connected);
717
718 return 0;
719 }
720
test_main_client_sync(void)721 static void test_main_client_sync(void)
722 {
723 int err;
724
725 err = common_init();
726 if (err) {
727 FAIL("common init failed (err %d)\n", err);
728 return;
729 }
730
731 /* Wait for broadcast assistant to request us to sync to PA */
732 printk("Waiting for flag_pa_synced\n");
733 WAIT_FOR_FLAG(flag_pa_synced);
734
735 /* Mod all sources by modifying the metadata */
736 mod_all_sources();
737
738 /* Wait for broadcast assistant to tell us to BIS sync */
739 printk("Waiting for flag_bis_sync_requested\n");
740 WAIT_FOR_FLAG(flag_bis_sync_requested);
741
742 /* Set the BIS sync state */
743 sync_all_broadcasts();
744
745 /* Wait for broadcast assistant to send us broadcast code */
746 printk("Waiting for flag_broadcast_code_received\n");
747 WAIT_FOR_FLAG(flag_broadcast_code_received);
748
749 /* Wait for broadcast assistant to remove source and terminate PA sync */
750 printk("Waiting for flag_pa_terminated\n");
751 WAIT_FOR_FLAG(flag_pa_terminated);
752
753 PASS("BAP Scan Delegator Client Sync passed\n");
754 }
755
test_main_server_sync_client_rem(void)756 static void test_main_server_sync_client_rem(void)
757 {
758 int err;
759
760 err = common_init();
761 if (err) {
762 FAIL("common init failed (err %d)\n", err);
763 return;
764 }
765
766 bt_le_scan_cb_register(&scan_cb);
767
768 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
769 if (err != 0) {
770 FAIL("Could not start scan (%d)", err);
771 return;
772 }
773
774 /* Wait for PA to sync */
775 printk("Waiting for flag_pa_synced\n");
776 WAIT_FOR_FLAG(flag_pa_synced);
777
778 /* Add PAs as receive state sources */
779 add_all_sources();
780
781 /* Wait for broadcast assistant to send us broadcast code */
782 printk("Waiting for flag_broadcast_code_received\n");
783 WAIT_FOR_FLAG(flag_broadcast_code_received);
784
785 /* Mod all sources by modifying the metadata */
786 mod_all_sources();
787
788 /* Set the BIS sync state */
789 sync_all_broadcasts();
790
791 /* For for client to remove source and thus terminate the PA */
792 printk("Waiting for flag_pa_terminated\n");
793 WAIT_FOR_FLAG(flag_pa_terminated);
794
795 PASS("BAP Scan Delegator Server Sync Client Remove passed\n");
796 }
797
test_main_server_sync_server_rem(void)798 static void test_main_server_sync_server_rem(void)
799 {
800 int err;
801
802 err = common_init();
803 if (err) {
804 FAIL("common init failed (err %d)\n", err);
805 return;
806 }
807
808 bt_le_scan_cb_register(&scan_cb);
809
810 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
811 if (err != 0) {
812 FAIL("Could not start scan (%d)", err);
813 return;
814 }
815
816 /* Wait for PA to sync */
817 printk("Waiting for flag_pa_synced\n");
818 WAIT_FOR_FLAG(flag_pa_synced);
819
820 /* Add PAs as receive state sources */
821 add_all_sources();
822
823 /* Wait for broadcast assistant to send us broadcast code */
824 printk("Waiting for flag_broadcast_code_received\n");
825 WAIT_FOR_FLAG(flag_broadcast_code_received);
826
827 /* Mod all sources by modifying the metadata */
828 mod_all_sources();
829
830 /* Set the BIS sync state */
831 sync_all_broadcasts();
832
833 /* Remote all sources, causing PA sync term request to trigger */
834 remove_all_sources();
835
836 /* Wait for PA sync to be terminated */
837 printk("Waiting for flag_pa_terminated\n");
838 WAIT_FOR_FLAG(flag_pa_terminated);
839
840 PASS("BAP Scan Delegator Server Sync Server Remove passed\n");
841 }
842
843 static const struct bst_test_instance test_scan_delegator[] = {
844 {
845 .test_id = "bap_scan_delegator_client_sync",
846 .test_pre_init_f = test_init,
847 .test_tick_f = test_tick,
848 .test_main_f = test_main_client_sync,
849 },
850 {
851 .test_id = "bap_scan_delegator_server_sync_client_rem",
852 .test_pre_init_f = test_init,
853 .test_tick_f = test_tick,
854 .test_main_f = test_main_server_sync_client_rem,
855 },
856 {
857 .test_id = "bap_scan_delegator_server_sync_server_rem",
858 .test_pre_init_f = test_init,
859 .test_tick_f = test_tick,
860 .test_main_f = test_main_server_sync_server_rem,
861 },
862 BSTEST_END_MARKER
863 };
864
test_scan_delegator_install(struct bst_test_list * tests)865 struct bst_test_list *test_scan_delegator_install(struct bst_test_list *tests)
866 {
867 return bst_add_tests(tests, test_scan_delegator);
868 }
869 #else
test_scan_delegator_install(struct bst_test_list * tests)870 struct bst_test_list *test_scan_delegator_install(struct bst_test_list *tests)
871 {
872 return tests;
873 }
874
875 #endif /* CONFIG_BT_BAP_SCAN_DELEGATOR */
876