1 /* Copyright (c) 2023 Nordic Semiconductor ASA
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 #include <string.h>
6 
7 #include <zephyr/kernel.h>
8 
9 #include <zephyr/bluetooth/att.h>
10 #include <zephyr/bluetooth/addr.h>
11 #include <zephyr/bluetooth/conn.h>
12 #include <zephyr/bluetooth/gatt.h>
13 #include <zephyr/bluetooth/uuid.h>
14 #include <zephyr/bluetooth/hci_types.h>
15 #include <zephyr/bluetooth/bluetooth.h>
16 
17 #include <zephyr/logging/log.h>
18 
19 #include <zephyr/settings/settings.h>
20 
21 #include "babblekit/testcase.h"
22 #include "babblekit/flags.h"
23 #include "common.h"
24 #include "settings.h"
25 
26 #include "argparse.h"
27 #include "bs_pc_backchannel.h"
28 
29 #define CLIENT_CLIENT_CHAN 0
30 #define SERVER_CLIENT_CHAN 1
31 
32 DEFINE_FLAG_STATIC(connected_flag);
33 DEFINE_FLAG_STATIC(disconnected_flag);
34 DEFINE_FLAG_STATIC(security_updated_flag);
35 
36 #define BT_UUID_DUMMY_SERVICE BT_UUID_DECLARE_128(DUMMY_SERVICE_TYPE)
37 #define BT_UUID_DUMMY_SERVICE_NOTIFY BT_UUID_DECLARE_128(DUMMY_SERVICE_NOTIFY_TYPE)
38 
39 static struct bt_conn *default_conn;
40 
41 static struct bt_conn_cb central_cb;
42 
43 DEFINE_FLAG_STATIC(gatt_write_flag);
44 static uint8_t gatt_write_att_err;
45 
gatt_write_cb(struct bt_conn * conn,uint8_t att_err,struct bt_gatt_write_params * params)46 static void gatt_write_cb(struct bt_conn *conn, uint8_t att_err,
47 			  struct bt_gatt_write_params *params)
48 {
49 	gatt_write_att_err = att_err;
50 
51 	if (att_err) {
52 		TEST_FAIL("GATT write ATT error (err %d)", att_err);
53 	}
54 
55 	SET_FLAG(gatt_write_flag);
56 }
57 
gatt_write(struct bt_conn * conn,uint16_t handle,const uint8_t * write_buf,size_t write_size)58 static int gatt_write(struct bt_conn *conn, uint16_t handle, const uint8_t *write_buf,
59 		      size_t write_size)
60 {
61 	int err;
62 	struct bt_gatt_write_params params;
63 
64 	params.func = gatt_write_cb;
65 	params.handle = handle;
66 	params.offset = 0;
67 	params.data = write_buf;
68 	params.length = write_size;
69 
70 	UNSET_FLAG(gatt_write_flag);
71 
72 	/* `bt_gatt_write` is used instead of `bt_gatt_subscribe` and
73 	 * `bt_gatt_unsubscribe` to bypass subscribtion checks of GATT client
74 	 */
75 	err = bt_gatt_write(conn, &params);
76 	if (err) {
77 		TEST_FAIL("GATT write failed (err %d)", err);
78 	}
79 
80 	WAIT_FOR_FLAG(gatt_write_flag);
81 
82 	return gatt_write_att_err;
83 }
84 
ccc_subscribe(void)85 static void ccc_subscribe(void)
86 {
87 	int err;
88 	uint8_t buf = 1;
89 
90 	err = gatt_write(default_conn, CCC_HANDLE, &buf, sizeof(buf));
91 	if (err) {
92 		TEST_FAIL("Failed to subscribe (att err %d)", err);
93 	}
94 }
95 
ccc_unsubscribe(void)96 static void ccc_unsubscribe(void)
97 {
98 	int err;
99 	uint8_t buf = 0;
100 
101 	err = gatt_write(default_conn, CCC_HANDLE, &buf, sizeof(buf));
102 	if (err) {
103 		TEST_FAIL("Failed to unsubscribe (att err %d)", err);
104 	}
105 }
106 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)107 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
108 			 struct net_buf_simple *ad)
109 {
110 	int err;
111 	char addr_str[BT_ADDR_LE_STR_LEN];
112 
113 	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
114 
115 	LOG_DBG("Device found: %s (RSSI %d)", addr_str, rssi);
116 
117 	err = bt_le_scan_stop();
118 	if (err) {
119 		TEST_FAIL("Failed to stop scanner (err %d)", err);
120 	}
121 
122 	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
123 				&default_conn);
124 	if (err) {
125 		TEST_FAIL("Could not connect to peer: %s (err %d)", addr_str, err);
126 	}
127 }
128 
connected(struct bt_conn * conn,uint8_t err)129 static void connected(struct bt_conn *conn, uint8_t err)
130 {
131 	const bt_addr_le_t *addr;
132 	char addr_str[BT_ADDR_LE_STR_LEN];
133 
134 	addr = bt_conn_get_dst(conn);
135 	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
136 
137 	if (err) {
138 		TEST_FAIL("Failed to connect to %s (err %d)", addr_str, err);
139 	}
140 
141 	LOG_DBG("Connected: %s", addr_str);
142 
143 	if (conn == default_conn) {
144 		SET_FLAG(connected_flag);
145 	}
146 }
147 
disconnected(struct bt_conn * conn,uint8_t reason)148 static void disconnected(struct bt_conn *conn, uint8_t reason)
149 {
150 	char addr_str[BT_ADDR_LE_STR_LEN];
151 
152 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
153 
154 	LOG_DBG("Disconnected: %s (reason 0x%02x)", addr_str, reason);
155 
156 	SET_FLAG(disconnected_flag);
157 
158 	if (default_conn != conn) {
159 		return;
160 	}
161 
162 	bt_conn_unref(default_conn);
163 	default_conn = NULL;
164 }
165 
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)166 static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
167 {
168 	char addr_str[BT_ADDR_LE_STR_LEN];
169 
170 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
171 
172 	if (!err) {
173 		LOG_DBG("Security changed: %s level %u", addr_str, level);
174 		SET_FLAG(security_updated_flag);
175 	} else {
176 		LOG_DBG("Security failed: %s level %u err %d", addr_str, level, err);
177 	}
178 }
179 
start_scan(void)180 static void start_scan(void)
181 {
182 	int err;
183 
184 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
185 	if (err) {
186 		TEST_FAIL("Scanning failed to start (err %d)", err);
187 	}
188 
189 	LOG_DBG("Scanning successfully started");
190 }
191 
disconnect(void)192 static void disconnect(void)
193 {
194 	int err;
195 
196 	err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
197 	if (err) {
198 		TEST_FAIL("Disconnection failed (err %d)", err);
199 	}
200 
201 	WAIT_FOR_FLAG(disconnected_flag);
202 	UNSET_FLAG(disconnected_flag);
203 }
204 
205 /* Test steps */
206 
connect_pair_subscribe(void)207 static void connect_pair_subscribe(void)
208 {
209 	int err;
210 
211 	start_scan();
212 
213 	WAIT_FOR_FLAG(connected_flag);
214 	UNSET_FLAG(connected_flag);
215 
216 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
217 	if (err != 0) {
218 		TEST_FAIL("Failed to set security (err %d)", err);
219 	}
220 
221 	WAIT_FOR_FLAG(security_updated_flag);
222 	UNSET_FLAG(security_updated_flag);
223 
224 	/* subscribe while being paired */
225 	ccc_subscribe();
226 
227 	/* confirm to server that we subscribed */
228 	backchannel_sync_send(SERVER_CLIENT_CHAN, SERVER_ID);
229 	/* wait for server to check that the subscribtion is well registered */
230 	backchannel_sync_wait(SERVER_CLIENT_CHAN, SERVER_ID);
231 }
232 
connect_unsubscribe(void)233 static void connect_unsubscribe(void)
234 {
235 	start_scan();
236 
237 	WAIT_FOR_FLAG(connected_flag);
238 	UNSET_FLAG(connected_flag);
239 
240 	/* wait for server to check that the subscribtion has not been restored */
241 	backchannel_sync_wait(SERVER_CLIENT_CHAN, SERVER_ID);
242 
243 	LOG_DBG("Trying to unsubscribe without being paired...");
244 	/* try to unsubscribe */
245 	ccc_unsubscribe();
246 
247 	/* confirm to server that we send unsubscribtion request */
248 	backchannel_sync_send(SERVER_CLIENT_CHAN, SERVER_ID);
249 	/* wait for server to check that the unsubscribtion is ignored */
250 	backchannel_sync_wait(SERVER_CLIENT_CHAN, SERVER_ID);
251 }
252 
connect_restore_sec(void)253 static void connect_restore_sec(void)
254 {
255 	int err;
256 
257 	start_scan();
258 
259 	WAIT_FOR_FLAG(connected_flag);
260 	UNSET_FLAG(connected_flag);
261 
262 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
263 	if (err != 0) {
264 		TEST_FAIL("Failed to set security (err %d)", err);
265 	}
266 
267 	WAIT_FOR_FLAG(security_updated_flag);
268 	UNSET_FLAG(security_updated_flag);
269 
270 	/* notify the end of security update to server */
271 	backchannel_sync_send(SERVER_CLIENT_CHAN, SERVER_ID);
272 	/* wait for server to check that the subscribtion has been restored */
273 	backchannel_sync_wait(SERVER_CLIENT_CHAN, SERVER_ID);
274 
275 	/* wait for server to check that the subscription no longer exist */
276 	backchannel_sync_send(SERVER_CLIENT_CHAN, SERVER_ID);
277 }
278 
279 /* Util functions */
280 
central_backchannel_init(void)281 void central_backchannel_init(void)
282 {
283 	uint device_number = get_device_nbr();
284 	uint channel_numbers[2] = {
285 		0,
286 		0,
287 	};
288 	uint device_numbers[2];
289 	uint num_ch = 2;
290 	uint *ch;
291 
292 	device_numbers[0] = (device_number == GOOD_CLIENT_ID) ? BAD_CLIENT_ID : GOOD_CLIENT_ID;
293 	device_numbers[1] = SERVER_ID;
294 
295 	LOG_DBG("Opening back channels for device %d", device_number);
296 	ch = bs_open_back_channel(device_number, device_numbers, channel_numbers, num_ch);
297 	if (!ch) {
298 		TEST_FAIL("Unable to open backchannel");
299 	}
300 	LOG_DBG("Back channels for device %d opened", device_number);
301 }
302 
set_public_addr(void)303 static void set_public_addr(void)
304 {
305 	bt_addr_le_t addr = {BT_ADDR_LE_RANDOM, {{0x0A, 0x89, 0x67, 0x45, 0x23, 0xC1}}};
306 
307 	bt_id_create(&addr, NULL);
308 }
309 
310 /* Main functions */
311 
run_central(void)312 void run_central(void)
313 {
314 	int err;
315 
316 	central_cb.connected = connected;
317 	central_cb.disconnected = disconnected;
318 	central_cb.security_changed = security_changed;
319 
320 	central_backchannel_init();
321 	set_public_addr();
322 
323 	err = bt_enable(NULL);
324 	if (err) {
325 		TEST_FAIL("Bluetooth init failed (err %d)", err);
326 	}
327 
328 	LOG_DBG("Bluetooth initialized");
329 
330 	bt_conn_cb_register(&central_cb);
331 
332 	err = settings_load();
333 	if (err) {
334 		TEST_FAIL("Settings load failed (err %d)", err);
335 	}
336 
337 	err = bt_unpair(BT_ID_DEFAULT, BT_ADDR_LE_ANY);
338 	if (err) {
339 		TEST_FAIL("Unpairing failed (err %d)", err);
340 	}
341 
342 	connect_pair_subscribe();
343 	disconnect();
344 
345 	/* tell the bad client that we disconnected and wait for him to disconnect */
346 	backchannel_sync_send(CLIENT_CLIENT_CHAN, BAD_CLIENT_ID);
347 	backchannel_sync_wait(CLIENT_CLIENT_CHAN, BAD_CLIENT_ID);
348 
349 	connect_restore_sec();
350 	disconnect();
351 
352 	TEST_PASS("Central test passed");
353 }
354 
run_bad_central(void)355 void run_bad_central(void)
356 {
357 	int err;
358 
359 	central_cb.connected = connected;
360 	central_cb.disconnected = disconnected;
361 	central_cb.security_changed = security_changed;
362 
363 	central_backchannel_init();
364 	set_public_addr();
365 
366 	/* wait for good central to disconnect from server */
367 	backchannel_sync_wait(CLIENT_CLIENT_CHAN, GOOD_CLIENT_ID);
368 
369 	err = bt_enable(NULL);
370 	if (err) {
371 		TEST_FAIL("Bluetooth init failed (err %d)");
372 	}
373 
374 	LOG_DBG("Bluetooth initialized");
375 
376 	bt_conn_cb_register(&central_cb);
377 
378 	err = settings_load();
379 	if (err) {
380 		TEST_FAIL("Settings load failed (err %d)");
381 	}
382 
383 	connect_unsubscribe();
384 	disconnect();
385 
386 	TEST_PASS("Bad Central test passed");
387 
388 	/* tell the good client that we disconnected from the server */
389 	backchannel_sync_send(CLIENT_CLIENT_CHAN, GOOD_CLIENT_ID);
390 }
391