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(¶ms, &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(¶ms, &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