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 <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 "bstests.h"
20 #include "common.h"
21 #ifdef CONFIG_BT_CSIP_SET_MEMBER
22 static struct bt_csip_set_member_svc_inst *svc_inst;
23 extern enum bst_result_t bst_result;
24 static volatile bool g_locked;
25 static uint8_t sirk_read_req_rsp = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT;
26 struct bt_csip_set_member_register_param param = {
27 .set_size = 3,
28 .rank = 1,
29 .lockable = true,
30 /* Using the CSIS test sample SIRK */
31 .sirk = { 0xcd, 0xcc, 0x72, 0xdd, 0x86, 0x8c, 0xcd, 0xce,
32 0x22, 0xfd, 0xa1, 0x21, 0x09, 0x7d, 0x7d, 0x45 },
33 };
34
csip_lock_changed_cb(struct bt_conn * conn,struct bt_csip_set_member_svc_inst * svc_inst,bool locked)35 static void csip_lock_changed_cb(struct bt_conn *conn,
36 struct bt_csip_set_member_svc_inst *svc_inst,
37 bool locked)
38 {
39 printk("Client %p %s the lock\n", conn, locked ? "locked" : "released");
40 g_locked = locked;
41 }
42
sirk_read_req_cb(struct bt_conn * conn,struct bt_csip_set_member_svc_inst * svc_inst)43 static uint8_t sirk_read_req_cb(struct bt_conn *conn,
44 struct bt_csip_set_member_svc_inst *svc_inst)
45 {
46 return sirk_read_req_rsp;
47 }
48
49 static struct bt_csip_set_member_cb csip_cbs = {
50 .lock_changed = csip_lock_changed_cb,
51 .sirk_read_req = sirk_read_req_cb,
52 };
53
bt_ready(int err)54 static void bt_ready(int err)
55 {
56 uint8_t rsi[BT_CSIP_RSI_SIZE];
57 struct bt_data ad[] = {
58 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
59 BT_CSIP_DATA_RSI(rsi),
60 };
61
62 if (err != 0) {
63 FAIL("Bluetooth init failed (err %d)\n", err);
64 return;
65 }
66
67 printk("Audio Server: Bluetooth initialized\n");
68
69 param.cb = &csip_cbs;
70
71 err = bt_csip_set_member_register(¶m, &svc_inst);
72 if (err != 0) {
73 FAIL("Could not register CSIP (err %d)\n", err);
74 return;
75 }
76
77 err = bt_csip_set_member_generate_rsi(svc_inst, rsi);
78 if (err != 0) {
79 FAIL("Failed to generate RSI (err %d)\n", err);
80 return;
81 }
82
83 err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0);
84 if (err != 0) {
85 FAIL("Advertising failed to start (err %d)\n", err);
86 }
87 }
88
test_sirk(void)89 static void test_sirk(void)
90 {
91 const uint8_t new_sirk[] = {0xff, 0xcc, 0x72, 0xdd, 0x86, 0x8c, 0xcd, 0xce,
92 0x22, 0xfd, 0xa1, 0x21, 0x09, 0x7d, 0x7d, 0x45};
93 uint8_t tmp_sirk[BT_CSIP_SIRK_SIZE];
94 int err;
95
96 printk("Setting new SIRK\n");
97 err = bt_csip_set_member_sirk(svc_inst, new_sirk);
98 if (err != 0) {
99 FAIL("Failed to set SIRK: %d\n", err);
100 return;
101 }
102
103 printk("Getting new SIRK\n");
104 err = bt_csip_set_member_get_sirk(svc_inst, tmp_sirk);
105 if (err != 0) {
106 FAIL("Failed to get SIRK: %d\n", err);
107 return;
108 }
109
110 if (memcmp(new_sirk, tmp_sirk, BT_CSIP_SIRK_SIZE) != 0) {
111 FAIL("The SIRK set and the SIRK set were different\n");
112 return;
113 }
114
115 printk("New SIRK correctly set and retrieved\n");
116 }
117
test_main(void)118 static void test_main(void)
119 {
120 int err;
121
122 err = bt_enable(bt_ready);
123
124 if (err != 0) {
125 FAIL("Bluetooth init failed (err %d)\n", err);
126 return;
127 }
128
129 WAIT_FOR_FLAG(flag_connected);
130
131 if (param.lockable) {
132 /* Waiting for lock */
133 WAIT_FOR_COND(g_locked);
134 /* Waiting for lock release */
135 WAIT_FOR_COND(!g_locked);
136 /* Waiting for lock */
137 WAIT_FOR_COND(g_locked);
138 /* Waiting for lock release */
139 WAIT_FOR_COND(!g_locked);
140 }
141
142 WAIT_FOR_UNSET_FLAG(flag_connected);
143
144 err = bt_csip_set_member_unregister(svc_inst);
145 if (err != 0) {
146 FAIL("Could not unregister CSIP (err %d)\n", err);
147 return;
148 }
149 svc_inst = NULL;
150
151 PASS("CSIP Set member passed: Client successfully disconnected\n");
152 }
153
test_force_release(void)154 static void test_force_release(void)
155 {
156 int err;
157
158 err = bt_enable(bt_ready);
159
160 if (err != 0) {
161 FAIL("Bluetooth init failed (err %d)\n", err);
162 return;
163 }
164
165 WAIT_FOR_FLAG(flag_connected);
166
167 WAIT_FOR_COND(g_locked);
168 printk("Force releasing set\n");
169 bt_csip_set_member_lock(svc_inst, false, true);
170
171 WAIT_FOR_UNSET_FLAG(flag_connected);
172
173 err = bt_csip_set_member_unregister(svc_inst);
174 if (err != 0) {
175 FAIL("Could not unregister CSIP (err %d)\n", err);
176 return;
177 }
178 svc_inst = NULL;
179
180 PASS("CSIP Set member passed: Client successfully disconnected\n");
181 }
182
test_csip_enc(void)183 static void test_csip_enc(void)
184 {
185 printk("Running %s\n", __func__);
186 sirk_read_req_rsp = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC;
187 test_main();
188 }
189
test_new_sirk(void)190 static void test_new_sirk(void)
191 {
192 int err;
193
194 err = bt_enable(bt_ready);
195
196 if (err != 0) {
197 FAIL("Bluetooth init failed (err %d)\n", err);
198 return;
199 }
200
201 WAIT_FOR_FLAG(flag_connected);
202
203 backchannel_sync_send_all();
204 backchannel_sync_wait_all();
205
206 test_sirk();
207
208 WAIT_FOR_UNSET_FLAG(flag_connected);
209
210 err = bt_csip_set_member_unregister(svc_inst);
211 if (err != 0) {
212 FAIL("Could not unregister CSIP (err %d)\n", err);
213 return;
214 }
215 svc_inst = NULL;
216
217 PASS("CSIP Set member passed: Client successfully disconnected\n");
218 }
219
test_args(int argc,char * argv[])220 static void test_args(int argc, char *argv[])
221 {
222 for (size_t argn = 0; argn < argc; argn++) {
223 const char *arg = argv[argn];
224
225 if (strcmp(arg, "size") == 0) {
226 param.set_size = strtol(argv[++argn], NULL, 10);
227 } else if (strcmp(arg, "rank") == 0) {
228 param.rank = strtol(argv[++argn], NULL, 10);
229 } else if (strcmp(arg, "not-lockable") == 0) {
230 param.lockable = false;
231 } else if (strcmp(arg, "sirk") == 0) {
232 size_t len;
233
234 argn++;
235
236 len = hex2bin(argv[argn], strlen(argv[argn]), param.sirk,
237 sizeof(param.sirk));
238 if (len == 0) {
239 FAIL("Could not parse SIRK");
240 return;
241 }
242 } else {
243 FAIL("Invalid arg: %s", arg);
244 }
245 }
246 }
247
248 static const struct bst_test_instance test_connect[] = {
249 {
250 .test_id = "csip_set_member",
251 .test_pre_init_f = test_init,
252 .test_tick_f = test_tick,
253 .test_main_f = test_main,
254 .test_args_f = test_args,
255 },
256 {
257 .test_id = "csip_set_member_release",
258 .test_pre_init_f = test_init,
259 .test_tick_f = test_tick,
260 .test_main_f = test_force_release,
261 .test_args_f = test_args,
262 },
263 {
264 .test_id = "csip_set_member_enc",
265 .test_pre_init_f = test_init,
266 .test_tick_f = test_tick,
267 .test_main_f = test_csip_enc,
268 .test_args_f = test_args,
269 },
270 {
271 .test_id = "csip_set_member_new_sirk",
272 .test_pre_init_f = test_init,
273 .test_tick_f = test_tick,
274 .test_main_f = test_new_sirk,
275 .test_args_f = test_args,
276 },
277 BSTEST_END_MARKER,
278 };
279
test_csip_set_member_install(struct bst_test_list * tests)280 struct bst_test_list *test_csip_set_member_install(struct bst_test_list *tests)
281 {
282 return bst_add_tests(tests, test_connect);
283 }
284 #else
285
test_csip_set_member_install(struct bst_test_list * tests)286 struct bst_test_list *test_csip_set_member_install(struct bst_test_list *tests)
287 {
288 return tests;
289 }
290
291 #endif /* CONFIG_BT_CSIP_SET_MEMBER */
292