1 /** @file
2  * @brief Bluetooth Link Layer functions
3  *
4  */
5 
6 /*
7  * Copyright (c) 2017-2018 Nordic Semiconductor ASA
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #include <stdlib.h>
13 #include <string.h>
14 #include <zephyr/kernel.h>
15 
16 #include <zephyr/bluetooth/hci.h>
17 #include <zephyr/bluetooth/bluetooth.h>
18 #include <zephyr/bluetooth/conn.h>
19 
20 #include <zephyr/shell/shell.h>
21 
22 #include "../controller/util/memq.h"
23 #include "../controller/include/ll.h"
24 
25 #include "bt.h"
26 
cmd_ll_addr_read(const struct shell * sh,size_t argc,char * argv[])27 int cmd_ll_addr_read(const struct shell *sh, size_t argc, char *argv[])
28 {
29 	uint8_t addr_type;
30 	const char *str_type;
31 	bt_addr_t addr;
32 	char str_addr[BT_ADDR_STR_LEN];
33 
34 	if (argc < 2) {
35 		return -EINVAL;
36 	}
37 
38 	str_type = argv[1];
39 	if (!strcmp(str_type, "random")) {
40 		addr_type = 1U;
41 	} else if (!strcmp(str_type, "public")) {
42 		addr_type = 0U;
43 	} else {
44 		return -EINVAL;
45 	}
46 
47 	(void)ll_addr_read(addr_type, addr.val);
48 	bt_addr_to_str(&addr, str_addr, sizeof(str_addr));
49 
50 	shell_print(sh, "Current %s address: %s", str_type, str_addr);
51 
52 	return 0;
53 }
54 
55 #if defined(CONFIG_BT_CTLR_DTM)
56 #include "../controller/ll_sw/ll_test.h"
57 
cmd_test_tx(const struct shell * sh,size_t argc,char * argv[])58 int cmd_test_tx(const struct shell *sh, size_t  argc, char *argv[])
59 {
60 	uint8_t chan, len, type, phy;
61 	uint8_t err;
62 
63 	if (argc < 5) {
64 		return -EINVAL;
65 	}
66 
67 	chan = strtoul(argv[1], NULL, 16);
68 	len  = strtoul(argv[2], NULL, 16);
69 	type = strtoul(argv[3], NULL, 16);
70 	phy  = strtoul(argv[4], NULL, 16);
71 
72 	err = ll_test_tx(chan, len, type, phy, BT_HCI_LE_TEST_CTE_DISABLED,
73 			 BT_HCI_LE_TEST_CTE_TYPE_ANY, BT_HCI_LE_TEST_SWITCH_PATTERN_LEN_ANY,
74 			 NULL, BT_HCI_TX_TEST_POWER_MAX_SET);
75 	if (err) {
76 		return -EINVAL;
77 	}
78 
79 	shell_print(sh, "test_tx...");
80 
81 	return 0;
82 }
83 
cmd_test_rx(const struct shell * sh,size_t argc,char * argv[])84 int cmd_test_rx(const struct shell *sh, size_t  argc, char *argv[])
85 {
86 	uint8_t chan, phy, mod_idx;
87 	uint8_t err;
88 
89 	if (argc < 4) {
90 		return -EINVAL;
91 	}
92 
93 	chan    = strtoul(argv[1], NULL, 16);
94 	phy     = strtoul(argv[2], NULL, 16);
95 	mod_idx = strtoul(argv[3], NULL, 16);
96 
97 	err = ll_test_rx(chan, phy, mod_idx, BT_HCI_LE_TEST_CTE_DISABLED,
98 			 BT_HCI_LE_TEST_CTE_TYPE_ANY, BT_HCI_LE_TEST_SLOT_DURATION_ANY,
99 			 BT_HCI_LE_TEST_SWITCH_PATTERN_LEN_ANY, NULL);
100 	if (err) {
101 		return -EINVAL;
102 	}
103 
104 	shell_print(sh, "test_rx...");
105 
106 	return 0;
107 }
108 
cmd_test_end(const struct shell * sh,size_t argc,char * argv[])109 int cmd_test_end(const struct shell *sh, size_t  argc, char *argv[])
110 {
111 	uint16_t num_rx;
112 	uint8_t err;
113 
114 	err = ll_test_end(&num_rx);
115 	if (err) {
116 		return -EINVAL;
117 	}
118 
119 	shell_print(sh, "num_rx= %u.", num_rx);
120 
121 	return 0;
122 }
123 #endif /* CONFIG_BT_CTLR_DTM */
124 
125 #if defined(CONFIG_BT_CTLR_ADV_EXT)
126 #include "../controller/ll_sw/lll.h"
127 
128 #if defined(CONFIG_BT_BROADCASTER)
129 #define OWN_ADDR_TYPE 1
130 #define PEER_ADDR_TYPE 0
131 #define PEER_ADDR NULL
132 #define ADV_CHAN_MAP 0x07
133 #define FILTER_POLICY 0x00
134 #define ADV_TX_PWR NULL
135 #define ADV_SEC_SKIP 0
136 #define ADV_PHY_S 0x01
137 #define ADV_SID 0
138 #define SCAN_REQ_NOT 0
139 
140 #define AD_OP 0x03
141 #define AD_FRAG_PREF 0x00
142 
143 static const struct bt_data adv_data[] = {
144 	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
145 	};
146 
cmd_advx(const struct shell * sh,size_t argc,char * argv[])147 int cmd_advx(const struct shell *sh, size_t argc, char *argv[])
148 {
149 	uint16_t adv_interval = 0x20;
150 	uint16_t handle = 0U;
151 	uint16_t evt_prop = 0U;
152 	uint8_t adv_type;
153 	uint8_t enable;
154 	uint8_t ad = 0;
155 	uint8_t phy_p;
156 	int32_t err;
157 
158 	if (argc < 2) {
159 		return -EINVAL;
160 	}
161 
162 	if (argc > 1) {
163 		if (!strcmp(argv[1], "on")) {
164 			adv_type = 0x05; /* Adv. Ext. */
165 			enable = 1U;
166 		} else if (!strcmp(argv[1], "hdcd")) {
167 			adv_type = 0x01; /* Directed */
168 			adv_interval = 0U; /* High Duty Cycle */
169 			phy_p = BIT(0);
170 			enable = 1U;
171 			goto do_enable;
172 		} else if (!strcmp(argv[1], "ldcd")) {
173 			adv_type = 0x04; /* Directed */
174 			enable = 1U;
175 		} else if (!strcmp(argv[1], "off")) {
176 			enable = 0U;
177 		} else {
178 			return -EINVAL;
179 		}
180 	}
181 
182 	phy_p = BIT(0);
183 
184 	if (argc > 2) {
185 		if (!strcmp(argv[2], "coded")) {
186 			phy_p = BIT(2);
187 		} else if (!strcmp(argv[2], "anon")) {
188 			evt_prop |= BIT(5);
189 		} else if (!strcmp(argv[2], "txp")) {
190 			evt_prop |= BIT(6);
191 		} else if (!strcmp(argv[2], "ad")) {
192 			ad = 1;
193 		} else {
194 			handle = strtoul(argv[2], NULL, 16);
195 			if (handle >= CONFIG_BT_CTLR_ADV_SET) {
196 				return -EINVAL;
197 			}
198 		}
199 	}
200 
201 	if (argc > 3) {
202 		if (!strcmp(argv[3], "anon")) {
203 			evt_prop |= BIT(5);
204 		} else if (!strcmp(argv[3], "txp")) {
205 			evt_prop |= BIT(6);
206 		} else if (!strcmp(argv[3], "ad")) {
207 			ad = 1;
208 		} else {
209 			handle = strtoul(argv[3], NULL, 16);
210 			if (handle >= CONFIG_BT_CTLR_ADV_SET) {
211 				return -EINVAL;
212 			}
213 		}
214 	}
215 
216 	if (argc > 4) {
217 		if (!strcmp(argv[4], "txp")) {
218 			evt_prop |= BIT(6);
219 		} else if (!strcmp(argv[4], "ad")) {
220 			ad = 1;
221 		} else {
222 			handle = strtoul(argv[4], NULL, 16);
223 			if (handle >= CONFIG_BT_CTLR_ADV_SET) {
224 				return -EINVAL;
225 			}
226 		}
227 	}
228 
229 	if (argc > 5) {
230 		if (!strcmp(argv[5], "ad")) {
231 			ad = 1;
232 		} else {
233 			handle = strtoul(argv[5], NULL, 16);
234 			if (handle >= CONFIG_BT_CTLR_ADV_SET) {
235 				return -EINVAL;
236 			}
237 		}
238 	}
239 
240 	if (argc > 6) {
241 		handle = strtoul(argv[6], NULL, 16);
242 		if (handle >= CONFIG_BT_CTLR_ADV_SET) {
243 			return -EINVAL;
244 		}
245 	}
246 
247 	if (!enable) {
248 		goto disable;
249 	}
250 
251 do_enable:
252 	shell_print(sh, "adv param set...");
253 	err = ll_adv_params_set(handle, evt_prop, adv_interval, adv_type,
254 				OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
255 				ADV_CHAN_MAP, FILTER_POLICY, ADV_TX_PWR,
256 				phy_p, ADV_SEC_SKIP, ADV_PHY_S, ADV_SID,
257 				SCAN_REQ_NOT);
258 	if (err) {
259 		goto exit;
260 	}
261 
262 	if (ad) {
263 		shell_print(sh, "ad data set...");
264 		err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF,
265 					     ARRAY_SIZE(adv_data),
266 					     (void *)adv_data);
267 		if (err) {
268 			goto exit;
269 		}
270 	}
271 
272 disable:
273 	shell_print(sh, "adv enable (%u)...", enable);
274 #if defined(CONFIG_BT_HCI_MESH_EXT)
275 	err = ll_adv_enable(handle, enable, 0, 0, 0, 0, 0);
276 #else /* !CONFIG_BT_HCI_MESH_EXT */
277 	err = ll_adv_enable(handle, enable, 0, 0);
278 #endif /* !CONFIG_BT_HCI_MESH_EXT */
279 	if (err) {
280 		goto exit;
281 	}
282 
283 	if (!enable) {
284 		err = ll_adv_aux_set_remove(handle);
285 		if (err) {
286 			goto exit;
287 		}
288 	}
289 
290 exit:
291 	shell_print(sh, "done (err= %d).", err);
292 
293 	return 0;
294 }
295 #endif /* CONFIG_BT_BROADCASTER */
296 
297 #if defined(CONFIG_BT_OBSERVER)
298 #define SCAN_INTERVAL 0x0004
299 #define SCAN_WINDOW 0x0004
300 #define SCAN_OWN_ADDR_TYPE 1
301 #define SCAN_FILTER_POLICY 0
302 
cmd_scanx(const struct shell * sh,size_t argc,char * argv[])303 int cmd_scanx(const struct shell *sh, size_t  argc, char *argv[])
304 {
305 	uint8_t type = 0U;
306 	uint8_t enable;
307 	int32_t err;
308 
309 	if (argc < 2) {
310 		return -EINVAL;
311 	}
312 
313 	if (argc > 1) {
314 		if (!strcmp(argv[1], "on")) {
315 			enable = 1U;
316 			type = 1U;
317 		} else if (!strcmp(argv[1], "passive")) {
318 			enable = 1U;
319 			type = 0U;
320 		} else if (!strcmp(argv[1], "off")) {
321 			enable = 0U;
322 			goto disable;
323 		} else {
324 			return -EINVAL;
325 		}
326 	}
327 
328 	type |= BIT(1);
329 
330 	if (argc > 2) {
331 		if (!strcmp(argv[2], "coded")) {
332 			type &= BIT(0);
333 			type |= BIT(3);
334 		} else {
335 			return -EINVAL;
336 		}
337 	}
338 
339 	shell_print(sh, "scan param set...");
340 	err = ll_scan_params_set(type, SCAN_INTERVAL, SCAN_WINDOW,
341 				 SCAN_OWN_ADDR_TYPE, SCAN_FILTER_POLICY);
342 	if (err) {
343 		goto exit;
344 	}
345 
346 disable:
347 	shell_print(sh, "scan enable (%u)...", enable);
348 	err = ll_scan_enable(enable, 0, 0);
349 	if (err) {
350 		goto exit;
351 	}
352 
353 exit:
354 	shell_print(sh, "done (err= %d).", err);
355 
356 	return err;
357 }
358 #endif /* CONFIG_BT_OBSERVER */
359 #endif /* CONFIG_BT_CTLR_ADV_EXT */
360