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