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 "babblekit/testcase.h"
18
19 #define NAME_LEN 30
20 #define BT_AD_DATA_NAME_SIZE (sizeof(CONFIG_BT_DEVICE_NAME) - 1U + 2U)
21 #define BT_AD_DATA_MFG_DATA_SIZE (254U + 2U)
22 /*
23 * for testing chaining the manufacturing data is duplicated, hence DATA_LEN needs to
24 * add twice the size for this element
25 */
26 #define DATA_LEN MIN((BT_AD_DATA_NAME_SIZE + \
27 BT_AD_DATA_MFG_DATA_SIZE + BT_AD_DATA_MFG_DATA_SIZE), \
28 CONFIG_BT_CTLR_ADV_DATA_LEN_MAX)
29
30 static K_SEM_DEFINE(sem_recv, 0, 1);
31
test_adv_main(void)32 static void test_adv_main(void)
33 {
34 extern int broadcaster_multiple(void);
35 int err;
36
37 err = bt_enable(NULL);
38 if (err) {
39 TEST_FAIL("Bluetooth init failed");
40
41 bs_trace_silent_exit(err);
42 return;
43 }
44
45 err = broadcaster_multiple();
46 if (err) {
47 TEST_FAIL("Adv tests failed");
48 bs_trace_silent_exit(err);
49 return;
50 }
51
52 /* Successfully started advertising multiple sets */
53 TEST_PASS("Adv tests passed");
54
55 /* Let the scanner receive the reports */
56 k_sleep(K_SECONDS(10));
57 }
58
data_cb(struct bt_data * data,void * user_data)59 static bool data_cb(struct bt_data *data, void *user_data)
60 {
61 char *name = user_data;
62 uint8_t len;
63
64 switch (data->type) {
65 case BT_DATA_NAME_SHORTENED:
66 case BT_DATA_NAME_COMPLETE:
67 len = MIN(data->data_len, NAME_LEN - 1);
68 (void)memcpy(name, data->data, len);
69 name[len] = '\0';
70 return false;
71 default:
72 return true;
73 }
74 }
75
scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)76 static void scan_recv(const struct bt_le_scan_recv_info *info,
77 struct net_buf_simple *buf)
78 {
79 static uint8_t sid[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
80 static uint8_t sid_count;
81 char name[NAME_LEN];
82 uint8_t data_status;
83 uint16_t data_len;
84
85 data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(info->adv_props);
86 if (data_status) {
87 return;
88 }
89
90 data_len = buf->len;
91 if (data_len != DATA_LEN) {
92 printk("Received datalength: %d\n", data_len);
93 return;
94 }
95
96 (void)memset(name, 0, sizeof(name));
97 bt_data_parse(buf, data_cb, name);
98
99 if (strcmp(name, CONFIG_BT_DEVICE_NAME)) {
100 printk("Wrong name %s\n", name);
101 return;
102 }
103
104 for (uint8_t i = 0; i < sid_count; i++) {
105 if (sid[i] == info->sid) {
106 printk("Received SID %d\n", info->sid);
107 return;
108 }
109 }
110
111 sid[sid_count++] = info->sid;
112
113 if (sid_count < CONFIG_BT_EXT_ADV_MAX_ADV_SET) {
114 printk("Received advertising sets: %d\n", sid_count);
115 return;
116 }
117
118 k_sem_give(&sem_recv);
119 }
120
121 static struct bt_le_scan_cb scan_callbacks = {
122 .recv = scan_recv,
123 };
124
test_scan_main(void)125 static void test_scan_main(void)
126 {
127 extern int observer_start(void);
128 int err;
129
130 err = bt_enable(NULL);
131 if (err) {
132 TEST_FAIL("Bluetooth init failed");
133
134 bs_trace_silent_exit(err);
135 return;
136 }
137
138 bt_le_scan_cb_register(&scan_callbacks);
139
140 err = observer_start();
141 if (err) {
142 TEST_FAIL("Observer start failed");
143
144 bs_trace_silent_exit(err);
145 return;
146 }
147
148 /* Let the recv callback verify the reports */
149 k_sleep(K_SECONDS(10));
150
151 err = k_sem_take(&sem_recv, K_NO_WAIT);
152 if (err) {
153 TEST_FAIL("Scan receive failed");
154
155 bs_trace_silent_exit(err);
156 return;
157 }
158
159 TEST_PASS("Scan tests passed");
160
161 bs_trace_silent_exit(0);
162 }
163
164 static const struct bst_test_instance test_def[] = {
165 {
166 .test_id = "adv",
167 .test_descr = "Central GATT Write",
168 .test_main_f = test_adv_main
169 },
170 {
171 .test_id = "scan",
172 .test_descr = "Peripheral GATT Write",
173 .test_main_f = test_scan_main
174 },
175 BSTEST_END_MARKER
176 };
177
test_adv_chain_install(struct bst_test_list * tests)178 struct bst_test_list *test_adv_chain_install(struct bst_test_list *tests)
179 {
180 return bst_add_tests(tests, test_def);
181 }
182
183 bst_test_install_t test_installers[] = {
184 test_adv_chain_install,
185 NULL
186 };
187
main(void)188 int main(void)
189 {
190 bst_main();
191 return 0;
192 }
193