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