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.h>
14 #include <sys/printk.h>
15 
16 #include <bluetooth/bluetooth.h>
17 #include <bluetooth/hci.h>
18 #include <bluetooth/conn.h>
19 #include <bluetooth/uuid.h>
20 #include <bluetooth/gatt.h>
21 #include <sys/byteorder.h>
22 
23 #define SCAN_INTERVAL 0x0140 /* 200 ms */
24 #define SCAN_WINDOW   0x0030 /* 30 ms */
25 #define INIT_INTERVAL 0x0010 /* 10 ms */
26 #define INIT_WINDOW   0x0010 /* 10 ms */
27 #define CONN_INTERVAL 0x00A0 /* 200 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 volatile conn_count;
36 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)37 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
38 			 struct net_buf_simple *ad)
39 {
40 	struct bt_conn_le_create_param create_param = {
41 		.options = BT_CONN_LE_OPT_NONE,
42 		.interval = INIT_INTERVAL,
43 		.window = INIT_WINDOW,
44 		.interval_coded = 0,
45 		.window_coded = 0,
46 		.timeout = 0,
47 	};
48 	struct bt_le_conn_param conn_param = {
49 		.interval_min = CONN_INTERVAL,
50 		.interval_max = CONN_INTERVAL,
51 		.latency = CONN_LATENCY,
52 		.timeout = CONN_TIMEOUT,
53 	};
54 	char addr_str[BT_ADDR_LE_STR_LEN];
55 	int err;
56 
57 	if (conn_connecting) {
58 		return;
59 	}
60 
61 	/* We're only interested in connectable events */
62 	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
63 	    type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
64 		return;
65 	}
66 
67 	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
68 	printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
69 
70 	/* connect only to devices in close proximity */
71 	if (rssi < -35) {
72 		return;
73 	}
74 
75 	if (bt_le_scan_stop()) {
76 		return;
77 	}
78 
79 	err = bt_conn_le_create(addr, &create_param, &conn_param,
80 				&conn_connecting);
81 	if (err) {
82 		printk("Create conn to %s failed (%d)\n", addr_str, err);
83 		start_scan();
84 	}
85 }
86 
start_scan(void)87 static void start_scan(void)
88 {
89 	struct bt_le_scan_param scan_param = {
90 		.type       = BT_HCI_LE_SCAN_PASSIVE,
91 		.options    = BT_LE_SCAN_OPT_NONE,
92 		.interval   = SCAN_INTERVAL,
93 		.window     = SCAN_WINDOW,
94 	};
95 	int err;
96 
97 	err = bt_le_scan_start(&scan_param, device_found);
98 	if (err) {
99 		printk("Scanning failed to start (err %d)\n", err);
100 		return;
101 	}
102 
103 	printk("Scanning successfully started\n");
104 }
105 
106 #if defined(CONFIG_BT_GATT_CLIENT)
mtu_exchange_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_exchange_params * params)107 static void mtu_exchange_cb(struct bt_conn *conn, uint8_t err,
108 			    struct bt_gatt_exchange_params *params)
109 {
110 	printk("MTU exchange %u %s (%u)\n", bt_conn_index(conn),
111 	       err == 0U ? "successful" : "failed", bt_gatt_get_mtu(conn));
112 }
113 
114 static struct bt_gatt_exchange_params mtu_exchange_params[CONFIG_BT_MAX_CONN];
115 
mtu_exchange(struct bt_conn * conn)116 static int mtu_exchange(struct bt_conn *conn)
117 {
118 	uint8_t conn_index;
119 	int err;
120 
121 	conn_index = bt_conn_index(conn);
122 
123 	printk("MTU (%u): %u\n", conn_index, bt_gatt_get_mtu(conn));
124 
125 	mtu_exchange_params[conn_index].func = mtu_exchange_cb;
126 
127 	err = bt_gatt_exchange_mtu(conn, &mtu_exchange_params[conn_index]);
128 	if (err) {
129 		printk("MTU exchange failed (err %d)", err);
130 	} else {
131 		printk("Exchange pending...");
132 	}
133 
134 	return err;
135 }
136 #endif /* CONFIG_BT_GATT_CLIENT */
137 
connected(struct bt_conn * conn,uint8_t reason)138 static void connected(struct bt_conn *conn, uint8_t reason)
139 {
140 	char addr[BT_ADDR_LE_STR_LEN];
141 
142 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
143 
144 	if (reason) {
145 		printk("Failed to connect to %s (%u)\n", addr, reason);
146 
147 		bt_conn_unref(conn_connecting);
148 		conn_connecting = NULL;
149 
150 		start_scan();
151 		return;
152 	}
153 
154 	conn_connecting = NULL;
155 
156 	conn_count++;
157 	if (conn_count < CONFIG_BT_MAX_CONN) {
158 		start_scan();
159 	}
160 
161 	printk("Connected (%u): %s\n", conn_count, addr);
162 
163 #if defined(CONFIG_BT_SMP)
164 	int err = bt_conn_set_security(conn, BT_SECURITY_L2);
165 
166 	if (err) {
167 		printk("Failed to set security (%d).\n", err);
168 	}
169 #endif
170 
171 #if defined(CONFIG_BT_GATT_CLIENT)
172 	mtu_exchange(conn);
173 #endif
174 }
175 
disconnected(struct bt_conn * conn,uint8_t reason)176 static void disconnected(struct bt_conn *conn, uint8_t reason)
177 {
178 	char addr[BT_ADDR_LE_STR_LEN];
179 
180 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
181 
182 	printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
183 
184 	bt_conn_unref(conn);
185 
186 	if (conn_count == CONFIG_BT_MAX_CONN) {
187 		start_scan();
188 	}
189 	conn_count--;
190 }
191 
le_param_req(struct bt_conn * conn,struct bt_le_conn_param * param)192 static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
193 {
194 	char addr[BT_ADDR_LE_STR_LEN];
195 
196 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
197 
198 	printk("LE conn param req: %s int (0x%04x, 0x%04x) lat %d to %d\n",
199 	       addr, param->interval_min, param->interval_max, param->latency,
200 	       param->timeout);
201 
202 	return true;
203 }
204 
le_param_updated(struct bt_conn * conn,uint16_t interval,uint16_t latency,uint16_t timeout)205 static void le_param_updated(struct bt_conn *conn, uint16_t interval,
206 			     uint16_t latency, uint16_t timeout)
207 {
208 	char addr[BT_ADDR_LE_STR_LEN];
209 
210 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
211 
212 	printk("LE conn param updated: %s int 0x%04x lat %d to %d\n",
213 	       addr, interval, latency, timeout);
214 }
215 
216 #if defined(CONFIG_BT_SMP)
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)217 static void security_changed(struct bt_conn *conn, bt_security_t level,
218 			     enum bt_security_err err)
219 {
220 	char addr[BT_ADDR_LE_STR_LEN];
221 
222 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
223 
224 	if (!err) {
225 		printk("Security changed: %s level %u\n", addr, level);
226 	} else {
227 		printk("Security failed: %s level %u err %d\n", addr, level,
228 		       err);
229 	}
230 }
231 #endif
232 
233 static struct bt_conn_cb conn_callbacks = {
234 	.connected = connected,
235 	.disconnected = disconnected,
236 	.le_param_req = le_param_req,
237 	.le_param_updated = le_param_updated,
238 #if defined(CONFIG_BT_SMP)
239 	.security_changed = security_changed,
240 #endif
241 };
242 
init_central(void)243 int init_central(void)
244 {
245 	int err;
246 
247 	err = bt_enable(NULL);
248 	if (err) {
249 		printk("Bluetooth init failed (err %d)\n", err);
250 		return err;
251 	}
252 
253 	printk("Bluetooth initialized\n");
254 
255 	bt_conn_cb_register(&conn_callbacks);
256 
257 	start_scan();
258 
259 	while (conn_count < CONFIG_BT_MAX_CONN) {
260 		k_sleep(K_SECONDS(1));
261 	}
262 
263 	return 0;
264 }
265