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