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 SERVER_CHAN 0
28 
29 CREATE_FLAG(connected_flag);
30 CREATE_FLAG(disconnected_flag);
31 CREATE_FLAG(security_updated_flag);
32 CREATE_FLAG(notification_received_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_subscribed_flag);
42 
notify_cb(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)43 static uint8_t notify_cb(struct bt_conn *conn, struct bt_gatt_subscribe_params *params,
44 			 const void *data, uint16_t length)
45 {
46 	uint8_t value;
47 
48 	if (conn == NULL || data == NULL) {
49 		/* Peer unpaired or subscription was removed */
50 		UNSET_FLAG(gatt_subscribed_flag);
51 
52 		return BT_GATT_ITER_STOP;
53 	}
54 
55 	__ASSERT_NO_MSG(length == sizeof(value));
56 
57 	value = *(uint8_t *)data;
58 
59 	LOG_DBG("#%d notification received", value);
60 
61 	SET_FLAG(notification_received_flag);
62 
63 	return BT_GATT_ITER_CONTINUE;
64 }
65 
subscribe_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_subscribe_params * params)66 static void subscribe_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_subscribe_params *params)
67 {
68 	if (err) {
69 		return;
70 	}
71 
72 	SET_FLAG(gatt_subscribed_flag);
73 }
74 
75 static struct bt_gatt_subscribe_params subscribe_params;
76 
ccc_subscribe(void)77 static void ccc_subscribe(void)
78 {
79 	int err;
80 
81 	UNSET_FLAG(gatt_subscribed_flag);
82 
83 	subscribe_params.notify = notify_cb;
84 	subscribe_params.subscribe = subscribe_cb;
85 	subscribe_params.ccc_handle = CCC_HANDLE;
86 	subscribe_params.value_handle = VAL_HANDLE;
87 	subscribe_params.value = BT_GATT_CCC_NOTIFY;
88 
89 	err = bt_gatt_subscribe(default_conn, &subscribe_params);
90 	if (err) {
91 		FAIL("Failed to subscribe (att err %d)", err);
92 	}
93 
94 	WAIT_FOR_FLAG(gatt_subscribed_flag);
95 }
96 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)97 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
98 			 struct net_buf_simple *ad)
99 {
100 	int err;
101 	char addr_str[BT_ADDR_LE_STR_LEN];
102 
103 	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
104 
105 	LOG_DBG("Device found: %s (RSSI %d)", addr_str, rssi);
106 
107 	err = bt_le_scan_stop();
108 	if (err) {
109 		FAIL("Failed to stop scanner (err %d)\n", err);
110 	}
111 
112 	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
113 				&default_conn);
114 	if (err) {
115 		FAIL("Could not connect to peer: %s (err %d)\n", addr_str, err);
116 	}
117 }
118 
connected(struct bt_conn * conn,uint8_t err)119 static void connected(struct bt_conn *conn, uint8_t err)
120 {
121 	const bt_addr_le_t *addr;
122 	char addr_str[BT_ADDR_LE_STR_LEN];
123 
124 	addr = bt_conn_get_dst(conn);
125 	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
126 
127 	if (err) {
128 		FAIL("Failed to connect to %s (err %d)\n", addr_str, err);
129 	}
130 
131 	LOG_DBG("Connected: %s", addr_str);
132 
133 	if (conn == default_conn) {
134 		SET_FLAG(connected_flag);
135 	}
136 }
137 
disconnected(struct bt_conn * conn,uint8_t reason)138 static void disconnected(struct bt_conn *conn, uint8_t reason)
139 {
140 	char addr_str[BT_ADDR_LE_STR_LEN];
141 
142 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
143 
144 	LOG_DBG("Disconnected: %s (reason 0x%02x)", addr_str, reason);
145 
146 	SET_FLAG(disconnected_flag);
147 
148 	if (default_conn != conn) {
149 		return;
150 	}
151 
152 	bt_conn_unref(default_conn);
153 	default_conn = NULL;
154 }
155 
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)156 static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
157 {
158 	char addr_str[BT_ADDR_LE_STR_LEN];
159 
160 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
161 
162 	if (!err) {
163 		LOG_DBG("Security changed: %s level %u", addr_str, level);
164 		SET_FLAG(security_updated_flag);
165 	} else {
166 		LOG_DBG("Security failed: %s level %u err %d", addr_str, level, err);
167 	}
168 }
169 
start_scan(void)170 static void start_scan(void)
171 {
172 	int err;
173 
174 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
175 	if (err) {
176 		FAIL("Scanning failed to start (err %d)\n", err);
177 	}
178 
179 	LOG_DBG("Scanning successfully started");
180 }
181 
disconnect(void)182 static void disconnect(void)
183 {
184 	int err;
185 
186 	err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
187 	if (err) {
188 		FAIL("Disconnection failed (err %d)\n", err);
189 	}
190 
191 	WAIT_FOR_FLAG(disconnected_flag);
192 	UNSET_FLAG(disconnected_flag);
193 }
194 
195 /* Test steps */
196 
connect_pair_subscribe(void)197 static void connect_pair_subscribe(void)
198 {
199 	int err;
200 
201 	start_scan();
202 
203 	WAIT_FOR_FLAG(connected_flag);
204 	UNSET_FLAG(connected_flag);
205 
206 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
207 	if (err != 0) {
208 		FAIL("Failed to set security (err %d)\n", err);
209 	}
210 
211 	WAIT_FOR_FLAG(security_updated_flag);
212 	UNSET_FLAG(security_updated_flag);
213 
214 	/* subscribe while being paired */
215 	ccc_subscribe();
216 
217 	/* confirm to server that we subscribed */
218 	backchannel_sync_send(SERVER_CHAN, SERVER_ID);
219 	/* wait for server to check that the subscribtion is well registered */
220 	backchannel_sync_wait(SERVER_CHAN, SERVER_ID);
221 
222 	WAIT_FOR_FLAG(notification_received_flag);
223 	UNSET_FLAG(notification_received_flag);
224 }
225 
connect_restore_sec(void)226 static void connect_restore_sec(void)
227 {
228 	int err;
229 
230 	start_scan();
231 
232 	WAIT_FOR_FLAG(connected_flag);
233 	UNSET_FLAG(connected_flag);
234 
235 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
236 	if (err != 0) {
237 		FAIL("Failed to set security (err %d)\n", err);
238 	}
239 
240 	WAIT_FOR_FLAG(security_updated_flag);
241 	UNSET_FLAG(security_updated_flag);
242 
243 	/* check local subscription state */
244 	if (GET_FLAG(gatt_subscribed_flag) == false) {
245 		FAIL("Not subscribed\n");
246 	}
247 
248 	/* notify the end of security update to server */
249 	backchannel_sync_send(SERVER_CHAN, SERVER_ID);
250 	/* wait for server to check that the subscribtion has been restored */
251 	backchannel_sync_wait(SERVER_CHAN, SERVER_ID);
252 
253 	WAIT_FOR_FLAG(notification_received_flag);
254 	UNSET_FLAG(notification_received_flag);
255 }
256 
257 /* Util functions */
258 
central_backchannel_init(void)259 void central_backchannel_init(void)
260 {
261 	uint device_number = get_device_nbr();
262 	uint channel_numbers[1] = {
263 		0,
264 	};
265 	uint device_numbers[1];
266 	uint num_ch = 1;
267 	uint *ch;
268 
269 	device_numbers[0] = SERVER_ID;
270 
271 	LOG_DBG("Opening back channels for device %d", device_number);
272 	ch = bs_open_back_channel(device_number, device_numbers, channel_numbers, num_ch);
273 	if (!ch) {
274 		FAIL("Unable to open backchannel\n");
275 	}
276 	LOG_DBG("Back channels for device %d opened", device_number);
277 }
278 
set_public_addr(void)279 static void set_public_addr(void)
280 {
281 	bt_addr_le_t addr = {BT_ADDR_LE_RANDOM, {{0x0A, 0x89, 0x67, 0x45, 0x23, 0xC1}}};
282 
283 	bt_id_create(&addr, NULL);
284 }
285 
286 /* Main functions */
287 
run_central(int times)288 void run_central(int times)
289 {
290 	int err;
291 
292 	central_cb.connected = connected;
293 	central_cb.disconnected = disconnected;
294 	central_cb.security_changed = security_changed;
295 
296 	central_backchannel_init();
297 	set_public_addr();
298 
299 	err = bt_enable(NULL);
300 	if (err) {
301 		FAIL("Bluetooth init failed (err %d)\n", err);
302 	}
303 
304 	LOG_DBG("Bluetooth initialized");
305 
306 	bt_conn_cb_register(&central_cb);
307 
308 	err = settings_load();
309 	if (err) {
310 		FAIL("Settings load failed (err %d)\n", err);
311 	}
312 
313 	err = bt_unpair(BT_ID_DEFAULT, BT_ADDR_LE_ANY);
314 	if (err) {
315 		FAIL("Unpairing failed (err %d)\n", err);
316 	}
317 
318 	connect_pair_subscribe();
319 	disconnect();
320 
321 	for (int i = 0; i < times; i++) {
322 		connect_restore_sec();
323 		disconnect();
324 	}
325 
326 	PASS("Central test passed\n");
327 }
328