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