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 <stddef.h>
11 #include <zephyr/sys/printk.h>
12
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/bluetooth/conn.h>
15 #include <zephyr/bluetooth/hci.h>
16
17 static struct k_work work_adv_start;
18 static uint8_t volatile conn_count;
19 static uint8_t id_current;
20 static bool volatile is_disconnecting;
21
22 static const struct bt_data ad[] = {
23 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
24 };
25
26 static const struct bt_data sd[] = {
27 BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
28 };
29
adv_start(struct k_work * work)30 static void adv_start(struct k_work *work)
31 {
32 struct bt_le_adv_param adv_param = {
33 .id = BT_ID_DEFAULT,
34 .sid = 0,
35 .secondary_max_skip = 0,
36 .options = (BT_LE_ADV_OPT_CONNECTABLE |
37 BT_LE_ADV_OPT_ONE_TIME),
38 .interval_min = 0x0020, /* 20 ms */
39 .interval_max = 0x0020, /* 20 ms */
40 .peer = NULL,
41 };
42 size_t id_count = 0xFF;
43 int err;
44
45 bt_id_get(NULL, &id_count);
46 if (id_current == id_count) {
47 int id;
48
49 id = bt_id_create(NULL, NULL);
50 if (id < 0) {
51 printk("Create id failed (%d)\n", id);
52 if (id_current == 0) {
53 id_current = CONFIG_BT_MAX_CONN;
54 }
55 id_current--;
56 } else {
57 printk("New id: %d\n", id);
58 }
59 }
60
61 printk("Using current id: %u\n", id_current);
62 adv_param.id = id_current;
63
64 err = bt_le_adv_start(&adv_param, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
65 if (err) {
66 printk("Advertising failed to start (err %d)\n", err);
67 return;
68 }
69
70 id_current++;
71 if (id_current == CONFIG_BT_MAX_CONN) {
72 id_current = 0;
73 }
74
75 printk("Advertising successfully started\n");
76 }
77
connected(struct bt_conn * conn,uint8_t err)78 static void connected(struct bt_conn *conn, uint8_t err)
79 {
80 char addr[BT_ADDR_LE_STR_LEN];
81
82 if (err) {
83 printk("Connection failed, err 0x%02x %s\n", err, bt_hci_err_to_str(err));
84 return;
85 }
86
87 conn_count++;
88 if (conn_count < CONFIG_BT_MAX_CONN) {
89 k_work_submit(&work_adv_start);
90 }
91
92 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
93
94 printk("Connected (%u): %s\n", conn_count, addr);
95 }
96
disconnected(struct bt_conn * conn,uint8_t reason)97 static void disconnected(struct bt_conn *conn, uint8_t reason)
98 {
99 char addr[BT_ADDR_LE_STR_LEN];
100
101 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
102
103 printk("Disconnected %s, reason %s(0x%02x)\n", addr, bt_hci_err_to_str(reason), reason);
104
105 if ((conn_count == 1U) && is_disconnecting) {
106 is_disconnecting = false;
107 k_work_submit(&work_adv_start);
108 }
109 conn_count--;
110 }
111
le_param_req(struct bt_conn * conn,struct bt_le_conn_param * param)112 static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
113 {
114 char addr[BT_ADDR_LE_STR_LEN];
115
116 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
117
118 printk("LE conn param req: %s int (0x%04x, 0x%04x) lat %d to %d\n",
119 addr, param->interval_min, param->interval_max, param->latency,
120 param->timeout);
121
122 return true;
123 }
124
le_param_updated(struct bt_conn * conn,uint16_t interval,uint16_t latency,uint16_t timeout)125 static void le_param_updated(struct bt_conn *conn, uint16_t interval,
126 uint16_t latency, uint16_t timeout)
127 {
128 char addr[BT_ADDR_LE_STR_LEN];
129
130 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
131
132 printk("LE conn param updated: %s int 0x%04x lat %d to %d\n",
133 addr, interval, latency, timeout);
134 }
135
136 #if defined(CONFIG_BT_USER_PHY_UPDATE)
le_phy_updated(struct bt_conn * conn,struct bt_conn_le_phy_info * param)137 static void le_phy_updated(struct bt_conn *conn,
138 struct bt_conn_le_phy_info *param)
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 printk("LE PHY Updated: %s Tx 0x%x, Rx 0x%x\n", addr, param->tx_phy,
145 param->rx_phy);
146 }
147 #endif /* CONFIG_BT_USER_PHY_UPDATE */
148
149 #if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
le_data_len_updated(struct bt_conn * conn,struct bt_conn_le_data_len_info * info)150 static void le_data_len_updated(struct bt_conn *conn,
151 struct bt_conn_le_data_len_info *info)
152 {
153 char addr[BT_ADDR_LE_STR_LEN];
154
155 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
156
157 printk("Data length updated: %s max tx %u (%u us) max rx %u (%u us)\n",
158 addr, info->tx_max_len, info->tx_max_time, info->rx_max_len,
159 info->rx_max_time);
160 }
161 #endif /* CONFIG_BT_USER_DATA_LEN_UPDATE */
162
163 #if defined(CONFIG_BT_SMP)
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)164 static void security_changed(struct bt_conn *conn, bt_security_t level,
165 enum bt_security_err err)
166 {
167 char addr[BT_ADDR_LE_STR_LEN];
168
169 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
170
171 if (!err) {
172 printk("Security changed: %s level %u\n", addr, level);
173 } else {
174 printk("Security failed: %s level %u err %s(%d)\n", addr, level,
175 bt_security_err_to_str(err), err);
176 }
177 }
178
auth_cancel(struct bt_conn * conn)179 static void auth_cancel(struct bt_conn *conn)
180 {
181 char addr[BT_ADDR_LE_STR_LEN];
182
183 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
184
185 printk("Pairing cancelled: %s\n", addr);
186 }
187
188 static struct bt_conn_auth_cb auth_callbacks = {
189 .cancel = auth_cancel,
190 };
191 #endif /* CONFIG_BT_SMP */
192
193 static struct bt_conn_cb conn_callbacks = {
194 .connected = connected,
195 .disconnected = disconnected,
196 .le_param_req = le_param_req,
197 .le_param_updated = le_param_updated,
198
199 #if defined(CONFIG_BT_SMP)
200 .security_changed = security_changed,
201 #endif /* CONFIG_BT_SMP */
202
203 #if defined(CONFIG_BT_USER_PHY_UPDATE)
204 .le_phy_updated = le_phy_updated,
205 #endif /* CONFIG_BT_USER_PHY_UPDATE */
206
207 #if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
208 .le_data_len_updated = le_data_len_updated,
209 #endif /* CONFIG_BT_USER_DATA_LEN_UPDATE */
210 };
211
212 #if defined(CONFIG_BT_OBSERVER)
213 #define BT_LE_SCAN_PASSIVE_ALLOW_DUPILCATES \
214 BT_LE_SCAN_PARAM(BT_LE_SCAN_TYPE_PASSIVE, \
215 BT_LE_SCAN_OPT_NONE, \
216 BT_GAP_SCAN_FAST_INTERVAL, \
217 BT_GAP_SCAN_FAST_INTERVAL)
218
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)219 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
220 struct net_buf_simple *ad)
221 {
222 char addr_str[BT_ADDR_LE_STR_LEN];
223
224 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
225 printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
226 }
227 #endif /* CONFIG_BT_OBSERVER */
228
init_peripheral(uint8_t iterations)229 int init_peripheral(uint8_t iterations)
230 {
231 size_t id_count;
232 int err;
233
234 err = bt_enable(NULL);
235 if (err) {
236 printk("Bluetooth init failed (err %d)\n", err);
237 return err;
238 }
239
240 bt_conn_cb_register(&conn_callbacks);
241
242 #if defined(CONFIG_BT_SMP)
243 bt_conn_auth_cb_register(&auth_callbacks);
244 #endif /* CONFIG_BT_SMP */
245
246 printk("Bluetooth initialized\n");
247
248 #if defined(CONFIG_BT_OBSERVER)
249 printk("Start continuous passive scanning...");
250 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE_ALLOW_DUPILCATES,
251 device_found);
252 if (err) {
253 printk("Scan start failed (%d).\n", err);
254 return err;
255 }
256 printk("success.\n");
257 #endif /* CONFIG_BT_OBSERVER */
258
259 k_work_init(&work_adv_start, adv_start);
260 k_work_submit(&work_adv_start);
261
262 /* wait for connection attempts on all identities */
263 do {
264 k_sleep(K_MSEC(10));
265
266 id_count = 0xFF;
267 bt_id_get(NULL, &id_count);
268 } while (id_count != CONFIG_BT_MAX_CONN);
269
270 /* rotate identities so reconnections are attempted in case of any
271 * disconnections
272 */
273 uint8_t prev_count = conn_count;
274 while (1) {
275 /* If maximum connections is reached, wait for disconnections
276 * initiated by peer central devices.
277 */
278 if (conn_count == CONFIG_BT_MAX_CONN) {
279 if (!iterations) {
280 break;
281 }
282 iterations--;
283 printk("Iterations remaining: %u\n", iterations);
284
285 printk("Wait for disconnections...\n");
286 is_disconnecting = true;
287 while (is_disconnecting) {
288 k_sleep(K_MSEC(10));
289 }
290 printk("All disconnected.\n");
291
292 continue;
293 }
294
295 /* As long as there is connection count changes, identity
296 * rotation in this loop is not needed.
297 */
298 if (prev_count != conn_count) {
299 prev_count = conn_count;
300
301 continue;
302 } else {
303 uint16_t wait = 6200U;
304
305 /* Maximum duration without connection count change,
306 * central waiting before disconnecting all its
307 * connections plus few seconds of margin.
308 */
309 while ((prev_count == conn_count) && wait) {
310 wait--;
311
312 k_sleep(K_MSEC(10));
313 }
314
315 if (wait) {
316 continue;
317 }
318 }
319
320 /* Stopping and restarting advertising to use new identity */
321 printk("Stop advertising...\n");
322 err = bt_le_adv_stop();
323 if (err) {
324 printk("Failed to stop advertising (%d)\n", err);
325
326 return err;
327 }
328
329 k_work_submit(&work_adv_start);
330 }
331
332 return 0;
333 }
334