1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "bs_bt_utils.h"
8 #include "argparse.h"
9 #include "bs_pc_backchannel.h"
10
11 BUILD_ASSERT(CONFIG_BT_MAX_PAIRED >= 2, "CONFIG_BT_MAX_PAIRED is too small.");
12 BUILD_ASSERT(CONFIG_BT_ID_MAX == 2, "CONFIG_BT_ID_MAX should be 2.");
13
14 #define BS_SECONDS(dur_sec) ((bs_time_t)dur_sec * USEC_PER_SEC)
15 #define TEST_TIMEOUT_SIMULATED BS_SECONDS(60)
16
17 DEFINE_FLAG(flag_is_connected);
18 DEFINE_FLAG(flag_test_end);
19
test_tick(bs_time_t HW_device_time)20 void test_tick(bs_time_t HW_device_time)
21 {
22 bs_trace_debug_time(0, "Simulation ends now.\n");
23 if (bst_result != Passed) {
24 bst_result = Failed;
25 bs_trace_error("Test did not pass before simulation ended.\n");
26 }
27 }
28
test_init(void)29 void test_init(void)
30 {
31 bst_ticker_set_next_tick_absolute(TEST_TIMEOUT_SIMULATED);
32 bst_result = In_progress;
33 }
34
wait_connected(void)35 void wait_connected(void)
36 {
37 UNSET_FLAG(flag_is_connected);
38 WAIT_FOR_FLAG(flag_is_connected);
39 printk("connected\n");
40 }
41
wait_disconnected(void)42 void wait_disconnected(void)
43 {
44 SET_FLAG(flag_is_connected);
45 WAIT_FOR_FLAG_UNSET(flag_is_connected);
46 printk("disconnected\n");
47 }
48
disconnected(struct bt_conn * conn,uint8_t reason)49 static void disconnected(struct bt_conn *conn, uint8_t reason)
50 {
51 UNSET_FLAG(flag_is_connected);
52 }
53
connected(struct bt_conn * conn,uint8_t err)54 static void connected(struct bt_conn *conn, uint8_t err)
55 {
56 if (err != 0) {
57 return;
58 }
59
60 SET_FLAG(flag_is_connected);
61 }
62
63 BT_CONN_CB_DEFINE(conn_callbacks) = {
64 .connected = connected,
65 .disconnected = disconnected,
66 };
67
bs_bt_utils_setup(void)68 void bs_bt_utils_setup(void)
69 {
70 int err;
71
72 UNSET_FLAG(flag_test_end);
73
74 err = bt_enable(NULL);
75 ASSERT(!err, "bt_enable failed.\n");
76 }
77
78 #if defined(CONFIG_BT_CENTRAL)
79 static bt_addr_le_t last_scanned_addr;
80 #endif /* CONFIG_BT_CENTRAL */
81
scan_connect_to_first_result_device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)82 static void scan_connect_to_first_result_device_found(const bt_addr_le_t *addr, int8_t rssi,
83 uint8_t type, struct net_buf_simple *ad)
84 {
85 #if defined(CONFIG_BT_CENTRAL)
86 struct bt_conn *conn;
87 char addr_str[BT_ADDR_LE_STR_LEN];
88 int err;
89
90 /* We're only interested in connectable events */
91 if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) {
92 FAIL("Unexpected advertisement type.");
93 }
94
95 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
96 printk("Got scan result, connecting.. dst %s, RSSI %d\n",
97 addr_str, rssi);
98
99 err = bt_le_scan_stop();
100 ASSERT(!err, "Err bt_le_scan_stop %d", err);
101
102 err = bt_conn_le_create(addr,
103 BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
104 &conn);
105 ASSERT(!err, "Err bt_conn_le_create %d", err);
106
107 /* Save address for later comparison */
108 memcpy(&last_scanned_addr, addr, sizeof(last_scanned_addr));
109 #endif /* CONFIG_BT_CENTRAL */
110 }
111
scan_connect_to_first_result(void)112 void scan_connect_to_first_result(void)
113 {
114 if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
115 printk("start scanner\n");
116 int err = bt_le_scan_start(
117 BT_LE_SCAN_PARAM(BT_LE_SCAN_TYPE_PASSIVE,
118 BT_LE_SCAN_OPT_FILTER_DUPLICATE,
119 10,
120 10),
121 scan_connect_to_first_result_device_found);
122
123 ASSERT(!err, "Err bt_le_scan_start %d", err);
124 }
125 }
126
scan_expect_same_address_device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)127 static void scan_expect_same_address_device_found(const bt_addr_le_t *addr, int8_t rssi,
128 uint8_t type, struct net_buf_simple *ad)
129 {
130 #if defined(CONFIG_BT_CENTRAL)
131 char addr_str[BT_ADDR_LE_STR_LEN];
132 char expected_addr_str[BT_ADDR_LE_STR_LEN];
133
134 /* We're only interested in connectable events */
135 if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) {
136 FAIL("Unexpected advertisement type.");
137 }
138
139 if (!bt_addr_le_eq(&last_scanned_addr, addr)) {
140 bt_addr_le_to_str(&last_scanned_addr,
141 expected_addr_str,
142 sizeof(expected_addr_str));
143 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
144
145 FAIL("Expected advertiser with addr %s, got %s\n",
146 expected_addr_str, addr_str);
147 }
148
149 int err = bt_le_scan_stop();
150
151 ASSERT(!err, "Err bt_le_scan_stop %d", err);
152 #endif /* CONFIG_BT_CENTRAL */
153
154 PASS("Advertiser used correct address on resume\n");
155 }
156
scan_expect_same_address(void)157 void scan_expect_same_address(void)
158 {
159 if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
160 printk("start scanner\n");
161 int err = bt_le_scan_start(BT_LE_SCAN_PASSIVE,
162 scan_expect_same_address_device_found);
163
164 ASSERT(!err, "Err bt_le_scan_start %d", err);
165 }
166 }
167
disconnect_device(struct bt_conn * conn,void * data)168 static void disconnect_device(struct bt_conn *conn, void *data)
169 {
170 int err;
171
172 /* We only use a single flag to indicate connections. Since this
173 * function will be called multiple times in a row, we have to set it
174 * back after it has been unset (in the `disconnected` callback).
175 */
176 SET_FLAG(flag_is_connected);
177
178 err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
179 ASSERT(!err, "Failed to initate disconnect (err %d)", err);
180
181 printk("Waiting for disconnection...\n");
182 WAIT_FOR_FLAG_UNSET(flag_is_connected);
183 }
184
disconnect(void)185 void disconnect(void)
186 {
187 bt_conn_foreach(BT_CONN_TYPE_LE, disconnect_device, NULL);
188 }
189
advertise_connectable(int id,bool persist)190 void advertise_connectable(int id, bool persist)
191 {
192 printk("start advertiser\n");
193 int err;
194 struct bt_le_adv_param param = {};
195
196 param.id = id;
197 param.interval_min = 0x0020;
198 param.interval_max = 0x4000;
199 param.options |= persist ? 0 : BT_LE_ADV_OPT_ONE_TIME;
200 param.options |= BT_LE_ADV_OPT_CONNECTABLE;
201
202 err = bt_le_adv_start(¶m, NULL, 0, NULL, 0);
203 ASSERT(err == 0, "Advertising failed to start (err %d)\n", err);
204 }
205
206 #define CHANNEL_ID 0
207 #define MSG_SIZE 1
208
backchannel_init(uint peer)209 void backchannel_init(uint peer)
210 {
211 uint device_number = get_device_nbr();
212 uint device_numbers[] = { peer };
213 uint channel_numbers[] = { CHANNEL_ID };
214 uint *ch;
215
216 ch = bs_open_back_channel(device_number, device_numbers,
217 channel_numbers, ARRAY_SIZE(channel_numbers));
218 if (!ch) {
219 FAIL("Unable to open backchannel\n");
220 }
221 }
222
backchannel_sync_send(void)223 void backchannel_sync_send(void)
224 {
225 uint8_t sync_msg[MSG_SIZE] = { get_device_nbr() };
226
227 printk("Sending sync\n");
228 bs_bc_send_msg(CHANNEL_ID, sync_msg, ARRAY_SIZE(sync_msg));
229 }
230
backchannel_sync_wait(void)231 void backchannel_sync_wait(void)
232 {
233 uint8_t sync_msg[MSG_SIZE];
234
235 while (true) {
236 if (bs_bc_is_msg_received(CHANNEL_ID) > 0) {
237 bs_bc_receive_msg(CHANNEL_ID, sync_msg,
238 ARRAY_SIZE(sync_msg));
239 if (sync_msg[0] != get_device_nbr()) {
240 /* Received a message from another device, exit */
241 break;
242 }
243 }
244
245 k_sleep(K_MSEC(1));
246 }
247
248 printk("Sync received\n");
249 }
250