1 /*
2  * Copyright (c) 2019 Bose Corporation
3  * Copyright (c) 2020-2024 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
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/audio/bap.h>
14 #include <zephyr/bluetooth/audio/csip.h>
15 #include <zephyr/bluetooth/addr.h>
16 #include <zephyr/bluetooth/bluetooth.h>
17 #include <zephyr/bluetooth/conn.h>
18 #include <zephyr/bluetooth/gap.h>
19 #include <zephyr/bluetooth/hci_types.h>
20 #include <zephyr/kernel.h>
21 #include <zephyr/net_buf.h>
22 #include <zephyr/sys/printk.h>
23 #include <zephyr/sys/util.h>
24 
25 #include "bstests.h"
26 #include "common.h"
27 
28 #ifdef CONFIG_BT_CSIP_SET_COORDINATOR
29 
30 static bool expect_rank = true;
31 static bool expect_set_size = true;
32 static bool expect_lockable = true;
33 
34 extern enum bst_result_t bst_result;
35 static volatile bool discovered;
36 static volatile bool discover_timed_out;
37 static volatile bool set_locked;
38 static volatile bool set_unlocked;
39 static volatile bool ordered_access_locked;
40 static volatile bool ordered_access_unlocked;
41 static const struct bt_csip_set_coordinator_csis_inst *primary_inst;
42 CREATE_FLAG(flag_sirk_changed);
43 
44 static uint8_t connected_member_count;
45 static uint8_t members_found;
46 static struct k_work_delayable discover_members_timer;
47 static bt_addr_le_t addr_found[CONFIG_BT_MAX_CONN];
48 static struct bt_conn *conns[CONFIG_BT_MAX_CONN];
49 static const struct bt_csip_set_coordinator_set_member *set_members[CONFIG_BT_MAX_CONN];
50 
51 static void csip_set_coordinator_lock_set_cb(int err);
52 
csip_set_coordinator_lock_release_cb(int err)53 static void csip_set_coordinator_lock_release_cb(int err)
54 {
55 	printk("%s\n", __func__);
56 
57 	if (err != 0) {
58 		FAIL("Release sets failed (%d)\n", err);
59 		return;
60 	}
61 
62 	set_unlocked = true;
63 }
64 
csip_set_coordinator_lock_set_cb(int err)65 static void csip_set_coordinator_lock_set_cb(int err)
66 {
67 	printk("%s\n", __func__);
68 
69 	if (err != 0) {
70 		FAIL("Lock sets failed (%d)\n", err);
71 		return;
72 	}
73 
74 	set_locked = true;
75 }
76 
csip_discover_cb(struct bt_conn * conn,const struct bt_csip_set_coordinator_set_member * member,int err,size_t set_count)77 static void csip_discover_cb(struct bt_conn *conn,
78 			     const struct bt_csip_set_coordinator_set_member *member,
79 			     int err, size_t set_count)
80 {
81 	uint8_t conn_index;
82 
83 	printk("%s\n", __func__);
84 
85 	if (err != 0 || set_count == 0U) {
86 		FAIL("Discover failed (%d)\n", err);
87 		return;
88 	}
89 
90 	conn_index = bt_conn_index(conn);
91 
92 	for (size_t i = 0U; i < set_count; i++) {
93 		const uint8_t rank = member->insts[i].info.rank;
94 		const uint8_t set_size = member->insts[i].info.set_size;
95 		const uint8_t lockable = member->insts[i].info.lockable;
96 
97 		printk("CSIS[%zu]: %p\n", i, &member->insts[i]);
98 		printk("\tRank: %u\n", rank);
99 		printk("\tSet Size: %u\n", set_size);
100 		printk("\tLockable: %u\n", lockable);
101 
102 		if ((expect_rank && rank == 0U) || (!expect_rank && rank != 0U)) {
103 			FAIL("Unexpected rank: %u %u", expect_rank, rank);
104 
105 			return;
106 		}
107 
108 		if ((expect_set_size && set_size == 0U) || (!expect_set_size && set_size != 0U)) {
109 			FAIL("Unexpected set_size: %u %u", expect_set_size, set_size);
110 
111 			return;
112 		}
113 
114 		if (expect_lockable != lockable) {
115 			FAIL("Unexpected lockable: %u %u", expect_lockable, lockable);
116 
117 			return;
118 		}
119 	}
120 
121 	if (primary_inst == NULL) {
122 		primary_inst = &member->insts[0];
123 	}
124 
125 	set_members[conn_index] = member;
126 	discovered = true;
127 }
128 
csip_lock_changed_cb(struct bt_csip_set_coordinator_csis_inst * inst,bool locked)129 static void csip_lock_changed_cb(struct bt_csip_set_coordinator_csis_inst *inst,
130 				 bool locked)
131 {
132 	printk("inst %p %s\n", inst, locked ? "locked" : "released");
133 }
134 
csip_sirk_changed_cb(struct bt_csip_set_coordinator_csis_inst * inst)135 static void csip_sirk_changed_cb(struct bt_csip_set_coordinator_csis_inst *inst)
136 {
137 	printk("Inst %p SIRK changed\n", inst);
138 
139 	SET_FLAG(flag_sirk_changed);
140 }
141 
csip_set_coordinator_ordered_access_cb(const struct bt_csip_set_coordinator_set_info * set_info,int err,bool locked,struct bt_csip_set_coordinator_set_member * member)142 static void csip_set_coordinator_ordered_access_cb(
143 	const struct bt_csip_set_coordinator_set_info *set_info, int err,
144 	bool locked,  struct bt_csip_set_coordinator_set_member *member)
145 {
146 	if (err) {
147 		FAIL("Ordered access failed with err %d\n", err);
148 	} else if (locked) {
149 		printk("Ordered access procedure locked member %p\n", member);
150 		ordered_access_locked = true;
151 	} else {
152 		printk("Ordered access procedure finished\n");
153 		ordered_access_unlocked = true;
154 	}
155 }
156 
157 static struct bt_csip_set_coordinator_cb cbs = {
158 	.lock_set = csip_set_coordinator_lock_set_cb,
159 	.release_set = csip_set_coordinator_lock_release_cb,
160 	.discover = csip_discover_cb,
161 	.lock_changed = csip_lock_changed_cb,
162 	.sirk_changed = csip_sirk_changed_cb,
163 	.ordered_access = csip_set_coordinator_ordered_access_cb,
164 };
165 
csip_set_coordinator_oap_cb(const struct bt_csip_set_coordinator_set_info * set_info,struct bt_csip_set_coordinator_set_member * members[],size_t count)166 static bool csip_set_coordinator_oap_cb(const struct bt_csip_set_coordinator_set_info *set_info,
167 					struct bt_csip_set_coordinator_set_member *members[],
168 					size_t count)
169 {
170 	for (size_t i = 0; i < count; i++) {
171 		printk("Ordered access for members[%zu]: %p\n", i, members[i]);
172 	}
173 
174 	return true;
175 }
176 
is_discovered(const bt_addr_le_t * addr)177 static bool is_discovered(const bt_addr_le_t *addr)
178 {
179 	for (int i = 0; i < members_found; i++) {
180 		if (bt_addr_le_eq(addr, &addr_found[i])) {
181 			return true;
182 		}
183 	}
184 	return false;
185 }
186 
csip_found(struct bt_data * data,void * user_data)187 static bool csip_found(struct bt_data *data, void *user_data)
188 {
189 	if (primary_inst == NULL ||
190 	    bt_csip_set_coordinator_is_set_member(primary_inst->info.sirk, data)) {
191 		const bt_addr_le_t *addr = user_data;
192 		char addr_str[BT_ADDR_LE_STR_LEN];
193 
194 		bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
195 		printk("Found CSIP advertiser with address %s\n", addr_str);
196 
197 		if (is_discovered(addr)) {
198 			printk("Set member already found\n");
199 			/* Stop parsing */
200 			return false;
201 		}
202 
203 		bt_addr_le_copy(&addr_found[members_found++], addr);
204 
205 		if (primary_inst == NULL || primary_inst->info.set_size == 0) {
206 			printk("Found member %u\n", members_found);
207 		} else {
208 			printk("Found member (%u / %u)\n", members_found,
209 			       primary_inst->info.set_size);
210 		}
211 
212 		/* Stop parsing */
213 		return false;
214 	}
215 	/* Continue parsing */
216 	return true;
217 }
218 
csip_set_coordinator_scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * ad)219 static void csip_set_coordinator_scan_recv(const struct bt_le_scan_recv_info *info,
220 					   struct net_buf_simple *ad)
221 {
222 	/* We're only interested in connectable events */
223 	if ((info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0U &&
224 	    (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0U) {
225 		bt_data_parse(ad, csip_found, (void *)info->addr);
226 	}
227 }
228 
229 static struct bt_le_scan_cb csip_set_coordinator_scan_callbacks = {
230 	.recv = csip_set_coordinator_scan_recv
231 };
232 
discover_members_timer_handler(struct k_work * work)233 static void discover_members_timer_handler(struct k_work *work)
234 {
235 	if (primary_inst->info.set_size > 0) {
236 		FAIL("Could not find all members (%u / %u)\n", members_found,
237 		     primary_inst->info.set_size);
238 	} else {
239 		discover_timed_out = true;
240 	}
241 }
242 
ordered_access(const struct bt_csip_set_coordinator_set_member ** members,size_t count,bool expect_locked)243 static void ordered_access(const struct bt_csip_set_coordinator_set_member **members,
244 			   size_t count, bool expect_locked)
245 {
246 	int err;
247 
248 	printk("Performing ordered access, expecting %s\n",
249 	       expect_locked ? "locked" : "unlocked");
250 
251 	if (expect_locked) {
252 		ordered_access_locked = false;
253 	} else {
254 		ordered_access_unlocked = false;
255 	}
256 
257 	err = bt_csip_set_coordinator_ordered_access(members, count, &primary_inst->info,
258 						     csip_set_coordinator_oap_cb);
259 	if (err != 0) {
260 		FAIL("Failed to do CSIP set coordinator ordered access (%d)",
261 		      err);
262 		return;
263 	}
264 
265 	if (expect_locked) {
266 		WAIT_FOR_COND(ordered_access_locked);
267 	} else {
268 		WAIT_FOR_COND(ordered_access_unlocked);
269 	}
270 }
271 
discover_csis(struct bt_conn * conn)272 static void discover_csis(struct bt_conn *conn)
273 {
274 	int err;
275 
276 	discovered = false;
277 
278 	err = bt_csip_set_coordinator_discover(conns[bt_conn_index(conn)]);
279 	if (err != 0) {
280 		FAIL("Failed to initialize set coordinator for connection %d\n", err);
281 		return;
282 	}
283 
284 	WAIT_FOR_COND(discovered);
285 }
286 
init(void)287 static void init(void)
288 {
289 	int err;
290 
291 	err = bt_enable(NULL);
292 	if (err != 0) {
293 		FAIL("Bluetooth init failed (err %d)\n", err);
294 		return;
295 	}
296 
297 	printk("Audio Client: Bluetooth initialized\n");
298 
299 	bt_csip_set_coordinator_register_cb(&cbs);
300 	k_work_init_delayable(&discover_members_timer,
301 			      discover_members_timer_handler);
302 	bt_le_scan_cb_register(&csip_set_coordinator_scan_callbacks);
303 }
304 
connect_set(void)305 static void connect_set(void)
306 {
307 	char addr[BT_ADDR_LE_STR_LEN];
308 	int err;
309 
310 	connected_member_count = 0U;
311 
312 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
313 	if (err != 0) {
314 		FAIL("Scanning failed to start (err %d)\n", err);
315 
316 		return;
317 	}
318 
319 	printk("Scanning successfully started\n");
320 
321 	WAIT_FOR_COND(members_found == 1U);
322 
323 	printk("Stopping scan\n");
324 	err = bt_le_scan_stop();
325 	if (err != 0) {
326 		FAIL("Could not stop scan");
327 
328 		return;
329 	}
330 
331 	bt_addr_le_to_str(&addr_found[0], addr, sizeof(addr));
332 	err = bt_conn_le_create(&addr_found[0], BT_CONN_LE_CREATE_CONN, BT_BAP_CONN_PARAM_RELAXED,
333 				&conns[0]);
334 	if (err != 0) {
335 		FAIL("Failed to connect to %s: %d\n", err);
336 
337 		return;
338 	}
339 	printk("Connecting to %s\n", addr);
340 
341 	WAIT_FOR_FLAG(flag_connected);
342 	connected_member_count++;
343 
344 	discover_csis(conns[0]);
345 	discover_csis(conns[0]); /* test that we can discover twice */
346 
347 	err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL);
348 	if (err != 0) {
349 		FAIL("Could not start scan: %d", err);
350 
351 		return;
352 	}
353 
354 	err = k_work_reschedule(&discover_members_timer,
355 				BT_CSIP_SET_COORDINATOR_DISCOVER_TIMER_VALUE);
356 	if (err < 0) { /* Can return 0, 1 and 2 for success */
357 		FAIL("Could not schedule discover_members_timer %d", err);
358 
359 		return;
360 	}
361 
362 	if (primary_inst->info.set_size > 0U) {
363 		WAIT_FOR_COND(members_found == primary_inst->info.set_size);
364 
365 		(void)k_work_cancel_delayable(&discover_members_timer);
366 	} else {
367 		WAIT_FOR_COND(discover_timed_out);
368 	}
369 
370 	err = bt_le_scan_stop();
371 	if (err != 0) {
372 		FAIL("Scanning failed to stop (err %d)\n", err);
373 
374 		return;
375 	}
376 
377 	for (uint8_t i = 1; i < members_found; i++) {
378 		bt_addr_le_to_str(&addr_found[i], addr, sizeof(addr));
379 
380 		UNSET_FLAG(flag_connected);
381 		printk("Connecting to member[%d] (%s)", i, addr);
382 		err = bt_conn_le_create(&addr_found[i], BT_CONN_LE_CREATE_CONN,
383 					BT_LE_CONN_PARAM_DEFAULT, &conns[i]);
384 		if (err != 0) {
385 			FAIL("Failed to connect to %s: %d\n", addr, err);
386 
387 			return;
388 		}
389 
390 		printk("Connected to %s\n", addr);
391 		WAIT_FOR_FLAG(flag_connected);
392 		connected_member_count++;
393 
394 		printk("Doing discovery on member[%u]", i);
395 		discover_csis(conns[i]);
396 	}
397 }
398 
disconnect_set(void)399 static void disconnect_set(void)
400 {
401 	for (uint8_t i = 0; i < connected_member_count; i++) {
402 		char addr[BT_ADDR_LE_STR_LEN];
403 		int err;
404 
405 		bt_addr_le_to_str(&addr_found[i], addr, sizeof(addr));
406 
407 		printk("Disconnecting member[%u] (%s)", i, addr);
408 		err = bt_conn_disconnect(conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
409 		(void)memset(&set_members[i], 0, sizeof(set_members[i]));
410 		if (err != 0) {
411 			FAIL("Failed to do disconnect\n", err);
412 			return;
413 		}
414 	}
415 }
416 
test_main(void)417 static void test_main(void)
418 {
419 	const struct bt_csip_set_coordinator_set_member *locked_members[CONFIG_BT_MAX_CONN];
420 	int err;
421 
422 	init();
423 	connect_set();
424 
425 	for (size_t i = 0; i < ARRAY_SIZE(locked_members); i++) {
426 		locked_members[i] = set_members[i];
427 	}
428 
429 	if (primary_inst->info.rank != 0U) {
430 		ordered_access(locked_members, connected_member_count, false);
431 	}
432 
433 	if (primary_inst->info.lockable) {
434 		printk("Locking set\n");
435 		err = bt_csip_set_coordinator_lock(locked_members, connected_member_count,
436 						   &primary_inst->info);
437 		if (err != 0) {
438 			FAIL("Failed to do set coordinator lock (%d)", err);
439 			return;
440 		}
441 
442 		WAIT_FOR_COND(set_locked);
443 	}
444 
445 	if (primary_inst->info.rank != 0U) {
446 		ordered_access(locked_members, connected_member_count, primary_inst->info.lockable);
447 	}
448 
449 	k_sleep(K_MSEC(1000)); /* Simulate doing stuff */
450 
451 	if (primary_inst->info.lockable) {
452 		printk("Releasing set\n");
453 		err = bt_csip_set_coordinator_release(locked_members, connected_member_count,
454 						      &primary_inst->info);
455 		if (err != 0) {
456 			FAIL("Failed to do set coordinator release (%d)", err);
457 			return;
458 		}
459 
460 		WAIT_FOR_COND(set_unlocked);
461 	}
462 
463 	if (primary_inst->info.rank != 0U) {
464 		ordered_access(locked_members, connected_member_count, false);
465 	}
466 
467 	if (primary_inst->info.lockable) {
468 		/* Lock and unlock again */
469 		set_locked = false;
470 		set_unlocked = false;
471 
472 		printk("Locking set\n");
473 		err = bt_csip_set_coordinator_lock(locked_members, connected_member_count,
474 						   &primary_inst->info);
475 		if (err != 0) {
476 			FAIL("Failed to do set coordinator lock (%d)", err);
477 			return;
478 		}
479 
480 		WAIT_FOR_COND(set_locked);
481 	}
482 
483 	k_sleep(K_MSEC(1000)); /* Simulate doing stuff */
484 
485 	if (primary_inst->info.lockable) {
486 		printk("Releasing set\n");
487 		err = bt_csip_set_coordinator_release(locked_members, connected_member_count,
488 						      &primary_inst->info);
489 		if (err != 0) {
490 			FAIL("Failed to do set coordinator release (%d)", err);
491 			return;
492 		}
493 
494 		WAIT_FOR_COND(set_unlocked);
495 	}
496 
497 	disconnect_set();
498 
499 	PASS("All members disconnected\n");
500 }
501 
test_new_sirk(void)502 static void test_new_sirk(void)
503 {
504 	init();
505 	connect_set();
506 
507 	backchannel_sync_send_all();
508 	backchannel_sync_wait_all();
509 
510 	WAIT_FOR_FLAG(flag_sirk_changed);
511 
512 	disconnect_set();
513 
514 	PASS("All members disconnected\n");
515 }
516 
test_args(int argc,char * argv[])517 static void test_args(int argc, char *argv[])
518 {
519 	for (int argn = 0; argn < argc; argn++) {
520 		const char *arg = argv[argn];
521 
522 		if (strcmp(arg, "no-size") == 0) {
523 			expect_set_size = false;
524 		} else if (strcmp(arg, "no-rank") == 0) {
525 			expect_rank = false;
526 		} else if (strcmp(arg, "no-lock") == 0) {
527 			expect_lockable = false;
528 		} else {
529 			FAIL("Invalid arg: %s", arg);
530 		}
531 	}
532 }
533 
534 static const struct bst_test_instance test_connect[] = {
535 	{
536 		.test_id = "csip_set_coordinator",
537 		.test_pre_init_f = test_init,
538 		.test_tick_f = test_tick,
539 		.test_main_f = test_main,
540 		.test_args_f = test_args,
541 	},
542 	{
543 		.test_id = "csip_set_coordinator_new_sirk",
544 		.test_pre_init_f = test_init,
545 		.test_tick_f = test_tick,
546 		.test_main_f = test_new_sirk,
547 		.test_args_f = test_args,
548 	},
549 	BSTEST_END_MARKER,
550 };
551 
test_csip_set_coordinator_install(struct bst_test_list * tests)552 struct bst_test_list *test_csip_set_coordinator_install(struct bst_test_list *tests)
553 {
554 	return bst_add_tests(tests, test_connect);
555 }
556 #else
test_csip_set_coordinator_install(struct bst_test_list * tests)557 struct bst_test_list *test_csip_set_coordinator_install(struct bst_test_list *tests)
558 {
559 	return tests;
560 }
561 
562 #endif /* CONFIG_BT_CSIP_SET_COORDINATOR */
563