1 /*
2  * Copyright (c) 2015-2016 Intel Corporation
3  * Copyright (c) 2017-2019 Oticon A/S
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 #include <zephyr/kernel.h>
8 
9 #include "bs_types.h"
10 #include "bs_tracing.h"
11 #include "time_machine.h"
12 #include "bstests.h"
13 
14 #include <zephyr/types.h>
15 #include <stddef.h>
16 #include <errno.h>
17 #include <zephyr/sys/printk.h>
18 
19 #include <zephyr/bluetooth/bluetooth.h>
20 #include <zephyr/bluetooth/hci.h>
21 #include <zephyr/bluetooth/conn.h>
22 #include <zephyr/bluetooth/uuid.h>
23 #include <zephyr/bluetooth/gatt.h>
24 #include <zephyr/sys/byteorder.h>
25 
26 static struct bt_conn *default_conn;
27 
28 static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0);
29 static struct bt_gatt_discover_params discover_params;
30 static struct bt_gatt_subscribe_params subscribe_params;
31 
32 #if defined(CONFIG_TEST_CONN_INTERVAL_1MS)
33 #define UPDATE_PARAM_INTERVAL_MIN 1
34 #define UPDATE_PARAM_INTERVAL_MAX 1
35 #define UPDATE_PARAM_LATENCY      0
36 #define UPDATE_PARAM_TIMEOUT      10
37 #define TEST_NOTIFY_COUNT         3000
38 #else /* !CONFIG_TEST_CONN_INTERVAL_1MS */
39 #define UPDATE_PARAM_INTERVAL_MIN 25
40 #define UPDATE_PARAM_INTERVAL_MAX 45
41 #define UPDATE_PARAM_LATENCY      1
42 #define UPDATE_PARAM_TIMEOUT      250
43 #define TEST_NOTIFY_COUNT         3
44 #endif /* !CONFIG_TEST_CONN_INTERVAL_1MS */
45 
46 static struct bt_le_conn_param update_params = {
47 	.interval_min = UPDATE_PARAM_INTERVAL_MIN,
48 	.interval_max = UPDATE_PARAM_INTERVAL_MAX,
49 	.latency = UPDATE_PARAM_LATENCY,
50 	.timeout = UPDATE_PARAM_TIMEOUT,
51 };
52 
53 static bool encrypt_link;
54 static bool expect_ntf = true;
55 static uint8_t repeat_connect;
56 static uint8_t connected_signal;
57 
58 /*
59  * Basic connection test:
60  *   We expect to find a connectable peripheral to which we will
61  *   connect.
62  *
63  *   After connecting, we update connection parameters and channel
64  *   map, and expect to receive 2 notifications.
65  *   If we do, the test case passes.
66  *   If we do not in 5 seconds, the testcase is considered failed
67  *
68  *   The thread code is mostly a copy of the central_hr sample device
69  */
70 
71 #define WAIT_TIME 6 /*seconds*/
72 #define WAIT_TIME_TX_DEFER 800 /* milliseconds */
73 #define WAIT_TIME_REPEAT 22 /*seconds*/
74 extern enum bst_result_t bst_result;
75 
76 #define FAIL(...)					\
77 	do {						\
78 		bst_result = Failed;			\
79 		bs_trace_error_time_line(__VA_ARGS__);	\
80 	} while (0)
81 
82 #define PASS(...)					\
83 	do {						\
84 		bst_result = Passed;			\
85 		bs_trace_info_time(1, __VA_ARGS__);	\
86 	} while (0)
87 
test_con1_init(void)88 static void test_con1_init(void)
89 {
90 	if (IS_ENABLED(CONFIG_BT_CTLR_TX_DEFER)) {
91 		bst_ticker_set_next_tick_absolute(WAIT_TIME_TX_DEFER*1e3);
92 	} else {
93 		bst_ticker_set_next_tick_absolute(WAIT_TIME*1e6);
94 	}
95 	bst_result = In_progress;
96 }
97 
test_con_encrypted_init(void)98 static void test_con_encrypted_init(void)
99 {
100 	encrypt_link = true;
101 	test_con1_init();
102 }
103 
test_con20_init(void)104 static void test_con20_init(void)
105 {
106 	repeat_connect = 20;
107 	expect_ntf = false;
108 	bst_ticker_set_next_tick_absolute(WAIT_TIME_REPEAT*1e6);
109 	bst_result = In_progress;
110 }
111 
test_con1_tick(bs_time_t HW_device_time)112 static void test_con1_tick(bs_time_t HW_device_time)
113 {
114 	/*
115 	 * If in WAIT_TIME seconds the testcase did not already pass
116 	 * (and finish) we consider it failed
117 	 */
118 	if (bst_result != Passed) {
119 		FAIL("test_connect1 failed (not passed after %i seconds)\n",
120 		     WAIT_TIME);
121 	}
122 }
123 
test_con20_tick(bs_time_t HW_device_time)124 static void test_con20_tick(bs_time_t HW_device_time)
125 {
126 	if (bst_result != Passed) {
127 		FAIL("test_connect1 failed (not passed after %i seconds)\n",
128 		     WAIT_TIME_REPEAT);
129 	}
130 }
131 
notify_func(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)132 static uint8_t notify_func(struct bt_conn *conn,
133 			struct bt_gatt_subscribe_params *params,
134 			const void *data, uint16_t length)
135 {
136 	static uint32_t cycle_stamp;
137 	static int notify_count;
138 	uint32_t cycle_now;
139 	uint64_t delta;
140 
141 	if (!data) {
142 		printk("[UNSUBSCRIBED]\n");
143 		params->value_handle = 0U;
144 		return BT_GATT_ITER_STOP;
145 	}
146 
147 	cycle_now = k_cycle_get_32();
148 	delta = cycle_now - cycle_stamp;
149 	cycle_stamp = cycle_now;
150 	delta = k_cyc_to_ns_floor64(delta);
151 
152 	if (!IS_ENABLED(CONFIG_TEST_CONN_INTERVAL_1MS) ||
153 	    ((delta > (NSEC_PER_MSEC / 2U)) &&
154 	     (delta < (NSEC_PER_MSEC + (NSEC_PER_MSEC / 2U))))) {
155 		notify_count++;
156 	}
157 
158 	printk("[NOTIFICATION] %u. data %p length %u in %llu ns\n",
159 	       notify_count, data, length, delta);
160 
161 	if (notify_count >= TEST_NOTIFY_COUNT) { /* We consider it passed */
162 		int err;
163 
164 		/* Disconnect before actually passing */
165 		err = bt_conn_disconnect(default_conn,
166 					 BT_HCI_ERR_REMOTE_USER_TERM_CONN);
167 		if (err) {
168 			FAIL("Disconnection failed (err %d)\n", err);
169 			return BT_GATT_ITER_STOP;
170 		}
171 
172 		if (bst_result != Failed) {
173 			PASS("Testcase passed\n");
174 		}
175 		bs_trace_silent_exit(0);
176 	}
177 
178 	return BT_GATT_ITER_CONTINUE;
179 }
180 
discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)181 static uint8_t discover_func(struct bt_conn *conn,
182 		const struct bt_gatt_attr *attr,
183 		struct bt_gatt_discover_params *params)
184 {
185 	int err;
186 
187 	if (!attr) {
188 		printk("Discover complete\n");
189 		memset(params, 0, sizeof(*params));
190 		return BT_GATT_ITER_STOP;
191 	}
192 
193 	printk("[ATTRIBUTE] handle %u\n", attr->handle);
194 
195 	if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_HRS)) {
196 		memcpy(&uuid, BT_UUID_HRS_MEASUREMENT, sizeof(uuid));
197 		discover_params.uuid = &uuid.uuid;
198 		discover_params.start_handle = attr->handle + 1;
199 		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
200 
201 		err = bt_gatt_discover(conn, &discover_params);
202 		if (err) {
203 			FAIL("Discover failed (err %d)\n", err);
204 		}
205 	} else if (!bt_uuid_cmp(discover_params.uuid,
206 			BT_UUID_HRS_MEASUREMENT)) {
207 		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
208 		discover_params.uuid = &uuid.uuid;
209 		discover_params.start_handle = attr->handle + 2;
210 		discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
211 		subscribe_params.value_handle = attr->handle + 1;
212 
213 		err = bt_gatt_discover(conn, &discover_params);
214 		if (err) {
215 			FAIL("Discover failed (err %d)\n", err);
216 		}
217 	} else {
218 		subscribe_params.notify = notify_func;
219 		subscribe_params.value = BT_GATT_CCC_NOTIFY;
220 		subscribe_params.ccc_handle = attr->handle;
221 
222 		err = bt_gatt_subscribe(conn, &subscribe_params);
223 		if (err && err != -EALREADY) {
224 			FAIL("Subscribe failed (err %d)\n", err);
225 		} else {
226 			printk("[SUBSCRIBED]\n");
227 		}
228 
229 		return BT_GATT_ITER_STOP;
230 	}
231 
232 	return BT_GATT_ITER_STOP;
233 }
234 
update_conn(struct bt_conn * conn,bool bonded)235 static void update_conn(struct bt_conn *conn, bool bonded)
236 {
237 	int err;
238 
239 	if (encrypt_link != bonded) {
240 		FAIL("Unexpected bonding status\n");
241 		return;
242 	}
243 
244 	printk("Updating connection (bonded: %d)\n", bonded);
245 
246 	err = bt_conn_le_param_update(conn, &update_params);
247 	if (err) {
248 		FAIL("Parameter update failed (err %d)\n", err);
249 		return;
250 	}
251 }
252 
253 static struct bt_conn_auth_info_cb auth_cb_success = {
254 	.pairing_complete = update_conn,
255 };
256 
connected(struct bt_conn * conn,uint8_t conn_err)257 static void connected(struct bt_conn *conn, uint8_t conn_err)
258 {
259 	char addr[BT_ADDR_LE_STR_LEN];
260 	int err;
261 
262 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
263 
264 	if (conn_err) {
265 		FAIL("Failed to connect to %s (%u)\n", addr, conn_err);
266 		return;
267 	}
268 
269 	printk("Connected: %s\n", addr);
270 
271 	if (conn != default_conn) {
272 		return;
273 	}
274 
275 	if (encrypt_link) {
276 		k_sleep(K_MSEC(500));
277 		bt_conn_auth_info_cb_register(&auth_cb_success);
278 		err = bt_conn_set_security(conn, BT_SECURITY_L2);
279 		if (err) {
280 			FAIL("bt_conn_set_security failed (err %d)\n", err);
281 			return;
282 		}
283 	} else {
284 		update_conn(conn, false);
285 	}
286 }
287 
params_updated(struct bt_conn * conn,uint16_t interval,uint16_t latency,uint16_t timeout)288 static void params_updated(struct bt_conn *conn, uint16_t interval,
289 			   uint16_t latency, uint16_t timeout)
290 {
291 	uint8_t chm[5] = { 0x11, 0x22, 0x33, 0x44, 0x00 };
292 	int err;
293 
294 	if (interval != UPDATE_PARAM_INTERVAL_MAX ||
295 	    latency != UPDATE_PARAM_LATENCY ||
296 	    timeout != UPDATE_PARAM_TIMEOUT) {
297 		FAIL("Unexpected connection parameters "
298 		     "(interval: %d, latency: %d, timeout: %d)\n",
299 		     interval, latency, timeout);
300 		return;
301 	}
302 
303 	printk("Connection parameters updated "
304 	       "(interval: %d, latency: %d, timeout: %d)\n",
305 	       interval, latency, timeout);
306 
307 	err = bt_le_set_chan_map(chm);
308 	if (err) {
309 		FAIL("Channel map update failed (err %d)\n", err);
310 		return;
311 	}
312 
313 	if (!expect_ntf) {
314 		connected_signal = 1;
315 	} else {
316 		memcpy(&uuid, BT_UUID_HRS, sizeof(uuid));
317 		discover_params.uuid = &uuid.uuid;
318 		discover_params.func = discover_func;
319 		discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
320 		discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
321 		discover_params.type = BT_GATT_DISCOVER_PRIMARY;
322 
323 		err = bt_gatt_discover(conn, &discover_params);
324 		if (err) {
325 			FAIL("Discover failed(err %d)\n", err);
326 			return;
327 		}
328 	}
329 }
330 
eir_found(struct bt_data * data,void * user_data)331 static bool eir_found(struct bt_data *data, void *user_data)
332 {
333 	bt_addr_le_t *addr = user_data;
334 	int i;
335 
336 	printk("[AD]: %u data_len %u\n", data->type, data->data_len);
337 
338 	switch (data->type) {
339 	case BT_DATA_UUID16_SOME:
340 	case BT_DATA_UUID16_ALL:
341 		if (data->data_len % sizeof(uint16_t) != 0U) {
342 			FAIL("AD malformed\n");
343 			return true;
344 		}
345 
346 		for (i = 0; i < data->data_len; i += sizeof(uint16_t)) {
347 			const struct bt_uuid *uuid;
348 			struct bt_le_conn_param *param;
349 			uint16_t u16;
350 			int err;
351 
352 			memcpy(&u16, &data->data[i], sizeof(u16));
353 			uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(u16));
354 			if (bt_uuid_cmp(uuid, BT_UUID_HRS)) {
355 				continue;
356 			}
357 
358 			err = bt_le_scan_stop();
359 			if (err) {
360 				FAIL("Stop LE scan failed (err %d)\n", err);
361 				continue;
362 			}
363 
364 			param = BT_LE_CONN_PARAM_DEFAULT;
365 			err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
366 						param, &default_conn);
367 			if (err) {
368 				printk("Create conn failed (err %d)\n", err);
369 			}
370 
371 			return false;
372 		}
373 	}
374 
375 	return true;
376 }
377 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)378 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
379 		struct net_buf_simple *ad)
380 {
381 	char dev[BT_ADDR_LE_STR_LEN];
382 
383 	bt_addr_le_to_str(addr, dev, sizeof(dev));
384 	printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n",
385 			dev, type, ad->len, rssi);
386 
387 	/* We're only interested in connectable events */
388 	if (type == BT_GAP_ADV_TYPE_ADV_IND ||
389 	    type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
390 		bt_data_parse(ad, eir_found, (void *)addr);
391 	}
392 }
393 
disconnected(struct bt_conn * conn,uint8_t reason)394 static void disconnected(struct bt_conn *conn, uint8_t reason)
395 {
396 	char addr[BT_ADDR_LE_STR_LEN];
397 	int err;
398 
399 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
400 
401 	printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
402 
403 	if (default_conn != conn) {
404 		return;
405 	}
406 
407 	bt_conn_unref(default_conn);
408 	default_conn = NULL;
409 
410 	/* This demo doesn't require active scan */
411 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
412 	if (err) {
413 		FAIL("Scanning failed to start (err %d)\n", err);
414 	}
415 
416 	printk("Scanning successfully re-started\n");
417 }
418 
419 static struct bt_conn_cb conn_callbacks = {
420 	.connected = connected,
421 	.disconnected = disconnected,
422 	.le_param_updated = params_updated,
423 };
424 
test_con1_main(void)425 static void test_con1_main(void)
426 {
427 	int err;
428 
429 	bt_conn_cb_register(&conn_callbacks);
430 
431 	err = bt_enable(NULL);
432 
433 	if (err) {
434 		FAIL("Bluetooth init failed (err %d)\n", err);
435 		return;
436 	}
437 
438 	printk("Bluetooth initialized\n");
439 
440 	err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
441 
442 	if (err) {
443 		FAIL("Scanning failed to start (err %d)\n", err);
444 		return;
445 	}
446 
447 	printk("Scanning successfully started\n");
448 }
449 
test_con20_main(void)450 static void test_con20_main(void)
451 {
452 	int err;
453 
454 	bt_conn_cb_register(&conn_callbacks);
455 
456 	err = bt_enable(NULL);
457 
458 	if (err) {
459 		FAIL("Bluetooth init failed (err %d)\n", err);
460 		return;
461 	}
462 
463 	printk("Bluetooth initialized\n");
464 
465 	err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
466 
467 	if (err) {
468 		FAIL("Scanning failed to start (err %d)\n", err);
469 		return;
470 	}
471 
472 	printk("Scanning successfully started\n");
473 	/* Implement notification. At the moment there is no suitable way
474 	 * of starting delayed work so we do it here
475 	 */
476 	while (1) {
477 		k_sleep(K_MSEC(500));
478 
479 		if (connected_signal) {
480 			/* Disconnect and continue */
481 			printk("Central Disconnect\n");
482 			connected_signal = 0;
483 			err = bt_conn_disconnect(default_conn,
484 						 BT_HCI_ERR_REMOTE_USER_TERM_CONN);
485 			if (err) {
486 				FAIL("Disconnection failed (err %d)\n", err);
487 				return;
488 			}
489 
490 			if (bst_result != Failed) {
491 				if (repeat_connect) {
492 					printk("Disconnection OK\n");
493 				} else {
494 					PASS("Testcase passed\n");
495 				}
496 			}
497 			if (!repeat_connect || bst_result == Failed) {
498 				bs_trace_silent_exit(0);
499 			}
500 			repeat_connect--;
501 		}
502 	}
503 
504 }
505 
506 static const struct bst_test_instance test_connect[] = {
507 	{
508 		.test_id = "central",
509 		.test_descr = "Basic connection test. It expects that a "
510 			      "peripheral device can be found. The test will "
511 			      "pass if it can connect to it, and receive a "
512 			      "notification in less than 5 seconds.",
513 		.test_pre_init_f = test_con1_init,
514 		.test_tick_f = test_con1_tick,
515 		.test_main_f = test_con1_main
516 	},
517 	{
518 		.test_id = "central_encrypted",
519 		.test_descr = "Same as central but with an encrypted link",
520 		.test_pre_init_f = test_con_encrypted_init,
521 		.test_tick_f = test_con1_tick,
522 		.test_main_f = test_con1_main
523 	},
524 	{
525 		.test_id = "central_repeat20",
526 		.test_descr = "Multiple connections test. It expects that a "
527 			      "peripheral device can be found. The test will "
528 			      "pass if it can connect to it 20 times, in less than 22 seconds."
529 			      "Disconnect and re-connect 20 times",
530 		.test_pre_init_f = test_con20_init,
531 		.test_tick_f = test_con20_tick,
532 		.test_main_f = test_con20_main
533 	},
534 	BSTEST_END_MARKER
535 };
536 
test_connect1_install(struct bst_test_list * tests)537 struct bst_test_list *test_connect1_install(struct bst_test_list *tests)
538 {
539 	tests = bst_add_tests(tests, test_connect);
540 	return tests;
541 }
542