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