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_lc3_preset.h>
15 #include <zephyr/bluetooth/audio/bap.h>
16 #include <zephyr/bluetooth/audio/cap.h>
17 #include <zephyr/bluetooth/audio/pbp.h>
18 #include <zephyr/bluetooth/bluetooth.h>
19 #include <zephyr/bluetooth/byteorder.h>
20 #include <zephyr/bluetooth/gap.h>
21 #include <zephyr/bluetooth/iso.h>
22 #include <zephyr/bluetooth/uuid.h>
23 #include <zephyr/kernel.h>
24 #include <zephyr/net_buf.h>
25 #include <zephyr/sys/printk.h>
26 #include <zephyr/sys/util.h>
27 #include <zephyr/toolchain.h>
28 
29 #include "bap_stream_tx.h"
30 #include "bstests.h"
31 #include "common.h"
32 
33 #if defined(CONFIG_BT_PBP)
34 /* PBS ASCII text */
35 #define PBS_DEMO                'P', 'B', 'P'
36 #define SEM_TIMEOUT K_SECONDS(2)
37 
38 extern enum bst_result_t bst_result;
39 
40 static const uint8_t pba_metadata[] = {
41 	BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, PBS_DEMO)};
42 
43 static uint8_t bis_codec_data[] = {
44 	BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_FREQ,
45 			BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CFG_FREQ_48KHZ))};
46 
47 static struct audio_test_stream broadcast_source_stream;
48 static struct bt_cap_stream *broadcast_stream;
49 
50 static struct bt_cap_initiator_broadcast_stream_param stream_params;
51 static struct bt_cap_initiator_broadcast_subgroup_param subgroup_param;
52 static struct bt_cap_initiator_broadcast_create_param create_param;
53 static struct bt_cap_broadcast_source *broadcast_source;
54 
55 static struct bt_bap_lc3_preset broadcast_preset_48_2_1 =
56 	BT_BAP_LC3_UNICAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT,
57 					 BT_AUDIO_CONTEXT_TYPE_MEDIA);
58 
59 static K_SEM_DEFINE(sem_started, 0U, 1);
60 static K_SEM_DEFINE(sem_stopped, 0U, 1);
61 
62 static struct bt_le_ext_adv *adv;
63 
started_cb(struct bt_bap_stream * stream)64 static void started_cb(struct bt_bap_stream *stream)
65 {
66 	struct audio_test_stream *test_stream = audio_test_stream_from_bap_stream(stream);
67 	int err;
68 
69 	test_stream->seq_num = 0U;
70 	test_stream->tx_cnt = 0U;
71 
72 	printk("Stream %p started\n", stream);
73 
74 	err = bap_stream_tx_register(stream);
75 	if (err != 0) {
76 		FAIL("Failed to register stream %p for TX: %d\n", stream, err);
77 		return;
78 	}
79 
80 	k_sem_give(&sem_started);
81 }
82 
stopped_cb(struct bt_bap_stream * stream,uint8_t reason)83 static void stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
84 {
85 	int err;
86 
87 	printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
88 
89 	err = bap_stream_tx_unregister(stream);
90 	if (err != 0) {
91 		FAIL("Failed to unregister stream %p for TX: %d\n", stream, err);
92 		return;
93 	}
94 
95 	k_sem_give(&sem_stopped);
96 }
97 
setup_extended_adv_data(struct bt_cap_broadcast_source * source,struct bt_le_ext_adv * adv)98 static int setup_extended_adv_data(struct bt_cap_broadcast_source *source,
99 				   struct bt_le_ext_adv *adv)
100 {
101 	/* Broadcast Audio Streaming Endpoint advertising data */
102 	NET_BUF_SIMPLE_DEFINE(ad_buf, BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE);
103 	NET_BUF_SIMPLE_DEFINE(pbp_ad_buf, BT_PBP_MIN_PBA_SIZE + ARRAY_SIZE(pba_metadata));
104 	NET_BUF_SIMPLE_DEFINE(base_buf, 128);
105 	static enum bt_pbp_announcement_feature pba_params;
106 	struct bt_data ext_ad[2];
107 	struct bt_data per_ad;
108 	uint32_t broadcast_id;
109 	int err;
110 
111 	err = bt_rand(&broadcast_id, BT_AUDIO_BROADCAST_ID_SIZE);
112 	if (err) {
113 		FAIL("Unable to generate broadcast ID: %d\n", err);
114 		return err;
115 	}
116 
117 	/* Broadcast Audio Announcements */
118 	net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL);
119 	net_buf_simple_add_le24(&ad_buf, broadcast_id);
120 	ext_ad[0].type = BT_DATA_SVC_DATA16;
121 	ext_ad[0].data_len = ad_buf.len;
122 	ext_ad[0].data = ad_buf.data;
123 
124 	/**
125 	 * Create a Public Broadcast Announcement
126 	 * Cycle between high and standard quality public broadcast audio.
127 	 */
128 	if (pba_params & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY) {
129 		pba_params = 0;
130 		pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_STANDARD_QUALITY;
131 		printk("Starting stream with standard quality!\n");
132 	} else {
133 		pba_params = 0;
134 		pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY;
135 		printk("Starting stream with high quality!\n");
136 	}
137 
138 	err = bt_pbp_get_announcement(pba_metadata, ARRAY_SIZE(pba_metadata), pba_params,
139 				      &pbp_ad_buf);
140 	if (err != 0) {
141 		printk("Failed to create public broadcast announcement!: %d\n", err);
142 
143 		return err;
144 	}
145 	ext_ad[1].type = BT_DATA_SVC_DATA16;
146 	ext_ad[1].data_len = pbp_ad_buf.len;
147 	ext_ad[1].data = pbp_ad_buf.data;
148 
149 	err = bt_le_ext_adv_set_data(adv, ext_ad, ARRAY_SIZE(ext_ad), NULL, 0);
150 	if (err != 0) {
151 		printk("Failed to set extended advertising data: %d\n", err);
152 
153 		return err;
154 	}
155 
156 	/* Setup periodic advertising data */
157 	err = bt_cap_initiator_broadcast_get_base(source, &base_buf);
158 	if (err != 0) {
159 		printk("Failed to get encoded BASE: %d\n", err);
160 
161 		return err;
162 	}
163 
164 	per_ad.type = BT_DATA_SVC_DATA16;
165 	per_ad.data_len = base_buf.len;
166 	per_ad.data = base_buf.data;
167 	err = bt_le_per_adv_set_data(adv, &per_ad, 1);
168 	if (err != 0) {
169 		printk("Failed to set periodic advertising data: %d\n", err);
170 
171 		return err;
172 	}
173 
174 	return 0;
175 }
176 
start_extended_adv(struct bt_le_ext_adv * adv)177 static int start_extended_adv(struct bt_le_ext_adv *adv)
178 {
179 	int err;
180 
181 	/* Start extended advertising */
182 	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
183 	if (err) {
184 		printk("Failed to start extended advertising: %d\n", err);
185 
186 		return err;
187 	}
188 
189 	/* Enable Periodic Advertising */
190 	err = bt_le_per_adv_start(adv);
191 	if (err) {
192 		printk("Failed to enable periodic advertising: %d\n", err);
193 
194 		return err;
195 	}
196 
197 	return 0;
198 }
199 
setup_extended_adv(struct bt_le_ext_adv ** adv)200 static int setup_extended_adv(struct bt_le_ext_adv **adv)
201 {
202 	int err;
203 
204 	/* Create a non-connectable advertising set */
205 	err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv);
206 	if (err != 0) {
207 		printk("Unable to create extended advertising set: %d\n", err);
208 
209 		return err;
210 	}
211 
212 	/* Set periodic advertising parameters */
213 	err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT);
214 	if (err) {
215 		printk("Failed to set periodic advertising parameters: %d\n", err);
216 
217 		return err;
218 	}
219 
220 	return 0;
221 }
222 
stop_extended_adv(struct bt_le_ext_adv * adv)223 static int stop_extended_adv(struct bt_le_ext_adv *adv)
224 {
225 	int err;
226 
227 	err = bt_le_per_adv_stop(adv);
228 	if (err) {
229 		printk("Failed to stop periodic advertising: %d\n", err);
230 
231 		return err;
232 	}
233 
234 	err = bt_le_ext_adv_stop(adv);
235 	if (err) {
236 		printk("Failed to stop extended advertising: %d\n", err);
237 
238 		return err;
239 	}
240 
241 	err = bt_le_ext_adv_delete(adv);
242 	if (err) {
243 		printk("Failed to delete extended advertising: %d\n", err);
244 
245 		return err;
246 	}
247 
248 	return 0;
249 }
250 
251 static struct bt_bap_stream_ops broadcast_stream_ops = {
252 	.started = started_cb,
253 	.stopped = stopped_cb,
254 	.sent = bap_stream_tx_sent_cb,
255 };
256 
test_main(void)257 static void test_main(void)
258 {
259 	int err;
260 	int count = 0;
261 
262 	err = bt_enable(NULL);
263 	if (err) {
264 		FAIL("Bluetooth enable failed (err %d)\n", err);
265 
266 		return;
267 	}
268 
269 	printk("Bluetooth initialized\n");
270 	bap_stream_tx_init();
271 
272 	broadcast_stream = &broadcast_source_stream.stream;
273 	bt_bap_stream_cb_register(&broadcast_source_stream.stream.bap_stream,
274 				  &broadcast_stream_ops);
275 
276 	stream_params.stream = &broadcast_source_stream.stream;
277 	stream_params.data_len = ARRAY_SIZE(bis_codec_data);
278 	stream_params.data = bis_codec_data;
279 
280 	subgroup_param.stream_count = 1U;
281 	subgroup_param.stream_params = &stream_params;
282 	subgroup_param.codec_cfg = &broadcast_preset_48_2_1.codec_cfg;
283 
284 	create_param.subgroup_count = 1U;
285 	create_param.subgroup_params = &subgroup_param;
286 	create_param.qos = &broadcast_preset_48_2_1.qos;
287 	create_param.packing = BT_ISO_PACKING_SEQUENTIAL;
288 	create_param.encryption = false;
289 
290 	while (count < PBP_STREAMS_TO_SEND) {
291 		k_sem_reset(&sem_started);
292 		k_sem_reset(&sem_stopped);
293 
294 		err = setup_extended_adv(&adv);
295 		if (err != 0) {
296 			printk("Unable to setup extended advertiser: %d\n", err);
297 			FAIL("Public Broadcast source failed\n");
298 		}
299 
300 		err = bt_cap_initiator_broadcast_audio_create(&create_param, &broadcast_source);
301 		if (err != 0) {
302 			printk("Unable to create broadcast source: %d\n", err);
303 			FAIL("Public Broadcast source failed\n");
304 		}
305 
306 		err = bt_cap_initiator_broadcast_audio_start(broadcast_source, adv);
307 		if (err != 0) {
308 			printk("Unable to start broadcast source: %d\n", err);
309 			FAIL("Public Broadcast source failed\n");
310 		}
311 
312 		err = setup_extended_adv_data(broadcast_source, adv);
313 		if (err != 0) {
314 			printk("Unable to setup extended advertising data: %d\n", err);
315 			FAIL("Public Broadcast source failed\n");
316 		}
317 
318 		err = start_extended_adv(adv);
319 		if (err != 0) {
320 			printk("Unable to start extended advertiser: %d\n", err);
321 			FAIL("Public Broadcast source failed\n");
322 		}
323 
324 		k_sem_take(&sem_started, SEM_TIMEOUT);
325 
326 		/* Wait for other devices to let us know when we can stop the source */
327 		printk("Waiting for signal from receiver to stop\n");
328 		backchannel_sync_wait_any();
329 
330 		printk("Stopping broadcast source\n");
331 		err = bt_cap_initiator_broadcast_audio_stop(broadcast_source);
332 		if (err != 0) {
333 			printk("Failed to stop broadcast source: %d\n", err);
334 			FAIL("Public Broadcast source failed\n");
335 		}
336 
337 		k_sem_take(&sem_stopped, SEM_TIMEOUT);
338 		err = bt_cap_initiator_broadcast_audio_delete(broadcast_source);
339 		if (err != 0) {
340 			printk("Failed to stop broadcast source: %d\n", err);
341 			FAIL("Public Broadcast source failed\n");
342 		}
343 
344 		broadcast_source = NULL;
345 
346 		err = stop_extended_adv(adv);
347 		if (err != 0) {
348 			printk("Failed to stop and delete extended advertising: %d\n", err);
349 			FAIL("Public Broadcast source failed\n");
350 		}
351 
352 		count++;
353 	}
354 
355 	PASS("Public Broadcast source passed\n");
356 }
357 
358 static const struct bst_test_instance test_pbp_broadcaster[] = {
359 	{
360 		.test_id = "public_broadcast_source",
361 		.test_pre_init_f = test_init,
362 		.test_tick_f = test_tick,
363 		.test_main_f = test_main
364 	},
365 	BSTEST_END_MARKER
366 };
367 
test_public_broadcast_source_install(struct bst_test_list * tests)368 struct bst_test_list *test_public_broadcast_source_install(struct bst_test_list *tests)
369 {
370 	return bst_add_tests(tests, test_pbp_broadcaster);
371 }
372 
373 #else /* CONFIG_BT_PBP */
374 
test_public_broadcast_source_install(struct bst_test_list * tests)375 struct bst_test_list *test_public_broadcast_source_install(struct bst_test_list *tests)
376 {
377 	return tests;
378 }
379 
380 #endif /* CONFIG_BT_PBP */
381