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