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(&param, 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