1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stddef.h>
8 
9 #include <zephyr/kernel.h>
10 
11 #include <zephyr/sys/printk.h>
12 #include <zephyr/sys/util.h>
13 
14 #include <zephyr/bluetooth/bluetooth.h>
15 #include <zephyr/bluetooth/hci.h>
16 
17 #include "bs_types.h"
18 #include "bs_tracing.h"
19 #include "time_machine.h"
20 #include "bstests.h"
21 
22 #define FAIL(...)					\
23 	do {						\
24 		bst_result = Failed;			\
25 		bs_trace_error_time_line(__VA_ARGS__);	\
26 	} while (0)
27 
28 #define PASS(...)					\
29 	do {						\
30 		bst_result = Passed;			\
31 		bs_trace_info_time(1, __VA_ARGS__);	\
32 	} while (0)
33 
34 #define NAME_LEN 30
35 #define BT_AD_DATA_NAME_SIZE     (sizeof(CONFIG_BT_DEVICE_NAME) - 1U + 2U)
36 #define BT_AD_DATA_MFG_DATA_SIZE (254U + 2U)
37 /*
38  * for testing chaining the manufacturing data is duplicated, hence DATA_LEN needs to
39  * add twice the size for this element
40  */
41 #define DATA_LEN                 MIN((BT_AD_DATA_NAME_SIZE + \
42 				      BT_AD_DATA_MFG_DATA_SIZE + BT_AD_DATA_MFG_DATA_SIZE), \
43 				     CONFIG_BT_CTLR_ADV_DATA_LEN_MAX)
44 
45 static K_SEM_DEFINE(sem_recv, 0, 1);
46 
47 extern enum bst_result_t bst_result;
48 
test_adv_main(void)49 static void test_adv_main(void)
50 {
51 	extern int broadcaster_multiple(void);
52 	int err;
53 
54 	err = bt_enable(NULL);
55 	if (err) {
56 		FAIL("Bluetooth init failed\n");
57 
58 		bs_trace_silent_exit(err);
59 		return;
60 	}
61 
62 	err = broadcaster_multiple();
63 	if (err) {
64 		FAIL("Adv tests failed\n");
65 		bs_trace_silent_exit(err);
66 		return;
67 	}
68 
69 	/* Successfully started advertising multiple sets */
70 	PASS("Adv tests passed\n");
71 
72 	/* Let the scanner receive the reports */
73 	k_sleep(K_SECONDS(10));
74 }
75 
data_cb(struct bt_data * data,void * user_data)76 static bool data_cb(struct bt_data *data, void *user_data)
77 {
78 	char *name = user_data;
79 	uint8_t len;
80 
81 	switch (data->type) {
82 	case BT_DATA_NAME_SHORTENED:
83 	case BT_DATA_NAME_COMPLETE:
84 		len = MIN(data->data_len, NAME_LEN - 1);
85 		(void)memcpy(name, data->data, len);
86 		name[len] = '\0';
87 		return false;
88 	default:
89 		return true;
90 	}
91 }
92 
scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)93 static void scan_recv(const struct bt_le_scan_recv_info *info,
94 		      struct net_buf_simple *buf)
95 {
96 	static uint8_t sid[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
97 	static uint8_t sid_count;
98 	char name[NAME_LEN];
99 	uint8_t data_status;
100 	uint16_t data_len;
101 
102 	data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(info->adv_props);
103 	if (data_status) {
104 		return;
105 	}
106 
107 	data_len = buf->len;
108 	if (data_len != DATA_LEN) {
109 		printk("Received datalength: %d\n", data_len);
110 		return;
111 	}
112 
113 	(void)memset(name, 0, sizeof(name));
114 	bt_data_parse(buf, data_cb, name);
115 
116 	if (strcmp(name, CONFIG_BT_DEVICE_NAME)) {
117 		printk("Wrong name %s\n", name);
118 		return;
119 	}
120 
121 	for (uint8_t i = 0; i < sid_count; i++) {
122 		if (sid[i] == info->sid) {
123 			printk("Received SID %d\n", info->sid);
124 			return;
125 		}
126 	}
127 
128 	sid[sid_count++] = info->sid;
129 
130 	if (sid_count < CONFIG_BT_EXT_ADV_MAX_ADV_SET) {
131 		printk("Received advertising sets: %d\n", sid_count);
132 		return;
133 	}
134 
135 	k_sem_give(&sem_recv);
136 }
137 
138 static struct bt_le_scan_cb scan_callbacks = {
139 	.recv = scan_recv,
140 };
141 
test_scan_main(void)142 static void test_scan_main(void)
143 {
144 	extern int observer_start(void);
145 	int err;
146 
147 	err = bt_enable(NULL);
148 	if (err) {
149 		FAIL("Bluetooth init failed\n");
150 
151 		bs_trace_silent_exit(err);
152 		return;
153 	}
154 
155 	bt_le_scan_cb_register(&scan_callbacks);
156 
157 	err = observer_start();
158 	if (err) {
159 		FAIL("Observer start failed\n");
160 
161 		bs_trace_silent_exit(err);
162 		return;
163 	}
164 
165 	/* Let the recv callback verify the reports */
166 	k_sleep(K_SECONDS(10));
167 
168 	err = k_sem_take(&sem_recv, K_NO_WAIT);
169 	if (err) {
170 		FAIL("Scan receive failed\n");
171 
172 		bs_trace_silent_exit(err);
173 		return;
174 	}
175 
176 	PASS("Scan tests passed\n");
177 
178 	bs_trace_silent_exit(0);
179 }
180 
test_adv_chain_init(void)181 static void test_adv_chain_init(void)
182 {
183 	bst_ticker_set_next_tick_absolute(60e6);
184 	bst_result = In_progress;
185 }
186 
test_adv_chain_tick(bs_time_t HW_device_time)187 static void test_adv_chain_tick(bs_time_t HW_device_time)
188 {
189 	bst_result = Failed;
190 	bs_trace_error_line("Test GATT Write finished.\n");
191 }
192 
193 static const struct bst_test_instance test_def[] = {
194 	{
195 		.test_id = "adv",
196 		.test_descr = "Central GATT Write",
197 		.test_pre_init_f = test_adv_chain_init,
198 		.test_tick_f = test_adv_chain_tick,
199 		.test_main_f = test_adv_main
200 	},
201 	{
202 		.test_id = "scan",
203 		.test_descr = "Peripheral GATT Write",
204 		.test_pre_init_f = test_adv_chain_init,
205 		.test_tick_f = test_adv_chain_tick,
206 		.test_main_f = test_scan_main
207 	},
208 	BSTEST_END_MARKER
209 };
210 
test_adv_chain_install(struct bst_test_list * tests)211 struct bst_test_list *test_adv_chain_install(struct bst_test_list *tests)
212 {
213 	return bst_add_tests(tests, test_def);
214 }
215 
216 bst_test_install_t test_installers[] = {
217 	test_adv_chain_install,
218 	NULL
219 };
220 
main(void)221 int main(void)
222 {
223 	bst_main();
224 	return 0;
225 }
226