1 /** @file
2 * @brief Bluetooth shell module
3 *
4 * Provide some Bluetooth shell commands that can be useful to applications.
5 */
6
7 /*
8 * Copyright (c) 2017 Intel Corporation
9 * Copyright (c) 2018-2025 Nordic Semiconductor ASA
10 *
11 * SPDX-License-Identifier: Apache-2.0
12 */
13
14 #include <errno.h>
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <sys/types.h>
22
23 #include <zephyr/autoconf.h>
24 #include <zephyr/bluetooth/addr.h>
25 #include <zephyr/bluetooth/audio/bap.h>
26 #include <zephyr/bluetooth/bluetooth.h>
27 #include <zephyr/bluetooth/classic/rfcomm.h>
28 #include <zephyr/bluetooth/classic/sdp.h>
29 #include <zephyr/bluetooth/conn.h>
30 #include <zephyr/bluetooth/ead.h>
31 #include <zephyr/bluetooth/gap.h>
32 #include <zephyr/bluetooth/hci.h>
33 #include <zephyr/bluetooth/hci_types.h>
34 #include <zephyr/bluetooth/iso.h>
35 #include <zephyr/bluetooth/uuid.h>
36 #include <zephyr/kernel.h>
37 #include <zephyr/net_buf.h>
38 #include <zephyr/settings/settings.h>
39 #include <zephyr/shell/shell.h>
40 #include <zephyr/shell/shell_string_conv.h>
41 #include <zephyr/shell/shell_types.h>
42 #include <zephyr/sys/__assert.h>
43 #include <zephyr/sys/atomic.h>
44 #include <zephyr/sys/printk.h>
45 #include <zephyr/sys/byteorder.h>
46 #include <zephyr/sys/util.h>
47 #include <zephyr/sys/util_macro.h>
48 #include <zephyr/toolchain.h>
49 #include <zephyr/types.h>
50
51 #include "audio/shell/audio.h"
52 #include "common/bt_shell_private.h"
53 #if defined(CONFIG_BT_LL_SW_SPLIT)
54 #include "controller/ll_sw/shell/ll.h"
55 #endif /* CONFIG_BT_LL_SW_SPLIT */
56 #include "host/shell/bt.h"
57 #if defined(CONFIG_BT_CLASSIC)
58 #include "host/classic/shell/bredr.h"
59 #endif
60
61 static bool no_settings_load;
62
63 uint8_t selected_id = BT_ID_DEFAULT;
64
65 #if defined(CONFIG_BT_CONN)
66 struct bt_conn *default_conn;
67
68 /* Connection context for BR/EDR legacy pairing in sec mode 3 */
69 static struct bt_conn *pairing_conn;
70
71 static struct bt_le_oob oob_local;
72 #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CLASSIC)
73 static struct bt_le_oob oob_remote;
74 #endif /* CONFIG_BT_SMP || CONFIG_BT_CLASSIC) */
75 #endif /* CONFIG_BT_CONN */
76
77 #if defined(CONFIG_BT_SMP)
78 static struct bt_conn_auth_info_cb auth_info_cb;
79 #endif /* CONFIG_BT_SMP */
80
81 #define NAME_LEN 30
82
83 #define KEY_STR_LEN 33
84
85 #define ADV_DATA_DELIMITER ", "
86
87 #define AD_SIZE 9
88
89 /*
90 * Based on the maximum number of parameters for HCI_LE_Generate_DHKey
91 * See BT Core Spec V5.2 Vol. 4, Part E, section 7.8.37
92 */
93 #define HCI_CMD_MAX_PARAM 65
94
95 #define DEFAULT_SCAN_TIMEOUT_SEC 10
96
97 #if defined(CONFIG_BT_BROADCASTER)
98 enum {
99 SHELL_ADV_OPT_CONNECTABLE,
100 SHELL_ADV_OPT_DISCOVERABLE,
101 SHELL_ADV_OPT_EXT_ADV,
102 SHELL_ADV_OPT_APPEARANCE,
103 SHELL_ADV_OPT_KEEP_RPA,
104
105 SHELL_ADV_OPT_NUM,
106 };
107
108 static ATOMIC_DEFINE(adv_opt, SHELL_ADV_OPT_NUM);
109 #if defined(CONFIG_BT_EXT_ADV)
110 uint8_t selected_adv;
111 struct bt_le_ext_adv *adv_sets[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
112 static ATOMIC_DEFINE(adv_set_opt, SHELL_ADV_OPT_NUM)[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
113 #endif /* CONFIG_BT_EXT_ADV */
114 #endif /* CONFIG_BT_BROADCASTER */
115
116 #if defined(CONFIG_BT_OBSERVER) || defined(CONFIG_BT_USER_PHY_UPDATE)
phy2str(uint8_t phy)117 static const char *phy2str(uint8_t phy)
118 {
119 switch (phy) {
120 case 0: return "No packets";
121 case BT_GAP_LE_PHY_1M:
122 return "LE 1M";
123 case BT_GAP_LE_PHY_2M:
124 return "LE 2M";
125 case BT_GAP_LE_PHY_CODED:
126 return "LE Coded";
127 default:
128 return "Unknown";
129 }
130 }
131 #endif
132
133 #if defined(CONFIG_BT_CONN) || (defined(CONFIG_BT_BROADCASTER) && defined(CONFIG_BT_EXT_ADV))
print_le_addr(const char * desc,const bt_addr_le_t * addr)134 static void print_le_addr(const char *desc, const bt_addr_le_t *addr)
135 {
136 char addr_str[BT_ADDR_LE_STR_LEN];
137
138 const char *addr_desc = bt_addr_le_is_identity(addr) ? "identity" :
139 bt_addr_le_is_rpa(addr) ? "resolvable" :
140 "non-resolvable";
141
142 bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
143
144 bt_shell_print("%s address: %s (%s)", desc, addr_str, addr_desc);
145 }
146 #endif /* CONFIG_BT_CONN || (CONFIG_BT_BROADCASTER && CONFIG_BT_EXT_ADV) */
147
148 #if defined(CONFIG_BT_TRANSMIT_POWER_CONTROL)
tx_power_flag2str(int8_t flag)149 static const char *tx_power_flag2str(int8_t flag)
150 {
151 switch (flag) {
152 case 0:
153 return "Neither Max nor Min Tx Power";
154 case 1:
155 return "Tx Power Level is at minimum";
156 case 2:
157 return "Tx Power Level is at maximum";
158 /* Current Tx Power Level is the only available one*/
159 case 3:
160 return "Tx Power Level is at minimum & maximum.";
161 default:
162 return "Unknown";
163 }
164 }
165
tx_power_report_reason2str(uint8_t reason)166 static const char *tx_power_report_reason2str(uint8_t reason)
167 {
168 switch (reason) {
169 case BT_HCI_LE_TX_POWER_REPORT_REASON_LOCAL_CHANGED:
170 return "Local Tx Power changed";
171 case BT_HCI_LE_TX_POWER_REPORT_REASON_REMOTE_CHANGED:
172 return "Remote Tx Power changed";
173 case BT_HCI_LE_TX_POWER_REPORT_REASON_READ_REMOTE_COMPLETED:
174 return "Completed to read remote Tx Power";
175 default:
176 return "Unknown";
177 }
178 }
179
tx_pwr_ctrl_phy2str(enum bt_conn_le_tx_power_phy phy)180 static const char *tx_pwr_ctrl_phy2str(enum bt_conn_le_tx_power_phy phy)
181 {
182 switch (phy) {
183 case BT_CONN_LE_TX_POWER_PHY_NONE:
184 return "None";
185 case BT_CONN_LE_TX_POWER_PHY_1M:
186 return "LE 1M";
187 case BT_CONN_LE_TX_POWER_PHY_2M:
188 return "LE 2M";
189 case BT_CONN_LE_TX_POWER_PHY_CODED_S8:
190 return "LE Coded S8";
191 case BT_CONN_LE_TX_POWER_PHY_CODED_S2:
192 return "LE Coded S2";
193 default:
194 return "Unknown";
195 }
196 }
197
enabled2str(bool enabled)198 static const char *enabled2str(bool enabled)
199 {
200 if (enabled) {
201 return "Enabled";
202 } else {
203 return "Disabled";
204 }
205 }
206
207 #endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */
208
209 #if defined(CONFIG_BT_PATH_LOSS_MONITORING)
plm_report_zone_str(enum bt_conn_le_path_loss_zone zone)210 static const char *plm_report_zone_str(enum bt_conn_le_path_loss_zone zone)
211 {
212 switch (zone) {
213 case BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_LOW:
214 return "Entered low zone";
215 case BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_MIDDLE:
216 return "Entered middle zone";
217 case BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH:
218 return "Entered high zone";
219 case BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE:
220 return "Path loss unavailable";
221 default:
222 return "Unknown";
223 }
224 }
225 #endif /* CONFIG_BT_PATH_LOSS_MONITORING */
226
227 #if defined(CONFIG_BT_CENTRAL)
228 static void bt_do_scan_filter_clear_name(void);
229 static int bt_do_scan_off(void);
230 static int bt_do_connect_le(int *ercd, size_t argc, char *argv[]);
231
232 static struct bt_auto_connect {
233 bt_addr_le_t addr;
234 bool addr_set;
235 bool connect_name;
236 } auto_connect;
237 #endif /* CONFIG_BT_CENTRAL */
238
239 #if defined(CONFIG_BT_OBSERVER)
active_scan_timeout(struct k_work * work)240 static void active_scan_timeout(struct k_work *work)
241 {
242 int err;
243
244 bt_shell_print("Scan timeout");
245
246 err = bt_le_scan_stop();
247 if (err) {
248 bt_shell_error("Failed to stop scan (err %d)", err);
249 }
250
251 #if defined(CONFIG_BT_CENTRAL)
252 if (auto_connect.connect_name) {
253 auto_connect.connect_name = false;
254 bt_do_scan_filter_clear_name();
255 }
256 #endif /* CONFIG_BT_CENTRAL */
257 }
258
259 static K_WORK_DELAYABLE_DEFINE(active_scan_timeout_work, active_scan_timeout);
260
261 static struct bt_scan_filter {
262 char name[NAME_LEN];
263 bool name_set;
264 char addr[BT_ADDR_STR_LEN];
265 bool addr_set;
266 int8_t rssi;
267 bool rssi_set;
268 uint16_t pa_interval;
269 bool pa_interval_set;
270 } scan_filter;
271
272 static const char scan_response_label[] = "[DEVICE]: ";
273 static bool scan_verbose_output;
274
275 #if defined(CONFIG_BT_EAD)
276 static uint8_t bt_shell_ead_session_key[BT_EAD_KEY_SIZE] = {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5,
277 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB,
278 0xCC, 0xCD, 0xCE, 0xCF};
279 static uint8_t bt_shell_ead_iv[BT_EAD_IV_SIZE] = {0xFB, 0x56, 0xE1, 0xDA, 0xDC, 0x7E, 0xAD, 0xF5};
280
281 /* this is the number of ad struct allowed */
282 #define BT_SHELL_EAD_MAX_AD 10
283 static size_t bt_shell_ead_ad_len;
284
285 #if defined(CONFIG_BT_CTLR_ADV_DATA_LEN_MAX)
286 /* this is the maximum total size of the ad data */
287 #define BT_SHELL_EAD_DATA_MAX_SIZE CONFIG_BT_CTLR_ADV_DATA_LEN_MAX
288 #else
289 #define BT_SHELL_EAD_DATA_MAX_SIZE 31
290 #endif
291 static size_t bt_shell_ead_data_size;
292 static uint8_t bt_shell_ead_data[BT_SHELL_EAD_DATA_MAX_SIZE] = {0};
293
294 int ead_update_ad(void);
295 #endif
296
297 static bool bt_shell_ead_decrypt_scan;
298
is_substring(const char * substr,const char * str)299 bool is_substring(const char *substr, const char *str)
300 {
301 const size_t str_len = strlen(str);
302 const size_t sub_str_len = strlen(substr);
303
304 if (sub_str_len > str_len) {
305 return false;
306 }
307
308 for (size_t pos = 0; pos < str_len; pos++) {
309 if (pos + sub_str_len > str_len) {
310 return false;
311 }
312
313 if (strncasecmp(substr, &str[pos], sub_str_len) == 0) {
314 return true;
315 }
316 }
317
318 return false;
319 }
320
data_cb(struct bt_data * data,void * user_data)321 static bool data_cb(struct bt_data *data, void *user_data)
322 {
323 char *name = user_data;
324
325 switch (data->type) {
326 case BT_DATA_NAME_SHORTENED:
327 case BT_DATA_NAME_COMPLETE:
328 case BT_DATA_BROADCAST_NAME:
329 memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1));
330 return false;
331 default:
332 return true;
333 }
334 }
335
print_data_hex(const uint8_t * data,uint8_t len,enum shell_vt100_color color)336 static void print_data_hex(const uint8_t *data, uint8_t len, enum shell_vt100_color color)
337 {
338 if (len == 0) {
339 return;
340 }
341
342 bt_shell_fprintf(color, "0x");
343 /* Reverse the byte order when printing as advertising data is LE
344 * and the MSB should be first in the printed output.
345 */
346 for (int16_t i = len - 1; i >= 0; i--) {
347 bt_shell_fprintf(color, "%02x", data[i]);
348 }
349 }
350
print_data_set(uint8_t set_value_len,const uint8_t * scan_data,uint8_t scan_data_len)351 static void print_data_set(uint8_t set_value_len,
352 const uint8_t *scan_data, uint8_t scan_data_len)
353 {
354 uint8_t idx = 0;
355
356 if (scan_data_len == 0 || set_value_len > scan_data_len) {
357 return;
358 }
359
360 do {
361 if (idx > 0) {
362 bt_shell_fprintf_info(ADV_DATA_DELIMITER);
363 }
364
365 print_data_hex(&scan_data[idx], set_value_len, SHELL_INFO);
366 idx += set_value_len;
367 } while (idx + set_value_len <= scan_data_len);
368
369 if (idx < scan_data_len) {
370 bt_shell_fprintf_warn(" Excess data: ");
371 print_data_hex(&scan_data[idx], scan_data_len - idx, SHELL_WARNING);
372 }
373 }
374
data_verbose_cb(struct bt_data * data,void * user_data)375 static bool data_verbose_cb(struct bt_data *data, void *user_data)
376 {
377 bt_shell_fprintf_info("%*sType 0x%02x: ",
378 (int)strlen(scan_response_label), "", data->type);
379
380 switch (data->type) {
381 case BT_DATA_UUID16_SOME:
382 case BT_DATA_UUID16_ALL:
383 case BT_DATA_SOLICIT16:
384 print_data_set(BT_UUID_SIZE_16, data->data, data->data_len);
385 break;
386 case BT_DATA_SVC_DATA16:
387 /* Data starts with a UUID16 (2 bytes),
388 * the rest is unknown and printed as single bytes
389 */
390 if (data->data_len < BT_UUID_SIZE_16) {
391 bt_shell_fprintf_warn("BT_DATA_SVC_DATA16 data length too short (%u)",
392 data->data_len);
393 break;
394 }
395 print_data_set(BT_UUID_SIZE_16, data->data, BT_UUID_SIZE_16);
396 if (data->data_len > BT_UUID_SIZE_16) {
397 bt_shell_fprintf_info(ADV_DATA_DELIMITER);
398 print_data_set(1, data->data + BT_UUID_SIZE_16,
399 data->data_len - BT_UUID_SIZE_16);
400 }
401 break;
402 case BT_DATA_UUID32_SOME:
403 case BT_DATA_UUID32_ALL:
404 print_data_set(BT_UUID_SIZE_32, data->data, data->data_len);
405 break;
406 case BT_DATA_SVC_DATA32:
407 /* Data starts with a UUID32 (4 bytes),
408 * the rest is unknown and printed as single bytes
409 */
410 if (data->data_len < BT_UUID_SIZE_32) {
411 bt_shell_fprintf_warn("BT_DATA_SVC_DATA32 data length too short (%u)",
412 data->data_len);
413 break;
414 }
415 print_data_set(BT_UUID_SIZE_32, data->data, BT_UUID_SIZE_32);
416 if (data->data_len > BT_UUID_SIZE_32) {
417 bt_shell_fprintf_info(ADV_DATA_DELIMITER);
418 print_data_set(1, data->data + BT_UUID_SIZE_32,
419 data->data_len - BT_UUID_SIZE_32);
420 }
421 break;
422 case BT_DATA_UUID128_SOME:
423 case BT_DATA_UUID128_ALL:
424 case BT_DATA_SOLICIT128:
425 print_data_set(BT_UUID_SIZE_128, data->data, data->data_len);
426 break;
427 case BT_DATA_SVC_DATA128:
428 /* Data starts with a UUID128 (16 bytes),
429 * the rest is unknown and printed as single bytes
430 */
431 if (data->data_len < BT_UUID_SIZE_128) {
432 bt_shell_fprintf_warn("BT_DATA_SVC_DATA128 data length too short (%u)",
433 data->data_len);
434 break;
435 }
436 print_data_set(BT_UUID_SIZE_128, data->data, BT_UUID_SIZE_128);
437 if (data->data_len > BT_UUID_SIZE_128) {
438 bt_shell_fprintf_info(ADV_DATA_DELIMITER);
439 print_data_set(1, data->data + BT_UUID_SIZE_128,
440 data->data_len - BT_UUID_SIZE_128);
441 }
442 break;
443 case BT_DATA_NAME_SHORTENED:
444 case BT_DATA_NAME_COMPLETE:
445 case BT_DATA_BROADCAST_NAME:
446 bt_shell_fprintf_info("%.*s", data->data_len, data->data);
447 break;
448 case BT_DATA_PUB_TARGET_ADDR:
449 case BT_DATA_RAND_TARGET_ADDR:
450 case BT_DATA_LE_BT_DEVICE_ADDRESS:
451 print_data_set(BT_ADDR_SIZE, data->data, data->data_len);
452 break;
453 case BT_DATA_CSIS_RSI:
454 print_data_set(3, data->data, data->data_len);
455 break;
456 case BT_DATA_ENCRYPTED_AD_DATA:
457 bt_shell_fprintf_info("Encrypted Advertising Data: ");
458 print_data_set(1, data->data, data->data_len);
459
460 if (bt_shell_ead_decrypt_scan) {
461 #if defined(CONFIG_BT_EAD)
462 bt_shell_fprintf_info("\n%*s[START DECRYPTED DATA]\n",
463 strlen(scan_response_label), "");
464
465 int ead_err;
466 struct net_buf_simple decrypted_buf;
467 size_t decrypted_data_size = BT_EAD_DECRYPTED_PAYLOAD_SIZE(data->data_len);
468 uint8_t decrypted_data[decrypted_data_size];
469
470 ead_err = bt_ead_decrypt(bt_shell_ead_session_key, bt_shell_ead_iv,
471 data->data, data->data_len, decrypted_data);
472 if (ead_err) {
473 bt_shell_error("Error during decryption (err %d)", ead_err);
474 }
475
476 net_buf_simple_init_with_data(&decrypted_buf, &decrypted_data[0],
477 decrypted_data_size);
478
479 bt_data_parse(&decrypted_buf, &data_verbose_cb, user_data);
480
481 bt_shell_fprintf_info("%*s[END DECRYPTED DATA]",
482 strlen(scan_response_label), "");
483 #endif
484 }
485 break;
486 default:
487 print_data_set(1, data->data, data->data_len);
488 }
489
490 bt_shell_fprintf_info("\n");
491
492 return true;
493 }
494
scan_response_type_txt(uint8_t type)495 static const char *scan_response_type_txt(uint8_t type)
496 {
497 switch (type) {
498 case BT_GAP_ADV_TYPE_ADV_IND:
499 return "ADV_IND";
500 case BT_GAP_ADV_TYPE_ADV_DIRECT_IND:
501 return "ADV_DIRECT_IND";
502 case BT_GAP_ADV_TYPE_ADV_SCAN_IND:
503 return "ADV_SCAN_IND";
504 case BT_GAP_ADV_TYPE_ADV_NONCONN_IND:
505 return "ADV_NONCONN_IND";
506 case BT_GAP_ADV_TYPE_SCAN_RSP:
507 return "SCAN_RSP";
508 case BT_GAP_ADV_TYPE_EXT_ADV:
509 return "EXT_ADV";
510 default:
511 return "UNKNOWN";
512 }
513 }
514
passes_scan_filter(const struct bt_le_scan_recv_info * info,const struct net_buf_simple * buf)515 bool passes_scan_filter(const struct bt_le_scan_recv_info *info, const struct net_buf_simple *buf)
516 {
517
518 if (scan_filter.rssi_set && (scan_filter.rssi > info->rssi)) {
519 return false;
520 }
521
522 if (scan_filter.pa_interval_set &&
523 (scan_filter.pa_interval > BT_CONN_INTERVAL_TO_MS(info->interval))) {
524 return false;
525 }
526
527 if (scan_filter.addr_set) {
528 char le_addr[BT_ADDR_LE_STR_LEN] = {0};
529
530 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
531
532 if (!is_substring(scan_filter.addr, le_addr)) {
533 return false;
534 }
535 }
536
537 if (scan_filter.name_set) {
538 struct net_buf_simple buf_copy;
539 char name[NAME_LEN] = {0};
540
541 /* call to bt_data_parse consumes netbufs so shallow clone for verbose output */
542 net_buf_simple_clone(buf, &buf_copy);
543 bt_data_parse(&buf_copy, data_cb, name);
544
545 if (!is_substring(scan_filter.name, name)) {
546 return false;
547 }
548 }
549
550 return true;
551 }
552
scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)553 static void scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf)
554 {
555 char le_addr[BT_ADDR_LE_STR_LEN];
556 char name[NAME_LEN];
557 struct net_buf_simple buf_copy;
558
559 if (!passes_scan_filter(info, buf)) {
560 return;
561 }
562
563 if (scan_verbose_output) {
564 /* call to bt_data_parse consumes netbufs so shallow clone for verbose output */
565 net_buf_simple_clone(buf, &buf_copy);
566 }
567
568 (void)memset(name, 0, sizeof(name));
569
570 bt_data_parse(buf, data_cb, name);
571 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
572
573 bt_shell_print("%s%s, AD evt type %u, RSSI %i %s "
574 "C:%u S:%u D:%d SR:%u E:%u Prim: %s, Secn: %s, "
575 "Interval: 0x%04x (%u us), SID: 0x%x",
576 scan_response_label,
577 le_addr, info->adv_type, info->rssi, name,
578 (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
579 (info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
580 (info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
581 (info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
582 (info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
583 phy2str(info->primary_phy), phy2str(info->secondary_phy),
584 info->interval, BT_CONN_INTERVAL_TO_US(info->interval),
585 info->sid);
586
587 if (scan_verbose_output) {
588 bt_shell_info("%*s[SCAN DATA START - %s]",
589 (int)strlen(scan_response_label), "",
590 scan_response_type_txt(info->adv_type));
591 bt_data_parse(&buf_copy, data_verbose_cb, NULL);
592 bt_shell_info("%*s[SCAN DATA END]", (int)strlen(scan_response_label), "");
593 }
594
595 #if defined(CONFIG_BT_CENTRAL)
596 if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0U) {
597 struct bt_conn *conn = bt_conn_lookup_addr_le(selected_id, info->addr);
598
599 /* Only store auto-connect address for devices we are not already connected to */
600 if (conn == NULL) {
601 /* Store address for later use */
602 auto_connect.addr_set = true;
603 bt_addr_le_copy(&auto_connect.addr, info->addr);
604
605 /* Use the above auto_connect.addr address to automatically connect */
606 if (auto_connect.connect_name) {
607 __maybe_unused int ercd;
608
609 auto_connect.connect_name = false;
610
611 bt_do_scan_off();
612
613 bt_do_scan_filter_clear_name();
614
615 /* "connect" is what would be in argv[0] normally */
616 bt_do_connect_le(&ercd, 1, (char *[]){"connect"});
617 }
618 } else {
619 bt_conn_unref(conn);
620 }
621 }
622 #endif /* CONFIG_BT_CENTRAL */
623 }
624
scan_timeout(void)625 static void scan_timeout(void)
626 {
627 bt_shell_print("Scan timeout");
628 }
629 #endif /* CONFIG_BT_OBSERVER */
630
631 #if defined(CONFIG_BT_EXT_ADV)
632 #if defined(CONFIG_BT_BROADCASTER)
adv_sent(struct bt_le_ext_adv * adv,struct bt_le_ext_adv_sent_info * info)633 static void adv_sent(struct bt_le_ext_adv *adv,
634 struct bt_le_ext_adv_sent_info *info)
635 {
636 bt_shell_print("Advertiser[%d] %p sent %d", bt_le_ext_adv_get_index(adv), adv,
637 info->num_sent);
638 }
639
adv_scanned(struct bt_le_ext_adv * adv,struct bt_le_ext_adv_scanned_info * info)640 static void adv_scanned(struct bt_le_ext_adv *adv,
641 struct bt_le_ext_adv_scanned_info *info)
642 {
643 char str[BT_ADDR_LE_STR_LEN];
644
645 bt_addr_le_to_str(info->addr, str, sizeof(str));
646
647 bt_shell_print("Advertiser[%d] %p scanned by %s", bt_le_ext_adv_get_index(adv), adv, str);
648 }
649 #endif /* CONFIG_BT_BROADCASTER */
650
651 #if defined(CONFIG_BT_PERIPHERAL)
adv_connected(struct bt_le_ext_adv * adv,struct bt_le_ext_adv_connected_info * info)652 static void adv_connected(struct bt_le_ext_adv *adv,
653 struct bt_le_ext_adv_connected_info *info)
654 {
655 char str[BT_ADDR_LE_STR_LEN];
656
657 bt_addr_le_to_str(bt_conn_get_dst(info->conn), str, sizeof(str));
658
659 bt_shell_print("Advertiser[%d] %p connected by %s", bt_le_ext_adv_get_index(adv), adv, str);
660 }
661 #endif /* CONFIG_BT_PERIPHERAL */
662
663 #if defined(CONFIG_BT_PRIVACY)
adv_rpa_expired(struct bt_le_ext_adv * adv)664 static bool adv_rpa_expired(struct bt_le_ext_adv *adv)
665 {
666 uint8_t adv_index = bt_le_ext_adv_get_index(adv);
667
668 bool keep_rpa = atomic_test_bit(adv_set_opt[adv_index], SHELL_ADV_OPT_KEEP_RPA);
669 bt_shell_print("Advertiser[%d] %p RPA %s", adv_index, adv,
670 keep_rpa ? "not expired" : "expired");
671
672 #if defined(CONFIG_BT_EAD)
673 /* EAD must be updated each time the RPA is updated */
674 if (!keep_rpa) {
675 ead_update_ad();
676 }
677 #endif
678
679 return keep_rpa;
680 }
681 #endif /* defined(CONFIG_BT_PRIVACY) */
682
683 #endif /* CONFIG_BT_EXT_ADV */
684
685 #if !defined(CONFIG_BT_CONN)
686 #if 0 /* FIXME: Add support for changing prompt */
687 static const char *current_prompt(void)
688 {
689 return NULL;
690 }
691 #endif
692 #endif /* !CONFIG_BT_CONN */
693
694 #if defined(CONFIG_BT_CONN)
695 #if 0 /* FIXME: Add support for changing prompt */
696 static const char *current_prompt(void)
697 {
698 static char str[BT_ADDR_LE_STR_LEN + 2];
699 static struct bt_conn_info info;
700
701 if (!default_conn) {
702 return NULL;
703 }
704
705 if (bt_conn_get_info(default_conn, &info) < 0) {
706 return NULL;
707 }
708
709 if (info.type != BT_CONN_TYPE_LE) {
710 return NULL;
711 }
712
713 bt_addr_le_to_str(info.le.dst, str, sizeof(str) - 2);
714 strcat(str, "> ");
715 return str;
716 }
717 #endif
718
conn_addr_str(struct bt_conn * conn,char * addr,size_t len)719 void conn_addr_str(struct bt_conn *conn, char *addr, size_t len)
720 {
721 struct bt_conn_info info;
722
723 if (bt_conn_get_info(conn, &info) < 0) {
724 addr[0] = '\0';
725 return;
726 }
727
728 switch (info.type) {
729 #if defined(CONFIG_BT_CLASSIC)
730 case BT_CONN_TYPE_BR:
731 bt_addr_to_str(info.br.dst, addr, len);
732 break;
733 #endif
734 case BT_CONN_TYPE_LE:
735 bt_addr_le_to_str(info.le.dst, addr, len);
736 break;
737 default:
738 break;
739 }
740 }
741
print_le_oob(const struct shell * sh,struct bt_le_oob * oob)742 static void print_le_oob(const struct shell *sh, struct bt_le_oob *oob)
743 {
744 char addr[BT_ADDR_LE_STR_LEN];
745 char c[KEY_STR_LEN];
746 char r[KEY_STR_LEN];
747
748 bt_addr_le_to_str(&oob->addr, addr, sizeof(addr));
749
750 bin2hex(oob->le_sc_data.c, sizeof(oob->le_sc_data.c), c, sizeof(c));
751 bin2hex(oob->le_sc_data.r, sizeof(oob->le_sc_data.r), r, sizeof(r));
752
753 shell_print(sh, "OOB data:");
754 shell_print(sh, "%-29s %-32s %-32s", "addr", "random", "confirm");
755 shell_print(sh, "%29s %32s %32s", addr, r, c);
756 }
757
connected(struct bt_conn * conn,uint8_t err)758 static void connected(struct bt_conn *conn, uint8_t err)
759 {
760 char addr[BT_ADDR_LE_STR_LEN];
761 struct bt_conn_info info;
762 int info_err;
763
764 conn_addr_str(conn, addr, sizeof(addr));
765
766 if (err) {
767 bt_shell_error("Failed to connect to %s 0x%02x %s", addr, err,
768 bt_hci_err_to_str(err));
769 goto done;
770 }
771
772 bt_shell_print("Connected: %s", addr);
773
774 info_err = bt_conn_get_info(conn, &info);
775 if (info_err != 0) {
776 bt_shell_error("Failed to connection information: %d", info_err);
777 goto done;
778 }
779
780 if (info.role == BT_CONN_ROLE_CENTRAL) {
781 if (default_conn != NULL) {
782 bt_conn_unref(default_conn);
783 }
784
785 default_conn = bt_conn_ref(conn);
786 } else if (info.role == BT_CONN_ROLE_PERIPHERAL) {
787 if (default_conn == NULL) {
788 default_conn = bt_conn_ref(conn);
789 }
790 }
791
792 done:
793 /* clear connection reference for sec mode 3 pairing */
794 if (pairing_conn) {
795 bt_conn_unref(pairing_conn);
796 pairing_conn = NULL;
797 }
798 }
799
disconnected_set_new_default_conn_cb(struct bt_conn * conn,void * user_data)800 static void disconnected_set_new_default_conn_cb(struct bt_conn *conn, void *user_data)
801 {
802 struct bt_conn_info info;
803
804 if (default_conn != NULL) {
805 /* nop */
806 return;
807 }
808
809 if (bt_conn_get_info(conn, &info) != 0) {
810 bt_shell_error("Unable to get info: conn %p", conn);
811 return;
812 }
813
814 if (info.state == BT_CONN_STATE_CONNECTED) {
815 default_conn = bt_conn_ref(conn);
816 }
817 }
818
disconnected(struct bt_conn * conn,uint8_t reason)819 static void disconnected(struct bt_conn *conn, uint8_t reason)
820 {
821 char addr[BT_ADDR_LE_STR_LEN];
822
823 conn_addr_str(conn, addr, sizeof(addr));
824 bt_shell_print("Disconnected: %s (reason 0x%02x)", addr, reason);
825
826 if (default_conn == conn) {
827 struct bt_conn_info info;
828 enum bt_conn_type conn_type = BT_CONN_TYPE_LE;
829
830 if (IS_ENABLED(CONFIG_BT_CLASSIC)) {
831 conn_type |= BT_CONN_TYPE_BR;
832 }
833
834 bt_conn_get_info(conn, &info);
835 bt_conn_unref(default_conn);
836 default_conn = NULL;
837
838 /* If we are connected to other devices, set one of them as default */
839 bt_conn_foreach(info.type, disconnected_set_new_default_conn_cb, NULL);
840 if (default_conn == NULL) {
841 bt_conn_foreach(conn_type, disconnected_set_new_default_conn_cb, NULL);
842 }
843
844 if (default_conn != NULL) {
845 conn_addr_str(default_conn, addr, sizeof(addr));
846 bt_shell_print("Selected conn is now: %s", addr);
847 }
848 }
849 }
850
le_param_req(struct bt_conn * conn,struct bt_le_conn_param * param)851 static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
852 {
853 bt_shell_print("LE conn param req: int (0x%04x, 0x%04x) lat %d to %d",
854 param->interval_min, param->interval_max,
855 param->latency, param->timeout);
856
857 return true;
858 }
859
le_param_updated(struct bt_conn * conn,uint16_t interval,uint16_t latency,uint16_t timeout)860 static void le_param_updated(struct bt_conn *conn, uint16_t interval,
861 uint16_t latency, uint16_t timeout)
862 {
863 bt_shell_print("LE conn param updated: int 0x%04x lat %d to %d",
864 interval, latency, timeout);
865 }
866
867 #if defined(CONFIG_BT_SMP)
identity_resolved(struct bt_conn * conn,const bt_addr_le_t * rpa,const bt_addr_le_t * identity)868 static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
869 const bt_addr_le_t *identity)
870 {
871 char addr_identity[BT_ADDR_LE_STR_LEN];
872 char addr_rpa[BT_ADDR_LE_STR_LEN];
873
874 bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
875 bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));
876
877 bt_shell_print("Identity resolved %s -> %s", addr_rpa, addr_identity);
878 }
879 #endif
880
881 #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CLASSIC)
security_err_str(enum bt_security_err err)882 static const char *security_err_str(enum bt_security_err err)
883 {
884 switch (err) {
885 case BT_SECURITY_ERR_SUCCESS:
886 return "Success";
887 case BT_SECURITY_ERR_AUTH_FAIL:
888 return "Authentication failure";
889 case BT_SECURITY_ERR_PIN_OR_KEY_MISSING:
890 return "PIN or key missing";
891 case BT_SECURITY_ERR_OOB_NOT_AVAILABLE:
892 return "OOB not available";
893 case BT_SECURITY_ERR_AUTH_REQUIREMENT:
894 return "Authentication requirements";
895 case BT_SECURITY_ERR_PAIR_NOT_SUPPORTED:
896 return "Pairing not supported";
897 case BT_SECURITY_ERR_PAIR_NOT_ALLOWED:
898 return "Pairing not allowed";
899 case BT_SECURITY_ERR_INVALID_PARAM:
900 return "Invalid parameters";
901 case BT_SECURITY_ERR_UNSPECIFIED:
902 return "Unspecified";
903 default:
904 return "Unknown";
905 }
906 }
907
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)908 static void security_changed(struct bt_conn *conn, bt_security_t level,
909 enum bt_security_err err)
910 {
911 char addr[BT_ADDR_LE_STR_LEN];
912
913 conn_addr_str(conn, addr, sizeof(addr));
914
915 if (!err) {
916 bt_shell_print("Security changed: %s level %u", addr, level);
917 } else {
918 bt_shell_print("Security failed: %s level %u "
919 "reason: %s (%d)",
920 addr, level, security_err_str(err), err);
921 }
922 }
923 #endif
924
925 #if defined(CONFIG_BT_REMOTE_INFO)
remote_info_available(struct bt_conn * conn,struct bt_conn_remote_info * remote_info)926 static void remote_info_available(struct bt_conn *conn,
927 struct bt_conn_remote_info *remote_info)
928 {
929 struct bt_conn_info info;
930
931 bt_conn_get_info(conn, &info);
932
933 if (IS_ENABLED(CONFIG_BT_REMOTE_VERSION)) {
934 bt_shell_print("Remote LMP version %s (0x%02x) subversion 0x%04x "
935 "manufacturer 0x%04x", bt_hci_get_ver_str(remote_info->version),
936 remote_info->version, remote_info->subversion,
937 remote_info->manufacturer);
938 }
939
940 if (info.type == BT_CONN_TYPE_LE) {
941 uint8_t features[8];
942 char features_str[2 * sizeof(features) + 1];
943
944 sys_memcpy_swap(features, remote_info->le.features,
945 sizeof(features));
946 bin2hex(features, sizeof(features),
947 features_str, sizeof(features_str));
948 bt_shell_print("LE Features: 0x%s ", features_str);
949 }
950 }
951 #endif /* defined(CONFIG_BT_REMOTE_INFO) */
952
953 #if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
le_data_len_updated(struct bt_conn * conn,struct bt_conn_le_data_len_info * info)954 void le_data_len_updated(struct bt_conn *conn,
955 struct bt_conn_le_data_len_info *info)
956 {
957 bt_shell_print("LE data len updated: TX (len: %d time: %d) RX (len: %d time: %d)",
958 info->tx_max_len, info->tx_max_time,
959 info->rx_max_len, info->rx_max_time);
960 }
961 #endif
962
963 #if defined(CONFIG_BT_USER_PHY_UPDATE)
le_phy_updated(struct bt_conn * conn,struct bt_conn_le_phy_info * info)964 void le_phy_updated(struct bt_conn *conn,
965 struct bt_conn_le_phy_info *info)
966 {
967 bt_shell_print("LE PHY updated: TX PHY %s, RX PHY %s",
968 phy2str(info->tx_phy), phy2str(info->rx_phy));
969 }
970 #endif
971
972 #if defined(CONFIG_BT_TRANSMIT_POWER_CONTROL)
tx_power_report(struct bt_conn * conn,const struct bt_conn_le_tx_power_report * report)973 void tx_power_report(struct bt_conn *conn,
974 const struct bt_conn_le_tx_power_report *report)
975 {
976 bt_shell_print("Tx Power Report: Reason: %s, PHY: %s, Tx Power Level: %d",
977 tx_power_report_reason2str(report->reason), tx_pwr_ctrl_phy2str(report->phy),
978 report->tx_power_level);
979 bt_shell_print("Tx Power Level Flag Info: %s, Delta: %d",
980 tx_power_flag2str(report->tx_power_level_flag), report->delta);
981 }
982 #endif
983
984 #if defined(CONFIG_BT_PATH_LOSS_MONITORING)
path_loss_threshold_report(struct bt_conn * conn,const struct bt_conn_le_path_loss_threshold_report * report)985 void path_loss_threshold_report(struct bt_conn *conn,
986 const struct bt_conn_le_path_loss_threshold_report *report)
987 {
988 bt_shell_print("Path Loss Threshold event: Zone: %s, Path loss dbm: %d",
989 plm_report_zone_str(report->zone), report->path_loss);
990 }
991 #endif
992
993 #if defined(CONFIG_BT_SUBRATING)
subrate_changed(struct bt_conn * conn,const struct bt_conn_le_subrate_changed * params)994 void subrate_changed(struct bt_conn *conn,
995 const struct bt_conn_le_subrate_changed *params)
996 {
997 if (params->status == BT_HCI_ERR_SUCCESS) {
998 bt_shell_print("Subrate parameters changed: "
999 "Subrate Factor: %d "
1000 "Continuation Number: %d "
1001 "Peripheral latency: 0x%04x "
1002 "Supervision timeout: 0x%04x (%d ms)",
1003 params->factor,
1004 params->continuation_number,
1005 params->peripheral_latency,
1006 params->supervision_timeout,
1007 params->supervision_timeout * 10);
1008 } else {
1009 bt_shell_print("Subrate change failed (HCI status 0x%02x)", params->status);
1010 }
1011 }
1012
1013 #if defined(CONFIG_BT_SHORTER_CONNECTION_INTERVALS)
conn_rate_changed(struct bt_conn * conn,uint8_t status,const struct bt_conn_le_conn_rate_changed * params)1014 static void conn_rate_changed(struct bt_conn *conn, uint8_t status,
1015 const struct bt_conn_le_conn_rate_changed *params)
1016 {
1017 if (status == BT_HCI_ERR_SUCCESS) {
1018 bt_shell_print("Connection rate parameters changed: "
1019 "Connection Interval: %u us "
1020 "Subrate Factor: %d "
1021 "Peripheral latency: 0x%04x "
1022 "Continuation Number: %d "
1023 "Supervision timeout: 0x%04x (%d ms)",
1024 params->interval_us,
1025 params->subrate_factor,
1026 params->peripheral_latency,
1027 params->continuation_number,
1028 params->supervision_timeout_10ms,
1029 params->supervision_timeout_10ms * 10);
1030 } else {
1031 bt_shell_print("Connection rate change failed (HCI status 0x%02x)", status);
1032 }
1033 }
1034 #endif /* CONFIG_BT_SHORTER_CONNECTION_INTERVALS */
1035 #endif /* CONFIG_BT_SUBRATING */
1036
1037 #if defined(CONFIG_BT_LE_EXTENDED_FEAT_SET)
read_all_remote_feat_complete(struct bt_conn * conn,const struct bt_conn_le_read_all_remote_feat_complete * params)1038 void read_all_remote_feat_complete(struct bt_conn *conn,
1039 const struct bt_conn_le_read_all_remote_feat_complete *params)
1040 {
1041 if (params->status == BT_HCI_ERR_SUCCESS) {
1042 uint8_t number_of_bytes = BT_HCI_LE_BYTES_PAGE_0_FEATURE_PAGE;
1043
1044 if (params->max_valid_page > 0) {
1045 number_of_bytes +=
1046 (params->max_valid_page * BT_HCI_LE_BYTES_PER_FEATURE_PAGE);
1047 }
1048
1049 bt_shell_fprintf_print(
1050 "Read all remote features complete, Max Remote Page %d, LE Features: 0x",
1051 params->max_remote_page);
1052
1053 for (int i = number_of_bytes - 1; i >= 0; i--) {
1054 uint8_t features = params->features[i];
1055 char features_str[(2 * sizeof(uint8_t)) + 1];
1056
1057 bin2hex(&features, sizeof(features), features_str, sizeof(features_str));
1058 bt_shell_fprintf_print("%s", features_str);
1059 }
1060 bt_shell_fprintf_print("\n");
1061 } else {
1062 bt_shell_print("Read all remote features failed (HCI status 0x%02x)",
1063 params->status);
1064 }
1065 }
1066 #endif
1067
1068 #if defined(CONFIG_BT_FRAME_SPACE_UPDATE)
frame_space_initiator_to_str(enum bt_conn_le_frame_space_update_initiator initiator)1069 static const char *frame_space_initiator_to_str(
1070 enum bt_conn_le_frame_space_update_initiator initiator)
1071 {
1072 switch (initiator) {
1073 case BT_CONN_LE_FRAME_SPACE_UPDATE_INITIATOR_LOCAL_HOST:
1074 return "Local Host";
1075 case BT_CONN_LE_FRAME_SPACE_UPDATE_INITIATOR_LOCAL_CONTROLLER:
1076 return "Local Controller";
1077 case BT_CONN_LE_FRAME_SPACE_UPDATE_INITIATOR_PEER:
1078 return "Peer";
1079 default:
1080 return "Unknown";
1081 }
1082 }
1083
frame_space_updated(struct bt_conn * conn,const struct bt_conn_le_frame_space_updated * params)1084 void frame_space_updated(struct bt_conn *conn,
1085 const struct bt_conn_le_frame_space_updated *params)
1086 {
1087 if (params->status != BT_HCI_ERR_SUCCESS) {
1088 bt_shell_print("Frame space update failed (HCI status 0x%02x)",
1089 params->status);
1090 return;
1091 }
1092
1093 bt_shell_print(
1094 "Frame space updated: frame space %d us, PHYs 0x%04x, spacing types 0x%04x, initiator %s",
1095 params->frame_space, params->phys, params->spacing_types,
1096 frame_space_initiator_to_str(params->initiator));
1097 }
1098 #endif
1099
1100 #if defined(CONFIG_BT_CHANNEL_SOUNDING)
print_remote_cs_capabilities(struct bt_conn * conn,uint8_t status,struct bt_conn_le_cs_capabilities * params)1101 void print_remote_cs_capabilities(struct bt_conn *conn,
1102 uint8_t status,
1103 struct bt_conn_le_cs_capabilities *params)
1104 {
1105 if (status != BT_HCI_ERR_SUCCESS) {
1106 bt_shell_print("Read Remote CS Capabilities failed (HCI status 0x%02x)", status);
1107 return;
1108 }
1109
1110 bt_shell_print(
1111 "Received remote channel sounding capabilities:\n"
1112 "- Num CS configurations: %d\n"
1113 "- Max consecutive CS procedures: %d\n"
1114 "- Num antennas supported: %d\n"
1115 "- Max antenna paths supported: %d\n"
1116 "- Initiator role supported: %s\n"
1117 "- Reflector role supported: %s\n"
1118 "- Mode 3 supported: %s\n"
1119 "- RTT AA only supported: %s\n"
1120 "- RTT AA only is 10ns precise: %s\n"
1121 "- RTT AA only N: %d\n"
1122 "- RTT sounding supported: %s\n"
1123 "- RTT sounding is 10ns precise: %s\n"
1124 "- RTT sounding N: %d\n"
1125 "- RTT random payload supported: %s\n"
1126 "- RTT random payload is 10ns precise: %s\n"
1127 "- RTT random payload N: %d\n"
1128 "- Phase-based NADM with sounding sequences supported: %s\n"
1129 "- Phase-based NADM with random sequences supported: %s\n"
1130 "- CS Sync 2M PHY supported: %s\n"
1131 "- CS Sync 2M 2BT PHY supported: %s\n"
1132 "- CS without transmitter FAE supported: %s\n"
1133 "- Channel selection algorithm #3c supported: %s\n"
1134 "- Phase-based ranging from RTT sounding sequence supported: %s\n"
1135 "- T_IP1 times supported: 0x%04x\n"
1136 "- T_IP2 times supported: 0x%04x\n"
1137 "- T_FCS times supported: 0x%04x\n"
1138 "- T_PM times supported: 0x%04x\n"
1139 "- T_SW time supported: %d us\n"
1140 "- TX SNR capability: 0x%02x",
1141 params->num_config_supported, params->max_consecutive_procedures_supported,
1142 params->num_antennas_supported, params->max_antenna_paths_supported,
1143 params->initiator_supported ? "Yes" : "No",
1144 params->reflector_supported ? "Yes" : "No", params->mode_3_supported ? "Yes" : "No",
1145 params->rtt_aa_only_precision == BT_CONN_LE_CS_RTT_AA_ONLY_NOT_SUPP ? "No" : "Yes",
1146 params->rtt_aa_only_precision == BT_CONN_LE_CS_RTT_AA_ONLY_10NS ? "Yes" : "No",
1147 params->rtt_aa_only_n,
1148 params->rtt_sounding_precision == BT_CONN_LE_CS_RTT_SOUNDING_NOT_SUPP ? "No"
1149 : "Yes",
1150 params->rtt_sounding_precision == BT_CONN_LE_CS_RTT_SOUNDING_10NS ? "Yes" : "No",
1151 params->rtt_sounding_n,
1152 params->rtt_random_payload_precision == BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_NOT_SUPP
1153 ? "No"
1154 : "Yes",
1155 params->rtt_random_payload_precision == BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_10NS
1156 ? "Yes"
1157 : "No",
1158 params->rtt_random_payload_n,
1159 params->phase_based_nadm_sounding_supported ? "Yes" : "No",
1160 params->phase_based_nadm_random_supported ? "Yes" : "No",
1161 params->cs_sync_2m_phy_supported ? "Yes" : "No",
1162 params->cs_sync_2m_2bt_phy_supported ? "Yes" : "No",
1163 params->cs_without_fae_supported ? "Yes" : "No",
1164 params->chsel_alg_3c_supported ? "Yes" : "No",
1165 params->pbr_from_rtt_sounding_seq_supported ? "Yes" : "No",
1166 params->t_ip1_times_supported, params->t_ip2_times_supported,
1167 params->t_fcs_times_supported, params->t_pm_times_supported, params->t_sw_time,
1168 params->tx_snr_capability);
1169 }
1170
print_remote_cs_fae_table(struct bt_conn * conn,uint8_t status,struct bt_conn_le_cs_fae_table * params)1171 void print_remote_cs_fae_table(struct bt_conn *conn,
1172 uint8_t status,
1173 struct bt_conn_le_cs_fae_table *params)
1174 {
1175 if (status != BT_HCI_ERR_SUCCESS) {
1176 bt_shell_print("Read Remote CS FAE Table failed (HCI status 0x%02x)", status);
1177 return;
1178 }
1179
1180 bt_shell_print("Received FAE Table: ");
1181 bt_shell_hexdump(params->remote_fae_table, 72);
1182 }
1183
le_cs_config_created(struct bt_conn * conn,uint8_t status,struct bt_conn_le_cs_config * config)1184 static void le_cs_config_created(struct bt_conn *conn,
1185 uint8_t status,
1186 struct bt_conn_le_cs_config *config)
1187 {
1188 if (status != BT_HCI_ERR_SUCCESS) {
1189 bt_shell_print("Create CS Config failed (HCI status 0x%02x)", status);
1190 return;
1191 }
1192
1193 const char *mode_str[5] = {"Unused", "1 (RTT)", "2 (PBR)", "3 (RTT + PBR)", "Invalid"};
1194 const char *role_str[3] = {"Initiator", "Reflector", "Invalid"};
1195 const char *rtt_type_str[8] = {"AA only", "32-bit sounding", "96-bit sounding",
1196 "32-bit random", "64-bit random", "96-bit random",
1197 "128-bit random", "Invalid"};
1198 const char *phy_str[4] = {"Invalid", "LE 1M PHY", "LE 2M PHY", "LE 2M 2BT PHY"};
1199 const char *chsel_type_str[3] = {"Algorithm #3b", "Algorithm #3c", "Invalid"};
1200 const char *ch3c_shape_str[3] = {"Hat shape", "X shape", "Invalid"};
1201
1202 uint8_t main_mode_type = BT_CONN_LE_CS_MODE_MAIN_MODE_PART(config->mode);
1203 uint8_t sub_mode_type = BT_CONN_LE_CS_MODE_SUB_MODE_PART(config->mode);
1204 uint8_t main_mode_idx = main_mode_type > 0 && main_mode_type < 4
1205 ? main_mode_type
1206 : 4;
1207 uint8_t sub_mode_idx = sub_mode_type;
1208 uint8_t role_idx = MIN(config->role, 2);
1209 uint8_t rtt_type_idx = MIN(config->rtt_type, 7);
1210 uint8_t phy_idx =
1211 config->cs_sync_phy > 0 && config->cs_sync_phy < 4 ? config->cs_sync_phy : 0;
1212 uint8_t chsel_type_idx = MIN(config->channel_selection_type, 2);
1213 uint8_t ch3c_shape_idx = MIN(config->ch3c_shape, 2);
1214
1215 bt_shell_print(
1216 "New CS config created:\n"
1217 "- ID: %d\n"
1218 "- Role: %s\n"
1219 "- Main mode: %s\n"
1220 "- Sub mode: %s\n"
1221 "- RTT type: %s\n"
1222 "- Main mode steps: %d - %d\n"
1223 "- Main mode repetition: %d\n"
1224 "- Mode 0 steps: %d\n"
1225 "- CS sync PHY: %s\n"
1226 "- T_IP1 time: %d\n"
1227 "- T_IP2 time: %d\n"
1228 "- T_FCS time: %d\n"
1229 "- T_PM time: %d\n"
1230 "- Channel map: 0x%08X%08X%04X\n"
1231 "- Channel map repetition: %d\n"
1232 "- Channel selection type: %s\n"
1233 "- Ch3c shape: %s\n"
1234 "- Ch3c jump: %d\n",
1235 config->id, role_str[role_idx], mode_str[main_mode_idx], mode_str[sub_mode_idx],
1236 rtt_type_str[rtt_type_idx], config->min_main_mode_steps,
1237 config->max_main_mode_steps, config->main_mode_repetition, config->mode_0_steps,
1238 phy_str[phy_idx], config->t_ip1_time_us, config->t_ip2_time_us,
1239 config->t_fcs_time_us, config->t_pm_time_us,
1240 sys_get_le32(&config->channel_map[6]), sys_get_le32(&config->channel_map[2]),
1241 sys_get_le16(&config->channel_map[0]), config->channel_map_repetition,
1242 chsel_type_str[chsel_type_idx], ch3c_shape_str[ch3c_shape_idx],
1243 config->ch3c_jump);
1244 }
1245
le_cs_config_removed(struct bt_conn * conn,uint8_t config_id)1246 static void le_cs_config_removed(struct bt_conn *conn, uint8_t config_id)
1247 {
1248 bt_shell_print("CS config %d is removed", config_id);
1249 }
1250 #endif
1251
1252 BT_CONN_CB_DEFINE(conn_callbacks) = {
1253 .connected = connected,
1254 .disconnected = disconnected,
1255 .le_param_req = le_param_req,
1256 .le_param_updated = le_param_updated,
1257 #if defined(CONFIG_BT_SMP)
1258 .identity_resolved = identity_resolved,
1259 #endif
1260 #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CLASSIC)
1261 .security_changed = security_changed,
1262 #endif
1263 #if defined(CONFIG_BT_REMOTE_INFO)
1264 .remote_info_available = remote_info_available,
1265 #endif
1266 #if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
1267 .le_data_len_updated = le_data_len_updated,
1268 #endif
1269 #if defined(CONFIG_BT_USER_PHY_UPDATE)
1270 .le_phy_updated = le_phy_updated,
1271 #endif
1272 #if defined(CONFIG_BT_TRANSMIT_POWER_CONTROL)
1273 .tx_power_report = tx_power_report,
1274 #endif
1275 #if defined(CONFIG_BT_PATH_LOSS_MONITORING)
1276 .path_loss_threshold_report = path_loss_threshold_report,
1277 #endif
1278 #if defined(CONFIG_BT_SUBRATING)
1279 .subrate_changed = subrate_changed,
1280 #endif
1281 #if defined(CONFIG_BT_SHORTER_CONNECTION_INTERVALS)
1282 .conn_rate_changed = conn_rate_changed,
1283 #endif
1284 #if defined(CONFIG_BT_LE_EXTENDED_FEAT_SET)
1285 .read_all_remote_feat_complete = read_all_remote_feat_complete,
1286 #endif
1287 #if defined(CONFIG_BT_FRAME_SPACE_UPDATE)
1288 .frame_space_updated = frame_space_updated,
1289 #endif
1290 #if defined(CONFIG_BT_CHANNEL_SOUNDING)
1291 .le_cs_read_remote_capabilities_complete = print_remote_cs_capabilities,
1292 .le_cs_read_remote_fae_table_complete = print_remote_cs_fae_table,
1293 .le_cs_config_complete = le_cs_config_created,
1294 .le_cs_config_removed = le_cs_config_removed,
1295 #endif
1296 #if defined(CONFIG_BT_CLASSIC)
1297 .role_changed = role_changed,
1298 #endif
1299 };
1300 #endif /* CONFIG_BT_CONN */
1301
1302 #if defined(CONFIG_BT_OBSERVER)
1303 static struct bt_le_scan_cb scan_callbacks = {
1304 .recv = scan_recv,
1305 .timeout = scan_timeout,
1306 };
1307 #endif /* defined(CONFIG_BT_OBSERVER) */
1308
1309 #if defined(CONFIG_BT_EXT_ADV)
1310 #if defined(CONFIG_BT_BROADCASTER)
1311 static struct bt_le_ext_adv_cb adv_callbacks = {
1312 .sent = adv_sent,
1313 .scanned = adv_scanned,
1314 #if defined(CONFIG_BT_PERIPHERAL)
1315 .connected = adv_connected,
1316 #endif /* CONFIG_BT_PERIPHERAL */
1317 #if defined(CONFIG_BT_PRIVACY)
1318 .rpa_expired = adv_rpa_expired,
1319 #endif /* defined(CONFIG_BT_PRIVACY) */
1320
1321 };
1322 #endif /* CONFIG_BT_BROADCASTER */
1323 #endif /* CONFIG_BT_EXT_ADV */
1324
1325 #if defined(CONFIG_BT_PER_ADV_SYNC)
1326 struct bt_le_per_adv_sync *per_adv_syncs[CONFIG_BT_PER_ADV_SYNC_MAX];
1327 size_t selected_per_adv_sync;
1328
per_adv_sync_sync_cb(struct bt_le_per_adv_sync * sync,struct bt_le_per_adv_sync_synced_info * info)1329 static void per_adv_sync_sync_cb(struct bt_le_per_adv_sync *sync,
1330 struct bt_le_per_adv_sync_synced_info *info)
1331 {
1332 const bool is_past_peer = info->conn != NULL;
1333 char le_addr[BT_ADDR_LE_STR_LEN];
1334 char past_peer[BT_ADDR_LE_STR_LEN];
1335
1336 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
1337
1338 if (is_past_peer) {
1339 conn_addr_str(info->conn, past_peer, sizeof(past_peer));
1340 }
1341
1342 bt_shell_print("PER_ADV_SYNC[%u]: [DEVICE]: %s synced, "
1343 "Interval 0x%04x (%u us), PHY %s, SD 0x%04X, PAST peer %s",
1344 bt_le_per_adv_sync_get_index(sync), le_addr,
1345 info->interval, BT_CONN_INTERVAL_TO_US(info->interval),
1346 phy2str(info->phy), info->service_data,
1347 is_past_peer ? past_peer : "not present");
1348
1349 if (info->conn) { /* if from PAST */
1350 for (int i = 0; i < ARRAY_SIZE(per_adv_syncs); i++) {
1351 if (!per_adv_syncs[i]) {
1352 per_adv_syncs[i] = sync;
1353 break;
1354 }
1355 }
1356 }
1357 }
1358
per_adv_sync_terminated_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_term_info * info)1359 static void per_adv_sync_terminated_cb(
1360 struct bt_le_per_adv_sync *sync,
1361 const struct bt_le_per_adv_sync_term_info *info)
1362 {
1363 char le_addr[BT_ADDR_LE_STR_LEN];
1364
1365 for (int i = 0; i < ARRAY_SIZE(per_adv_syncs); i++) {
1366 if (per_adv_syncs[i] == sync) {
1367 per_adv_syncs[i] = NULL;
1368 break;
1369 }
1370 }
1371
1372 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
1373 bt_shell_print("PER_ADV_SYNC[%u]: [DEVICE]: %s sync terminated",
1374 bt_le_per_adv_sync_get_index(sync), le_addr);
1375 }
1376
per_adv_sync_recv_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_recv_info * info,struct net_buf_simple * buf)1377 static void per_adv_sync_recv_cb(
1378 struct bt_le_per_adv_sync *sync,
1379 const struct bt_le_per_adv_sync_recv_info *info,
1380 struct net_buf_simple *buf)
1381 {
1382 char le_addr[BT_ADDR_LE_STR_LEN];
1383
1384 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
1385 bt_shell_print("PER_ADV_SYNC[%u]: [DEVICE]: %s, tx_power %i, "
1386 "RSSI %i, CTE %u, data length %u",
1387 bt_le_per_adv_sync_get_index(sync), le_addr, info->tx_power,
1388 info->rssi, info->cte_type, buf->len);
1389 }
1390
per_adv_sync_biginfo_cb(struct bt_le_per_adv_sync * sync,const struct bt_iso_biginfo * biginfo)1391 static void per_adv_sync_biginfo_cb(struct bt_le_per_adv_sync *sync,
1392 const struct bt_iso_biginfo *biginfo)
1393 {
1394 char le_addr[BT_ADDR_LE_STR_LEN];
1395
1396 bt_addr_le_to_str(biginfo->addr, le_addr, sizeof(le_addr));
1397 bt_shell_print("BIG_INFO PER_ADV_SYNC[%u]: [DEVICE]: %s, sid 0x%02x, num_bis %u, "
1398 "nse 0x%02x, interval 0x%04x (%u us), bn 0x%02x, pto 0x%02x, irc 0x%02x, "
1399 "max_pdu 0x%04x, sdu_interval 0x%04x, max_sdu 0x%04x, phy %s, framing 0x%02x, "
1400 "%sencrypted",
1401 bt_le_per_adv_sync_get_index(sync), le_addr, biginfo->sid, biginfo->num_bis,
1402 biginfo->sub_evt_count, biginfo->iso_interval,
1403 BT_CONN_INTERVAL_TO_US(biginfo->iso_interval), biginfo->burst_number,
1404 biginfo->offset, biginfo->rep_count, biginfo->max_pdu, biginfo->sdu_interval,
1405 biginfo->max_sdu, phy2str(biginfo->phy), biginfo->framing,
1406 biginfo->encryption ? "" : "not ");
1407 }
1408
1409 static struct bt_le_per_adv_sync_cb per_adv_sync_cb = {
1410 .synced = per_adv_sync_sync_cb,
1411 .term = per_adv_sync_terminated_cb,
1412 .recv = per_adv_sync_recv_cb,
1413 .biginfo = per_adv_sync_biginfo_cb,
1414 };
1415 #endif /* CONFIG_BT_PER_ADV_SYNC */
1416
bt_ready(int err)1417 static void bt_ready(int err)
1418 {
1419 if (err) {
1420 bt_shell_error("Bluetooth init failed (err %d)", err);
1421 return;
1422 }
1423
1424 bt_shell_print("Bluetooth initialized");
1425
1426 if (IS_ENABLED(CONFIG_SETTINGS) && !no_settings_load) {
1427 settings_load();
1428 bt_shell_print("Settings Loaded");
1429 }
1430
1431 if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
1432 bt_le_oob_set_legacy_flag(true);
1433 }
1434
1435 #if defined(CONFIG_BT_OBSERVER)
1436 bt_le_scan_cb_register(&scan_callbacks);
1437 #endif
1438
1439 #if defined(CONFIG_BT_CONN)
1440 default_conn = NULL;
1441 #endif /* CONFIG_BT_CONN */
1442
1443 #if defined(CONFIG_BT_PER_ADV_SYNC)
1444 bt_le_per_adv_sync_cb_register(&per_adv_sync_cb);
1445 #endif /* CONFIG_BT_PER_ADV_SYNC */
1446
1447 #if defined(CONFIG_BT_SMP)
1448 bt_conn_auth_info_cb_register(&auth_info_cb);
1449 #endif /* CONFIG_BT_SMP */
1450 }
1451
cmd_init(const struct shell * sh,size_t argc,char * argv[])1452 static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
1453 {
1454 int err;
1455 bool sync = false;
1456
1457 for (size_t argn = 1; argn < argc; argn++) {
1458 const char *arg = argv[argn];
1459
1460 if (!strcmp(arg, "no-settings-load")) {
1461 no_settings_load = true;
1462 } else if (!strcmp(arg, "sync")) {
1463 sync = true;
1464 } else {
1465 shell_help(sh);
1466 return SHELL_CMD_HELP_PRINTED;
1467 }
1468 }
1469
1470 if (sync) {
1471 err = bt_enable(NULL);
1472 bt_ready(err);
1473 } else {
1474 err = bt_enable(bt_ready);
1475 if (err) {
1476 shell_error(sh, "Bluetooth init failed (err %d)", err);
1477 }
1478 }
1479
1480 return err;
1481 }
1482
cmd_disable(const struct shell * sh,size_t argc,char * argv[])1483 static int cmd_disable(const struct shell *sh, size_t argc, char *argv[])
1484 {
1485 return bt_disable();
1486 }
1487
1488 #ifdef CONFIG_SETTINGS
cmd_settings_load(const struct shell * sh,size_t argc,char * argv[])1489 static int cmd_settings_load(const struct shell *sh, size_t argc,
1490 char *argv[])
1491 {
1492 int err;
1493
1494 err = settings_load();
1495 if (err) {
1496 shell_error(sh, "Settings load failed (err %d)", err);
1497 return err;
1498 }
1499
1500 shell_print(sh, "Settings loaded");
1501 return 0;
1502 }
1503 #endif
1504
1505 #if defined(CONFIG_BT_HCI)
cmd_hci_cmd(const struct shell * sh,size_t argc,char * argv[])1506 static int cmd_hci_cmd(const struct shell *sh, size_t argc, char *argv[])
1507 {
1508 uint8_t ogf;
1509 uint16_t ocf;
1510 struct net_buf *buf = NULL, *rsp;
1511 int err;
1512 static uint8_t hex_data[HCI_CMD_MAX_PARAM];
1513 int hex_data_len;
1514
1515 hex_data_len = 0;
1516 ogf = strtoul(argv[1], NULL, 16);
1517 ocf = strtoul(argv[2], NULL, 16);
1518
1519 if (argc > 3) {
1520 size_t len;
1521
1522 if (strlen(argv[3]) > 2 * HCI_CMD_MAX_PARAM) {
1523 shell_error(sh, "Data field too large\n");
1524 return -ENOEXEC;
1525 }
1526
1527 len = hex2bin(argv[3], strlen(argv[3]), &hex_data[hex_data_len],
1528 sizeof(hex_data) - hex_data_len);
1529 if (!len) {
1530 shell_error(sh, "HCI command illegal data field\n");
1531 return -ENOEXEC;
1532 }
1533
1534 buf = bt_hci_cmd_alloc(K_FOREVER);
1535 if (buf == NULL) {
1536 shell_error(sh, "Unable to allocate HCI buffer");
1537 return -ENOMEM;
1538 }
1539
1540 net_buf_add_mem(buf, hex_data, len);
1541 }
1542
1543 err = bt_hci_cmd_send_sync(BT_OP(ogf, ocf), buf, &rsp);
1544 if (err) {
1545 shell_error(sh, "HCI command failed (err %d)", err);
1546 return err;
1547 } else {
1548 shell_hexdump(sh, rsp->data, rsp->len);
1549 net_buf_unref(rsp);
1550 }
1551
1552 return 0;
1553 }
1554 #endif /* CONFIG_BT_HCI */
1555
cmd_name(const struct shell * sh,size_t argc,char * argv[])1556 static int cmd_name(const struct shell *sh, size_t argc, char *argv[])
1557 {
1558 int err;
1559
1560 if (argc < 2) {
1561 shell_print(sh, "Bluetooth Local Name: %s", bt_get_name());
1562 return 0;
1563 }
1564
1565 err = bt_set_name(argv[1]);
1566 if (err) {
1567 shell_error(sh, "Unable to set name %s (err %d)", argv[1], err);
1568 return err;
1569 }
1570
1571 return 0;
1572 }
1573
cmd_appearance(const struct shell * sh,size_t argc,char * argv[])1574 static int cmd_appearance(const struct shell *sh, size_t argc, char *argv[])
1575 {
1576 if (argc == 1) {
1577 shell_print(sh, "Bluetooth Appearance: 0x%04x", bt_get_appearance());
1578 return 0;
1579 }
1580
1581 #if defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC)
1582 uint16_t app;
1583 int err = 0;
1584 const char *val;
1585
1586 val = argv[1];
1587
1588 if (strlen(val) != 6 || strncmp(val, "0x", 2)) {
1589 shell_error(sh, "Argument must be 0x followed by exactly 4 hex digits.");
1590 return -EINVAL;
1591 }
1592
1593 app = shell_strtoul(val, 16, &err);
1594 if (err) {
1595 shell_error(sh, "Argument must be 0x followed by exactly 4 hex digits.");
1596 return -EINVAL;
1597 }
1598
1599 err = bt_set_appearance(app);
1600 if (err) {
1601 shell_error(sh, "bt_set_appearance(0x%04x) failed with err %d", app, err);
1602 return err;
1603 }
1604 #endif /* defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC) */
1605
1606 return 0;
1607 }
1608
cmd_id_create(const struct shell * sh,size_t argc,char * argv[])1609 static int cmd_id_create(const struct shell *sh, size_t argc, char *argv[])
1610 {
1611 char addr_str[BT_ADDR_LE_STR_LEN];
1612 bt_addr_le_t addr;
1613 int err;
1614
1615 if (argc > 1) {
1616 err = bt_addr_le_from_str(argv[1], "random", &addr);
1617 if (err) {
1618 shell_error(sh, "Invalid address");
1619 }
1620 } else {
1621 bt_addr_le_copy(&addr, BT_ADDR_LE_ANY);
1622 }
1623
1624 err = bt_id_create(&addr, NULL);
1625 if (err < 0) {
1626 shell_error(sh, "Creating new ID failed (err %d)", err);
1627 return err;
1628 }
1629
1630 bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));
1631 shell_print(sh, "New identity (%d) created: %s", err, addr_str);
1632
1633 return 0;
1634 }
1635
cmd_id_reset(const struct shell * sh,size_t argc,char * argv[])1636 static int cmd_id_reset(const struct shell *sh, size_t argc, char *argv[])
1637 {
1638 char addr_str[BT_ADDR_LE_STR_LEN];
1639 bt_addr_le_t addr;
1640 uint8_t id;
1641 int err;
1642
1643 if (argc < 2) {
1644 shell_error(sh, "Identity handle not specified");
1645 return -ENOEXEC;
1646 }
1647
1648 id = strtol(argv[1], NULL, 10);
1649
1650 if (argc > 2) {
1651 err = bt_addr_le_from_str(argv[2], "random", &addr);
1652 if (err) {
1653 shell_print(sh, "Invalid address");
1654 return err;
1655 }
1656 } else {
1657 bt_addr_le_copy(&addr, BT_ADDR_LE_ANY);
1658 }
1659
1660 err = bt_id_reset(id, &addr, NULL);
1661 if (err < 0) {
1662 shell_print(sh, "Resetting ID %u failed (err %d)", id, err);
1663 return err;
1664 }
1665
1666 bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));
1667 shell_print(sh, "Identity %u reset: %s", id, addr_str);
1668
1669 return 0;
1670 }
1671
cmd_id_delete(const struct shell * sh,size_t argc,char * argv[])1672 static int cmd_id_delete(const struct shell *sh, size_t argc, char *argv[])
1673 {
1674 uint8_t id;
1675 int err;
1676
1677 if (argc < 2) {
1678 shell_error(sh, "Identity handle not specified");
1679 return -ENOEXEC;
1680 }
1681
1682 id = strtol(argv[1], NULL, 10);
1683
1684 err = bt_id_delete(id);
1685 if (err < 0) {
1686 shell_error(sh, "Deleting ID %u failed (err %d)", id, err);
1687 return err;
1688 }
1689
1690 shell_print(sh, "Identity %u deleted", id);
1691
1692 return 0;
1693 }
1694
cmd_id_show(const struct shell * sh,size_t argc,char * argv[])1695 static int cmd_id_show(const struct shell *sh, size_t argc, char *argv[])
1696 {
1697 bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
1698 size_t i, count = CONFIG_BT_ID_MAX;
1699
1700 bt_id_get(addrs, &count);
1701
1702 for (i = 0; i < count; i++) {
1703 char addr_str[BT_ADDR_LE_STR_LEN];
1704
1705 bt_addr_le_to_str(&addrs[i], addr_str, sizeof(addr_str));
1706 shell_print(sh, "%s%zu: %s", i == selected_id ? "*" : " ", i, addr_str);
1707 }
1708
1709 return 0;
1710 }
1711
cmd_id_select(const struct shell * sh,size_t argc,char * argv[])1712 static int cmd_id_select(const struct shell *sh, size_t argc, char *argv[])
1713 {
1714 char addr_str[BT_ADDR_LE_STR_LEN];
1715 bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
1716 size_t count = CONFIG_BT_ID_MAX;
1717 uint8_t id;
1718
1719 id = strtol(argv[1], NULL, 10);
1720
1721 bt_id_get(addrs, &count);
1722 if (count <= id) {
1723 shell_error(sh, "Invalid identity");
1724 return -ENOEXEC;
1725 }
1726
1727 bt_addr_le_to_str(&addrs[id], addr_str, sizeof(addr_str));
1728 shell_print(sh, "Selected identity: %s", addr_str);
1729 selected_id = id;
1730
1731 return 0;
1732 }
1733
1734 #if defined(CONFIG_BT_OBSERVER)
cmd_active_scan_on(const struct shell * sh,uint32_t options,uint16_t timeout)1735 static int cmd_active_scan_on(const struct shell *sh, uint32_t options,
1736 uint16_t timeout)
1737 {
1738 int err;
1739 struct bt_le_scan_param param = {
1740 .type = BT_LE_SCAN_TYPE_ACTIVE,
1741 .options = BT_LE_SCAN_OPT_NONE,
1742 .interval = BT_GAP_SCAN_FAST_INTERVAL,
1743 .window = BT_GAP_SCAN_FAST_WINDOW,
1744 .timeout = 0, };
1745
1746 param.options |= options;
1747
1748 err = bt_le_scan_start(¶m, NULL);
1749 if (err) {
1750 shell_error(sh, "Bluetooth set active scan failed (err %d)", err);
1751 return err;
1752 } else {
1753 shell_print(sh, "Bluetooth active scan enabled");
1754 }
1755
1756 if (timeout != 0) {
1757 /* Schedule the k_work to act as a timeout */
1758 (void)k_work_reschedule(&active_scan_timeout_work, K_SECONDS(timeout));
1759 }
1760
1761 return 0;
1762 }
1763
cmd_passive_scan_on(const struct shell * sh,uint32_t options,uint16_t timeout)1764 static int cmd_passive_scan_on(const struct shell *sh, uint32_t options,
1765 uint16_t timeout)
1766 {
1767 struct bt_le_scan_param param = {
1768 .type = BT_LE_SCAN_TYPE_PASSIVE,
1769 .options = BT_LE_SCAN_OPT_NONE,
1770 .interval = 0x10,
1771 .window = 0x10,
1772 .timeout = timeout, };
1773 int err;
1774
1775 param.options |= options;
1776
1777 err = bt_le_scan_start(¶m, NULL);
1778 if (err) {
1779 shell_error(sh, "Bluetooth set passive scan failed (err %d)", err);
1780 return err;
1781 } else {
1782 shell_print(sh, "Bluetooth passive scan enabled");
1783 }
1784
1785 return 0;
1786 }
1787
bt_do_scan_off(void)1788 static int bt_do_scan_off(void)
1789 {
1790 int err;
1791
1792 /* Cancel the potentially pending scan timeout work */
1793 (void)k_work_cancel_delayable(&active_scan_timeout_work);
1794
1795 err = bt_le_scan_stop();
1796
1797 return err;
1798 }
1799
cmd_scan_off(const struct shell * sh)1800 static int cmd_scan_off(const struct shell *sh)
1801 {
1802 int err;
1803
1804 err = bt_do_scan_off();
1805 if (err) {
1806 shell_error(sh, "Stopping scanning failed (err %d)", err);
1807 return err;
1808 } else {
1809 shell_print(sh, "Scan successfully stopped");
1810 }
1811
1812 return 0;
1813 }
1814
cmd_scan(const struct shell * sh,size_t argc,char * argv[])1815 static int cmd_scan(const struct shell *sh, size_t argc, char *argv[])
1816 {
1817 const char *action;
1818 uint32_t options = 0;
1819 uint16_t timeout = 0;
1820
1821 /* Parse duplicate filtering data */
1822 for (size_t argn = 2; argn < argc; argn++) {
1823 const char *arg = argv[argn];
1824
1825 if (!strcmp(arg, "dups")) {
1826 options |= BT_LE_SCAN_OPT_FILTER_DUPLICATE;
1827 } else if (!strcmp(arg, "nodups")) {
1828 options &= ~BT_LE_SCAN_OPT_FILTER_DUPLICATE;
1829 } else if (!strcmp(arg, "fal")) {
1830 options |= BT_LE_SCAN_OPT_FILTER_ACCEPT_LIST;
1831 } else if (!strcmp(arg, "coded")) {
1832 options |= BT_LE_SCAN_OPT_CODED;
1833 } else if (!strcmp(arg, "no-1m")) {
1834 options |= BT_LE_SCAN_OPT_NO_1M;
1835 } else if (!strcmp(arg, "timeout")) {
1836 if (++argn == argc) {
1837 shell_help(sh);
1838 return SHELL_CMD_HELP_PRINTED;
1839 }
1840
1841 timeout = strtoul(argv[argn], NULL, 16);
1842 } else {
1843 shell_help(sh);
1844 return SHELL_CMD_HELP_PRINTED;
1845 }
1846 }
1847
1848 action = argv[1];
1849 if (!strcmp(action, "on")) {
1850 return cmd_active_scan_on(sh, options, timeout);
1851 } else if (!strcmp(action, "off")) {
1852 return cmd_scan_off(sh);
1853 } else if (!strcmp(action, "passive")) {
1854 return cmd_passive_scan_on(sh, options, timeout);
1855 } else {
1856 shell_help(sh);
1857 return SHELL_CMD_HELP_PRINTED;
1858 }
1859
1860 return 0;
1861 }
1862
cmd_scan_verbose_output(const struct shell * sh,size_t argc,char * argv[])1863 static int cmd_scan_verbose_output(const struct shell *sh, size_t argc, char *argv[])
1864 {
1865 const char *verbose_state;
1866
1867 verbose_state = argv[1];
1868 if (!strcmp(verbose_state, "on")) {
1869 scan_verbose_output = true;
1870 } else if (!strcmp(verbose_state, "off")) {
1871 scan_verbose_output = false;
1872 } else {
1873 shell_help(sh);
1874 return SHELL_CMD_HELP_PRINTED;
1875 }
1876
1877 return 0;
1878 }
1879
cmd_scan_filter_set_name(const struct shell * sh,size_t argc,char * argv[])1880 static int cmd_scan_filter_set_name(const struct shell *sh, size_t argc,
1881 char *argv[])
1882 {
1883 const char *name_arg = argv[1];
1884
1885 if (strlen(name_arg) >= sizeof(scan_filter.name)) {
1886 shell_error(sh, "Name is too long (max %zu): %s\n",
1887 sizeof(scan_filter.name), name_arg);
1888 return -ENOEXEC;
1889 }
1890
1891 strcpy(scan_filter.name, name_arg);
1892 scan_filter.name_set = true;
1893
1894 return 0;
1895 }
1896
cmd_scan_filter_set_addr(const struct shell * sh,size_t argc,char * argv[])1897 static int cmd_scan_filter_set_addr(const struct shell *sh, size_t argc,
1898 char *argv[])
1899 {
1900 const size_t max_cpy_len = sizeof(scan_filter.addr) - 1;
1901 const char *addr_arg = argv[1];
1902 size_t len = strlen(addr_arg);
1903
1904 /* Validate length including null terminator. */
1905 if (len > max_cpy_len) {
1906 shell_error(sh, "Invalid address string: %s\n", addr_arg);
1907 return -ENOEXEC;
1908 }
1909
1910 /* Validate input to check if valid (subset of) BT address */
1911 for (size_t i = 0; i < len; i++) {
1912 const char c = addr_arg[i];
1913 uint8_t tmp;
1914
1915 if (c != ':' && char2hex(c, &tmp) < 0) {
1916 shell_error(sh, "Invalid address string: %s\n", addr_arg);
1917 return -ENOEXEC;
1918 }
1919 }
1920
1921 strncpy(scan_filter.addr, addr_arg, max_cpy_len);
1922 scan_filter.addr[max_cpy_len] = '\0'; /* ensure NULL termination */
1923 scan_filter.addr_set = true;
1924
1925 return 0;
1926 }
1927
cmd_scan_filter_set_rssi(const struct shell * sh,size_t argc,char * argv[])1928 static int cmd_scan_filter_set_rssi(const struct shell *sh, size_t argc, char *argv[])
1929 {
1930 int err = 0;
1931 long rssi;
1932
1933 rssi = shell_strtol(argv[1], 10, &err);
1934
1935 if (!err) {
1936 if (IN_RANGE(rssi, INT8_MIN, INT8_MAX)) {
1937 scan_filter.rssi = (int8_t)rssi;
1938 scan_filter.rssi_set = true;
1939 shell_print(sh, "RSSI cutoff set at %d dB", scan_filter.rssi);
1940
1941 return 0;
1942 }
1943
1944 shell_print(sh, "value out of bounds (%d to %d)", INT8_MIN, INT8_MAX);
1945 err = -ERANGE;
1946 }
1947
1948 shell_print(sh, "error %d", err);
1949 shell_help(sh);
1950
1951 return SHELL_CMD_HELP_PRINTED;
1952 }
1953
cmd_scan_filter_set_pa_interval(const struct shell * sh,size_t argc,char * argv[])1954 static int cmd_scan_filter_set_pa_interval(const struct shell *sh, size_t argc,
1955 char *argv[])
1956 {
1957 unsigned long pa_interval;
1958 int err = 0;
1959
1960 pa_interval = shell_strtoul(argv[1], 10, &err);
1961
1962 if (!err) {
1963 if (IN_RANGE(pa_interval,
1964 BT_GAP_PER_ADV_MIN_INTERVAL,
1965 BT_GAP_PER_ADV_MAX_INTERVAL)) {
1966 scan_filter.pa_interval = (uint16_t)pa_interval;
1967 scan_filter.pa_interval_set = true;
1968 shell_print(sh, "PA interval cutoff set at %u",
1969 scan_filter.pa_interval);
1970
1971 return 0;
1972 }
1973
1974 shell_print(sh, "value out of bounds (%d to %d)",
1975 BT_GAP_PER_ADV_MIN_INTERVAL,
1976 BT_GAP_PER_ADV_MAX_INTERVAL);
1977
1978 err = -ERANGE;
1979 }
1980
1981 shell_print(sh, "error %d", err);
1982 shell_help(sh);
1983
1984 return SHELL_CMD_HELP_PRINTED;
1985 }
1986
cmd_scan_filter_clear_all(const struct shell * sh,size_t argc,char * argv[])1987 static int cmd_scan_filter_clear_all(const struct shell *sh, size_t argc,
1988 char *argv[])
1989 {
1990 (void)memset(&scan_filter, 0, sizeof(scan_filter));
1991
1992 return 0;
1993 }
1994
bt_do_scan_filter_clear_name(void)1995 static void bt_do_scan_filter_clear_name(void)
1996 {
1997 (void)memset(scan_filter.name, 0, sizeof(scan_filter.name));
1998 scan_filter.name_set = false;
1999 }
2000
cmd_scan_filter_clear_name(const struct shell * sh,size_t argc,char * argv[])2001 static int cmd_scan_filter_clear_name(const struct shell *sh, size_t argc,
2002 char *argv[])
2003 {
2004 ARG_UNUSED(sh);
2005 ARG_UNUSED(argc);
2006 ARG_UNUSED(argv);
2007
2008 bt_do_scan_filter_clear_name();
2009
2010 return 0;
2011 }
2012
cmd_scan_filter_clear_addr(const struct shell * sh,size_t argc,char * argv[])2013 static int cmd_scan_filter_clear_addr(const struct shell *sh, size_t argc,
2014 char *argv[])
2015 {
2016 ARG_UNUSED(sh);
2017 ARG_UNUSED(argc);
2018 ARG_UNUSED(argv);
2019
2020 (void)memset(scan_filter.addr, 0, sizeof(scan_filter.addr));
2021 scan_filter.addr_set = false;
2022
2023 return 0;
2024 }
2025
2026 #endif /* CONFIG_BT_OBSERVER */
2027
2028 #if defined(CONFIG_BT_BROADCASTER)
ad_init(struct bt_data * data_array,const size_t data_array_size,const atomic_t * adv_options)2029 static ssize_t ad_init(struct bt_data *data_array, const size_t data_array_size,
2030 const atomic_t *adv_options)
2031 {
2032 const bool discoverable = atomic_test_bit(adv_options, SHELL_ADV_OPT_DISCOVERABLE);
2033 const bool appearance = atomic_test_bit(adv_options, SHELL_ADV_OPT_APPEARANCE);
2034 const bool adv_ext = atomic_test_bit(adv_options, SHELL_ADV_OPT_EXT_ADV);
2035 static uint8_t ad_flags;
2036 size_t ad_len = 0;
2037
2038 /* Set BR/EDR Not Supported if LE-only device */
2039 ad_flags = IS_ENABLED(CONFIG_BT_CLASSIC) ? 0 : BT_LE_AD_NO_BREDR;
2040
2041 if (discoverable) {
2042 /* A privacy-enabled Set Member should advertise RSI values only when in
2043 * the GAP Limited Discoverable mode.
2044 */
2045 if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
2046 IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER) &&
2047 svc_inst != NULL) {
2048 ad_flags |= BT_LE_AD_LIMITED;
2049 } else {
2050 ad_flags |= BT_LE_AD_GENERAL;
2051 }
2052 }
2053
2054 if (ad_flags != 0) {
2055 __ASSERT(data_array_size > ad_len, "No space for AD_FLAGS");
2056 data_array[ad_len].type = BT_DATA_FLAGS;
2057 data_array[ad_len].data_len = sizeof(ad_flags);
2058 data_array[ad_len].data = &ad_flags;
2059 ad_len++;
2060 }
2061
2062 if (appearance) {
2063 const uint16_t appearance2 = bt_get_appearance();
2064 static uint8_t appearance_data[sizeof(appearance2)];
2065
2066 __ASSERT(data_array_size > ad_len, "No space for appearance");
2067 sys_put_le16(appearance2, appearance_data);
2068 data_array[ad_len].type = BT_DATA_GAP_APPEARANCE;
2069 data_array[ad_len].data_len = sizeof(appearance_data);
2070 data_array[ad_len].data = appearance_data;
2071 ad_len++;
2072 }
2073
2074 if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER)) {
2075 ssize_t csis_ad_len;
2076
2077 csis_ad_len = csis_ad_data_add(&data_array[ad_len],
2078 data_array_size - ad_len, discoverable);
2079 if (csis_ad_len < 0) {
2080 bt_shell_error("Failed to add CSIS data (err %zd)", csis_ad_len);
2081 return ad_len;
2082 }
2083
2084 ad_len += csis_ad_len;
2085 }
2086
2087 if (IS_ENABLED(CONFIG_BT_AUDIO) && IS_ENABLED(CONFIG_BT_EXT_ADV) && adv_ext) {
2088 const bool connectable = atomic_test_bit(adv_options, SHELL_ADV_OPT_CONNECTABLE);
2089
2090 ad_len += audio_ad_data_add(&data_array[ad_len], data_array_size - ad_len,
2091 discoverable, connectable);
2092 }
2093
2094 return ad_len;
2095 }
2096
set_ad_name_complete(struct bt_data * ad,const char * name)2097 void set_ad_name_complete(struct bt_data *ad, const char *name)
2098 {
2099 ad->type = BT_DATA_NAME_COMPLETE;
2100 ad->data_len = strlen(name);
2101 ad->data = name;
2102 }
2103
set_ad_device_name_complete(struct bt_data * ad)2104 void set_ad_device_name_complete(struct bt_data *ad)
2105 {
2106 const char *name = bt_get_name();
2107
2108 set_ad_name_complete(ad, name);
2109 }
2110
cmd_advertise(const struct shell * sh,size_t argc,char * argv[])2111 static int cmd_advertise(const struct shell *sh, size_t argc, char *argv[])
2112 {
2113 struct bt_le_adv_param param = {};
2114 struct bt_data ad[4];
2115 struct bt_data sd[4];
2116 bool discoverable = true;
2117 bool appearance = false;
2118 ssize_t ad_len = 0;
2119 ssize_t sd_len = 0;
2120 int err;
2121 bool with_name = true;
2122 bool name_ad = false;
2123 bool name_sd = true;
2124
2125 if (!strcmp(argv[1], "off")) {
2126 if (bt_le_adv_stop() < 0) {
2127 shell_error(sh, "Failed to stop advertising");
2128 return -ENOEXEC;
2129 } else {
2130 shell_print(sh, "Advertising stopped");
2131 }
2132
2133 return 0;
2134 }
2135
2136 param.id = selected_id;
2137 param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
2138 param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
2139
2140 if (!strcmp(argv[1], "on")) {
2141 param.options = BT_LE_ADV_OPT_CONN;
2142 } else if (!strcmp(argv[1], "nconn")) {
2143 param.options = 0U;
2144 } else {
2145 goto fail;
2146 }
2147
2148 for (size_t argn = 2; argn < argc; argn++) {
2149 const char *arg = argv[argn];
2150
2151 if (!strcmp(arg, "discov")) {
2152 discoverable = true;
2153 } else if (!strcmp(arg, "non_discov")) {
2154 discoverable = false;
2155 } else if (!strcmp(arg, "appearance")) {
2156 appearance = true;
2157 } else if (!strcmp(arg, "fal")) {
2158 param.options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
2159 param.options |= BT_LE_ADV_OPT_FILTER_CONN;
2160 } else if (!strcmp(arg, "fal-scan")) {
2161 param.options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
2162 } else if (!strcmp(arg, "fal-conn")) {
2163 param.options |= BT_LE_ADV_OPT_FILTER_CONN;
2164 } else if (!strcmp(arg, "identity")) {
2165 param.options |= BT_LE_ADV_OPT_USE_IDENTITY;
2166 } else if (!strcmp(arg, "no-name")) {
2167 with_name = false;
2168 } else if (!strcmp(arg, "name-ad")) {
2169 name_ad = true;
2170 name_sd = false;
2171 } else if (!strcmp(arg, "disable-37")) {
2172 param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_37;
2173 } else if (!strcmp(arg, "disable-38")) {
2174 param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_38;
2175 } else if (!strcmp(arg, "disable-39")) {
2176 param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_39;
2177 } else {
2178 goto fail;
2179 }
2180 }
2181
2182 if (name_ad && with_name) {
2183 set_ad_device_name_complete(&ad[0]);
2184 ad_len++;
2185 }
2186
2187 if (name_sd && with_name) {
2188 set_ad_device_name_complete(&sd[0]);
2189 sd_len++;
2190 }
2191
2192 atomic_clear(adv_opt);
2193 atomic_set_bit_to(adv_opt, SHELL_ADV_OPT_CONNECTABLE,
2194 (param.options & BT_LE_ADV_OPT_CONN) > 0);
2195 atomic_set_bit_to(adv_opt, SHELL_ADV_OPT_DISCOVERABLE, discoverable);
2196 atomic_set_bit_to(adv_opt, SHELL_ADV_OPT_APPEARANCE, appearance);
2197
2198 err = ad_init(&ad[ad_len], ARRAY_SIZE(ad) - ad_len, adv_opt);
2199 if (err < 0) {
2200 return -ENOEXEC;
2201 }
2202 ad_len += err;
2203
2204 err = bt_le_adv_start(¶m, ad_len > 0 ? ad : NULL, ad_len, sd_len > 0 ? sd : NULL,
2205 sd_len);
2206 if (err < 0) {
2207 shell_error(sh, "Failed to start advertising (err %d)", err);
2208 return err;
2209 } else {
2210 shell_print(sh, "Advertising started");
2211 }
2212
2213 return 0;
2214
2215 fail:
2216 shell_help(sh);
2217 return -ENOEXEC;
2218 }
2219
2220 #if defined(CONFIG_BT_PERIPHERAL)
cmd_directed_adv(const struct shell * sh,size_t argc,char * argv[])2221 static int cmd_directed_adv(const struct shell *sh,
2222 size_t argc, char *argv[])
2223 {
2224 int err;
2225 bt_addr_le_t addr;
2226 struct bt_le_adv_param param;
2227
2228 err = bt_addr_le_from_str(argv[1], argv[2], &addr);
2229 param = *BT_LE_ADV_CONN_DIR(&addr);
2230 if (err) {
2231 shell_error(sh, "Invalid peer address (err %d)", err);
2232 return err;
2233 }
2234
2235 for (size_t argn = 3; argn < argc; argn++) {
2236 const char *arg = argv[argn];
2237
2238 if (!strcmp(arg, "low")) {
2239 param.options |= BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY;
2240 param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
2241 param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
2242 } else if (!strcmp(arg, "identity")) {
2243 param.options |= BT_LE_ADV_OPT_USE_IDENTITY;
2244 } else if (!strcmp(arg, "dir-rpa")) {
2245 param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA;
2246 } else if (!strcmp(arg, "disable-37")) {
2247 param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_37;
2248 } else if (!strcmp(arg, "disable-38")) {
2249 param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_38;
2250 } else if (!strcmp(arg, "disable-39")) {
2251 param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_39;
2252 } else {
2253 shell_help(sh);
2254 return -ENOEXEC;
2255 }
2256 }
2257
2258 err = bt_le_adv_start(¶m, NULL, 0, NULL, 0);
2259 if (err) {
2260 shell_error(sh, "Failed to start directed advertising (%d)", err);
2261 return -ENOEXEC;
2262 } else {
2263 shell_print(sh, "Started directed advertising");
2264 }
2265
2266 return 0;
2267 }
2268 #endif /* CONFIG_BT_PERIPHERAL */
2269
2270 #if defined(CONFIG_BT_EXT_ADV)
parse_and_set_adv_param(size_t argc,char * argv[],struct bt_le_adv_param * param)2271 static bool parse_and_set_adv_param(size_t argc, char *argv[], struct bt_le_adv_param *param)
2272 {
2273 static uint8_t next_adv_sid = BT_GAP_SID_MIN;
2274
2275 memset(param, 0, sizeof(struct bt_le_adv_param));
2276
2277 if (!strcmp(argv[1], "conn-scan")) {
2278 param->options |= BT_LE_ADV_OPT_CONN;
2279 param->options |= BT_LE_ADV_OPT_SCANNABLE;
2280 } else if (!strcmp(argv[1], "conn-nscan")) {
2281 param->options |= BT_LE_ADV_OPT_CONN;
2282 } else if (!strcmp(argv[1], "nconn-scan")) {
2283 param->options |= BT_LE_ADV_OPT_SCANNABLE;
2284 } else if (!strcmp(argv[1], "nconn-nscan")) {
2285 /* Acceptable option, nothing to do */
2286 } else {
2287 return false;
2288 }
2289
2290 for (size_t argn = 2; argn < argc; argn++) {
2291 const char *arg = argv[argn];
2292
2293 if (!strcmp(arg, "ext-adv")) {
2294 param->options |= BT_LE_ADV_OPT_EXT_ADV;
2295 } else if (!strcmp(arg, "coded")) {
2296 param->options |= BT_LE_ADV_OPT_CODED;
2297 } else if (!strcmp(arg, "no-2m")) {
2298 param->options |= BT_LE_ADV_OPT_NO_2M;
2299 } else if (!strcmp(arg, "anon")) {
2300 param->options |= BT_LE_ADV_OPT_ANONYMOUS;
2301 } else if (!strcmp(arg, "tx-power")) {
2302 param->options |= BT_LE_ADV_OPT_USE_TX_POWER;
2303 } else if (!strcmp(arg, "scan-reports")) {
2304 param->options |= BT_LE_ADV_OPT_NOTIFY_SCAN_REQ;
2305 } else if (!strcmp(arg, "fal")) {
2306 param->options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
2307 param->options |= BT_LE_ADV_OPT_FILTER_CONN;
2308 } else if (!strcmp(arg, "fal-scan")) {
2309 param->options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
2310 } else if (!strcmp(arg, "fal-conn")) {
2311 param->options |= BT_LE_ADV_OPT_FILTER_CONN;
2312 } else if (!strcmp(arg, "identity")) {
2313 param->options |= BT_LE_ADV_OPT_USE_IDENTITY;
2314 } else if (!strcmp(arg, "low")) {
2315 param->options |= BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY;
2316 } else if (!strcmp(arg, "dir-rpa")) {
2317 param->options |= BT_LE_ADV_OPT_DIR_ADDR_RPA;
2318 } else if (!strcmp(arg, "disable-37")) {
2319 param->options |= BT_LE_ADV_OPT_DISABLE_CHAN_37;
2320 } else if (!strcmp(arg, "disable-38")) {
2321 param->options |= BT_LE_ADV_OPT_DISABLE_CHAN_38;
2322 } else if (!strcmp(arg, "disable-39")) {
2323 param->options |= BT_LE_ADV_OPT_DISABLE_CHAN_39;
2324 } else if (!strcmp(arg, "directed")) {
2325 static bt_addr_le_t addr;
2326
2327 if ((argn + 2) >= argc) {
2328 return false;
2329 }
2330
2331 if (bt_addr_le_from_str(argv[argn + 1], argv[argn + 2], &addr)) {
2332 return false;
2333 }
2334
2335 param->peer = &addr;
2336 argn += 2;
2337 } else {
2338 return false;
2339 }
2340 }
2341
2342 param->id = selected_id;
2343 param->sid = next_adv_sid++;
2344 if (param->peer &&
2345 !(param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
2346 param->interval_min = 0;
2347 param->interval_max = 0;
2348 } else {
2349 param->interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
2350 param->interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
2351 }
2352
2353 if (next_adv_sid > BT_GAP_SID_MAX) {
2354 next_adv_sid = BT_GAP_SID_MIN;
2355 }
2356
2357 return true;
2358 }
2359
cmd_adv_create(const struct shell * sh,size_t argc,char * argv[])2360 static int cmd_adv_create(const struct shell *sh, size_t argc, char *argv[])
2361 {
2362 struct bt_le_adv_param param;
2363 struct bt_le_ext_adv *adv;
2364 uint8_t adv_index;
2365 int err;
2366
2367 if (!parse_and_set_adv_param(argc, argv, ¶m)) {
2368 shell_help(sh);
2369 return -ENOEXEC;
2370 }
2371
2372 err = bt_le_ext_adv_create(¶m, &adv_callbacks, &adv);
2373 if (err) {
2374 shell_error(sh, "Failed to create advertiser set (%d)", err);
2375 return -ENOEXEC;
2376 }
2377
2378 adv_index = bt_le_ext_adv_get_index(adv);
2379 adv_sets[adv_index] = adv;
2380
2381 atomic_clear(adv_set_opt[adv_index]);
2382 atomic_set_bit_to(adv_set_opt[adv_index], SHELL_ADV_OPT_CONNECTABLE,
2383 (param.options & BT_LE_ADV_OPT_CONN) > 0);
2384 atomic_set_bit_to(adv_set_opt[adv_index], SHELL_ADV_OPT_EXT_ADV,
2385 (param.options & BT_LE_ADV_OPT_EXT_ADV) > 0);
2386
2387 shell_print(sh, "Created adv id: %d, adv: %p", adv_index, adv);
2388
2389 return 0;
2390 }
2391
cmd_adv_param(const struct shell * sh,size_t argc,char * argv[])2392 static int cmd_adv_param(const struct shell *sh, size_t argc, char *argv[])
2393 {
2394 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2395 struct bt_le_adv_param param;
2396 int err;
2397
2398 if (!parse_and_set_adv_param(argc, argv, ¶m)) {
2399 shell_help(sh);
2400 return -ENOEXEC;
2401 }
2402
2403 err = bt_le_ext_adv_update_param(adv, ¶m);
2404 if (err) {
2405 shell_error(sh, "Failed to update advertiser set (%d)", err);
2406 return -ENOEXEC;
2407 }
2408
2409 return 0;
2410 }
2411
cmd_adv_data(const struct shell * sh,size_t argc,char * argv[])2412 static int cmd_adv_data(const struct shell *sh, size_t argc, char *argv[])
2413 {
2414 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2415 static uint8_t hex_data[1650];
2416 bool appearance = false;
2417 struct bt_data *data;
2418 struct bt_data ad[AD_SIZE];
2419 struct bt_data sd[AD_SIZE];
2420 size_t hex_data_len;
2421 size_t ad_len = 0;
2422 size_t sd_len = 0;
2423 ssize_t len = 0;
2424 bool discoverable = false;
2425 size_t *data_len;
2426 int err;
2427 bool name = false;
2428 bool dev_name = false;
2429 const char *name_value = NULL;
2430
2431 if (!adv) {
2432 return -EINVAL;
2433 }
2434
2435 hex_data_len = 0;
2436 data = ad;
2437 data_len = &ad_len;
2438
2439 for (size_t argn = 1; argn < argc; argn++) {
2440 const char *arg = argv[argn];
2441
2442 if (name && !dev_name && name_value == NULL) {
2443 if (*data_len == ARRAY_SIZE(ad)) {
2444 /* Maximum entries limit reached. */
2445 shell_print(sh, "Failed to set advertising data: "
2446 "Maximum entries limit reached");
2447
2448 return -ENOEXEC;
2449 }
2450
2451 len = strlen(arg);
2452 memcpy(&hex_data[hex_data_len], arg, len);
2453 name_value = &hex_data[hex_data_len];
2454
2455 set_ad_name_complete(&data[*data_len], name_value);
2456
2457 (*data_len)++;
2458 hex_data_len += len;
2459
2460 continue;
2461 }
2462
2463 if (strcmp(arg, "scan-response") && *data_len == ARRAY_SIZE(ad)) {
2464 /* Maximum entries limit reached. */
2465 shell_print(sh, "Failed to set advertising data: "
2466 "Maximum entries limit reached");
2467
2468 return -ENOEXEC;
2469 }
2470
2471 if (!strcmp(arg, "discov")) {
2472 discoverable = true;
2473 } else if (!strcmp(arg, "non_discov")) {
2474 discoverable = false;
2475 } else if (!strcmp(arg, "appearance")) {
2476 appearance = true;
2477 } else if (!strcmp(arg, "scan-response")) {
2478 if (data == sd) {
2479 shell_print(sh, "Failed to set advertising data: "
2480 "duplicate scan-response option");
2481 return -ENOEXEC;
2482 }
2483
2484 data = sd;
2485 data_len = &sd_len;
2486 } else if (!strcmp(arg, "name") && !name) {
2487 name = true;
2488 } else if (!strcmp(arg, "dev-name")) {
2489 name = true;
2490 dev_name = true;
2491 } else {
2492 len = hex2bin(arg, strlen(arg), &hex_data[hex_data_len],
2493 sizeof(hex_data) - hex_data_len);
2494
2495 if (!len || (len - 1) != (hex_data[hex_data_len])) {
2496 shell_print(sh, "Failed to set advertising data: "
2497 "malformed hex data");
2498 return -ENOEXEC;
2499 }
2500
2501 data[*data_len].type = hex_data[hex_data_len + 1];
2502 data[*data_len].data_len = len - 2;
2503 data[*data_len].data = &hex_data[hex_data_len + 2];
2504 (*data_len)++;
2505 hex_data_len += len;
2506 }
2507 }
2508
2509 if (name && !dev_name && name_value == NULL) {
2510 shell_error(sh, "Failed to set advertising data: Expected a value for 'name'");
2511 return -ENOEXEC;
2512 }
2513
2514 if (name && dev_name && name_value == NULL) {
2515 if (*data_len == ARRAY_SIZE(ad)) {
2516 /* Maximum entries limit reached. */
2517 shell_print(sh, "Failed to set advertising data: "
2518 "Maximum entries limit reached");
2519
2520 return -ENOEXEC;
2521 }
2522
2523 set_ad_device_name_complete(&data[*data_len]);
2524
2525 (*data_len)++;
2526 }
2527
2528 atomic_set_bit_to(adv_set_opt[selected_adv], SHELL_ADV_OPT_DISCOVERABLE, discoverable);
2529 atomic_set_bit_to(adv_set_opt[selected_adv], SHELL_ADV_OPT_APPEARANCE, appearance);
2530
2531 len = ad_init(&data[*data_len], AD_SIZE - *data_len, adv_set_opt[selected_adv]);
2532 if (len < 0) {
2533 shell_error(sh, "Failed to initialize stack advertising data");
2534
2535 return -ENOEXEC;
2536 }
2537
2538 if (data == ad) {
2539 ad_len += len;
2540 } else {
2541 sd_len += len;
2542 }
2543
2544 err = bt_le_ext_adv_set_data(adv, ad_len > 0 ? ad : NULL, ad_len,
2545 sd_len > 0 ? sd : NULL, sd_len);
2546 if (err) {
2547 shell_print(sh, "Failed to set advertising set data (%d)", err);
2548 return -ENOEXEC;
2549 }
2550
2551 return 0;
2552 }
2553
cmd_adv_start(const struct shell * sh,size_t argc,char * argv[])2554 static int cmd_adv_start(const struct shell *sh, size_t argc, char *argv[])
2555 {
2556 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2557 struct bt_le_ext_adv_start_param param;
2558 uint8_t num_events = 0;
2559 int32_t timeout = 0;
2560 int err;
2561
2562 if (!adv) {
2563 shell_print(sh, "Advertiser[%d] not created", selected_adv);
2564 return -EINVAL;
2565 }
2566
2567 for (size_t argn = 1; argn < argc; argn++) {
2568 const char *arg = argv[argn];
2569
2570 if (!strcmp(arg, "timeout")) {
2571 if (++argn == argc) {
2572 goto fail_show_help;
2573 }
2574
2575 timeout = strtoul(argv[argn], NULL, 16);
2576 }
2577
2578 if (!strcmp(arg, "num-events")) {
2579 if (++argn == argc) {
2580 goto fail_show_help;
2581 }
2582
2583 num_events = strtoul(argv[argn], NULL, 16);
2584 }
2585 }
2586
2587 param.timeout = timeout;
2588 param.num_events = num_events;
2589
2590 err = bt_le_ext_adv_start(adv, ¶m);
2591 if (err) {
2592 shell_print(sh, "Failed to start advertising set (%d)", err);
2593 return -ENOEXEC;
2594 }
2595
2596 shell_print(sh, "Advertiser[%d] %p set started", selected_adv, adv);
2597 return 0;
2598
2599 fail_show_help:
2600 shell_help(sh);
2601 return -ENOEXEC;
2602 }
2603
cmd_adv_stop(const struct shell * sh,size_t argc,char * argv[])2604 static int cmd_adv_stop(const struct shell *sh, size_t argc, char *argv[])
2605 {
2606 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2607 int err;
2608
2609 if (!adv) {
2610 shell_print(sh, "Advertiser[%d] not created", selected_adv);
2611 return -EINVAL;
2612 }
2613
2614 err = bt_le_ext_adv_stop(adv);
2615 if (err) {
2616 shell_print(sh, "Failed to stop advertising set (%d)", err);
2617 return -ENOEXEC;
2618 }
2619
2620 shell_print(sh, "Advertiser set stopped");
2621 return 0;
2622 }
2623
cmd_adv_delete(const struct shell * sh,size_t argc,char * argv[])2624 static int cmd_adv_delete(const struct shell *sh, size_t argc, char *argv[])
2625 {
2626 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2627 int err;
2628
2629 if (!adv) {
2630 shell_print(sh, "Advertiser[%d] not created", selected_adv);
2631 return -EINVAL;
2632 }
2633
2634 err = bt_le_ext_adv_delete(adv);
2635 if (err) {
2636 shell_error(sh, "Failed to delete advertiser set");
2637 return err;
2638 }
2639
2640 adv_sets[selected_adv] = NULL;
2641 return 0;
2642 }
2643
cmd_adv_select(const struct shell * sh,size_t argc,char * argv[])2644 static int cmd_adv_select(const struct shell *sh, size_t argc, char *argv[])
2645 {
2646 if (argc == 2) {
2647 uint8_t id = strtol(argv[1], NULL, 10);
2648
2649 if (!(id < ARRAY_SIZE(adv_sets))) {
2650 return -EINVAL;
2651 }
2652
2653 selected_adv = id;
2654 return 0;
2655 }
2656
2657 for (int i = 0; i < ARRAY_SIZE(adv_sets); i++) {
2658 if (adv_sets[i]) {
2659 shell_print(sh, "Advertiser[%d] %p", i, adv_sets[i]);
2660 }
2661 }
2662
2663 return -ENOEXEC;
2664 }
2665
cmd_adv_info(const struct shell * sh,size_t argc,char * argv[])2666 static int cmd_adv_info(const struct shell *sh, size_t argc, char *argv[])
2667 {
2668 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2669 struct bt_le_ext_adv_info info;
2670 int err;
2671
2672 if (!adv) {
2673 return -EINVAL;
2674 }
2675
2676 err = bt_le_ext_adv_get_info(adv, &info);
2677 if (err) {
2678 shell_error(sh, "Failed to get advertising set info: %d", err);
2679 return err;
2680 }
2681
2682 shell_print(sh, "Advertiser[%d] %p", selected_adv, adv);
2683 shell_print(sh, "Id: %d, SID %u, TX power: %d dBm", info.id, info.sid, info.tx_power);
2684 shell_print(sh, "Adv state: %d", info.ext_adv_state);
2685 print_le_addr("Address", info.addr);
2686
2687 if (IS_ENABLED(CONFIG_BT_PER_ADV)) {
2688 shell_print(sh, "Per Adv state: %d", info.per_adv_state);
2689 }
2690
2691 return 0;
2692 }
2693
2694 #if defined(CONFIG_BT_PERIPHERAL)
cmd_adv_oob(const struct shell * sh,size_t argc,char * argv[])2695 static int cmd_adv_oob(const struct shell *sh, size_t argc, char *argv[])
2696 {
2697 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2698 int err;
2699
2700 if (!adv) {
2701 return -EINVAL;
2702 }
2703
2704 err = bt_le_ext_adv_oob_get_local(adv, &oob_local);
2705 if (err) {
2706 shell_error(sh, "OOB data failed");
2707 return err;
2708 }
2709
2710 print_le_oob(sh, &oob_local);
2711
2712 return 0;
2713 }
2714 #endif /* CONFIG_BT_PERIPHERAL */
2715
2716 #if defined(CONFIG_BT_PRIVACY)
cmd_adv_rpa_expire(const struct shell * sh,size_t argc,char * argv[])2717 static int cmd_adv_rpa_expire(const struct shell *sh, size_t argc, char *argv[])
2718 {
2719 if (!strcmp(argv[1], "on")) {
2720 atomic_clear_bit(adv_set_opt[selected_adv], SHELL_ADV_OPT_KEEP_RPA);
2721 shell_print(sh, "RPA will expire on next timeout");
2722 } else if (!strcmp(argv[1], "off")) {
2723 atomic_set_bit(adv_set_opt[selected_adv], SHELL_ADV_OPT_KEEP_RPA);
2724 shell_print(sh, "RPA will not expire on RPA timeout");
2725 } else {
2726 shell_error(sh, "Invalid argument: %s", argv[1]);
2727 return -EINVAL;
2728 }
2729
2730 return 0;
2731 }
2732 #endif /* CONFIG_BT_PRIVACY */
2733
2734 #if defined(CONFIG_BT_PER_ADV)
cmd_per_adv(const struct shell * sh,size_t argc,char * argv[])2735 static int cmd_per_adv(const struct shell *sh, size_t argc, char *argv[])
2736 {
2737 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2738
2739 if (!adv) {
2740 shell_error(sh, "No extended advertisement set selected");
2741 return -EINVAL;
2742 }
2743
2744 if (!strcmp(argv[1], "off")) {
2745 if (bt_le_per_adv_stop(adv) < 0) {
2746 shell_error(sh, "Failed to stop periodic advertising");
2747 } else {
2748 shell_print(sh, "Periodic advertising stopped");
2749 }
2750 } else if (!strcmp(argv[1], "on")) {
2751 if (bt_le_per_adv_start(adv) < 0) {
2752 shell_error(sh, "Failed to start periodic advertising");
2753 } else {
2754 shell_print(sh, "Periodic advertising started");
2755 }
2756 } else {
2757 shell_error(sh, "Invalid argument: %s", argv[1]);
2758 return -EINVAL;
2759 }
2760
2761 return 0;
2762 }
2763
cmd_per_adv_param(const struct shell * sh,size_t argc,char * argv[])2764 static int cmd_per_adv_param(const struct shell *sh, size_t argc,
2765 char *argv[])
2766 {
2767 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2768 struct bt_le_per_adv_param param;
2769 int err;
2770
2771 if (!adv) {
2772 shell_error(sh, "No extended advertisement set selected");
2773 return -EINVAL;
2774 }
2775
2776 if (argc > 1) {
2777 param.interval_min = strtol(argv[1], NULL, 16);
2778 } else {
2779 param.interval_min = BT_GAP_ADV_SLOW_INT_MIN;
2780 }
2781
2782 if (argc > 2) {
2783 param.interval_max = strtol(argv[2], NULL, 16);
2784 } else {
2785 param.interval_max = param.interval_min * 1.2;
2786 }
2787
2788 if (param.interval_min > param.interval_max) {
2789 shell_error(sh, "Min interval shall be less than max interval");
2790 return -EINVAL;
2791 }
2792
2793 if (argc > 3 && !strcmp(argv[3], "tx-power")) {
2794 param.options = BT_LE_ADV_OPT_USE_TX_POWER;
2795 } else {
2796 param.options = 0;
2797 }
2798
2799 err = bt_le_per_adv_set_param(adv, ¶m);
2800 if (err) {
2801 shell_error(sh, "Failed to set periodic advertising parameters (%d)", err);
2802 return -ENOEXEC;
2803 }
2804
2805 return 0;
2806 }
2807
pa_ad_init(struct bt_data * data_array,const size_t data_array_size)2808 static ssize_t pa_ad_init(struct bt_data *data_array,
2809 const size_t data_array_size)
2810 {
2811 size_t ad_len = 0;
2812
2813 if (IS_ENABLED(CONFIG_BT_AUDIO)) {
2814 ssize_t audio_pa_ad_len;
2815
2816 audio_pa_ad_len = audio_pa_data_add(&data_array[ad_len],
2817 data_array_size - ad_len);
2818 if (audio_pa_ad_len < 0U) {
2819 return audio_pa_ad_len;
2820 }
2821
2822 ad_len += audio_pa_ad_len;
2823 }
2824
2825 return ad_len;
2826 }
2827
cmd_per_adv_data(const struct shell * sh,size_t argc,char * argv[])2828 static int cmd_per_adv_data(const struct shell *sh, size_t argc,
2829 char *argv[])
2830 {
2831 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
2832 static uint8_t hex_data[256];
2833 static struct bt_data ad[2U];
2834 ssize_t stack_ad_len;
2835 uint8_t ad_len = 0;
2836 int err;
2837
2838 if (!adv) {
2839 shell_error(sh, "No extended advertisement set selected");
2840 return -EINVAL;
2841 }
2842
2843 if (argc > 1) {
2844 size_t hex_len = 0U;
2845
2846 (void)memset(hex_data, 0, sizeof(hex_data));
2847 hex_len = hex2bin(argv[1U], strlen(argv[1U]), hex_data,
2848 sizeof(hex_data));
2849
2850 if (hex_len == 0U) {
2851 shell_error(sh, "Could not parse adv data");
2852
2853 return -ENOEXEC;
2854 }
2855
2856 ad[ad_len].data_len = hex_data[0U];
2857 ad[ad_len].type = hex_data[1U];
2858 ad[ad_len].data = &hex_data[2U];
2859 ad_len++;
2860 }
2861
2862 stack_ad_len = pa_ad_init(&ad[ad_len], ARRAY_SIZE(ad) - ad_len);
2863 if (stack_ad_len < 0) {
2864 shell_error(sh, "Failed to get stack PA data");
2865
2866 return -ENOEXEC;
2867 }
2868 ad_len += stack_ad_len;
2869
2870 err = bt_le_per_adv_set_data(adv, ad, ad_len);
2871 if (err) {
2872 shell_error(sh, "Failed to set periodic advertising data (%d)", err);
2873 return -ENOEXEC;
2874 }
2875
2876 return 0;
2877 }
2878 #endif /* CONFIG_BT_PER_ADV */
2879 #endif /* CONFIG_BT_EXT_ADV */
2880 #endif /* CONFIG_BT_BROADCASTER */
2881
2882 #if defined(CONFIG_BT_PER_ADV_SYNC)
2883
cmd_per_adv_sync_create(const struct shell * sh,size_t argc,char * argv[])2884 static int cmd_per_adv_sync_create(const struct shell *sh, size_t argc,
2885 char *argv[])
2886 {
2887 struct bt_le_per_adv_sync *per_adv_sync = per_adv_syncs[selected_per_adv_sync];
2888 int err;
2889 struct bt_le_per_adv_sync_param create_params = { 0 };
2890 uint32_t options = 0;
2891
2892 if (per_adv_sync != NULL) {
2893 shell_error(sh, "Selected per-adv-sync is not NULL");
2894 return -ENOEXEC;
2895 }
2896
2897 err = bt_addr_le_from_str(argv[1], argv[2], &create_params.addr);
2898 if (err) {
2899 shell_error(sh, "Invalid peer address (err %d)", err);
2900 return -ENOEXEC;
2901 }
2902
2903 /* Default values */
2904 create_params.timeout = 1000; /* 10 seconds */
2905 create_params.skip = 10;
2906
2907 create_params.sid = strtol(argv[3], NULL, 16);
2908
2909 for (int j = 4; j < argc; j++) {
2910 if (!strcmp(argv[j], "aoa")) {
2911 options |= BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOA;
2912 } else if (!strcmp(argv[j], "aod_1us")) {
2913 options |= BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_1US;
2914 } else if (!strcmp(argv[j], "aod_2us")) {
2915 options |= BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_2US;
2916 } else if (!strcmp(argv[j], "only_cte")) {
2917 options |= BT_LE_PER_ADV_SYNC_OPT_SYNC_ONLY_CONST_TONE_EXT;
2918 } else if (!strcmp(argv[j], "timeout")) {
2919 if (++j == argc) {
2920 shell_help(sh);
2921 return SHELL_CMD_HELP_PRINTED;
2922 }
2923
2924 create_params.timeout = strtoul(argv[j], NULL, 16);
2925 } else if (!strcmp(argv[j], "skip")) {
2926 if (++j == argc) {
2927 shell_help(sh);
2928 return SHELL_CMD_HELP_PRINTED;
2929 }
2930
2931 create_params.skip = strtoul(argv[j], NULL, 16);
2932 } else {
2933 shell_help(sh);
2934 return SHELL_CMD_HELP_PRINTED;
2935 }
2936
2937 /* TODO: add support to parse using the per adv list */
2938 }
2939
2940 create_params.options = options;
2941
2942 err = bt_le_per_adv_sync_create(&create_params, &per_adv_syncs[selected_per_adv_sync]);
2943 if (err) {
2944 shell_error(sh, "Per adv sync failed (%d)", err);
2945 } else {
2946 shell_print(sh, "Per adv sync pending");
2947 }
2948
2949 return 0;
2950 }
2951
cmd_per_adv_sync_delete(const struct shell * sh,size_t argc,char * argv[])2952 static int cmd_per_adv_sync_delete(const struct shell *sh, size_t argc,
2953 char *argv[])
2954 {
2955 struct bt_le_per_adv_sync *per_adv_sync = per_adv_syncs[selected_per_adv_sync];
2956 int err;
2957
2958 if (!per_adv_sync) {
2959 shell_error(sh, "Selected per-adv-sync is NULL");
2960 return -EINVAL;
2961 }
2962
2963 err = bt_le_per_adv_sync_delete(per_adv_sync);
2964
2965 if (err) {
2966 shell_error(sh, "Per adv sync delete failed (%d)", err);
2967 } else {
2968 shell_print(sh, "Per adv sync deleted");
2969 per_adv_syncs[selected_per_adv_sync] = NULL;
2970 }
2971
2972 return 0;
2973 }
2974
cmd_per_adv_sync_select(const struct shell * sh,size_t argc,char * argv[])2975 static int cmd_per_adv_sync_select(const struct shell *sh, size_t argc, char *argv[])
2976 {
2977 if (argc == 2) {
2978 unsigned long id;
2979 int err = 0;
2980
2981 id = shell_strtoul(argv[1], 0, &err);
2982 if (err != 0) {
2983 shell_error(sh, "Could not parse id: %d", err);
2984 return -ENOEXEC;
2985 }
2986
2987 if (id > ARRAY_SIZE(adv_sets)) {
2988 shell_error(sh, "Invalid id: %lu", id);
2989 return -EINVAL;
2990 }
2991
2992 selected_per_adv_sync = id;
2993 return 0;
2994 }
2995
2996 for (size_t i = 0U; i < ARRAY_SIZE(adv_sets); i++) {
2997 if (adv_sets[i]) {
2998 shell_print(sh, "PER_ADV_SYNC[%zu] %p", i, adv_sets[i]);
2999 }
3000 }
3001
3002 return -ENOEXEC;
3003 }
3004
3005 #if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER)
cmd_past_subscribe(const struct shell * sh,size_t argc,char * argv[])3006 static int cmd_past_subscribe(const struct shell *sh, size_t argc,
3007 char *argv[])
3008 {
3009 struct bt_le_per_adv_sync_transfer_param param;
3010 int err;
3011 int i = 0;
3012 bool global = true;
3013
3014 if (i == ARRAY_SIZE(per_adv_syncs)) {
3015 shell_error(sh, "Cannot create more per adv syncs");
3016 return -ENOEXEC;
3017 }
3018
3019 /* Default values */
3020 param.options = 0;
3021 param.timeout = 1000; /* 10 seconds */
3022 param.skip = 10;
3023
3024 for (int j = 1; j < argc; j++) {
3025 if (!strcmp(argv[j], "aoa")) {
3026 param.options |=
3027 BT_LE_PER_ADV_SYNC_TRANSFER_OPT_SYNC_NO_AOA;
3028 } else if (!strcmp(argv[j], "aod_1us")) {
3029 param.options |=
3030 BT_LE_PER_ADV_SYNC_TRANSFER_OPT_SYNC_NO_AOD_1US;
3031 } else if (!strcmp(argv[j], "aod_2us")) {
3032 param.options |=
3033 BT_LE_PER_ADV_SYNC_TRANSFER_OPT_SYNC_NO_AOD_2US;
3034 } else if (!strcmp(argv[j], "only_cte")) {
3035 param.options |=
3036 BT_LE_PER_ADV_SYNC_TRANSFER_OPT_SYNC_ONLY_CTE;
3037 } else if (!strcmp(argv[j], "timeout")) {
3038 if (++j == argc) {
3039 shell_help(sh);
3040 return SHELL_CMD_HELP_PRINTED;
3041 }
3042
3043 param.timeout = strtoul(argv[j], NULL, 16);
3044 } else if (!strcmp(argv[j], "skip")) {
3045 if (++j == argc) {
3046 shell_help(sh);
3047 return SHELL_CMD_HELP_PRINTED;
3048 }
3049
3050 param.skip = strtoul(argv[j], NULL, 16);
3051 } else if (!strcmp(argv[j], "conn")) {
3052 if (!default_conn) {
3053 shell_print(sh, "Not connected");
3054 return -EINVAL;
3055 }
3056 global = false;
3057 } else {
3058 shell_help(sh);
3059 return SHELL_CMD_HELP_PRINTED;
3060 }
3061 }
3062
3063 bt_le_per_adv_sync_cb_register(&per_adv_sync_cb);
3064
3065 err = bt_le_per_adv_sync_transfer_subscribe(
3066 global ? NULL : default_conn, ¶m);
3067
3068 if (err) {
3069 shell_error(sh, "PAST subscribe failed (%d)", err);
3070 } else {
3071 shell_print(sh, "Subscribed to PAST");
3072 }
3073
3074 return 0;
3075 }
3076
cmd_past_unsubscribe(const struct shell * sh,size_t argc,char * argv[])3077 static int cmd_past_unsubscribe(const struct shell *sh, size_t argc,
3078 char *argv[])
3079 {
3080 int err;
3081
3082 if (argc > 1) {
3083 if (!strcmp(argv[1], "conn")) {
3084 if (default_conn) {
3085 err =
3086 bt_le_per_adv_sync_transfer_unsubscribe(
3087 default_conn);
3088 } else {
3089 shell_print(sh, "Not connected");
3090 return -EINVAL;
3091 }
3092 } else {
3093 shell_help(sh);
3094 return SHELL_CMD_HELP_PRINTED;
3095 }
3096 } else {
3097 err = bt_le_per_adv_sync_transfer_unsubscribe(NULL);
3098 }
3099
3100 if (err) {
3101 shell_error(sh, "PAST unsubscribe failed (%d)", err);
3102 }
3103
3104 return err;
3105 }
3106 #endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER */
3107
3108 #if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER)
cmd_per_adv_sync_transfer(const struct shell * sh,size_t argc,char * argv[])3109 static int cmd_per_adv_sync_transfer(const struct shell *sh, size_t argc,
3110 char *argv[])
3111 {
3112 int err;
3113 int index;
3114 struct bt_le_per_adv_sync *per_adv_sync;
3115
3116 if (argc > 1) {
3117 index = strtol(argv[1], NULL, 10);
3118 } else {
3119 index = 0;
3120 }
3121
3122 if (index >= ARRAY_SIZE(per_adv_syncs)) {
3123 shell_error(sh, "Maximum index is %zu but %d was requested",
3124 ARRAY_SIZE(per_adv_syncs) - 1, index);
3125 }
3126
3127 per_adv_sync = per_adv_syncs[index];
3128 if (!per_adv_sync) {
3129 return -EINVAL;
3130 }
3131
3132 err = bt_le_per_adv_sync_transfer(per_adv_sync, default_conn, 0);
3133 if (err) {
3134 shell_error(sh, "Periodic advertising sync transfer failed (%d)", err);
3135 }
3136
3137 return err;
3138 }
3139 #endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER */
3140 #endif /* CONFIG_BT_PER_ADV_SYNC */
3141
3142 #if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER) && defined(CONFIG_BT_PER_ADV)
cmd_per_adv_set_info_transfer(const struct shell * sh,size_t argc,char * argv[])3143 static int cmd_per_adv_set_info_transfer(const struct shell *sh, size_t argc,
3144 char *argv[])
3145 {
3146 const struct bt_le_ext_adv *adv = adv_sets[selected_adv];
3147 int err;
3148
3149 if (default_conn == NULL) {
3150 shell_error(sh, "%s: at least, one connection is required",
3151 sh->ctx->active_cmd.syntax);
3152 return -ENOEXEC;
3153 }
3154
3155 err = bt_le_per_adv_set_info_transfer(adv, default_conn, 0U);
3156 if (err) {
3157 shell_error(sh, "Periodic advertising sync transfer failed (%d)", err);
3158 }
3159
3160 return err;
3161 }
3162 #endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER && CONFIG_BT_PER_ADV */
3163
3164 #if defined(CONFIG_BT_TRANSMIT_POWER_CONTROL)
cmd_read_remote_tx_power(const struct shell * sh,size_t argc,char * argv[])3165 static int cmd_read_remote_tx_power(const struct shell *sh, size_t argc, char *argv[])
3166 {
3167 if (argc < 3) {
3168 int err = 0;
3169 enum bt_conn_le_tx_power_phy phy = strtoul(argv[1], NULL, 16);
3170
3171 err = bt_conn_le_get_remote_tx_power_level(default_conn, phy);
3172
3173 if (!err) {
3174 shell_print(sh, "Read Remote TX Power for PHY %s",
3175 tx_pwr_ctrl_phy2str(phy));
3176 } else {
3177 shell_print(sh, "error %d", err);
3178 }
3179 } else {
3180 shell_help(sh);
3181 return SHELL_CMD_HELP_PRINTED;
3182 }
3183 return 0;
3184 }
3185
cmd_read_local_tx_power(const struct shell * sh,size_t argc,char * argv[])3186 static int cmd_read_local_tx_power(const struct shell *sh, size_t argc, char *argv[])
3187 {
3188 int err = 0;
3189
3190 if (argc < 3) {
3191 struct bt_conn_le_tx_power tx_power_level;
3192
3193 tx_power_level.phy = strtoul(argv[1], NULL, 16);
3194
3195 int8_t unachievable_current_level = -100;
3196 /* Arbitrary, these are output parameters.*/
3197 tx_power_level.current_level = unachievable_current_level;
3198 tx_power_level.max_level = 6;
3199
3200 if (default_conn == NULL) {
3201 shell_error(sh, "Conn handle error, at least one connection is required.");
3202 return -ENOEXEC;
3203 }
3204 err = bt_conn_le_get_tx_power_level(default_conn, &tx_power_level);
3205 if (err) {
3206 shell_print(sh, "Command returned error %d", err);
3207 return err;
3208 }
3209 if (tx_power_level.current_level == unachievable_current_level) {
3210 shell_print(sh, "We received no current tx power level.");
3211 return -EIO;
3212 }
3213 shell_print(sh, "Read local TX Power: current level: %d, PHY: %s, Max Level: %d",
3214 tx_power_level.current_level,
3215 tx_pwr_ctrl_phy2str((enum bt_conn_le_tx_power_phy)tx_power_level.phy),
3216 tx_power_level.max_level);
3217 } else {
3218 shell_help(sh);
3219 return SHELL_CMD_HELP_PRINTED;
3220 }
3221
3222 return err;
3223 }
3224
cmd_set_power_report_enable(const struct shell * sh,size_t argc,char * argv[])3225 static int cmd_set_power_report_enable(const struct shell *sh, size_t argc, char *argv[])
3226 {
3227 if (argc < 4) {
3228 int err = 0;
3229 bool local_enable = 0;
3230 bool remote_enable = 0;
3231
3232 if (*argv[1] == '1') {
3233 local_enable = 1;
3234 }
3235 if (*argv[2] == '1') {
3236 remote_enable = 1;
3237 }
3238 if (default_conn == NULL) {
3239 shell_error(sh, "Conn handle error, at least one connection is required.");
3240 return -ENOEXEC;
3241 }
3242 err = bt_conn_le_set_tx_power_report_enable(default_conn, local_enable,
3243 remote_enable);
3244 if (!err) {
3245 shell_print(sh, "Tx Power Report: local: %s, remote: %s",
3246 enabled2str(local_enable), enabled2str(remote_enable));
3247 } else {
3248 shell_print(sh, "error %d", err);
3249 }
3250 } else {
3251 shell_help(sh);
3252 return SHELL_CMD_HELP_PRINTED;
3253 }
3254 return 0;
3255 }
3256
3257 #endif
3258
3259 #if defined(CONFIG_BT_PATH_LOSS_MONITORING)
cmd_set_path_loss_reporting_parameters(const struct shell * sh,size_t argc,char * argv[])3260 static int cmd_set_path_loss_reporting_parameters(const struct shell *sh, size_t argc, char *argv[])
3261 {
3262 int err = 0;
3263
3264 if (default_conn == NULL) {
3265 shell_error(sh, "Conn handle error, at least one connection is required.");
3266 return -ENOEXEC;
3267 }
3268
3269 for (size_t argn = 1; argn < argc; argn++) {
3270 (void)shell_strtoul(argv[argn], 10, &err);
3271
3272 if (err) {
3273 shell_help(sh);
3274 shell_error(sh, "Could not parse input number %d", argn);
3275 return SHELL_CMD_HELP_PRINTED;
3276 }
3277 }
3278
3279 const struct bt_conn_le_path_loss_reporting_param params = {
3280 .high_threshold = shell_strtoul(argv[1], 10, &err),
3281 .high_hysteresis = shell_strtoul(argv[2], 10, &err),
3282 .low_threshold = shell_strtoul(argv[3], 10, &err),
3283 .low_hysteresis = shell_strtoul(argv[4], 10, &err),
3284 .min_time_spent = shell_strtoul(argv[5], 10, &err),
3285 };
3286
3287 err = bt_conn_le_set_path_loss_mon_param(default_conn, ¶ms);
3288 if (err) {
3289 shell_error(sh, "bt_conn_le_set_path_loss_mon_param returned error %d", err);
3290 return -ENOEXEC;
3291 }
3292
3293 return 0;
3294 }
3295
cmd_set_path_loss_reporting_enable(const struct shell * sh,size_t argc,char * argv[])3296 static int cmd_set_path_loss_reporting_enable(const struct shell *sh, size_t argc, char *argv[])
3297 {
3298 bool enable;
3299 int err = 0;
3300
3301 if (default_conn == NULL) {
3302 shell_error(sh, "Conn handle error, at least one connection is required.");
3303 return -ENOEXEC;
3304 }
3305
3306 enable = shell_strtobool(argv[1], 10, &err);
3307 if (err) {
3308 shell_help(sh);
3309 return SHELL_CMD_HELP_PRINTED;
3310 }
3311
3312 err = bt_conn_le_set_path_loss_mon_enable(default_conn, enable);
3313
3314 if (err) {
3315 shell_error(sh, "bt_conn_le_set_path_loss_mon_enable returned error %d", err);
3316 return -ENOEXEC;
3317 }
3318
3319 return 0;
3320 }
3321 #endif
3322
3323 #if defined(CONFIG_BT_SUBRATING)
cmd_subrate_set_defaults(const struct shell * sh,size_t argc,char * argv[])3324 static int cmd_subrate_set_defaults(const struct shell *sh, size_t argc, char *argv[])
3325 {
3326 int err = 0;
3327
3328 for (size_t argn = 1; argn < argc; argn++) {
3329 (void)shell_strtoul(argv[argn], 10, &err);
3330
3331 if (err) {
3332 shell_help(sh);
3333 shell_error(sh, "Could not parse input number %d", argn);
3334 return SHELL_CMD_HELP_PRINTED;
3335 }
3336 }
3337
3338 const struct bt_conn_le_subrate_param params = {
3339 .subrate_min = shell_strtoul(argv[1], 10, &err),
3340 .subrate_max = shell_strtoul(argv[2], 10, &err),
3341 .max_latency = shell_strtoul(argv[3], 10, &err),
3342 .continuation_number = shell_strtoul(argv[4], 10, &err),
3343 .supervision_timeout = shell_strtoul(argv[5], 10, &err) * 100, /* 10ms units */
3344 };
3345
3346 err = bt_conn_le_subrate_set_defaults(¶ms);
3347 if (err) {
3348 shell_error(sh, "bt_conn_le_subrate_set_defaults returned error %d", err);
3349 return -ENOEXEC;
3350 }
3351
3352 return 0;
3353 }
3354
cmd_subrate_request(const struct shell * sh,size_t argc,char * argv[])3355 static int cmd_subrate_request(const struct shell *sh, size_t argc, char *argv[])
3356 {
3357 int err = 0;
3358
3359 if (default_conn == NULL) {
3360 shell_error(sh, "Conn handle error, at least one connection is required.");
3361 return -ENOEXEC;
3362 }
3363
3364 for (size_t argn = 1; argn < argc; argn++) {
3365 (void)shell_strtoul(argv[argn], 10, &err);
3366
3367 if (err) {
3368 shell_help(sh);
3369 shell_error(sh, "Could not parse input number %d", argn);
3370 return SHELL_CMD_HELP_PRINTED;
3371 }
3372 }
3373
3374 const struct bt_conn_le_subrate_param params = {
3375 .subrate_min = shell_strtoul(argv[1], 10, &err),
3376 .subrate_max = shell_strtoul(argv[2], 10, &err),
3377 .max_latency = shell_strtoul(argv[3], 10, &err),
3378 .continuation_number = shell_strtoul(argv[4], 10, &err),
3379 .supervision_timeout = shell_strtoul(argv[5], 10, &err) * 100, /* 10ms units */
3380 };
3381
3382 err = bt_conn_le_subrate_request(default_conn, ¶ms);
3383 if (err) {
3384 shell_error(sh, "bt_conn_le_subrate_request returned error %d", err);
3385 return -ENOEXEC;
3386 }
3387
3388 return 0;
3389 }
3390
3391 #if defined(CONFIG_BT_SHORTER_CONNECTION_INTERVALS)
cmd_read_min_conn_interval_groups(const struct shell * sh,size_t argc,char * argv[])3392 static int cmd_read_min_conn_interval_groups(const struct shell *sh, size_t argc, char *argv[])
3393 {
3394 int err;
3395 struct bt_conn_le_min_conn_interval_info info;
3396
3397 err = bt_conn_le_read_min_conn_interval_groups(&info);
3398 if (err != 0) {
3399 shell_error(sh, "bt_conn_le_read_min_conn_interval_groups returned error %d", err);
3400 return -ENOEXEC;
3401 }
3402
3403 shell_print(sh, "Minimum supported connection interval: %u us",
3404 info.min_supported_conn_interval_us);
3405 shell_print(sh, "Number of groups: %u", info.num_groups);
3406
3407 for (uint8_t i = 0; i < info.num_groups; i++) {
3408 shell_print(
3409 sh,
3410 " Group %u: min=0x%04x (%u us), max=0x%04x (%u us), stride=0x%04x (%u us)",
3411 i,
3412 info.groups[i].min_125us,
3413 BT_CONN_SCI_INTERVAL_TO_US(info.groups[i].min_125us),
3414 info.groups[i].max_125us,
3415 BT_CONN_SCI_INTERVAL_TO_US(info.groups[i].max_125us),
3416 info.groups[i].stride_125us,
3417 BT_CONN_SCI_INTERVAL_TO_US(info.groups[i].stride_125us));
3418 }
3419
3420 return 0;
3421 }
3422
cmd_read_min_conn_interval(const struct shell * sh,size_t argc,char * argv[])3423 static int cmd_read_min_conn_interval(const struct shell *sh, size_t argc, char *argv[])
3424 {
3425 int err;
3426 uint16_t min_interval_us;
3427
3428 err = bt_conn_le_read_min_conn_interval(&min_interval_us);
3429 if (err != 0) {
3430 shell_error(sh, "bt_conn_le_read_min_conn_interval returned error %d", err);
3431 return -ENOEXEC;
3432 }
3433
3434 shell_print(sh, "Minimum supported connection interval: %u us", min_interval_us);
3435 return 0;
3436 }
3437
cmd_conn_rate_set_defaults(const struct shell * sh,size_t argc,char * argv[])3438 static int cmd_conn_rate_set_defaults(const struct shell *sh, size_t argc, char *argv[])
3439 {
3440 int err = 0;
3441
3442 for (size_t argn = 1; argn < argc; argn++) {
3443 (void)shell_strtoul(argv[argn], 10, &err);
3444
3445 if (err != 0) {
3446 shell_help(sh);
3447 shell_error(sh, "Could not parse input number %zu", argn);
3448 return SHELL_CMD_HELP_PRINTED;
3449 }
3450 }
3451
3452 const struct bt_conn_le_conn_rate_param params = {
3453 .interval_min_125us = shell_strtoul(argv[1], 10, &err),
3454 .interval_max_125us = shell_strtoul(argv[2], 10, &err),
3455 .subrate_min = shell_strtoul(argv[3], 10, &err),
3456 .subrate_max = shell_strtoul(argv[4], 10, &err),
3457 .max_latency = shell_strtoul(argv[5], 10, &err),
3458 .continuation_number = shell_strtoul(argv[6], 10, &err),
3459 .supervision_timeout_10ms = shell_strtoul(argv[7], 10, &err),
3460 .min_ce_len_125us = shell_strtoul(argv[8], 10, &err),
3461 .max_ce_len_125us = shell_strtoul(argv[9], 10, &err),
3462 };
3463
3464 err = bt_conn_le_conn_rate_set_defaults(¶ms);
3465 if (err != 0) {
3466 shell_error(sh, "bt_conn_le_conn_rate_set_defaults returned error %d", err);
3467 return -ENOEXEC;
3468 }
3469
3470 return 0;
3471 }
3472
cmd_conn_rate_request(const struct shell * sh,size_t argc,char * argv[])3473 static int cmd_conn_rate_request(const struct shell *sh, size_t argc, char *argv[])
3474 {
3475 int err = 0;
3476
3477 if (default_conn == NULL) {
3478 shell_error(sh, "Conn handle error, at least one connection is required.");
3479 return -ENOEXEC;
3480 }
3481
3482 for (size_t argn = 1; argn < argc; argn++) {
3483 (void)shell_strtoul(argv[argn], 10, &err);
3484
3485 if (err != 0) {
3486 shell_help(sh);
3487 shell_error(sh, "Could not parse input number %zu", argn);
3488 return SHELL_CMD_HELP_PRINTED;
3489 }
3490 }
3491
3492 const struct bt_conn_le_conn_rate_param params = {
3493 .interval_min_125us = shell_strtoul(argv[1], 10, &err),
3494 .interval_max_125us = shell_strtoul(argv[2], 10, &err),
3495 .subrate_min = shell_strtoul(argv[3], 10, &err),
3496 .subrate_max = shell_strtoul(argv[4], 10, &err),
3497 .max_latency = shell_strtoul(argv[5], 10, &err),
3498 .continuation_number = shell_strtoul(argv[6], 10, &err),
3499 .supervision_timeout_10ms = shell_strtoul(argv[7], 10, &err),
3500 .min_ce_len_125us = shell_strtoul(argv[8], 10, &err),
3501 .max_ce_len_125us = shell_strtoul(argv[9], 10, &err),
3502 };
3503
3504 err = bt_conn_le_conn_rate_request(default_conn, ¶ms);
3505 if (err != 0) {
3506 shell_error(sh, "bt_conn_le_conn_rate_request returned error %d", err);
3507 return -ENOEXEC;
3508 }
3509
3510 return 0;
3511 }
3512 #endif /* CONFIG_BT_SHORTER_CONNECTION_INTERVALS */
3513 #endif /* CONFIG_BT_SUBRATING */
3514
3515 #if defined(CONFIG_BT_LE_EXTENDED_FEAT_SET)
cmd_read_all_remote_features(const struct shell * sh,size_t argc,char * argv[])3516 static int cmd_read_all_remote_features(const struct shell *sh, size_t argc, char *argv[])
3517 {
3518 int err = 0;
3519
3520 if (default_conn == NULL) {
3521 shell_error(sh, "Conn handle error, at least one connection is required.");
3522 return -ENOEXEC;
3523 }
3524
3525 uint8_t pages_requested = shell_strtoul(argv[1], 10, &err);
3526
3527 if (err != 0) {
3528 shell_help(sh);
3529 shell_error(sh, "Could not parse input for pages_requested");
3530 return SHELL_CMD_HELP_PRINTED;
3531 }
3532
3533 err = bt_conn_le_read_all_remote_features(default_conn, pages_requested);
3534 if (err != 0) {
3535 shell_error(sh, "bt_conn_le_read_all_remote_features returned error %d", err);
3536 return -ENOEXEC;
3537 }
3538
3539 return 0;
3540 }
3541 #endif
3542
3543 #if defined(CONFIG_BT_FRAME_SPACE_UPDATE)
cmd_frame_space_update(const struct shell * sh,size_t argc,char * argv[])3544 static int cmd_frame_space_update(const struct shell *sh, size_t argc, char *argv[])
3545 {
3546 int err = 0;
3547 struct bt_conn_le_frame_space_update_param params;
3548
3549 if (default_conn == NULL) {
3550 shell_error(sh, "Conn handle error, at least one connection is required.");
3551 return -ENOEXEC;
3552 }
3553
3554 params.frame_space_min = shell_strtoul(argv[1], 10, &err);
3555 if (err) {
3556 shell_help(sh);
3557 shell_error(sh, "Could not parse frame_space_min input");
3558 return SHELL_CMD_HELP_PRINTED;
3559 }
3560
3561 params.frame_space_max = shell_strtoul(argv[2], 10, &err);
3562 if (err) {
3563 shell_help(sh);
3564 shell_error(sh, "Could not parse frame_space_max input");
3565 return SHELL_CMD_HELP_PRINTED;
3566 }
3567
3568 params.phys = shell_strtoul(argv[3], 16, &err);
3569 if (err) {
3570 shell_help(sh);
3571 shell_error(sh, "Could not parse phys input");
3572 return SHELL_CMD_HELP_PRINTED;
3573 }
3574
3575 params.spacing_types = shell_strtoul(argv[4], 16, &err);
3576 if (err) {
3577 shell_help(sh);
3578 shell_error(sh, "Could not parse spacing_types input");
3579 return SHELL_CMD_HELP_PRINTED;
3580 }
3581
3582 err = bt_conn_le_frame_space_update(default_conn, ¶ms);
3583 if (err != 0) {
3584 shell_error(sh, "bt_conn_le_frame_space_update returned error %d", err);
3585 return -ENOEXEC;
3586 }
3587
3588 return 0;
3589 }
3590 #endif
3591
3592 #if defined(CONFIG_BT_CONN)
3593 #if defined(CONFIG_BT_CENTRAL)
bt_do_connect_le(int * ercd,size_t argc,char * argv[])3594 static int bt_do_connect_le(int *ercd, size_t argc, char *argv[])
3595 {
3596 struct bt_le_conn_param conn_param;
3597 int err;
3598 bt_addr_le_t addr;
3599 struct bt_conn *conn = NULL;
3600 uint32_t options = 0;
3601
3602 if (IS_ENABLED(CONFIG_BT_BAP_UNICAST) || IS_ENABLED(CONFIG_BT_BAP_BROADCAST_ASSISTANT)) {
3603 conn_param = *BT_BAP_CONN_PARAM_RELAXED;
3604 } else {
3605 conn_param = *BT_LE_CONN_PARAM_DEFAULT;
3606 }
3607
3608 *ercd = 0;
3609
3610 /* When no arguments are specified, connect to the last scanned device. */
3611 if (argc == 1) {
3612 if (auto_connect.addr_set) {
3613 bt_addr_le_copy(&addr, &auto_connect.addr);
3614 } else {
3615 return -ENOENT;
3616 }
3617 } else {
3618 err = bt_addr_le_from_str(argv[1], argv[2], &addr);
3619 if (err) {
3620 *ercd = err;
3621 return -EINVAL;
3622 }
3623 }
3624
3625 #if defined(CONFIG_BT_EXT_ADV)
3626 for (size_t argn = 3; argn < argc; argn++) {
3627 const char *arg = argv[argn];
3628
3629 if (!strcmp(arg, "coded")) {
3630 options |= BT_CONN_LE_OPT_CODED;
3631 } else if (!strcmp(arg, "no-1m")) {
3632 options |= BT_CONN_LE_OPT_NO_1M;
3633 } else {
3634 return SHELL_CMD_HELP_PRINTED;
3635 }
3636 }
3637 #endif /* defined(CONFIG_BT_EXT_ADV) */
3638
3639 struct bt_conn_le_create_param *create_params =
3640 BT_CONN_LE_CREATE_PARAM(options,
3641 BT_GAP_SCAN_FAST_INTERVAL,
3642 BT_GAP_SCAN_FAST_INTERVAL);
3643
3644 err = bt_conn_le_create(&addr, create_params, &conn_param, &conn);
3645 if (err) {
3646 *ercd = err;
3647 return -ENOEXEC;
3648 } else {
3649 /* unref connection obj in advance as app user */
3650 bt_conn_unref(conn);
3651 }
3652
3653 return 0;
3654 }
3655
cmd_connect_le(const struct shell * sh,size_t argc,char * argv[])3656 static int cmd_connect_le(const struct shell *sh, size_t argc, char *argv[])
3657 {
3658 int err;
3659 int ercd;
3660
3661 err = bt_do_connect_le(&ercd, argc, argv);
3662 switch (err) {
3663 case -ENOENT:
3664 shell_error(sh, "No connectable adv stored. Please trigger a scan first.");
3665 shell_help(sh);
3666 return SHELL_CMD_HELP_PRINTED;
3667 case -EINVAL:
3668 shell_error(sh, "Invalid peer address (err %d)", ercd);
3669 return ercd;
3670 case SHELL_CMD_HELP_PRINTED:
3671 shell_help(sh);
3672 return SHELL_CMD_HELP_PRINTED;
3673 case -ENOEXEC:
3674 shell_error(sh, "Connection failed (%d)", ercd);
3675 return -ENOEXEC;
3676 default:
3677 shell_print(sh, "Connection pending");
3678 return 0;
3679 }
3680 }
3681
cmd_connect_le_name(const struct shell * sh,size_t argc,char * argv[])3682 static int cmd_connect_le_name(const struct shell *sh, size_t argc, char *argv[])
3683 {
3684 const struct bt_le_scan_param param = {
3685 .type = BT_LE_SCAN_TYPE_ACTIVE,
3686 .options = BT_LE_SCAN_OPT_NONE,
3687 .interval = BT_GAP_SCAN_FAST_INTERVAL,
3688 .window = BT_GAP_SCAN_FAST_WINDOW,
3689 .timeout = 0,
3690 };
3691 int err;
3692
3693 /* Set the name filter which we will use in the scan callback to
3694 * automatically connect to the first device that passes the filter
3695 */
3696 err = cmd_scan_filter_set_name(sh, argc, argv);
3697 if (err) {
3698 shell_error(sh, "Bluetooth set scan filter name to %s failed (err %d)",
3699 argv[1], err);
3700 return err;
3701 }
3702
3703 err = bt_le_scan_start(¶m, NULL);
3704 if (err) {
3705 shell_error(sh, "Bluetooth scan failed (err %d)", err);
3706 return err;
3707 }
3708
3709 shell_print(sh, "Bluetooth active scan enabled");
3710
3711 /* Set boolean to tell the scan callback to connect to this name */
3712 auto_connect.connect_name = true;
3713
3714 /* Schedule the k_work to act as a timeout */
3715 (void)k_work_reschedule(&active_scan_timeout_work, K_SECONDS(DEFAULT_SCAN_TIMEOUT_SEC));
3716
3717 return 0;
3718 }
3719 #endif /* CONFIG_BT_CENTRAL */
3720
cmd_disconnect(const struct shell * sh,size_t argc,char * argv[])3721 static int cmd_disconnect(const struct shell *sh, size_t argc, char *argv[])
3722 {
3723 struct bt_conn *conn;
3724 int err;
3725
3726 if (default_conn && argc < 3) {
3727 conn = bt_conn_ref(default_conn);
3728 } else {
3729 bt_addr_le_t addr;
3730
3731 if (argc < 3) {
3732 shell_help(sh);
3733 return SHELL_CMD_HELP_PRINTED;
3734 }
3735
3736 err = bt_addr_le_from_str(argv[1], argv[2], &addr);
3737 if (err) {
3738 shell_error(sh, "Invalid peer address (err %d)", err);
3739 return err;
3740 }
3741
3742 conn = bt_conn_lookup_addr_le(selected_id, &addr);
3743 }
3744
3745 if (!conn) {
3746 shell_error(sh, "Not connected");
3747 return -ENOEXEC;
3748 }
3749
3750 err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
3751 if (err) {
3752 shell_error(sh, "Disconnection failed (err %d)", err);
3753 return err;
3754 }
3755
3756 bt_conn_unref(conn);
3757
3758 return 0;
3759 }
3760
cmd_select(const struct shell * sh,size_t argc,char * argv[])3761 static int cmd_select(const struct shell *sh, size_t argc, char *argv[])
3762 {
3763 char addr_str[BT_ADDR_LE_STR_LEN];
3764 struct bt_conn *conn;
3765 bt_addr_le_t addr;
3766 int err;
3767
3768 err = bt_addr_le_from_str(argv[1], argv[2], &addr);
3769 if (err) {
3770 shell_error(sh, "Invalid peer address (err %d)", err);
3771 return err;
3772 }
3773
3774 conn = bt_conn_lookup_addr_le(selected_id, &addr);
3775 if (!conn) {
3776 shell_error(sh, "No matching connection found");
3777 return -ENOEXEC;
3778 }
3779
3780 if (default_conn) {
3781 bt_conn_unref(default_conn);
3782 }
3783
3784 default_conn = conn;
3785
3786 bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));
3787 shell_print(sh, "Selected conn is now: %s", addr_str);
3788
3789 return 0;
3790 }
3791
get_conn_type_str(uint8_t type)3792 static const char *get_conn_type_str(uint8_t type)
3793 {
3794 switch (type) {
3795 case BT_CONN_TYPE_LE: return "LE";
3796 case BT_CONN_TYPE_BR: return "BR/EDR";
3797 case BT_CONN_TYPE_SCO: return "SCO";
3798 default: return "Invalid";
3799 }
3800 }
3801
get_conn_role_str(uint8_t role)3802 static const char *get_conn_role_str(uint8_t role)
3803 {
3804 switch (role) {
3805 case BT_CONN_ROLE_CENTRAL: return "central";
3806 case BT_CONN_ROLE_PERIPHERAL: return "peripheral";
3807 default: return "Invalid";
3808 }
3809 }
3810
cmd_info(const struct shell * sh,size_t argc,char * argv[])3811 static int cmd_info(const struct shell *sh, size_t argc, char *argv[])
3812 {
3813 struct bt_conn *conn = NULL;
3814 struct bt_conn_info info;
3815 bt_addr_le_t addr;
3816 int err;
3817
3818 switch (argc) {
3819 case 1:
3820 if (default_conn) {
3821 conn = bt_conn_ref(default_conn);
3822 }
3823 break;
3824 case 2:
3825 addr.type = BT_ADDR_LE_PUBLIC;
3826 err = bt_addr_from_str(argv[1], &addr.a);
3827 if (err) {
3828 shell_error(sh, "Invalid peer address (err %d)", err);
3829 return err;
3830 }
3831 conn = bt_conn_lookup_addr_le(selected_id, &addr);
3832 break;
3833 case 3:
3834 err = bt_addr_le_from_str(argv[1], argv[2], &addr);
3835
3836 if (err) {
3837 shell_error(sh, "Invalid peer address (err %d)", err);
3838 return err;
3839 }
3840 conn = bt_conn_lookup_addr_le(selected_id, &addr);
3841 break;
3842 }
3843
3844 if (!conn) {
3845 shell_error(sh, "Not connected");
3846 return -ENOEXEC;
3847 }
3848
3849 err = bt_conn_get_info(conn, &info);
3850 if (err) {
3851 shell_print(sh, "Failed to get info");
3852 goto done;
3853 }
3854
3855 shell_print(sh, "Type: %s, Role: %s, Id: %u",
3856 get_conn_type_str(info.type),
3857 get_conn_role_str(info.role),
3858 info.id);
3859
3860 if (info.type == BT_CONN_TYPE_LE) {
3861 print_le_addr("Remote", info.le.dst);
3862 print_le_addr("Local", info.le.src);
3863 print_le_addr("Remote on-air", info.le.remote);
3864 print_le_addr("Local on-air", info.le.local);
3865
3866 shell_print(sh, "Interval: %u us", info.le.interval_us);
3867 shell_print(sh, "Latency: 0x%04x",
3868 info.le.latency);
3869 shell_print(sh, "Supervision timeout: 0x%04x (%d ms)",
3870 info.le.timeout, info.le.timeout * 10);
3871 #if defined(CONFIG_BT_USER_PHY_UPDATE)
3872 shell_print(sh, "LE PHY: TX PHY %s, RX PHY %s",
3873 phy2str(info.le.phy->tx_phy),
3874 phy2str(info.le.phy->rx_phy));
3875 #endif
3876 #if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
3877 shell_print(sh, "LE data len: TX (len: %d time: %d) RX (len: %d time: %d)",
3878 info.le.data_len->tx_max_len, info.le.data_len->tx_max_time,
3879 info.le.data_len->rx_max_len, info.le.data_len->rx_max_time);
3880 #endif
3881 #if defined(CONFIG_BT_SUBRATING)
3882 shell_print(sh, "LE Subrating: Subrate Factor: %d Continuation Number: %d",
3883 info.le.subrate->factor, info.le.subrate->continuation_number);
3884 #endif
3885 }
3886
3887 #if defined(CONFIG_BT_CLASSIC)
3888 if (info.type == BT_CONN_TYPE_BR) {
3889 char addr_str[BT_ADDR_STR_LEN];
3890
3891 bt_addr_to_str(info.br.dst, addr_str, sizeof(addr_str));
3892 shell_print(sh, "Peer address %s", addr_str);
3893 }
3894 #endif /* defined(CONFIG_BT_CLASSIC) */
3895
3896 done:
3897 bt_conn_unref(conn);
3898
3899 return err;
3900 }
3901
cmd_conn_update(const struct shell * sh,size_t argc,char * argv[])3902 static int cmd_conn_update(const struct shell *sh, size_t argc, char *argv[])
3903 {
3904 struct bt_le_conn_param param;
3905 int err;
3906
3907 if (default_conn == NULL) {
3908 shell_error(sh, "%s: at least, one connection is required",
3909 sh->ctx->active_cmd.syntax);
3910 return -ENOEXEC;
3911 }
3912
3913 param.interval_min = strtoul(argv[1], NULL, 16);
3914 param.interval_max = strtoul(argv[2], NULL, 16);
3915 param.latency = strtoul(argv[3], NULL, 16);
3916 param.timeout = strtoul(argv[4], NULL, 16);
3917
3918 err = bt_conn_le_param_update(default_conn, ¶m);
3919 if (err) {
3920 shell_error(sh, "conn update failed (err %d).", err);
3921 } else {
3922 shell_print(sh, "conn update initiated.");
3923 }
3924
3925 return err;
3926 }
3927
3928 #if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
tx_time_calc(uint8_t phy,uint16_t max_len)3929 static uint16_t tx_time_calc(uint8_t phy, uint16_t max_len)
3930 {
3931 /* Access address + header + payload + MIC + CRC */
3932 uint16_t total_len = 4 + 2 + max_len + 4 + 3;
3933
3934 switch (phy) {
3935 case BT_GAP_LE_PHY_1M:
3936 /* 1 byte preamble, 8 us per byte */
3937 return 8 * (1 + total_len);
3938 case BT_GAP_LE_PHY_2M:
3939 /* 2 byte preamble, 4 us per byte */
3940 return 4 * (2 + total_len);
3941 case BT_GAP_LE_PHY_CODED:
3942 /* S8: Preamble + CI + TERM1 + 64 us per byte + TERM2 */
3943 return 80 + 16 + 24 + 64 * (total_len) + 24;
3944 default:
3945 return 0;
3946 }
3947 }
3948
cmd_conn_data_len_update(const struct shell * sh,size_t argc,char * argv[])3949 static int cmd_conn_data_len_update(const struct shell *sh, size_t argc,
3950 char *argv[])
3951 {
3952 struct bt_conn_le_data_len_param param;
3953 int err;
3954
3955 if (default_conn == NULL) {
3956 shell_error(sh, "%s: at least, one connection is required",
3957 sh->ctx->active_cmd.syntax);
3958 return -ENOEXEC;
3959 }
3960
3961 param.tx_max_len = strtoul(argv[1], NULL, 10);
3962
3963 if (argc > 2) {
3964 param.tx_max_time = strtoul(argv[2], NULL, 10);
3965 } else {
3966 /* Assume 1M if not able to retrieve PHY */
3967 uint8_t phy = BT_GAP_LE_PHY_1M;
3968
3969 #if defined(CONFIG_BT_USER_PHY_UPDATE)
3970 struct bt_conn_info info;
3971
3972 err = bt_conn_get_info(default_conn, &info);
3973 if (!err) {
3974 phy = info.le.phy->tx_phy;
3975 }
3976 #endif
3977 param.tx_max_time = tx_time_calc(phy, param.tx_max_len);
3978 shell_print(sh, "Calculated tx time: %d", param.tx_max_time);
3979 }
3980
3981 err = bt_conn_le_data_len_update(default_conn, ¶m);
3982 if (err) {
3983 shell_error(sh, "data len update failed (err %d).", err);
3984 } else {
3985 shell_print(sh, "data len update initiated.");
3986 }
3987
3988 return err;
3989 }
3990 #endif
3991
3992 #if defined(CONFIG_BT_USER_PHY_UPDATE)
cmd_conn_phy_update(const struct shell * sh,size_t argc,char * argv[])3993 static int cmd_conn_phy_update(const struct shell *sh, size_t argc,
3994 char *argv[])
3995 {
3996 struct bt_conn_le_phy_param param;
3997 int err;
3998
3999 if (default_conn == NULL) {
4000 shell_error(sh, "%s: at least, one connection is required",
4001 sh->ctx->active_cmd.syntax);
4002 return -ENOEXEC;
4003 }
4004
4005 param.pref_tx_phy = strtoul(argv[1], NULL, 16);
4006 param.pref_rx_phy = param.pref_tx_phy;
4007 param.options = BT_CONN_LE_PHY_OPT_NONE;
4008
4009 for (size_t argn = 2; argn < argc; argn++) {
4010 const char *arg = argv[argn];
4011
4012 if (!strcmp(arg, "s2")) {
4013 param.options |= BT_CONN_LE_PHY_OPT_CODED_S2;
4014 } else if (!strcmp(arg, "s8")) {
4015 param.options |= BT_CONN_LE_PHY_OPT_CODED_S8;
4016 } else {
4017 param.pref_rx_phy = strtoul(arg, NULL, 16);
4018 }
4019 }
4020
4021 err = bt_conn_le_phy_update(default_conn, ¶m);
4022 if (err) {
4023 shell_error(sh, "PHY update failed (err %d).", err);
4024 } else {
4025 shell_print(sh, "PHY update initiated.");
4026 }
4027
4028 return err;
4029 }
4030 #endif
4031
4032 #if defined(CONFIG_BT_CENTRAL) || defined(CONFIG_BT_BROADCASTER)
cmd_chan_map(const struct shell * sh,size_t argc,char * argv[])4033 static int cmd_chan_map(const struct shell *sh, size_t argc, char *argv[])
4034 {
4035 uint8_t chan_map[5] = {};
4036 int err;
4037
4038 if (hex2bin(argv[1], strlen(argv[1]), chan_map, 5) == 0) {
4039 shell_error(sh, "Invalid channel map");
4040 return -ENOEXEC;
4041 }
4042 sys_mem_swap(chan_map, 5);
4043
4044 err = bt_le_set_chan_map(chan_map);
4045 if (err) {
4046 shell_error(sh, "Failed to set channel map (err %d)", err);
4047 } else {
4048 shell_print(sh, "Channel map set");
4049 }
4050
4051 return err;
4052 }
4053 #endif /* CONFIG_BT_CENTRAL */
4054
cmd_oob(const struct shell * sh,size_t argc,char * argv[])4055 static int cmd_oob(const struct shell *sh, size_t argc, char *argv[])
4056 {
4057 int err;
4058
4059 err = bt_le_oob_get_local(selected_id, &oob_local);
4060 if (err) {
4061 shell_error(sh, "OOB data failed");
4062 return err;
4063 }
4064
4065 print_le_oob(sh, &oob_local);
4066
4067 return 0;
4068 }
4069
4070 #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CLASSIC)
cmd_oob_remote(const struct shell * sh,size_t argc,char * argv[])4071 static int cmd_oob_remote(const struct shell *sh, size_t argc,
4072 char *argv[])
4073 {
4074 int err;
4075 bt_addr_le_t addr;
4076
4077 err = bt_addr_le_from_str(argv[1], argv[2], &addr);
4078 if (err) {
4079 shell_error(sh, "Invalid peer address (err %d)", err);
4080 return err;
4081 }
4082
4083 bt_addr_le_copy(&oob_remote.addr, &addr);
4084
4085 if (argc == 5) {
4086 hex2bin(argv[3], strlen(argv[3]), oob_remote.le_sc_data.r,
4087 sizeof(oob_remote.le_sc_data.r));
4088 hex2bin(argv[4], strlen(argv[4]), oob_remote.le_sc_data.c,
4089 sizeof(oob_remote.le_sc_data.c));
4090 bt_le_oob_set_sc_flag(true);
4091 } else {
4092 shell_help(sh);
4093 return -ENOEXEC;
4094 }
4095
4096 return 0;
4097 }
4098
cmd_oob_clear(const struct shell * sh,size_t argc,char * argv[])4099 static int cmd_oob_clear(const struct shell *sh, size_t argc, char *argv[])
4100 {
4101 memset(&oob_remote, 0, sizeof(oob_remote));
4102 bt_le_oob_set_sc_flag(false);
4103
4104 return 0;
4105 }
4106 #endif /* CONFIG_BT_SMP || CONFIG_BT_CLASSIC) */
4107
cmd_clear(const struct shell * sh,size_t argc,char * argv[])4108 static int cmd_clear(const struct shell *sh, size_t argc, char *argv[])
4109 {
4110 bt_addr_le_t addr;
4111 int err;
4112
4113 if (strcmp(argv[1], "all") == 0) {
4114 err = bt_unpair(selected_id, NULL);
4115 if (err) {
4116 shell_error(sh, "Failed to clear pairings (err %d)", err);
4117 return err;
4118 } else {
4119 shell_print(sh, "Pairings successfully cleared");
4120 }
4121
4122 return 0;
4123 }
4124
4125 if (argc < 3) {
4126 shell_print(sh, "Both address and address type needed");
4127 return -ENOEXEC;
4128 } else {
4129 err = bt_addr_le_from_str(argv[1], argv[2], &addr);
4130 }
4131
4132 if (err) {
4133 shell_print(sh, "Invalid address");
4134 return err;
4135 }
4136
4137 err = bt_unpair(selected_id, &addr);
4138 if (err) {
4139 shell_error(sh, "Failed to clear pairing (err %d)", err);
4140 } else {
4141 shell_print(sh, "Pairing successfully cleared");
4142 }
4143
4144 return err;
4145 }
4146 #endif /* CONFIG_BT_CONN */
4147
4148 #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CLASSIC)
cmd_security(const struct shell * sh,size_t argc,char * argv[])4149 static int cmd_security(const struct shell *sh, size_t argc, char *argv[])
4150 {
4151 int err, sec;
4152 struct bt_conn_info info;
4153
4154 if (!default_conn || (bt_conn_get_info(default_conn, &info) < 0)) {
4155 shell_error(sh, "Not connected");
4156 return -ENOEXEC;
4157 }
4158
4159 if (argc < 2) {
4160 shell_print(sh, "BT_SECURITY_L%d", bt_conn_get_security(default_conn));
4161
4162 return 0;
4163 }
4164
4165 sec = *argv[1] - '0';
4166
4167 if ((info.type == BT_CONN_TYPE_BR &&
4168 (sec < BT_SECURITY_L0 || sec > BT_SECURITY_L4))) {
4169 shell_error(sh, "Invalid BR/EDR security level (%d)", sec);
4170 return -ENOEXEC;
4171 }
4172
4173 if ((info.type == BT_CONN_TYPE_LE &&
4174 (sec < BT_SECURITY_L1 || sec > BT_SECURITY_L4))) {
4175 shell_error(sh, "Invalid LE security level (%d)", sec);
4176 return -ENOEXEC;
4177 }
4178
4179 if (argc > 2) {
4180 if (!strcmp(argv[2], "force-pair")) {
4181 sec |= BT_SECURITY_FORCE_PAIR;
4182 } else {
4183 shell_help(sh);
4184 return -ENOEXEC;
4185 }
4186 }
4187
4188 err = bt_conn_set_security(default_conn, sec);
4189 if (err) {
4190 shell_error(sh, "Setting security failed (err %d)", err);
4191 }
4192
4193 return err;
4194 }
4195
cmd_bondable(const struct shell * sh,size_t argc,char * argv[])4196 static int cmd_bondable(const struct shell *sh, size_t argc, char *argv[])
4197 {
4198 const char *bondable;
4199
4200 bondable = argv[1];
4201 if (!strcmp(bondable, "on")) {
4202 bt_set_bondable(true);
4203 } else if (!strcmp(bondable, "off")) {
4204 bt_set_bondable(false);
4205 } else {
4206 shell_help(sh);
4207 return SHELL_CMD_HELP_PRINTED;
4208 }
4209
4210 return 0;
4211 }
4212
4213 #if defined(CONFIG_BT_BONDABLE_PER_CONNECTION)
cmd_conn_bondable(const struct shell * sh,size_t argc,char * argv[])4214 static int cmd_conn_bondable(const struct shell *sh, size_t argc, char *argv[])
4215 {
4216 int err = 0;
4217 bool enable;
4218
4219 if (!default_conn) {
4220 shell_error(sh, "Not connected");
4221 return -ENOEXEC;
4222 }
4223
4224 enable = shell_strtobool(argv[1], 0, &err);
4225 if (err) {
4226 shell_help(sh);
4227 return SHELL_CMD_HELP_PRINTED;
4228 }
4229
4230 shell_print(sh, "[%p] set conn bondable %s", default_conn, argv[1]);
4231
4232 err = bt_conn_set_bondable(default_conn, enable);
4233 if (err) {
4234 shell_error(sh, "Set conn bondable failed: err %d", err);
4235 return -ENOEXEC;
4236 }
4237 shell_print(sh, "Set conn bondable done");
4238 return 0;
4239 }
4240 #endif /* CONFIG_BT_BONDABLE_PER_CONNECTION */
4241
bond_info(const struct bt_bond_info * info,void * user_data)4242 static void bond_info(const struct bt_bond_info *info, void *user_data)
4243 {
4244 char addr[BT_ADDR_LE_STR_LEN];
4245 int *bond_count = user_data;
4246
4247 bt_addr_le_to_str(&info->addr, addr, sizeof(addr));
4248 bt_shell_print("Remote Identity: %s", addr);
4249 (*bond_count)++;
4250 }
4251
cmd_bonds(const struct shell * sh,size_t argc,char * argv[])4252 static int cmd_bonds(const struct shell *sh, size_t argc, char *argv[])
4253 {
4254 int bond_count = 0;
4255
4256 shell_print(sh, "Bonded devices:");
4257 bt_foreach_bond(selected_id, bond_info, &bond_count);
4258 shell_print(sh, "Total %d", bond_count);
4259
4260 return 0;
4261 }
4262
connection_info(struct bt_conn * conn,void * user_data)4263 static void connection_info(struct bt_conn *conn, void *user_data)
4264 {
4265 char addr[BT_ADDR_LE_STR_LEN];
4266 int *conn_count = user_data;
4267 struct bt_conn_info info;
4268 const char *selected;
4269 const char *role_str;
4270
4271 if (bt_conn_get_info(conn, &info) < 0) {
4272 bt_shell_error("Unable to get info: conn %p", conn);
4273 return;
4274 }
4275
4276 selected = conn == default_conn ? "*" : " ";
4277 role_str = get_conn_role_str(info.role);
4278
4279 switch (info.type) {
4280 #if defined(CONFIG_BT_CLASSIC)
4281 case BT_CONN_TYPE_BR:
4282 bt_addr_to_str(info.br.dst, addr, sizeof(addr));
4283 bt_shell_print("%s#%u [BR][%s] %s", selected, info.id, role_str, addr);
4284 break;
4285 #endif
4286 case BT_CONN_TYPE_LE:
4287 bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
4288 bt_shell_print("%s#%u [LE][%s] %s: Interval %u us, latency %u, timeout %u ms",
4289 selected, info.id, role_str, addr, info.le.interval_us,
4290 info.le.latency, info.le.timeout * 10);
4291 break;
4292 #if defined(CONFIG_BT_ISO)
4293 case BT_CONN_TYPE_ISO:
4294 bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
4295 bt_shell_print(" #%u [ISO][%s] %s", info.id, role_str, addr);
4296 break;
4297 #endif
4298 default:
4299 break;
4300 }
4301
4302 (*conn_count)++;
4303 }
4304
cmd_connections(const struct shell * sh,size_t argc,char * argv[])4305 static int cmd_connections(const struct shell *sh, size_t argc, char *argv[])
4306 {
4307 int conn_count = 0;
4308
4309 shell_print(sh, "Connected devices:");
4310 bt_conn_foreach(BT_CONN_TYPE_ALL, connection_info, &conn_count);
4311 shell_print(sh, "Total %d", conn_count);
4312
4313 return 0;
4314 }
4315
auth_passkey_display(struct bt_conn * conn,unsigned int passkey)4316 static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
4317 {
4318 char addr[BT_ADDR_LE_STR_LEN];
4319 char passkey_str[7];
4320
4321 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
4322
4323 snprintk(passkey_str, 7, "%06u", passkey);
4324
4325 bt_shell_print("Passkey for %s: %s", addr, passkey_str);
4326 }
4327
4328 #if defined(CONFIG_BT_PASSKEY_KEYPRESS)
auth_passkey_display_keypress(struct bt_conn * conn,enum bt_conn_auth_keypress type)4329 static void auth_passkey_display_keypress(struct bt_conn *conn,
4330 enum bt_conn_auth_keypress type)
4331 {
4332 char addr[BT_ADDR_LE_STR_LEN];
4333
4334 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
4335
4336 bt_shell_print("Passkey keypress notification from %s: type %d", addr, type);
4337 }
4338 #endif
4339
auth_passkey_confirm(struct bt_conn * conn,unsigned int passkey)4340 static void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey)
4341 {
4342 char addr[BT_ADDR_LE_STR_LEN];
4343 char passkey_str[7];
4344
4345 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
4346
4347 snprintk(passkey_str, 7, "%06u", passkey);
4348
4349 bt_shell_print("Confirm passkey for %s: %s", addr, passkey_str);
4350 }
4351
auth_passkey_entry(struct bt_conn * conn)4352 static void auth_passkey_entry(struct bt_conn *conn)
4353 {
4354 char addr[BT_ADDR_LE_STR_LEN];
4355
4356 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
4357
4358 bt_shell_print("Enter passkey for %s", addr);
4359 }
4360
auth_cancel(struct bt_conn * conn)4361 static void auth_cancel(struct bt_conn *conn)
4362 {
4363 char addr[BT_ADDR_LE_STR_LEN];
4364
4365 conn_addr_str(conn, addr, sizeof(addr));
4366
4367 bt_shell_print("Pairing cancelled: %s", addr);
4368
4369 /* clear connection reference for sec mode 3 pairing */
4370 if (pairing_conn) {
4371 bt_conn_unref(pairing_conn);
4372 pairing_conn = NULL;
4373 }
4374 }
4375
auth_pairing_confirm(struct bt_conn * conn)4376 static void auth_pairing_confirm(struct bt_conn *conn)
4377 {
4378 char addr[BT_ADDR_LE_STR_LEN];
4379
4380 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
4381
4382 bt_shell_print("Confirm pairing for %s", addr);
4383 }
4384
4385 #if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
oob_config_str(int oob_config)4386 static const char *oob_config_str(int oob_config)
4387 {
4388 switch (oob_config) {
4389 case BT_CONN_OOB_LOCAL_ONLY:
4390 return "Local";
4391 case BT_CONN_OOB_REMOTE_ONLY:
4392 return "Remote";
4393 case BT_CONN_OOB_BOTH_PEERS:
4394 return "Local and Remote";
4395 case BT_CONN_OOB_NO_DATA:
4396 default:
4397 return "no";
4398 }
4399 }
4400 #endif /* !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) */
4401
auth_pairing_oob_data_request(struct bt_conn * conn,struct bt_conn_oob_info * oob_info)4402 static void auth_pairing_oob_data_request(struct bt_conn *conn,
4403 struct bt_conn_oob_info *oob_info)
4404 {
4405 char addr[BT_ADDR_LE_STR_LEN];
4406 struct bt_conn_info info;
4407 int err;
4408
4409 err = bt_conn_get_info(conn, &info);
4410 if (err) {
4411 return;
4412 }
4413
4414 #if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
4415 if (oob_info->type == BT_CONN_OOB_LE_SC) {
4416 struct bt_le_oob_sc_data *oobd_local =
4417 oob_info->lesc.oob_config != BT_CONN_OOB_REMOTE_ONLY
4418 ? &oob_local.le_sc_data
4419 : NULL;
4420 struct bt_le_oob_sc_data *oobd_remote =
4421 oob_info->lesc.oob_config != BT_CONN_OOB_LOCAL_ONLY
4422 ? &oob_remote.le_sc_data
4423 : NULL;
4424
4425 if (oobd_remote &&
4426 !bt_addr_le_eq(info.le.remote, &oob_remote.addr)) {
4427 bt_addr_le_to_str(info.le.remote, addr, sizeof(addr));
4428 bt_shell_print("No OOB data available for remote %s", addr);
4429 bt_conn_auth_cancel(conn);
4430 return;
4431 }
4432
4433 if (oobd_local &&
4434 !bt_addr_le_eq(info.le.local, &oob_local.addr)) {
4435 bt_addr_le_to_str(info.le.local, addr, sizeof(addr));
4436 bt_shell_print("No OOB data available for local %s", addr);
4437 bt_conn_auth_cancel(conn);
4438 return;
4439 }
4440
4441 bt_le_oob_set_sc_data(conn, oobd_local, oobd_remote);
4442
4443 bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
4444 bt_shell_print("Set %s OOB SC data for %s, ",
4445 oob_config_str(oob_info->lesc.oob_config), addr);
4446 return;
4447 }
4448 #endif /* CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
4449
4450 bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
4451 bt_shell_print("Legacy OOB TK requested from remote %s", addr);
4452 }
4453
auth_pairing_complete(struct bt_conn * conn,bool bonded)4454 static void auth_pairing_complete(struct bt_conn *conn, bool bonded)
4455 {
4456 char addr[BT_ADDR_LE_STR_LEN];
4457 struct bt_conn_info info;
4458
4459 if (bt_conn_get_info(conn, &info) < 0) {
4460 return;
4461 }
4462
4463 switch (info.type) {
4464 case BT_CONN_TYPE_LE:
4465 bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
4466 break;
4467 case BT_CONN_TYPE_BR:
4468 bt_addr_to_str(info.br.dst, addr, sizeof(addr));
4469 break;
4470 default:
4471 bt_shell_print("Unrecognized conn type: %d", info.type);
4472 return;
4473 }
4474
4475 bt_shell_print("%s with %s", bonded ? "Bonded" : "Paired", addr);
4476 }
4477
auth_pairing_failed(struct bt_conn * conn,enum bt_security_err err)4478 static void auth_pairing_failed(struct bt_conn *conn, enum bt_security_err err)
4479 {
4480 char addr[BT_ADDR_LE_STR_LEN];
4481 struct bt_conn_info info;
4482
4483 if (bt_conn_get_info(conn, &info) < 0) {
4484 return;
4485 }
4486
4487 switch (info.type) {
4488 case BT_CONN_TYPE_LE:
4489 bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
4490 break;
4491 case BT_CONN_TYPE_BR:
4492 bt_addr_to_str(info.br.dst, addr, sizeof(addr));
4493 break;
4494 default:
4495 bt_shell_print("Unrecognized conn type: %d", info.type);
4496 return;
4497 }
4498
4499 bt_shell_print("Pairing failed with %s reason: %s (%d)", addr, security_err_str(err), err);
4500 }
4501
4502 #if defined(CONFIG_BT_CLASSIC)
auth_pincode_entry(struct bt_conn * conn,bool highsec)4503 static void auth_pincode_entry(struct bt_conn *conn, bool highsec)
4504 {
4505 char addr[BT_ADDR_STR_LEN];
4506 struct bt_conn_info info;
4507
4508 if (bt_conn_get_info(conn, &info) < 0) {
4509 return;
4510 }
4511
4512 if (info.type != BT_CONN_TYPE_BR) {
4513 return;
4514 }
4515
4516 bt_addr_to_str(info.br.dst, addr, sizeof(addr));
4517
4518 if (highsec) {
4519 bt_shell_print("Enter 16 digits wide PIN code for %s", addr);
4520 } else {
4521 bt_shell_print("Enter PIN code for %s", addr);
4522 }
4523
4524 /*
4525 * Save connection info since in security mode 3 (link level enforced
4526 * security) PIN request callback is called before connected callback
4527 */
4528 if (!default_conn && !pairing_conn) {
4529 pairing_conn = bt_conn_ref(conn);
4530 }
4531 }
4532 #endif
4533
4534 #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
pairing_accept(struct bt_conn * conn,const struct bt_conn_pairing_feat * const feat)4535 enum bt_security_err pairing_accept(struct bt_conn *conn,
4536 const struct bt_conn_pairing_feat *const feat)
4537 {
4538 if (feat != NULL) {
4539 bt_shell_print("Remote pairing features: "
4540 "IO: 0x%02x, OOB: %d, AUTH: 0x%02x, Key: %d, "
4541 "Init Kdist: 0x%02x, Resp Kdist: 0x%02x",
4542 feat->io_capability, feat->oob_data_flag,
4543 feat->auth_req, feat->max_enc_key_size,
4544 feat->init_key_dist, feat->resp_key_dist);
4545 } else {
4546 bt_shell_print("Remote pairing");
4547 }
4548
4549 return BT_SECURITY_ERR_SUCCESS;
4550 }
4551 #endif /* CONFIG_BT_SMP_APP_PAIRING_ACCEPT */
4552
bond_deleted(uint8_t id,const bt_addr_le_t * peer)4553 void bond_deleted(uint8_t id, const bt_addr_le_t *peer)
4554 {
4555 char addr[BT_ADDR_LE_STR_LEN];
4556
4557 bt_addr_le_to_str(peer, addr, sizeof(addr));
4558 bt_shell_print("Bond deleted for %s, id %u", addr, id);
4559 }
4560
4561 #if defined(CONFIG_BT_CLASSIC)
br_bond_deleted(const bt_addr_t * peer)4562 static void br_bond_deleted(const bt_addr_t *peer)
4563 {
4564 char addr[BT_ADDR_STR_LEN];
4565
4566 bt_addr_to_str(peer, addr, sizeof(addr));
4567 bt_shell_print("Classic bond deleted for %s", addr);
4568 }
4569 #endif /* CONFIG_BT_CLASSIC */
4570
4571 #if defined(CONFIG_BT_APP_PASSKEY)
4572 static uint32_t app_passkey = BT_PASSKEY_RAND;
4573
auth_app_passkey(struct bt_conn * conn)4574 static uint32_t auth_app_passkey(struct bt_conn *conn)
4575 {
4576 return app_passkey;
4577 }
4578 #endif /* CONFIG_BT_APP_PASSKEY */
4579
4580 static struct bt_conn_auth_cb auth_cb_display = {
4581 .passkey_display = auth_passkey_display,
4582 #if defined(CONFIG_BT_PASSKEY_KEYPRESS)
4583 .passkey_display_keypress = auth_passkey_display_keypress,
4584 #endif
4585 .passkey_entry = NULL,
4586 .passkey_confirm = NULL,
4587 #if defined(CONFIG_BT_CLASSIC)
4588 .pincode_entry = auth_pincode_entry,
4589 #endif
4590 .oob_data_request = NULL,
4591 .cancel = auth_cancel,
4592 .pairing_confirm = auth_pairing_confirm,
4593 #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
4594 .pairing_accept = pairing_accept,
4595 #endif
4596 #if defined(CONFIG_BT_APP_PASSKEY)
4597 .app_passkey = auth_app_passkey,
4598 #endif
4599 };
4600
4601 static struct bt_conn_auth_cb auth_cb_display_yes_no = {
4602 .passkey_display = auth_passkey_display,
4603 .passkey_entry = NULL,
4604 .passkey_confirm = auth_passkey_confirm,
4605 #if defined(CONFIG_BT_CLASSIC)
4606 .pincode_entry = auth_pincode_entry,
4607 #endif
4608 #if defined(CONFIG_BT_APP_PASSKEY)
4609 .app_passkey = auth_app_passkey,
4610 #endif
4611 .oob_data_request = NULL,
4612 .cancel = auth_cancel,
4613 .pairing_confirm = auth_pairing_confirm,
4614 #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
4615 .pairing_accept = pairing_accept,
4616 #endif
4617 };
4618
4619 static struct bt_conn_auth_cb auth_cb_input = {
4620 .passkey_display = NULL,
4621 .passkey_entry = auth_passkey_entry,
4622 .passkey_confirm = NULL,
4623 #if defined(CONFIG_BT_CLASSIC)
4624 .pincode_entry = auth_pincode_entry,
4625 #endif
4626 #if defined(CONFIG_BT_APP_PASSKEY)
4627 .app_passkey = auth_app_passkey,
4628 #endif
4629 .oob_data_request = NULL,
4630 .cancel = auth_cancel,
4631 .pairing_confirm = auth_pairing_confirm,
4632 #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
4633 .pairing_accept = pairing_accept,
4634 #endif
4635 };
4636
4637 static struct bt_conn_auth_cb auth_cb_confirm = {
4638 #if defined(CONFIG_BT_CLASSIC)
4639 .pincode_entry = auth_pincode_entry,
4640 #endif
4641 #if defined(CONFIG_BT_APP_PASSKEY)
4642 .app_passkey = auth_app_passkey,
4643 #endif
4644 .oob_data_request = NULL,
4645 .cancel = auth_cancel,
4646 .pairing_confirm = auth_pairing_confirm,
4647 #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
4648 .pairing_accept = pairing_accept,
4649 #endif
4650 };
4651
4652 static struct bt_conn_auth_cb auth_cb_all = {
4653 .passkey_display = auth_passkey_display,
4654 .passkey_entry = auth_passkey_entry,
4655 .passkey_confirm = auth_passkey_confirm,
4656 #if defined(CONFIG_BT_CLASSIC)
4657 .pincode_entry = auth_pincode_entry,
4658 #endif
4659 #if defined(CONFIG_BT_APP_PASSKEY)
4660 .app_passkey = auth_app_passkey,
4661 #endif
4662 .oob_data_request = auth_pairing_oob_data_request,
4663 .cancel = auth_cancel,
4664 .pairing_confirm = auth_pairing_confirm,
4665 #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
4666 .pairing_accept = pairing_accept,
4667 #endif
4668 };
4669
4670 static struct bt_conn_auth_cb auth_cb_oob = {
4671 .passkey_display = NULL,
4672 .passkey_entry = NULL,
4673 .passkey_confirm = NULL,
4674 #if defined(CONFIG_BT_CLASSIC)
4675 .pincode_entry = NULL,
4676 #endif
4677 .oob_data_request = auth_pairing_oob_data_request,
4678 .cancel = auth_cancel,
4679 .pairing_confirm = NULL,
4680 #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
4681 .pairing_accept = pairing_accept,
4682 #endif
4683 };
4684
4685 static struct bt_conn_auth_cb auth_cb_status = {
4686 #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
4687 .pairing_accept = pairing_accept,
4688 #endif
4689 };
4690
4691 static struct bt_conn_auth_info_cb auth_info_cb = {
4692 .pairing_failed = auth_pairing_failed,
4693 .pairing_complete = auth_pairing_complete,
4694 .bond_deleted = bond_deleted,
4695 #if defined(CONFIG_BT_CLASSIC)
4696 .br_bond_deleted = br_bond_deleted,
4697 #endif /* CONFIG_BT_CLASSIC */
4698 };
4699
cmd_auth(const struct shell * sh,size_t argc,char * argv[])4700 static int cmd_auth(const struct shell *sh, size_t argc, char *argv[])
4701 {
4702 int err;
4703
4704 if (!strcmp(argv[1], "all")) {
4705 err = bt_conn_auth_cb_register(&auth_cb_all);
4706 } else if (!strcmp(argv[1], "input")) {
4707 err = bt_conn_auth_cb_register(&auth_cb_input);
4708 } else if (!strcmp(argv[1], "display")) {
4709 err = bt_conn_auth_cb_register(&auth_cb_display);
4710 } else if (!strcmp(argv[1], "yesno")) {
4711 err = bt_conn_auth_cb_register(&auth_cb_display_yes_no);
4712 } else if (!strcmp(argv[1], "confirm")) {
4713 err = bt_conn_auth_cb_register(&auth_cb_confirm);
4714 } else if (!strcmp(argv[1], "oob")) {
4715 err = bt_conn_auth_cb_register(&auth_cb_oob);
4716 } else if (!strcmp(argv[1], "status")) {
4717 err = bt_conn_auth_cb_register(&auth_cb_status);
4718 } else if (!strcmp(argv[1], "none")) {
4719 err = bt_conn_auth_cb_register(NULL);
4720 } else {
4721 shell_help(sh);
4722 return SHELL_CMD_HELP_PRINTED;
4723 }
4724
4725 if (err) {
4726 shell_error(sh, "Failed to set auth handlers (%d)", err);
4727 }
4728
4729 return err;
4730 }
4731
cmd_auth_cancel(const struct shell * sh,size_t argc,char * argv[])4732 static int cmd_auth_cancel(const struct shell *sh,
4733 size_t argc, char *argv[])
4734 {
4735 struct bt_conn *conn;
4736
4737 if (default_conn) {
4738 conn = default_conn;
4739 } else if (pairing_conn) {
4740 conn = pairing_conn;
4741 } else {
4742 conn = NULL;
4743 }
4744
4745 if (!conn) {
4746 shell_print(sh, "Not connected");
4747 return -ENOEXEC;
4748 }
4749
4750 bt_conn_auth_cancel(conn);
4751
4752 return 0;
4753 }
4754
cmd_auth_passkey_confirm(const struct shell * sh,size_t argc,char * argv[])4755 static int cmd_auth_passkey_confirm(const struct shell *sh,
4756 size_t argc, char *argv[])
4757 {
4758 if (!default_conn) {
4759 shell_print(sh, "Not connected");
4760 return -ENOEXEC;
4761 }
4762
4763 bt_conn_auth_passkey_confirm(default_conn);
4764 return 0;
4765 }
4766
cmd_auth_pairing_confirm(const struct shell * sh,size_t argc,char * argv[])4767 static int cmd_auth_pairing_confirm(const struct shell *sh,
4768 size_t argc, char *argv[])
4769 {
4770 if (!default_conn) {
4771 shell_print(sh, "Not connected");
4772 return -ENOEXEC;
4773 }
4774
4775 bt_conn_auth_pairing_confirm(default_conn);
4776 return 0;
4777 }
4778
4779 #if defined(CONFIG_BT_FILTER_ACCEPT_LIST)
cmd_fal_add(const struct shell * sh,size_t argc,char * argv[])4780 static int cmd_fal_add(const struct shell *sh, size_t argc, char *argv[])
4781 {
4782 bt_addr_le_t addr;
4783 int err;
4784
4785 err = bt_addr_le_from_str(argv[1], argv[2], &addr);
4786 if (err) {
4787 shell_error(sh, "Invalid peer address (err %d)", err);
4788 return err;
4789 }
4790
4791 err = bt_le_filter_accept_list_add(&addr);
4792 if (err) {
4793 shell_error(sh, "Add to fa list failed (err %d)", err);
4794 return err;
4795 }
4796
4797 return 0;
4798 }
4799
cmd_fal_rem(const struct shell * sh,size_t argc,char * argv[])4800 static int cmd_fal_rem(const struct shell *sh, size_t argc, char *argv[])
4801 {
4802 bt_addr_le_t addr;
4803 int err;
4804
4805 err = bt_addr_le_from_str(argv[1], argv[2], &addr);
4806 if (err) {
4807 shell_error(sh, "Invalid peer address (err %d)", err);
4808 return err;
4809 }
4810
4811 err = bt_le_filter_accept_list_remove(&addr);
4812 if (err) {
4813 shell_error(sh, "Remove from fa list failed (err %d)", err);
4814 return err;
4815 }
4816 return 0;
4817 }
4818
cmd_fal_clear(const struct shell * sh,size_t argc,char * argv[])4819 static int cmd_fal_clear(const struct shell *sh, size_t argc, char *argv[])
4820 {
4821 int err;
4822
4823 err = bt_le_filter_accept_list_clear();
4824 if (err) {
4825 shell_error(sh, "Clearing fa list failed (err %d)", err);
4826 return err;
4827 }
4828
4829 return 0;
4830 }
4831
4832 #if defined(CONFIG_BT_CENTRAL)
cmd_fal_connect(const struct shell * sh,size_t argc,char * argv[])4833 static int cmd_fal_connect(const struct shell *sh, size_t argc, char *argv[])
4834 {
4835 int err;
4836 const char *action = argv[1];
4837 uint32_t options = 0;
4838
4839 #if defined(CONFIG_BT_EXT_ADV)
4840 for (size_t argn = 2; argn < argc; argn++) {
4841 const char *arg = argv[argn];
4842
4843 if (!strcmp(arg, "coded")) {
4844 options |= BT_CONN_LE_OPT_CODED;
4845 } else if (!strcmp(arg, "no-1m")) {
4846 options |= BT_CONN_LE_OPT_NO_1M;
4847 } else {
4848 shell_help(sh);
4849 return SHELL_CMD_HELP_PRINTED;
4850 }
4851 }
4852 #endif /* defined(CONFIG_BT_EXT_ADV) */
4853 struct bt_conn_le_create_param *create_params =
4854 BT_CONN_LE_CREATE_PARAM(options,
4855 BT_GAP_SCAN_FAST_INTERVAL,
4856 BT_GAP_SCAN_FAST_WINDOW);
4857
4858 if (!strcmp(action, "on")) {
4859 err = bt_conn_le_create_auto(create_params, BT_LE_CONN_PARAM_DEFAULT);
4860 if (err) {
4861 shell_error(sh, "Auto connect failed (err %d)", err);
4862 return err;
4863 }
4864 } else if (!strcmp(action, "off")) {
4865 err = bt_conn_create_auto_stop();
4866 if (err) {
4867 shell_error(sh, "Auto connect stop failed (err %d)", err);
4868 }
4869 return err;
4870 }
4871
4872 return 0;
4873 }
4874 #endif /* CONFIG_BT_CENTRAL */
4875 #endif /* defined(CONFIG_BT_FILTER_ACCEPT_LIST) */
4876
4877 #if defined(CONFIG_BT_APP_PASSKEY)
cmd_app_passkey(const struct shell * sh,size_t argc,char * argv[])4878 static int cmd_app_passkey(const struct shell *sh,
4879 size_t argc, char *argv[])
4880 {
4881 uint32_t passkey;
4882
4883 if (argc < 2) {
4884 app_passkey = BT_PASSKEY_RAND;
4885 shell_print(sh, "App passkey cleared");
4886 return 0;
4887 }
4888
4889 passkey = atoi(argv[1]);
4890 if (passkey > 999999) {
4891 shell_print(sh, "Passkey should be between 0-999999");
4892 return -ENOEXEC;
4893 }
4894
4895 app_passkey = passkey;
4896 shell_print(sh, "App passkey set to %06u", passkey);
4897
4898 return 0;
4899 }
4900 #endif /* CONFIG_BT_APP_PASSKEY */
4901
cmd_auth_passkey(const struct shell * sh,size_t argc,char * argv[])4902 static int cmd_auth_passkey(const struct shell *sh,
4903 size_t argc, char *argv[])
4904 {
4905 unsigned int passkey;
4906 int err;
4907
4908 if (!default_conn) {
4909 shell_print(sh, "Not connected");
4910 return -ENOEXEC;
4911 }
4912
4913 passkey = atoi(argv[1]);
4914 if (passkey > 999999) {
4915 shell_print(sh, "Passkey should be between 0-999999");
4916 return -EINVAL;
4917 }
4918
4919 err = bt_conn_auth_passkey_entry(default_conn, passkey);
4920 if (err) {
4921 shell_error(sh, "Failed to set passkey (%d)", err);
4922 return err;
4923 }
4924
4925 return 0;
4926 }
4927
4928 #if defined(CONFIG_BT_PASSKEY_KEYPRESS)
cmd_auth_passkey_notify(const struct shell * sh,size_t argc,char * argv[])4929 static int cmd_auth_passkey_notify(const struct shell *sh,
4930 size_t argc, char *argv[])
4931 {
4932 unsigned long type;
4933 int err;
4934
4935 if (!default_conn) {
4936 shell_print(sh, "Not connected");
4937 return -ENOEXEC;
4938 }
4939
4940 err = 0;
4941 type = shell_strtoul(argv[1], 0, &err);
4942 if (err ||
4943 (type != BT_CONN_AUTH_KEYPRESS_ENTRY_STARTED &&
4944 type != BT_CONN_AUTH_KEYPRESS_DIGIT_ENTERED &&
4945 type != BT_CONN_AUTH_KEYPRESS_DIGIT_ERASED && type != BT_CONN_AUTH_KEYPRESS_CLEARED &&
4946 type != BT_CONN_AUTH_KEYPRESS_ENTRY_COMPLETED)) {
4947 shell_error(sh, "<type> must be a value of enum bt_conn_auth_keypress");
4948 return -EINVAL;
4949 }
4950
4951 err = bt_conn_auth_keypress_notify(default_conn, type);
4952 if (err) {
4953 shell_error(sh, "bt_conn_auth_keypress_notify errno %d", err);
4954 return err;
4955 }
4956
4957 return 0;
4958 }
4959 #endif /* CONFIG_BT_PASSKEY_KEYPRESS */
4960
4961 #if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
cmd_auth_oob_tk(const struct shell * sh,size_t argc,char * argv[])4962 static int cmd_auth_oob_tk(const struct shell *sh, size_t argc, char *argv[])
4963 {
4964 uint8_t tk[16];
4965 size_t len;
4966 int err;
4967
4968 len = hex2bin(argv[1], strlen(argv[1]), tk, sizeof(tk));
4969 if (len != sizeof(tk)) {
4970 shell_error(sh, "TK should be 16 bytes");
4971 return -EINVAL;
4972 }
4973
4974 err = bt_le_oob_set_legacy_tk(default_conn, tk);
4975 if (err) {
4976 shell_error(sh, "Failed to set TK (%d)", err);
4977 return err;
4978 }
4979
4980 return 0;
4981 }
4982 #endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */
4983 #endif /* CONFIG_BT_SMP) || CONFIG_BT_CLASSIC */
4984
4985 #if defined(CONFIG_BT_EAD)
cmd_encrypted_ad_set_keys(const struct shell * sh,size_t argc,char * argv[])4986 static int cmd_encrypted_ad_set_keys(const struct shell *sh, size_t argc, char *argv[])
4987 {
4988 size_t len;
4989
4990 const char *session_key = argv[1];
4991 const char *iv = argv[2];
4992
4993 len = hex2bin(session_key, strlen(session_key), bt_shell_ead_session_key, BT_EAD_KEY_SIZE);
4994 if (len != BT_EAD_KEY_SIZE) {
4995 shell_error(sh, "Failed to set session key");
4996 return -ENOEXEC;
4997 }
4998
4999 len = hex2bin(iv, strlen(iv), bt_shell_ead_iv, BT_EAD_IV_SIZE);
5000 if (len != BT_EAD_IV_SIZE) {
5001 shell_error(sh, "Failed to set initialisation vector");
5002 return -ENOEXEC;
5003 }
5004
5005 shell_info(sh, "session key set to:");
5006 shell_hexdump(sh, bt_shell_ead_session_key, BT_EAD_KEY_SIZE);
5007 shell_info(sh, "initialisation vector set to:");
5008 shell_hexdump(sh, bt_shell_ead_iv, BT_EAD_IV_SIZE);
5009
5010 return 0;
5011 }
5012
encrypted_ad_store_ad(const struct shell * sh,uint8_t type,const uint8_t * data,uint8_t data_len)5013 int encrypted_ad_store_ad(const struct shell *sh, uint8_t type, const uint8_t *data,
5014 uint8_t data_len)
5015 {
5016 /* data_len is the size of the data, add two bytes for the size of the type
5017 * and the length that will be stored with the data
5018 */
5019 uint8_t new_data_size = data_len + 2;
5020
5021 if (bt_shell_ead_data_size + new_data_size > BT_SHELL_EAD_DATA_MAX_SIZE) {
5022 shell_error(sh, "Failed to add data (trying to add %d but %d already used on %d)",
5023 new_data_size, bt_shell_ead_data_size, BT_SHELL_EAD_DATA_MAX_SIZE);
5024 return -ENOEXEC;
5025 }
5026
5027 /* the length is the size of the data + the size of the type */
5028 bt_shell_ead_data[bt_shell_ead_data_size] = data_len + 1;
5029 bt_shell_ead_data[bt_shell_ead_data_size + 1] = type;
5030 memcpy(&bt_shell_ead_data[bt_shell_ead_data_size + 2], data, data_len);
5031
5032 bt_shell_ead_data_size += new_data_size;
5033 bt_shell_ead_ad_len += 1;
5034
5035 return 0;
5036 }
5037
is_payload_valid_ad(uint8_t * payload,size_t payload_size)5038 bool is_payload_valid_ad(uint8_t *payload, size_t payload_size)
5039 {
5040 size_t idx = 0;
5041 bool is_valid = true;
5042
5043 uint8_t ad_len;
5044
5045 while (idx < payload_size) {
5046 ad_len = payload[idx];
5047
5048 if (payload_size <= ad_len) {
5049 is_valid = false;
5050 break;
5051 }
5052
5053 idx += ad_len + 1;
5054 }
5055
5056 if (idx != payload_size) {
5057 is_valid = false;
5058 }
5059
5060 return is_valid;
5061 }
5062
cmd_encrypted_ad_add_ead(const struct shell * sh,size_t argc,char * argv[])5063 static int cmd_encrypted_ad_add_ead(const struct shell *sh, size_t argc, char *argv[])
5064 {
5065 size_t len;
5066
5067 char *hex_payload = argv[1];
5068 size_t hex_payload_size = strlen(hex_payload);
5069
5070 uint8_t payload[BT_SHELL_EAD_DATA_MAX_SIZE] = {0};
5071 uint8_t payload_size = hex_payload_size / 2 + hex_payload_size % 2;
5072
5073 uint8_t ead_size = BT_EAD_ENCRYPTED_PAYLOAD_SIZE(payload_size);
5074
5075 if (ead_size > BT_SHELL_EAD_DATA_MAX_SIZE) {
5076 shell_error(sh,
5077 "Failed to add data. Maximum AD size is %d, passed data size after "
5078 "encryption is %d",
5079 BT_SHELL_EAD_DATA_MAX_SIZE, ead_size);
5080 return -ENOEXEC;
5081 }
5082
5083 len = hex2bin(hex_payload, hex_payload_size, payload, BT_SHELL_EAD_DATA_MAX_SIZE);
5084 if (len != payload_size) {
5085 shell_error(sh, "Failed to add data");
5086 return -ENOEXEC;
5087 }
5088
5089 /* check that the given advertising data structures are valid before encrypting them */
5090 if (!is_payload_valid_ad(payload, payload_size)) {
5091 shell_error(sh, "Failed to add data. Advertising structure are malformed.");
5092 return -ENOEXEC;
5093 }
5094
5095 /* store not-yet encrypted AD but claim the expected size of encrypted AD */
5096 return encrypted_ad_store_ad(sh, BT_DATA_ENCRYPTED_AD_DATA, payload, ead_size);
5097 }
5098
cmd_encrypted_ad_add_ad(const struct shell * sh,size_t argc,char * argv[])5099 static int cmd_encrypted_ad_add_ad(const struct shell *sh, size_t argc, char *argv[])
5100 {
5101 size_t len;
5102 uint8_t ad_len;
5103 uint8_t ad_type;
5104
5105 char *hex_payload = argv[1];
5106 size_t hex_payload_size = strlen(hex_payload);
5107
5108 uint8_t payload[BT_SHELL_EAD_DATA_MAX_SIZE] = {0};
5109 uint8_t payload_size = hex_payload_size / 2 + hex_payload_size % 2;
5110
5111 len = hex2bin(hex_payload, hex_payload_size, payload, BT_SHELL_EAD_DATA_MAX_SIZE);
5112 if (len != payload_size) {
5113 shell_error(sh, "Failed to add data");
5114 return -ENOEXEC;
5115 }
5116
5117 /* the length received is the length of ad data + the length of the data
5118 * type but `bt_data` struct `data_len` field is only the size of the
5119 * data
5120 */
5121 ad_len = payload[0] - 1;
5122 ad_type = payload[1];
5123
5124 /* if the ad data is malformed or there is more than 1 ad data passed we
5125 * fail
5126 */
5127 if (len != ad_len + 2) {
5128 shell_error(sh,
5129 "Failed to add data. Data need to be formatted as specified in the "
5130 "Core Spec. Only one non-encrypted AD payload can be added at a time.");
5131 return -ENOEXEC;
5132 }
5133
5134 return encrypted_ad_store_ad(sh, ad_type, payload, payload_size);
5135 }
5136
cmd_encrypted_ad_clear_ad(const struct shell * sh,size_t argc,char * argv[])5137 static int cmd_encrypted_ad_clear_ad(const struct shell *sh, size_t argc, char *argv[])
5138 {
5139 memset(bt_shell_ead_data, 0, BT_SHELL_EAD_DATA_MAX_SIZE);
5140
5141 bt_shell_ead_ad_len = 0;
5142 bt_shell_ead_data_size = 0;
5143
5144 shell_info(sh, "Advertising data has been cleared.");
5145
5146 return 0;
5147 }
5148
ead_encrypt_ad(const uint8_t * payload,uint8_t payload_size,uint8_t * encrypted_payload)5149 int ead_encrypt_ad(const uint8_t *payload, uint8_t payload_size, uint8_t *encrypted_payload)
5150 {
5151 int err;
5152
5153 err = bt_ead_encrypt(bt_shell_ead_session_key, bt_shell_ead_iv, payload, payload_size,
5154 encrypted_payload);
5155 if (err != 0) {
5156 bt_shell_error("Failed to encrypt AD.");
5157 return -1;
5158 }
5159
5160 return 0;
5161 }
5162
ead_update_ad(void)5163 int ead_update_ad(void)
5164 {
5165 int err;
5166 size_t idx = 0;
5167 struct bt_le_ext_adv *adv = adv_sets[selected_adv];
5168
5169 struct bt_data *ad;
5170 size_t ad_structs_idx = 0;
5171 struct bt_data ad_structs[BT_SHELL_EAD_MAX_AD] = {0};
5172
5173 size_t encrypted_data_buf_len = 0;
5174 uint8_t encrypted_data_buf[BT_SHELL_EAD_DATA_MAX_SIZE] = {0};
5175
5176 while (idx < bt_shell_ead_data_size && ad_structs_idx < BT_SHELL_EAD_MAX_AD) {
5177 ad = &ad_structs[ad_structs_idx];
5178
5179 /* the data_len from bt_data struct doesn't include the size of the type */
5180 ad->data_len = bt_shell_ead_data[idx] - 1;
5181
5182 if (ad->data_len < 0) {
5183 /* if the len is less than 0 that mean there is not even a type field */
5184 bt_shell_error("Failed to update AD due to malformed AD.");
5185 return -ENOEXEC;
5186 }
5187
5188 ad->type = bt_shell_ead_data[idx + 1];
5189
5190 if (ad->data_len > 0) {
5191 if (ad->type == BT_DATA_ENCRYPTED_AD_DATA) {
5192 /* for EAD the size used to store the non-encrypted data
5193 * is the size of those data when encrypted
5194 */
5195 ead_encrypt_ad(&bt_shell_ead_data[idx + 2],
5196 BT_EAD_DECRYPTED_PAYLOAD_SIZE(ad->data_len),
5197 &encrypted_data_buf[encrypted_data_buf_len]);
5198
5199 ad->data = &encrypted_data_buf[encrypted_data_buf_len];
5200 encrypted_data_buf_len += ad->data_len;
5201 } else {
5202 ad->data = &bt_shell_ead_data[idx + 2];
5203 }
5204 }
5205
5206 ad_structs_idx += 1;
5207 idx += ad->data_len + 2;
5208 }
5209
5210 err = bt_le_ext_adv_set_data(adv, ad_structs, bt_shell_ead_ad_len, NULL, 0);
5211 if (err != 0) {
5212 bt_shell_error("Failed to set advertising data (err %d)", err);
5213 return -ENOEXEC;
5214 }
5215
5216 bt_shell_info("Advertising data for Advertiser[%d] %p updated.", selected_adv, adv);
5217
5218 return 0;
5219 }
5220
cmd_encrypted_ad_commit_ad(const struct shell * sh,size_t argc,char * argv[])5221 static int cmd_encrypted_ad_commit_ad(const struct shell *sh, size_t argc, char *argv[])
5222 {
5223 return ead_update_ad();
5224 }
5225
cmd_encrypted_ad_decrypt_scan(const struct shell * sh,size_t argc,char * argv[])5226 static int cmd_encrypted_ad_decrypt_scan(const struct shell *sh, size_t argc, char *argv[])
5227 {
5228 const char *action = argv[1];
5229
5230 if (strcmp(action, "on") == 0) {
5231 bt_shell_ead_decrypt_scan = true;
5232 shell_info(sh, "Received encrypted advertising data will now be decrypted using "
5233 "provided key materials.");
5234 } else if (strcmp(action, "off") == 0) {
5235 bt_shell_ead_decrypt_scan = false;
5236 shell_info(sh, "Received encrypted advertising data will now longer be decrypted.");
5237 } else {
5238 shell_error(sh, "Invalid option.");
5239 return -ENOEXEC;
5240 }
5241
5242 return 0;
5243 }
5244 #endif
5245
cmd_default_handler(const struct shell * sh,size_t argc,char ** argv)5246 static int cmd_default_handler(const struct shell *sh, size_t argc, char **argv)
5247 {
5248 if (argc == 1) {
5249 shell_help(sh);
5250 return SHELL_CMD_HELP_PRINTED;
5251 }
5252
5253 shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]);
5254
5255 return -EINVAL;
5256 }
5257
5258 #define HELP_NONE "[none]"
5259 #define HELP_ONOFF "<on, off>"
5260 #define HELP_ADDR "<address: XX:XX:XX:XX:XX:XX>"
5261 #define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
5262
5263 #if defined(CONFIG_BT_EXT_ADV)
5264 #define EXT_ADV_SCAN_OPT " [coded] [no-1m]"
5265 #define EXT_ADV_PARAM \
5266 "<type: conn-scan conn-nscan, nconn-scan nconn-nscan> " \
5267 "[ext-adv] [no-2m] [coded] [anon] [tx-power] [scan-reports] " \
5268 "[filter-accept-list: fal, fal-scan, fal-conn] [identity] " \
5269 "[directed " HELP_ADDR_LE "] [mode: low] [dir-rpa] " \
5270 "[disable-37] [disable-38] [disable-39]"
5271 #else
5272 #define EXT_ADV_SCAN_OPT ""
5273 #endif /* defined(CONFIG_BT_EXT_ADV) */
5274
5275 #if defined(CONFIG_BT_OBSERVER)
5276 SHELL_STATIC_SUBCMD_SET_CREATE(bt_scan_filter_set_cmds,
5277 SHELL_CMD_ARG(name, NULL, "<name>", cmd_scan_filter_set_name, 2, 0),
5278 SHELL_CMD_ARG(addr, NULL, HELP_ADDR, cmd_scan_filter_set_addr, 2, 0),
5279 SHELL_CMD_ARG(rssi, NULL, "<rssi>", cmd_scan_filter_set_rssi, 2, 0),
5280 SHELL_CMD_ARG(pa_interval, NULL, "<pa_interval>",
5281 cmd_scan_filter_set_pa_interval, 2, 0),
5282 SHELL_SUBCMD_SET_END
5283 );
5284
5285 SHELL_STATIC_SUBCMD_SET_CREATE(bt_scan_filter_clear_cmds,
5286 SHELL_CMD_ARG(all, NULL, "", cmd_scan_filter_clear_all, 1, 0),
5287 SHELL_CMD_ARG(name, NULL, "", cmd_scan_filter_clear_name, 1, 0),
5288 SHELL_CMD_ARG(addr, NULL, "", cmd_scan_filter_clear_addr, 1, 0),
5289 SHELL_SUBCMD_SET_END
5290 );
5291 #endif /* CONFIG_BT_OBSERVER */
5292
5293 #if defined(CONFIG_BT_EAD)
5294 SHELL_STATIC_SUBCMD_SET_CREATE(
5295 bt_encrypted_ad_cmds,
5296 SHELL_CMD_ARG(set-keys, NULL, "<session key> <init vector>", cmd_encrypted_ad_set_keys, 3,
5297 0),
5298 SHELL_CMD_ARG(add-ead, NULL, "<advertising data>", cmd_encrypted_ad_add_ead, 2, 0),
5299 SHELL_CMD_ARG(add-ad, NULL, "<advertising data>", cmd_encrypted_ad_add_ad, 2, 0),
5300 SHELL_CMD(clear-ad, NULL, HELP_NONE, cmd_encrypted_ad_clear_ad),
5301 SHELL_CMD(commit-ad, NULL, HELP_NONE, cmd_encrypted_ad_commit_ad),
5302 SHELL_CMD_ARG(decrypt-scan, NULL, HELP_ONOFF, cmd_encrypted_ad_decrypt_scan, 2, 0),
5303 SHELL_SUBCMD_SET_END);
5304 #endif
5305
5306 SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds,
5307 SHELL_CMD_ARG(init, NULL, "[no-settings-load], [sync]",
5308 cmd_init, 1, 2),
5309 SHELL_CMD_ARG(disable, NULL, HELP_NONE, cmd_disable, 1, 0),
5310 #if defined(CONFIG_SETTINGS)
5311 SHELL_CMD_ARG(settings-load, NULL, HELP_NONE, cmd_settings_load, 1, 0),
5312 #endif
5313 #if defined(CONFIG_BT_HCI)
5314 SHELL_CMD_ARG(hci-cmd, NULL, "<ogf> <ocf> [data]", cmd_hci_cmd, 3, 1),
5315 #endif
5316 SHELL_CMD_ARG(id-create, NULL, HELP_ADDR, cmd_id_create, 1, 1),
5317 SHELL_CMD_ARG(id-reset, NULL, "<id> "HELP_ADDR, cmd_id_reset, 2, 1),
5318 SHELL_CMD_ARG(id-delete, NULL, "<id>", cmd_id_delete, 2, 0),
5319 SHELL_CMD_ARG(id-show, NULL, HELP_NONE, cmd_id_show, 1, 0),
5320 SHELL_CMD_ARG(id-select, NULL, "<id>", cmd_id_select, 2, 0),
5321 SHELL_CMD_ARG(name, NULL, "[name]", cmd_name, 1, 1),
5322 #if defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC)
5323 SHELL_CMD_ARG(appearance, NULL, "[new appearance value]", cmd_appearance, 1, 1),
5324 #else
5325 SHELL_CMD_ARG(appearance, NULL, HELP_NONE, cmd_appearance, 1, 0),
5326 #endif /* CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC */
5327 #if defined(CONFIG_BT_OBSERVER)
5328 SHELL_CMD_ARG(scan, NULL,
5329 "<value: on, passive, off> [filter: dups, nodups] [fal]"
5330 EXT_ADV_SCAN_OPT,
5331 cmd_scan, 2, 4),
5332 SHELL_CMD(scan-filter-set, &bt_scan_filter_set_cmds,
5333 "Scan filter set commands",
5334 cmd_default_handler),
5335 SHELL_CMD(scan-filter-clear, &bt_scan_filter_clear_cmds,
5336 "Scan filter clear commands",
5337 cmd_default_handler),
5338 SHELL_CMD_ARG(scan-verbose-output, NULL, "<value: on, off>", cmd_scan_verbose_output, 2, 0),
5339 #endif /* CONFIG_BT_OBSERVER */
5340 #if defined(CONFIG_BT_TRANSMIT_POWER_CONTROL)
5341 SHELL_CMD_ARG(read-remote-tx-power, NULL, HELP_NONE, cmd_read_remote_tx_power, 2, 0),
5342 SHELL_CMD_ARG(read-local-tx-power, NULL, HELP_NONE, cmd_read_local_tx_power, 2, 0),
5343 SHELL_CMD_ARG(set-power-report-enable, NULL, HELP_NONE, cmd_set_power_report_enable, 3, 0),
5344 #endif
5345 #if defined(CONFIG_BT_PATH_LOSS_MONITORING)
5346 SHELL_CMD_ARG(path-loss-monitoring-set-params, NULL,
5347 "<high threshold> <high hysteresis> <low threshold> <low hysteresis> <min time spent>",
5348 cmd_set_path_loss_reporting_parameters, 6, 0),
5349 SHELL_CMD_ARG(path-loss-monitoring-enable, NULL, "<enable: true, false>",
5350 cmd_set_path_loss_reporting_enable, 2, 0),
5351 #endif
5352 #if defined(CONFIG_BT_SUBRATING)
5353 SHELL_CMD_ARG(subrate-set-defaults, NULL,
5354 "<min subrate factor> <max subrate factor> <max peripheral latency> "
5355 "<min continuation number> <supervision timeout (seconds)>",
5356 cmd_subrate_set_defaults, 6, 0),
5357 SHELL_CMD_ARG(subrate-request, NULL,
5358 "<min subrate factor> <max subrate factor> <max peripheral latency> "
5359 "<min continuation number> <supervision timeout (seconds)>",
5360 cmd_subrate_request, 6, 0),
5361 #if defined(CONFIG_BT_SHORTER_CONNECTION_INTERVALS)
5362 SHELL_CMD_ARG(read-min-conn-interval-groups, NULL,
5363 "Read minimum supported connection interval and groups",
5364 cmd_read_min_conn_interval_groups, 1, 0),
5365 SHELL_CMD_ARG(read-min-conn-interval, NULL,
5366 "Read minimum supported connection interval only",
5367 cmd_read_min_conn_interval, 1, 0),
5368 SHELL_CMD_ARG(conn-rate-set-defaults, NULL,
5369 "<min interval (125us)> <max interval (125us)> <min subrate> <max subrate> "
5370 "<max latency> <continuation number> <supervision timeout (10ms)> "
5371 "<min CE len (125us)> <max CE len (125us)>",
5372 cmd_conn_rate_set_defaults, 10, 0),
5373 SHELL_CMD_ARG(conn-rate-request, NULL,
5374 "<min interval (125us)> <max interval (125us)> <min subrate> <max subrate> "
5375 "<max latency> <continuation number> <supervision timeout (10ms)> "
5376 "<min CE len (125us)> <max CE len (125us)>",
5377 cmd_conn_rate_request, 10, 0),
5378 #endif /* CONFIG_BT_SHORTER_CONNECTION_INTERVALS */
5379 #endif /* CONFIG_BT_SUBRATING */
5380 #if defined(CONFIG_BT_LE_EXTENDED_FEAT_SET)
5381 SHELL_CMD_ARG(read-all-remote-features, NULL, "<pages_requested>",
5382 cmd_read_all_remote_features, 2, 0),
5383 #endif
5384 #if defined(CONFIG_BT_FRAME_SPACE_UPDATE)
5385 SHELL_CMD_ARG(frame-space-update, NULL,
5386 "[frame_space_min <us>] [frame_space_max <us>] [phys <phy mask>] "
5387 "[spacing_types <spacing types mask>]",
5388 cmd_frame_space_update, 5, 0),
5389 #endif
5390 #if defined(CONFIG_BT_BROADCASTER)
5391 SHELL_CMD_ARG(advertise, NULL,
5392 "<type: off, on, nconn> [mode: discov, non_discov] "
5393 "[filter-accept-list: fal, fal-scan, fal-conn] [identity] [no-name] "
5394 "[name-ad] [appearance] "
5395 "[disable-37] [disable-38] [disable-39]",
5396 cmd_advertise, 2, 8),
5397 #if defined(CONFIG_BT_PERIPHERAL)
5398 SHELL_CMD_ARG(directed-adv, NULL, HELP_ADDR_LE " [mode: low] "
5399 "[identity] [dir-rpa]",
5400 cmd_directed_adv, 3, 6),
5401 #endif /* CONFIG_BT_PERIPHERAL */
5402 #if defined(CONFIG_BT_EXT_ADV)
5403 SHELL_CMD_ARG(adv-create, NULL, EXT_ADV_PARAM, cmd_adv_create, 2, 11),
5404 SHELL_CMD_ARG(adv-param, NULL, EXT_ADV_PARAM, cmd_adv_param, 2, 11),
5405 SHELL_CMD_ARG(adv-data, NULL, "<data> [scan-response <data>] "
5406 "<type: discov, hex> [appearance] "
5407 "[name <str>] [dev-name]",
5408 cmd_adv_data, 1, 16),
5409 SHELL_CMD_ARG(adv-start, NULL,
5410 "[timeout <timeout>] [num-events <num events>]",
5411 cmd_adv_start, 1, 4),
5412 SHELL_CMD_ARG(adv-stop, NULL, HELP_NONE, cmd_adv_stop, 1, 0),
5413 SHELL_CMD_ARG(adv-delete, NULL, HELP_NONE, cmd_adv_delete, 1, 0),
5414 SHELL_CMD_ARG(adv-select, NULL, "[adv]", cmd_adv_select, 1, 1),
5415 SHELL_CMD_ARG(adv-info, NULL, HELP_NONE, cmd_adv_info, 1, 0),
5416 #if defined(CONFIG_BT_PERIPHERAL)
5417 SHELL_CMD_ARG(adv-oob, NULL, HELP_NONE, cmd_adv_oob, 1, 0),
5418 #endif /* CONFIG_BT_PERIPHERAL */
5419 #if defined(CONFIG_BT_PRIVACY)
5420 SHELL_CMD_ARG(adv-rpa-expire, NULL, HELP_ONOFF, cmd_adv_rpa_expire, 2, 0),
5421 #endif
5422 #if defined(CONFIG_BT_PER_ADV)
5423 SHELL_CMD_ARG(per-adv, NULL, HELP_ONOFF, cmd_per_adv, 2, 0),
5424 SHELL_CMD_ARG(per-adv-param, NULL,
5425 "[<interval-min> [<interval-max> [tx_power]]]",
5426 cmd_per_adv_param, 1, 3),
5427 SHELL_CMD_ARG(per-adv-data, NULL, "[data]", cmd_per_adv_data, 1, 1),
5428 #endif /* CONFIG_BT_PER_ADV */
5429 #endif /* CONFIG_BT_EXT_ADV */
5430 #endif /* CONFIG_BT_BROADCASTER */
5431 #if defined(CONFIG_BT_PER_ADV_SYNC)
5432 SHELL_CMD_ARG(per-adv-sync-create, NULL,
5433 HELP_ADDR_LE " <sid> [skip <count>] [timeout <ms>] [aoa] "
5434 "[aod_1us] [aod_2us] [cte_only]",
5435 cmd_per_adv_sync_create, 4, 6),
5436 SHELL_CMD_ARG(per-adv-sync-delete, NULL, "[<index>]",
5437 cmd_per_adv_sync_delete, 1, 1),
5438 SHELL_CMD_ARG(per-adv-sync-select, NULL, "[adv]", cmd_per_adv_sync_select, 1, 1),
5439 #endif /* defined(CONFIG_BT_PER_ADV_SYNC) */
5440 #if defined(CONFIG_BT_EAD)
5441 SHELL_CMD(encrypted-ad, &bt_encrypted_ad_cmds, "Manage advertiser with encrypted data",
5442 cmd_default_handler),
5443 #endif /* CONFIG_BT_EAD */
5444 #if defined(CONFIG_BT_CONN)
5445 #if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER)
5446 SHELL_CMD_ARG(past-subscribe, NULL, "[conn] [skip <count>] "
5447 "[timeout <ms>] [aoa] [aod_1us] [aod_2us] [cte_only]",
5448 cmd_past_subscribe, 1, 7),
5449 SHELL_CMD_ARG(past-unsubscribe, NULL, "[conn]",
5450 cmd_past_unsubscribe, 1, 1),
5451 #endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER */
5452 #if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER)
5453 #if defined(CONFIG_BT_PER_ADV_SYNC)
5454 SHELL_CMD_ARG(per-adv-sync-transfer, NULL, "[<index>]",
5455 cmd_per_adv_sync_transfer, 1, 1),
5456 #endif /* CONFIG_BT_PER_ADV_SYNC */
5457 #if defined(CONFIG_BT_PER_ADV)
5458 SHELL_CMD_ARG(per-adv-set-info-transfer, NULL, "",
5459 cmd_per_adv_set_info_transfer, 1, 0),
5460 #endif /* CONFIG_BT_PER_ADV */
5461 #endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER */
5462 #if defined(CONFIG_BT_CENTRAL)
5463 SHELL_CMD_ARG(connect, NULL, HELP_ADDR_LE EXT_ADV_SCAN_OPT,
5464 cmd_connect_le, 1, 3),
5465 SHELL_CMD_ARG(connect-name, NULL, "<name filter>",
5466 cmd_connect_le_name, 2, 0),
5467 #endif /* CONFIG_BT_CENTRAL */
5468 SHELL_CMD_ARG(disconnect, NULL, HELP_ADDR_LE, cmd_disconnect, 1, 2),
5469 SHELL_CMD_ARG(select, NULL, HELP_ADDR_LE, cmd_select, 3, 0),
5470 SHELL_CMD_ARG(info, NULL, HELP_ADDR_LE, cmd_info, 1, 2),
5471 SHELL_CMD_ARG(conn-update, NULL, "<min> <max> <latency> <timeout>",
5472 cmd_conn_update, 5, 0),
5473 #if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
5474 SHELL_CMD_ARG(data-len-update, NULL, "<tx_max_len> [tx_max_time]",
5475 cmd_conn_data_len_update, 2, 1),
5476 #endif
5477 #if defined(CONFIG_BT_USER_PHY_UPDATE)
5478 SHELL_CMD_ARG(phy-update, NULL, "<tx_phy> [rx_phy] [s2] [s8]",
5479 cmd_conn_phy_update, 2, 3),
5480 #endif
5481 #if defined(CONFIG_BT_CENTRAL) || defined(CONFIG_BT_BROADCASTER)
5482 SHELL_CMD_ARG(channel-map, NULL, "<channel-map: XXXXXXXXXX> (36-0)",
5483 cmd_chan_map, 2, 1),
5484 #endif /* CONFIG_BT_CENTRAL */
5485 SHELL_CMD_ARG(oob, NULL, HELP_NONE, cmd_oob, 1, 0),
5486 SHELL_CMD_ARG(clear, NULL, "[all] ["HELP_ADDR_LE"]", cmd_clear, 2, 1),
5487 #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CLASSIC)
5488 SHELL_CMD_ARG(security, NULL, "<security level BR/EDR: 0 - 4, "
5489 "LE: 1 - 4> [force-pair]",
5490 cmd_security, 1, 2),
5491 SHELL_CMD_ARG(bondable, NULL, HELP_ONOFF, cmd_bondable,
5492 2, 0),
5493 #if defined(CONFIG_BT_BONDABLE_PER_CONNECTION)
5494 SHELL_CMD_ARG(conn-bondable, NULL, HELP_ONOFF, cmd_conn_bondable, 2, 0),
5495 #endif /* CONFIG_BT_BONDABLE_PER_CONNECTION */
5496 SHELL_CMD_ARG(bonds, NULL, HELP_NONE, cmd_bonds, 1, 0),
5497 SHELL_CMD_ARG(connections, NULL, HELP_NONE, cmd_connections, 1, 0),
5498 SHELL_CMD_ARG(auth, NULL,
5499 "<method: all, input, display, yesno, confirm, "
5500 "oob, status, none>",
5501 cmd_auth, 2, 0),
5502 SHELL_CMD_ARG(auth-cancel, NULL, HELP_NONE, cmd_auth_cancel, 1, 0),
5503 SHELL_CMD_ARG(auth-passkey, NULL, "<passkey>", cmd_auth_passkey, 2, 0),
5504 #if defined(CONFIG_BT_PASSKEY_KEYPRESS)
5505 SHELL_CMD_ARG(auth-passkey-notify, NULL, "<type>",
5506 cmd_auth_passkey_notify, 2, 0),
5507 #endif /* CONFIG_BT_PASSKEY_KEYPRESS */
5508 SHELL_CMD_ARG(auth-passkey-confirm, NULL, HELP_NONE,
5509 cmd_auth_passkey_confirm, 1, 0),
5510 SHELL_CMD_ARG(auth-pairing-confirm, NULL, HELP_NONE,
5511 cmd_auth_pairing_confirm, 1, 0),
5512 #if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
5513 SHELL_CMD_ARG(auth-oob-tk, NULL, "<tk>", cmd_auth_oob_tk, 2, 0),
5514 #endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */
5515 SHELL_CMD_ARG(oob-remote, NULL,
5516 HELP_ADDR_LE" <oob rand> <oob confirm>",
5517 cmd_oob_remote, 3, 2),
5518 SHELL_CMD_ARG(oob-clear, NULL, HELP_NONE, cmd_oob_clear, 1, 0),
5519 #if defined(CONFIG_BT_FILTER_ACCEPT_LIST)
5520 SHELL_CMD_ARG(fal-add, NULL, HELP_ADDR_LE, cmd_fal_add, 3, 0),
5521 SHELL_CMD_ARG(fal-rem, NULL, HELP_ADDR_LE, cmd_fal_rem, 3, 0),
5522 SHELL_CMD_ARG(fal-clear, NULL, HELP_NONE, cmd_fal_clear, 1, 0),
5523
5524 #if defined(CONFIG_BT_CENTRAL)
5525 SHELL_CMD_ARG(fal-connect, NULL, HELP_ONOFF EXT_ADV_SCAN_OPT,
5526 cmd_fal_connect, 2, 3),
5527 #endif /* CONFIG_BT_CENTRAL */
5528 #endif /* defined(CONFIG_BT_FILTER_ACCEPT_LIST) */
5529 #if defined(CONFIG_BT_APP_PASSKEY)
5530 SHELL_CMD_ARG(app-passkey, NULL, "[passkey]", cmd_app_passkey,
5531 1, 1),
5532 #endif /* CONFIG_BT_APP_PASSKEY */
5533 #endif /* CONFIG_BT_SMP || CONFIG_BT_CLASSIC) */
5534 #endif /* CONFIG_BT_CONN */
5535
5536 #if defined(CONFIG_BT_LL_SW_SPLIT)
5537 SHELL_CMD(ll-addr, NULL, "<random|public>", cmd_ll_addr_read),
5538 #if defined(CONFIG_BT_CTLR_ADV_EXT)
5539 #if defined(CONFIG_BT_BROADCASTER)
5540 SHELL_CMD_ARG(advx, NULL,
5541 "<on hdcd ldcd off> [coded] [anon] [txp] [ad]",
5542 cmd_advx, 2, 4),
5543 #endif /* CONFIG_BT_BROADCASTER */
5544 #if defined(CONFIG_BT_OBSERVER)
5545 SHELL_CMD_ARG(scanx, NULL, "<on passive off> [coded]", cmd_scanx,
5546 2, 1),
5547 #endif /* CONFIG_BT_OBSERVER */
5548 #endif /* CONFIG_BT_CTLR_ADV_EXT */
5549 #if defined(CONFIG_BT_CTLR_DTM)
5550 SHELL_CMD_ARG(test_tx, NULL, "<chan> <len> <type> <phy>", cmd_test_tx,
5551 5, 0),
5552 SHELL_CMD_ARG(test_rx, NULL, "<chan> <phy> <mod_idx>", cmd_test_rx,
5553 4, 0),
5554 SHELL_CMD_ARG(test_end, NULL, HELP_NONE, cmd_test_end, 1, 0),
5555 #endif /* CONFIG_BT_CTLR_DTM */
5556 #endif /* CONFIG_BT_LL_SW_SPLIT */
5557
5558 SHELL_SUBCMD_SET_END
5559 );
5560
5561 SHELL_CMD_REGISTER(bt, &bt_cmds, "Bluetooth shell commands", cmd_default_handler);
5562