1 /*
2  * Copyright (c) 2021-2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <errno.h>
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h>
11 
12 #include <zephyr/autoconf.h>
13 #include <zephyr/bluetooth/addr.h>
14 #include <zephyr/bluetooth/audio/audio.h>
15 #include <zephyr/bluetooth/audio/bap.h>
16 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
17 #include <zephyr/bluetooth/audio/pacs.h>
18 #include <zephyr/bluetooth/bluetooth.h>
19 #include <zephyr/bluetooth/conn.h>
20 #include <zephyr/bluetooth/gap.h>
21 #include <zephyr/bluetooth/gatt.h>
22 #include <zephyr/bluetooth/hci_types.h>
23 #include <zephyr/bluetooth/iso.h>
24 #include <zephyr/bluetooth/uuid.h>
25 #include <zephyr/kernel.h>
26 #include <zephyr/net_buf.h>
27 #include <zephyr/sys/atomic.h>
28 #include <zephyr/sys/atomic_types.h>
29 #include <zephyr/sys/printk.h>
30 #include <zephyr/sys/util.h>
31 
32 #include "bap_stream_rx.h"
33 #include "bap_stream_tx.h"
34 #include "bstests.h"
35 #include "common.h"
36 #include "bap_common.h"
37 
38 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
39 
40 extern enum bst_result_t bst_result;
41 
42 static struct audio_test_stream test_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
43 static struct bt_bap_ep *g_sinks[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
44 static struct bt_bap_ep *g_sources[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
45 
46 static struct bt_bap_unicast_group_stream_pair_param pair_params[ARRAY_SIZE(test_streams)];
47 static struct bt_bap_unicast_group_stream_param stream_params[ARRAY_SIZE(test_streams)];
48 
49 /*Mandatory support preset by both client and server */
50 static struct bt_bap_lc3_preset preset_16_2_1 = BT_BAP_LC3_UNICAST_PRESET_16_2_1(
51 	BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
52 
53 CREATE_FLAG(flag_mtu_exchanged);
54 CREATE_FLAG(flag_sink_discovered);
55 CREATE_FLAG(flag_source_discovered);
56 CREATE_FLAG(flag_codec_cap_found);
57 CREATE_FLAG(flag_endpoint_found);
58 CREATE_FLAG(flag_stream_codec_configured);
59 static atomic_t flag_stream_qos_configured;
60 CREATE_FLAG(flag_stream_enabled);
61 CREATE_FLAG(flag_stream_metadata);
62 CREATE_FLAG(flag_stream_started);
63 CREATE_FLAG(flag_stream_connected);
64 CREATE_FLAG(flag_stream_disconnected);
65 CREATE_FLAG(flag_stream_disabled);
66 CREATE_FLAG(flag_stream_stopped);
67 CREATE_FLAG(flag_stream_released);
68 CREATE_FLAG(flag_operation_success);
69 
stream_configured(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg_pref * pref)70 static void stream_configured(struct bt_bap_stream *stream, const struct bt_bap_qos_cfg_pref *pref)
71 {
72 	printk("Configured stream %p\n", stream);
73 
74 	/* TODO: The preference should be used/taken into account when
75 	 * setting the QoS
76 	 */
77 
78 	SET_FLAG(flag_stream_codec_configured);
79 }
80 
stream_qos_set(struct bt_bap_stream * stream)81 static void stream_qos_set(struct bt_bap_stream *stream)
82 {
83 	struct audio_test_stream *test_stream = audio_test_stream_from_bap_stream(stream);
84 
85 	printk("QoS set stream %p\n", stream);
86 
87 	test_stream->tx_sdu_size = stream->qos->sdu;
88 
89 	atomic_inc(&flag_stream_qos_configured);
90 }
91 
stream_enabled(struct bt_bap_stream * stream)92 static void stream_enabled(struct bt_bap_stream *stream)
93 {
94 	printk("Enabled stream %p\n", stream);
95 
96 	SET_FLAG(flag_stream_enabled);
97 }
98 
stream_started(struct bt_bap_stream * stream)99 static void stream_started(struct bt_bap_stream *stream)
100 {
101 	printk("Started stream %p\n", stream);
102 
103 	if (bap_stream_tx_can_send(stream)) {
104 		int err;
105 
106 		err = bap_stream_tx_register(stream);
107 		if (err != 0) {
108 			FAIL("Failed to register stream %p for TX: %d\n", stream, err);
109 			return;
110 		}
111 	}
112 
113 	SET_FLAG(flag_stream_started);
114 }
115 
stream_connected(struct bt_bap_stream * stream)116 static void stream_connected(struct bt_bap_stream *stream)
117 {
118 	printk("Connected stream %p\n", stream);
119 
120 	SET_FLAG(flag_stream_connected);
121 }
122 
stream_disconnected(struct bt_bap_stream * stream,uint8_t reason)123 static void stream_disconnected(struct bt_bap_stream *stream, uint8_t reason)
124 {
125 	printk("Disconnected stream %p with reason %u\n", stream, reason);
126 
127 	SET_FLAG(flag_stream_disconnected);
128 }
129 
stream_metadata_updated(struct bt_bap_stream * stream)130 static void stream_metadata_updated(struct bt_bap_stream *stream)
131 {
132 	printk("Metadata updated stream %p\n", stream);
133 
134 	SET_FLAG(flag_stream_metadata);
135 }
136 
stream_disabled(struct bt_bap_stream * stream)137 static void stream_disabled(struct bt_bap_stream *stream)
138 {
139 	printk("Disabled stream %p\n", stream);
140 
141 	SET_FLAG(flag_stream_disabled);
142 }
143 
stream_stopped(struct bt_bap_stream * stream,uint8_t reason)144 static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason)
145 {
146 	printk("Stopped stream %p with reason 0x%02X\n", stream, reason);
147 
148 	if (bap_stream_tx_can_send(stream)) {
149 		int err;
150 
151 		err = bap_stream_tx_unregister(stream);
152 		if (err != 0) {
153 			FAIL("Failed to unregister stream %p for TX: %d\n", stream, err);
154 			return;
155 		}
156 	}
157 
158 	SET_FLAG(flag_stream_stopped);
159 }
160 
stream_released(struct bt_bap_stream * stream)161 static void stream_released(struct bt_bap_stream *stream)
162 {
163 	printk("Released stream %p\n", stream);
164 
165 	SET_FLAG(flag_stream_released);
166 }
167 
168 static struct bt_bap_stream_ops stream_ops = {
169 	.configured = stream_configured,
170 	.qos_set = stream_qos_set,
171 	.enabled = stream_enabled,
172 	.started = stream_started,
173 	.metadata_updated = stream_metadata_updated,
174 	.disabled = stream_disabled,
175 	.stopped = stream_stopped,
176 	.released = stream_released,
177 	.recv = bap_stream_rx_recv_cb,
178 	.sent = bap_stream_tx_sent_cb,
179 	.connected = stream_connected,
180 	.disconnected = stream_disconnected,
181 };
182 
unicast_client_location_cb(struct bt_conn * conn,enum bt_audio_dir dir,enum bt_audio_location loc)183 static void unicast_client_location_cb(struct bt_conn *conn,
184 				       enum bt_audio_dir dir,
185 				       enum bt_audio_location loc)
186 {
187 	printk("dir %u loc %X\n", dir, loc);
188 }
189 
available_contexts_cb(struct bt_conn * conn,enum bt_audio_context snk_ctx,enum bt_audio_context src_ctx)190 static void available_contexts_cb(struct bt_conn *conn,
191 				  enum bt_audio_context snk_ctx,
192 				  enum bt_audio_context src_ctx)
193 {
194 	printk("snk ctx %u src ctx %u\n", snk_ctx, src_ctx);
195 }
196 
197 
config_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)198 static void config_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
199 		      enum bt_bap_ascs_reason reason)
200 {
201 	printk("stream %p config operation rsp_code %u reason %u\n", stream, rsp_code, reason);
202 
203 	if (rsp_code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
204 		SET_FLAG(flag_operation_success);
205 	}
206 }
207 
qos_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)208 static void qos_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
209 		   enum bt_bap_ascs_reason reason)
210 {
211 	printk("stream %p qos operation rsp_code %u reason %u\n", stream, rsp_code, reason);
212 
213 	if (rsp_code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
214 		SET_FLAG(flag_operation_success);
215 	}
216 }
217 
enable_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)218 static void enable_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
219 		      enum bt_bap_ascs_reason reason)
220 {
221 	printk("stream %p enable operation rsp_code %u reason %u\n", stream, rsp_code, reason);
222 
223 	if (rsp_code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
224 		SET_FLAG(flag_operation_success);
225 	}
226 }
227 
start_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)228 static void start_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
229 		     enum bt_bap_ascs_reason reason)
230 {
231 	printk("stream %p start operation rsp_code %u reason %u\n", stream, rsp_code, reason);
232 
233 	if (rsp_code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
234 		SET_FLAG(flag_operation_success);
235 	}
236 }
237 
stop_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)238 static void stop_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
239 		    enum bt_bap_ascs_reason reason)
240 {
241 	printk("stream %p stop operation rsp_code %u reason %u\n", stream, rsp_code, reason);
242 
243 	if (rsp_code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
244 		SET_FLAG(flag_operation_success);
245 	}
246 }
247 
disable_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)248 static void disable_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
249 		       enum bt_bap_ascs_reason reason)
250 {
251 	printk("stream %p disable operation rsp_code %u reason %u\n", stream, rsp_code, reason);
252 
253 	if (rsp_code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
254 		SET_FLAG(flag_operation_success);
255 	}
256 }
257 
metadata_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)258 static void metadata_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
259 			enum bt_bap_ascs_reason reason)
260 {
261 	printk("stream %p metadata operation rsp_code %u reason %u\n", stream, rsp_code, reason);
262 
263 	if (rsp_code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
264 		SET_FLAG(flag_operation_success);
265 	}
266 }
267 
release_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)268 static void release_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
269 		       enum bt_bap_ascs_reason reason)
270 {
271 	printk("stream %p release operation rsp_code %u reason %u\n", stream, rsp_code, reason);
272 
273 	if (rsp_code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
274 		SET_FLAG(flag_operation_success);
275 	}
276 }
277 
add_remote_sink(struct bt_bap_ep * ep)278 static void add_remote_sink(struct bt_bap_ep *ep)
279 {
280 	for (size_t i = 0U; i < ARRAY_SIZE(g_sinks); i++) {
281 		if (g_sinks[i] == NULL) {
282 			printk("Sink #%zu: ep %p\n", i, ep);
283 			g_sinks[i] = ep;
284 			return;
285 		}
286 	}
287 
288 	FAIL("Could not add sink ep\n");
289 }
290 
add_remote_source(struct bt_bap_ep * ep)291 static void add_remote_source(struct bt_bap_ep *ep)
292 {
293 	for (size_t i = 0U; i < ARRAY_SIZE(g_sources); i++) {
294 		if (g_sources[i] == NULL) {
295 			printk("Source #%u: ep %p\n", i, ep);
296 			g_sources[i] = ep;
297 			return;
298 		}
299 	}
300 
301 	FAIL("Could not add source ep\n");
302 }
303 
print_remote_codec_cap(const struct bt_audio_codec_cap * codec_cap,enum bt_audio_dir dir)304 static void print_remote_codec_cap(const struct bt_audio_codec_cap *codec_cap,
305 				   enum bt_audio_dir dir)
306 {
307 	printk("codec %p dir 0x%02x\n", codec_cap, dir);
308 
309 	print_codec_cap(codec_cap);
310 }
311 
discover_sinks_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)312 static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
313 {
314 	if (err != 0) {
315 		FAIL("Discovery failed: %d\n", err);
316 		return;
317 	}
318 
319 	printk("Discover complete\n");
320 
321 	SET_FLAG(flag_sink_discovered);
322 }
323 
discover_sources_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)324 static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
325 {
326 	if (err != 0) {
327 		FAIL("Discovery failed: %d\n", err);
328 		return;
329 	}
330 
331 	printk("Sources discover complete\n");
332 
333 	SET_FLAG(flag_source_discovered);
334 }
335 
pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_audio_codec_cap * codec_cap)336 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir,
337 			  const struct bt_audio_codec_cap *codec_cap)
338 {
339 	print_remote_codec_cap(codec_cap, dir);
340 	SET_FLAG(flag_codec_cap_found);
341 }
342 
endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)343 static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
344 {
345 	if (dir == BT_AUDIO_DIR_SINK) {
346 		add_remote_sink(ep);
347 	} else {
348 		add_remote_source(ep);
349 	}
350 
351 	SET_FLAG(flag_endpoint_found);
352 }
353 
354 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
355 	.location = unicast_client_location_cb,
356 	.available_contexts = available_contexts_cb,
357 	.config = config_cb,
358 	.qos = qos_cb,
359 	.enable = enable_cb,
360 	.start = start_cb,
361 	.stop = stop_cb,
362 	.disable = disable_cb,
363 	.metadata = metadata_cb,
364 	.release = release_cb,
365 	.pac_record = pac_record_cb,
366 	.endpoint = endpoint_cb,
367 };
368 
att_mtu_updated(struct bt_conn * conn,uint16_t tx,uint16_t rx)369 static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
370 {
371 	printk("MTU exchanged\n");
372 	SET_FLAG(flag_mtu_exchanged);
373 }
374 
375 static struct bt_gatt_cb gatt_callbacks = {
376 	.att_mtu_updated = att_mtu_updated,
377 };
378 
parse_ascs_ad_data(struct bt_data * data,void * user_data)379 static bool parse_ascs_ad_data(struct bt_data *data, void *user_data)
380 {
381 	const struct bt_le_scan_recv_info *info = user_data;
382 	uint16_t available_source_context;
383 	uint16_t available_sink_context;
384 	struct net_buf_simple net_buf;
385 	struct bt_uuid_16 adv_uuid;
386 	uint8_t announcement_type;
387 	void *uuid;
388 	int err;
389 
390 	const size_t min_data_len = BT_UUID_SIZE_16 + sizeof(announcement_type) +
391 				    sizeof(available_sink_context) +
392 				    sizeof(available_source_context);
393 
394 	if (data->type != BT_DATA_SVC_DATA16) {
395 		return true;
396 	}
397 
398 	if (data->data_len < min_data_len) {
399 
400 		return true;
401 	}
402 
403 	net_buf_simple_init_with_data(&net_buf, (void *)data->data, data->data_len);
404 
405 	uuid = net_buf_simple_pull_mem(&net_buf, BT_UUID_SIZE_16);
406 	if (!bt_uuid_create(&adv_uuid.uuid, uuid, BT_UUID_SIZE_16)) {
407 		return true;
408 	}
409 
410 	if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_ASCS)) {
411 		return true;
412 	}
413 
414 	announcement_type = net_buf_simple_pull_u8(&net_buf);
415 	available_sink_context = net_buf_simple_pull_le16(&net_buf);
416 	available_source_context = net_buf_simple_pull_le16(&net_buf);
417 
418 	printk("Found ASCS with announcement type 0x%02X, sink ctx 0x%04X, source ctx 0x%04X\n",
419 	       announcement_type, available_sink_context, available_source_context);
420 
421 	printk("Stopping scan\n");
422 	if (bt_le_scan_stop()) {
423 		FAIL("Could not stop scan");
424 		return false;
425 	}
426 
427 	err = bt_conn_le_create(info->addr, BT_CONN_LE_CREATE_CONN, BT_BAP_CONN_PARAM_RELAXED,
428 				&default_conn);
429 	if (err) {
430 		FAIL("Could not connect to peer: %d", err);
431 		return false;
432 	}
433 
434 	/* Stop parsing */
435 	return false;
436 }
437 
broadcast_scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * ad)438 static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad)
439 {
440 	char addr_str[BT_ADDR_LE_STR_LEN];
441 
442 	if (default_conn) {
443 		return;
444 	}
445 
446 	/* We're only interested in connectable events */
447 	if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) == 0) {
448 		return;
449 	}
450 	/* connect only to devices in close proximity */
451 	if (info->rssi < -70) {
452 		return;
453 	}
454 
455 	bt_addr_le_to_str(info->addr, addr_str, sizeof(addr_str));
456 	printk("Device found: %s (RSSI %d)\n", addr_str, info->rssi);
457 
458 	bt_data_parse(ad, parse_ascs_ad_data, (void *)info);
459 }
460 
461 static struct bt_le_scan_cb bap_scan_cb = {
462 	.recv = broadcast_scan_recv,
463 };
464 
init(void)465 static void init(void)
466 {
467 	int err;
468 
469 	err = bt_enable(NULL);
470 	if (err != 0) {
471 		FAIL("Bluetooth enable failed (err %d)\n", err);
472 		return;
473 	}
474 
475 	printk("Bluetooth initialized\n");
476 	bap_stream_tx_init();
477 
478 	for (size_t i = 0; i < ARRAY_SIZE(test_streams); i++) {
479 		struct bt_bap_stream *bap_stream =
480 			bap_stream_from_audio_test_stream(&test_streams[i]);
481 
482 		bap_stream->ops = &stream_ops;
483 	}
484 
485 	bt_le_scan_cb_register(&bap_scan_cb);
486 	bt_gatt_cb_register(&gatt_callbacks);
487 
488 	err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
489 	if (err != 0) {
490 		FAIL("Failed to register client callbacks: %d", err);
491 		return;
492 	}
493 }
494 
scan_and_connect(void)495 static void scan_and_connect(void)
496 {
497 	int err;
498 
499 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
500 	if (err != 0) {
501 		FAIL("Scanning failed to start (err %d)\n", err);
502 		return;
503 	}
504 
505 	printk("Scanning successfully started\n");
506 	WAIT_FOR_FLAG(flag_connected);
507 }
508 
disconnect_acl(void)509 static void disconnect_acl(void)
510 {
511 	int err;
512 
513 	err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
514 	if (err != 0) {
515 		FAIL("Failed to disconnect (err %d)\n", err);
516 		return;
517 	}
518 
519 	WAIT_FOR_UNSET_FLAG(flag_connected);
520 }
521 
exchange_mtu(void)522 static void exchange_mtu(void)
523 {
524 	WAIT_FOR_FLAG(flag_mtu_exchanged);
525 }
526 
discover_sinks(void)527 static void discover_sinks(void)
528 {
529 	int err;
530 
531 	unicast_client_cbs.discover = discover_sinks_cb;
532 
533 	UNSET_FLAG(flag_codec_cap_found);
534 	UNSET_FLAG(flag_sink_discovered);
535 	UNSET_FLAG(flag_endpoint_found);
536 
537 	err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SINK);
538 	if (err != 0) {
539 		printk("Failed to discover sink: %d\n", err);
540 		return;
541 	}
542 
543 	memset(g_sinks, 0, sizeof(g_sinks));
544 
545 	WAIT_FOR_FLAG(flag_codec_cap_found);
546 	WAIT_FOR_FLAG(flag_endpoint_found);
547 	WAIT_FOR_FLAG(flag_sink_discovered);
548 }
549 
discover_sources(void)550 static void discover_sources(void)
551 {
552 	int err;
553 
554 	unicast_client_cbs.discover = discover_sources_cb;
555 
556 	UNSET_FLAG(flag_codec_cap_found);
557 	UNSET_FLAG(flag_source_discovered);
558 
559 	err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SOURCE);
560 	if (err != 0) {
561 		printk("Failed to discover sink: %d\n", err);
562 		return;
563 	}
564 
565 	memset(g_sources, 0, sizeof(g_sources));
566 
567 	WAIT_FOR_FLAG(flag_codec_cap_found);
568 	WAIT_FOR_FLAG(flag_source_discovered);
569 }
570 
codec_configure_stream(struct bt_bap_stream * stream,struct bt_bap_ep * ep,struct bt_audio_codec_cfg * codec_cfg)571 static int codec_configure_stream(struct bt_bap_stream *stream, struct bt_bap_ep *ep,
572 				  struct bt_audio_codec_cfg *codec_cfg)
573 {
574 	int err;
575 
576 	UNSET_FLAG(flag_stream_codec_configured);
577 	UNSET_FLAG(flag_operation_success);
578 
579 	do {
580 
581 		err = bt_bap_stream_config(default_conn, stream, ep, codec_cfg);
582 		if (err == -EBUSY) {
583 			k_sleep(BAP_RETRY_WAIT);
584 		} else if (err != 0) {
585 			FAIL("Could not configure stream %p: %d\n", stream, err);
586 			return err;
587 		}
588 	} while (err == -EBUSY);
589 
590 	WAIT_FOR_FLAG(flag_stream_codec_configured);
591 	WAIT_FOR_FLAG(flag_operation_success);
592 
593 	return 0;
594 }
595 
codec_configure_streams(size_t stream_cnt)596 static void codec_configure_streams(size_t stream_cnt)
597 {
598 	for (size_t i = 0U; i < ARRAY_SIZE(pair_params); i++) {
599 		if (pair_params[i].rx_param != NULL && g_sources[i] != NULL) {
600 			struct bt_bap_stream *stream = pair_params[i].rx_param->stream;
601 			const int err = codec_configure_stream(stream, g_sources[i],
602 							       &preset_16_2_1.codec_cfg);
603 
604 			if (err != 0) {
605 				FAIL("Unable to configure source stream[%zu]: %d", i, err);
606 				return;
607 			}
608 		}
609 
610 		if (pair_params[i].tx_param != NULL && g_sinks[i] != NULL) {
611 			struct bt_bap_stream *stream = pair_params[i].tx_param->stream;
612 			const int err = codec_configure_stream(stream, g_sinks[i],
613 							       &preset_16_2_1.codec_cfg);
614 
615 			if (err != 0) {
616 				FAIL("Unable to configure sink stream[%zu]: %d", i, err);
617 				return;
618 			}
619 		}
620 	}
621 }
622 
qos_configure_streams(struct bt_bap_unicast_group * unicast_group,size_t stream_cnt)623 static void qos_configure_streams(struct bt_bap_unicast_group *unicast_group,
624 				  size_t stream_cnt)
625 {
626 	int err;
627 
628 	UNSET_FLAG(flag_stream_qos_configured);
629 
630 	do {
631 		err = bt_bap_stream_qos(default_conn, unicast_group);
632 		if (err == -EBUSY) {
633 			k_sleep(BAP_RETRY_WAIT);
634 		} else if (err != 0) {
635 			FAIL("Unable to QoS configure streams: %d\n", err);
636 			return;
637 		}
638 	} while (err == -EBUSY);
639 
640 	while (atomic_get(&flag_stream_qos_configured) != stream_cnt) {
641 		(void)k_sleep(K_MSEC(1));
642 	}
643 }
644 
enable_stream(struct bt_bap_stream * stream)645 static int enable_stream(struct bt_bap_stream *stream)
646 {
647 	int err;
648 
649 	UNSET_FLAG(flag_stream_enabled);
650 
651 	do {
652 		err = bt_bap_stream_enable(stream, NULL, 0);
653 		if (err == -EBUSY) {
654 			k_sleep(BAP_RETRY_WAIT);
655 		} else if (err != 0) {
656 			FAIL("Could not enable stream %p: %d\n", stream, err);
657 			return err;
658 		}
659 	} while (err == -EBUSY);
660 
661 	WAIT_FOR_FLAG(flag_stream_enabled);
662 
663 	return 0;
664 }
665 
enable_streams(size_t stream_cnt)666 static void enable_streams(size_t stream_cnt)
667 {
668 	for (size_t i = 0U; i < stream_cnt; i++) {
669 		struct bt_bap_stream *stream = bap_stream_from_audio_test_stream(&test_streams[i]);
670 		int err;
671 
672 		err = enable_stream(stream);
673 		if (err != 0) {
674 			FAIL("Unable to enable stream[%zu]: %d", i, err);
675 
676 			return;
677 		}
678 	}
679 }
680 
metadata_update_stream(struct bt_bap_stream * stream)681 static int metadata_update_stream(struct bt_bap_stream *stream)
682 {
683 	const uint8_t new_meta[] = {
684 		BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_VENDOR, LONG_META),
685 	};
686 	int err;
687 
688 	UNSET_FLAG(flag_stream_metadata);
689 
690 	do {
691 		err = bt_bap_stream_metadata(stream, new_meta, ARRAY_SIZE(new_meta));
692 		if (err == -EBUSY) {
693 			k_sleep(BAP_RETRY_WAIT);
694 		} else if (err != 0) {
695 			FAIL("Could not metadata update stream %p: %d\n", stream, err);
696 			return err;
697 		}
698 	} while (err == -EBUSY);
699 
700 	WAIT_FOR_FLAG(flag_stream_metadata);
701 
702 	return 0;
703 }
704 
metadata_update_streams(size_t stream_cnt)705 static void metadata_update_streams(size_t stream_cnt)
706 {
707 	for (size_t i = 0U; i < stream_cnt; i++) {
708 		struct bt_bap_stream *stream = bap_stream_from_audio_test_stream(&test_streams[i]);
709 		int err;
710 
711 		err = metadata_update_stream(stream);
712 		if (err != 0) {
713 			FAIL("Unable to metadata update stream[%zu]: %d", i, err);
714 
715 			return;
716 		}
717 	}
718 }
719 
connect_stream(struct bt_bap_stream * stream)720 static int connect_stream(struct bt_bap_stream *stream)
721 {
722 	int err;
723 
724 	UNSET_FLAG(flag_stream_started);
725 
726 	do {
727 		err = bt_bap_stream_connect(stream);
728 		if (err == -EALREADY) {
729 			SET_FLAG(flag_stream_started);
730 		} else if (err != 0) {
731 			FAIL("Could not start stream %p: %d\n", stream, err);
732 			return err;
733 		}
734 	} while (err == -EBUSY);
735 
736 	WAIT_FOR_FLAG(flag_stream_started);
737 
738 	return 0;
739 }
740 
connect_streams(void)741 static void connect_streams(void)
742 {
743 	struct bt_bap_stream *source_stream;
744 	struct bt_bap_stream *sink_stream;
745 
746 	/* We only support a single CIS so far, so only start one. We can use the group pair
747 	 * params to start both a sink and source stream that use the same CIS
748 	 */
749 
750 	source_stream = pair_params[0].rx_param == NULL ? NULL : pair_params[0].rx_param->stream;
751 	sink_stream = pair_params[0].tx_param == NULL ? NULL : pair_params[0].tx_param->stream;
752 
753 	UNSET_FLAG(flag_stream_connected);
754 
755 	if (sink_stream != NULL) {
756 		const int err = connect_stream(sink_stream);
757 
758 		if (err != 0) {
759 			FAIL("Unable to connect sink: %d", err);
760 
761 			return;
762 		}
763 	}
764 
765 	if (source_stream != NULL) {
766 		const int err = connect_stream(source_stream);
767 
768 		if (err != 0) {
769 			FAIL("Unable to connect source stream: %d", err);
770 
771 			return;
772 		}
773 	}
774 
775 	WAIT_FOR_FLAG(flag_stream_connected);
776 }
777 
start_stream(struct bt_bap_stream * stream)778 static int start_stream(struct bt_bap_stream *stream)
779 {
780 	int err;
781 
782 	UNSET_FLAG(flag_stream_started);
783 
784 	do {
785 		err = bt_bap_stream_start(stream);
786 		if (err == -EBUSY) {
787 			k_sleep(BAP_RETRY_WAIT);
788 		} else if (err != 0) {
789 			FAIL("Could not start stream %p: %d\n", stream, err);
790 			return err;
791 		}
792 	} while (err == -EBUSY);
793 
794 	WAIT_FOR_FLAG(flag_stream_started);
795 
796 	return 0;
797 }
798 
start_streams(void)799 static void start_streams(void)
800 {
801 	struct bt_bap_stream *source_stream;
802 
803 	source_stream = pair_params[0].rx_param == NULL ? NULL : pair_params[0].rx_param->stream;
804 
805 	if (source_stream != NULL) {
806 		const int err = start_stream(source_stream);
807 
808 		if (err != 0) {
809 			FAIL("Unable to start source stream: %d", err);
810 
811 			return;
812 		}
813 	}
814 }
815 
transceive_streams(void)816 static void transceive_streams(void)
817 {
818 	struct bt_bap_stream *source_stream;
819 	struct bt_bap_stream *sink_stream;
820 
821 	source_stream = pair_params[0].rx_param == NULL ? NULL : pair_params[0].rx_param->stream;
822 	sink_stream = pair_params[0].tx_param == NULL ? NULL : pair_params[0].tx_param->stream;
823 
824 	if (sink_stream != NULL) {
825 		struct audio_test_stream *test_stream =
826 			audio_test_stream_from_bap_stream(sink_stream);
827 
828 		/* Keep sending until we reach the minimum expected */
829 		while (test_stream->tx_cnt < MIN_SEND_COUNT) {
830 			k_sleep(K_MSEC(100));
831 		}
832 	}
833 
834 	if (source_stream != NULL) {
835 		printk("Waiting for data\n");
836 		WAIT_FOR_FLAG(flag_audio_received);
837 	}
838 }
839 
disable_streams(size_t stream_cnt)840 static void disable_streams(size_t stream_cnt)
841 {
842 	for (size_t i = 0; i < stream_cnt; i++) {
843 		int err;
844 
845 		UNSET_FLAG(flag_operation_success);
846 		UNSET_FLAG(flag_stream_disabled);
847 
848 		do {
849 			err = bt_bap_stream_disable(
850 				bap_stream_from_audio_test_stream(&test_streams[i]));
851 			if (err == -EBUSY) {
852 				k_sleep(BAP_RETRY_WAIT);
853 			} else if (err != 0) {
854 				FAIL("Could not disable stream: %d\n", err);
855 				return;
856 			}
857 		} while (err == -EBUSY);
858 
859 		WAIT_FOR_FLAG(flag_operation_success);
860 		WAIT_FOR_FLAG(flag_stream_disabled);
861 	}
862 }
863 
stop_streams(size_t stream_cnt)864 static void stop_streams(size_t stream_cnt)
865 {
866 	UNSET_FLAG(flag_stream_disconnected);
867 
868 	for (size_t i = 0; i < stream_cnt; i++) {
869 		struct bt_bap_stream *source_stream;
870 		int err;
871 
872 		/* We can only stop source streams */
873 		source_stream =
874 			pair_params[i].rx_param == NULL ? NULL : pair_params[i].rx_param->stream;
875 
876 		if (source_stream == NULL) {
877 			continue;
878 		}
879 
880 		UNSET_FLAG(flag_operation_success);
881 		UNSET_FLAG(flag_stream_stopped);
882 
883 		do {
884 			err = bt_bap_stream_stop(source_stream);
885 			if (err == -EBUSY) {
886 				k_sleep(BAP_RETRY_WAIT);
887 			} else if (err != 0) {
888 				FAIL("Could not stop stream: %d\n", err);
889 				return;
890 			}
891 		} while (err == -EBUSY);
892 
893 		WAIT_FOR_FLAG(flag_operation_success);
894 		WAIT_FOR_FLAG(flag_stream_stopped);
895 	}
896 
897 	WAIT_FOR_FLAG(flag_stream_disconnected);
898 }
899 
release_streams(size_t stream_cnt)900 static void release_streams(size_t stream_cnt)
901 {
902 	for (size_t i = 0; i < stream_cnt; i++) {
903 		int err;
904 
905 		UNSET_FLAG(flag_operation_success);
906 		UNSET_FLAG(flag_stream_released);
907 
908 		do {
909 			err = bt_bap_stream_release(
910 				bap_stream_from_audio_test_stream(&test_streams[i]));
911 			if (err == -EBUSY) {
912 				k_sleep(BAP_RETRY_WAIT);
913 			} else if (err != 0) {
914 				FAIL("Could not release stream: %d\n", err);
915 				return;
916 			}
917 		} while (err == -EBUSY);
918 
919 		WAIT_FOR_FLAG(flag_operation_success);
920 		WAIT_FOR_FLAG(flag_stream_released);
921 	}
922 }
923 
create_unicast_group(struct bt_bap_unicast_group ** unicast_group)924 static size_t create_unicast_group(struct bt_bap_unicast_group **unicast_group)
925 {
926 	struct bt_bap_unicast_group_param param;
927 	size_t stream_cnt = 0;
928 	size_t pair_cnt = 0;
929 	int err;
930 
931 	memset(stream_params, 0, sizeof(stream_params));
932 	memset(pair_params, 0, sizeof(pair_params));
933 
934 	for (size_t i = 0U; i < MIN(ARRAY_SIZE(g_sinks), ARRAY_SIZE(test_streams)); i++) {
935 		if (g_sinks[i] == NULL) {
936 			break;
937 		}
938 
939 		stream_params[stream_cnt].stream =
940 			bap_stream_from_audio_test_stream(&test_streams[stream_cnt]);
941 		stream_params[stream_cnt].qos = &preset_16_2_1.qos;
942 		pair_params[i].tx_param = &stream_params[stream_cnt];
943 
944 		stream_cnt++;
945 
946 		break;
947 	}
948 
949 	for (size_t i = 0U; i < MIN(ARRAY_SIZE(g_sources), ARRAY_SIZE(test_streams)); i++) {
950 		if (g_sources[i] == NULL) {
951 			break;
952 		}
953 
954 		stream_params[stream_cnt].stream =
955 			bap_stream_from_audio_test_stream(&test_streams[stream_cnt]);
956 		stream_params[stream_cnt].qos = &preset_16_2_1.qos;
957 		pair_params[i].rx_param = &stream_params[stream_cnt];
958 
959 		stream_cnt++;
960 
961 		break;
962 	}
963 
964 	for (pair_cnt = 0U; pair_cnt < ARRAY_SIZE(pair_params); pair_cnt++) {
965 		if (pair_params[pair_cnt].rx_param == NULL &&
966 		    pair_params[pair_cnt].tx_param == NULL) {
967 			break;
968 		}
969 	}
970 
971 	if (stream_cnt == 0U) {
972 		FAIL("No streams added to group");
973 
974 		return 0;
975 	}
976 
977 	param.params = pair_params;
978 	param.params_count = pair_cnt;
979 	param.packing = BT_ISO_PACKING_SEQUENTIAL;
980 
981 	/* Require controller support for CIGs */
982 	err = bt_bap_unicast_group_create(&param, unicast_group);
983 	if (err != 0) {
984 		FAIL("Unable to create unicast group: %d", err);
985 
986 		return 0;
987 	}
988 
989 	return stream_cnt;
990 }
991 
delete_unicast_group(struct bt_bap_unicast_group * unicast_group)992 static void delete_unicast_group(struct bt_bap_unicast_group *unicast_group)
993 {
994 	int err;
995 
996 	/* Require controller support for CIGs */
997 	err = bt_bap_unicast_group_delete(unicast_group);
998 	if (err != 0) {
999 		FAIL("Unable to delete unicast group: %d", err);
1000 		return;
1001 	}
1002 }
1003 
test_main(void)1004 static void test_main(void)
1005 {
1006 	/* TODO: Temporarily reduce to 1 due to bug in controller. Set to > 1 value again when
1007 	 * https://github.com/zephyrproject-rtos/zephyr/issues/57904 has been resolved.
1008 	 */
1009 	const unsigned int iterations = 1;
1010 
1011 	init();
1012 
1013 	scan_and_connect();
1014 
1015 	exchange_mtu();
1016 
1017 	discover_sinks();
1018 	discover_sinks(); /* test that we can discover twice */
1019 
1020 	discover_sources();
1021 	discover_sources(); /* test that we can discover twice */
1022 
1023 	/* Run the stream setup multiple time to ensure states are properly
1024 	 * set and reset
1025 	 */
1026 	for (unsigned int i = 0U; i < iterations; i++) {
1027 		struct bt_bap_unicast_group *unicast_group;
1028 		size_t stream_cnt;
1029 
1030 		printk("\n########### Running iteration #%u\n\n", i);
1031 
1032 		printk("Creating unicast group\n");
1033 		stream_cnt = create_unicast_group(&unicast_group);
1034 
1035 		printk("Codec configuring streams\n");
1036 		codec_configure_streams(stream_cnt);
1037 
1038 		printk("QoS configuring streams\n");
1039 		qos_configure_streams(unicast_group, stream_cnt);
1040 
1041 		printk("Enabling streams\n");
1042 		enable_streams(stream_cnt);
1043 
1044 		printk("Metadata update streams\n");
1045 		metadata_update_streams(stream_cnt);
1046 
1047 		printk("Connecting streams\n");
1048 		connect_streams();
1049 
1050 		printk("Starting streams\n");
1051 		start_streams();
1052 
1053 		printk("Starting transceiving\n");
1054 		transceive_streams();
1055 
1056 		printk("Disabling streams\n");
1057 		disable_streams(stream_cnt);
1058 
1059 		printk("Stopping streams\n");
1060 		stop_streams(stream_cnt);
1061 
1062 		printk("Releasing streams\n");
1063 		release_streams(stream_cnt);
1064 
1065 		/* Test removing streams from group after creation */
1066 		printk("Deleting unicast group\n");
1067 		delete_unicast_group(unicast_group);
1068 		unicast_group = NULL;
1069 	}
1070 
1071 	disconnect_acl();
1072 
1073 	PASS("Unicast client passed\n");
1074 }
1075 
test_main_acl_disconnect(void)1076 static void test_main_acl_disconnect(void)
1077 {
1078 	struct bt_bap_unicast_group *unicast_group;
1079 	size_t stream_cnt;
1080 
1081 	init();
1082 
1083 	stream_ops.recv = NULL; /* We do not care about data in this test */
1084 
1085 	scan_and_connect();
1086 
1087 	exchange_mtu();
1088 
1089 	discover_sinks();
1090 
1091 	discover_sources();
1092 
1093 	printk("Creating unicast group\n");
1094 	stream_cnt = create_unicast_group(&unicast_group);
1095 
1096 	printk("Codec configuring streams\n");
1097 	codec_configure_streams(stream_cnt);
1098 
1099 	printk("QoS configuring streams\n");
1100 	qos_configure_streams(unicast_group, stream_cnt);
1101 
1102 	printk("Enabling streams\n");
1103 	enable_streams(stream_cnt);
1104 
1105 	printk("Metadata update streams\n");
1106 	metadata_update_streams(stream_cnt);
1107 
1108 	printk("Connecting streams\n");
1109 	connect_streams();
1110 
1111 	printk("Starting streams\n");
1112 	start_streams();
1113 
1114 	disconnect_acl();
1115 
1116 	printk("Deleting unicast group\n");
1117 	delete_unicast_group(unicast_group);
1118 	unicast_group = NULL;
1119 
1120 	/* Reconnect */
1121 	scan_and_connect();
1122 
1123 	disconnect_acl();
1124 
1125 	PASS("Unicast client ACL disconnect passed\n");
1126 }
1127 
test_main_async_group(void)1128 static void test_main_async_group(void)
1129 {
1130 	struct bt_bap_stream rx_stream = {0};
1131 	struct bt_bap_stream tx_stream = {0};
1132 	struct bt_bap_qos_cfg rx_qos = BT_BAP_QOS_CFG_UNFRAMED(7500U, 30U, 2U, 75U, 40000U);
1133 	struct bt_bap_qos_cfg tx_qos = BT_BAP_QOS_CFG_UNFRAMED(10000U, 40U, 2U, 100U, 40000U);
1134 	struct bt_bap_unicast_group_stream_param rx_param = {
1135 		.qos = &rx_qos,
1136 		.stream = &rx_stream,
1137 	};
1138 	struct bt_bap_unicast_group_stream_param tx_param = {
1139 		.qos = &tx_qos,
1140 		.stream = &tx_stream,
1141 	};
1142 	struct bt_bap_unicast_group_stream_pair_param pair_param = {
1143 		.rx_param = &rx_param,
1144 		.tx_param = &tx_param,
1145 	};
1146 	struct bt_bap_unicast_group_param param = {
1147 		.params = &pair_param,
1148 		.params_count = 1U,
1149 		.packing = BT_ISO_PACKING_SEQUENTIAL,
1150 	};
1151 	struct bt_bap_unicast_group *unicast_group;
1152 	int err;
1153 
1154 	init();
1155 
1156 	err = bt_bap_unicast_group_create(&param, &unicast_group);
1157 	if (err != 0) {
1158 		FAIL("Unable to create unicast group: %d", err);
1159 
1160 		return;
1161 	}
1162 
1163 	PASS("Unicast client async group parameters passed\n");
1164 }
1165 
test_main_reconf_group(void)1166 static void test_main_reconf_group(void)
1167 {
1168 	static struct bt_bap_lc3_preset preset_16_2_2 = BT_BAP_LC3_UNICAST_PRESET_16_2_2(
1169 		BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
1170 	struct bt_bap_stream rx_stream = {0};
1171 	struct bt_bap_stream tx_stream = {0};
1172 	struct bt_bap_unicast_group_stream_param rx_param = {
1173 		.qos = &preset_16_2_1.qos,
1174 		.stream = &rx_stream,
1175 	};
1176 	struct bt_bap_unicast_group_stream_param tx_param = {
1177 		.qos = &preset_16_2_1.qos,
1178 		.stream = &tx_stream,
1179 	};
1180 	struct bt_bap_unicast_group_stream_pair_param pair_param = {
1181 		.rx_param = &rx_param,
1182 		.tx_param = &tx_param,
1183 	};
1184 	struct bt_bap_unicast_group_param param = {
1185 		.params = &pair_param,
1186 		.params_count = 1U,
1187 		.packing = BT_ISO_PACKING_SEQUENTIAL,
1188 	};
1189 	struct bt_bap_unicast_group *unicast_group;
1190 	int err;
1191 
1192 	init();
1193 
1194 	err = bt_bap_unicast_group_create(&param, &unicast_group);
1195 	if (err != 0) {
1196 		FAIL("Unable to create unicast group: %d", err);
1197 
1198 		return;
1199 	}
1200 
1201 	rx_param.qos = &preset_16_2_2.qos;
1202 	tx_param.qos = &preset_16_2_2.qos;
1203 	err = bt_bap_unicast_group_reconfig(unicast_group, &param);
1204 	if (err != 0) {
1205 		FAIL("Unable to reconfigure unicast group: %d", err);
1206 
1207 		return;
1208 	}
1209 
1210 	PASS("Unicast client async group parameters passed\n");
1211 }
1212 
1213 static const struct bst_test_instance test_unicast_client[] = {
1214 	{
1215 		.test_id = "unicast_client",
1216 		.test_pre_init_f = test_init,
1217 		.test_tick_f = test_tick,
1218 		.test_main_f = test_main,
1219 	},
1220 	{
1221 		.test_id = "unicast_client_acl_disconnect",
1222 		.test_pre_init_f = test_init,
1223 		.test_tick_f = test_tick,
1224 		.test_main_f = test_main_acl_disconnect,
1225 	},
1226 	{
1227 		.test_id = "unicast_client_async_group",
1228 		.test_pre_init_f = test_init,
1229 		.test_tick_f = test_tick,
1230 		.test_main_f = test_main_async_group,
1231 		.test_descr = "Tests that a unicast group (CIG) can be created with different "
1232 			      "values in each direction, such as 10000us SDU interval in C to P "
1233 			      "and 7500us for P to C",
1234 	},
1235 	{
1236 		.test_id = "unicast_client_reconf_group",
1237 		.test_pre_init_f = test_init,
1238 		.test_tick_f = test_tick,
1239 		.test_main_f = test_main_reconf_group,
1240 		.test_descr = "Tests that a unicast group (CIG) can be reconfigred with new values",
1241 	},
1242 	BSTEST_END_MARKER,
1243 };
1244 
test_unicast_client_install(struct bst_test_list * tests)1245 struct bst_test_list *test_unicast_client_install(struct bst_test_list *tests)
1246 {
1247 	return bst_add_tests(tests, test_unicast_client);
1248 }
1249 
1250 #else /* !(CONFIG_BT_BAP_UNICAST_CLIENT) */
1251 
test_unicast_client_install(struct bst_test_list * tests)1252 struct bst_test_list *test_unicast_client_install(struct bst_test_list *tests)
1253 {
1254 	return tests;
1255 }
1256 
1257 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1258