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