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/autoconf.h>
12 #include <zephyr/bluetooth/bluetooth.h>
13 #include <zephyr/bluetooth/audio/audio.h>
14 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
15 #include <zephyr/bluetooth/audio/cap.h>
16 #include <zephyr/bluetooth/audio/bap.h>
17 #include <zephyr/bluetooth/audio/pbp.h>
18 #include <zephyr/bluetooth/byteorder.h>
19 #include <zephyr/bluetooth/crypto.h>
20 #include <zephyr/bluetooth/gap.h>
21 #include <zephyr/bluetooth/hci_types.h>
22 #include <zephyr/bluetooth/iso.h>
23 #include <zephyr/bluetooth/uuid.h>
24 #include <zephyr/kernel.h>
25 #include <zephyr/net_buf.h>
26 #include <zephyr/sys/byteorder.h>
27 #include <zephyr/sys/printk.h>
28 #include <zephyr/sys/util.h>
29 #include <zephyr/sys/util_macro.h>
30 #include <zephyr/types.h>
31 
32 #define BROADCAST_ENQUEUE_COUNT 2U
33 
34 /* PBS ASCII text */
35 #define PBS_DEMO                'P', 'B', 'P'
36 
37 NET_BUF_POOL_FIXED_DEFINE(tx_pool,
38 			  (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT),
39 			  BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL);
40 
41 static K_SEM_DEFINE(sem_broadcast_started, 0, 1);
42 static K_SEM_DEFINE(sem_broadcast_stopped, 0, 1);
43 
44 static struct bt_cap_stream broadcast_source_stream;
45 static struct bt_cap_stream *broadcast_stream;
46 
47 static uint8_t bis_codec_data[] = {BT_AUDIO_CODEC_DATA(
48 	BT_AUDIO_CODEC_CFG_FREQ, BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CFG_FREQ_48KHZ))};
49 
50 const uint8_t pba_metadata[] = {
51 	BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, PBS_DEMO)
52 };
53 
54 static uint8_t appearance_addata[] = {
55 	BT_BYTES_LIST_LE16(BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE)
56 };
57 
58 static const char broadcast_name[] = "PBP Source Demo";
59 
60 static struct bt_bap_lc3_preset broadcast_preset_48_2_1 =
61 	BT_BAP_LC3_UNICAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT,
62 					BT_AUDIO_CONTEXT_TYPE_MEDIA);
63 
64 static const struct bt_data ad[] = {
65 	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
66 };
67 
68 struct bt_cap_initiator_broadcast_stream_param stream_params;
69 struct bt_cap_initiator_broadcast_subgroup_param subgroup_param;
70 struct bt_cap_initiator_broadcast_create_param create_param;
71 struct bt_cap_broadcast_source *broadcast_source;
72 static struct k_work_delayable audio_send_work;
73 struct bt_le_ext_adv *ext_adv;
74 
broadcast_started_cb(struct bt_bap_stream * stream)75 static void broadcast_started_cb(struct bt_bap_stream *stream)
76 {
77 	printk("Stream %p started\n", stream);
78 	k_sem_give(&sem_broadcast_started);
79 }
80 
broadcast_stopped_cb(struct bt_bap_stream * stream,uint8_t reason)81 static void broadcast_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
82 {
83 	if (reason == BT_HCI_ERR_LOCALHOST_TERM_CONN) {
84 		printk("Stream %p ended\n", stream);
85 	} else {
86 		printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
87 	}
88 
89 	k_sem_give(&sem_broadcast_stopped);
90 }
91 
broadcast_sent_cb(struct bt_bap_stream * stream)92 static void broadcast_sent_cb(struct bt_bap_stream *stream)
93 {
94 	static uint8_t mock_data[CONFIG_BT_ISO_TX_MTU];
95 	static bool mock_data_initialized;
96 	static uint32_t seq_num;
97 	struct net_buf *buf;
98 	int ret;
99 
100 	if (broadcast_preset_48_2_1.qos.sdu > CONFIG_BT_ISO_TX_MTU) {
101 		printk("Invalid SDU %u for the MTU: %d", broadcast_preset_48_2_1.qos.sdu,
102 			CONFIG_BT_ISO_TX_MTU);
103 
104 		return;
105 	}
106 
107 	if (!mock_data_initialized) {
108 		for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) {
109 			/* Initialize mock data */
110 			mock_data[i] = (uint8_t)i;
111 		}
112 		mock_data_initialized = true;
113 	}
114 
115 	buf = net_buf_alloc(&tx_pool, K_NO_WAIT);
116 	if (buf == NULL) {
117 		printk("Could not allocate buffer when sending on %p\n", stream);
118 
119 		/* Retry next SDU interval */
120 		k_work_schedule(&audio_send_work, K_USEC(broadcast_preset_48_2_1.qos.interval));
121 		return;
122 	}
123 
124 	net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
125 	net_buf_add_mem(buf, mock_data, broadcast_preset_48_2_1.qos.sdu);
126 	ret = bt_bap_stream_send(stream, buf, seq_num++);
127 	if (ret < 0) {
128 		printk("Could not send on %p: %d\n", stream, ret);
129 		net_buf_unref(buf);
130 
131 		/* Retry next SDU interval */
132 		k_work_schedule(&audio_send_work, K_USEC(broadcast_preset_48_2_1.qos.interval));
133 		return;
134 	}
135 }
136 
audio_timer_timeout(struct k_work * work)137 static void audio_timer_timeout(struct k_work *work)
138 {
139 	broadcast_sent_cb(&broadcast_stream->bap_stream);
140 }
141 
142 static struct bt_bap_stream_ops broadcast_stream_ops = {
143 	.started = broadcast_started_cb,
144 	.stopped = broadcast_stopped_cb,
145 	.sent = broadcast_sent_cb
146 };
147 
setup_extended_adv(struct bt_le_ext_adv ** adv)148 static int setup_extended_adv(struct bt_le_ext_adv **adv)
149 {
150 	int err;
151 
152 	/* Create a non-connectable advertising set */
153 	err = bt_le_ext_adv_create(BT_BAP_ADV_PARAM_BROADCAST_FAST, NULL, adv);
154 	if (err != 0) {
155 		printk("Unable to create extended advertising set: %d\n", err);
156 
157 		return err;
158 	}
159 
160 	/* Set advertising data to have complete local name set */
161 	err = bt_le_ext_adv_set_data(*adv, ad, ARRAY_SIZE(ad), NULL, 0);
162 	if (err) {
163 		printk("Failed to set advertising data (err %d)\n", err);
164 
165 		return 0;
166 	}
167 
168 	/* Set periodic advertising parameters */
169 	err = bt_le_per_adv_set_param(*adv, BT_BAP_PER_ADV_PARAM_BROADCAST_FAST);
170 	if (err) {
171 		printk("Failed to set periodic advertising parameters: %d\n", err);
172 
173 		return err;
174 	}
175 
176 	return 0;
177 }
178 
setup_extended_adv_data(struct bt_cap_broadcast_source * source,struct bt_le_ext_adv * adv)179 static int setup_extended_adv_data(struct bt_cap_broadcast_source *source,
180 				   struct bt_le_ext_adv *adv)
181 {
182 	/* Broadcast Audio Streaming Endpoint advertising data */
183 	NET_BUF_SIMPLE_DEFINE(ad_buf,
184 			      BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE);
185 	NET_BUF_SIMPLE_DEFINE(base_buf, 128);
186 	NET_BUF_SIMPLE_DEFINE(pbp_ad_buf, BT_PBP_MIN_PBA_SIZE + ARRAY_SIZE(pba_metadata));
187 	static enum bt_pbp_announcement_feature pba_params;
188 	struct bt_data ext_ad[4];
189 	struct bt_data per_ad;
190 	uint32_t broadcast_id;
191 	int err;
192 
193 #if defined(CONFIG_STATIC_BROADCAST_ID)
194 	broadcast_id = CONFIG_BROADCAST_ID;
195 #else
196 	err = bt_rand(&broadcast_id, BT_AUDIO_BROADCAST_ID_SIZE);
197 	if (err) {
198 		printk("Unable to generate broadcast ID: %d\n", err);
199 		return err;
200 	}
201 #endif /* CONFIG_STATIC_BROADCAST_ID */
202 
203 	/* Setup extended advertising data */
204 	ext_ad[0].type = BT_DATA_GAP_APPEARANCE;
205 	ext_ad[0].data_len = 2;
206 	ext_ad[0].data = appearance_addata;
207 	/* Broadcast name AD Type */
208 	ext_ad[1].type = BT_DATA_BROADCAST_NAME;
209 	ext_ad[1].data_len = ARRAY_SIZE(broadcast_name);
210 	ext_ad[1].data = broadcast_name;
211 	/* Broadcast Audio Announcement */
212 	net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL);
213 	net_buf_simple_add_le24(&ad_buf, broadcast_id);
214 	ext_ad[2].type = BT_DATA_SVC_DATA16;
215 	ext_ad[2].data_len = ad_buf.len;
216 	ext_ad[2].data = ad_buf.data;
217 
218 	/**
219 	 * Create a Public Broadcast Announcement
220 	 * Cycle between high and standard quality public broadcast audio.
221 	 */
222 	if (pba_params & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY) {
223 		pba_params = 0;
224 		pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_STANDARD_QUALITY;
225 		printk("Starting stream with standard quality!\n");
226 	} else {
227 		pba_params = 0;
228 		pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY;
229 		printk("Starting stream with high quality!\n");
230 	}
231 	err = bt_pbp_get_announcement(pba_metadata, ARRAY_SIZE(pba_metadata), pba_params,
232 				      &pbp_ad_buf);
233 	if (err != 0) {
234 		printk("Failed to create public broadcast announcement!: %d\n", err);
235 
236 		return err;
237 	}
238 	ext_ad[3].type = BT_DATA_SVC_DATA16;
239 	ext_ad[3].data_len = pbp_ad_buf.len;
240 	ext_ad[3].data = pbp_ad_buf.data;
241 	err = bt_le_ext_adv_set_data(adv, ext_ad, ARRAY_SIZE(ext_ad), NULL, 0);
242 	if (err != 0) {
243 		printk("Failed to set extended advertising data: %d\n", err);
244 
245 		return err;
246 	}
247 
248 	/* Setup periodic advertising data */
249 	err = bt_cap_initiator_broadcast_get_base(source, &base_buf);
250 	if (err != 0) {
251 		printk("Failed to get encoded BASE: %d\n", err);
252 
253 		return err;
254 	}
255 
256 	per_ad.type = BT_DATA_SVC_DATA16;
257 	per_ad.data_len = base_buf.len;
258 	per_ad.data = base_buf.data;
259 	err = bt_le_per_adv_set_data(adv, &per_ad, 1);
260 	if (err != 0) {
261 		printk("Failed to set periodic advertising data: %d\n", err);
262 
263 		return err;
264 	}
265 
266 	return 0;
267 }
268 
start_extended_adv(struct bt_le_ext_adv * adv)269 static int start_extended_adv(struct bt_le_ext_adv *adv)
270 {
271 	int err;
272 
273 	/* Start extended advertising */
274 	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
275 	if (err) {
276 		printk("Failed to start extended advertising: %d\n", err);
277 
278 		return err;
279 	}
280 
281 	/* Enable Periodic Advertising */
282 	err = bt_le_per_adv_start(adv);
283 	if (err) {
284 		printk("Failed to enable periodic advertising: %d\n", err);
285 
286 		return err;
287 	}
288 
289 	return 0;
290 }
291 
stop_and_delete_extended_adv(struct bt_le_ext_adv * adv)292 static int stop_and_delete_extended_adv(struct bt_le_ext_adv *adv)
293 {
294 	int err;
295 
296 	/* Stop extended advertising */
297 	err = bt_le_per_adv_stop(adv);
298 	if (err) {
299 		printk("Failed to stop periodic advertising: %d\n", err);
300 
301 		return err;
302 	}
303 
304 	err = bt_le_ext_adv_stop(adv);
305 	if (err) {
306 		printk("Failed to stop extended advertising: %d\n", err);
307 
308 		return err;
309 	}
310 
311 	err = bt_le_ext_adv_delete(adv);
312 	if (err) {
313 		printk("Failed to delete extended advertising: %d\n", err);
314 
315 		return err;
316 	}
317 
318 	return 0;
319 }
320 
reset(void)321 static int reset(void)
322 {
323 	k_sem_reset(&sem_broadcast_started);
324 	k_sem_reset(&sem_broadcast_stopped);
325 
326 	return 0;
327 }
328 
cap_initiator_init(void)329 int cap_initiator_init(void)
330 {
331 	if (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE)) {
332 		broadcast_stream = &broadcast_source_stream;
333 		bt_bap_stream_cb_register(&broadcast_stream->bap_stream, &broadcast_stream_ops);
334 	}
335 
336 	k_work_init_delayable(&audio_send_work, audio_timer_timeout);
337 
338 	return 0;
339 }
340 
cap_initiator_setup(void)341 void cap_initiator_setup(void)
342 {
343 	int err;
344 
345 	stream_params.stream = &broadcast_source_stream;
346 	stream_params.data_len = ARRAY_SIZE(bis_codec_data);
347 	stream_params.data = bis_codec_data;
348 
349 	subgroup_param.stream_count = 1U;
350 	subgroup_param.stream_params = &stream_params;
351 	subgroup_param.codec_cfg = &broadcast_preset_48_2_1.codec_cfg;
352 
353 	create_param.subgroup_count = 1U;
354 	create_param.subgroup_params = &subgroup_param;
355 	create_param.qos = &broadcast_preset_48_2_1.qos;
356 	create_param.packing = BT_ISO_PACKING_SEQUENTIAL;
357 	create_param.encryption = false;
358 
359 	while (true) {
360 		err = reset();
361 		if (err != 0) {
362 			printk("Resetting failed: %d - Aborting\n", err);
363 
364 			return;
365 		}
366 
367 		err = setup_extended_adv(&ext_adv);
368 		if (err != 0) {
369 			printk("Unable to setup extended advertiser: %d\n", err);
370 
371 			return;
372 		}
373 
374 		err = bt_cap_initiator_broadcast_audio_create(&create_param, &broadcast_source);
375 		if (err != 0) {
376 			printk("Unable to create broadcast source: %d\n", err);
377 
378 			return;
379 		}
380 
381 		err = bt_cap_initiator_broadcast_audio_start(broadcast_source, ext_adv);
382 		if (err != 0) {
383 			printk("Unable to start broadcast source: %d\n", err);
384 
385 			return;
386 		}
387 
388 		err = setup_extended_adv_data(broadcast_source, ext_adv);
389 		if (err != 0) {
390 			printk("Unable to setup extended advertising data: %d\n", err);
391 
392 			return;
393 		}
394 
395 		err = start_extended_adv(ext_adv);
396 		if (err != 0) {
397 			printk("Unable to start extended advertiser: %d\n", err);
398 
399 			return;
400 		}
401 		k_sem_take(&sem_broadcast_started, K_FOREVER);
402 
403 		/* Initialize sending */
404 		for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) {
405 			broadcast_sent_cb(&broadcast_stream->bap_stream);
406 		}
407 
408 		/* Keeping running for a little while */
409 		k_sleep(K_SECONDS(15));
410 
411 		err = bt_cap_initiator_broadcast_audio_stop(broadcast_source);
412 		if (err != 0) {
413 			printk("Failed to stop broadcast source: %d\n", err);
414 
415 			return;
416 		}
417 
418 		k_sem_take(&sem_broadcast_stopped, K_FOREVER);
419 		err = bt_cap_initiator_broadcast_audio_delete(broadcast_source);
420 		if (err != 0) {
421 			printk("Failed to stop broadcast source: %d\n", err);
422 
423 			return;
424 		}
425 		broadcast_source = NULL;
426 
427 		err = stop_and_delete_extended_adv(ext_adv);
428 		if (err != 0) {
429 			printk("Failed to stop and delete extended advertising: %d\n", err);
430 
431 			return;
432 		}
433 	}
434 }
435 
436 
main(void)437 int main(void)
438 {
439 	int err;
440 
441 	err = bt_enable(NULL);
442 	if (err != 0) {
443 		printk("Bluetooth enable failed (err %d)\n", err);
444 
445 		return err;
446 	}
447 
448 	printk("Bluetooth initialized\n");
449 
450 	/* Initialize CAP Initiator */
451 	err = cap_initiator_init();
452 	if (err != 0) {
453 		return err;
454 	}
455 
456 	printk("CAP initialized\n");
457 
458 	/* Configure and start broadcast stream */
459 	cap_initiator_setup();
460 
461 	return 0;
462 }
463