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 test_stream->valid_rx_cnt = 0U;
103
104 printk("Stream %p started\n", stream);
105 }
106
stopped_cb(struct bt_bap_stream * stream,uint8_t reason)107 static void stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
108 {
109 printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
110 }
111
pa_decode_base(struct bt_data * data,void * user_data)112 static bool pa_decode_base(struct bt_data *data, void *user_data)
113 {
114 const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data);
115 uint32_t base_bis_index_bitfield = 0U;
116 int err;
117
118 /* Base is NULL if the data does not contain a valid BASE */
119 if (base == NULL) {
120 return true;
121 }
122
123 err = bt_bap_base_get_bis_indexes(base, &base_bis_index_bitfield);
124 if (err != 0) {
125 return false;
126 }
127
128 bis_index_bitfield = base_bis_index_bitfield & bis_index_mask;
129 k_sem_give(&sem_base_received);
130
131 return false;
132 }
133
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)134 static void broadcast_pa_recv(struct bt_le_per_adv_sync *sync,
135 const struct bt_le_per_adv_sync_recv_info *info,
136 struct net_buf_simple *buf)
137 {
138 bt_data_parse(buf, pa_decode_base, NULL);
139 }
140
broadcast_pa_synced(struct bt_le_per_adv_sync * sync,struct bt_le_per_adv_sync_synced_info * info)141 static void broadcast_pa_synced(struct bt_le_per_adv_sync *sync,
142 struct bt_le_per_adv_sync_synced_info *info)
143 {
144 printk("PA synced\n");
145 k_sem_give(&sem_pa_synced);
146 }
147
broadcast_pa_terminated(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_term_info * info)148 static void broadcast_pa_terminated(struct bt_le_per_adv_sync *sync,
149 const struct bt_le_per_adv_sync_term_info *info)
150 {
151 if (sync == bcast_pa_sync) {
152 printk("PA sync %p lost with reason %u\n", sync, info->reason);
153 bcast_pa_sync = NULL;
154
155 k_sem_give(&sem_pa_sync_lost);
156 }
157 }
158
159 static struct bt_bap_stream_ops stream_ops = {
160 .started = started_cb,
161 .stopped = stopped_cb,
162 .recv = bap_stream_rx_recv_cb,
163 };
164
165 static struct bt_le_per_adv_sync_cb broadcast_sync_cb = {
166 .synced = broadcast_pa_synced,
167 .recv = broadcast_pa_recv,
168 .term = broadcast_pa_terminated,
169 };
170
reset(void)171 static int reset(void)
172 {
173 int err;
174
175 k_sem_reset(&sem_pa_synced);
176 k_sem_reset(&sem_base_received);
177 k_sem_reset(&sem_syncable);
178 k_sem_reset(&sem_pa_sync_lost);
179 UNSET_FLAG(flag_audio_received);
180
181 broadcast_id = BT_BAP_INVALID_BROADCAST_ID;
182 bis_index_bitfield = 0U;
183 pbs_found = false;
184
185 if (broadcast_sink != NULL) {
186 err = bt_bap_broadcast_sink_delete(broadcast_sink);
187 if (err) {
188 printk("Deleting broadcast sink failed (err %d)\n", err);
189
190 return err;
191 }
192
193 broadcast_sink = NULL;
194 }
195
196 return 0;
197 }
198
init(void)199 static int init(void)
200 {
201 const struct bt_pacs_register_param pacs_param = {
202 .snk_pac = true,
203 .snk_loc = true,
204 .src_pac = true,
205 .src_loc = true,
206 };
207 int err;
208
209 err = bt_enable(NULL);
210 if (err) {
211 FAIL("Bluetooth enable failed (err %d)\n", err);
212
213 return err;
214 }
215
216 printk("Bluetooth initialized\n");
217
218 err = bt_pacs_register(&pacs_param);
219 if (err) {
220 FAIL("Could not register PACS (err %d)\n", err);
221 return err;
222 }
223
224 bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs);
225 bt_le_per_adv_sync_cb_register(&broadcast_sync_cb);
226
227 err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap);
228 if (err) {
229 printk("Capability register failed (err %d)\n", err);
230
231 return err;
232 }
233
234 for (size_t i = 0U; i < ARRAY_SIZE(test_streams); i++) {
235 streams_p[i] = bap_stream_from_audio_test_stream(&test_streams[i]);
236 bt_bap_stream_cb_register(streams_p[i], &stream_ops);
237 }
238
239 return 0;
240 }
241
sync_broadcast_pa(const struct bt_le_scan_recv_info * info)242 static void sync_broadcast_pa(const struct bt_le_scan_recv_info *info)
243 {
244 struct bt_le_per_adv_sync_param param;
245 int err;
246
247 /* Unregister the callbacks to prevent broadcast_scan_recv to be called again */
248 bt_le_scan_cb_unregister(&broadcast_scan_cb);
249 err = bt_le_scan_stop();
250 if (err != 0) {
251 printk("Could not stop scan: %d\n", err);
252 }
253
254 bt_addr_le_copy(¶m.addr, info->addr);
255 param.options = 0;
256 param.sid = info->sid;
257 param.skip = PA_SYNC_SKIP;
258 param.timeout = interval_to_sync_timeout(info->interval);
259 err = bt_le_per_adv_sync_create(¶m, &bcast_pa_sync);
260 if (err != 0) {
261 printk("Could not sync to PA: %d\n", err);
262 }
263 }
264
scan_check_and_sync_broadcast(struct bt_data * data,void * user_data)265 static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data)
266 {
267 enum bt_pbp_announcement_feature source_features;
268 struct bt_uuid_16 adv_uuid;
269 uint8_t *tmp_meta;
270 int ret;
271
272 if (data->type != BT_DATA_SVC_DATA16) {
273 return true;
274 }
275
276 if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) {
277 return true;
278 }
279
280 if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) {
281 /* Save broadcast_id */
282 if (broadcast_id == BT_BAP_INVALID_BROADCAST_ID) {
283 broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16);
284 }
285
286 /* Found Broadcast Audio and Public Broadcast Announcement Services */
287 if (pbs_found) {
288 return false;
289 }
290 }
291
292 ret = bt_pbp_parse_announcement(data, &source_features, &tmp_meta);
293 if (ret >= 0) {
294 printk("Found Suitable Public Broadcast Announcement with %d octets of metadata\n",
295 ret);
296 pbs_found = true;
297
298 /* Continue parsing if Broadcast Audio Announcement Service was not found */
299 if (broadcast_id == BT_BAP_INVALID_BROADCAST_ID) {
300 return true;
301 }
302
303 return false;
304 }
305
306 /* Continue parsing */
307 return true;
308 }
309
broadcast_scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * ad)310 static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info,
311 struct net_buf_simple *ad)
312 {
313 pbs_found = false;
314
315 /* We are only interested in non-connectable periodic advertisers */
316 if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) ||
317 info->interval == 0) {
318 return;
319 }
320
321 bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)&broadcast_id);
322
323 if ((broadcast_id != BT_BAP_INVALID_BROADCAST_ID) && pbs_found) {
324 sync_broadcast_pa(info);
325 }
326 }
327
test_main(void)328 static void test_main(void)
329 {
330 int count = 0;
331 int err;
332
333 init();
334
335 while (count < PBP_STREAMS_TO_SEND) {
336 printk("Resetting for iteration %d\n", count);
337 err = reset();
338 if (err != 0) {
339 printk("Resetting failed: %d\n", err);
340 break;
341 }
342
343 /* Register callbacks */
344 bt_le_scan_cb_register(&broadcast_scan_cb);
345
346 /* Start scanning */
347 printk("Starting scan\n");
348 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
349 if (err) {
350 printk("Scan start failed (err %d)\n", err);
351 break;
352 }
353
354 /* Wait for PA sync */
355 printk("Waiting for PA Sync\n");
356 err = k_sem_take(&sem_pa_synced, SEM_TIMEOUT);
357 if (err != 0) {
358 printk("sem_pa_synced timed out\n");
359 break;
360 }
361
362 /* Wait for BASE decode */
363 printk("Waiting for BASE\n");
364 err = k_sem_take(&sem_base_received, SEM_TIMEOUT);
365 if (err != 0) {
366 printk("sem_base_received timed out\n");
367 break;
368 }
369
370 /* Create broadcast sink */
371 printk("Creating broadcast sink\n");
372 err = bt_bap_broadcast_sink_create(bcast_pa_sync, broadcast_id, &broadcast_sink);
373 if (err != 0) {
374 printk("Sink not created!\n");
375 break;
376 }
377
378 printk("Waiting for syncable\n");
379 err = k_sem_take(&sem_syncable, SEM_TIMEOUT);
380 if (err != 0) {
381 printk("sem_syncable timed out\n");
382 break;
383 }
384
385 /* Sync to broadcast source */
386 printk("Syncing broadcast sink\n");
387 err = bt_bap_broadcast_sink_sync(broadcast_sink, bis_index_bitfield,
388 streams_p, NULL);
389 if (err != 0) {
390 printk("Unable to sync to broadcast source: %d\n", err);
391 break;
392 }
393
394 /* Wait for data */
395 printk("Waiting for data\n");
396 WAIT_FOR_FLAG(flag_audio_received);
397
398 printk("Sending signal to broadcaster to stop\n");
399 backchannel_sync_send_all(); /* let the broadcast source know it can stop */
400
401 /* Wait for the stream to end */
402 printk("Waiting for sync lost\n");
403 k_sem_take(&sem_pa_sync_lost, SEM_TIMEOUT);
404
405 count++;
406 }
407
408 if (count == PBP_STREAMS_TO_SEND) {
409 /* Pass if we synced only with the high quality broadcast */
410 PASS("Public Broadcast sink passed\n");
411 } else {
412 FAIL("Public Broadcast sink failed (%d/%d)\n", count, PBP_STREAMS_TO_SEND);
413 }
414 }
415
416 static const struct bst_test_instance test_public_broadcast_sink[] = {
417 {
418 .test_id = "public_broadcast_sink",
419 .test_pre_init_f = test_init,
420 .test_tick_f = test_tick,
421 .test_main_f = test_main
422 },
423 BSTEST_END_MARKER
424 };
425
test_public_broadcast_sink_install(struct bst_test_list * tests)426 struct bst_test_list *test_public_broadcast_sink_install(struct bst_test_list *tests)
427 {
428 return bst_add_tests(tests, test_public_broadcast_sink);
429 }
430
431 #else /* !CONFIG_BT_PBP */
432
test_public_broadcast_sink_install(struct bst_test_list * tests)433 struct bst_test_list *test_public_broadcast_sink_install(struct bst_test_list *tests)
434 {
435 return tests;
436 }
437
438 #endif /* CONFIG_BT_PBP */
439