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(&param, &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