1 /* Copyright (c) 2023 Nordic Semiconductor ASA
2 * SPDX-License-Identifier: Apache-2.0
3 */
4
5 #include <string.h>
6
7 #include <zephyr/kernel.h>
8
9 #include <zephyr/bluetooth/att.h>
10 #include <zephyr/bluetooth/addr.h>
11 #include <zephyr/bluetooth/conn.h>
12 #include <zephyr/bluetooth/gatt.h>
13 #include <zephyr/bluetooth/uuid.h>
14 #include <zephyr/bluetooth/hci_types.h>
15 #include <zephyr/bluetooth/bluetooth.h>
16
17 #include <zephyr/logging/log.h>
18
19 #include <zephyr/settings/settings.h>
20
21 #include "common.h"
22 #include "settings.h"
23
24 #include "argparse.h"
25 #include "bs_pc_backchannel.h"
26
27 #define SERVER_CHAN 0
28
29 CREATE_FLAG(connected_flag);
30 CREATE_FLAG(disconnected_flag);
31 CREATE_FLAG(security_updated_flag);
32 CREATE_FLAG(notification_received_flag);
33
34 #define BT_UUID_DUMMY_SERVICE BT_UUID_DECLARE_128(DUMMY_SERVICE_TYPE)
35 #define BT_UUID_DUMMY_SERVICE_NOTIFY BT_UUID_DECLARE_128(DUMMY_SERVICE_NOTIFY_TYPE)
36
37 static struct bt_conn *default_conn;
38
39 static struct bt_conn_cb central_cb;
40
41 CREATE_FLAG(gatt_subscribed_flag);
42
notify_cb(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)43 static uint8_t notify_cb(struct bt_conn *conn, struct bt_gatt_subscribe_params *params,
44 const void *data, uint16_t length)
45 {
46 uint8_t value;
47
48 if (conn == NULL || data == NULL) {
49 /* Peer unpaired or subscription was removed */
50 UNSET_FLAG(gatt_subscribed_flag);
51
52 return BT_GATT_ITER_STOP;
53 }
54
55 __ASSERT_NO_MSG(length == sizeof(value));
56
57 value = *(uint8_t *)data;
58
59 LOG_DBG("#%d notification received", value);
60
61 SET_FLAG(notification_received_flag);
62
63 return BT_GATT_ITER_CONTINUE;
64 }
65
subscribe_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_subscribe_params * params)66 static void subscribe_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_subscribe_params *params)
67 {
68 if (err) {
69 return;
70 }
71
72 SET_FLAG(gatt_subscribed_flag);
73 }
74
75 static struct bt_gatt_subscribe_params subscribe_params;
76
ccc_subscribe(void)77 static void ccc_subscribe(void)
78 {
79 int err;
80
81 UNSET_FLAG(gatt_subscribed_flag);
82
83 subscribe_params.notify = notify_cb;
84 subscribe_params.subscribe = subscribe_cb;
85 subscribe_params.ccc_handle = CCC_HANDLE;
86 subscribe_params.value_handle = VAL_HANDLE;
87 subscribe_params.value = BT_GATT_CCC_NOTIFY;
88
89 err = bt_gatt_subscribe(default_conn, &subscribe_params);
90 if (err) {
91 FAIL("Failed to subscribe (att err %d)", err);
92 }
93
94 WAIT_FOR_FLAG(gatt_subscribed_flag);
95 }
96
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)97 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
98 struct net_buf_simple *ad)
99 {
100 int err;
101 char addr_str[BT_ADDR_LE_STR_LEN];
102
103 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
104
105 LOG_DBG("Device found: %s (RSSI %d)", addr_str, rssi);
106
107 err = bt_le_scan_stop();
108 if (err) {
109 FAIL("Failed to stop scanner (err %d)\n", err);
110 }
111
112 err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
113 &default_conn);
114 if (err) {
115 FAIL("Could not connect to peer: %s (err %d)\n", addr_str, err);
116 }
117 }
118
connected(struct bt_conn * conn,uint8_t err)119 static void connected(struct bt_conn *conn, uint8_t err)
120 {
121 const bt_addr_le_t *addr;
122 char addr_str[BT_ADDR_LE_STR_LEN];
123
124 addr = bt_conn_get_dst(conn);
125 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
126
127 if (err) {
128 FAIL("Failed to connect to %s (err %d)\n", addr_str, err);
129 }
130
131 LOG_DBG("Connected: %s", addr_str);
132
133 if (conn == default_conn) {
134 SET_FLAG(connected_flag);
135 }
136 }
137
disconnected(struct bt_conn * conn,uint8_t reason)138 static void disconnected(struct bt_conn *conn, uint8_t reason)
139 {
140 char addr_str[BT_ADDR_LE_STR_LEN];
141
142 bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
143
144 LOG_DBG("Disconnected: %s (reason 0x%02x)", addr_str, reason);
145
146 SET_FLAG(disconnected_flag);
147
148 if (default_conn != conn) {
149 return;
150 }
151
152 bt_conn_unref(default_conn);
153 default_conn = NULL;
154 }
155
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)156 static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
157 {
158 char addr_str[BT_ADDR_LE_STR_LEN];
159
160 bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
161
162 if (!err) {
163 LOG_DBG("Security changed: %s level %u", addr_str, level);
164 SET_FLAG(security_updated_flag);
165 } else {
166 LOG_DBG("Security failed: %s level %u err %d", addr_str, level, err);
167 }
168 }
169
start_scan(void)170 static void start_scan(void)
171 {
172 int err;
173
174 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
175 if (err) {
176 FAIL("Scanning failed to start (err %d)\n", err);
177 }
178
179 LOG_DBG("Scanning successfully started");
180 }
181
disconnect(void)182 static void disconnect(void)
183 {
184 int err;
185
186 err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
187 if (err) {
188 FAIL("Disconnection failed (err %d)\n", err);
189 }
190
191 WAIT_FOR_FLAG(disconnected_flag);
192 UNSET_FLAG(disconnected_flag);
193 }
194
195 /* Test steps */
196
connect_pair_subscribe(void)197 static void connect_pair_subscribe(void)
198 {
199 int err;
200
201 start_scan();
202
203 WAIT_FOR_FLAG(connected_flag);
204 UNSET_FLAG(connected_flag);
205
206 err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
207 if (err != 0) {
208 FAIL("Failed to set security (err %d)\n", err);
209 }
210
211 WAIT_FOR_FLAG(security_updated_flag);
212 UNSET_FLAG(security_updated_flag);
213
214 /* subscribe while being paired */
215 ccc_subscribe();
216
217 /* confirm to server that we subscribed */
218 backchannel_sync_send(SERVER_CHAN, SERVER_ID);
219 /* wait for server to check that the subscribtion is well registered */
220 backchannel_sync_wait(SERVER_CHAN, SERVER_ID);
221
222 WAIT_FOR_FLAG(notification_received_flag);
223 UNSET_FLAG(notification_received_flag);
224 }
225
connect_restore_sec(void)226 static void connect_restore_sec(void)
227 {
228 int err;
229
230 start_scan();
231
232 WAIT_FOR_FLAG(connected_flag);
233 UNSET_FLAG(connected_flag);
234
235 err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
236 if (err != 0) {
237 FAIL("Failed to set security (err %d)\n", err);
238 }
239
240 WAIT_FOR_FLAG(security_updated_flag);
241 UNSET_FLAG(security_updated_flag);
242
243 /* check local subscription state */
244 if (GET_FLAG(gatt_subscribed_flag) == false) {
245 FAIL("Not subscribed\n");
246 }
247
248 /* notify the end of security update to server */
249 backchannel_sync_send(SERVER_CHAN, SERVER_ID);
250 /* wait for server to check that the subscribtion has been restored */
251 backchannel_sync_wait(SERVER_CHAN, SERVER_ID);
252
253 WAIT_FOR_FLAG(notification_received_flag);
254 UNSET_FLAG(notification_received_flag);
255 }
256
257 /* Util functions */
258
central_backchannel_init(void)259 void central_backchannel_init(void)
260 {
261 uint device_number = get_device_nbr();
262 uint channel_numbers[1] = {
263 0,
264 };
265 uint device_numbers[1];
266 uint num_ch = 1;
267 uint *ch;
268
269 device_numbers[0] = SERVER_ID;
270
271 LOG_DBG("Opening back channels for device %d", device_number);
272 ch = bs_open_back_channel(device_number, device_numbers, channel_numbers, num_ch);
273 if (!ch) {
274 FAIL("Unable to open backchannel\n");
275 }
276 LOG_DBG("Back channels for device %d opened", device_number);
277 }
278
set_public_addr(void)279 static void set_public_addr(void)
280 {
281 bt_addr_le_t addr = {BT_ADDR_LE_RANDOM, {{0x0A, 0x89, 0x67, 0x45, 0x23, 0xC1}}};
282
283 bt_id_create(&addr, NULL);
284 }
285
286 /* Main functions */
287
run_central(int times)288 void run_central(int times)
289 {
290 int err;
291
292 central_cb.connected = connected;
293 central_cb.disconnected = disconnected;
294 central_cb.security_changed = security_changed;
295
296 central_backchannel_init();
297 set_public_addr();
298
299 err = bt_enable(NULL);
300 if (err) {
301 FAIL("Bluetooth init failed (err %d)\n", err);
302 }
303
304 LOG_DBG("Bluetooth initialized");
305
306 bt_conn_cb_register(¢ral_cb);
307
308 err = settings_load();
309 if (err) {
310 FAIL("Settings load failed (err %d)\n", err);
311 }
312
313 err = bt_unpair(BT_ID_DEFAULT, BT_ADDR_LE_ANY);
314 if (err) {
315 FAIL("Unpairing failed (err %d)\n", err);
316 }
317
318 connect_pair_subscribe();
319 disconnect();
320
321 for (int i = 0; i < times; i++) {
322 connect_restore_sec();
323 disconnect();
324 }
325
326 PASS("Central test passed\n");
327 }
328