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