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