1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "bs_bt_utils.h"
8 
9 #include <stdint.h>
10 #include <string.h>
11 
12 #include <zephyr/bluetooth/addr.h>
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/bluetooth/conn.h>
15 #include <zephyr/toolchain.h>
16 
17 #include <babblekit/testcase.h>
18 
19 DEFINE_FLAG(flag_new_address);
20 DEFINE_FLAG(flag_connected);
21 
scanned_cb(struct bt_le_ext_adv * adv,struct bt_le_ext_adv_scanned_info * info)22 void scanned_cb(struct bt_le_ext_adv *adv, struct bt_le_ext_adv_scanned_info *info)
23 {
24 	static bool init;
25 	static int64_t old_time;
26 	static bt_addr_le_t old_addr;
27 	bt_addr_le_t new_addr;
28 
29 	if (bst_result == Passed) {
30 		return;
31 	}
32 
33 	if (!init) {
34 		old_addr = *info->addr;
35 		old_time = k_uptime_get();
36 		init = true;
37 	}
38 
39 	new_addr = *info->addr;
40 
41 	/* Check if the scan request comes from a new address */
42 	if (bt_addr_le_cmp(&old_addr, &new_addr)) {
43 		int64_t new_time, diff, time_diff_ms, rpa_timeout_ms;
44 
45 		printk("Scanned request from new ");
46 		print_address(info->addr);
47 
48 		/* Ensure the RPA rotation occurs within +-10% of CONFIG_BT_RPA_TIMEOUT */
49 		new_time = k_uptime_get();
50 		time_diff_ms = new_time - old_time;
51 		rpa_timeout_ms = CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC;
52 
53 		if (time_diff_ms > rpa_timeout_ms) {
54 			diff = time_diff_ms - rpa_timeout_ms;
55 		} else {
56 			diff = rpa_timeout_ms - time_diff_ms;
57 		}
58 
59 		if (diff > rpa_timeout_ms * 0.10) {
60 			FAIL("RPA rotation did not occur within +-10%% of CONFIG_BT_RPA_TIMEOUT");
61 		}
62 		old_time = new_time;
63 
64 		SET_FLAG(flag_new_address);
65 	}
66 
67 	old_addr = new_addr;
68 }
69 
connected_cb(struct bt_le_ext_adv * adv,struct bt_le_ext_adv_connected_info * info)70 static void connected_cb(struct bt_le_ext_adv *adv, struct bt_le_ext_adv_connected_info *info)
71 {
72 	SET_FLAG(flag_connected);
73 }
74 
75 static struct bt_le_ext_adv_cb adv_callbacks = {
76 	.scanned = scanned_cb,
77 	.connected = connected_cb
78 };
79 
start_advertising(void)80 void start_advertising(void)
81 {
82 	int err;
83 	uint8_t mfg_data[] = {0xAB, 0xCD, 0xEF};
84 	const struct bt_data sd[] = {BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, 3)};
85 	struct bt_le_adv_param params;
86 	struct bt_le_ext_adv_start_param start_params;
87 	struct bt_le_ext_adv *adv;
88 
89 	/* Enable bluetooth */
90 	err = bt_enable(NULL);
91 	if (err) {
92 		FAIL("Failed to enable bluetooth (err %d\n)", err);
93 	}
94 
95 	/* Create advertising set */
96 	params.id = BT_ID_DEFAULT;
97 	params.sid = 0;
98 	params.secondary_max_skip = 0;
99 	params.options = BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_SCANNABLE |
100 			 BT_LE_ADV_OPT_NOTIFY_SCAN_REQ;
101 	params.interval_min = BT_GAP_ADV_FAST_INT_MIN_1;
102 	params.interval_max = BT_GAP_ADV_FAST_INT_MAX_1;
103 	params.peer = NULL;
104 
105 	err = bt_le_ext_adv_create(&params, &adv_callbacks, &adv);
106 	if (err) {
107 		FAIL("Failed to create advertising set (err %d)\n", err);
108 	}
109 
110 	/* Set scan data */
111 	err = bt_le_ext_adv_set_data(adv, NULL, 0, sd, ARRAY_SIZE(sd));
112 	if (err) {
113 		FAIL("Failed to set advertising data (err %d)", err);
114 	}
115 
116 	/* Start advertising */
117 	start_params.timeout = 0;
118 	start_params.num_events = 0;
119 
120 	err = bt_le_ext_adv_start(adv, &start_params);
121 	if (err) {
122 		FAIL("Failed to start advertising (err %d)\n", err);
123 	}
124 }
125 
tester_procedure(void)126 void tester_procedure(void)
127 {
128 	start_advertising();
129 
130 	for (int i = 0; i < 5; i++) {
131 		WAIT_FOR_FLAG(flag_new_address);
132 		UNSET_FLAG(flag_new_address);
133 	}
134 
135 	PASS("PASS\n");
136 }
137 
tester_procedure_periph_delayed_start_of_conn_adv(void)138 void tester_procedure_periph_delayed_start_of_conn_adv(void)
139 {
140 	backchannel_init(0);
141 
142 	int err;
143 	struct bt_le_adv_param params =
144 		BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONN | BT_LE_ADV_OPT_USE_IDENTITY,
145 				     BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL);
146 	struct bt_data ad;
147 	struct bt_le_ext_adv *adv;
148 
149 	/* Enable bluetooth */
150 	err = bt_enable(NULL);
151 	TEST_ASSERT(!err, "Failed to enable bluetooth (err %d)");
152 
153 	/* Advertiser to use a long RPA timeout */
154 	err = bt_le_set_rpa_timeout(100);
155 	TEST_ASSERT(!err, "Failed to set RPA timeout (err %d)", err);
156 
157 	err = bt_le_ext_adv_create(&params, &adv_callbacks, &adv);
158 	TEST_ASSERT(!err, "Failed to create advertising set (err %d)", err);
159 
160 	ad.type = BT_DATA_NAME_COMPLETE;
161 	ad.data_len = strlen(CONFIG_BT_DEVICE_NAME);
162 	ad.data = (const uint8_t *)CONFIG_BT_DEVICE_NAME;
163 
164 	err = bt_le_ext_adv_set_data(adv, &ad, 1, NULL, 0);
165 	TEST_ASSERT(!err, "Failed to set advertising data (err %d)", err);
166 
167 	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
168 	TEST_ASSERT(!err, "Failed to start advertiser (err %d)", err);
169 
170 	backchannel_sync_wait();
171 
172 	err = bt_le_ext_adv_stop(adv);
173 	TEST_ASSERT(!err, "Failed to stop advertiser (err %d)", err);
174 
175 	/* Wait a few RPA cycles before restaring the advertiser to force RPA timeout
176 	 * on the DUT.
177 	 */
178 	k_sleep(K_SECONDS(7));
179 
180 	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
181 	TEST_ASSERT(!err, "Failed to restart advertiser (err %d)", err);
182 
183 	WAIT_FOR_FLAG(flag_connected);
184 
185 	PASS("PASS\n");
186 }
187