1 /*
2  * Copyright (c) 2023-2025 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include <stddef.h>
11 #include <string.h>
12 
13 #include <zephyr/autoconf.h>
14 #include <zephyr/bluetooth/addr.h>
15 #include <zephyr/bluetooth/audio/audio.h>
16 #include <zephyr/bluetooth/audio/cap.h>
17 #include <zephyr/bluetooth/audio/bap.h>
18 #include <zephyr/bluetooth/audio/csip.h>
19 #include <zephyr/bluetooth/audio/gmap.h>
20 #include <zephyr/bluetooth/audio/gmap_lc3_preset.h>
21 #include <zephyr/bluetooth/bluetooth.h>
22 #include <zephyr/bluetooth/byteorder.h>
23 #include <zephyr/bluetooth/conn.h>
24 #include <zephyr/bluetooth/crypto.h>
25 #include <zephyr/bluetooth/gap.h>
26 #include <zephyr/bluetooth/gatt.h>
27 #include <zephyr/bluetooth/hci_types.h>
28 #include <zephyr/bluetooth/iso.h>
29 #include <zephyr/bluetooth/uuid.h>
30 #include <zephyr/kernel.h>
31 #include <zephyr/net_buf.h>
32 #include <zephyr/sys/byteorder.h>
33 #include <zephyr/sys/printk.h>
34 #include <zephyr/sys/util.h>
35 #include <zephyr/sys/util_macro.h>
36 #include <zephyr/toolchain.h>
37 
38 #include "bap_stream_tx.h"
39 #include "bap_stream_rx.h"
40 #include "bstests.h"
41 #include "common.h"
42 #include "bap_common.h"
43 
44 #if defined(CONFIG_BT_GMAP)
45 
46 #define UNICAST_SINK_SUPPORTED (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0)
47 #define UNICAST_SRC_SUPPORTED  (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0)
48 
49 #define CONTEXT  (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_GAME)
50 #define LOCATION (BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT)
51 
52 #define GMAP_BROADCAST_AC_MAX_STREAM 2
53 #define GMAP_UNICAST_AC_MAX_CONN     2U
54 #define GMAP_UNICAST_AC_MAX_SNK      (2U * GMAP_UNICAST_AC_MAX_CONN)
55 #define GMAP_UNICAST_AC_MAX_SRC      (2U * GMAP_UNICAST_AC_MAX_CONN)
56 #define GMAP_UNICAST_AC_MAX_PAIR     MAX(GMAP_UNICAST_AC_MAX_SNK, GMAP_UNICAST_AC_MAX_SRC)
57 #define GMAP_UNICAST_AC_MAX_STREAM   (GMAP_UNICAST_AC_MAX_SNK + GMAP_UNICAST_AC_MAX_SRC)
58 
59 extern enum bst_result_t bst_result;
60 static const struct named_lc3_preset *snk_named_preset;
61 static const struct named_lc3_preset *src_named_preset;
62 static const struct named_lc3_preset *broadcast_named_preset;
63 
64 struct gmap_unicast_ac_param {
65 	char *name;
66 	size_t conn_cnt;
67 	size_t snk_cnt[GMAP_UNICAST_AC_MAX_CONN];
68 	size_t src_cnt[GMAP_UNICAST_AC_MAX_CONN];
69 	size_t snk_chan_cnt;
70 	const struct named_lc3_preset *snk_named_preset;
71 	const struct named_lc3_preset *src_named_preset;
72 };
73 struct gmap_broadcast_ac_param {
74 	char *name;
75 	size_t stream_cnt;
76 	size_t chan_cnt;
77 	const struct named_lc3_preset *named_preset;
78 };
79 
80 static struct named_lc3_preset gmap_unicast_snk_presets[] = {
81 	{"32_1_gr", BT_GMAP_LC3_PRESET_32_1_GR(LOCATION, CONTEXT)},
82 	{"32_2_gr", BT_GMAP_LC3_PRESET_32_2_GR(LOCATION, CONTEXT)},
83 	{"48_1_gr", BT_GMAP_LC3_PRESET_48_1_GR(LOCATION, CONTEXT)},
84 	{"48_2_gr", BT_GMAP_LC3_PRESET_48_2_GR(LOCATION, CONTEXT)},
85 	{"48_3_gr", BT_GMAP_LC3_PRESET_48_3_GR(LOCATION, CONTEXT)},
86 	{"48_4_gr", BT_GMAP_LC3_PRESET_48_4_GR(LOCATION, CONTEXT)},
87 };
88 
89 static struct named_lc3_preset gmap_unicast_src_presets[] = {
90 	{"16_1_gs", BT_GMAP_LC3_PRESET_16_1_GS(LOCATION, CONTEXT)},
91 	{"16_2_gs", BT_GMAP_LC3_PRESET_16_2_GS(LOCATION, CONTEXT)},
92 	{"32_1_gs", BT_GMAP_LC3_PRESET_32_1_GS(LOCATION, CONTEXT)},
93 	{"32_2_gs", BT_GMAP_LC3_PRESET_32_2_GS(LOCATION, CONTEXT)},
94 	{"48_1_gs", BT_GMAP_LC3_PRESET_48_1_GS(LOCATION, CONTEXT)},
95 	{"48_2_gs", BT_GMAP_LC3_PRESET_48_2_GS(LOCATION, CONTEXT)},
96 };
97 
98 static struct named_lc3_preset gmap_broadcast_presets[] = {
99 	{"48_1_g", BT_GMAP_LC3_PRESET_48_1_G(LOCATION, CONTEXT)},
100 	{"48_2_g", BT_GMAP_LC3_PRESET_48_2_G(LOCATION, CONTEXT)},
101 	{"48_3_g", BT_GMAP_LC3_PRESET_48_3_G(LOCATION, CONTEXT)},
102 	{"48_4_g", BT_GMAP_LC3_PRESET_48_4_G(LOCATION, CONTEXT)},
103 };
104 
105 struct named_lc3_preset named_preset;
106 
107 static struct audio_test_stream broadcast_streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
108 static struct unicast_stream unicast_streams[GMAP_UNICAST_AC_MAX_STREAM];
109 static struct bt_cap_stream *started_unicast_streams[GMAP_UNICAST_AC_MAX_STREAM];
110 static size_t started_unicast_streams_cnt;
111 static struct bt_bap_ep
112 	*sink_eps[GMAP_UNICAST_AC_MAX_CONN][CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
113 static struct bt_bap_ep
114 	*source_eps[GMAP_UNICAST_AC_MAX_CONN][CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
115 static struct bt_conn *connected_conns[GMAP_UNICAST_AC_MAX_CONN];
116 static size_t connected_conn_cnt;
117 
118 static K_SEM_DEFINE(sem_stream_started, 0U,
119 		    MAX(ARRAY_SIZE(unicast_streams), ARRAY_SIZE(broadcast_streams)));
120 static K_SEM_DEFINE(sem_stream_stopped, 0U,
121 		    MAX(ARRAY_SIZE(unicast_streams), ARRAY_SIZE(broadcast_streams)));
122 
123 CREATE_FLAG(flag_cas_discovered);
124 CREATE_FLAG(flag_started);
125 CREATE_FLAG(flag_updated);
126 CREATE_FLAG(flag_stopped);
127 CREATE_FLAG(flag_mtu_exchanged);
128 CREATE_FLAG(flag_sink_discovered);
129 CREATE_FLAG(flag_source_discovered);
130 CREATE_FLAG(flag_gmap_discovered);
131 
gmap_get_named_preset(bool is_unicast,enum bt_audio_dir dir,const char * preset_arg)132 const struct named_lc3_preset *gmap_get_named_preset(bool is_unicast, enum bt_audio_dir dir,
133 						     const char *preset_arg)
134 {
135 	if (is_unicast) {
136 		if (dir == BT_AUDIO_DIR_SINK) {
137 			for (size_t i = 0U; i < ARRAY_SIZE(gmap_unicast_snk_presets); i++) {
138 				if (!strcmp(preset_arg, gmap_unicast_snk_presets[i].name)) {
139 					return &gmap_unicast_snk_presets[i];
140 				}
141 			}
142 		} else if (dir == BT_AUDIO_DIR_SOURCE) {
143 			for (size_t i = 0U; i < ARRAY_SIZE(gmap_unicast_src_presets); i++) {
144 				if (!strcmp(preset_arg, gmap_unicast_src_presets[i].name)) {
145 					return &gmap_unicast_src_presets[i];
146 				}
147 			}
148 		}
149 	} else {
150 
151 		for (size_t i = 0U; i < ARRAY_SIZE(gmap_broadcast_presets); i++) {
152 			if (!strcmp(preset_arg, gmap_broadcast_presets[i].name)) {
153 				return &gmap_broadcast_presets[i];
154 			}
155 		}
156 	}
157 
158 	return NULL;
159 }
160 
stream_configured_cb(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg_pref * pref)161 static void stream_configured_cb(struct bt_bap_stream *stream,
162 				 const struct bt_bap_qos_cfg_pref *pref)
163 {
164 	printk("Configured stream %p\n", stream);
165 
166 	/* TODO: The preference should be used/taken into account when
167 	 * setting the QoS
168 	 */
169 }
170 
stream_qos_set_cb(struct bt_bap_stream * stream)171 static void stream_qos_set_cb(struct bt_bap_stream *stream)
172 {
173 	printk("QoS set stream %p\n", stream);
174 }
175 
stream_enabled_cb(struct bt_bap_stream * stream)176 static void stream_enabled_cb(struct bt_bap_stream *stream)
177 {
178 	printk("Enabled stream %p\n", stream);
179 }
180 
stream_started_cb(struct bt_bap_stream * stream)181 static void stream_started_cb(struct bt_bap_stream *stream)
182 {
183 	struct audio_test_stream *test_stream = audio_test_stream_from_bap_stream(stream);
184 
185 	memset(&test_stream->last_info, 0, sizeof(test_stream->last_info));
186 	test_stream->rx_cnt = 0U;
187 	test_stream->valid_rx_cnt = 0U;
188 	test_stream->seq_num = 0U;
189 	test_stream->tx_cnt = 0U;
190 
191 	printk("Started stream %p\n", stream);
192 
193 	if (bap_stream_tx_can_send(stream)) {
194 		int err;
195 
196 		err = bap_stream_tx_register(stream);
197 		if (err != 0) {
198 			FAIL("Failed to register stream %p for TX: %d\n", stream, err);
199 			return;
200 		}
201 	}
202 
203 	k_sem_give(&sem_stream_started);
204 }
205 
stream_metadata_updated_cb(struct bt_bap_stream * stream)206 static void stream_metadata_updated_cb(struct bt_bap_stream *stream)
207 {
208 	printk("Metadata updated stream %p\n", stream);
209 }
210 
stream_disabled_cb(struct bt_bap_stream * stream)211 static void stream_disabled_cb(struct bt_bap_stream *stream)
212 {
213 	printk("Disabled stream %p\n", stream);
214 }
215 
stream_stopped_cb(struct bt_bap_stream * stream,uint8_t reason)216 static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
217 {
218 	printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
219 
220 	if (bap_stream_tx_can_send(stream)) {
221 		int err;
222 
223 		err = bap_stream_tx_unregister(stream);
224 		if (err != 0) {
225 			FAIL("Failed to unregister stream %p for TX: %d\n", stream, err);
226 			return;
227 		}
228 	}
229 
230 	k_sem_give(&sem_stream_stopped);
231 }
232 
stream_released_cb(struct bt_bap_stream * stream)233 static void stream_released_cb(struct bt_bap_stream *stream)
234 {
235 	printk("Released stream %p\n", stream);
236 }
237 
238 static struct bt_bap_stream_ops stream_ops = {
239 	.configured = stream_configured_cb,
240 	.qos_set = stream_qos_set_cb,
241 	.enabled = stream_enabled_cb,
242 	.started = stream_started_cb,
243 	.metadata_updated = stream_metadata_updated_cb,
244 	.disabled = stream_disabled_cb,
245 	.stopped = stream_stopped_cb,
246 	.released = stream_released_cb,
247 	.sent = bap_stream_tx_sent_cb,
248 	.recv = bap_stream_rx_recv_cb,
249 };
250 
cap_discovery_complete_cb(struct bt_conn * conn,int err,const struct bt_csip_set_coordinator_set_member * member,const struct bt_csip_set_coordinator_csis_inst * csis_inst)251 static void cap_discovery_complete_cb(struct bt_conn *conn, int err,
252 				      const struct bt_csip_set_coordinator_set_member *member,
253 				      const struct bt_csip_set_coordinator_csis_inst *csis_inst)
254 {
255 	if (err != 0) {
256 		FAIL("Failed to discover CAS: %d\n", err);
257 
258 		return;
259 	}
260 
261 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER)) {
262 		if (csis_inst == NULL) {
263 			FAIL("Failed to discover CAS CSIS\n");
264 
265 			return;
266 		}
267 
268 		printk("Found CAS with CSIS %p\n", csis_inst);
269 	} else {
270 		printk("Found CAS\n");
271 	}
272 
273 	SET_FLAG(flag_cas_discovered);
274 }
275 
unicast_start_complete_cb(int err,struct bt_conn * conn)276 static void unicast_start_complete_cb(int err, struct bt_conn *conn)
277 {
278 	if (err != 0) {
279 		FAIL("Failed to start (failing conn %p): %d\n", conn, err);
280 
281 		return;
282 	}
283 
284 	SET_FLAG(flag_started);
285 }
286 
unicast_update_complete_cb(int err,struct bt_conn * conn)287 static void unicast_update_complete_cb(int err, struct bt_conn *conn)
288 {
289 	if (err != 0) {
290 		FAIL("Failed to update (failing conn %p): %d\n", conn, err);
291 
292 		return;
293 	}
294 
295 	SET_FLAG(flag_updated);
296 }
297 
unicast_stop_complete_cb(int err,struct bt_conn * conn)298 static void unicast_stop_complete_cb(int err, struct bt_conn *conn)
299 {
300 	if (err != 0) {
301 		FAIL("Failed to stop (failing conn %p): %d\n", conn, err);
302 
303 		return;
304 	}
305 
306 	SET_FLAG(flag_stopped);
307 }
308 
309 static struct bt_cap_initiator_cb cap_cb = {
310 	.unicast_discovery_complete = cap_discovery_complete_cb,
311 	.unicast_start_complete = unicast_start_complete_cb,
312 	.unicast_update_complete = unicast_update_complete_cb,
313 	.unicast_stop_complete = unicast_stop_complete_cb,
314 };
315 
add_remote_sink_ep(struct bt_conn * conn,struct bt_bap_ep * ep)316 static void add_remote_sink_ep(struct bt_conn *conn, struct bt_bap_ep *ep)
317 {
318 	for (size_t i = 0U; i < ARRAY_SIZE(sink_eps[bt_conn_index(conn)]); i++) {
319 		if (sink_eps[bt_conn_index(conn)][i] == NULL) {
320 			printk("Conn %p: Sink #%zu: ep %p\n", conn, i, ep);
321 			sink_eps[bt_conn_index(conn)][i] = ep;
322 			break;
323 		}
324 	}
325 }
326 
add_remote_source_ep(struct bt_conn * conn,struct bt_bap_ep * ep)327 static void add_remote_source_ep(struct bt_conn *conn, struct bt_bap_ep *ep)
328 {
329 	for (size_t i = 0U; i < ARRAY_SIZE(source_eps[bt_conn_index(conn)]); i++) {
330 		if (source_eps[bt_conn_index(conn)][i] == NULL) {
331 			printk("Conn %p: Source #%zu: ep %p\n", conn, i, ep);
332 			source_eps[bt_conn_index(conn)][i] = ep;
333 			break;
334 		}
335 	}
336 }
337 
bap_pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_audio_codec_cap * codec_cap)338 static void bap_pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir,
339 			      const struct bt_audio_codec_cap *codec_cap)
340 {
341 	printk("conn %p codec_cap %p dir 0x%02x\n", conn, codec_cap, dir);
342 
343 	print_codec_cap(codec_cap);
344 }
345 
bap_endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)346 static void bap_endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
347 {
348 	if (dir == BT_AUDIO_DIR_SINK) {
349 		add_remote_sink_ep(conn, ep);
350 	} else if (dir == BT_AUDIO_DIR_SOURCE) {
351 		add_remote_source_ep(conn, ep);
352 	}
353 }
354 
bap_discover_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)355 static void bap_discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
356 {
357 	if (err != 0) {
358 		FAIL("Discovery failed for dir %u: %d\n", dir, err);
359 		return;
360 	}
361 
362 	if (dir == BT_AUDIO_DIR_SINK) {
363 		printk("Sink discover complete\n");
364 		SET_FLAG(flag_sink_discovered);
365 	} else if (dir == BT_AUDIO_DIR_SOURCE) {
366 		printk("Source discover complete\n");
367 		SET_FLAG(flag_source_discovered);
368 	}
369 }
370 
371 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
372 	.pac_record = bap_pac_record_cb,
373 	.endpoint = bap_endpoint_cb,
374 	.discover = bap_discover_cb,
375 };
376 
att_mtu_updated(struct bt_conn * conn,uint16_t tx,uint16_t rx)377 static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
378 {
379 	printk("MTU exchanged\n");
380 	SET_FLAG(flag_mtu_exchanged);
381 }
382 
383 static struct bt_gatt_cb gatt_callbacks = {
384 	.att_mtu_updated = att_mtu_updated,
385 };
386 
gmap_discover_cb(struct bt_conn * conn,int err,enum bt_gmap_role role,struct bt_gmap_feat features)387 static void gmap_discover_cb(struct bt_conn *conn, int err, enum bt_gmap_role role,
388 			     struct bt_gmap_feat features)
389 {
390 	enum bt_gmap_ugt_feat ugt_feat;
391 
392 	if (err != 0) {
393 		FAIL("gmap discovery (err %d)\n", err);
394 		return;
395 	}
396 
397 	printk("GMAP discovered for conn %p:\n\trole 0x%02x\n\tugg_feat 0x%02x\n\tugt_feat "
398 	       "0x%02x\n\tbgs_feat 0x%02x\n\tbgr_feat 0x%02x\n",
399 	       conn, role, features.ugg_feat, features.ugt_feat, features.bgs_feat,
400 	       features.bgr_feat);
401 
402 	if ((role & BT_GMAP_ROLE_UGT) == 0) {
403 		FAIL("Remote GMAP device is not a UGT\n");
404 		return;
405 	}
406 
407 	ugt_feat = features.ugt_feat;
408 	if ((ugt_feat & BT_GMAP_UGT_FEAT_SOURCE) == 0 ||
409 	    (ugt_feat & BT_GMAP_UGT_FEAT_80KBPS_SOURCE) == 0 ||
410 	    (ugt_feat & BT_GMAP_UGT_FEAT_SINK) == 0 ||
411 	    (ugt_feat & BT_GMAP_UGT_FEAT_64KBPS_SINK) == 0 ||
412 	    (ugt_feat & BT_GMAP_UGT_FEAT_MULTIPLEX) == 0 ||
413 	    (ugt_feat & BT_GMAP_UGT_FEAT_MULTISINK) == 0 ||
414 	    (ugt_feat & BT_GMAP_UGT_FEAT_MULTISOURCE) == 0) {
415 		FAIL("Remote GMAP device does not have expected UGT features: %d\n", ugt_feat);
416 		return;
417 	}
418 
419 	SET_FLAG(flag_gmap_discovered);
420 }
421 
422 static const struct bt_gmap_cb gmap_cb = {
423 	.discover = gmap_discover_cb,
424 };
425 
scan_recv_cb(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)426 static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf)
427 {
428 	char addr_str[BT_ADDR_LE_STR_LEN];
429 	struct bt_conn *conn;
430 	int err;
431 
432 	/* Check for connectable, extended advertising */
433 	if (((info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) == 0) ||
434 	    ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE)) == 0) {
435 		/* We're only interested in connectable extended advertising */
436 	}
437 
438 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, info->addr);
439 	if (conn != NULL) {
440 		/* Already connected to this device */
441 		bt_conn_unref(conn);
442 		return;
443 	}
444 
445 	bt_addr_le_to_str(info->addr, addr_str, sizeof(addr_str));
446 	printk("Device found: %s (RSSI %d)\n", addr_str, info->rssi);
447 
448 	/* connect only to devices in close proximity */
449 	if (info->rssi < -70) {
450 		FAIL("RSSI too low");
451 		return;
452 	}
453 
454 	printk("Stopping scan\n");
455 	if (bt_le_scan_stop()) {
456 		FAIL("Could not stop scan");
457 		return;
458 	}
459 
460 	err = bt_conn_le_create(info->addr, BT_CONN_LE_CREATE_CONN,
461 				BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN,
462 						 0, BT_GAP_MS_TO_CONN_TIMEOUT(4000)),
463 				&connected_conns[connected_conn_cnt]);
464 	if (err != 0) {
465 		FAIL("Could not connect to peer: %d", err);
466 	}
467 }
468 
init(void)469 static void init(void)
470 {
471 	const struct bt_gmap_feat features = {
472 		.ugg_feat = (BT_GMAP_UGG_FEAT_MULTIPLEX | BT_GMAP_UGG_FEAT_96KBPS_SOURCE |
473 			     BT_GMAP_UGG_FEAT_MULTISINK),
474 	};
475 	const enum bt_gmap_role role = BT_GMAP_ROLE_UGG;
476 	static struct bt_le_scan_cb scan_cb = {
477 		.recv = scan_recv_cb,
478 	};
479 	int err;
480 
481 	err = bt_enable(NULL);
482 	if (err != 0) {
483 		FAIL("Bluetooth enable failed (err %d)\n", err);
484 		return;
485 	}
486 
487 	printk("Bluetooth initialized\n");
488 	bap_stream_tx_init();
489 
490 	bt_gatt_cb_register(&gatt_callbacks);
491 	err = bt_le_scan_cb_register(&scan_cb);
492 	if (err != 0) {
493 		FAIL("Failed to register scan callbacks (err %d)\n", err);
494 		return;
495 	}
496 
497 	err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
498 	if (err != 0) {
499 		FAIL("Failed to register BAP callbacks (err %d)\n", err);
500 		return;
501 	}
502 
503 	err = bt_cap_initiator_register_cb(&cap_cb);
504 	if (err != 0) {
505 		FAIL("Failed to register CAP callbacks (err %d)\n", err);
506 		return;
507 	}
508 
509 	for (size_t i = 0; i < ARRAY_SIZE(unicast_streams); i++) {
510 		bt_cap_stream_ops_register(
511 			cap_stream_from_audio_test_stream(&unicast_streams[i].stream), &stream_ops);
512 	}
513 
514 	for (size_t i = 0; i < ARRAY_SIZE(broadcast_streams); i++) {
515 		bt_cap_stream_ops_register(cap_stream_from_audio_test_stream(&broadcast_streams[i]),
516 					   &stream_ops);
517 	}
518 
519 	err = bt_gmap_register(role, features);
520 	if (err != 0) {
521 		FAIL("Failed to register GMAS (err %d)\n", err);
522 
523 		return;
524 	}
525 
526 	err = bt_gmap_cb_register(&gmap_cb);
527 	if (err != 0) {
528 		FAIL("Failed to register callbacks (err %d)\n", err);
529 
530 		return;
531 	}
532 }
533 
scan_and_connect(void)534 static void scan_and_connect(void)
535 {
536 	int err;
537 
538 	UNSET_FLAG(flag_connected);
539 
540 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
541 	if (err != 0) {
542 		FAIL("Scanning failed to start (err %d)\n", err);
543 		return;
544 	}
545 
546 	printk("Scanning successfully started\n");
547 	WAIT_FOR_FLAG(flag_connected);
548 	connected_conn_cnt++;
549 }
550 
discover_sink(struct bt_conn * conn)551 static void discover_sink(struct bt_conn *conn)
552 {
553 	int err;
554 
555 	UNSET_FLAG(flag_sink_discovered);
556 
557 	err = bt_bap_unicast_client_discover(conn, BT_AUDIO_DIR_SINK);
558 	if (err != 0) {
559 		printk("Failed to discover sink: %d\n", err);
560 		return;
561 	}
562 
563 	WAIT_FOR_FLAG(flag_sink_discovered);
564 }
565 
discover_source(struct bt_conn * conn)566 static void discover_source(struct bt_conn *conn)
567 {
568 	int err;
569 
570 	UNSET_FLAG(flag_source_discovered);
571 
572 	err = bt_bap_unicast_client_discover(conn, BT_AUDIO_DIR_SOURCE);
573 	if (err != 0) {
574 		printk("Failed to discover source: %d\n", err);
575 		return;
576 	}
577 
578 	WAIT_FOR_FLAG(flag_source_discovered);
579 }
580 
discover_gmas(struct bt_conn * conn)581 static void discover_gmas(struct bt_conn *conn)
582 {
583 	int err;
584 
585 	UNSET_FLAG(flag_gmap_discovered);
586 
587 	err = bt_gmap_discover(conn);
588 	if (err != 0) {
589 		printk("Failed to discover GMAS: %d\n", err);
590 		return;
591 	}
592 
593 	WAIT_FOR_FLAG(flag_gmap_discovered);
594 }
595 
discover_cas(struct bt_conn * conn)596 static void discover_cas(struct bt_conn *conn)
597 {
598 	int err;
599 
600 	UNSET_FLAG(flag_cas_discovered);
601 
602 	err = bt_cap_initiator_unicast_discover(conn);
603 	if (err != 0) {
604 		printk("Failed to discover CAS: %d\n", err);
605 		return;
606 	}
607 
608 	WAIT_FOR_FLAG(flag_cas_discovered);
609 }
610 
gmap_unicast_ac_create_unicast_group(const struct gmap_unicast_ac_param * param,struct unicast_stream * snk_uni_streams[],size_t snk_cnt,struct unicast_stream * src_uni_streams[],size_t src_cnt,struct bt_bap_unicast_group ** unicast_group)611 static int gmap_unicast_ac_create_unicast_group(const struct gmap_unicast_ac_param *param,
612 						struct unicast_stream *snk_uni_streams[],
613 						size_t snk_cnt,
614 						struct unicast_stream *src_uni_streams[],
615 						size_t src_cnt,
616 						struct bt_bap_unicast_group **unicast_group)
617 {
618 	struct bt_bap_unicast_group_stream_param
619 		snk_group_stream_params[GMAP_UNICAST_AC_MAX_SNK] = {0};
620 	struct bt_bap_unicast_group_stream_param
621 		src_group_stream_params[GMAP_UNICAST_AC_MAX_SRC] = {0};
622 	struct bt_bap_unicast_group_stream_pair_param pair_params[GMAP_UNICAST_AC_MAX_PAIR] = {0};
623 	struct bt_bap_unicast_group_param group_param = {0};
624 	size_t snk_stream_cnt = 0U;
625 	size_t src_stream_cnt = 0U;
626 	size_t pair_cnt = 0U;
627 
628 	/* Create Group
629 	 *
630 	 * First setup the individual stream parameters and then match them in pairs by connection
631 	 * and direction
632 	 */
633 	for (size_t i = 0U; i < snk_cnt; i++) {
634 		snk_group_stream_params[i].qos = &snk_uni_streams[i]->qos;
635 		snk_group_stream_params[i].stream =
636 			bap_stream_from_audio_test_stream(&snk_uni_streams[i]->stream);
637 	}
638 	for (size_t i = 0U; i < src_cnt; i++) {
639 		src_group_stream_params[i].qos = &src_uni_streams[i]->qos;
640 		src_group_stream_params[i].stream =
641 			bap_stream_from_audio_test_stream(&src_uni_streams[i]->stream);
642 	}
643 
644 	for (size_t i = 0U; i < param->conn_cnt; i++) {
645 		for (size_t j = 0; j < MAX(param->snk_cnt[i], param->src_cnt[i]); j++) {
646 			if (param->snk_cnt[i] > j) {
647 				pair_params[pair_cnt].tx_param =
648 					&snk_group_stream_params[snk_stream_cnt++];
649 			} else {
650 				pair_params[pair_cnt].tx_param = NULL;
651 			}
652 
653 			if (param->src_cnt[i] > j) {
654 				pair_params[pair_cnt].rx_param =
655 					&src_group_stream_params[src_stream_cnt++];
656 			} else {
657 				pair_params[pair_cnt].rx_param = NULL;
658 			}
659 
660 			pair_cnt++;
661 		}
662 	}
663 
664 	group_param.packing = BT_ISO_PACKING_SEQUENTIAL;
665 	group_param.params = pair_params;
666 	group_param.params_count = pair_cnt;
667 
668 	return bt_bap_unicast_group_create(&group_param, unicast_group);
669 }
670 
gmap_ac_cap_unicast_start(const struct gmap_unicast_ac_param * param,struct unicast_stream * snk_uni_streams[],size_t snk_cnt,struct unicast_stream * src_uni_streams[],size_t src_cnt,struct bt_bap_unicast_group * unicast_group)671 static int gmap_ac_cap_unicast_start(const struct gmap_unicast_ac_param *param,
672 				     struct unicast_stream *snk_uni_streams[], size_t snk_cnt,
673 				     struct unicast_stream *src_uni_streams[], size_t src_cnt,
674 				     struct bt_bap_unicast_group *unicast_group)
675 {
676 	struct bt_cap_unicast_audio_start_stream_param stream_params[GMAP_UNICAST_AC_MAX_STREAM] = {
677 		0};
678 	struct bt_audio_codec_cfg *snk_codec_cfgs[GMAP_UNICAST_AC_MAX_SNK] = {0};
679 	struct bt_audio_codec_cfg *src_codec_cfgs[GMAP_UNICAST_AC_MAX_SRC] = {0};
680 	struct bt_cap_stream *snk_cap_streams[GMAP_UNICAST_AC_MAX_SNK] = {0};
681 	struct bt_cap_stream *src_cap_streams[GMAP_UNICAST_AC_MAX_SRC] = {0};
682 	struct bt_cap_unicast_audio_start_param start_param = {0};
683 	struct bt_bap_ep *snk_eps[GMAP_UNICAST_AC_MAX_SNK] = {0};
684 	struct bt_bap_ep *src_eps[GMAP_UNICAST_AC_MAX_SRC] = {0};
685 	size_t snk_stream_cnt = 0U;
686 	size_t src_stream_cnt = 0U;
687 	size_t stream_cnt = 0U;
688 	size_t snk_ep_cnt = 0U;
689 	size_t src_ep_cnt = 0U;
690 	int err;
691 
692 	for (size_t i = 0U; i < param->conn_cnt; i++) {
693 #if UNICAST_SINK_SUPPORTED
694 		for (size_t j = 0U; j < param->snk_cnt[i]; j++) {
695 			snk_eps[snk_ep_cnt] = sink_eps[bt_conn_index(connected_conns[i])][j];
696 			if (snk_eps[snk_ep_cnt] == NULL) {
697 				FAIL("No sink[%zu][%zu] endpoint available\n", i, j);
698 
699 				return -ENODEV;
700 			}
701 			snk_ep_cnt++;
702 		}
703 #endif /* UNICAST_SINK_SUPPORTED */
704 
705 #if UNICAST_SRC_SUPPORTED
706 		for (size_t j = 0U; j < param->src_cnt[i]; j++) {
707 			src_eps[src_ep_cnt] = source_eps[bt_conn_index(connected_conns[i])][j];
708 			if (src_eps[src_ep_cnt] == NULL) {
709 				FAIL("No source[%zu][%zu] endpoint available\n", i, j);
710 
711 				return -ENODEV;
712 			}
713 			src_ep_cnt++;
714 		}
715 #endif /* UNICAST_SRC_SUPPORTED > 0 */
716 	}
717 
718 	if (snk_ep_cnt != snk_cnt) {
719 		FAIL("Sink endpoint and stream count mismatch: %zu != %zu\n", snk_ep_cnt, snk_cnt);
720 
721 		return -EINVAL;
722 	}
723 
724 	if (src_ep_cnt != src_cnt) {
725 		FAIL("Source endpoint and stream count mismatch: %zu != %zu\n", src_ep_cnt,
726 		     src_cnt);
727 
728 		return -EINVAL;
729 	}
730 
731 	/* Setup arrays of parameters based on the preset for easier access. This also copies the
732 	 * preset so that we can modify them (e.g. update the metadata)
733 	 */
734 	for (size_t i = 0U; i < snk_cnt; i++) {
735 		snk_cap_streams[i] = cap_stream_from_audio_test_stream(&snk_uni_streams[i]->stream);
736 		snk_codec_cfgs[i] = &snk_uni_streams[i]->codec_cfg;
737 	}
738 
739 	for (size_t i = 0U; i < src_cnt; i++) {
740 		src_cap_streams[i] = cap_stream_from_audio_test_stream(&src_uni_streams[i]->stream);
741 		src_codec_cfgs[i] = &src_uni_streams[i]->codec_cfg;
742 	}
743 
744 	/* CAP Start */
745 	for (size_t i = 0U; i < param->conn_cnt; i++) {
746 		for (size_t j = 0U; j < param->snk_cnt[i]; j++) {
747 			struct bt_cap_unicast_audio_start_stream_param *stream_param =
748 				&stream_params[stream_cnt];
749 
750 			stream_param->member.member = connected_conns[i];
751 			stream_param->codec_cfg = snk_codec_cfgs[snk_stream_cnt];
752 			stream_param->ep = snk_eps[snk_stream_cnt];
753 			stream_param->stream = snk_cap_streams[snk_stream_cnt];
754 
755 			snk_stream_cnt++;
756 			stream_cnt++;
757 
758 			/* If we have more than 1 connection or stream in one direction, we set the
759 			 * location bit accordingly
760 			 */
761 			if (param->conn_cnt > 1U || param->snk_cnt[i] > 1U) {
762 				const int err = bt_audio_codec_cfg_set_chan_allocation(
763 					stream_param->codec_cfg, (enum bt_audio_location)BIT(i));
764 
765 				if (err < 0) {
766 					FAIL("Failed to set channel allocation: %d\n", err);
767 					return err;
768 				}
769 			}
770 		}
771 
772 		for (size_t j = 0U; j < param->src_cnt[i]; j++) {
773 			struct bt_cap_unicast_audio_start_stream_param *stream_param =
774 				&stream_params[stream_cnt];
775 
776 			stream_param->member.member = connected_conns[i];
777 			stream_param->codec_cfg = src_codec_cfgs[src_stream_cnt];
778 			stream_param->ep = src_eps[src_stream_cnt];
779 			stream_param->stream = src_cap_streams[src_stream_cnt];
780 
781 			src_stream_cnt++;
782 			stream_cnt++;
783 
784 			/* If we have more than 1 connection or stream in one direction, we set the
785 			 * location bit accordingly
786 			 */
787 			if (param->conn_cnt > 1U || param->src_cnt[i] > 1U) {
788 				const int err = bt_audio_codec_cfg_set_chan_allocation(
789 					stream_param->codec_cfg, (enum bt_audio_location)BIT(i));
790 
791 				if (err < 0) {
792 					FAIL("Failed to set channel allocation: %d\n", err);
793 					return err;
794 				}
795 			}
796 		}
797 	}
798 
799 	start_param.stream_params = stream_params;
800 	start_param.count = stream_cnt;
801 	start_param.type = BT_CAP_SET_TYPE_AD_HOC;
802 
803 	err = bt_cap_initiator_unicast_audio_start(&start_param);
804 	if (err == 0) {
805 		for (size_t i = 0U; i < start_param.count; i++) {
806 			started_unicast_streams[i] = start_param.stream_params[i].stream;
807 		}
808 
809 		started_unicast_streams_cnt = start_param.count;
810 	}
811 
812 	return err;
813 }
814 
gmap_ac_unicast(const struct gmap_unicast_ac_param * param,struct bt_bap_unicast_group ** unicast_group)815 static int gmap_ac_unicast(const struct gmap_unicast_ac_param *param,
816 			   struct bt_bap_unicast_group **unicast_group)
817 {
818 	/* Allocate params large enough for any params, but only use what is required */
819 	struct unicast_stream *snk_uni_streams[GMAP_UNICAST_AC_MAX_SNK];
820 	struct unicast_stream *src_uni_streams[GMAP_UNICAST_AC_MAX_SRC];
821 	size_t snk_cnt = 0;
822 	size_t src_cnt = 0;
823 	int err;
824 
825 	if (param->conn_cnt > GMAP_UNICAST_AC_MAX_CONN) {
826 		FAIL("Invalid conn_cnt: %zu\n", param->conn_cnt);
827 
828 		return -EINVAL;
829 	}
830 
831 	for (size_t i = 0; i < param->conn_cnt; i++) {
832 		/* Verify conn values */
833 		if (param->snk_cnt[i] > GMAP_UNICAST_AC_MAX_SNK) {
834 			FAIL("Invalid conn_snk_cnt[%zu]: %zu\n", i, param->snk_cnt[i]);
835 
836 			return -EINVAL;
837 		}
838 
839 		if (param->src_cnt[i] > GMAP_UNICAST_AC_MAX_SRC) {
840 			FAIL("Invalid conn_src_cnt[%zu]: %zu\n", i, param->src_cnt[i]);
841 
842 			return -EINVAL;
843 		}
844 	}
845 
846 	/* Get total count of sink and source streams to setup */
847 	for (size_t i = 0U; i < param->conn_cnt; i++) {
848 		for (size_t j = 0U; j < param->snk_cnt[i]; j++) {
849 			snk_cnt++;
850 		}
851 
852 		for (size_t j = 0U; j < param->src_cnt[i]; j++) {
853 			src_cnt++;
854 		}
855 	}
856 
857 	/* Setup arrays of parameters based on the preset for easier access. This also copies the
858 	 * preset so that we can modify them (e.g. update the metadata)
859 	 */
860 	for (size_t i = 0U; i < snk_cnt; i++) {
861 		snk_uni_streams[i] = &unicast_streams[i];
862 
863 		copy_unicast_stream_preset(snk_uni_streams[i], param->snk_named_preset);
864 
865 		/* Some audio configuration requires multiple sink channels,
866 		 * so multiply the SDU based on the channel count
867 		 */
868 		snk_uni_streams[i]->qos.sdu *= param->snk_chan_cnt;
869 	}
870 
871 	for (size_t i = 0U; i < src_cnt; i++) {
872 		src_uni_streams[i] = &unicast_streams[i + snk_cnt];
873 		copy_unicast_stream_preset(src_uni_streams[i], param->src_named_preset);
874 	}
875 
876 	err = gmap_unicast_ac_create_unicast_group(param, snk_uni_streams, snk_cnt, src_uni_streams,
877 						   src_cnt, unicast_group);
878 	if (err != 0) {
879 		FAIL("Failed to create group: %d\n", err);
880 
881 		return err;
882 	}
883 
884 	UNSET_FLAG(flag_started);
885 
886 	printk("Starting %zu streams for %s\n", snk_cnt + src_cnt, param->name);
887 	err = gmap_ac_cap_unicast_start(param, snk_uni_streams, snk_cnt, src_uni_streams, src_cnt,
888 					*unicast_group);
889 	if (err != 0) {
890 		FAIL("Failed to start unicast audio: %d\n\n", err);
891 
892 		return err;
893 	}
894 
895 	WAIT_FOR_FLAG(flag_started);
896 
897 	/* let other devices know we have started what we wanted */
898 	backchannel_sync_send_all();
899 
900 	return 0;
901 }
902 
unicast_audio_stop(struct bt_bap_unicast_group * unicast_group)903 static void unicast_audio_stop(struct bt_bap_unicast_group *unicast_group)
904 {
905 	struct bt_cap_unicast_audio_stop_param param;
906 	int err;
907 
908 	UNSET_FLAG(flag_stopped);
909 
910 	param.type = BT_CAP_SET_TYPE_AD_HOC;
911 	param.count = started_unicast_streams_cnt;
912 	param.streams = started_unicast_streams;
913 	param.release = true;
914 
915 	err = bt_cap_initiator_unicast_audio_stop(&param);
916 	if (err != 0) {
917 		FAIL("Failed to start unicast audio: %d\n", err);
918 		return;
919 	}
920 
921 	WAIT_FOR_FLAG(flag_stopped);
922 
923 	started_unicast_streams_cnt = 0U;
924 	memset(started_unicast_streams, 0, sizeof(started_unicast_streams));
925 }
926 
unicast_group_delete(struct bt_bap_unicast_group * unicast_group)927 static void unicast_group_delete(struct bt_bap_unicast_group *unicast_group)
928 {
929 	int err;
930 
931 	err = bt_bap_unicast_group_delete(unicast_group);
932 	if (err != 0) {
933 		FAIL("Failed to create group: %d\n", err);
934 		return;
935 	}
936 }
937 
test_gmap_ugg_unicast_ac(const struct gmap_unicast_ac_param * param)938 static void test_gmap_ugg_unicast_ac(const struct gmap_unicast_ac_param *param)
939 {
940 	struct bt_bap_unicast_group *unicast_group;
941 	bool expect_tx = false;
942 	bool expect_rx = false;
943 
944 	printk("Running test for %s with Sink Preset %s and Source Preset %s\n", param->name,
945 	       param->snk_named_preset != NULL ? param->snk_named_preset->name : "None",
946 	       param->src_named_preset != NULL ? param->src_named_preset->name : "None");
947 
948 	if (param->conn_cnt > GMAP_UNICAST_AC_MAX_CONN) {
949 		FAIL("Invalid conn_cnt: %zu\n", param->conn_cnt);
950 		return;
951 	}
952 
953 	init();
954 
955 	for (size_t i = 0U; i < param->conn_cnt; i++) {
956 		UNSET_FLAG(flag_mtu_exchanged);
957 
958 		scan_and_connect();
959 
960 		WAIT_FOR_FLAG(flag_mtu_exchanged);
961 
962 		printk("Connected %zu/%zu\n", i + 1, param->conn_cnt);
963 	}
964 
965 	if (connected_conn_cnt < param->conn_cnt) {
966 		FAIL("Only %zu/%u connected devices, please connect additional devices for this "
967 		     "audio configuration\n",
968 		     connected_conn_cnt, param->conn_cnt);
969 		return;
970 	}
971 
972 	for (size_t i = 0U; i < param->conn_cnt; i++) {
973 		discover_cas(connected_conns[i]);
974 
975 		if (param->snk_cnt[i] > 0U) {
976 			discover_sink(connected_conns[i]);
977 			expect_tx = true;
978 		}
979 
980 		if (param->src_cnt[i] > 0U) {
981 			discover_source(connected_conns[i]);
982 			expect_rx = true;
983 		}
984 
985 		discover_gmas(connected_conns[i]);
986 		discover_gmas(connected_conns[i]); /* test that we can discover twice */
987 	}
988 
989 	gmap_ac_unicast(param, &unicast_group);
990 
991 	if (expect_tx) {
992 		/* Wait until acceptors have received expected data */
993 		backchannel_sync_wait_all();
994 	}
995 
996 	if (expect_rx) {
997 		printk("Waiting for data\n");
998 		WAIT_FOR_FLAG(flag_audio_received);
999 	}
1000 
1001 	unicast_audio_stop(unicast_group);
1002 
1003 	unicast_group_delete(unicast_group);
1004 	unicast_group = NULL;
1005 
1006 	for (size_t i = 0U; i < param->conn_cnt; i++) {
1007 		const int err =
1008 			bt_conn_disconnect(connected_conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
1009 
1010 		if (err != 0) {
1011 			FAIL("Failed to disconnect conn[%zu]: %d\n", i, err);
1012 		}
1013 
1014 		bt_conn_unref(connected_conns[i]);
1015 		connected_conns[i] = NULL;
1016 	}
1017 
1018 	PASS("GMAP UGG passed for %s with Sink Preset %s and Source Preset %s\n", param->name,
1019 	     param->snk_named_preset != NULL ? param->snk_named_preset->name : "None",
1020 	     param->src_named_preset != NULL ? param->src_named_preset->name : "None");
1021 }
1022 
setup_extended_adv_data(struct bt_cap_broadcast_source * source,struct bt_le_ext_adv * adv)1023 static void setup_extended_adv_data(struct bt_cap_broadcast_source *source,
1024 				    struct bt_le_ext_adv *adv)
1025 {
1026 	/* Broadcast Audio Streaming Endpoint advertising data */
1027 	NET_BUF_SIMPLE_DEFINE(ad_buf, BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE);
1028 	NET_BUF_SIMPLE_DEFINE(base_buf, 128);
1029 	struct bt_data ext_ad;
1030 	struct bt_data per_ad;
1031 	uint32_t broadcast_id;
1032 	int err;
1033 
1034 	err = bt_rand(&broadcast_id, BT_AUDIO_BROADCAST_ID_SIZE);
1035 	if (err) {
1036 		FAIL("Unable to generate broadcast ID: %d\n", err);
1037 		return;
1038 	}
1039 
1040 	/* Setup extended advertising data */
1041 	net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL);
1042 	net_buf_simple_add_le24(&ad_buf, broadcast_id);
1043 	ext_ad.type = BT_DATA_SVC_DATA16;
1044 	ext_ad.data_len = ad_buf.len;
1045 	ext_ad.data = ad_buf.data;
1046 	err = bt_le_ext_adv_set_data(adv, &ext_ad, 1, NULL, 0);
1047 	if (err != 0) {
1048 		FAIL("Failed to set extended advertising data: %d\n", err);
1049 		return;
1050 	}
1051 
1052 	/* Setup periodic advertising data */
1053 	err = bt_cap_initiator_broadcast_get_base(source, &base_buf);
1054 	if (err != 0) {
1055 		FAIL("Failed to get encoded BASE: %d\n", err);
1056 		return;
1057 	}
1058 
1059 	per_ad.type = BT_DATA_SVC_DATA16;
1060 	per_ad.data_len = base_buf.len;
1061 	per_ad.data = base_buf.data;
1062 	err = bt_le_per_adv_set_data(adv, &per_ad, 1);
1063 	if (err != 0) {
1064 		FAIL("Failed to set periodic advertising data: %d\n", err);
1065 		return;
1066 	}
1067 }
1068 
start_extended_adv(struct bt_le_ext_adv * adv)1069 static void start_extended_adv(struct bt_le_ext_adv *adv)
1070 {
1071 	int err;
1072 
1073 	/* Start extended advertising */
1074 	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
1075 	if (err) {
1076 		FAIL("Failed to start extended advertising: %d\n", err);
1077 		return;
1078 	}
1079 
1080 	/* Enable Periodic Advertising */
1081 	err = bt_le_per_adv_start(adv);
1082 	if (err) {
1083 		FAIL("Failed to enable periodic advertising: %d\n", err);
1084 		return;
1085 	}
1086 }
1087 
stop_and_delete_extended_adv(struct bt_le_ext_adv * adv)1088 static void stop_and_delete_extended_adv(struct bt_le_ext_adv *adv)
1089 {
1090 	int err;
1091 
1092 	/* Stop extended advertising */
1093 	err = bt_le_per_adv_stop(adv);
1094 	if (err) {
1095 		FAIL("Failed to stop periodic advertising: %d\n", err);
1096 		return;
1097 	}
1098 
1099 	err = bt_le_ext_adv_stop(adv);
1100 	if (err) {
1101 		FAIL("Failed to stop extended advertising: %d\n", err);
1102 		return;
1103 	}
1104 
1105 	err = bt_le_ext_adv_delete(adv);
1106 	if (err) {
1107 		FAIL("Failed to delete extended advertising: %d\n", err);
1108 		return;
1109 	}
1110 }
1111 
broadcast_audio_start(struct bt_cap_broadcast_source * broadcast_source,struct bt_le_ext_adv * adv)1112 static void broadcast_audio_start(struct bt_cap_broadcast_source *broadcast_source,
1113 				  struct bt_le_ext_adv *adv)
1114 {
1115 	int err;
1116 
1117 	err = bt_cap_initiator_broadcast_audio_start(broadcast_source, adv);
1118 	if (err != 0) {
1119 		FAIL("Unable to start broadcast source: %d\n", err);
1120 		return;
1121 	}
1122 
1123 	printk("Broadcast source created\n");
1124 }
1125 
broadcast_audio_stop(struct bt_cap_broadcast_source * broadcast_source,size_t stream_count)1126 static void broadcast_audio_stop(struct bt_cap_broadcast_source *broadcast_source,
1127 				 size_t stream_count)
1128 {
1129 	int err;
1130 
1131 	printk("Stopping broadcast source\n");
1132 
1133 	err = bt_cap_initiator_broadcast_audio_stop(broadcast_source);
1134 	if (err != 0) {
1135 		FAIL("Failed to stop broadcast source: %d\n", err);
1136 		return;
1137 	}
1138 
1139 	/* Wait for all to be stopped */
1140 	printk("Waiting for broadcast_streams to be stopped\n");
1141 	for (size_t i = 0U; i < stream_count; i++) {
1142 		k_sem_take(&sem_stream_stopped, K_FOREVER);
1143 	}
1144 
1145 	printk("Broadcast source stopped\n");
1146 }
1147 
broadcast_audio_delete(struct bt_cap_broadcast_source * broadcast_source)1148 static void broadcast_audio_delete(struct bt_cap_broadcast_source *broadcast_source)
1149 {
1150 	int err;
1151 
1152 	printk("Deleting broadcast source\n");
1153 
1154 	err = bt_cap_initiator_broadcast_audio_delete(broadcast_source);
1155 	if (err != 0) {
1156 		FAIL("Failed to stop broadcast source: %d\n", err);
1157 		return;
1158 	}
1159 
1160 	printk("Broadcast source deleted\n");
1161 }
1162 
test_gmap_ugg_broadcast_ac(const struct gmap_broadcast_ac_param * param)1163 static int test_gmap_ugg_broadcast_ac(const struct gmap_broadcast_ac_param *param)
1164 {
1165 	uint8_t stereo_data[] = {
1166 		BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_CHAN_ALLOC,
1167 				    BT_AUDIO_LOCATION_FRONT_RIGHT | BT_AUDIO_LOCATION_FRONT_LEFT)};
1168 	uint8_t right_data[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_CHAN_ALLOC,
1169 						    BT_AUDIO_LOCATION_FRONT_RIGHT)};
1170 	uint8_t left_data[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_CHAN_ALLOC,
1171 						   BT_AUDIO_LOCATION_FRONT_LEFT)};
1172 	struct bt_cap_initiator_broadcast_subgroup_param subgroup_param = {0};
1173 	struct bt_cap_initiator_broadcast_create_param create_param = {0};
1174 	struct bt_cap_initiator_broadcast_stream_param
1175 		stream_params[GMAP_BROADCAST_AC_MAX_STREAM] = {0};
1176 	struct bt_cap_broadcast_source *broadcast_source;
1177 	struct bt_audio_codec_cfg codec_cfg;
1178 	struct bt_bap_qos_cfg qos;
1179 	struct bt_le_ext_adv *adv;
1180 	int err;
1181 
1182 	for (size_t i = 0U; i < param->stream_cnt; i++) {
1183 		stream_params[i].stream = cap_stream_from_audio_test_stream(&broadcast_streams[i]);
1184 
1185 		if (param->stream_cnt == 1U) {
1186 			stream_params[i].data_len = ARRAY_SIZE(stereo_data);
1187 			stream_params[i].data = stereo_data;
1188 		} else if (i == 0U) {
1189 			stream_params[i].data_len = ARRAY_SIZE(left_data);
1190 			stream_params[i].data = left_data;
1191 		} else if (i == 1U) {
1192 			stream_params[i].data_len = ARRAY_SIZE(right_data);
1193 			stream_params[i].data = right_data;
1194 		}
1195 	}
1196 
1197 	memcpy(&codec_cfg, &broadcast_named_preset->preset.codec_cfg, sizeof(codec_cfg));
1198 	memcpy(&qos, &broadcast_named_preset->preset.qos, sizeof(qos));
1199 	qos.sdu *= param->chan_cnt;
1200 
1201 	subgroup_param.stream_count = param->stream_cnt;
1202 	subgroup_param.stream_params = stream_params;
1203 	subgroup_param.codec_cfg = &codec_cfg;
1204 	create_param.subgroup_count = 1U;
1205 	create_param.subgroup_params = &subgroup_param;
1206 	create_param.qos = &qos;
1207 
1208 	init();
1209 	setup_broadcast_adv(&adv);
1210 
1211 	err = bt_cap_initiator_broadcast_audio_create(&create_param, &broadcast_source);
1212 	if (err != 0) {
1213 		FAIL("Failed to create broadcast source: %d\n", err);
1214 		return -ENOEXEC;
1215 	}
1216 
1217 	for (size_t i = 0U; i < param->stream_cnt; i++) {
1218 		struct audio_test_stream *test_stream = &broadcast_streams[i];
1219 
1220 		test_stream->tx_sdu_size = create_param.qos->sdu;
1221 	}
1222 
1223 	broadcast_audio_start(broadcast_source, adv);
1224 	setup_extended_adv_data(broadcast_source, adv);
1225 	start_extended_adv(adv);
1226 
1227 	/* Wait for all to be started */
1228 	printk("Waiting for broadcast_streams to be started\n");
1229 	for (size_t i = 0U; i < param->stream_cnt; i++) {
1230 		k_sem_take(&sem_stream_started, K_FOREVER);
1231 	}
1232 
1233 	/* Wait for other devices to have received what they wanted */
1234 	backchannel_sync_wait_any();
1235 
1236 	broadcast_audio_stop(broadcast_source, param->stream_cnt);
1237 
1238 	broadcast_audio_delete(broadcast_source);
1239 	broadcast_source = NULL;
1240 
1241 	stop_and_delete_extended_adv(adv);
1242 	adv = NULL;
1243 
1244 	PASS("CAP initiator broadcast passed\n");
1245 
1246 	return 0;
1247 }
1248 
test_gmap_ac_1(void)1249 static void test_gmap_ac_1(void)
1250 {
1251 	const struct gmap_unicast_ac_param param = {
1252 		.name = "ac_1",
1253 		.conn_cnt = 1U,
1254 		.snk_cnt = {1U},
1255 		.src_cnt = {0U},
1256 		.snk_chan_cnt = 1U,
1257 		.snk_named_preset = snk_named_preset,
1258 		.src_named_preset = NULL,
1259 	};
1260 
1261 	test_gmap_ugg_unicast_ac(&param);
1262 }
1263 
test_gmap_ac_2(void)1264 static void test_gmap_ac_2(void)
1265 {
1266 	const struct gmap_unicast_ac_param param = {
1267 		.name = "ac_2",
1268 		.conn_cnt = 1U,
1269 		.snk_cnt = {0U},
1270 		.src_cnt = {1U},
1271 		.snk_chan_cnt = 1U,
1272 		.snk_named_preset = NULL,
1273 		.src_named_preset = src_named_preset,
1274 	};
1275 
1276 	test_gmap_ugg_unicast_ac(&param);
1277 }
1278 
test_gmap_ac_3(void)1279 static void test_gmap_ac_3(void)
1280 {
1281 	const struct gmap_unicast_ac_param param = {
1282 		.name = "ac_3",
1283 		.conn_cnt = 1U,
1284 		.snk_cnt = {1U},
1285 		.src_cnt = {1U},
1286 		.snk_chan_cnt = 1U,
1287 		.snk_named_preset = snk_named_preset,
1288 		.src_named_preset = src_named_preset,
1289 	};
1290 
1291 	test_gmap_ugg_unicast_ac(&param);
1292 }
1293 
test_gmap_ac_4(void)1294 static void test_gmap_ac_4(void)
1295 {
1296 	const struct gmap_unicast_ac_param param = {
1297 		.name = "ac_4",
1298 		.conn_cnt = 1U,
1299 		.snk_cnt = {1U},
1300 		.src_cnt = {0U},
1301 		.snk_chan_cnt = 2U,
1302 		.snk_named_preset = snk_named_preset,
1303 		.src_named_preset = NULL,
1304 	};
1305 
1306 	test_gmap_ugg_unicast_ac(&param);
1307 }
1308 
test_gmap_ac_5(void)1309 static void test_gmap_ac_5(void)
1310 {
1311 	const struct gmap_unicast_ac_param param = {
1312 		.name = "ac_5",
1313 		.conn_cnt = 1U,
1314 		.snk_cnt = {1U},
1315 		.src_cnt = {1U},
1316 		.snk_chan_cnt = 2U,
1317 		.snk_named_preset = snk_named_preset,
1318 		.src_named_preset = src_named_preset,
1319 	};
1320 
1321 	test_gmap_ugg_unicast_ac(&param);
1322 }
1323 
test_gmap_ac_6_i(void)1324 static void test_gmap_ac_6_i(void)
1325 {
1326 	const struct gmap_unicast_ac_param param = {
1327 		.name = "ac_6_i",
1328 		.conn_cnt = 1U,
1329 		.snk_cnt = {2U},
1330 		.src_cnt = {0U},
1331 		.snk_chan_cnt = 1U,
1332 		.snk_named_preset = snk_named_preset,
1333 		.src_named_preset = NULL,
1334 	};
1335 
1336 	test_gmap_ugg_unicast_ac(&param);
1337 }
1338 
test_gmap_ac_6_ii(void)1339 static void test_gmap_ac_6_ii(void)
1340 {
1341 	const struct gmap_unicast_ac_param param = {
1342 		.name = "ac_6_ii",
1343 		.conn_cnt = 2U,
1344 		.snk_cnt = {1U, 1U},
1345 		.src_cnt = {0U, 0U},
1346 		.snk_chan_cnt = 1U,
1347 		.snk_named_preset = snk_named_preset,
1348 		.src_named_preset = NULL,
1349 	};
1350 
1351 	test_gmap_ugg_unicast_ac(&param);
1352 }
1353 
test_gmap_ac_7_ii(void)1354 static void test_gmap_ac_7_ii(void)
1355 {
1356 	const struct gmap_unicast_ac_param param = {
1357 		.name = "ac_7_ii",
1358 		.conn_cnt = 2U,
1359 		.snk_cnt = {1U, 0U},
1360 		.src_cnt = {0U, 1U},
1361 		.snk_chan_cnt = 1U,
1362 		.snk_named_preset = snk_named_preset,
1363 		.src_named_preset = src_named_preset,
1364 	};
1365 
1366 	test_gmap_ugg_unicast_ac(&param);
1367 }
1368 
test_gmap_ac_8_i(void)1369 static void test_gmap_ac_8_i(void)
1370 {
1371 	const struct gmap_unicast_ac_param param = {
1372 		.name = "ac_8_i",
1373 		.conn_cnt = 1U,
1374 		.snk_cnt = {2U},
1375 		.src_cnt = {1U},
1376 		.snk_chan_cnt = 1U,
1377 		.snk_named_preset = snk_named_preset,
1378 		.src_named_preset = src_named_preset,
1379 	};
1380 
1381 	test_gmap_ugg_unicast_ac(&param);
1382 }
1383 
test_gmap_ac_8_ii(void)1384 static void test_gmap_ac_8_ii(void)
1385 {
1386 	const struct gmap_unicast_ac_param param = {
1387 		.name = "ac_8_ii",
1388 		.conn_cnt = 2U,
1389 		.snk_cnt = {1U, 1U},
1390 		.src_cnt = {1U, 0U},
1391 		.snk_chan_cnt = 1U,
1392 		.snk_named_preset = snk_named_preset,
1393 		.src_named_preset = src_named_preset,
1394 	};
1395 
1396 	test_gmap_ugg_unicast_ac(&param);
1397 }
1398 
test_gmap_ac_11_i(void)1399 static void test_gmap_ac_11_i(void)
1400 {
1401 	const struct gmap_unicast_ac_param param = {
1402 		.name = "ac_11_i",
1403 		.conn_cnt = 1U,
1404 		.snk_cnt = {2U},
1405 		.src_cnt = {2U},
1406 		.snk_chan_cnt = 1U,
1407 		.snk_named_preset = snk_named_preset,
1408 		.src_named_preset = src_named_preset,
1409 	};
1410 
1411 	test_gmap_ugg_unicast_ac(&param);
1412 }
1413 
test_gmap_ac_11_ii(void)1414 static void test_gmap_ac_11_ii(void)
1415 {
1416 	const struct gmap_unicast_ac_param param = {
1417 		.name = "ac_11_ii",
1418 		.conn_cnt = 2U,
1419 		.snk_cnt = {1U, 1U},
1420 		.src_cnt = {1U, 1U},
1421 		.snk_chan_cnt = 1U,
1422 		.snk_named_preset = snk_named_preset,
1423 		.src_named_preset = src_named_preset,
1424 	};
1425 
1426 	test_gmap_ugg_unicast_ac(&param);
1427 }
1428 
test_gmap_ac_12(void)1429 static void test_gmap_ac_12(void)
1430 {
1431 	const struct gmap_broadcast_ac_param param = {
1432 		.name = "ac_12",
1433 		.stream_cnt = 1U,
1434 		.chan_cnt = 1U,
1435 		.named_preset = broadcast_named_preset,
1436 	};
1437 
1438 	test_gmap_ugg_broadcast_ac(&param);
1439 }
1440 
1441 #if CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT >= GMAP_BROADCAST_AC_MAX_STREAM
test_gmap_ac_13(void)1442 static void test_gmap_ac_13(void)
1443 {
1444 	const struct gmap_broadcast_ac_param param = {
1445 		.name = "ac_13",
1446 		.stream_cnt = 2U,
1447 		.chan_cnt = 1U,
1448 		.named_preset = broadcast_named_preset,
1449 	};
1450 
1451 	test_gmap_ugg_broadcast_ac(&param);
1452 }
1453 #endif /* CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT >= GMAP_BROADCAST_AC_MAX_STREAM */
1454 
test_gmap_ac_14(void)1455 static void test_gmap_ac_14(void)
1456 {
1457 	const struct gmap_broadcast_ac_param param = {
1458 		.name = "ac_14",
1459 		.stream_cnt = 1U,
1460 		.chan_cnt = 2U,
1461 		.named_preset = broadcast_named_preset,
1462 	};
1463 
1464 	test_gmap_ugg_broadcast_ac(&param);
1465 }
1466 
test_args(int argc,char * argv[])1467 static void test_args(int argc, char *argv[])
1468 {
1469 	for (size_t argn = 0; argn < argc; argn++) {
1470 		const char *arg = argv[argn];
1471 
1472 		if (strcmp(arg, "sink_preset") == 0) {
1473 			const char *preset_arg = argv[++argn];
1474 
1475 			snk_named_preset =
1476 				gmap_get_named_preset(true, BT_AUDIO_DIR_SINK, preset_arg);
1477 			if (snk_named_preset == NULL) {
1478 				FAIL("Failed to get sink preset from %s\n", preset_arg);
1479 			}
1480 		} else if (strcmp(arg, "source_preset") == 0) {
1481 			const char *preset_arg = argv[++argn];
1482 
1483 			src_named_preset =
1484 				gmap_get_named_preset(true, BT_AUDIO_DIR_SOURCE, preset_arg);
1485 			if (src_named_preset == NULL) {
1486 				FAIL("Failed to get source preset from %s\n", preset_arg);
1487 			}
1488 		} else if (strcmp(arg, "broadcast_preset") == 0) {
1489 			const char *preset_arg = argv[++argn];
1490 
1491 			broadcast_named_preset = gmap_get_named_preset(
1492 				false, BT_AUDIO_DIR_SINK /* unused */, preset_arg);
1493 			if (broadcast_named_preset == NULL) {
1494 				FAIL("Failed to get broadcast preset from %s\n", preset_arg);
1495 			}
1496 		} else {
1497 			FAIL("Invalid arg: %s\n", arg);
1498 		}
1499 	}
1500 }
1501 
1502 static const struct bst_test_instance test_gmap_ugg[] = {
1503 	{
1504 		.test_id = "gmap_ugg_ac_1",
1505 		.test_pre_init_f = test_init,
1506 		.test_tick_f = test_tick,
1507 		.test_main_f = test_gmap_ac_1,
1508 		.test_args_f = test_args,
1509 	},
1510 	{
1511 		.test_id = "gmap_ugg_ac_2",
1512 		.test_pre_init_f = test_init,
1513 		.test_tick_f = test_tick,
1514 		.test_main_f = test_gmap_ac_2,
1515 		.test_args_f = test_args,
1516 	},
1517 	{
1518 		.test_id = "gmap_ugg_ac_3",
1519 		.test_pre_init_f = test_init,
1520 		.test_tick_f = test_tick,
1521 		.test_main_f = test_gmap_ac_3,
1522 		.test_args_f = test_args,
1523 	},
1524 	{
1525 		.test_id = "gmap_ugg_ac_4",
1526 		.test_pre_init_f = test_init,
1527 		.test_tick_f = test_tick,
1528 		.test_main_f = test_gmap_ac_4,
1529 		.test_args_f = test_args,
1530 	},
1531 	{
1532 		.test_id = "gmap_ugg_ac_5",
1533 		.test_pre_init_f = test_init,
1534 		.test_tick_f = test_tick,
1535 		.test_main_f = test_gmap_ac_5,
1536 		.test_args_f = test_args,
1537 	},
1538 	{
1539 		.test_id = "gmap_ugg_ac_6_i",
1540 		.test_pre_init_f = test_init,
1541 		.test_tick_f = test_tick,
1542 		.test_main_f = test_gmap_ac_6_i,
1543 		.test_args_f = test_args,
1544 	},
1545 	{
1546 		.test_id = "gmap_ugg_ac_6_ii",
1547 		.test_pre_init_f = test_init,
1548 		.test_tick_f = test_tick,
1549 		.test_main_f = test_gmap_ac_6_ii,
1550 		.test_args_f = test_args,
1551 	},
1552 	{
1553 		.test_id = "gmap_ugg_ac_7_ii",
1554 		.test_pre_init_f = test_init,
1555 		.test_tick_f = test_tick,
1556 		.test_main_f = test_gmap_ac_7_ii,
1557 		.test_args_f = test_args,
1558 	},
1559 	{
1560 		.test_id = "gmap_ugg_ac_8_i",
1561 		.test_pre_init_f = test_init,
1562 		.test_tick_f = test_tick,
1563 		.test_main_f = test_gmap_ac_8_i,
1564 		.test_args_f = test_args,
1565 	},
1566 	{
1567 		.test_id = "gmap_ugg_ac_8_ii",
1568 		.test_pre_init_f = test_init,
1569 		.test_tick_f = test_tick,
1570 		.test_main_f = test_gmap_ac_8_ii,
1571 		.test_args_f = test_args,
1572 	},
1573 	{
1574 		.test_id = "gmap_ugg_ac_11_i",
1575 		.test_pre_init_f = test_init,
1576 		.test_tick_f = test_tick,
1577 		.test_main_f = test_gmap_ac_11_i,
1578 		.test_args_f = test_args,
1579 	},
1580 	{
1581 		.test_id = "gmap_ugg_ac_11_ii",
1582 		.test_pre_init_f = test_init,
1583 		.test_tick_f = test_tick,
1584 		.test_main_f = test_gmap_ac_11_ii,
1585 		.test_args_f = test_args,
1586 	},
1587 	{
1588 		.test_id = "gmap_ugg_ac_12",
1589 		.test_pre_init_f = test_init,
1590 		.test_tick_f = test_tick,
1591 		.test_main_f = test_gmap_ac_12,
1592 		.test_args_f = test_args,
1593 	},
1594 #if CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT >= GMAP_BROADCAST_AC_MAX_STREAM
1595 	{
1596 		.test_id = "gmap_ugg_ac_13",
1597 		.test_pre_init_f = test_init,
1598 		.test_tick_f = test_tick,
1599 		.test_main_f = test_gmap_ac_13,
1600 		.test_args_f = test_args,
1601 	},
1602 #endif /* CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT >= GMAP_BROADCAST_AC_MAX_STREAM */
1603 	{
1604 		.test_id = "gmap_ugg_ac_14",
1605 		.test_pre_init_f = test_init,
1606 		.test_tick_f = test_tick,
1607 		.test_main_f = test_gmap_ac_14,
1608 		.test_args_f = test_args,
1609 	},
1610 	BSTEST_END_MARKER,
1611 };
1612 
test_gmap_ugg_install(struct bst_test_list * tests)1613 struct bst_test_list *test_gmap_ugg_install(struct bst_test_list *tests)
1614 {
1615 	return bst_add_tests(tests, test_gmap_ugg);
1616 }
1617 
1618 #else /* !(CONFIG_BT_GMAP) */
1619 
test_gmap_ugg_install(struct bst_test_list * tests)1620 struct bst_test_list *test_gmap_ugg_install(struct bst_test_list *tests)
1621 {
1622 	return tests;
1623 }
1624 
1625 #endif /* CONFIG_BT_GMAP */
1626