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