1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "utils.h"
8 #include "gatt_utils.h"
9 #include <zephyr/sys/__assert.h>
10 #include <zephyr/bluetooth/hci.h>
11
12 DEFINE_FLAG(flag_is_connected);
13 DEFINE_FLAG(flag_test_end);
14
wait_connected(void)15 void wait_connected(void)
16 {
17 UNSET_FLAG(flag_is_connected);
18 WAIT_FOR_FLAG(flag_is_connected);
19 printk("connected\n");
20
21 }
22
wait_disconnected(void)23 void wait_disconnected(void)
24 {
25 SET_FLAG(flag_is_connected);
26 WAIT_FOR_FLAG_UNSET(flag_is_connected);
27 printk("disconnected\n");
28 }
29
disconnected(struct bt_conn * conn,uint8_t reason)30 static void disconnected(struct bt_conn *conn, uint8_t reason)
31 {
32 bt_conn_unref(conn);
33 UNSET_FLAG(flag_is_connected);
34 gatt_clear_flags();
35 }
36
connected(struct bt_conn * conn,uint8_t err)37 static void connected(struct bt_conn *conn, uint8_t err)
38 {
39 if (err != 0) {
40 return;
41 }
42
43 bt_conn_ref(conn);
44 SET_FLAG(flag_is_connected);
45 }
46
47 DEFINE_FLAG(flag_encrypted);
48
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)49 void security_changed(struct bt_conn *conn, bt_security_t level,
50 enum bt_security_err err)
51 {
52 __ASSERT(err == 0, "Error setting security (err %u)\n", err);
53
54 printk("Encrypted\n");
55 SET_FLAG(flag_encrypted);
56 }
57
58 BT_CONN_CB_DEFINE(conn_callbacks) = {
59 .connected = connected,
60 .disconnected = disconnected,
61 .security_changed = security_changed,
62 };
63
scan_connect_to_first_result_device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)64 static void scan_connect_to_first_result_device_found(const bt_addr_le_t *addr, int8_t rssi,
65 uint8_t type, struct net_buf_simple *ad)
66 {
67 struct bt_conn *conn;
68 char addr_str[BT_ADDR_LE_STR_LEN];
69 int err;
70
71 /* We're only interested in connectable events */
72 if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) {
73 FAIL("Unexpected advertisement type.");
74 }
75
76 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
77 printk("Got scan result, connecting.. dst %s, RSSI %d\n",
78 addr_str, rssi);
79
80 err = bt_le_scan_stop();
81 __ASSERT(!err, "Err bt_le_scan_stop %d", err);
82
83 err = bt_conn_le_create(addr,
84 BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
85 &conn);
86 __ASSERT(!err, "Err bt_conn_le_create %d", err);
87 }
88
scan_connect_to_first_result(void)89 void scan_connect_to_first_result(void)
90 {
91 int err;
92
93 printk("start scanner\n");
94 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE,
95 scan_connect_to_first_result_device_found);
96 __ASSERT(!err, "Err bt_le_scan_start %d", err);
97 }
98
advertise_connectable(void)99 void advertise_connectable(void)
100 {
101 printk("start advertiser\n");
102 int err;
103 struct bt_le_adv_param param = {};
104
105 param.interval_min = 0x0020;
106 param.interval_max = 0x4000;
107 param.options |= BT_LE_ADV_OPT_ONE_TIME;
108 param.options |= BT_LE_ADV_OPT_CONNECTABLE;
109
110 err = bt_le_adv_start(¶m, NULL, 0, NULL, 0);
111 __ASSERT(err == 0, "Advertising failed to start (err %d)\n", err);
112 }
113
disconnect(struct bt_conn * conn)114 void disconnect(struct bt_conn *conn)
115 {
116 int err;
117
118 err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
119 __ASSERT(!err, "Failed to initate disconnection (err %d)", err);
120
121 printk("Waiting for disconnection...\n");
122 WAIT_FOR_FLAG_UNSET(flag_is_connected);
123 }
124
get_active_conn_cb(struct bt_conn * src,void * dst)125 static void get_active_conn_cb(struct bt_conn *src, void *dst)
126 {
127 *(struct bt_conn **)dst = src;
128 }
129
get_conn(void)130 struct bt_conn *get_conn(void)
131 {
132 struct bt_conn *ret;
133
134 bt_conn_foreach(BT_CONN_TYPE_LE, get_active_conn_cb, &ret);
135
136 return ret;
137 }
138
139 DEFINE_FLAG(flag_pairing_complete);
140
pairing_failed(struct bt_conn * conn,enum bt_security_err reason)141 static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
142 {
143 FAIL("Pairing failed (unexpected): reason %u", reason);
144 }
145
pairing_complete(struct bt_conn * conn,bool bonded)146 static void pairing_complete(struct bt_conn *conn, bool bonded)
147 {
148 __ASSERT(bonded, "Bonding failed\n");
149
150 printk("Paired\n");
151 SET_FLAG(flag_pairing_complete);
152 }
153
154 static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = {
155 .pairing_failed = pairing_failed,
156 .pairing_complete = pairing_complete,
157 };
158
set_security(struct bt_conn * conn,bt_security_t sec)159 void set_security(struct bt_conn *conn, bt_security_t sec)
160 {
161 int err;
162
163 UNSET_FLAG(flag_encrypted);
164
165 err = bt_conn_set_security(conn, sec);
166 __ASSERT(!err, "Err bt_conn_set_security %d", err);
167
168 WAIT_FOR_FLAG(flag_encrypted);
169 }
170
wait_secured(void)171 void wait_secured(void)
172 {
173 UNSET_FLAG(flag_encrypted);
174 WAIT_FOR_FLAG(flag_encrypted);
175 }
176
bond(struct bt_conn * conn)177 void bond(struct bt_conn *conn)
178 {
179 UNSET_FLAG(flag_pairing_complete);
180
181 int err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb);
182
183 __ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n");
184
185 set_security(conn, BT_SECURITY_L2);
186
187 WAIT_FOR_FLAG(flag_pairing_complete);
188 }
189
wait_bonded(void)190 void wait_bonded(void)
191 {
192 UNSET_FLAG(flag_encrypted);
193 UNSET_FLAG(flag_pairing_complete);
194
195 int err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb);
196
197 __ASSERT(!err, "bt_conn_auth_info_cb_register failed.\n");
198
199 WAIT_FOR_FLAG(flag_encrypted);
200 WAIT_FOR_FLAG(flag_pairing_complete);
201 }
202
connect_as_central(void)203 struct bt_conn *connect_as_central(void)
204 {
205 struct bt_conn *conn;
206
207 scan_connect_to_first_result();
208 wait_connected();
209 conn = get_conn();
210
211 return conn;
212 }
213
connect_as_peripheral(void)214 struct bt_conn *connect_as_peripheral(void)
215 {
216 struct bt_conn *conn;
217
218 advertise_connectable();
219 wait_connected();
220 conn = get_conn();
221
222 return conn;
223 }
224