1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2021 Nordic Semiconductor ASA
5  * Copyright (c) 2015-2016 Intel Corporation
6  *
7  * SPDX-License-Identifier: Apache-2.0
8  */
9 
10 #include <zephyr/types.h>
11 #include <stddef.h>
12 #include <errno.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/sys/printk.h>
15 
16 #include <zephyr/bluetooth/bluetooth.h>
17 #include <zephyr/bluetooth/hci.h>
18 #include <zephyr/bluetooth/conn.h>
19 #include <zephyr/bluetooth/uuid.h>
20 #include <zephyr/bluetooth/gatt.h>
21 #include <zephyr/sys/byteorder.h>
22 
23 #define SCAN_INTERVAL 0x0010 /* 10 ms */
24 #define SCAN_WINDOW   0x0010 /* 10 ms */
25 #define INIT_INTERVAL 0x0010 /* 10 ms */
26 #define INIT_WINDOW   0x0010 /* 10 ms */
27 #define CONN_INTERVAL 0x0320 /* 1000 ms */
28 #define CONN_LATENCY  0
29 #define CONN_TIMEOUT  MIN(MAX((CONN_INTERVAL * 125 * \
30 			       MAX(CONFIG_BT_MAX_CONN, 6) / 1000), 10), 3200)
31 
32 static void start_scan(void);
33 
34 static struct bt_conn *conn_connecting;
35 static uint8_t conn_count_max;
36 static uint8_t volatile conn_count;
37 static bool volatile is_disconnecting;
38 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)39 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
40 			 struct net_buf_simple *ad)
41 {
42 	struct bt_conn_le_create_param create_param = {
43 		.options = BT_CONN_LE_OPT_NONE,
44 		.interval = INIT_INTERVAL,
45 		.window = INIT_WINDOW,
46 		.interval_coded = 0,
47 		.window_coded = 0,
48 		.timeout = 0,
49 	};
50 	struct bt_le_conn_param conn_param = {
51 		.interval_min = CONN_INTERVAL,
52 		.interval_max = CONN_INTERVAL,
53 		.latency = CONN_LATENCY,
54 		.timeout = CONN_TIMEOUT,
55 	};
56 	char addr_str[BT_ADDR_LE_STR_LEN];
57 	int err;
58 
59 	if (conn_connecting) {
60 		return;
61 	}
62 
63 	/* We're only interested in connectable events */
64 	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
65 	    type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND &&
66 	    type != BT_GAP_ADV_TYPE_EXT_ADV) {
67 		return;
68 	}
69 
70 	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
71 	printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
72 
73 	/* connect only to devices in close proximity */
74 	if (rssi < -50) {
75 		return;
76 	}
77 
78 	err = bt_le_scan_stop();
79 	if (err != 0) {
80 		printk("Failed to stop scanning (err %d)\n", err);
81 		return;
82 	}
83 
84 	err = bt_conn_le_create(addr, &create_param, &conn_param,
85 				&conn_connecting);
86 	if (err) {
87 		printk("Create conn to %s failed (%d)\n", addr_str, err);
88 		start_scan();
89 	}
90 }
91 
start_scan(void)92 static void start_scan(void)
93 {
94 	struct bt_le_scan_param scan_param = {
95 		.type       = BT_LE_SCAN_TYPE_PASSIVE,
96 		.options    = BT_LE_SCAN_OPT_NONE,
97 		.interval   = SCAN_INTERVAL,
98 		.window     = SCAN_WINDOW,
99 	};
100 	int err;
101 
102 	err = bt_le_scan_start(&scan_param, device_found);
103 	if (err) {
104 		printk("Scanning failed to start (err %d)\n", err);
105 		return;
106 	}
107 
108 	printk("Scanning successfully started\n");
109 }
110 
111 #if defined(CONFIG_BT_GATT_CLIENT)
mtu_exchange_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_exchange_params * params)112 static void mtu_exchange_cb(struct bt_conn *conn, uint8_t err,
113 			    struct bt_gatt_exchange_params *params)
114 {
115 	printk("MTU exchange %u %s (%u)\n", bt_conn_index(conn),
116 	       err == 0U ? "successful" : "failed", bt_gatt_get_mtu(conn));
117 }
118 
119 static struct bt_gatt_exchange_params mtu_exchange_params[CONFIG_BT_MAX_CONN];
120 
mtu_exchange(struct bt_conn * conn)121 static int mtu_exchange(struct bt_conn *conn)
122 {
123 	uint8_t conn_index;
124 	int err;
125 
126 	conn_index = bt_conn_index(conn);
127 
128 	printk("MTU (%u): %u\n", conn_index, bt_gatt_get_mtu(conn));
129 
130 	mtu_exchange_params[conn_index].func = mtu_exchange_cb;
131 
132 	err = bt_gatt_exchange_mtu(conn, &mtu_exchange_params[conn_index]);
133 	if (err) {
134 		printk("MTU exchange failed (err %d)", err);
135 	} else {
136 		printk("Exchange pending...");
137 	}
138 
139 	return err;
140 }
141 #endif /* CONFIG_BT_GATT_CLIENT */
142 
connected(struct bt_conn * conn,uint8_t reason)143 static void connected(struct bt_conn *conn, uint8_t reason)
144 {
145 	char addr[BT_ADDR_LE_STR_LEN];
146 
147 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
148 
149 	if (reason) {
150 		printk("Failed to connect to %s (%u)\n", addr, reason);
151 
152 		bt_conn_unref(conn_connecting);
153 		conn_connecting = NULL;
154 
155 		start_scan();
156 		return;
157 	}
158 
159 	conn_connecting = NULL;
160 
161 	conn_count++;
162 	if (conn_count < conn_count_max) {
163 		start_scan();
164 	}
165 
166 	printk("Connected (%u): %s\n", conn_count, addr);
167 
168 #if defined(CONFIG_BT_SMP)
169 	int err = bt_conn_set_security(conn, BT_SECURITY_L2);
170 
171 	if (err) {
172 		printk("Failed to set security (%d).\n", err);
173 	}
174 #endif
175 
176 #if defined(CONFIG_BT_GATT_CLIENT)
177 	mtu_exchange(conn);
178 #endif
179 }
180 
disconnected(struct bt_conn * conn,uint8_t reason)181 static void disconnected(struct bt_conn *conn, uint8_t reason)
182 {
183 	char addr[BT_ADDR_LE_STR_LEN];
184 
185 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
186 
187 	printk("Disconnected: %s, reason 0x%02x %s\n", addr, reason, bt_hci_err_to_str(reason));
188 
189 	bt_conn_unref(conn);
190 
191 	if ((conn_count == 1U) && (is_disconnecting || (reason == BT_HCI_ERR_CONN_FAIL_TO_ESTAB))) {
192 		is_disconnecting = false;
193 		start_scan();
194 	}
195 	conn_count--;
196 }
197 
le_param_req(struct bt_conn * conn,struct bt_le_conn_param * param)198 static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
199 {
200 	char addr[BT_ADDR_LE_STR_LEN];
201 
202 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
203 
204 	printk("LE conn param req: %s int (0x%04x, 0x%04x) lat %d to %d\n",
205 	       addr, param->interval_min, param->interval_max, param->latency,
206 	       param->timeout);
207 
208 	return true;
209 }
210 
le_param_updated(struct bt_conn * conn,uint16_t interval,uint16_t latency,uint16_t timeout)211 static void le_param_updated(struct bt_conn *conn, uint16_t interval,
212 			     uint16_t latency, uint16_t timeout)
213 {
214 	char addr[BT_ADDR_LE_STR_LEN];
215 
216 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
217 
218 	printk("LE conn param updated: %s int 0x%04x lat %d to %d\n",
219 	       addr, interval, latency, timeout);
220 }
221 
222 #if defined(CONFIG_BT_SMP)
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)223 static void security_changed(struct bt_conn *conn, bt_security_t level,
224 			     enum bt_security_err err)
225 {
226 	char addr[BT_ADDR_LE_STR_LEN];
227 
228 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
229 
230 	if (!err) {
231 		printk("Security changed: %s level %u\n", addr, level);
232 	} else {
233 		printk("Security failed: %s level %u err %d %s\n", addr, level,
234 		       err, bt_security_err_to_str(err));
235 	}
236 }
237 #endif
238 
239 #if defined(CONFIG_BT_USER_PHY_UPDATE)
le_phy_updated(struct bt_conn * conn,struct bt_conn_le_phy_info * param)240 static void le_phy_updated(struct bt_conn *conn,
241 			   struct bt_conn_le_phy_info *param)
242 {
243 	char addr[BT_ADDR_LE_STR_LEN];
244 
245 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
246 
247 	printk("LE PHY Updated: %s Tx 0x%x, Rx 0x%x\n", addr, param->tx_phy,
248 	       param->rx_phy);
249 }
250 #endif /* CONFIG_BT_USER_PHY_UPDATE */
251 
252 #if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
le_data_len_updated(struct bt_conn * conn,struct bt_conn_le_data_len_info * info)253 static void le_data_len_updated(struct bt_conn *conn,
254 				struct bt_conn_le_data_len_info *info)
255 {
256 	char addr[BT_ADDR_LE_STR_LEN];
257 
258 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
259 
260 	printk("Data length updated: %s max tx %u (%u us) max rx %u (%u us)\n",
261 	       addr, info->tx_max_len, info->tx_max_time, info->rx_max_len,
262 	       info->rx_max_time);
263 }
264 #endif /* CONFIG_BT_USER_DATA_LEN_UPDATE */
265 
266 static struct bt_conn_cb conn_callbacks = {
267 	.connected = connected,
268 	.disconnected = disconnected,
269 	.le_param_req = le_param_req,
270 	.le_param_updated = le_param_updated,
271 
272 #if defined(CONFIG_BT_SMP)
273 	.security_changed = security_changed,
274 #endif
275 
276 #if defined(CONFIG_BT_USER_PHY_UPDATE)
277 	.le_phy_updated = le_phy_updated,
278 #endif /* CONFIG_BT_USER_PHY_UPDATE */
279 
280 #if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
281 	.le_data_len_updated = le_data_len_updated,
282 #endif /* CONFIG_BT_USER_DATA_LEN_UPDATE */
283 };
284 
remote_info(struct bt_conn * conn,void * data)285 static void remote_info(struct bt_conn *conn, void *data)
286 {
287 	struct bt_conn_remote_info remote_info;
288 	char addr[BT_ADDR_LE_STR_LEN];
289 	int err;
290 
291 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
292 
293 	printk("Get remote info %s...\n", addr);
294 	err = bt_conn_get_remote_info(conn, &remote_info);
295 	if (err) {
296 		printk("Failed remote info %s (err: %d)\n", addr, err);
297 		return;
298 	}
299 	printk("Successfully got remote info %s\n", addr);
300 
301 	uint8_t *actual_count = (void *)data;
302 
303 	(*actual_count)++;
304 }
305 
disconnect(struct bt_conn * conn,void * data)306 static void disconnect(struct bt_conn *conn, void *data)
307 {
308 	char addr[BT_ADDR_LE_STR_LEN];
309 	int err;
310 
311 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
312 
313 	printk("Disconnecting %s...\n", addr);
314 
315 	err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
316 	if (err) {
317 		printk("Failed disconnection %s.\n", addr);
318 		return;
319 	}
320 
321 	printk("Disconnect initiated\n");
322 }
323 
init_central(uint8_t max_conn,uint8_t iterations)324 int init_central(uint8_t max_conn, uint8_t iterations)
325 {
326 	int err;
327 
328 	conn_count_max = max_conn;
329 
330 	err = bt_enable(NULL);
331 	if (err) {
332 		printk("Bluetooth init failed (err %d)\n", err);
333 		return err;
334 	}
335 
336 	printk("Bluetooth initialized\n");
337 
338 	bt_conn_cb_register(&conn_callbacks);
339 
340 	start_scan();
341 
342 	while (true) {
343 		if (conn_count < conn_count_max) {
344 			printk("Waiting for connections...\n");
345 
346 			while (conn_count < conn_count_max) {
347 				k_sleep(K_MSEC(10));
348 			}
349 		}
350 
351 		is_disconnecting = true;
352 
353 		/* Let us perform version exchange on all connections to ensure
354 		 * there is actual communication.
355 		 */
356 		uint8_t actual_count = 0U;
357 
358 		bt_conn_foreach(BT_CONN_TYPE_LE, remote_info, &actual_count);
359 		if (actual_count < conn_count_max) {
360 			k_sleep(K_MSEC(10));
361 
362 			continue;
363 		}
364 
365 		/* Lets wait sufficiently to ensure a stable connection
366 		 * before starting to disconnect for next iteration.
367 		 */
368 		printk("Waiting for stable connections...\n");
369 		k_sleep(K_SECONDS(60));
370 
371 		if (!iterations) {
372 			break;
373 		}
374 		iterations--;
375 		printk("Iterations remaining: %u\n", iterations);
376 
377 		/* Device needing multiple connections is the one
378 		 * initiating the disconnects.
379 		 */
380 		if (conn_count_max > 1U) {
381 			printk("Disconnecting all...\n");
382 			bt_conn_foreach(BT_CONN_TYPE_LE, disconnect, NULL);
383 		} else {
384 			printk("Wait for disconnections...\n");
385 		}
386 
387 		while (is_disconnecting) {
388 			k_sleep(K_MSEC(10));
389 		}
390 		printk("All disconnected.\n");
391 	}
392 
393 	return 0;
394 }
395