1 /*
2 * Copyright (c) 2022-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_lc3_preset.h>
16 #include <zephyr/bluetooth/audio/cap.h>
17 #include <zephyr/bluetooth/audio/bap.h>
18 #include <zephyr/bluetooth/audio/csip.h>
19 #include <zephyr/bluetooth/audio/lc3.h>
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/byteorder.h>
22 #include <zephyr/bluetooth/conn.h>
23 #include <zephyr/bluetooth/gap.h>
24 #include <zephyr/bluetooth/gatt.h>
25 #include <zephyr/bluetooth/hci_types.h>
26 #include <zephyr/bluetooth/iso.h>
27 #include <zephyr/bluetooth/uuid.h>
28 #include <zephyr/kernel.h>
29 #include <zephyr/net_buf.h>
30 #include <zephyr/sys/atomic.h>
31 #include <zephyr/sys/byteorder.h>
32 #include <zephyr/sys/printk.h>
33 #include <zephyr/sys/util.h>
34 #include <zephyr/sys/util_macro.h>
35 #include <zephyr/sys_clock.h>
36
37 #include "bstests.h"
38 #include "common.h"
39 #include "bap_common.h"
40
41 #if defined(CONFIG_BT_CAP_INITIATOR_UNICAST)
42 #define UNICAST_SINK_SUPPORTED (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0)
43 #define UNICAST_SRC_SUPPORTED (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0)
44
45 #define CAP_AC_MAX_CONN 2U
46 #define CAP_AC_MAX_SNK (2U * CAP_AC_MAX_CONN)
47 #define CAP_AC_MAX_SRC (2U * CAP_AC_MAX_CONN)
48 #define CAP_AC_MAX_PAIR MAX(CAP_AC_MAX_SNK, CAP_AC_MAX_SRC)
49 #define CAP_AC_MAX_STREAM (CAP_AC_MAX_SNK + CAP_AC_MAX_SRC)
50
51 #define CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED)
52 #define LOCATION (BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT)
53
54 struct cap_initiator_ac_param {
55 char *name;
56 size_t conn_cnt;
57 size_t snk_cnt[CAP_AC_MAX_CONN];
58 size_t src_cnt[CAP_AC_MAX_CONN];
59 size_t snk_chan_cnt;
60 size_t src_chan_cnt;
61 const struct named_lc3_preset *snk_named_preset;
62 const struct named_lc3_preset *src_named_preset;
63 };
64
65 extern enum bst_result_t bst_result;
66
67 static struct bt_bap_lc3_preset unicast_preset_16_2_1 = BT_BAP_LC3_UNICAST_PRESET_16_2_1(
68 BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
69
70 static struct bt_cap_stream unicast_client_sink_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
71 static struct bt_cap_stream
72 unicast_client_source_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
73 static struct bt_bap_ep
74 *unicast_sink_eps[CONFIG_BT_MAX_CONN][CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
75 static struct bt_bap_ep
76 *unicast_source_eps[CONFIG_BT_MAX_CONN][CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
77 static struct unicast_stream unicast_streams[CAP_AC_MAX_STREAM];
78 static struct bt_conn *connected_conns[CAP_AC_MAX_CONN];
79 static size_t connected_conn_cnt;
80 static const struct named_lc3_preset *snk_named_preset;
81 static const struct named_lc3_preset *src_named_preset;
82 static struct bt_cap_stream *non_idle_streams[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT];
83 static size_t non_idle_streams_cnt;
84
85 CREATE_FLAG(flag_discovered);
86 CREATE_FLAG(flag_codec_found);
87 CREATE_FLAG(flag_endpoint_found);
88 CREATE_FLAG(flag_started);
89 CREATE_FLAG(flag_start_failed);
90 CREATE_FLAG(flag_start_timeout);
91 CREATE_FLAG(flag_updated);
92 CREATE_FLAG(flag_stopped);
93 CREATE_FLAG(flag_mtu_exchanged);
94 CREATE_FLAG(flag_sink_discovered);
95 CREATE_FLAG(flag_source_discovered);
96
97 static const struct named_lc3_preset lc3_unicast_presets[] = {
98 {"8_1_1", BT_BAP_LC3_UNICAST_PRESET_8_1_1(LOCATION, CONTEXT)},
99 {"8_2_1", BT_BAP_LC3_UNICAST_PRESET_8_2_1(LOCATION, CONTEXT)},
100 {"16_1_1", BT_BAP_LC3_UNICAST_PRESET_16_1_1(LOCATION, CONTEXT)},
101 {"16_2_1", BT_BAP_LC3_UNICAST_PRESET_16_2_1(LOCATION, CONTEXT)},
102 {"24_1_1", BT_BAP_LC3_UNICAST_PRESET_24_1_1(LOCATION, CONTEXT)},
103 {"24_2_1", BT_BAP_LC3_UNICAST_PRESET_24_2_1(LOCATION, CONTEXT)},
104 {"32_1_1", BT_BAP_LC3_UNICAST_PRESET_32_1_1(LOCATION, CONTEXT)},
105 {"32_2_1", BT_BAP_LC3_UNICAST_PRESET_32_2_1(LOCATION, CONTEXT)},
106 {"441_1_1", BT_BAP_LC3_UNICAST_PRESET_441_1_1(LOCATION, CONTEXT)},
107 {"441_2_1", BT_BAP_LC3_UNICAST_PRESET_441_2_1(LOCATION, CONTEXT)},
108 {"48_1_1", BT_BAP_LC3_UNICAST_PRESET_48_1_1(LOCATION, CONTEXT)},
109 {"48_2_1", BT_BAP_LC3_UNICAST_PRESET_48_2_1(LOCATION, CONTEXT)},
110 {"48_3_1", BT_BAP_LC3_UNICAST_PRESET_48_3_1(LOCATION, CONTEXT)},
111 {"48_4_1", BT_BAP_LC3_UNICAST_PRESET_48_4_1(LOCATION, CONTEXT)},
112 {"48_5_1", BT_BAP_LC3_UNICAST_PRESET_48_5_1(LOCATION, CONTEXT)},
113 {"48_6_1", BT_BAP_LC3_UNICAST_PRESET_48_6_1(LOCATION, CONTEXT)},
114 /* High-reliability presets */
115 {"8_1_2", BT_BAP_LC3_UNICAST_PRESET_8_1_2(LOCATION, CONTEXT)},
116 {"8_2_2", BT_BAP_LC3_UNICAST_PRESET_8_2_2(LOCATION, CONTEXT)},
117 {"16_1_2", BT_BAP_LC3_UNICAST_PRESET_16_1_2(LOCATION, CONTEXT)},
118 {"16_2_2", BT_BAP_LC3_UNICAST_PRESET_16_2_2(LOCATION, CONTEXT)},
119 {"24_1_2", BT_BAP_LC3_UNICAST_PRESET_24_1_2(LOCATION, CONTEXT)},
120 {"24_2_2", BT_BAP_LC3_UNICAST_PRESET_24_2_2(LOCATION, CONTEXT)},
121 {"32_1_2", BT_BAP_LC3_UNICAST_PRESET_32_1_2(LOCATION, CONTEXT)},
122 {"32_2_2", BT_BAP_LC3_UNICAST_PRESET_32_2_2(LOCATION, CONTEXT)},
123 {"441_1_2", BT_BAP_LC3_UNICAST_PRESET_441_1_2(LOCATION, CONTEXT)},
124 {"441_2_2", BT_BAP_LC3_UNICAST_PRESET_441_2_2(LOCATION, CONTEXT)},
125 {"48_1_2", BT_BAP_LC3_UNICAST_PRESET_48_1_2(LOCATION, CONTEXT)},
126 {"48_2_2", BT_BAP_LC3_UNICAST_PRESET_48_2_2(LOCATION, CONTEXT)},
127 {"48_3_2", BT_BAP_LC3_UNICAST_PRESET_48_3_2(LOCATION, CONTEXT)},
128 {"48_4_2", BT_BAP_LC3_UNICAST_PRESET_48_4_2(LOCATION, CONTEXT)},
129 {"48_5_2", BT_BAP_LC3_UNICAST_PRESET_48_5_2(LOCATION, CONTEXT)},
130 {"48_6_2", BT_BAP_LC3_UNICAST_PRESET_48_6_2(LOCATION, CONTEXT)},
131 };
132
unicast_stream_configured(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg_pref * pref)133 static void unicast_stream_configured(struct bt_bap_stream *stream,
134 const struct bt_bap_qos_cfg_pref *pref)
135 {
136 struct bt_cap_stream *cap_stream = cap_stream_from_bap_stream(stream);
137 printk("Configured stream %p\n", stream);
138
139 for (size_t i = 0U; i < ARRAY_SIZE(non_idle_streams); i++) {
140 if (non_idle_streams[i] == NULL) {
141 non_idle_streams[i] = cap_stream;
142 non_idle_streams_cnt++;
143 return;
144 }
145 }
146
147 FAIL("Could not store cap_stream in non_idle_streams\n");
148
149 /* TODO: The preference should be used/taken into account when
150 * setting the QoS
151 */
152 }
153
unicast_stream_qos_set(struct bt_bap_stream * stream)154 static void unicast_stream_qos_set(struct bt_bap_stream *stream)
155 {
156 printk("QoS set stream %p\n", stream);
157 }
158
unicast_stream_enabled(struct bt_bap_stream * stream)159 static void unicast_stream_enabled(struct bt_bap_stream *stream)
160 {
161 printk("Enabled stream %p\n", stream);
162 }
163
unicast_stream_started(struct bt_bap_stream * stream)164 static void unicast_stream_started(struct bt_bap_stream *stream)
165 {
166 printk("Started stream %p\n", stream);
167 }
168
unicast_stream_metadata_updated(struct bt_bap_stream * stream)169 static void unicast_stream_metadata_updated(struct bt_bap_stream *stream)
170 {
171 printk("Metadata updated stream %p\n", stream);
172 }
173
unicast_stream_disabled(struct bt_bap_stream * stream)174 static void unicast_stream_disabled(struct bt_bap_stream *stream)
175 {
176 printk("Disabled stream %p\n", stream);
177 }
178
unicast_stream_stopped(struct bt_bap_stream * stream,uint8_t reason)179 static void unicast_stream_stopped(struct bt_bap_stream *stream, uint8_t reason)
180 {
181 printk("Stopped stream %p with reason 0x%02X\n", stream, reason);
182 }
183
unicast_stream_released(struct bt_bap_stream * stream)184 static void unicast_stream_released(struct bt_bap_stream *stream)
185 {
186 struct bt_cap_stream *cap_stream = cap_stream_from_bap_stream(stream);
187
188 printk("Released stream %p\n", stream);
189
190 for (size_t i = 0U; i < ARRAY_SIZE(non_idle_streams); i++) {
191 if (non_idle_streams[i] == cap_stream) {
192 non_idle_streams[i] = NULL;
193 non_idle_streams_cnt--;
194 return;
195 }
196 }
197
198 FAIL("Could not find cap_stream in non_idle_streams\n");
199 }
200
201 static struct bt_bap_stream_ops unicast_stream_ops = {
202 .configured = unicast_stream_configured,
203 .qos_set = unicast_stream_qos_set,
204 .enabled = unicast_stream_enabled,
205 .started = unicast_stream_started,
206 .metadata_updated = unicast_stream_metadata_updated,
207 .disabled = unicast_stream_disabled,
208 .stopped = unicast_stream_stopped,
209 .released = unicast_stream_released,
210 };
211
cap_discovery_complete_cb(struct bt_conn * conn,int err,const struct bt_csip_set_coordinator_set_member * member,const struct bt_csip_set_coordinator_csis_inst * csis_inst)212 static void cap_discovery_complete_cb(struct bt_conn *conn, int err,
213 const struct bt_csip_set_coordinator_set_member *member,
214 const struct bt_csip_set_coordinator_csis_inst *csis_inst)
215 {
216 if (err != 0) {
217 FAIL("Failed to discover CAS: %d", err);
218
219 return;
220 }
221
222 if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER)) {
223 if (csis_inst == NULL) {
224 FAIL("Failed to discover CAS CSIS");
225
226 return;
227 }
228
229 printk("Found CAS with CSIS %p\n", csis_inst);
230 } else {
231 printk("Found CAS\n");
232 }
233
234 SET_FLAG(flag_discovered);
235 }
236
unicast_start_complete_cb(int err,struct bt_conn * conn)237 static void unicast_start_complete_cb(int err, struct bt_conn *conn)
238 {
239 if (err == -ECANCELED) {
240 SET_FLAG(flag_start_timeout);
241 } else if (err != 0) {
242 printk("Failed to start (failing conn %p): %d\n", conn, err);
243 SET_FLAG(flag_start_failed);
244 } else {
245 SET_FLAG(flag_started);
246 }
247 }
248
unicast_update_complete_cb(int err,struct bt_conn * conn)249 static void unicast_update_complete_cb(int err, struct bt_conn *conn)
250 {
251 if (err != 0) {
252 FAIL("Failed to update (failing conn %p): %d", conn, err);
253
254 return;
255 }
256
257 SET_FLAG(flag_updated);
258 }
259
unicast_stop_complete_cb(int err,struct bt_conn * conn)260 static void unicast_stop_complete_cb(int err, struct bt_conn *conn)
261 {
262 if (err != 0) {
263 FAIL("Failed to stop (failing conn %p): %d", conn, err);
264
265 return;
266 }
267
268 SET_FLAG(flag_stopped);
269 }
270
271 static struct bt_cap_initiator_cb cap_cb = {
272 .unicast_discovery_complete = cap_discovery_complete_cb,
273 .unicast_start_complete = unicast_start_complete_cb,
274 .unicast_update_complete = unicast_update_complete_cb,
275 .unicast_stop_complete = unicast_stop_complete_cb,
276 };
277
add_remote_sink(const struct bt_conn * conn,struct bt_bap_ep * ep)278 static void add_remote_sink(const struct bt_conn *conn, struct bt_bap_ep *ep)
279 {
280 const uint8_t conn_index = bt_conn_index(conn);
281
282 for (size_t i = 0U; i < ARRAY_SIZE(unicast_sink_eps[conn_index]); i++) {
283 if (unicast_sink_eps[conn_index][i] == NULL) {
284 printk("Conn[%u] %p: Sink #%zu: ep %p\n", conn_index, conn, i, ep);
285 unicast_sink_eps[conn_index][i] = ep;
286 return;
287 }
288 }
289
290 FAIL("Could not add sink ep\n");
291 }
292
add_remote_source(const struct bt_conn * conn,struct bt_bap_ep * ep)293 static void add_remote_source(const struct bt_conn *conn, struct bt_bap_ep *ep)
294 {
295 const uint8_t conn_index = bt_conn_index(conn);
296
297 for (size_t i = 0U; i < ARRAY_SIZE(unicast_source_eps[conn_index]); i++) {
298 if (unicast_source_eps[conn_index][i] == NULL) {
299 printk("Conn[%u] %p: Source #%zu: ep %p\n", conn_index, conn, i, ep);
300 unicast_source_eps[conn_index][i] = ep;
301 return;
302 }
303 }
304
305 FAIL("Could not add source ep\n");
306 }
307
print_remote_codec(const struct bt_audio_codec_cap * codec_cap,enum bt_audio_dir dir)308 static void print_remote_codec(const struct bt_audio_codec_cap *codec_cap, enum bt_audio_dir dir)
309 {
310 printk("codec_cap %p dir 0x%02x\n", codec_cap, dir);
311
312 print_codec_cap(codec_cap);
313 }
314
pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_audio_codec_cap * codec_cap)315 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir,
316 const struct bt_audio_codec_cap *codec_cap)
317 {
318 print_remote_codec(codec_cap, dir);
319 SET_FLAG(flag_codec_found);
320 }
321
discover_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)322 static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
323 {
324 if (err != 0) {
325 FAIL("Discovery failed: %d\n", err);
326 return;
327 }
328
329 if (dir == BT_AUDIO_DIR_SINK) {
330 printk("Sink discover complete\n");
331
332 SET_FLAG(flag_sink_discovered);
333 } else if (dir == BT_AUDIO_DIR_SOURCE) {
334 printk("Source discover complete\n");
335
336 SET_FLAG(flag_source_discovered);
337 } else {
338 FAIL("Invalid dir: %u\n", dir);
339 }
340 }
341
endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)342 static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
343 {
344 if (dir == BT_AUDIO_DIR_SINK) {
345 add_remote_sink(conn, ep);
346 SET_FLAG(flag_endpoint_found);
347 } else if (dir == BT_AUDIO_DIR_SOURCE) {
348 add_remote_source(conn, ep);
349 SET_FLAG(flag_endpoint_found);
350 } else {
351 FAIL("Invalid param dir: %u\n", dir);
352 }
353 }
354
355 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
356 .discover = discover_cb,
357 .pac_record = pac_record_cb,
358 .endpoint = endpoint_cb,
359 };
360
att_mtu_updated(struct bt_conn * conn,uint16_t tx,uint16_t rx)361 static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
362 {
363 printk("MTU exchanged\n");
364 SET_FLAG(flag_mtu_exchanged);
365 }
366
367 static struct bt_gatt_cb gatt_callbacks = {
368 .att_mtu_updated = att_mtu_updated,
369 };
370
check_audio_support_and_connect_cb(struct bt_data * data,void * user_data)371 static bool check_audio_support_and_connect_cb(struct bt_data *data, void *user_data)
372 {
373 char addr_str[BT_ADDR_LE_STR_LEN];
374 bt_addr_le_t *addr = user_data;
375 const struct bt_uuid *uuid;
376 uint16_t uuid_val;
377 int err;
378
379 printk("data->type %u\n", data->type);
380
381 if (data->type != BT_DATA_SVC_DATA16) {
382 return true; /* Continue parsing to next AD data type */
383 }
384
385 if (data->data_len < sizeof(uuid_val)) {
386 return true; /* Continue parsing to next AD data type */
387 }
388
389 /* We are looking for the CAS service data */
390 uuid_val = sys_get_le16(data->data);
391 uuid = BT_UUID_DECLARE_16(uuid_val);
392 if (bt_uuid_cmp(uuid, BT_UUID_CAS) != 0) {
393 return true; /* Continue parsing to next AD data type */
394 }
395
396 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
397 printk("Device found: %s\n", addr_str);
398
399 printk("Stopping scan\n");
400 if (bt_le_scan_stop()) {
401 FAIL("Could not stop scan");
402 return false;
403 }
404
405 err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
406 BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN,
407 0, BT_GAP_MS_TO_CONN_TIMEOUT(4000)),
408 &connected_conns[connected_conn_cnt]);
409 if (err != 0) {
410 FAIL("Could not connect to peer: %d", err);
411 }
412
413 return false; /* Stop parsing */
414 }
415
scan_recv_cb(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)416 static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf)
417 {
418 struct bt_conn *conn;
419
420 conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, info->addr);
421 if (conn != NULL) {
422 /* Already connected to this device */
423 bt_conn_unref(conn);
424 return;
425 }
426
427 /* Check for connectable, extended advertising */
428 if (((info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0) &&
429 ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE)) != 0) {
430 /* Check for TMAS support in advertising data */
431 bt_data_parse(buf, check_audio_support_and_connect_cb, (void *)info->addr);
432 }
433 }
434
init(void)435 static void init(void)
436 {
437 static struct bt_le_scan_cb scan_callbacks = {
438 .recv = scan_recv_cb,
439 };
440 int err;
441
442 err = bt_enable(NULL);
443 if (err != 0) {
444 FAIL("Bluetooth enable failed (err %d)\n", err);
445 return;
446 }
447
448 bt_gatt_cb_register(&gatt_callbacks);
449 err = bt_le_scan_cb_register(&scan_callbacks);
450 if (err != 0) {
451 FAIL("Failed to register scan callbacks (err %d)\n", err);
452 return;
453 }
454
455 err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
456 if (err != 0) {
457 FAIL("Failed to register BAP unicast client callbacks (err %d)\n", err);
458 return;
459 }
460
461 err = bt_cap_initiator_register_cb(&cap_cb);
462 if (err != 0) {
463 FAIL("Failed to register CAP callbacks (err %d)\n", err);
464 return;
465 }
466
467 for (size_t i = 0; i < ARRAY_SIZE(unicast_client_sink_streams); i++) {
468 bt_cap_stream_ops_register(&unicast_client_sink_streams[i], &unicast_stream_ops);
469 }
470
471 for (size_t i = 0; i < ARRAY_SIZE(unicast_client_source_streams); i++) {
472 bt_cap_stream_ops_register(&unicast_client_source_streams[i], &unicast_stream_ops);
473 }
474
475 for (size_t i = 0; i < ARRAY_SIZE(unicast_streams); i++) {
476 bt_cap_stream_ops_register(&unicast_streams[i].stream, &unicast_stream_ops);
477 }
478 }
479
scan_and_connect(void)480 static void scan_and_connect(void)
481 {
482 int err;
483
484 UNSET_FLAG(flag_connected);
485
486 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
487 if (err != 0) {
488 FAIL("Scanning failed to start (err %d)\n", err);
489 return;
490 }
491
492 printk("Scanning successfully started\n");
493 WAIT_FOR_FLAG(flag_connected);
494 connected_conn_cnt++;
495 }
496
discover_sink(struct bt_conn * conn)497 static void discover_sink(struct bt_conn *conn)
498 {
499 const uint8_t conn_index = bt_conn_index(conn);
500 int err;
501
502 UNSET_FLAG(flag_sink_discovered);
503 UNSET_FLAG(flag_codec_found);
504 UNSET_FLAG(flag_endpoint_found);
505
506 err = bt_bap_unicast_client_discover(conn, BT_AUDIO_DIR_SINK);
507 if (err != 0) {
508 printk("Failed to discover sink: %d\n", err);
509 return;
510 }
511
512 memset(unicast_sink_eps[conn_index], 0, sizeof(unicast_sink_eps[conn_index]));
513
514 WAIT_FOR_FLAG(flag_sink_discovered);
515 WAIT_FOR_FLAG(flag_endpoint_found);
516 WAIT_FOR_FLAG(flag_codec_found);
517 }
518
discover_source(struct bt_conn * conn)519 static void discover_source(struct bt_conn *conn)
520 {
521 const uint8_t conn_index = bt_conn_index(conn);
522 int err;
523
524 UNSET_FLAG(flag_source_discovered);
525 UNSET_FLAG(flag_codec_found);
526 UNSET_FLAG(flag_endpoint_found);
527
528 err = bt_bap_unicast_client_discover(conn, BT_AUDIO_DIR_SOURCE);
529 if (err != 0) {
530 printk("Failed to discover sink: %d\n", err);
531 return;
532 }
533
534 memset(unicast_source_eps[conn_index], 0, sizeof(unicast_source_eps[conn_index]));
535
536 WAIT_FOR_FLAG(flag_source_discovered);
537 WAIT_FOR_FLAG(flag_endpoint_found);
538 WAIT_FOR_FLAG(flag_codec_found);
539 }
540
discover_cas_inval(struct bt_conn * conn)541 static void discover_cas_inval(struct bt_conn *conn)
542 {
543 int err;
544
545 /* Test if it handles concurrent request for same connection */
546 UNSET_FLAG(flag_discovered);
547
548 err = bt_cap_initiator_unicast_discover(conn);
549 if (err != 0) {
550 printk("Failed to discover CAS: %d\n", err);
551 return;
552 }
553
554 err = bt_cap_initiator_unicast_discover(conn);
555 if (err == 0) {
556 FAIL("bt_cap_initiator_unicast_discover while previous discovery has not completed "
557 "did not fail\n");
558 return;
559 }
560
561 WAIT_FOR_FLAG(flag_discovered);
562 }
563
discover_cas(struct bt_conn * conn)564 static void discover_cas(struct bt_conn *conn)
565 {
566 int err;
567
568 UNSET_FLAG(flag_discovered);
569
570 err = bt_cap_initiator_unicast_discover(conn);
571 if (err != 0) {
572 printk("Failed to discover CAS: %d\n", err);
573 return;
574 }
575
576 WAIT_FOR_FLAG(flag_discovered);
577 }
578
unicast_group_create(struct bt_bap_unicast_group ** out_unicast_group)579 static void unicast_group_create(struct bt_bap_unicast_group **out_unicast_group)
580 {
581 struct bt_bap_unicast_group_stream_param group_source_stream_params;
582 struct bt_bap_unicast_group_stream_param group_sink_stream_params;
583 struct bt_bap_unicast_group_stream_pair_param pair_params;
584 struct bt_bap_unicast_group_param group_param;
585 int err;
586
587 group_sink_stream_params.qos = &unicast_preset_16_2_1.qos;
588 group_sink_stream_params.stream = &unicast_client_sink_streams[0].bap_stream;
589 group_source_stream_params.qos = &unicast_preset_16_2_1.qos;
590 group_source_stream_params.stream = &unicast_client_source_streams[0].bap_stream;
591 pair_params.tx_param = &group_sink_stream_params;
592 pair_params.rx_param = &group_source_stream_params;
593
594 group_param.packing = BT_ISO_PACKING_SEQUENTIAL;
595 group_param.params_count = 1;
596 group_param.params = &pair_params;
597
598 err = bt_bap_unicast_group_create(&group_param, out_unicast_group);
599 if (err != 0) {
600 FAIL("Failed to create group: %d\n", err);
601 return;
602 }
603 }
604
unicast_audio_start(struct bt_bap_unicast_group * unicast_group,bool wait)605 static void unicast_audio_start(struct bt_bap_unicast_group *unicast_group, bool wait)
606 {
607 struct bt_cap_unicast_audio_start_stream_param stream_param[2];
608 struct bt_cap_unicast_audio_start_param param;
609 int err;
610
611 param.type = BT_CAP_SET_TYPE_AD_HOC;
612 param.count = ARRAY_SIZE(stream_param);
613 param.stream_params = stream_param;
614 stream_param[0].member.member = default_conn;
615 stream_param[0].stream = &unicast_client_sink_streams[0];
616 stream_param[0].ep = unicast_sink_eps[bt_conn_index(default_conn)][0];
617 stream_param[0].codec_cfg = &unicast_preset_16_2_1.codec_cfg;
618
619 stream_param[1].member.member = default_conn;
620 stream_param[1].stream = &unicast_client_source_streams[0];
621 stream_param[1].ep = unicast_source_eps[bt_conn_index(default_conn)][0];
622 stream_param[1].codec_cfg = &unicast_preset_16_2_1.codec_cfg;
623
624 UNSET_FLAG(flag_started);
625
626 err = bt_cap_initiator_unicast_audio_start(¶m);
627 if (err != 0) {
628 FAIL("Failed to start unicast audio: %d\n", err);
629 return;
630 }
631
632 if (wait) {
633 WAIT_FOR_FLAG(flag_started);
634 }
635 }
636
unicast_audio_update_inval(void)637 static void unicast_audio_update_inval(void)
638 {
639 struct bt_audio_codec_cfg invalid_codec = BT_AUDIO_CODEC_LC3_CONFIG(
640 BT_AUDIO_CODEC_CFG_FREQ_16KHZ, BT_AUDIO_CODEC_CFG_DURATION_10,
641 BT_AUDIO_LOCATION_FRONT_LEFT, 40U, 1, BT_AUDIO_CONTEXT_TYPE_MEDIA);
642 struct bt_cap_unicast_audio_update_stream_param stream_params[1] = {0};
643 struct bt_cap_unicast_audio_update_param param = {0};
644 int err;
645
646 stream_params[0].stream = &unicast_client_sink_streams[0];
647 stream_params[0].meta = unicast_preset_16_2_1.codec_cfg.meta;
648 stream_params[0].meta_len = unicast_preset_16_2_1.codec_cfg.meta_len;
649 param.count = ARRAY_SIZE(stream_params);
650 param.stream_params = stream_params;
651 param.type = BT_CAP_SET_TYPE_AD_HOC;
652
653 err = bt_cap_initiator_unicast_audio_update(NULL);
654 if (err == 0) {
655 FAIL("bt_cap_initiator_unicast_audio_update with NULL params did not fail\n");
656 return;
657 }
658
659 param.count = 0U;
660 err = bt_cap_initiator_unicast_audio_update(¶m);
661 if (err == 0) {
662 FAIL("bt_cap_initiator_unicast_audio_update with 0 param count did not fail\n");
663 return;
664 }
665
666 /* Clear metadata so that it does not contain the mandatory stream context */
667 param.count = ARRAY_SIZE(stream_params);
668 memset(&invalid_codec.meta, 0, sizeof(invalid_codec.meta));
669 stream_params[0].meta = invalid_codec.meta;
670
671 err = bt_cap_initiator_unicast_audio_update(¶m);
672 if (err == 0) {
673 FAIL("bt_cap_initiator_unicast_audio_update with invalid Codec metadata did not "
674 "fail\n");
675 return;
676 }
677 }
678
unicast_audio_update(void)679 static void unicast_audio_update(void)
680 {
681 struct bt_cap_unicast_audio_update_stream_param stream_params[2] = {0};
682 struct bt_cap_unicast_audio_update_param param = {0};
683 uint8_t new_meta[] = {
684 3,
685 BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT,
686 BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED),
687 LONG_META_LEN,
688 BT_AUDIO_METADATA_TYPE_VENDOR,
689 LONG_META,
690 };
691 int err;
692
693 stream_params[0].stream = &unicast_client_sink_streams[0];
694 stream_params[0].meta = new_meta;
695 stream_params[0].meta_len = ARRAY_SIZE(new_meta);
696
697 stream_params[1].stream = &unicast_client_source_streams[0];
698 stream_params[1].meta = new_meta;
699 stream_params[1].meta_len = ARRAY_SIZE(new_meta);
700
701 param.count = ARRAY_SIZE(stream_params);
702 param.stream_params = stream_params;
703 param.type = BT_CAP_SET_TYPE_AD_HOC;
704
705 UNSET_FLAG(flag_updated);
706
707 err = bt_cap_initiator_unicast_audio_update(¶m);
708 if (err != 0) {
709 FAIL("Failed to update unicast audio: %d\n", err);
710 return;
711 }
712
713 WAIT_FOR_FLAG(flag_updated);
714 printk("READ LONG META\n");
715 }
716
unicast_audio_stop(struct bt_bap_unicast_group * unicast_group)717 static void unicast_audio_stop(struct bt_bap_unicast_group *unicast_group)
718 {
719 struct bt_cap_unicast_audio_stop_param param;
720 int err;
721
722 param.type = BT_CAP_SET_TYPE_AD_HOC;
723 param.count = non_idle_streams_cnt;
724 param.streams = non_idle_streams;
725 param.release = false;
726
727 /* Stop without release first to verify that we enter the QoS Configured state */
728 UNSET_FLAG(flag_stopped);
729 printk("Stopping without relasing\n");
730
731 err = bt_cap_initiator_unicast_audio_stop(¶m);
732 if (err != 0) {
733 FAIL("Failed to stop unicast audio without release: %d\n", err);
734 return;
735 }
736
737 WAIT_FOR_FLAG(flag_stopped);
738
739 /* Verify that it cannot be stopped twice */
740 err = bt_cap_initiator_unicast_audio_stop(¶m);
741 if (err == 0) {
742 FAIL("bt_cap_initiator_unicast_audio_stop without release with already-stopped "
743 "streams did not fail\n");
744 return;
745 }
746
747 /* Stop with release first to verify that we enter the idle state */
748 UNSET_FLAG(flag_stopped);
749 param.release = true;
750 printk("Relasing\n");
751
752 err = bt_cap_initiator_unicast_audio_stop(¶m);
753 if (err != 0) {
754 FAIL("Failed to stop unicast audio: %d\n", err);
755 return;
756 }
757
758 WAIT_FOR_FLAG(flag_stopped);
759
760 /* Verify that it cannot be stopped twice */
761 err = bt_cap_initiator_unicast_audio_stop(¶m);
762 if (err == 0) {
763 FAIL("bt_cap_initiator_unicast_audio_stop with already-stopped streams did not "
764 "fail\n");
765 return;
766 }
767 }
768
unicast_audio_cancel(void)769 static void unicast_audio_cancel(void)
770 {
771 int err;
772
773 err = bt_cap_initiator_unicast_audio_cancel();
774 if (err != 0) {
775 FAIL("Failed to cancel unicast audio: %d\n", err);
776 return;
777 }
778 }
779
unicast_group_delete_inval(void)780 static void unicast_group_delete_inval(void)
781 {
782 int err;
783
784 err = bt_bap_unicast_group_delete(NULL);
785 if (err == 0) {
786 FAIL("bt_bap_unicast_group_delete with NULL group did not fail\n");
787 return;
788 }
789 }
790
unicast_group_delete(struct bt_bap_unicast_group * unicast_group)791 static void unicast_group_delete(struct bt_bap_unicast_group *unicast_group)
792 {
793 int err;
794
795 err = bt_bap_unicast_group_delete(unicast_group);
796 if (err != 0) {
797 FAIL("Failed to create group: %d\n", err);
798 return;
799 }
800
801 /* Verify that it cannot be deleted twice */
802 err = bt_bap_unicast_group_delete(unicast_group);
803 if (err == 0) {
804 FAIL("bt_bap_unicast_group_delete with already-deleted unicast group did not "
805 "fail\n");
806 return;
807 }
808 }
809
test_main_cap_initiator_unicast(void)810 static void test_main_cap_initiator_unicast(void)
811 {
812 struct bt_bap_unicast_group *unicast_group;
813 const size_t iterations = 2;
814
815 init();
816
817 scan_and_connect();
818
819 WAIT_FOR_FLAG(flag_mtu_exchanged);
820
821 discover_cas(default_conn);
822 discover_cas(default_conn); /* test that we can discover twice */
823
824 discover_sink(default_conn);
825 discover_source(default_conn);
826
827 for (size_t i = 0U; i < iterations; i++) {
828 printk("\nRunning iteration i=%zu\n\n", i);
829 unicast_group_create(&unicast_group);
830
831 for (size_t j = 0U; j < iterations; j++) {
832 printk("\nRunning iteration j=%zu\n\n", i);
833
834 unicast_audio_start(unicast_group, true);
835
836 unicast_audio_update();
837
838 unicast_audio_stop(unicast_group);
839 }
840
841 unicast_group_delete(unicast_group);
842 unicast_group = NULL;
843 }
844
845 PASS("CAP initiator unicast passed\n");
846 }
847
test_main_cap_initiator_unicast_inval(void)848 static void test_main_cap_initiator_unicast_inval(void)
849 {
850 struct bt_bap_unicast_group *unicast_group;
851
852 init();
853
854 scan_and_connect();
855
856 WAIT_FOR_FLAG(flag_mtu_exchanged);
857
858 discover_cas_inval(default_conn);
859 discover_cas(default_conn);
860
861 discover_sink(default_conn);
862 discover_source(default_conn);
863
864 unicast_group_create(&unicast_group);
865
866 unicast_audio_start(unicast_group, true);
867
868 unicast_audio_update_inval();
869 unicast_audio_update();
870
871 unicast_audio_stop(unicast_group);
872
873 unicast_group_delete_inval();
874 unicast_group_delete(unicast_group);
875 unicast_group = NULL;
876
877 PASS("CAP initiator unicast inval passed\n");
878 }
879
test_cap_initiator_unicast_timeout(void)880 static void test_cap_initiator_unicast_timeout(void)
881 {
882 struct bt_bap_unicast_group *unicast_group;
883 const k_timeout_t timeout = K_SECONDS(10);
884 const size_t iterations = 2;
885
886 init();
887
888 scan_and_connect();
889
890 WAIT_FOR_FLAG(flag_mtu_exchanged);
891
892 discover_cas(default_conn);
893
894 discover_sink(default_conn);
895 discover_source(default_conn);
896
897 unicast_group_create(&unicast_group);
898
899 for (size_t j = 0U; j < iterations; j++) {
900 printk("\nRunning iteration #%zu\n\n", j);
901 unicast_audio_start(unicast_group, false);
902
903 k_sleep(timeout);
904 if ((bool)atomic_get(&flag_started)) {
905 FAIL("Unexpected start complete\n");
906 } else {
907 unicast_audio_cancel();
908 }
909
910 WAIT_FOR_FLAG(flag_start_timeout);
911
912 unicast_audio_stop(unicast_group);
913 }
914
915 unicast_group_delete(unicast_group);
916 unicast_group = NULL;
917
918 PASS("CAP initiator unicast timeout passed\n");
919 }
920
set_invalid_metadata_type(uint8_t type)921 static void set_invalid_metadata_type(uint8_t type)
922 {
923 const uint8_t val = 0xFF;
924 int err;
925
926 err = bt_audio_codec_cfg_meta_set_val(&unicast_preset_16_2_1.codec_cfg, type, &val,
927 sizeof(val));
928 if (err < 0) {
929 FAIL("Failed to set invalid metadata type: %d\n", err);
930 return;
931 }
932 }
933
unset_invalid_metadata_type(uint8_t type)934 static void unset_invalid_metadata_type(uint8_t type)
935 {
936 int err;
937
938 err = bt_audio_codec_cfg_meta_unset_val(&unicast_preset_16_2_1.codec_cfg, type);
939 if (err < 0) {
940 FAIL("Failed to unset invalid metadata type: %d\n", err);
941 return;
942 }
943 }
944
test_cap_initiator_unicast_ase_error(void)945 static void test_cap_initiator_unicast_ase_error(void)
946 {
947 struct bt_bap_unicast_group *unicast_group;
948 const uint8_t inval_type = 0xFD;
949
950 init();
951
952 scan_and_connect();
953
954 WAIT_FOR_FLAG(flag_mtu_exchanged);
955
956 discover_cas(default_conn);
957 discover_sink(default_conn);
958 discover_source(default_conn);
959
960 unicast_group_create(&unicast_group);
961
962 set_invalid_metadata_type(inval_type);
963
964 /* With invalid metadata type, start should fail */
965 unicast_audio_start(unicast_group, false);
966 WAIT_FOR_FLAG(flag_start_failed);
967
968 /* Remove invalid type and retry */
969 unset_invalid_metadata_type(inval_type);
970
971 /* Without invalid metadata type, start should pass */
972 unicast_audio_start(unicast_group, true);
973
974 unicast_audio_stop(unicast_group);
975
976 unicast_group_delete(unicast_group);
977 unicast_group = NULL;
978
979 PASS("CAP initiator unicast ASE error passed\n");
980 }
981
cap_get_named_preset(const char * preset_arg)982 static const struct named_lc3_preset *cap_get_named_preset(const char *preset_arg)
983 {
984 for (size_t i = 0U; i < ARRAY_SIZE(lc3_unicast_presets); i++) {
985 if (strcmp(preset_arg, lc3_unicast_presets[i].name) == 0) {
986 return &lc3_unicast_presets[i];
987 }
988 }
989
990 return NULL;
991 }
992
cap_initiator_ac_create_unicast_group(const struct cap_initiator_ac_param * param,struct unicast_stream * snk_uni_streams[],size_t snk_cnt,struct unicast_stream * src_uni_streams[],size_t src_cnt,struct bt_bap_unicast_group ** unicast_group)993 static int cap_initiator_ac_create_unicast_group(const struct cap_initiator_ac_param *param,
994 struct unicast_stream *snk_uni_streams[],
995 size_t snk_cnt,
996 struct unicast_stream *src_uni_streams[],
997 size_t src_cnt,
998 struct bt_bap_unicast_group **unicast_group)
999 {
1000 struct bt_bap_unicast_group_stream_param snk_group_stream_params[CAP_AC_MAX_SNK] = {0};
1001 struct bt_bap_unicast_group_stream_param src_group_stream_params[CAP_AC_MAX_SRC] = {0};
1002 struct bt_bap_unicast_group_stream_pair_param pair_params[CAP_AC_MAX_PAIR] = {0};
1003 struct bt_bap_unicast_group_param group_param = {0};
1004 struct bt_bap_qos_cfg *snk_qos[CAP_AC_MAX_SNK];
1005 struct bt_bap_qos_cfg *src_qos[CAP_AC_MAX_SRC];
1006 size_t snk_stream_cnt = 0U;
1007 size_t src_stream_cnt = 0U;
1008 size_t pair_cnt = 0U;
1009
1010 for (size_t i = 0U; i < snk_cnt; i++) {
1011 snk_qos[i] = &snk_uni_streams[i]->qos;
1012 }
1013
1014 for (size_t i = 0U; i < src_cnt; i++) {
1015 src_qos[i] = &src_uni_streams[i]->qos;
1016 }
1017
1018 /* Create Group
1019 *
1020 * First setup the individual stream parameters and then match them in pairs by connection
1021 * and direction
1022 */
1023 for (size_t i = 0U; i < snk_cnt; i++) {
1024 snk_group_stream_params[i].qos = snk_qos[i];
1025 snk_group_stream_params[i].stream = &snk_uni_streams[i]->stream.bap_stream;
1026 }
1027 for (size_t i = 0U; i < src_cnt; i++) {
1028 src_group_stream_params[i].qos = src_qos[i];
1029 src_group_stream_params[i].stream = &src_uni_streams[i]->stream.bap_stream;
1030 }
1031
1032 for (size_t i = 0U; i < param->conn_cnt; i++) {
1033 for (size_t j = 0; j < MAX(param->snk_cnt[i], param->src_cnt[i]); j++) {
1034 if (param->snk_cnt[i] > j) {
1035 pair_params[pair_cnt].tx_param =
1036 &snk_group_stream_params[snk_stream_cnt++];
1037 } else {
1038 pair_params[pair_cnt].tx_param = NULL;
1039 }
1040
1041 if (param->src_cnt[i] > j) {
1042 pair_params[pair_cnt].rx_param =
1043 &src_group_stream_params[src_stream_cnt++];
1044 } else {
1045 pair_params[pair_cnt].rx_param = NULL;
1046 }
1047
1048 pair_cnt++;
1049 }
1050 }
1051
1052 group_param.packing = BT_ISO_PACKING_SEQUENTIAL;
1053 group_param.params = pair_params;
1054 group_param.params_count = pair_cnt;
1055
1056 return bt_bap_unicast_group_create(&group_param, unicast_group);
1057 }
1058
cap_initiator_ac_cap_unicast_start(const struct cap_initiator_ac_param * param,struct unicast_stream * snk_uni_streams[],size_t snk_cnt,struct unicast_stream * src_uni_streams[],size_t src_cnt,struct bt_bap_unicast_group * unicast_group)1059 static int cap_initiator_ac_cap_unicast_start(const struct cap_initiator_ac_param *param,
1060 struct unicast_stream *snk_uni_streams[],
1061 size_t snk_cnt,
1062 struct unicast_stream *src_uni_streams[],
1063 size_t src_cnt,
1064 struct bt_bap_unicast_group *unicast_group)
1065 {
1066 struct bt_cap_unicast_audio_start_stream_param stream_params[CAP_AC_MAX_STREAM] = {0};
1067 struct bt_audio_codec_cfg *snk_codec_cfgs[CAP_AC_MAX_SNK] = {0};
1068 struct bt_audio_codec_cfg *src_codec_cfgs[CAP_AC_MAX_SRC] = {0};
1069 struct bt_cap_stream *snk_cap_streams[CAP_AC_MAX_SNK] = {0};
1070 struct bt_cap_stream *src_cap_streams[CAP_AC_MAX_SRC] = {0};
1071 struct bt_cap_unicast_audio_start_param start_param = {0};
1072 struct bt_bap_ep *snk_eps[CAP_AC_MAX_SNK] = {0};
1073 struct bt_bap_ep *src_eps[CAP_AC_MAX_SRC] = {0};
1074 size_t snk_stream_cnt = 0U;
1075 size_t src_stream_cnt = 0U;
1076 size_t stream_cnt = 0U;
1077 size_t snk_ep_cnt = 0U;
1078 size_t src_ep_cnt = 0U;
1079
1080 for (size_t i = 0U; i < param->conn_cnt; i++) {
1081 const uint8_t conn_index = bt_conn_index(connected_conns[i]);
1082 #if UNICAST_SINK_SUPPORTED
1083 for (size_t j = 0U; j < param->snk_cnt[i]; j++) {
1084 snk_eps[snk_ep_cnt] = unicast_sink_eps[conn_index][j];
1085 if (snk_eps[snk_ep_cnt] == NULL) {
1086 FAIL("No sink[%u][%zu] endpoint available\n", conn_index, j);
1087
1088 return -ENODEV;
1089 }
1090 snk_ep_cnt++;
1091 }
1092 #endif /* UNICAST_SINK_SUPPORTED */
1093
1094 #if UNICAST_SRC_SUPPORTED
1095 for (size_t j = 0U; j < param->src_cnt[i]; j++) {
1096 src_eps[src_ep_cnt] = unicast_source_eps[conn_index][j];
1097 if (src_eps[src_ep_cnt] == NULL) {
1098 FAIL("No source[%u][%zu] endpoint available\n", conn_index, j);
1099
1100 return -ENODEV;
1101 }
1102 src_ep_cnt++;
1103 }
1104 #endif /* UNICAST_SRC_SUPPORTED > 0 */
1105 }
1106
1107 if (snk_ep_cnt != snk_cnt) {
1108 FAIL("Sink endpoint and stream count mismatch: %zu != %zu\n", snk_ep_cnt, snk_cnt);
1109
1110 return -EINVAL;
1111 }
1112
1113 if (src_ep_cnt != src_cnt) {
1114 FAIL("Source endpoint and stream count mismatch: %zu != %zu\n", src_ep_cnt,
1115 src_cnt);
1116
1117 return -EINVAL;
1118 }
1119
1120 /* Setup arrays of parameters based on the preset for easier access. This also copies the
1121 * preset so that we can modify them (e.g. update the metadata)
1122 */
1123 for (size_t i = 0U; i < snk_cnt; i++) {
1124 snk_cap_streams[i] = &snk_uni_streams[i]->stream;
1125 snk_codec_cfgs[i] = &snk_uni_streams[i]->codec_cfg;
1126 }
1127
1128 for (size_t i = 0U; i < src_cnt; i++) {
1129 src_cap_streams[i] = &src_uni_streams[i]->stream;
1130 src_codec_cfgs[i] = &src_uni_streams[i]->codec_cfg;
1131 }
1132
1133 /* CAP Start */
1134 for (size_t i = 0U; i < param->conn_cnt; i++) {
1135 for (size_t j = 0U; j < param->snk_cnt[i]; j++) {
1136 struct bt_cap_unicast_audio_start_stream_param *stream_param =
1137 &stream_params[stream_cnt];
1138
1139 stream_param->member.member = connected_conns[i];
1140 stream_param->codec_cfg = snk_codec_cfgs[snk_stream_cnt];
1141 stream_param->ep = snk_eps[snk_stream_cnt];
1142 stream_param->stream = snk_cap_streams[snk_stream_cnt];
1143
1144 snk_stream_cnt++;
1145 stream_cnt++;
1146
1147 /* If we have more than 1 connection or stream in one direction, we set the
1148 * location bit accordingly
1149 */
1150 if (param->conn_cnt > 1U || param->snk_cnt[i] > 1U) {
1151 const int err = bt_audio_codec_cfg_set_chan_allocation(
1152 stream_param->codec_cfg, (enum bt_audio_location)BIT(i));
1153
1154 if (err < 0) {
1155 FAIL("Failed to set channel allocation: %d\n", err);
1156 return err;
1157 }
1158 }
1159 }
1160
1161 for (size_t j = 0U; j < param->src_cnt[i]; j++) {
1162 struct bt_cap_unicast_audio_start_stream_param *stream_param =
1163 &stream_params[stream_cnt];
1164
1165 stream_param->member.member = connected_conns[i];
1166 stream_param->codec_cfg = src_codec_cfgs[src_stream_cnt];
1167 stream_param->ep = src_eps[src_stream_cnt];
1168 stream_param->stream = src_cap_streams[src_stream_cnt];
1169
1170 src_stream_cnt++;
1171 stream_cnt++;
1172
1173 /* If we have more than 1 connection or stream in one direction, we set the
1174 * location bit accordingly
1175 */
1176 if (param->conn_cnt > 1U || param->src_cnt[i] > 1U) {
1177 const int err = bt_audio_codec_cfg_set_chan_allocation(
1178 stream_param->codec_cfg, (enum bt_audio_location)BIT(i));
1179
1180 if (err < 0) {
1181 FAIL("Failed to set channel allocation: %d\n", err);
1182 return err;
1183 }
1184 }
1185 }
1186 }
1187
1188 start_param.stream_params = stream_params;
1189 start_param.count = stream_cnt;
1190 start_param.type = BT_CAP_SET_TYPE_AD_HOC;
1191
1192 return bt_cap_initiator_unicast_audio_start(&start_param);
1193 }
1194
cap_initiator_ac_unicast(const struct cap_initiator_ac_param * param,struct bt_bap_unicast_group ** unicast_group)1195 static int cap_initiator_ac_unicast(const struct cap_initiator_ac_param *param,
1196 struct bt_bap_unicast_group **unicast_group)
1197 {
1198 /* Allocate params large enough for any params, but only use what is required */
1199 struct unicast_stream *snk_uni_streams[CAP_AC_MAX_SNK];
1200 struct unicast_stream *src_uni_streams[CAP_AC_MAX_SRC];
1201 size_t snk_cnt = 0;
1202 size_t src_cnt = 0;
1203 int err;
1204
1205 if (param->conn_cnt > CAP_AC_MAX_CONN) {
1206 FAIL("Invalid conn_cnt: %zu\n", param->conn_cnt);
1207
1208 return -EINVAL;
1209 }
1210
1211 for (size_t i = 0; i < param->conn_cnt; i++) {
1212 /* Verify conn values */
1213 if (param->snk_cnt[i] > CAP_AC_MAX_SNK) {
1214 FAIL("Invalid param->snk_cnt[%zu]: %zu\n", i, param->snk_cnt[i]);
1215
1216 return -EINVAL;
1217 }
1218
1219 if (param->src_cnt[i] > CAP_AC_MAX_SRC) {
1220 FAIL("Invalid param->src_cnt[%zu]: %zu\n", i, param->src_cnt[i]);
1221
1222 return -EINVAL;
1223 }
1224 }
1225
1226 /* Set all endpoints from multiple connections in a single array, and verify that the known
1227 * endpoints matches the audio configuration
1228 */
1229 for (size_t i = 0U; i < param->conn_cnt; i++) {
1230 for (size_t j = 0U; j < param->snk_cnt[i]; j++) {
1231 snk_cnt++;
1232 }
1233
1234 for (size_t j = 0U; j < param->src_cnt[i]; j++) {
1235 src_cnt++;
1236 }
1237 }
1238
1239 /* Setup arrays of parameters based on the preset for easier access. This also copies the
1240 * preset so that we can modify them (e.g. update the metadata)
1241 */
1242 for (size_t i = 0U; i < snk_cnt; i++) {
1243 snk_uni_streams[i] = &unicast_streams[i];
1244
1245 if (param->snk_named_preset == NULL) {
1246 FAIL("No sink preset available\n");
1247 return -EINVAL;
1248 }
1249
1250 copy_unicast_stream_preset(snk_uni_streams[i], param->snk_named_preset);
1251
1252 /* Some audio configuration requires multiple sink channels,
1253 * so multiply the SDU based on the channel count
1254 */
1255 snk_uni_streams[i]->qos.sdu *= param->snk_chan_cnt;
1256 }
1257
1258 for (size_t i = 0U; i < src_cnt; i++) {
1259 src_uni_streams[i] = &unicast_streams[i + snk_cnt];
1260
1261 if (param->src_named_preset == NULL) {
1262 FAIL("No sink preset available\n");
1263 return -EINVAL;
1264 }
1265
1266 copy_unicast_stream_preset(src_uni_streams[i], param->src_named_preset);
1267
1268 /* Some audio configuration requires multiple source channels,
1269 * so multiply the SDU based on the channel count
1270 */
1271 src_uni_streams[i]->qos.sdu *= param->src_chan_cnt;
1272 }
1273
1274 err = cap_initiator_ac_create_unicast_group(param, snk_uni_streams, snk_cnt,
1275 src_uni_streams, src_cnt, unicast_group);
1276 if (err != 0) {
1277 FAIL("Failed to create group: %d\n", err);
1278
1279 return err;
1280 }
1281
1282 UNSET_FLAG(flag_started);
1283
1284 printk("Starting %zu streams for %s\n", snk_cnt + src_cnt, param->name);
1285 err = cap_initiator_ac_cap_unicast_start(param, snk_uni_streams, snk_cnt, src_uni_streams,
1286 src_cnt, *unicast_group);
1287 if (err != 0) {
1288 FAIL("Failed to start unicast audio: %d\n\n", err);
1289
1290 return err;
1291 }
1292
1293 WAIT_FOR_FLAG(flag_started);
1294
1295 return 0;
1296 }
1297
test_cap_initiator_ac(const struct cap_initiator_ac_param * param)1298 static void test_cap_initiator_ac(const struct cap_initiator_ac_param *param)
1299 {
1300 struct bt_bap_unicast_group *unicast_group;
1301
1302 printk("Running test for %s with Sink Preset %s and Source Preset %s\n", param->name,
1303 param->snk_named_preset != NULL ? param->snk_named_preset->name : "None",
1304 param->src_named_preset != NULL ? param->src_named_preset->name : "None");
1305
1306 if (param->conn_cnt > CAP_AC_MAX_CONN) {
1307 FAIL("Invalid conn_cnt: %zu\n", param->conn_cnt);
1308 return;
1309 }
1310
1311 if (param->snk_named_preset == NULL && param->src_named_preset == NULL) {
1312 FAIL("No presets available\n");
1313 return;
1314 }
1315
1316 init();
1317
1318 for (size_t i = 0U; i < param->conn_cnt; i++) {
1319 UNSET_FLAG(flag_mtu_exchanged);
1320
1321 scan_and_connect();
1322
1323 WAIT_FOR_FLAG(flag_mtu_exchanged);
1324
1325 printk("Connected %zu/%zu\n", i + 1, param->conn_cnt);
1326 }
1327
1328 if (connected_conn_cnt < param->conn_cnt) {
1329 FAIL("Only %zu/%u connected devices, please connect additional devices for this "
1330 "audio configuration\n",
1331 connected_conn_cnt, param->conn_cnt);
1332 return;
1333 }
1334
1335 for (size_t i = 0U; i < param->conn_cnt; i++) {
1336 discover_cas(connected_conns[i]);
1337
1338 if (param->snk_cnt[i] > 0U) {
1339 discover_sink(connected_conns[i]);
1340 }
1341
1342 if (param->src_cnt[i] > 0U) {
1343 discover_source(connected_conns[i]);
1344 }
1345 }
1346
1347 cap_initiator_ac_unicast(param, &unicast_group);
1348
1349 unicast_audio_stop(unicast_group);
1350
1351 unicast_group_delete(unicast_group);
1352 unicast_group = NULL;
1353
1354 for (size_t i = 0U; i < param->conn_cnt; i++) {
1355 const int err =
1356 bt_conn_disconnect(connected_conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
1357
1358 if (err != 0) {
1359 FAIL("Failed to disconnect conn[%zu]: %d\n", i, err);
1360 }
1361
1362 bt_conn_unref(connected_conns[i]);
1363 connected_conns[i] = NULL;
1364 }
1365
1366 PASS("CAP initiator passed for %s with Sink Preset %s and Source Preset %s\n", param->name,
1367 param->snk_named_preset != NULL ? param->snk_named_preset->name : "None",
1368 param->src_named_preset != NULL ? param->src_named_preset->name : "None");
1369 }
1370
test_cap_initiator_ac_1(void)1371 static void test_cap_initiator_ac_1(void)
1372 {
1373 const struct cap_initiator_ac_param param = {
1374 .name = "ac_1",
1375 .conn_cnt = 1U,
1376 .snk_cnt = {1U},
1377 .src_cnt = {0U},
1378 .snk_chan_cnt = 1U,
1379 .src_chan_cnt = 0U,
1380 .snk_named_preset = snk_named_preset,
1381 .src_named_preset = NULL,
1382 };
1383
1384 test_cap_initiator_ac(¶m);
1385 }
1386
test_cap_initiator_ac_2(void)1387 static void test_cap_initiator_ac_2(void)
1388 {
1389 const struct cap_initiator_ac_param param = {
1390 .name = "ac_2",
1391 .conn_cnt = 1U,
1392 .snk_cnt = {0U},
1393 .src_cnt = {1U},
1394 .snk_chan_cnt = 0U,
1395 .src_chan_cnt = 1U,
1396 .snk_named_preset = NULL,
1397 .src_named_preset = src_named_preset,
1398 };
1399
1400 test_cap_initiator_ac(¶m);
1401 }
1402
test_cap_initiator_ac_3(void)1403 static void test_cap_initiator_ac_3(void)
1404 {
1405 const struct cap_initiator_ac_param param = {
1406 .name = "ac_3",
1407 .conn_cnt = 1U,
1408 .snk_cnt = {1U},
1409 .src_cnt = {1U},
1410 .snk_chan_cnt = 1U,
1411 .src_chan_cnt = 1U,
1412 .snk_named_preset = snk_named_preset,
1413 .src_named_preset = src_named_preset,
1414 };
1415
1416 test_cap_initiator_ac(¶m);
1417 }
1418
test_cap_initiator_ac_4(void)1419 static void test_cap_initiator_ac_4(void)
1420 {
1421 const struct cap_initiator_ac_param param = {
1422 .name = "ac_4",
1423 .conn_cnt = 1U,
1424 .snk_cnt = {1U},
1425 .src_cnt = {0U},
1426 .snk_chan_cnt = 2U,
1427 .src_chan_cnt = 0U,
1428 .snk_named_preset = snk_named_preset,
1429 .src_named_preset = NULL,
1430 };
1431
1432 test_cap_initiator_ac(¶m);
1433 }
1434
test_cap_initiator_ac_5(void)1435 static void test_cap_initiator_ac_5(void)
1436 {
1437 const struct cap_initiator_ac_param param = {
1438 .name = "ac_5",
1439 .conn_cnt = 1U,
1440 .snk_cnt = {1U},
1441 .src_cnt = {1U},
1442 .snk_chan_cnt = 2U,
1443 .src_chan_cnt = 1U,
1444 .snk_named_preset = snk_named_preset,
1445 .src_named_preset = src_named_preset,
1446 };
1447
1448 test_cap_initiator_ac(¶m);
1449 }
1450
test_cap_initiator_ac_6_i(void)1451 static void test_cap_initiator_ac_6_i(void)
1452 {
1453 const struct cap_initiator_ac_param param = {
1454 .name = "ac_6_i",
1455 .conn_cnt = 1U,
1456 .snk_cnt = {2U},
1457 .src_cnt = {0U},
1458 .snk_chan_cnt = 1U,
1459 .src_chan_cnt = 0U,
1460 .snk_named_preset = snk_named_preset,
1461 .src_named_preset = NULL,
1462 };
1463
1464 test_cap_initiator_ac(¶m);
1465 }
1466
test_cap_initiator_ac_6_ii(void)1467 static void test_cap_initiator_ac_6_ii(void)
1468 {
1469 const struct cap_initiator_ac_param param = {
1470 .name = "ac_6_ii",
1471 .conn_cnt = 2U,
1472 .snk_cnt = {1U, 1U},
1473 .src_cnt = {0U, 0U},
1474 .snk_chan_cnt = 1U,
1475 .src_chan_cnt = 0U,
1476 .snk_named_preset = snk_named_preset,
1477 .src_named_preset = NULL,
1478 };
1479
1480 test_cap_initiator_ac(¶m);
1481 }
1482
test_cap_initiator_ac_7_i(void)1483 static void test_cap_initiator_ac_7_i(void)
1484 {
1485 const struct cap_initiator_ac_param param = {
1486 .name = "ac_7_i",
1487 .conn_cnt = 1U,
1488 /* TODO: These should be in different CIS but will be in the same currently */
1489 .snk_cnt = {1U},
1490 .src_cnt = {1U},
1491 .snk_chan_cnt = 1U,
1492 .src_chan_cnt = 1U,
1493 .snk_named_preset = snk_named_preset,
1494 .src_named_preset = src_named_preset,
1495 };
1496
1497 test_cap_initiator_ac(¶m);
1498 }
1499
test_cap_initiator_ac_7_ii(void)1500 static void test_cap_initiator_ac_7_ii(void)
1501 {
1502 const struct cap_initiator_ac_param param = {
1503 .name = "ac_7_ii",
1504 .conn_cnt = 2U,
1505 .snk_cnt = {1U, 0U},
1506 .src_cnt = {0U, 1U},
1507 .snk_chan_cnt = 1U,
1508 .src_chan_cnt = 1U,
1509 .snk_named_preset = snk_named_preset,
1510 .src_named_preset = src_named_preset,
1511 };
1512
1513 test_cap_initiator_ac(¶m);
1514 }
1515
test_cap_initiator_ac_8_i(void)1516 static void test_cap_initiator_ac_8_i(void)
1517 {
1518 const struct cap_initiator_ac_param param = {
1519 .name = "ac_8_i",
1520 .conn_cnt = 1U,
1521 .snk_cnt = {2U},
1522 .src_cnt = {1U},
1523 .snk_chan_cnt = 1U,
1524 .src_chan_cnt = 1U,
1525 .snk_named_preset = snk_named_preset,
1526 .src_named_preset = src_named_preset,
1527 };
1528
1529 test_cap_initiator_ac(¶m);
1530 }
1531
test_cap_initiator_ac_8_ii(void)1532 static void test_cap_initiator_ac_8_ii(void)
1533 {
1534 const struct cap_initiator_ac_param param = {
1535 .name = "ac_8_ii",
1536 .conn_cnt = 2U,
1537 .snk_cnt = {1U, 1U},
1538 .src_cnt = {1U, 0U},
1539 .snk_chan_cnt = 1U,
1540 .src_chan_cnt = 1U,
1541 .snk_named_preset = snk_named_preset,
1542 .src_named_preset = src_named_preset,
1543 };
1544
1545 test_cap_initiator_ac(¶m);
1546 }
1547
test_cap_initiator_ac_9_i(void)1548 static void test_cap_initiator_ac_9_i(void)
1549 {
1550 const struct cap_initiator_ac_param param = {
1551 .name = "ac_9_i",
1552 .conn_cnt = 1U,
1553 .snk_cnt = {0U},
1554 .src_cnt = {2U},
1555 .snk_chan_cnt = 0U,
1556 .src_chan_cnt = 1U,
1557 .snk_named_preset = NULL,
1558 .src_named_preset = src_named_preset,
1559 };
1560
1561 test_cap_initiator_ac(¶m);
1562 }
1563
test_cap_initiator_ac_9_ii(void)1564 static void test_cap_initiator_ac_9_ii(void)
1565 {
1566 const struct cap_initiator_ac_param param = {
1567 .name = "ac_9_ii",
1568 .conn_cnt = 2U,
1569 .snk_cnt = {0U, 0U},
1570 .src_cnt = {1U, 1U},
1571 .snk_chan_cnt = 0U,
1572 .src_chan_cnt = 1U,
1573 .snk_named_preset = NULL,
1574 .src_named_preset = src_named_preset,
1575 };
1576
1577 test_cap_initiator_ac(¶m);
1578 }
test_cap_initiator_ac_10(void)1579 static void test_cap_initiator_ac_10(void)
1580 {
1581 const struct cap_initiator_ac_param param = {
1582 .name = "ac_10",
1583 .conn_cnt = 1U,
1584 .snk_cnt = {0U},
1585 .src_cnt = {1U},
1586 .snk_chan_cnt = 1U,
1587 .src_chan_cnt = 2U,
1588 .snk_named_preset = snk_named_preset,
1589 .src_named_preset = src_named_preset,
1590 };
1591
1592 test_cap_initiator_ac(¶m);
1593 }
1594
test_cap_initiator_ac_11_i(void)1595 static void test_cap_initiator_ac_11_i(void)
1596 {
1597 const struct cap_initiator_ac_param param = {
1598 .name = "ac_11_i",
1599 .conn_cnt = 1U,
1600 .snk_cnt = {2U},
1601 .src_cnt = {2U},
1602 .snk_chan_cnt = 1U,
1603 .src_chan_cnt = 1U,
1604 .snk_named_preset = snk_named_preset,
1605 .src_named_preset = src_named_preset,
1606 };
1607
1608 test_cap_initiator_ac(¶m);
1609 }
1610
test_cap_initiator_ac_11_ii(void)1611 static void test_cap_initiator_ac_11_ii(void)
1612 {
1613 const struct cap_initiator_ac_param param = {
1614 .name = "ac_11_ii",
1615 .conn_cnt = 2U,
1616 .snk_cnt = {1U, 1U},
1617 .src_cnt = {1U, 1U},
1618 .snk_chan_cnt = 1U,
1619 .src_chan_cnt = 1U,
1620 .snk_named_preset = snk_named_preset,
1621 .src_named_preset = src_named_preset,
1622 };
1623
1624 test_cap_initiator_ac(¶m);
1625 }
1626
test_args(int argc,char * argv[])1627 static void test_args(int argc, char *argv[])
1628 {
1629 for (size_t argn = 0; argn < argc; argn++) {
1630 const char *arg = argv[argn];
1631
1632 if (strcmp(arg, "sink_preset") == 0) {
1633 const char *preset_arg = argv[++argn];
1634
1635 snk_named_preset = cap_get_named_preset(preset_arg);
1636 if (snk_named_preset == NULL) {
1637 FAIL("Failed to get sink preset from %s\n", preset_arg);
1638 }
1639 } else if (strcmp(arg, "source_preset") == 0) {
1640 const char *preset_arg = argv[++argn];
1641
1642 src_named_preset = cap_get_named_preset(preset_arg);
1643 if (src_named_preset == NULL) {
1644 FAIL("Failed to get source preset from %s\n", preset_arg);
1645 }
1646 } else {
1647 FAIL("Invalid arg: %s\n", arg);
1648 }
1649 }
1650 }
1651
1652 static const struct bst_test_instance test_cap_initiator_unicast[] = {
1653 {
1654 .test_id = "cap_initiator_unicast",
1655 .test_pre_init_f = test_init,
1656 .test_tick_f = test_tick,
1657 .test_main_f = test_main_cap_initiator_unicast,
1658 },
1659 {
1660 .test_id = "cap_initiator_unicast_timeout",
1661 .test_pre_init_f = test_init,
1662 .test_tick_f = test_tick,
1663 .test_main_f = test_cap_initiator_unicast_timeout,
1664 },
1665 {
1666 .test_id = "cap_initiator_unicast_ase_error",
1667 .test_pre_init_f = test_init,
1668 .test_tick_f = test_tick,
1669 .test_main_f = test_cap_initiator_unicast_ase_error,
1670 },
1671 {
1672 .test_id = "cap_initiator_unicast_inval",
1673 .test_pre_init_f = test_init,
1674 .test_tick_f = test_tick,
1675 .test_main_f = test_main_cap_initiator_unicast_inval,
1676 },
1677 {
1678 .test_id = "cap_initiator_ac_1",
1679 .test_pre_init_f = test_init,
1680 .test_tick_f = test_tick,
1681 .test_main_f = test_cap_initiator_ac_1,
1682 .test_args_f = test_args,
1683 },
1684 {
1685 .test_id = "cap_initiator_ac_2",
1686 .test_pre_init_f = test_init,
1687 .test_tick_f = test_tick,
1688 .test_main_f = test_cap_initiator_ac_2,
1689 .test_args_f = test_args,
1690 },
1691 {
1692 .test_id = "cap_initiator_ac_3",
1693 .test_pre_init_f = test_init,
1694 .test_tick_f = test_tick,
1695 .test_main_f = test_cap_initiator_ac_3,
1696 .test_args_f = test_args,
1697 },
1698 {
1699 .test_id = "cap_initiator_ac_4",
1700 .test_pre_init_f = test_init,
1701 .test_tick_f = test_tick,
1702 .test_main_f = test_cap_initiator_ac_4,
1703 .test_args_f = test_args,
1704 },
1705 {
1706 .test_id = "cap_initiator_ac_5",
1707 .test_pre_init_f = test_init,
1708 .test_tick_f = test_tick,
1709 .test_main_f = test_cap_initiator_ac_5,
1710 .test_args_f = test_args,
1711 },
1712 {
1713 .test_id = "cap_initiator_ac_6_i",
1714 .test_pre_init_f = test_init,
1715 .test_tick_f = test_tick,
1716 .test_main_f = test_cap_initiator_ac_6_i,
1717 .test_args_f = test_args,
1718 },
1719 {
1720 .test_id = "cap_initiator_ac_6_ii",
1721 .test_pre_init_f = test_init,
1722 .test_tick_f = test_tick,
1723 .test_main_f = test_cap_initiator_ac_6_ii,
1724 .test_args_f = test_args,
1725 },
1726 {
1727 .test_id = "cap_initiator_ac_7_i",
1728 .test_pre_init_f = test_init,
1729 .test_tick_f = test_tick,
1730 .test_main_f = test_cap_initiator_ac_7_i,
1731 .test_args_f = test_args,
1732 },
1733 {
1734 .test_id = "cap_initiator_ac_7_ii",
1735 .test_pre_init_f = test_init,
1736 .test_tick_f = test_tick,
1737 .test_main_f = test_cap_initiator_ac_7_ii,
1738 .test_args_f = test_args,
1739 },
1740 {
1741 .test_id = "cap_initiator_ac_8_i",
1742 .test_pre_init_f = test_init,
1743 .test_tick_f = test_tick,
1744 .test_main_f = test_cap_initiator_ac_8_i,
1745 .test_args_f = test_args,
1746 },
1747 {
1748 .test_id = "cap_initiator_ac_8_ii",
1749 .test_pre_init_f = test_init,
1750 .test_tick_f = test_tick,
1751 .test_main_f = test_cap_initiator_ac_8_ii,
1752 .test_args_f = test_args,
1753 },
1754 {
1755 .test_id = "cap_initiator_ac_9_i",
1756 .test_pre_init_f = test_init,
1757 .test_tick_f = test_tick,
1758 .test_main_f = test_cap_initiator_ac_9_i,
1759 .test_args_f = test_args,
1760 },
1761 {
1762 .test_id = "cap_initiator_ac_9_ii",
1763 .test_pre_init_f = test_init,
1764 .test_tick_f = test_tick,
1765 .test_main_f = test_cap_initiator_ac_9_ii,
1766 .test_args_f = test_args,
1767 },
1768 {
1769 .test_id = "cap_initiator_ac_10",
1770 .test_pre_init_f = test_init,
1771 .test_tick_f = test_tick,
1772 .test_main_f = test_cap_initiator_ac_10,
1773 .test_args_f = test_args,
1774 },
1775 {
1776 .test_id = "cap_initiator_ac_11_i",
1777 .test_pre_init_f = test_init,
1778 .test_tick_f = test_tick,
1779 .test_main_f = test_cap_initiator_ac_11_i,
1780 .test_args_f = test_args,
1781 },
1782 {
1783 .test_id = "cap_initiator_ac_11_ii",
1784 .test_pre_init_f = test_init,
1785 .test_tick_f = test_tick,
1786 .test_main_f = test_cap_initiator_ac_11_ii,
1787 .test_args_f = test_args,
1788 },
1789 BSTEST_END_MARKER,
1790 };
1791
test_cap_initiator_unicast_install(struct bst_test_list * tests)1792 struct bst_test_list *test_cap_initiator_unicast_install(struct bst_test_list *tests)
1793 {
1794 return bst_add_tests(tests, test_cap_initiator_unicast);
1795 }
1796
1797 #else /* !CONFIG_BT_CAP_INITIATOR_UNICAST */
1798
test_cap_initiator_unicast_install(struct bst_test_list * tests)1799 struct bst_test_list *test_cap_initiator_unicast_install(struct bst_test_list *tests)
1800 {
1801 return tests;
1802 }
1803
1804 #endif /* CONFIG_BT_CAP_INITIATOR_UNICAST */
1805