1 /*
2  * Copyright (c) 2021-2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <inttypes.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include <zephyr/autoconf.h>
14 #include <zephyr/bluetooth/addr.h>
15 #include <zephyr/bluetooth/att.h>
16 #include <zephyr/bluetooth/audio/audio.h>
17 #include <zephyr/bluetooth/audio/bap.h>
18 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
19 #include <zephyr/bluetooth/bluetooth.h>
20 #include <zephyr/bluetooth/conn.h>
21 #include <zephyr/bluetooth/gap.h>
22 #include <zephyr/bluetooth/gatt.h>
23 #include <zephyr/bluetooth/hci.h>
24 #include <zephyr/bluetooth/hci_types.h>
25 #include <zephyr/bluetooth/iso.h>
26 #include <zephyr/bluetooth/uuid.h>
27 #include <zephyr/kernel.h>
28 #include <zephyr/net_buf.h>
29 #include <zephyr/sys/__assert.h>
30 #include <zephyr/sys/byteorder.h>
31 #include <zephyr/sys/printk.h>
32 #include <zephyr/sys/util.h>
33 #include <zephyr/sys/util_macro.h>
34 #include <zephyr/types.h>
35 
36 #include "stream_tx.h"
37 
38 static void start_scan(void);
39 
40 uint64_t unicast_audio_recv_ctr; /* This value is exposed to test code */
41 
42 static struct bt_bap_unicast_client_cb unicast_client_cbs;
43 static struct bt_conn *default_conn;
44 static struct bt_bap_unicast_group *unicast_group;
45 static struct audio_sink {
46 	struct bt_bap_ep *ep;
47 	uint16_t seq_num;
48 } sinks[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
49 static struct bt_bap_ep *sources[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
50 
51 static struct bt_bap_stream streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT +
52 				      CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
53 static size_t configured_sink_stream_count;
54 static size_t configured_source_stream_count;
55 
56 #define configured_stream_count (configured_sink_stream_count + \
57 				 configured_source_stream_count)
58 
59 /* Select a codec configuration to apply that is mandatory to support by both client and server.
60  * Allows this sample application to work without logic to parse the codec capabilities of the
61  * server and selection of an appropriate codec configuration.
62  */
63 static struct bt_bap_lc3_preset codec_configuration = BT_BAP_LC3_UNICAST_PRESET_16_2_1(
64 	BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
65 
66 static K_SEM_DEFINE(sem_connected, 0, 1);
67 static K_SEM_DEFINE(sem_disconnected, 0, 1);
68 static K_SEM_DEFINE(sem_mtu_exchanged, 0, 1);
69 static K_SEM_DEFINE(sem_security_updated, 0, 1);
70 static K_SEM_DEFINE(sem_sinks_discovered, 0, 1);
71 static K_SEM_DEFINE(sem_sources_discovered, 0, 1);
72 static K_SEM_DEFINE(sem_stream_configured, 0, 1);
73 static K_SEM_DEFINE(sem_stream_qos, 0, ARRAY_SIZE(sinks) + ARRAY_SIZE(sources));
74 static K_SEM_DEFINE(sem_stream_enabled, 0, 1);
75 static K_SEM_DEFINE(sem_stream_started, 0, 1);
76 static K_SEM_DEFINE(sem_stream_connected, 0, 1);
77 
print_hex(const uint8_t * ptr,size_t len)78 static void print_hex(const uint8_t *ptr, size_t len)
79 {
80 	while (len-- != 0) {
81 		printk("%02x", *ptr++);
82 	}
83 }
84 
print_cb(struct bt_data * data,void * user_data)85 static bool print_cb(struct bt_data *data, void *user_data)
86 {
87 	const char *str = (const char *)user_data;
88 
89 	printk("%s: type 0x%02x value_len %u\n", str, data->type, data->data_len);
90 	print_hex(data->data, data->data_len);
91 	printk("\n");
92 
93 	return true;
94 }
95 
print_codec_cap(const struct bt_audio_codec_cap * codec_cap)96 static void print_codec_cap(const struct bt_audio_codec_cap *codec_cap)
97 {
98 	printk("codec id 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid,
99 	       codec_cap->vid, codec_cap->data_len);
100 
101 	if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) {
102 		bt_audio_data_parse(codec_cap->data, codec_cap->data_len, print_cb, "data");
103 	} else { /* If not LC3, we cannot assume it's LTV */
104 		printk("data: ");
105 		print_hex(codec_cap->data, codec_cap->data_len);
106 		printk("\n");
107 	}
108 
109 	bt_audio_data_parse(codec_cap->meta, codec_cap->meta_len, print_cb, "meta");
110 }
111 
check_audio_support_and_connect(struct bt_data * data,void * user_data)112 static bool check_audio_support_and_connect(struct bt_data *data,
113 					    void *user_data)
114 {
115 	struct net_buf_simple ascs_svc_data;
116 	bt_addr_le_t *addr = user_data;
117 	uint8_t announcement_type;
118 	uint32_t audio_contexts;
119 	const struct bt_uuid *uuid;
120 	uint16_t uuid_val;
121 	uint8_t meta_len;
122 	size_t min_size;
123 	int err;
124 
125 	printk("[AD]: %u data_len %u\n", data->type, data->data_len);
126 
127 	if (data->type != BT_DATA_SVC_DATA16) {
128 		return true; /* Continue parsing to next AD data type */
129 	}
130 
131 	if (data->data_len < sizeof(uuid_val)) {
132 		printk("AD invalid size %u\n", data->data_len);
133 		return true; /* Continue parsing to next AD data type */
134 	}
135 
136 	net_buf_simple_init_with_data(&ascs_svc_data, (void *)data->data,
137 				      data->data_len);
138 
139 	uuid_val = net_buf_simple_pull_le16(&ascs_svc_data);
140 	uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(uuid_val));
141 	if (bt_uuid_cmp(uuid, BT_UUID_ASCS) != 0) {
142 		/* We are looking for the ASCS service data */
143 		return true; /* Continue parsing to next AD data type */
144 	}
145 
146 	min_size = sizeof(announcement_type) + sizeof(audio_contexts) + sizeof(meta_len);
147 	if (ascs_svc_data.len < min_size) {
148 		printk("AD invalid size %u\n", data->data_len);
149 		return false; /* Stop parsing */
150 	}
151 
152 	announcement_type = net_buf_simple_pull_u8(&ascs_svc_data);
153 	audio_contexts = net_buf_simple_pull_le32(&ascs_svc_data);
154 	meta_len = net_buf_simple_pull_u8(&ascs_svc_data);
155 
156 	err = bt_le_scan_stop();
157 	if (err != 0) {
158 		printk("Failed to stop scan: %d\n", err);
159 		return false; /* Stop parsing */
160 	}
161 
162 	printk("Audio server found with type %u, contexts 0x%08x and meta_len %u; connecting\n",
163 	       announcement_type, audio_contexts, meta_len);
164 
165 	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
166 				BT_LE_CONN_PARAM_DEFAULT,
167 				&default_conn);
168 	if (err != 0) {
169 		printk("Create conn to failed (%u)\n", err);
170 		start_scan();
171 	}
172 
173 	return false; /* Stop parsing */
174 }
175 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)176 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
177 			 struct net_buf_simple *ad)
178 {
179 	char addr_str[BT_ADDR_LE_STR_LEN];
180 
181 	if (default_conn != NULL) {
182 		/* Already connected */
183 		return;
184 	}
185 
186 	/* We're only interested in connectable events */
187 	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
188 	    type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND &&
189 	    type != BT_GAP_ADV_TYPE_EXT_ADV) {
190 		return;
191 	}
192 
193 	(void)bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
194 	printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
195 
196 	/* connect only to devices in close proximity */
197 	if (rssi < -50) {
198 		return;
199 	}
200 
201 	bt_data_parse(ad, check_audio_support_and_connect, (void *)addr);
202 }
203 
start_scan(void)204 static void start_scan(void)
205 {
206 	int err;
207 
208 	/* This demo doesn't require active scan */
209 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
210 	if (err != 0) {
211 		printk("Scanning failed to start (err %d)\n", err);
212 		return;
213 	}
214 
215 	printk("Scanning successfully started\n");
216 }
217 
stream_configured(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg_pref * pref)218 static void stream_configured(struct bt_bap_stream *stream, const struct bt_bap_qos_cfg_pref *pref)
219 {
220 	printk("Audio Stream %p configured\n", stream);
221 
222 	k_sem_give(&sem_stream_configured);
223 }
224 
stream_qos_set(struct bt_bap_stream * stream)225 static void stream_qos_set(struct bt_bap_stream *stream)
226 {
227 	printk("Audio Stream %p QoS set\n", stream);
228 
229 	k_sem_give(&sem_stream_qos);
230 }
231 
stream_enabled(struct bt_bap_stream * stream)232 static void stream_enabled(struct bt_bap_stream *stream)
233 {
234 	printk("Audio Stream %p enabled\n", stream);
235 
236 	k_sem_give(&sem_stream_enabled);
237 }
238 
stream_tx_can_send(const struct bt_bap_stream * stream)239 static bool stream_tx_can_send(const struct bt_bap_stream *stream)
240 {
241 	struct bt_bap_ep_info info;
242 	int err;
243 
244 	if (stream == NULL || stream->ep == NULL) {
245 		return false;
246 	}
247 
248 	err = bt_bap_ep_get_info(stream->ep, &info);
249 	if (err != 0) {
250 		return false;
251 	}
252 
253 	return info.can_send;
254 }
255 
stream_connected_cb(struct bt_bap_stream * stream)256 static void stream_connected_cb(struct bt_bap_stream *stream)
257 {
258 	printk("Audio Stream %p connected\n", stream);
259 
260 	/* Reset sequence number for sinks */
261 	for (size_t i = 0U; i < configured_sink_stream_count; i++) {
262 		if (stream->ep == sinks[i].ep) {
263 			sinks[i].seq_num = 0U;
264 			break;
265 		}
266 	}
267 
268 	k_sem_give(&sem_stream_connected);
269 }
270 
stream_started(struct bt_bap_stream * stream)271 static void stream_started(struct bt_bap_stream *stream)
272 {
273 	printk("Audio Stream %p started\n", stream);
274 	/* Register the stream for TX if it can send */
275 	if (IS_ENABLED(CONFIG_BT_AUDIO_TX) && stream_tx_can_send(stream)) {
276 		const int err = stream_tx_register(stream);
277 
278 		if (err != 0) {
279 			printk("Failed to register stream %p for TX: %d\n", stream, err);
280 		}
281 	}
282 
283 	k_sem_give(&sem_stream_started);
284 }
285 
stream_metadata_updated(struct bt_bap_stream * stream)286 static void stream_metadata_updated(struct bt_bap_stream *stream)
287 {
288 	printk("Audio Stream %p metadata updated\n", stream);
289 }
290 
stream_disabled(struct bt_bap_stream * stream)291 static void stream_disabled(struct bt_bap_stream *stream)
292 {
293 	printk("Audio Stream %p disabled\n", stream);
294 }
295 
stream_stopped(struct bt_bap_stream * stream,uint8_t reason)296 static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason)
297 {
298 	printk("Audio Stream %p stopped with reason 0x%02X\n", stream, reason);
299 
300 	/* Unregister the stream for TX if it can send */
301 	if (IS_ENABLED(CONFIG_BT_AUDIO_TX) && stream_tx_can_send(stream)) {
302 		const int err = stream_tx_unregister(stream);
303 
304 		if (err != 0) {
305 			printk("Failed to unregister stream %p for TX: %d", stream, err);
306 		}
307 	}
308 }
309 
stream_released(struct bt_bap_stream * stream)310 static void stream_released(struct bt_bap_stream *stream)
311 {
312 	printk("Audio Stream %p released\n", stream);
313 }
314 
stream_recv(struct bt_bap_stream * stream,const struct bt_iso_recv_info * info,struct net_buf * buf)315 static void stream_recv(struct bt_bap_stream *stream,
316 			const struct bt_iso_recv_info *info,
317 			struct net_buf *buf)
318 {
319 	if (info->flags & BT_ISO_FLAGS_VALID) {
320 		unicast_audio_recv_ctr++;
321 		printk("Incoming audio on stream %p len %u (%"PRIu64")\n", stream, buf->len,
322 			unicast_audio_recv_ctr);
323 	}
324 }
325 
326 static struct bt_bap_stream_ops stream_ops = {
327 	.configured = stream_configured,
328 	.qos_set = stream_qos_set,
329 	.enabled = stream_enabled,
330 	.started = stream_started,
331 	.metadata_updated = stream_metadata_updated,
332 	.disabled = stream_disabled,
333 	.stopped = stream_stopped,
334 	.released = stream_released,
335 	.recv = stream_recv,
336 	.connected = stream_connected_cb,
337 };
338 
add_remote_source(struct bt_bap_ep * ep)339 static void add_remote_source(struct bt_bap_ep *ep)
340 {
341 	for (size_t i = 0U; i < ARRAY_SIZE(sources); i++) {
342 		if (sources[i] == NULL) {
343 			printk("Source #%zu: ep %p\n", i, ep);
344 			sources[i] = ep;
345 			return;
346 		}
347 	}
348 
349 	printk("Could not add source ep\n");
350 }
351 
add_remote_sink(struct bt_bap_ep * ep)352 static void add_remote_sink(struct bt_bap_ep *ep)
353 {
354 	for (size_t i = 0U; i < ARRAY_SIZE(sinks); i++) {
355 		if (sinks[i].ep == NULL) {
356 			printk("Sink #%zu: ep %p\n", i, ep);
357 			sinks[i].ep = ep;
358 			return;
359 		}
360 	}
361 
362 	printk("Could not add sink ep\n");
363 }
364 
print_remote_codec_cap(const struct bt_audio_codec_cap * codec_cap,enum bt_audio_dir dir)365 static void print_remote_codec_cap(const struct bt_audio_codec_cap *codec_cap,
366 				   enum bt_audio_dir dir)
367 {
368 	printk("codec_cap %p dir 0x%02x\n", codec_cap, dir);
369 
370 	print_codec_cap(codec_cap);
371 }
372 
discover_sinks_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)373 static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
374 {
375 	if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
376 		printk("Discovery failed: %d\n", err);
377 		return;
378 	}
379 
380 	if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
381 		printk("Discover sinks completed without finding any sink ASEs\n");
382 	} else {
383 		printk("Discover sinks complete: err %d\n", err);
384 	}
385 
386 	k_sem_give(&sem_sinks_discovered);
387 }
388 
discover_sources_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)389 static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
390 {
391 	if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
392 		printk("Discovery failed: %d\n", err);
393 		return;
394 	}
395 
396 	if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
397 		printk("Discover sinks completed without finding any source ASEs\n");
398 	} else {
399 		printk("Discover sources complete: err %d\n", err);
400 	}
401 
402 	k_sem_give(&sem_sources_discovered);
403 }
404 
connected(struct bt_conn * conn,uint8_t err)405 static void connected(struct bt_conn *conn, uint8_t err)
406 {
407 	char addr[BT_ADDR_LE_STR_LEN];
408 
409 	(void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
410 
411 	if (err != 0) {
412 		printk("Failed to connect to %s %u %s\n", addr, err, bt_hci_err_to_str(err));
413 
414 		bt_conn_unref(default_conn);
415 		default_conn = NULL;
416 
417 		start_scan();
418 		return;
419 	}
420 
421 	if (conn != default_conn) {
422 		return;
423 	}
424 
425 	printk("Connected: %s\n", addr);
426 	k_sem_give(&sem_connected);
427 }
428 
disconnected(struct bt_conn * conn,uint8_t reason)429 static void disconnected(struct bt_conn *conn, uint8_t reason)
430 {
431 	char addr[BT_ADDR_LE_STR_LEN];
432 
433 	if (conn != default_conn) {
434 		return;
435 	}
436 
437 	(void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
438 
439 	printk("Disconnected: %s, reason 0x%02x %s\n", addr, reason, bt_hci_err_to_str(reason));
440 
441 	bt_conn_unref(default_conn);
442 	default_conn = NULL;
443 
444 	k_sem_give(&sem_disconnected);
445 }
446 
security_changed_cb(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)447 static void security_changed_cb(struct bt_conn *conn, bt_security_t level,
448 				enum bt_security_err err)
449 {
450 	if (err == 0) {
451 		k_sem_give(&sem_security_updated);
452 	} else {
453 		printk("Failed to set security level: %s(%u)", bt_security_err_to_str(err), err);
454 	}
455 }
456 
457 BT_CONN_CB_DEFINE(conn_callbacks) = {
458 	.connected = connected,
459 	.disconnected = disconnected,
460 	.security_changed = security_changed_cb
461 };
462 
att_mtu_updated(struct bt_conn * conn,uint16_t tx,uint16_t rx)463 static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
464 {
465 	printk("MTU exchanged: %u/%u\n", tx, rx);
466 	k_sem_give(&sem_mtu_exchanged);
467 }
468 
469 static struct bt_gatt_cb gatt_callbacks = {
470 	.att_mtu_updated = att_mtu_updated,
471 };
472 
unicast_client_location_cb(struct bt_conn * conn,enum bt_audio_dir dir,enum bt_audio_location loc)473 static void unicast_client_location_cb(struct bt_conn *conn,
474 				      enum bt_audio_dir dir,
475 				      enum bt_audio_location loc)
476 {
477 	printk("dir %u loc %X\n", dir, loc);
478 }
479 
available_contexts_cb(struct bt_conn * conn,enum bt_audio_context snk_ctx,enum bt_audio_context src_ctx)480 static void available_contexts_cb(struct bt_conn *conn,
481 				  enum bt_audio_context snk_ctx,
482 				  enum bt_audio_context src_ctx)
483 {
484 	printk("snk ctx %u src ctx %u\n", snk_ctx, src_ctx);
485 }
486 
pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_audio_codec_cap * codec_cap)487 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir,
488 			  const struct bt_audio_codec_cap *codec_cap)
489 {
490 	print_remote_codec_cap(codec_cap, dir);
491 }
492 
endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)493 static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
494 {
495 	if (dir == BT_AUDIO_DIR_SOURCE) {
496 		add_remote_source(ep);
497 	} else if (dir == BT_AUDIO_DIR_SINK) {
498 		add_remote_sink(ep);
499 	}
500 }
501 
502 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
503 	.location = unicast_client_location_cb,
504 	.available_contexts = available_contexts_cb,
505 	.pac_record = pac_record_cb,
506 	.endpoint = endpoint_cb,
507 };
508 
init(void)509 static int init(void)
510 {
511 	int err;
512 
513 	err = bt_enable(NULL);
514 	if (err != 0) {
515 		printk("Bluetooth enable failed (err %d)\n", err);
516 		return err;
517 	}
518 
519 	for (size_t i = 0; i < ARRAY_SIZE(streams); i++) {
520 		streams[i].ops = &stream_ops;
521 	}
522 
523 	bt_gatt_cb_register(&gatt_callbacks);
524 
525 	if (IS_ENABLED(CONFIG_BT_AUDIO_TX)) {
526 		stream_tx_init();
527 	}
528 
529 	return 0;
530 }
531 
scan_and_connect(void)532 static int scan_and_connect(void)
533 {
534 	int err;
535 
536 	start_scan();
537 
538 	err = k_sem_take(&sem_connected, K_FOREVER);
539 	if (err != 0) {
540 		printk("failed to take sem_connected (err %d)\n", err);
541 		return err;
542 	}
543 
544 	err = k_sem_take(&sem_mtu_exchanged, K_FOREVER);
545 	if (err != 0) {
546 		printk("failed to take sem_mtu_exchanged (err %d)\n", err);
547 		return err;
548 	}
549 
550 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
551 	if (err != 0) {
552 		printk("failed to set security (err %d)\n", err);
553 		return err;
554 	}
555 
556 	err = k_sem_take(&sem_security_updated, K_FOREVER);
557 	if (err != 0) {
558 		printk("failed to take sem_security_updated (err %d)\n", err);
559 		return err;
560 	}
561 
562 	return 0;
563 }
564 
discover_sinks(void)565 static int discover_sinks(void)
566 {
567 	int err;
568 
569 	unicast_client_cbs.discover = discover_sinks_cb;
570 
571 	err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SINK);
572 	if (err != 0) {
573 		printk("Failed to discover sinks: %d\n", err);
574 		return err;
575 	}
576 
577 	err = k_sem_take(&sem_sinks_discovered, K_FOREVER);
578 	if (err != 0) {
579 		printk("failed to take sem_sinks_discovered (err %d)\n", err);
580 		return err;
581 	}
582 
583 	return 0;
584 }
585 
discover_sources(void)586 static int discover_sources(void)
587 {
588 	int err;
589 
590 	unicast_client_cbs.discover = discover_sources_cb;
591 
592 	err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SOURCE);
593 	if (err != 0) {
594 		printk("Failed to discover sources: %d\n", err);
595 		return err;
596 	}
597 
598 	err = k_sem_take(&sem_sources_discovered, K_FOREVER);
599 	if (err != 0) {
600 		printk("failed to take sem_sources_discovered (err %d)\n", err);
601 		return err;
602 	}
603 
604 	return 0;
605 }
606 
configure_stream(struct bt_bap_stream * stream,struct bt_bap_ep * ep)607 static int configure_stream(struct bt_bap_stream *stream, struct bt_bap_ep *ep)
608 {
609 	int err;
610 
611 	err = bt_bap_stream_config(default_conn, stream, ep, &codec_configuration.codec_cfg);
612 	if (err != 0) {
613 		return err;
614 	}
615 
616 	err = k_sem_take(&sem_stream_configured, K_FOREVER);
617 	if (err != 0) {
618 		printk("failed to take sem_stream_configured (err %d)\n", err);
619 		return err;
620 	}
621 
622 	return 0;
623 }
624 
configure_streams(void)625 static int configure_streams(void)
626 {
627 	int err;
628 
629 	for (size_t i = 0; i < ARRAY_SIZE(sinks); i++) {
630 		struct bt_bap_ep *ep = sinks[i].ep;
631 		struct bt_bap_stream *stream = &streams[i];
632 
633 		if (ep == NULL) {
634 			continue;
635 		}
636 
637 		err = configure_stream(stream, ep);
638 		if (err != 0) {
639 			printk("Could not configure sink stream[%zu]: %d\n",
640 			       i, err);
641 			return err;
642 		}
643 
644 		printk("Configured sink stream[%zu]\n", i);
645 		configured_sink_stream_count++;
646 	}
647 
648 	for (size_t i = 0; i < ARRAY_SIZE(sources); i++) {
649 		struct bt_bap_ep *ep = sources[i];
650 		struct bt_bap_stream *stream = &streams[i + configured_sink_stream_count];
651 
652 		if (ep == NULL) {
653 			continue;
654 		}
655 
656 		err = configure_stream(stream, ep);
657 		if (err != 0) {
658 			printk("Could not configure source stream[%zu]: %d\n",
659 			       i, err);
660 			return err;
661 		}
662 
663 		printk("Configured source stream[%zu]\n", i);
664 		configured_source_stream_count++;
665 	}
666 
667 	return 0;
668 }
669 
create_group(void)670 static int create_group(void)
671 {
672 	const size_t params_count = MAX(configured_sink_stream_count,
673 					configured_source_stream_count);
674 	struct bt_bap_unicast_group_stream_pair_param pair_params[params_count];
675 	struct bt_bap_unicast_group_stream_param stream_params[configured_stream_count];
676 	struct bt_bap_unicast_group_param param;
677 	int err;
678 
679 	for (size_t i = 0U; i < configured_stream_count; i++) {
680 		stream_params[i].stream = &streams[i];
681 		stream_params[i].qos = &codec_configuration.qos;
682 	}
683 
684 	for (size_t i = 0U; i < params_count; i++) {
685 		if (i < configured_sink_stream_count) {
686 			pair_params[i].tx_param = &stream_params[i];
687 		} else {
688 			pair_params[i].tx_param = NULL;
689 		}
690 
691 		if (i < configured_source_stream_count) {
692 			pair_params[i].rx_param = &stream_params[i + configured_sink_stream_count];
693 		} else {
694 			pair_params[i].rx_param = NULL;
695 		}
696 	}
697 
698 	param.params = pair_params;
699 	param.params_count = params_count;
700 	param.packing = BT_ISO_PACKING_SEQUENTIAL;
701 
702 	err = bt_bap_unicast_group_create(&param, &unicast_group);
703 	if (err != 0) {
704 		printk("Could not create unicast group (err %d)\n", err);
705 		return err;
706 	}
707 
708 	return 0;
709 }
710 
delete_group(void)711 static int delete_group(void)
712 {
713 	int err;
714 
715 	err = bt_bap_unicast_group_delete(unicast_group);
716 	if (err != 0) {
717 		printk("Could not create unicast group (err %d)\n", err);
718 		return err;
719 	}
720 
721 	return 0;
722 }
723 
set_stream_qos(void)724 static int set_stream_qos(void)
725 {
726 	int err;
727 
728 	err = bt_bap_stream_qos(default_conn, unicast_group);
729 	if (err != 0) {
730 		printk("Unable to setup QoS: %d\n", err);
731 		return err;
732 	}
733 
734 	for (size_t i = 0U; i < configured_stream_count; i++) {
735 		printk("QoS: waiting for %zu streams\n", configured_stream_count);
736 		err = k_sem_take(&sem_stream_qos, K_FOREVER);
737 		if (err != 0) {
738 			printk("failed to take sem_stream_qos (err %d)\n", err);
739 			return err;
740 		}
741 	}
742 
743 	return 0;
744 }
745 
enable_streams(void)746 static int enable_streams(void)
747 {
748 	for (size_t i = 0U; i < configured_stream_count; i++) {
749 		int err;
750 
751 		err = bt_bap_stream_enable(&streams[i], codec_configuration.codec_cfg.meta,
752 					   codec_configuration.codec_cfg.meta_len);
753 		if (err != 0) {
754 			printk("Unable to enable stream: %d\n", err);
755 			return err;
756 		}
757 
758 		err = k_sem_take(&sem_stream_enabled, K_FOREVER);
759 		if (err != 0) {
760 			printk("failed to take sem_stream_enabled (err %d)\n", err);
761 			return err;
762 		}
763 	}
764 
765 	return 0;
766 }
767 
connect_streams(void)768 static int connect_streams(void)
769 {
770 	for (size_t i = 0U; i < configured_stream_count; i++) {
771 		int err;
772 
773 		k_sem_reset(&sem_stream_connected);
774 
775 		err = bt_bap_stream_connect(&streams[i]);
776 		if (err == -EALREADY) {
777 			/* We have already connected a paired stream */
778 			continue;
779 		} else if (err != 0) {
780 			printk("Unable to start stream: %d\n", err);
781 			return err;
782 		}
783 
784 		err = k_sem_take(&sem_stream_connected, K_FOREVER);
785 		if (err != 0) {
786 			printk("failed to take sem_stream_connected (err %d)\n", err);
787 			return err;
788 		}
789 	}
790 
791 	return 0;
792 }
793 
stream_dir(const struct bt_bap_stream * stream)794 static enum bt_audio_dir stream_dir(const struct bt_bap_stream *stream)
795 {
796 	struct bt_bap_ep_info ep_info;
797 	int err;
798 
799 	err = bt_bap_ep_get_info(stream->ep, &ep_info);
800 	if (err != 0) {
801 		printk("Failed to get ep info for %p: %d\n", stream, err);
802 		__ASSERT_NO_MSG(false);
803 
804 		return 0;
805 	}
806 
807 	return ep_info.dir;
808 }
809 
start_streams(void)810 static int start_streams(void)
811 {
812 	for (size_t i = 0U; i < configured_stream_count; i++) {
813 		struct bt_bap_stream *stream = &streams[i];
814 		int err;
815 
816 		if (stream_dir(stream) == BT_AUDIO_DIR_SOURCE) {
817 			err = bt_bap_stream_start(&streams[i]);
818 			if (err != 0) {
819 				printk("Unable to start stream: %d\n", err);
820 				return err;
821 			}
822 		} /* Sink streams are started by the unicast server */
823 
824 		err = k_sem_take(&sem_stream_started, K_FOREVER);
825 		if (err != 0) {
826 			printk("failed to take sem_stream_started (err %d)\n", err);
827 			return err;
828 		}
829 	}
830 
831 	return 0;
832 }
833 
reset_data(void)834 static void reset_data(void)
835 {
836 	k_sem_reset(&sem_connected);
837 	k_sem_reset(&sem_disconnected);
838 	k_sem_reset(&sem_mtu_exchanged);
839 	k_sem_reset(&sem_security_updated);
840 	k_sem_reset(&sem_sinks_discovered);
841 	k_sem_reset(&sem_sources_discovered);
842 	k_sem_reset(&sem_stream_configured);
843 	k_sem_reset(&sem_stream_qos);
844 	k_sem_reset(&sem_stream_enabled);
845 	k_sem_reset(&sem_stream_started);
846 	k_sem_reset(&sem_stream_connected);
847 
848 	configured_sink_stream_count = 0;
849 	configured_source_stream_count = 0;
850 	memset(sinks, 0, sizeof(sinks));
851 	memset(sources, 0, sizeof(sources));
852 }
853 
main(void)854 int main(void)
855 {
856 	int err;
857 
858 	printk("Initializing\n");
859 	err = init();
860 	if (err != 0) {
861 		return 0;
862 	}
863 	printk("Initialized\n");
864 
865 	err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
866 	if (err != 0) {
867 		printk("Failed to register client callbacks: %d", err);
868 		return 0;
869 	}
870 
871 	while (true) {
872 		reset_data();
873 
874 		printk("Waiting for connection\n");
875 		err = scan_and_connect();
876 		if (err != 0) {
877 			return 0;
878 		}
879 		printk("Connected\n");
880 
881 		printk("Discovering sinks\n");
882 		err = discover_sinks();
883 		if (err != 0) {
884 			return 0;
885 		}
886 		printk("Sinks discovered\n");
887 
888 		printk("Discovering sources\n");
889 		err = discover_sources();
890 		if (err != 0) {
891 			return 0;
892 		}
893 		printk("Sources discovered\n");
894 
895 		printk("Configuring streams\n");
896 		err = configure_streams();
897 		if (err != 0) {
898 			return 0;
899 		}
900 
901 		if (configured_stream_count == 0U) {
902 			printk("No streams were configured\n");
903 			return 0;
904 		}
905 
906 		printk("Creating unicast group\n");
907 		err = create_group();
908 		if (err != 0) {
909 			return 0;
910 		}
911 		printk("Unicast group created\n");
912 
913 		printk("Setting stream QoS\n");
914 		err = set_stream_qos();
915 		if (err != 0) {
916 			return 0;
917 		}
918 		printk("Stream QoS Set\n");
919 
920 		printk("Enabling streams\n");
921 		err = enable_streams();
922 		if (err != 0) {
923 			return 0;
924 		}
925 		printk("Streams enabled\n");
926 
927 		printk("Connecting streams\n");
928 		err = connect_streams();
929 		if (err != 0) {
930 			return 0;
931 		}
932 		printk("Streams connected\n");
933 
934 		printk("Starting streams\n");
935 		err = start_streams();
936 		if (err != 0) {
937 			return 0;
938 		}
939 		printk("Streams started\n");
940 
941 		/* Wait for disconnect */
942 		err = k_sem_take(&sem_disconnected, K_FOREVER);
943 		if (err != 0) {
944 			printk("failed to take sem_disconnected (err %d)\n", err);
945 			return 0;
946 		}
947 
948 		printk("Deleting group\n");
949 		err = delete_group();
950 		if (err != 0) {
951 			return 0;
952 		}
953 		printk("Group deleted\n");
954 	}
955 }
956