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