1 /*
2 * Copyright 2023 NXP
3 * Copyright (c) 2024 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
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/audio/audio.h>
14 #include <zephyr/bluetooth/audio/bap.h>
15 #include <zephyr/bluetooth/audio/cap.h>
16 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
17 #include <zephyr/bluetooth/audio/pacs.h>
18 #include <zephyr/bluetooth/audio/pbp.h>
19 #include <zephyr/bluetooth/addr.h>
20 #include <zephyr/bluetooth/audio/lc3.h>
21 #include <zephyr/bluetooth/bluetooth.h>
22 #include <zephyr/bluetooth/gap.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/byteorder.h>
28 #include <zephyr/sys/printk.h>
29 #include <zephyr/sys/util.h>
30 #include <zephyr/sys/util_macro.h>
31
32 #include "bap_stream_rx.h"
33 #include "bstests.h"
34 #include "common.h"
35
36 #if defined(CONFIG_BT_PBP)
37 #define SEM_TIMEOUT K_SECONDS(30)
38
39 extern enum bst_result_t bst_result;
40
41 static bool pbs_found;
42
43 static K_SEM_DEFINE(sem_pa_synced, 0U, 1U);
44 static K_SEM_DEFINE(sem_base_received, 0U, 1U);
45 static K_SEM_DEFINE(sem_syncable, 0U, 1U);
46 static K_SEM_DEFINE(sem_pa_sync_lost, 0U, 1U);
47
48 static struct bt_bap_broadcast_sink *broadcast_sink;
49 static struct bt_le_per_adv_sync *bcast_pa_sync;
50
51 static struct audio_test_stream test_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
52 static struct bt_bap_stream *streams_p[ARRAY_SIZE(test_streams)];
53
54 static const struct bt_audio_codec_cap codec = BT_AUDIO_CODEC_CAP_LC3(
55 BT_AUDIO_CODEC_CAP_FREQ_16KHZ | BT_AUDIO_CODEC_CAP_FREQ_24KHZ |
56 BT_AUDIO_CODEC_CAP_FREQ_48KHZ,
57 BT_AUDIO_CODEC_CAP_DURATION_10, BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1), 40u, 155u, 1u,
58 BT_AUDIO_CONTEXT_TYPE_MEDIA);
59
60 /* Create a mask for the maximum BIS we can sync to using the number of streams
61 * we have. We add an additional 1 since the bis indexes start from 1 and not
62 * 0.
63 */
64 static const uint32_t bis_index_mask = BIT_MASK(ARRAY_SIZE(test_streams) + 1U);
65 static uint32_t bis_index_bitfield;
66 static uint32_t broadcast_id;
67
68 static struct bt_pacs_cap cap = {
69 .codec_cap = &codec,
70 };
71
72 static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info,
73 struct net_buf_simple *ad);
74
75 static struct bt_le_scan_cb broadcast_scan_cb = {
76 .recv = broadcast_scan_recv
77 };
78
base_recv_cb(struct bt_bap_broadcast_sink * sink,const struct bt_bap_base * base,size_t base_size)79 static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base,
80 size_t base_size)
81 {
82 k_sem_give(&sem_base_received);
83 }
84
syncable_cb(struct bt_bap_broadcast_sink * sink,const struct bt_iso_biginfo * biginfo)85 static void syncable_cb(struct bt_bap_broadcast_sink *sink, const struct bt_iso_biginfo *biginfo)
86 {
87 printk("Broadcast sink %p is now syncable\n", sink);
88 k_sem_give(&sem_syncable);
89 }
90
91 static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = {
92 .base_recv = base_recv_cb,
93 .syncable = syncable_cb,
94 };
95
started_cb(struct bt_bap_stream * stream)96 static void started_cb(struct bt_bap_stream *stream)
97 {
98 struct audio_test_stream *test_stream = audio_test_stream_from_bap_stream(stream);
99
100 memset(&test_stream->last_info, 0, sizeof(test_stream->last_info));
101 test_stream->rx_cnt = 0U;
102
103 printk("Stream %p started\n", stream);
104 }
105
stopped_cb(struct bt_bap_stream * stream,uint8_t reason)106 static void stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
107 {
108 printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
109 }
110
pa_decode_base(struct bt_data * data,void * user_data)111 static bool pa_decode_base(struct bt_data *data, void *user_data)
112 {
113 const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data);
114 uint32_t base_bis_index_bitfield = 0U;
115 int err;
116
117 /* Base is NULL if the data does not contain a valid BASE */
118 if (base == NULL) {
119 return true;
120 }
121
122 err = bt_bap_base_get_bis_indexes(base, &base_bis_index_bitfield);
123 if (err != 0) {
124 return false;
125 }
126
127 bis_index_bitfield = base_bis_index_bitfield & bis_index_mask;
128 k_sem_give(&sem_base_received);
129
130 return false;
131 }
132
broadcast_pa_recv(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_recv_info * info,struct net_buf_simple * buf)133 static void broadcast_pa_recv(struct bt_le_per_adv_sync *sync,
134 const struct bt_le_per_adv_sync_recv_info *info,
135 struct net_buf_simple *buf)
136 {
137 bt_data_parse(buf, pa_decode_base, NULL);
138 }
139
broadcast_pa_synced(struct bt_le_per_adv_sync * sync,struct bt_le_per_adv_sync_synced_info * info)140 static void broadcast_pa_synced(struct bt_le_per_adv_sync *sync,
141 struct bt_le_per_adv_sync_synced_info *info)
142 {
143 printk("PA synced\n");
144 k_sem_give(&sem_pa_synced);
145 }
146
broadcast_pa_terminated(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_term_info * info)147 static void broadcast_pa_terminated(struct bt_le_per_adv_sync *sync,
148 const struct bt_le_per_adv_sync_term_info *info)
149 {
150 if (sync == bcast_pa_sync) {
151 printk("PA sync %p lost with reason %u\n", sync, info->reason);
152 bcast_pa_sync = NULL;
153
154 k_sem_give(&sem_pa_sync_lost);
155 }
156 }
157
158 static struct bt_bap_stream_ops stream_ops = {
159 .started = started_cb,
160 .stopped = stopped_cb,
161 .recv = bap_stream_rx_recv_cb,
162 };
163
164 static struct bt_le_per_adv_sync_cb broadcast_sync_cb = {
165 .synced = broadcast_pa_synced,
166 .recv = broadcast_pa_recv,
167 .term = broadcast_pa_terminated,
168 };
169
reset(void)170 static int reset(void)
171 {
172 int err;
173
174 k_sem_reset(&sem_pa_synced);
175 k_sem_reset(&sem_base_received);
176 k_sem_reset(&sem_syncable);
177 k_sem_reset(&sem_pa_sync_lost);
178 UNSET_FLAG(flag_audio_received);
179
180 broadcast_id = BT_BAP_INVALID_BROADCAST_ID;
181 bis_index_bitfield = 0U;
182 pbs_found = false;
183
184 if (broadcast_sink != NULL) {
185 err = bt_bap_broadcast_sink_delete(broadcast_sink);
186 if (err) {
187 printk("Deleting broadcast sink failed (err %d)\n", err);
188
189 return err;
190 }
191
192 broadcast_sink = NULL;
193 }
194
195 return 0;
196 }
197
init(void)198 static int init(void)
199 {
200 int err;
201
202 err = bt_enable(NULL);
203 if (err) {
204 FAIL("Bluetooth enable failed (err %d)\n", err);
205
206 return err;
207 }
208
209 printk("Bluetooth initialized\n");
210
211 bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs);
212 bt_le_per_adv_sync_cb_register(&broadcast_sync_cb);
213
214 err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap);
215 if (err) {
216 printk("Capability register failed (err %d)\n", err);
217
218 return err;
219 }
220
221 for (size_t i = 0U; i < ARRAY_SIZE(test_streams); i++) {
222 streams_p[i] = bap_stream_from_audio_test_stream(&test_streams[i]);
223 bt_bap_stream_cb_register(streams_p[i], &stream_ops);
224 }
225
226 return 0;
227 }
228
sync_broadcast_pa(const struct bt_le_scan_recv_info * info)229 static void sync_broadcast_pa(const struct bt_le_scan_recv_info *info)
230 {
231 struct bt_le_per_adv_sync_param param;
232 int err;
233
234 /* Unregister the callbacks to prevent broadcast_scan_recv to be called again */
235 bt_le_scan_cb_unregister(&broadcast_scan_cb);
236 err = bt_le_scan_stop();
237 if (err != 0) {
238 printk("Could not stop scan: %d\n", err);
239 }
240
241 bt_addr_le_copy(¶m.addr, info->addr);
242 param.options = 0;
243 param.sid = info->sid;
244 param.skip = PA_SYNC_SKIP;
245 param.timeout = interval_to_sync_timeout(info->interval);
246 err = bt_le_per_adv_sync_create(¶m, &bcast_pa_sync);
247 if (err != 0) {
248 printk("Could not sync to PA: %d\n", err);
249 }
250 }
251
scan_check_and_sync_broadcast(struct bt_data * data,void * user_data)252 static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data)
253 {
254 enum bt_pbp_announcement_feature source_features;
255 struct bt_uuid_16 adv_uuid;
256 uint8_t *tmp_meta;
257 int ret;
258
259 if (data->type != BT_DATA_SVC_DATA16) {
260 return true;
261 }
262
263 if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) {
264 return true;
265 }
266
267 if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) {
268 /* Save broadcast_id */
269 if (broadcast_id == BT_BAP_INVALID_BROADCAST_ID) {
270 broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16);
271 }
272
273 /* Found Broadcast Audio and Public Broadcast Announcement Services */
274 if (pbs_found) {
275 return false;
276 }
277 }
278
279 ret = bt_pbp_parse_announcement(data, &source_features, &tmp_meta);
280 if (ret >= 0) {
281 printk("Found Suitable Public Broadcast Announcement with %d octets of metadata\n",
282 ret);
283 pbs_found = true;
284
285 /* Continue parsing if Broadcast Audio Announcement Service was not found */
286 if (broadcast_id == BT_BAP_INVALID_BROADCAST_ID) {
287 return true;
288 }
289
290 return false;
291 }
292
293 /* Continue parsing */
294 return true;
295 }
296
broadcast_scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * ad)297 static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info,
298 struct net_buf_simple *ad)
299 {
300 pbs_found = false;
301
302 /* We are only interested in non-connectable periodic advertisers */
303 if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) ||
304 info->interval == 0) {
305 return;
306 }
307
308 bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)&broadcast_id);
309
310 if ((broadcast_id != BT_BAP_INVALID_BROADCAST_ID) && pbs_found) {
311 sync_broadcast_pa(info);
312 }
313 }
314
test_main(void)315 static void test_main(void)
316 {
317 int count = 0;
318 int err;
319
320 init();
321
322 while (count < PBP_STREAMS_TO_SEND) {
323 printk("Resetting for iteration %d\n", count);
324 err = reset();
325 if (err != 0) {
326 printk("Resetting failed: %d\n", err);
327 break;
328 }
329
330 /* Register callbacks */
331 bt_le_scan_cb_register(&broadcast_scan_cb);
332
333 /* Start scanning */
334 printk("Starting scan\n");
335 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
336 if (err) {
337 printk("Scan start failed (err %d)\n", err);
338 break;
339 }
340
341 /* Wait for PA sync */
342 printk("Waiting for PA Sync\n");
343 err = k_sem_take(&sem_pa_synced, SEM_TIMEOUT);
344 if (err != 0) {
345 printk("sem_pa_synced timed out\n");
346 break;
347 }
348
349 /* Wait for BASE decode */
350 printk("Waiting for BASE\n");
351 err = k_sem_take(&sem_base_received, SEM_TIMEOUT);
352 if (err != 0) {
353 printk("sem_base_received timed out\n");
354 break;
355 }
356
357 /* Create broadcast sink */
358 printk("Creating broadcast sink\n");
359 err = bt_bap_broadcast_sink_create(bcast_pa_sync, broadcast_id, &broadcast_sink);
360 if (err != 0) {
361 printk("Sink not created!\n");
362 break;
363 }
364
365 printk("Waiting for syncable\n");
366 err = k_sem_take(&sem_syncable, SEM_TIMEOUT);
367 if (err != 0) {
368 printk("sem_syncable timed out\n");
369 break;
370 }
371
372 /* Sync to broadcast source */
373 printk("Syncing broadcast sink\n");
374 err = bt_bap_broadcast_sink_sync(broadcast_sink, bis_index_bitfield,
375 streams_p, NULL);
376 if (err != 0) {
377 printk("Unable to sync to broadcast source: %d\n", err);
378 break;
379 }
380
381 /* Wait for data */
382 printk("Waiting for data\n");
383 WAIT_FOR_FLAG(flag_audio_received);
384
385 printk("Sending signal to broadcaster to stop\n");
386 backchannel_sync_send_all(); /* let the broadcast source know it can stop */
387
388 /* Wait for the stream to end */
389 printk("Waiting for sync lost\n");
390 k_sem_take(&sem_pa_sync_lost, SEM_TIMEOUT);
391
392 count++;
393 }
394
395 if (count == PBP_STREAMS_TO_SEND) {
396 /* Pass if we synced only with the high quality broadcast */
397 PASS("Public Broadcast sink passed\n");
398 } else {
399 FAIL("Public Broadcast sink failed (%d/%d)\n", count, PBP_STREAMS_TO_SEND);
400 }
401 }
402
403 static const struct bst_test_instance test_public_broadcast_sink[] = {
404 {
405 .test_id = "public_broadcast_sink",
406 .test_pre_init_f = test_init,
407 .test_tick_f = test_tick,
408 .test_main_f = test_main
409 },
410 BSTEST_END_MARKER
411 };
412
test_public_broadcast_sink_install(struct bst_test_list * tests)413 struct bst_test_list *test_public_broadcast_sink_install(struct bst_test_list *tests)
414 {
415 return bst_add_tests(tests, test_public_broadcast_sink);
416 }
417
418 #else /* !CONFIG_BT_PBP */
419
test_public_broadcast_sink_install(struct bst_test_list * tests)420 struct bst_test_list *test_public_broadcast_sink_install(struct bst_test_list *tests)
421 {
422 return tests;
423 }
424
425 #endif /* CONFIG_BT_PBP */
426