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