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