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(¶m, 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(¶m, &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(¶m, &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, ¶m);
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