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, BT_BAP_CONN_PARAM_RELAXED,
166 &default_conn);
167 if (err != 0) {
168 printk("Create conn to failed (%u)\n", err);
169 start_scan();
170 }
171
172 return false; /* Stop parsing */
173 }
174
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)175 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
176 struct net_buf_simple *ad)
177 {
178 char addr_str[BT_ADDR_LE_STR_LEN];
179
180 if (default_conn != NULL) {
181 /* Already connected */
182 return;
183 }
184
185 /* We're only interested in connectable events */
186 if (type != BT_GAP_ADV_TYPE_ADV_IND &&
187 type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND &&
188 type != BT_GAP_ADV_TYPE_EXT_ADV) {
189 return;
190 }
191
192 (void)bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
193 printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
194
195 /* connect only to devices in close proximity */
196 if (rssi < -50) {
197 return;
198 }
199
200 bt_data_parse(ad, check_audio_support_and_connect, (void *)addr);
201 }
202
start_scan(void)203 static void start_scan(void)
204 {
205 int err;
206
207 /* This demo doesn't require active scan */
208 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
209 if (err != 0) {
210 printk("Scanning failed to start (err %d)\n", err);
211 return;
212 }
213
214 printk("Scanning successfully started\n");
215 }
216
stream_configured(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg_pref * pref)217 static void stream_configured(struct bt_bap_stream *stream, const struct bt_bap_qos_cfg_pref *pref)
218 {
219 printk("Audio Stream %p configured\n", stream);
220
221 k_sem_give(&sem_stream_configured);
222 }
223
stream_qos_set(struct bt_bap_stream * stream)224 static void stream_qos_set(struct bt_bap_stream *stream)
225 {
226 printk("Audio Stream %p QoS set\n", stream);
227
228 k_sem_give(&sem_stream_qos);
229 }
230
stream_enabled(struct bt_bap_stream * stream)231 static void stream_enabled(struct bt_bap_stream *stream)
232 {
233 printk("Audio Stream %p enabled\n", stream);
234
235 k_sem_give(&sem_stream_enabled);
236 }
237
stream_tx_can_send(const struct bt_bap_stream * stream)238 static bool stream_tx_can_send(const struct bt_bap_stream *stream)
239 {
240 struct bt_bap_ep_info info;
241 int err;
242
243 if (stream == NULL || stream->ep == NULL) {
244 return false;
245 }
246
247 err = bt_bap_ep_get_info(stream->ep, &info);
248 if (err != 0) {
249 return false;
250 }
251
252 return info.can_send;
253 }
254
stream_connected_cb(struct bt_bap_stream * stream)255 static void stream_connected_cb(struct bt_bap_stream *stream)
256 {
257 printk("Audio Stream %p connected\n", stream);
258
259 /* Reset sequence number for sinks */
260 for (size_t i = 0U; i < configured_sink_stream_count; i++) {
261 if (stream->ep == sinks[i].ep) {
262 sinks[i].seq_num = 0U;
263 break;
264 }
265 }
266
267 k_sem_give(&sem_stream_connected);
268 }
269
stream_started(struct bt_bap_stream * stream)270 static void stream_started(struct bt_bap_stream *stream)
271 {
272 printk("Audio Stream %p started\n", stream);
273 /* Register the stream for TX if it can send */
274 if (IS_ENABLED(CONFIG_BT_AUDIO_TX) && stream_tx_can_send(stream)) {
275 const int err = stream_tx_register(stream);
276
277 if (err != 0) {
278 printk("Failed to register stream %p for TX: %d\n", stream, err);
279 }
280 }
281
282 k_sem_give(&sem_stream_started);
283 }
284
stream_metadata_updated(struct bt_bap_stream * stream)285 static void stream_metadata_updated(struct bt_bap_stream *stream)
286 {
287 printk("Audio Stream %p metadata updated\n", stream);
288 }
289
stream_disabled(struct bt_bap_stream * stream)290 static void stream_disabled(struct bt_bap_stream *stream)
291 {
292 printk("Audio Stream %p disabled\n", stream);
293 }
294
stream_stopped(struct bt_bap_stream * stream,uint8_t reason)295 static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason)
296 {
297 printk("Audio Stream %p stopped with reason 0x%02X\n", stream, reason);
298
299 /* Unregister the stream for TX if it can send */
300 if (IS_ENABLED(CONFIG_BT_AUDIO_TX) && stream_tx_can_send(stream)) {
301 const int err = stream_tx_unregister(stream);
302
303 if (err != 0) {
304 printk("Failed to unregister stream %p for TX: %d", stream, err);
305 }
306 }
307 }
308
stream_released(struct bt_bap_stream * stream)309 static void stream_released(struct bt_bap_stream *stream)
310 {
311 printk("Audio Stream %p released\n", stream);
312 }
313
stream_recv(struct bt_bap_stream * stream,const struct bt_iso_recv_info * info,struct net_buf * buf)314 static void stream_recv(struct bt_bap_stream *stream,
315 const struct bt_iso_recv_info *info,
316 struct net_buf *buf)
317 {
318 if (info->flags & BT_ISO_FLAGS_VALID) {
319 unicast_audio_recv_ctr++;
320 printk("Incoming audio on stream %p len %u (%"PRIu64")\n", stream, buf->len,
321 unicast_audio_recv_ctr);
322 }
323 }
324
325 static struct bt_bap_stream_ops stream_ops = {
326 .configured = stream_configured,
327 .qos_set = stream_qos_set,
328 .enabled = stream_enabled,
329 .started = stream_started,
330 .metadata_updated = stream_metadata_updated,
331 .disabled = stream_disabled,
332 .stopped = stream_stopped,
333 .released = stream_released,
334 .recv = stream_recv,
335 .connected = stream_connected_cb,
336 };
337
add_remote_source(struct bt_bap_ep * ep)338 static void add_remote_source(struct bt_bap_ep *ep)
339 {
340 for (size_t i = 0U; i < ARRAY_SIZE(sources); i++) {
341 if (sources[i] == NULL) {
342 printk("Source #%zu: ep %p\n", i, ep);
343 sources[i] = ep;
344 return;
345 }
346 }
347
348 printk("Could not add source ep\n");
349 }
350
add_remote_sink(struct bt_bap_ep * ep)351 static void add_remote_sink(struct bt_bap_ep *ep)
352 {
353 for (size_t i = 0U; i < ARRAY_SIZE(sinks); i++) {
354 if (sinks[i].ep == NULL) {
355 printk("Sink #%zu: ep %p\n", i, ep);
356 sinks[i].ep = ep;
357 return;
358 }
359 }
360
361 printk("Could not add sink ep\n");
362 }
363
print_remote_codec_cap(const struct bt_audio_codec_cap * codec_cap,enum bt_audio_dir dir)364 static void print_remote_codec_cap(const struct bt_audio_codec_cap *codec_cap,
365 enum bt_audio_dir dir)
366 {
367 printk("codec_cap %p dir 0x%02x\n", codec_cap, dir);
368
369 print_codec_cap(codec_cap);
370 }
371
discover_sinks_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)372 static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
373 {
374 if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
375 printk("Discovery failed: %d\n", err);
376 return;
377 }
378
379 if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
380 printk("Discover sinks completed without finding any sink ASEs\n");
381 } else {
382 printk("Discover sinks complete: err %d\n", err);
383 }
384
385 k_sem_give(&sem_sinks_discovered);
386 }
387
discover_sources_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)388 static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
389 {
390 if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
391 printk("Discovery failed: %d\n", err);
392 return;
393 }
394
395 if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
396 printk("Discover sinks completed without finding any source ASEs\n");
397 } else {
398 printk("Discover sources complete: err %d\n", err);
399 }
400
401 k_sem_give(&sem_sources_discovered);
402 }
403
connected(struct bt_conn * conn,uint8_t err)404 static void connected(struct bt_conn *conn, uint8_t err)
405 {
406 char addr[BT_ADDR_LE_STR_LEN];
407
408 (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
409
410 if (err != 0) {
411 printk("Failed to connect to %s %u %s\n", addr, err, bt_hci_err_to_str(err));
412
413 bt_conn_unref(default_conn);
414 default_conn = NULL;
415
416 start_scan();
417 return;
418 }
419
420 if (conn != default_conn) {
421 return;
422 }
423
424 printk("Connected: %s\n", addr);
425 k_sem_give(&sem_connected);
426 }
427
disconnected(struct bt_conn * conn,uint8_t reason)428 static void disconnected(struct bt_conn *conn, uint8_t reason)
429 {
430 char addr[BT_ADDR_LE_STR_LEN];
431
432 if (conn != default_conn) {
433 return;
434 }
435
436 (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
437
438 printk("Disconnected: %s, reason 0x%02x %s\n", addr, reason, bt_hci_err_to_str(reason));
439
440 bt_conn_unref(default_conn);
441 default_conn = NULL;
442
443 k_sem_give(&sem_disconnected);
444 }
445
security_changed_cb(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)446 static void security_changed_cb(struct bt_conn *conn, bt_security_t level,
447 enum bt_security_err err)
448 {
449 if (err == 0) {
450 k_sem_give(&sem_security_updated);
451 } else {
452 printk("Failed to set security level: %s(%u)", bt_security_err_to_str(err), err);
453 }
454 }
455
456 BT_CONN_CB_DEFINE(conn_callbacks) = {
457 .connected = connected,
458 .disconnected = disconnected,
459 .security_changed = security_changed_cb
460 };
461
att_mtu_updated(struct bt_conn * conn,uint16_t tx,uint16_t rx)462 static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
463 {
464 printk("MTU exchanged: %u/%u\n", tx, rx);
465 k_sem_give(&sem_mtu_exchanged);
466 }
467
468 static struct bt_gatt_cb gatt_callbacks = {
469 .att_mtu_updated = att_mtu_updated,
470 };
471
unicast_client_location_cb(struct bt_conn * conn,enum bt_audio_dir dir,enum bt_audio_location loc)472 static void unicast_client_location_cb(struct bt_conn *conn,
473 enum bt_audio_dir dir,
474 enum bt_audio_location loc)
475 {
476 printk("dir %u loc %X\n", dir, loc);
477 }
478
available_contexts_cb(struct bt_conn * conn,enum bt_audio_context snk_ctx,enum bt_audio_context src_ctx)479 static void available_contexts_cb(struct bt_conn *conn,
480 enum bt_audio_context snk_ctx,
481 enum bt_audio_context src_ctx)
482 {
483 printk("snk ctx %u src ctx %u\n", snk_ctx, src_ctx);
484 }
485
pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_audio_codec_cap * codec_cap)486 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir,
487 const struct bt_audio_codec_cap *codec_cap)
488 {
489 print_remote_codec_cap(codec_cap, dir);
490 }
491
endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)492 static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
493 {
494 if (dir == BT_AUDIO_DIR_SOURCE) {
495 add_remote_source(ep);
496 } else if (dir == BT_AUDIO_DIR_SINK) {
497 add_remote_sink(ep);
498 }
499 }
500
501 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
502 .location = unicast_client_location_cb,
503 .available_contexts = available_contexts_cb,
504 .pac_record = pac_record_cb,
505 .endpoint = endpoint_cb,
506 };
507
init(void)508 static int init(void)
509 {
510 int err;
511
512 err = bt_enable(NULL);
513 if (err != 0) {
514 printk("Bluetooth enable failed (err %d)\n", err);
515 return err;
516 }
517
518 for (size_t i = 0; i < ARRAY_SIZE(streams); i++) {
519 streams[i].ops = &stream_ops;
520 }
521
522 bt_gatt_cb_register(&gatt_callbacks);
523
524 if (IS_ENABLED(CONFIG_BT_AUDIO_TX)) {
525 stream_tx_init();
526 }
527
528 return 0;
529 }
530
scan_and_connect(void)531 static int scan_and_connect(void)
532 {
533 int err;
534
535 start_scan();
536
537 err = k_sem_take(&sem_connected, K_FOREVER);
538 if (err != 0) {
539 printk("failed to take sem_connected (err %d)\n", err);
540 return err;
541 }
542
543 err = k_sem_take(&sem_mtu_exchanged, K_FOREVER);
544 if (err != 0) {
545 printk("failed to take sem_mtu_exchanged (err %d)\n", err);
546 return err;
547 }
548
549 err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
550 if (err != 0) {
551 printk("failed to set security (err %d)\n", err);
552 return err;
553 }
554
555 err = k_sem_take(&sem_security_updated, K_FOREVER);
556 if (err != 0) {
557 printk("failed to take sem_security_updated (err %d)\n", err);
558 return err;
559 }
560
561 return 0;
562 }
563
discover_sinks(void)564 static int discover_sinks(void)
565 {
566 int err;
567
568 unicast_client_cbs.discover = discover_sinks_cb;
569
570 err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SINK);
571 if (err != 0) {
572 printk("Failed to discover sinks: %d\n", err);
573 return err;
574 }
575
576 err = k_sem_take(&sem_sinks_discovered, K_FOREVER);
577 if (err != 0) {
578 printk("failed to take sem_sinks_discovered (err %d)\n", err);
579 return err;
580 }
581
582 return 0;
583 }
584
discover_sources(void)585 static int discover_sources(void)
586 {
587 int err;
588
589 unicast_client_cbs.discover = discover_sources_cb;
590
591 err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SOURCE);
592 if (err != 0) {
593 printk("Failed to discover sources: %d\n", err);
594 return err;
595 }
596
597 err = k_sem_take(&sem_sources_discovered, K_FOREVER);
598 if (err != 0) {
599 printk("failed to take sem_sources_discovered (err %d)\n", err);
600 return err;
601 }
602
603 return 0;
604 }
605
configure_stream(struct bt_bap_stream * stream,struct bt_bap_ep * ep)606 static int configure_stream(struct bt_bap_stream *stream, struct bt_bap_ep *ep)
607 {
608 int err;
609
610 err = bt_bap_stream_config(default_conn, stream, ep, &codec_configuration.codec_cfg);
611 if (err != 0) {
612 return err;
613 }
614
615 err = k_sem_take(&sem_stream_configured, K_FOREVER);
616 if (err != 0) {
617 printk("failed to take sem_stream_configured (err %d)\n", err);
618 return err;
619 }
620
621 return 0;
622 }
623
configure_streams(void)624 static int configure_streams(void)
625 {
626 int err;
627
628 for (size_t i = 0; i < ARRAY_SIZE(sinks); i++) {
629 struct bt_bap_ep *ep = sinks[i].ep;
630 struct bt_bap_stream *stream = &streams[i];
631
632 if (ep == NULL) {
633 continue;
634 }
635
636 err = configure_stream(stream, ep);
637 if (err != 0) {
638 printk("Could not configure sink stream[%zu]: %d\n",
639 i, err);
640 return err;
641 }
642
643 printk("Configured sink stream[%zu]\n", i);
644 configured_sink_stream_count++;
645 }
646
647 for (size_t i = 0; i < ARRAY_SIZE(sources); i++) {
648 struct bt_bap_ep *ep = sources[i];
649 struct bt_bap_stream *stream = &streams[i + configured_sink_stream_count];
650
651 if (ep == NULL) {
652 continue;
653 }
654
655 err = configure_stream(stream, ep);
656 if (err != 0) {
657 printk("Could not configure source stream[%zu]: %d\n",
658 i, err);
659 return err;
660 }
661
662 printk("Configured source stream[%zu]\n", i);
663 configured_source_stream_count++;
664 }
665
666 return 0;
667 }
668
create_group(void)669 static int create_group(void)
670 {
671 const size_t params_count = MAX(configured_sink_stream_count,
672 configured_source_stream_count);
673 struct bt_bap_unicast_group_stream_pair_param pair_params[params_count];
674 struct bt_bap_unicast_group_stream_param stream_params[configured_stream_count];
675 struct bt_bap_unicast_group_param param;
676 int err;
677
678 for (size_t i = 0U; i < configured_stream_count; i++) {
679 stream_params[i].stream = &streams[i];
680 stream_params[i].qos = &codec_configuration.qos;
681 }
682
683 for (size_t i = 0U; i < params_count; i++) {
684 if (i < configured_sink_stream_count) {
685 pair_params[i].tx_param = &stream_params[i];
686 } else {
687 pair_params[i].tx_param = NULL;
688 }
689
690 if (i < configured_source_stream_count) {
691 pair_params[i].rx_param = &stream_params[i + configured_sink_stream_count];
692 } else {
693 pair_params[i].rx_param = NULL;
694 }
695 }
696
697 param.params = pair_params;
698 param.params_count = params_count;
699 param.packing = BT_ISO_PACKING_SEQUENTIAL;
700
701 err = bt_bap_unicast_group_create(¶m, &unicast_group);
702 if (err != 0) {
703 printk("Could not create unicast group (err %d)\n", err);
704 return err;
705 }
706
707 return 0;
708 }
709
delete_group(void)710 static int delete_group(void)
711 {
712 int err;
713
714 err = bt_bap_unicast_group_delete(unicast_group);
715 if (err != 0) {
716 printk("Could not create unicast group (err %d)\n", err);
717 return err;
718 }
719
720 return 0;
721 }
722
set_stream_qos(void)723 static int set_stream_qos(void)
724 {
725 int err;
726
727 err = bt_bap_stream_qos(default_conn, unicast_group);
728 if (err != 0) {
729 printk("Unable to setup QoS: %d\n", err);
730 return err;
731 }
732
733 for (size_t i = 0U; i < configured_stream_count; i++) {
734 printk("QoS: waiting for %zu streams\n", configured_stream_count);
735 err = k_sem_take(&sem_stream_qos, K_FOREVER);
736 if (err != 0) {
737 printk("failed to take sem_stream_qos (err %d)\n", err);
738 return err;
739 }
740 }
741
742 return 0;
743 }
744
enable_streams(void)745 static int enable_streams(void)
746 {
747 for (size_t i = 0U; i < configured_stream_count; i++) {
748 int err;
749
750 err = bt_bap_stream_enable(&streams[i], codec_configuration.codec_cfg.meta,
751 codec_configuration.codec_cfg.meta_len);
752 if (err != 0) {
753 printk("Unable to enable stream: %d\n", err);
754 return err;
755 }
756
757 err = k_sem_take(&sem_stream_enabled, K_FOREVER);
758 if (err != 0) {
759 printk("failed to take sem_stream_enabled (err %d)\n", err);
760 return err;
761 }
762 }
763
764 return 0;
765 }
766
connect_streams(void)767 static int connect_streams(void)
768 {
769 for (size_t i = 0U; i < configured_stream_count; i++) {
770 int err;
771
772 k_sem_reset(&sem_stream_connected);
773
774 err = bt_bap_stream_connect(&streams[i]);
775 if (err == -EALREADY) {
776 /* We have already connected a paired stream */
777 continue;
778 } else if (err != 0) {
779 printk("Unable to start stream: %d\n", err);
780 return err;
781 }
782
783 err = k_sem_take(&sem_stream_connected, K_FOREVER);
784 if (err != 0) {
785 printk("failed to take sem_stream_connected (err %d)\n", err);
786 return err;
787 }
788 }
789
790 return 0;
791 }
792
stream_dir(const struct bt_bap_stream * stream)793 static enum bt_audio_dir stream_dir(const struct bt_bap_stream *stream)
794 {
795 struct bt_bap_ep_info ep_info;
796 int err;
797
798 err = bt_bap_ep_get_info(stream->ep, &ep_info);
799 if (err != 0) {
800 printk("Failed to get ep info for %p: %d\n", stream, err);
801 __ASSERT_NO_MSG(false);
802
803 return 0;
804 }
805
806 return ep_info.dir;
807 }
808
start_streams(void)809 static int start_streams(void)
810 {
811 for (size_t i = 0U; i < configured_stream_count; i++) {
812 struct bt_bap_stream *stream = &streams[i];
813 int err;
814
815 if (stream_dir(stream) == BT_AUDIO_DIR_SOURCE) {
816 err = bt_bap_stream_start(&streams[i]);
817 if (err != 0) {
818 printk("Unable to start stream: %d\n", err);
819 return err;
820 }
821 } /* Sink streams are started by the unicast server */
822
823 err = k_sem_take(&sem_stream_started, K_FOREVER);
824 if (err != 0) {
825 printk("failed to take sem_stream_started (err %d)\n", err);
826 return err;
827 }
828 }
829
830 return 0;
831 }
832
reset_data(void)833 static void reset_data(void)
834 {
835 k_sem_reset(&sem_connected);
836 k_sem_reset(&sem_disconnected);
837 k_sem_reset(&sem_mtu_exchanged);
838 k_sem_reset(&sem_security_updated);
839 k_sem_reset(&sem_sinks_discovered);
840 k_sem_reset(&sem_sources_discovered);
841 k_sem_reset(&sem_stream_configured);
842 k_sem_reset(&sem_stream_qos);
843 k_sem_reset(&sem_stream_enabled);
844 k_sem_reset(&sem_stream_started);
845 k_sem_reset(&sem_stream_connected);
846
847 configured_sink_stream_count = 0;
848 configured_source_stream_count = 0;
849 memset(sinks, 0, sizeof(sinks));
850 memset(sources, 0, sizeof(sources));
851 }
852
main(void)853 int main(void)
854 {
855 int err;
856
857 printk("Initializing\n");
858 err = init();
859 if (err != 0) {
860 return 0;
861 }
862 printk("Initialized\n");
863
864 err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
865 if (err != 0) {
866 printk("Failed to register client callbacks: %d", err);
867 return 0;
868 }
869
870 while (true) {
871 reset_data();
872
873 printk("Waiting for connection\n");
874 err = scan_and_connect();
875 if (err != 0) {
876 return 0;
877 }
878 printk("Connected\n");
879
880 printk("Discovering sinks\n");
881 err = discover_sinks();
882 if (err != 0) {
883 return 0;
884 }
885 printk("Sinks discovered\n");
886
887 printk("Discovering sources\n");
888 err = discover_sources();
889 if (err != 0) {
890 return 0;
891 }
892 printk("Sources discovered\n");
893
894 printk("Configuring streams\n");
895 err = configure_streams();
896 if (err != 0) {
897 return 0;
898 }
899
900 if (configured_stream_count == 0U) {
901 printk("No streams were configured\n");
902 return 0;
903 }
904
905 printk("Creating unicast group\n");
906 err = create_group();
907 if (err != 0) {
908 return 0;
909 }
910 printk("Unicast group created\n");
911
912 printk("Setting stream QoS\n");
913 err = set_stream_qos();
914 if (err != 0) {
915 return 0;
916 }
917 printk("Stream QoS Set\n");
918
919 printk("Enabling streams\n");
920 err = enable_streams();
921 if (err != 0) {
922 return 0;
923 }
924 printk("Streams enabled\n");
925
926 printk("Connecting streams\n");
927 err = connect_streams();
928 if (err != 0) {
929 return 0;
930 }
931 printk("Streams connected\n");
932
933 printk("Starting streams\n");
934 err = start_streams();
935 if (err != 0) {
936 return 0;
937 }
938 printk("Streams started\n");
939
940 /* Wait for disconnect */
941 err = k_sem_take(&sem_disconnected, K_FOREVER);
942 if (err != 0) {
943 printk("failed to take sem_disconnected (err %d)\n", err);
944 return 0;
945 }
946
947 printk("Deleting group\n");
948 err = delete_group();
949 if (err != 0) {
950 return 0;
951 }
952 printk("Group deleted\n");
953 }
954 }
955