1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <zephyr/kernel.h>
7
8 #include "bs_types.h"
9 #include "bs_tracing.h"
10 #include "time_machine.h"
11 #include "bstests.h"
12
13 #include <zephyr/types.h>
14 #include <zephyr/sys/printk.h>
15
16 #include <zephyr/bluetooth/bluetooth.h>
17
18 #include "common.h"
19
20 extern enum bst_result_t bst_result;
21
22 static struct bt_conn *g_conn;
23
24 CREATE_FLAG(flag_connected);
25 CREATE_FLAG(flag_bonded);
26
connected(struct bt_conn * conn,uint8_t err)27 static void connected(struct bt_conn *conn, uint8_t err)
28 {
29 char addr[BT_ADDR_LE_STR_LEN];
30
31 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
32
33 if (err != BT_HCI_ERR_SUCCESS) {
34 FAIL("Failed to connect to %s: %u\n", addr, err);
35 return;
36 }
37
38 printk("Connected to %s\n", addr);
39 g_conn = bt_conn_ref(conn);
40 SET_FLAG(flag_connected);
41 }
42
disconnected(struct bt_conn * conn,uint8_t reason)43 static void disconnected(struct bt_conn *conn, uint8_t reason)
44 {
45 char addr[BT_ADDR_LE_STR_LEN];
46
47 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
48
49 printk("Disconnected: %s (reason %u)\n", addr, reason);
50
51 bt_conn_unref(g_conn);
52 g_conn = NULL;
53 }
54
55 static struct bt_conn_cb conn_cbs = {
56 .connected = connected,
57 .disconnected = disconnected,
58 };
59
pairing_complete_cb(struct bt_conn * conn,bool bonded)60 static void pairing_complete_cb(struct bt_conn *conn, bool bonded)
61 {
62 if (conn == g_conn && bonded) {
63 SET_FLAG(flag_bonded);
64 }
65 }
66
67 static struct bt_conn_auth_info_cb auto_info_cbs = {
68 .pairing_complete = pairing_complete_cb,
69 };
70
common_init(void)71 static void common_init(void)
72 {
73 int err;
74
75 err = bt_enable(NULL);
76
77 if (err) {
78 FAIL("Bluetooth init failed: %d\n", err);
79 return;
80 }
81 printk("Bluetooth initialized\n");
82
83 bt_conn_cb_register(&conn_cbs);
84 bt_conn_auth_info_cb_register(&auto_info_cbs);
85 }
86
create_per_adv_set(struct bt_le_ext_adv ** adv)87 static void create_per_adv_set(struct bt_le_ext_adv **adv)
88 {
89 int err;
90
91 printk("Creating extended advertising set...");
92 err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv);
93 if (err) {
94 printk("Failed to create advertising set: %d\n", err);
95 return;
96 }
97 printk("done.\n");
98
99 printk("Setting periodic advertising parameters...");
100 err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT);
101 if (err) {
102 printk("Failed to set periodic advertising parameters: %d\n",
103 err);
104 return;
105 }
106 printk("done.\n");
107 }
108
109 #if defined(CONFIG_BT_CTLR_PHY_CODED)
create_per_adv_set_coded(struct bt_le_ext_adv ** adv)110 static void create_per_adv_set_coded(struct bt_le_ext_adv **adv)
111 {
112 int err;
113
114 printk("Creating coded PHY extended advertising set...");
115 err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CODED_NCONN, NULL, adv);
116 if (err) {
117 printk("Failed to create advertising set: %d\n", err);
118 return;
119 }
120 printk("done.\n");
121
122 printk("Setting periodic advertising parameters...");
123 err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT);
124 if (err) {
125 printk("Failed to set periodic advertising parameters: %d\n",
126 err);
127 return;
128 }
129 printk("done.\n");
130 }
131 #endif /* CONFIG_BT_CTLR_PHY_CODED */
132
create_conn_adv_set(struct bt_le_ext_adv ** adv)133 static void create_conn_adv_set(struct bt_le_ext_adv **adv)
134 {
135 int err;
136
137 printk("Creating connectable extended advertising set...");
138 err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, adv);
139 if (err) {
140 printk("Failed to create advertising set: %d\n", err);
141 return;
142 }
143 printk("done.\n");
144 }
145
start_ext_adv_set(struct bt_le_ext_adv * adv)146 static void start_ext_adv_set(struct bt_le_ext_adv *adv)
147 {
148 int err;
149
150 printk("Starting Extended Advertising...");
151 err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
152 if (err) {
153 printk("Failed to start extended advertising: %d\n", err);
154 return;
155 }
156 printk("done.\n");
157 }
158
start_per_adv_set(struct bt_le_ext_adv * adv)159 static void start_per_adv_set(struct bt_le_ext_adv *adv)
160 {
161 int err;
162
163 printk("Starting periodic advertising...");
164 err = bt_le_per_adv_start(adv);
165 if (err) {
166 printk("Failed to start periodic advertising: %d\n", err);
167 return;
168 }
169 printk("done.\n");
170 }
171
172 #if defined(CONFIG_BT_PER_ADV)
set_per_adv_data(struct bt_le_ext_adv * adv)173 static void set_per_adv_data(struct bt_le_ext_adv *adv)
174 {
175 int err;
176 const struct bt_data ad[] = {
177 BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, ARRAY_SIZE(mfg_data)),
178 BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, ARRAY_SIZE(mfg_data))};
179
180 printk("Setting Periodic Advertising Data...");
181 err = bt_le_per_adv_set_data(adv, ad, ARRAY_SIZE(ad));
182 if (err) {
183 printk("Failed to set periodic advertising data: %d\n",
184 err);
185 return;
186 }
187 printk("done.\n");
188 }
189 #endif
190
stop_ext_adv_set(struct bt_le_ext_adv * adv)191 static void stop_ext_adv_set(struct bt_le_ext_adv *adv)
192 {
193 int err;
194
195 printk("Stopping Extended Advertising...");
196 err = bt_le_ext_adv_stop(adv);
197 if (err) {
198 printk("Failed to stop extended advertising: %d\n",
199 err);
200 return;
201 }
202 printk("done.\n");
203 }
204
stop_per_adv_set(struct bt_le_ext_adv * adv)205 static void stop_per_adv_set(struct bt_le_ext_adv *adv)
206 {
207 int err;
208
209 printk("Stopping Periodic Advertising...");
210 err = bt_le_per_adv_stop(adv);
211 if (err) {
212 printk("Failed to stop periodic advertising: %d\n",
213 err);
214 return;
215 }
216 printk("done.\n");
217 }
218
delete_adv_set(struct bt_le_ext_adv * adv)219 static void delete_adv_set(struct bt_le_ext_adv *adv)
220 {
221 int err;
222
223 printk("Delete extended advertising set...");
224 err = bt_le_ext_adv_delete(adv);
225 if (err) {
226 printk("Failed Delete extended advertising set: %d\n", err);
227 return;
228 }
229 printk("done.\n");
230 }
231
main_per_adv_advertiser(void)232 static void main_per_adv_advertiser(void)
233 {
234 struct bt_le_ext_adv *per_adv;
235
236 common_init();
237
238 create_per_adv_set(&per_adv);
239
240 start_per_adv_set(per_adv);
241 start_ext_adv_set(per_adv);
242
243 /* Advertise for a bit */
244 k_sleep(K_SECONDS(10));
245
246 stop_per_adv_set(per_adv);
247 stop_ext_adv_set(per_adv);
248
249 delete_adv_set(per_adv);
250 per_adv = NULL;
251
252 PASS("Periodic advertiser passed\n");
253 }
254
255 #if defined(CONFIG_BT_CTLR_PHY_CODED)
main_per_adv_advertiser_coded(void)256 static void main_per_adv_advertiser_coded(void)
257 {
258 struct bt_le_ext_adv *per_adv;
259
260 common_init();
261
262 create_per_adv_set_coded(&per_adv);
263
264 start_per_adv_set(per_adv);
265 start_ext_adv_set(per_adv);
266
267 /* Advertise for a bit */
268 k_sleep(K_SECONDS(10));
269
270 stop_per_adv_set(per_adv);
271 stop_ext_adv_set(per_adv);
272
273 delete_adv_set(per_adv);
274 per_adv = NULL;
275
276 PASS("Periodic advertiser coded PHY passed\n");
277 }
278 #endif /* CONFIG_BT_CTLR_PHY_CODED */
279
main_per_adv_conn_advertiser(void)280 static void main_per_adv_conn_advertiser(void)
281 {
282 struct bt_le_ext_adv *conn_adv;
283 struct bt_le_ext_adv *per_adv;
284
285 common_init();
286
287 create_per_adv_set(&per_adv);
288 create_conn_adv_set(&conn_adv);
289
290 start_per_adv_set(per_adv);
291 start_ext_adv_set(per_adv);
292 start_ext_adv_set(conn_adv);
293
294 WAIT_FOR_FLAG(flag_connected);
295
296 /* Advertise for a bit */
297 k_sleep(K_SECONDS(10));
298
299 stop_per_adv_set(per_adv);
300 stop_ext_adv_set(per_adv);
301 stop_ext_adv_set(conn_adv);
302
303 delete_adv_set(per_adv);
304 per_adv = NULL;
305 delete_adv_set(conn_adv);
306 conn_adv = NULL;
307
308 PASS("Periodic advertiser passed\n");
309 }
310
main_per_adv_conn_privacy_advertiser(void)311 static void main_per_adv_conn_privacy_advertiser(void)
312 {
313 struct bt_le_ext_adv *conn_adv;
314 struct bt_le_ext_adv *per_adv;
315
316 common_init();
317
318 create_conn_adv_set(&conn_adv);
319
320 start_ext_adv_set(conn_adv);
321
322 WAIT_FOR_FLAG(flag_connected);
323 WAIT_FOR_FLAG(flag_bonded);
324
325 /* Start periodic advertising after bonding so that the scanner gets
326 * the resolved address
327 */
328 create_per_adv_set(&per_adv);
329 start_per_adv_set(per_adv);
330 start_ext_adv_set(per_adv);
331
332 /* Advertise for a bit */
333 k_sleep(K_SECONDS(10));
334
335 stop_per_adv_set(per_adv);
336 stop_ext_adv_set(per_adv);
337 stop_ext_adv_set(conn_adv);
338
339 delete_adv_set(per_adv);
340 per_adv = NULL;
341 delete_adv_set(conn_adv);
342 conn_adv = NULL;
343
344 PASS("Periodic advertiser passed\n");
345 }
346
main_per_adv_long_data_advertiser(void)347 static void main_per_adv_long_data_advertiser(void)
348 {
349 #if defined(CONFIG_BT_PER_ADV)
350 struct bt_le_ext_adv *per_adv;
351
352 common_init();
353
354 create_per_adv_set(&per_adv);
355
356 set_per_adv_data(per_adv);
357 start_per_adv_set(per_adv);
358 start_ext_adv_set(per_adv);
359
360 /* Advertise for a bit */
361 k_sleep(K_SECONDS(10));
362
363 stop_per_adv_set(per_adv);
364 stop_ext_adv_set(per_adv);
365
366 delete_adv_set(per_adv);
367 per_adv = NULL;
368 #endif
369 PASS("Periodic long data advertiser passed\n");
370 }
371
372 static const struct bst_test_instance per_adv_advertiser[] = {
373 {
374 .test_id = "per_adv_advertiser",
375 .test_descr = "Basic periodic advertising test. "
376 "Will just start periodic advertising.",
377 .test_pre_init_f = test_init,
378 .test_tick_f = test_tick,
379 .test_main_f = main_per_adv_advertiser
380 },
381 #if defined(CONFIG_BT_CTLR_PHY_CODED)
382 {
383 .test_id = "per_adv_advertiser_coded_phy",
384 .test_descr = "Basic periodic advertising test on Coded PHY. "
385 "Advertiser and periodic advertiser uses Coded PHY",
386 .test_pre_init_f = test_init,
387 .test_tick_f = test_tick,
388 .test_main_f = main_per_adv_advertiser_coded
389 },
390 #endif /* CONFIG_BT_CTLR_PHY_CODED */
391 {
392 .test_id = "per_adv_conn_advertiser",
393 .test_descr = "Periodic advertising test with concurrent ACL "
394 "and PA sync.",
395 .test_pre_init_f = test_init,
396 .test_tick_f = test_tick,
397 .test_main_f = main_per_adv_conn_advertiser
398 },
399 {
400 .test_id = "per_adv_conn_privacy_advertiser",
401 .test_descr = "Periodic advertising test with concurrent ACL "
402 "with bonding and PA sync.",
403 .test_pre_init_f = test_init,
404 .test_tick_f = test_tick,
405 .test_main_f = main_per_adv_conn_privacy_advertiser
406 },
407 {
408 .test_id = "per_adv_long_data_advertiser",
409 .test_descr = "Periodic advertising test with a longer data length. "
410 "To test the reassembly of large data packets",
411 .test_pre_init_f = test_init,
412 .test_tick_f = test_tick,
413 .test_main_f = main_per_adv_long_data_advertiser
414 },
415 BSTEST_END_MARKER
416 };
417
test_per_adv_advertiser(struct bst_test_list * tests)418 struct bst_test_list *test_per_adv_advertiser(struct bst_test_list *tests)
419 {
420 return bst_add_tests(tests, per_adv_advertiser);
421 }
422