1 /*
2  * Copyright (c) 2019 Bose Corporation
3  * Copyright (c) 2020-2025 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 #include <stdbool.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include <zephyr/autoconf.h>
13 #include <zephyr/bluetooth/audio/csip.h>
14 #include <zephyr/bluetooth/bluetooth.h>
15 #include <zephyr/bluetooth/gap.h>
16 #include <zephyr/sys/printk.h>
17 #include <zephyr/sys/util.h>
18 
19 #include "bs_tracing.h"
20 #include "bstests.h"
21 #include "common.h"
22 #ifdef CONFIG_BT_CSIP_SET_MEMBER
23 static struct bt_csip_set_member_svc_inst *svc_inst;
24 extern enum bst_result_t bst_result;
25 static volatile bool g_locked;
26 static uint8_t sirk_read_req_rsp = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT;
27 struct bt_csip_set_member_register_param param = {
28 	.lockable = true,
29 	/* Using the CSIS test sample SIRK */
30 	.sirk = TEST_SAMPLE_SIRK,
31 };
32 
csip_lock_changed_cb(struct bt_conn * conn,struct bt_csip_set_member_svc_inst * svc_inst,bool locked)33 static void csip_lock_changed_cb(struct bt_conn *conn,
34 				 struct bt_csip_set_member_svc_inst *svc_inst,
35 				 bool locked)
36 {
37 	printk("Client %p %s the lock\n", conn, locked ? "locked" : "released");
38 	g_locked = locked;
39 }
40 
sirk_read_req_cb(struct bt_conn * conn,struct bt_csip_set_member_svc_inst * svc_inst)41 static uint8_t sirk_read_req_cb(struct bt_conn *conn,
42 				struct bt_csip_set_member_svc_inst *svc_inst)
43 {
44 	return sirk_read_req_rsp;
45 }
46 
47 static struct bt_csip_set_member_cb csip_cbs = {
48 	.lock_changed = csip_lock_changed_cb,
49 	.sirk_read_req = sirk_read_req_cb,
50 };
51 
bt_ready(int err)52 static void bt_ready(int err)
53 {
54 	struct bt_le_ext_adv *ext_adv;
55 
56 	if (err != 0) {
57 		FAIL("Bluetooth init failed (err %d)\n", err);
58 		return;
59 	}
60 
61 	printk("Audio Server: Bluetooth initialized\n");
62 
63 	param.cb = &csip_cbs;
64 
65 	err = bt_csip_set_member_register(&param, &svc_inst);
66 	if (err != 0) {
67 		FAIL("Could not register CSIP (err %d)\n", err);
68 		return;
69 	}
70 
71 	err = bt_csip_set_member_generate_rsi(svc_inst, csip_rsi);
72 	if (err != 0) {
73 		FAIL("Failed to generate RSI (err %d)\n", err);
74 		return;
75 	}
76 
77 	setup_connectable_adv(&ext_adv);
78 }
79 
test_sirk(void)80 static void test_sirk(void)
81 {
82 	const uint8_t new_sirk[] = {0xff, 0xcc, 0x72, 0xdd, 0x86, 0x8c, 0xcd, 0xce,
83 				    0x22, 0xfd, 0xa1, 0x21, 0x09, 0x7d, 0x7d, 0x45};
84 	struct bt_csip_set_member_set_info info;
85 	int err;
86 
87 	printk("Setting new SIRK\n");
88 	err = bt_csip_set_member_sirk(svc_inst, new_sirk);
89 	if (err != 0) {
90 		FAIL("Failed to set SIRK: %d\n", err);
91 		return;
92 	}
93 
94 	printk("Getting new SIRK\n");
95 	err = bt_csip_set_member_get_info(svc_inst, &info);
96 	if (err != 0) {
97 		FAIL("Failed to get SIRK: %d\n", err);
98 		return;
99 	}
100 
101 	if (memcmp(new_sirk, info.sirk, BT_CSIP_SIRK_SIZE) != 0) {
102 		FAIL("The SIRK set and the set SIRK were different\n");
103 		return;
104 	}
105 
106 	printk("New SIRK correctly set and retrieved\n");
107 }
108 
update_set_size_and_rank(void)109 static void update_set_size_and_rank(void)
110 {
111 	struct bt_csip_set_member_set_info info;
112 	uint8_t old_set_size;
113 	uint8_t old_rank;
114 	uint8_t new_set_size;
115 	uint8_t new_rank;
116 	int err;
117 
118 	err = bt_csip_set_member_get_info(svc_inst, &info);
119 	if (err != 0) {
120 		FAIL("Failed to get SIRK: %d\n", err);
121 		return;
122 	}
123 
124 	/* Simulate a new device being added as rank 1 to the set, making the set size increase by 1
125 	 * and this device's rank increase by 1
126 	 */
127 	old_set_size = info.set_size;
128 	old_rank = info.rank;
129 	new_set_size = old_set_size + 1U;
130 	new_rank = old_rank + 1U;
131 
132 	printk("Setting new SIRK\n");
133 	err = bt_csip_set_member_set_size_and_rank(svc_inst, new_set_size, new_rank);
134 	if (err != 0) {
135 		FAIL("Failed to set new size and rank: %d\n", err);
136 		return;
137 	}
138 
139 	printk("Getting new SIRK\n");
140 	err = bt_csip_set_member_get_info(svc_inst, &info);
141 	if (err != 0) {
142 		FAIL("Failed to get SIRK: %d\n", err);
143 		return;
144 	}
145 
146 	if (info.set_size != new_set_size) {
147 		FAIL("Unexpected set size %u != %u\n", info.set_size, new_set_size);
148 		return;
149 	}
150 
151 	if (info.rank != new_rank) {
152 		FAIL("Unexpected rank %u != %u\n", info.rank, new_rank);
153 		return;
154 	}
155 
156 	printk("New size correctly set and retrieved\n");
157 }
158 
test_main(void)159 static void test_main(void)
160 {
161 	int err;
162 
163 	err = bt_enable(bt_ready);
164 
165 	if (err != 0) {
166 		FAIL("Bluetooth init failed (err %d)\n", err);
167 		return;
168 	}
169 
170 	WAIT_FOR_FLAG(flag_connected);
171 
172 	if (param.lockable) {
173 		/* Waiting for lock */
174 		WAIT_FOR_COND(g_locked);
175 		/* Waiting for lock release */
176 		WAIT_FOR_COND(!g_locked);
177 		/* Waiting for lock */
178 		WAIT_FOR_COND(g_locked);
179 		/* Waiting for lock release */
180 		WAIT_FOR_COND(!g_locked);
181 	}
182 
183 	WAIT_FOR_UNSET_FLAG(flag_connected);
184 
185 	err = bt_csip_set_member_unregister(svc_inst);
186 	if (err != 0) {
187 		FAIL("Could not unregister CSIP (err %d)\n", err);
188 		return;
189 	}
190 	svc_inst = NULL;
191 
192 	PASS("CSIP Set member passed: Client successfully disconnected\n");
193 }
194 
test_force_release(void)195 static void test_force_release(void)
196 {
197 	int err;
198 
199 	err = bt_enable(bt_ready);
200 
201 	if (err != 0) {
202 		FAIL("Bluetooth init failed (err %d)\n", err);
203 		return;
204 	}
205 
206 	WAIT_FOR_FLAG(flag_connected);
207 
208 	WAIT_FOR_COND(g_locked);
209 	printk("Force releasing set\n");
210 	bt_csip_set_member_lock(svc_inst, false, true);
211 
212 	WAIT_FOR_UNSET_FLAG(flag_connected);
213 
214 	err = bt_csip_set_member_unregister(svc_inst);
215 	if (err != 0) {
216 		FAIL("Could not unregister CSIP (err %d)\n", err);
217 		return;
218 	}
219 	svc_inst = NULL;
220 
221 	PASS("CSIP Set member passed: Client successfully disconnected\n");
222 }
223 
test_csip_enc(void)224 static void test_csip_enc(void)
225 {
226 	printk("Running %s\n", __func__);
227 	sirk_read_req_rsp = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC;
228 	test_main();
229 }
230 
test_new_sirk(void)231 static void test_new_sirk(void)
232 {
233 	int err;
234 
235 	err = bt_enable(bt_ready);
236 
237 	if (err != 0) {
238 		FAIL("Bluetooth init failed (err %d)\n", err);
239 		return;
240 	}
241 
242 	WAIT_FOR_FLAG(flag_connected);
243 
244 	backchannel_sync_send_all();
245 	backchannel_sync_wait_all();
246 
247 	test_sirk();
248 
249 	WAIT_FOR_UNSET_FLAG(flag_connected);
250 
251 	err = bt_csip_set_member_unregister(svc_inst);
252 	if (err != 0) {
253 		FAIL("Could not unregister CSIP (err %d)\n", err);
254 		return;
255 	}
256 	svc_inst = NULL;
257 
258 	PASS("CSIP Set member passed: Client successfully disconnected\n");
259 }
260 
test_new_set_size_and_rank(void)261 static void test_new_set_size_and_rank(void)
262 {
263 	int err;
264 
265 	err = bt_enable(bt_ready);
266 
267 	if (err != 0) {
268 		FAIL("Bluetooth init failed (err %d)\n", err);
269 		return;
270 	}
271 
272 	WAIT_FOR_FLAG(flag_connected);
273 
274 	backchannel_sync_send_all();
275 	backchannel_sync_wait_all();
276 
277 	update_set_size_and_rank();
278 
279 	WAIT_FOR_UNSET_FLAG(flag_connected);
280 
281 	err = bt_csip_set_member_unregister(svc_inst);
282 	if (err != 0) {
283 		FAIL("Could not unregister CSIP (err %d)\n", err);
284 		return;
285 	}
286 	svc_inst = NULL;
287 
288 	PASS("CSIP Set member passed: Client successfully disconnected\n");
289 }
290 
test_register(void)291 static void test_register(void)
292 {
293 	for (size_t iteration = 1; iteration <= 5; iteration++) {
294 		struct bt_csip_set_member_svc_inst
295 			*svc_insts[CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT];
296 		int err;
297 
298 		printk("Running iteration %zu\n", iteration);
299 
300 		ARRAY_FOR_EACH(svc_insts, i) {
301 			err = bt_csip_set_member_register(&param, &svc_insts[i]);
302 			if (err != 0) {
303 				FAIL("[%zu]: Could not register CSIS (err %d)\n", i, err);
304 				return;
305 			}
306 		}
307 
308 		err = bt_csip_set_member_register(&param, &svc_inst);
309 		if (err == 0) {
310 			FAIL("Registered more CSIS than expected\n");
311 			return;
312 		}
313 
314 		ARRAY_FOR_EACH(svc_insts, i) {
315 			err = bt_csip_set_member_unregister(svc_insts[i]);
316 			if (err != 0) {
317 				FAIL("[%zu]: Could not unregister CSIS (err %d)\n", i, err);
318 				return;
319 			}
320 			svc_insts[i] = NULL;
321 		}
322 	}
323 
324 	PASS("CSIP Set member register passed\n");
325 	/* We can terminate the test immediately here as there is no peer devices we keep
326 	 * communicating with.
327 	 */
328 	bs_trace_silent_exit(0);
329 }
330 
test_args(int argc,char * argv[])331 static void test_args(int argc, char *argv[])
332 {
333 	for (size_t argn = 0; argn < argc; argn++) {
334 		const char *arg = argv[argn];
335 
336 		if (strcmp(arg, "size") == 0) {
337 			param.set_size = strtol(argv[++argn], NULL, 10);
338 		} else if (strcmp(arg, "rank") == 0) {
339 			param.rank = strtol(argv[++argn], NULL, 10);
340 		} else if (strcmp(arg, "not-lockable") == 0) {
341 			param.lockable = false;
342 		} else if (strcmp(arg, "sirk") == 0) {
343 			size_t len;
344 
345 			argn++;
346 
347 			len = hex2bin(argv[argn], strlen(argv[argn]), param.sirk,
348 				      sizeof(param.sirk));
349 			if (len == 0) {
350 				FAIL("Could not parse SIRK");
351 				return;
352 			}
353 		} else {
354 			FAIL("Invalid arg: %s", arg);
355 		}
356 	}
357 }
358 
359 static const struct bst_test_instance test_connect[] = {
360 	{
361 		.test_id = "csip_set_member",
362 		.test_pre_init_f = test_init,
363 		.test_tick_f = test_tick,
364 		.test_main_f = test_main,
365 		.test_args_f = test_args,
366 	},
367 	{
368 		.test_id = "csip_set_member_release",
369 		.test_pre_init_f = test_init,
370 		.test_tick_f = test_tick,
371 		.test_main_f = test_force_release,
372 		.test_args_f = test_args,
373 	},
374 	{
375 		.test_id = "csip_set_member_enc",
376 		.test_pre_init_f = test_init,
377 		.test_tick_f = test_tick,
378 		.test_main_f = test_csip_enc,
379 		.test_args_f = test_args,
380 	},
381 	{
382 		.test_id = "csip_set_member_new_sirk",
383 		.test_pre_init_f = test_init,
384 		.test_tick_f = test_tick,
385 		.test_main_f = test_new_sirk,
386 		.test_args_f = test_args,
387 	},
388 	{
389 		.test_id = "csip_set_member_new_size_and_rank",
390 		.test_pre_init_f = test_init,
391 		.test_tick_f = test_tick,
392 		.test_main_f = test_new_set_size_and_rank,
393 		.test_args_f = test_args,
394 	},
395 	{
396 		.test_id = "csip_set_member_register",
397 		.test_pre_init_f = test_init,
398 		.test_tick_f = test_tick,
399 		.test_main_f = test_register,
400 		.test_args_f = test_args,
401 	},
402 	BSTEST_END_MARKER,
403 };
404 
test_csip_set_member_install(struct bst_test_list * tests)405 struct bst_test_list *test_csip_set_member_install(struct bst_test_list *tests)
406 {
407 	return bst_add_tests(tests, test_connect);
408 }
409 #else
410 
test_csip_set_member_install(struct bst_test_list * tests)411 struct bst_test_list *test_csip_set_member_install(struct bst_test_list *tests)
412 {
413 	return tests;
414 }
415 
416 #endif /* CONFIG_BT_CSIP_SET_MEMBER */
417