2017-05-22 10:17:22 +03:00
|
|
|
/** @file
|
|
|
|
* @brief Bluetooth shell module
|
|
|
|
*
|
|
|
|
* Provide some Bluetooth shell commands that can be useful to applications.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2017 Intel Corporation
|
2018-09-25 15:16:55 +02:00
|
|
|
* Copyright (c) 2018 Nordic Semiconductor ASA
|
2017-05-22 10:17:22 +03:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
#include <errno.h>
|
|
|
|
#include <zephyr/types.h>
|
2021-12-27 15:15:41 +01:00
|
|
|
#include <ctype.h>
|
2017-05-22 11:49:31 +03:00
|
|
|
#include <stddef.h>
|
2017-05-22 10:17:22 +03:00
|
|
|
#include <stdlib.h>
|
2017-05-22 11:49:31 +03:00
|
|
|
#include <string.h>
|
2021-12-27 15:15:41 +01:00
|
|
|
#include <strings.h>
|
2022-05-06 11:12:04 +02:00
|
|
|
#include <zephyr/sys/printk.h>
|
|
|
|
#include <zephyr/sys/byteorder.h>
|
|
|
|
#include <zephyr/sys/util.h>
|
includes: prefer <zephyr/kernel.h> over <zephyr/zephyr.h>
As of today <zephyr/zephyr.h> is 100% equivalent to <zephyr/kernel.h>.
This patch proposes to then include <zephyr/kernel.h> instead of
<zephyr/zephyr.h> since it is more clear that you are including the
Kernel APIs and (probably) nothing else. <zephyr/zephyr.h> sounds like a
catch-all header that may be confusing. Most applications need to
include a bunch of other things to compile, e.g. driver headers or
subsystem headers like BT, logging, etc.
The idea of a catch-all header in Zephyr is probably not feasible
anyway. Reason is that Zephyr is not a library, like it could be for
example `libpython`. Zephyr provides many utilities nowadays: a kernel,
drivers, subsystems, etc and things will likely grow. A catch-all header
would be massive, difficult to keep up-to-date. It is also likely that
an application will only build a small subset. Note that subsystem-level
headers may use a catch-all approach to make things easier, though.
NOTE: This patch is **NOT** removing the header, just removing its usage
in-tree. I'd advocate for its deprecation (add a #warning on it), but I
understand many people will have concerns.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
2022-08-25 09:58:46 +02:00
|
|
|
#include <zephyr/kernel.h>
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2022-05-06 11:12:04 +02:00
|
|
|
#include <zephyr/settings/settings.h>
|
2018-04-28 21:08:06 +03:00
|
|
|
|
2022-05-06 11:12:04 +02:00
|
|
|
#include <zephyr/bluetooth/hci.h>
|
|
|
|
#include <zephyr/bluetooth/bluetooth.h>
|
|
|
|
#include <zephyr/bluetooth/conn.h>
|
|
|
|
#include <zephyr/bluetooth/rfcomm.h>
|
|
|
|
#include <zephyr/bluetooth/sdp.h>
|
|
|
|
#include <zephyr/bluetooth/iso.h>
|
2022-07-22 13:03:55 +02:00
|
|
|
#include <zephyr/bluetooth/audio/audio.h>
|
2022-10-20 11:25:38 +02:00
|
|
|
#include <zephyr/bluetooth/audio/pacs.h>
|
2022-10-11 13:53:49 +02:00
|
|
|
#include <zephyr/bluetooth/audio/csip.h>
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2022-05-06 11:12:04 +02:00
|
|
|
#include <zephyr/shell/shell.h>
|
2017-05-22 10:17:22 +03:00
|
|
|
|
2017-05-29 12:54:56 +03:00
|
|
|
#include "bt.h"
|
2017-06-06 13:58:55 +02:00
|
|
|
#include "ll.h"
|
2019-01-09 23:14:36 +05:30
|
|
|
#include "hci.h"
|
2017-05-29 12:54:56 +03:00
|
|
|
|
2021-01-19 15:41:18 +01:00
|
|
|
static bool no_settings_load;
|
|
|
|
|
2020-09-03 21:57:47 +02:00
|
|
|
uint8_t selected_id = BT_ID_DEFAULT;
|
2018-09-24 10:59:23 +03:00
|
|
|
const struct shell *ctx_shell;
|
2018-07-16 15:11:08 +03:00
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
#if defined(CONFIG_BT_CONN)
|
|
|
|
struct bt_conn *default_conn;
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
/* Connection context for BR/EDR legacy pairing in sec mode 3 */
|
|
|
|
static struct bt_conn *pairing_conn;
|
2019-05-28 13:28:48 +02:00
|
|
|
|
|
|
|
static struct bt_le_oob oob_local;
|
2020-08-19 12:54:46 +05:30
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2019-05-28 13:28:48 +02:00
|
|
|
static struct bt_le_oob oob_remote;
|
2020-08-19 12:54:46 +05:30
|
|
|
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR) */
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2022-03-08 14:33:56 +01:00
|
|
|
#if defined(CONFIG_BT_SMP)
|
|
|
|
static struct bt_conn_auth_info_cb auth_info_cb;
|
|
|
|
#endif /* CONFIG_BT_SMP */
|
|
|
|
|
2018-06-26 13:50:14 +03:00
|
|
|
#define NAME_LEN 30
|
|
|
|
|
2019-05-28 13:28:48 +02:00
|
|
|
#define KEY_STR_LEN 33
|
|
|
|
|
2020-05-20 16:40:57 +02:00
|
|
|
/*
|
|
|
|
* Based on the maximum number of parameters for HCI_LE_Generate_DHKey
|
|
|
|
* See BT Core Spec V5.2 Vol. 4, Part E, section 7.8.37
|
|
|
|
*/
|
|
|
|
#define HCI_CMD_MAX_PARAM 65
|
|
|
|
|
2022-07-22 13:03:55 +02:00
|
|
|
enum {
|
|
|
|
SHELL_ADV_OPT_CONNECTABLE,
|
|
|
|
SHELL_ADV_OPT_DISCOVERABLE,
|
|
|
|
SHELL_ADV_OPT_EXT_ADV,
|
2022-09-27 15:47:48 +02:00
|
|
|
SHELL_ADV_OPT_APPEARANCE,
|
2022-10-13 11:27:56 +02:00
|
|
|
SHELL_ADV_OPT_KEEP_RPA,
|
2022-07-22 13:03:55 +02:00
|
|
|
|
|
|
|
SHELL_ADV_OPT_NUM,
|
|
|
|
};
|
|
|
|
|
|
|
|
static ATOMIC_DEFINE(adv_opt, SHELL_ADV_OPT_NUM);
|
2020-02-02 23:45:32 +01:00
|
|
|
#if defined(CONFIG_BT_EXT_ADV)
|
2020-08-12 14:22:51 +02:00
|
|
|
uint8_t selected_adv;
|
2020-02-02 23:45:32 +01:00
|
|
|
struct bt_le_ext_adv *adv_sets[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
|
2022-07-22 13:03:55 +02:00
|
|
|
static ATOMIC_DEFINE(adv_set_opt, SHELL_ADV_OPT_NUM)[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
|
2020-08-19 12:54:46 +05:30
|
|
|
#endif /* CONFIG_BT_EXT_ADV */
|
2020-02-02 23:45:32 +01:00
|
|
|
|
2020-11-18 13:13:45 +03:00
|
|
|
#if defined(CONFIG_BT_OBSERVER) || defined(CONFIG_BT_USER_PHY_UPDATE)
|
|
|
|
static const char *phy2str(uint8_t phy)
|
|
|
|
{
|
|
|
|
switch (phy) {
|
|
|
|
case 0: return "No packets";
|
|
|
|
case BT_GAP_LE_PHY_1M: return "LE 1M";
|
|
|
|
case BT_GAP_LE_PHY_2M: return "LE 2M";
|
|
|
|
case BT_GAP_LE_PHY_CODED: return "LE Coded";
|
|
|
|
default: return "Unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-11-22 15:32:01 +01:00
|
|
|
#if defined(CONFIG_BT_CONN) || (defined(CONFIG_BT_BROADCASTER) && defined(CONFIG_BT_EXT_ADV))
|
|
|
|
static void print_le_addr(const char *desc, const bt_addr_le_t *addr)
|
|
|
|
{
|
|
|
|
char addr_str[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
const char *addr_desc = bt_addr_le_is_identity(addr) ? "identity" :
|
|
|
|
bt_addr_le_is_rpa(addr) ? "resolvable" :
|
|
|
|
"non-resolvable";
|
|
|
|
|
|
|
|
bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
|
|
|
|
|
|
|
|
shell_print(ctx_shell, "%s address: %s (%s)", desc, addr_str,
|
|
|
|
addr_desc);
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_CONN || (CONFIG_BT_BROADCASTER && CONFIG_BT_EXT_ADV) */
|
|
|
|
|
2022-05-24 16:15:59 +02:00
|
|
|
#if defined(CONFIG_BT_CENTRAL)
|
2022-09-06 16:18:57 +02:00
|
|
|
static int cmd_scan_off(const struct shell *sh);
|
|
|
|
static int cmd_connect_le(const struct shell *sh, size_t argc, char *argv[]);
|
|
|
|
static int cmd_scan_filter_clear_name(const struct shell *sh, size_t argc,
|
|
|
|
char *argv[]);
|
|
|
|
|
2022-05-24 16:15:59 +02:00
|
|
|
static struct bt_auto_connect {
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
bool addr_set;
|
2022-09-06 16:18:57 +02:00
|
|
|
bool connect_name;
|
2022-05-24 16:15:59 +02:00
|
|
|
} auto_connect;
|
|
|
|
#endif
|
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_OBSERVER)
|
2021-12-27 15:15:41 +01:00
|
|
|
static struct bt_scan_filter {
|
|
|
|
char name[NAME_LEN];
|
|
|
|
bool name_set;
|
|
|
|
char addr[18]; /* fits xx:xx:xx:xx:xx:xx\0 */
|
|
|
|
bool addr_set;
|
2022-05-23 15:55:40 +02:00
|
|
|
int8_t rssi;
|
|
|
|
bool rssi_set;
|
2022-12-15 20:02:15 +01:00
|
|
|
uint16_t pa_interval;
|
|
|
|
bool pa_interval_set;
|
2021-12-27 15:15:41 +01:00
|
|
|
} scan_filter;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Compares two strings without case sensitivy
|
|
|
|
*
|
|
|
|
* @param substr The substring
|
|
|
|
* @param str The string to find the substring in
|
|
|
|
*
|
|
|
|
* @return true if @substr is a substring of @p, else false
|
|
|
|
*/
|
|
|
|
static bool is_substring(const char *substr, const char *str)
|
|
|
|
{
|
|
|
|
const size_t str_len = strlen(str);
|
|
|
|
const size_t sub_str_len = strlen(substr);
|
|
|
|
|
|
|
|
if (sub_str_len > str_len) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t pos = 0; pos < str_len; pos++) {
|
|
|
|
if (tolower(substr[0]) == tolower(str[pos])) {
|
|
|
|
if (pos + sub_str_len > str_len) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strncasecmp(substr, &str[pos], sub_str_len) == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-06-26 13:50:14 +03:00
|
|
|
static bool data_cb(struct bt_data *data, void *user_data)
|
|
|
|
{
|
|
|
|
char *name = user_data;
|
|
|
|
|
|
|
|
switch (data->type) {
|
|
|
|
case BT_DATA_NAME_SHORTENED:
|
|
|
|
case BT_DATA_NAME_COMPLETE:
|
2019-02-11 17:14:19 +00:00
|
|
|
memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1));
|
2018-06-26 13:50:14 +03:00
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-02 00:57:09 +01:00
|
|
|
static void scan_recv(const struct bt_le_scan_recv_info *info,
|
|
|
|
struct net_buf_simple *buf)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
2018-06-26 13:50:14 +03:00
|
|
|
char name[NAME_LEN];
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2022-12-15 20:05:52 +01:00
|
|
|
if (scan_filter.rssi_set && (scan_filter.rssi > info->rssi)) {
|
2021-12-27 15:15:41 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-15 20:05:52 +01:00
|
|
|
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
|
|
|
|
2021-12-27 15:15:41 +01:00
|
|
|
if (scan_filter.addr_set && !is_substring(scan_filter.addr, le_addr)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-15 20:05:52 +01:00
|
|
|
(void)memset(name, 0, sizeof(name));
|
|
|
|
|
|
|
|
bt_data_parse(buf, data_cb, name);
|
|
|
|
|
|
|
|
if (scan_filter.name_set && !is_substring(scan_filter.name, name)) {
|
2022-05-23 15:55:40 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-15 20:02:15 +01:00
|
|
|
if (scan_filter.pa_interval_set &&
|
|
|
|
(scan_filter.pa_interval > BT_CONN_INTERVAL_TO_MS(info->interval))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-02 00:57:09 +01:00
|
|
|
shell_print(ctx_shell, "[DEVICE]: %s, AD evt type %u, RSSI %i %s "
|
2020-05-04 16:14:38 +02:00
|
|
|
"C:%u S:%u D:%d SR:%u E:%u Prim: %s, Secn: %s, "
|
2023-01-05 14:09:39 +01:00
|
|
|
"Interval: 0x%04x (%u us), SID: 0x%x",
|
2020-02-02 00:57:09 +01:00
|
|
|
le_addr, info->adv_type, info->rssi, name,
|
|
|
|
(info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
|
|
|
|
(info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
|
|
|
|
(info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
|
|
|
|
(info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
|
|
|
|
(info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
|
2020-05-04 16:14:38 +02:00
|
|
|
phy2str(info->primary_phy), phy2str(info->secondary_phy),
|
2023-01-05 14:09:39 +01:00
|
|
|
info->interval, BT_CONN_INTERVAL_TO_US(info->interval),
|
2020-11-11 15:09:36 +01:00
|
|
|
info->sid);
|
2022-05-24 16:15:59 +02:00
|
|
|
|
|
|
|
/* Store address for later use */
|
|
|
|
#if defined(CONFIG_BT_CENTRAL)
|
|
|
|
auto_connect.addr_set = true;
|
|
|
|
bt_addr_le_copy(&auto_connect.addr, info->addr);
|
2022-09-06 16:18:57 +02:00
|
|
|
|
|
|
|
/* Use the above auto_connect.addr address to automatically connect */
|
|
|
|
if (auto_connect.connect_name) {
|
|
|
|
auto_connect.connect_name = false;
|
|
|
|
|
|
|
|
cmd_scan_off(ctx_shell);
|
|
|
|
|
|
|
|
/* "name" is what would be in argv[0] normally */
|
|
|
|
cmd_scan_filter_clear_name(ctx_shell, 1, (char *[]){ "name" });
|
|
|
|
|
|
|
|
/* "connect" is what would be in argv[0] normally */
|
|
|
|
cmd_connect_le(ctx_shell, 1, (char *[]){ "connect" });
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_CENTRAL */
|
2020-02-02 00:57:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void scan_timeout(void)
|
|
|
|
{
|
|
|
|
shell_print(ctx_shell, "Scan timeout");
|
2022-09-06 16:18:57 +02:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CENTRAL)
|
|
|
|
if (auto_connect.connect_name) {
|
|
|
|
auto_connect.connect_name = false;
|
|
|
|
/* "name" is what would be in argv[0] normally */
|
|
|
|
cmd_scan_filter_clear_name(ctx_shell, 1, (char *[]){ "name" });
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_CENTRAL */
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_OBSERVER */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
#if defined(CONFIG_BT_EXT_ADV)
|
|
|
|
#if defined(CONFIG_BT_BROADCASTER)
|
2020-02-02 22:14:15 +01:00
|
|
|
static void adv_sent(struct bt_le_ext_adv *adv,
|
|
|
|
struct bt_le_ext_adv_sent_info *info)
|
|
|
|
{
|
|
|
|
shell_print(ctx_shell, "Advertiser[%d] %p sent %d",
|
|
|
|
bt_le_ext_adv_get_index(adv), adv, info->num_sent);
|
|
|
|
}
|
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
static void adv_scanned(struct bt_le_ext_adv *adv,
|
|
|
|
struct bt_le_ext_adv_scanned_info *info)
|
2020-02-02 22:14:15 +01:00
|
|
|
{
|
|
|
|
char str[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
bt_addr_le_to_str(info->addr, str, sizeof(str));
|
2020-02-02 22:14:15 +01:00
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
shell_print(ctx_shell, "Advertiser[%d] %p scanned by %s",
|
2020-02-02 22:14:15 +01:00
|
|
|
bt_le_ext_adv_get_index(adv), adv, str);
|
|
|
|
}
|
2020-08-19 12:54:46 +05:30
|
|
|
#endif /* CONFIG_BT_BROADCASTER */
|
2020-02-02 22:14:15 +01:00
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
#if defined(CONFIG_BT_PERIPHERAL)
|
|
|
|
static void adv_connected(struct bt_le_ext_adv *adv,
|
|
|
|
struct bt_le_ext_adv_connected_info *info)
|
2020-02-02 22:14:15 +01:00
|
|
|
{
|
|
|
|
char str[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(info->conn), str, sizeof(str));
|
2020-02-02 22:14:15 +01:00
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
shell_print(ctx_shell, "Advertiser[%d] %p connected by %s",
|
2020-02-02 22:14:15 +01:00
|
|
|
bt_le_ext_adv_get_index(adv), adv, str);
|
|
|
|
}
|
2020-08-19 12:54:46 +05:30
|
|
|
#endif /* CONFIG_BT_PERIPHERAL */
|
2022-10-13 11:27:56 +02:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_PRIVACY)
|
|
|
|
static bool adv_rpa_expired(struct bt_le_ext_adv *adv)
|
|
|
|
{
|
|
|
|
uint8_t adv_index = bt_le_ext_adv_get_index(adv);
|
|
|
|
|
|
|
|
bool keep_rpa = atomic_test_bit(adv_set_opt[adv_index],
|
|
|
|
SHELL_ADV_OPT_KEEP_RPA);
|
|
|
|
shell_print(ctx_shell, "Advertiser[%d] %p RPA %s",
|
|
|
|
adv_index, adv,
|
|
|
|
keep_rpa ? "not expired" : "expired");
|
|
|
|
|
|
|
|
return keep_rpa;
|
|
|
|
}
|
|
|
|
#endif /* defined(CONFIG_BT_PRIVACY) */
|
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
#endif /* CONFIG_BT_EXT_ADV */
|
2020-02-02 22:14:15 +01:00
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
#if !defined(CONFIG_BT_CONN)
|
2018-09-24 10:59:23 +03:00
|
|
|
#if 0 /* FIXME: Add support for changing prompt */
|
2018-01-04 11:44:50 +01:00
|
|
|
static const char *current_prompt(void)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-09-24 10:59:23 +03:00
|
|
|
#endif
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* !CONFIG_BT_CONN */
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CONN)
|
2018-09-24 10:59:23 +03:00
|
|
|
#if 0 /* FIXME: Add support for changing prompt */
|
2018-01-04 11:44:50 +01:00
|
|
|
static const char *current_prompt(void)
|
|
|
|
{
|
|
|
|
static char str[BT_ADDR_LE_STR_LEN + 2];
|
|
|
|
static struct bt_conn_info info;
|
|
|
|
|
|
|
|
if (!default_conn) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bt_conn_get_info(default_conn, &info) < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.type != BT_CONN_TYPE_LE) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_addr_le_to_str(info.le.dst, str, sizeof(str) - 2);
|
|
|
|
strcat(str, "> ");
|
|
|
|
return str;
|
|
|
|
}
|
2018-09-24 10:59:23 +03:00
|
|
|
#endif
|
2018-01-04 11:44:50 +01:00
|
|
|
|
2018-09-25 14:24:25 +03:00
|
|
|
void conn_addr_str(struct bt_conn *conn, char *addr, size_t len)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_conn_info info;
|
|
|
|
|
|
|
|
if (bt_conn_get_info(conn, &info) < 0) {
|
|
|
|
addr[0] = '\0';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (info.type) {
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
case BT_CONN_TYPE_BR:
|
|
|
|
bt_addr_to_str(info.br.dst, addr, len);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case BT_CONN_TYPE_LE:
|
2019-08-05 09:31:20 +02:00
|
|
|
bt_addr_le_to_str(info.le.dst, addr, len);
|
2017-05-22 11:49:31 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static void print_le_oob(const struct shell *sh, struct bt_le_oob *oob)
|
2020-03-16 14:38:53 +01:00
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
char c[KEY_STR_LEN];
|
|
|
|
char r[KEY_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(&oob->addr, addr, sizeof(addr));
|
|
|
|
|
|
|
|
bin2hex(oob->le_sc_data.c, sizeof(oob->le_sc_data.c), c, sizeof(c));
|
|
|
|
bin2hex(oob->le_sc_data.r, sizeof(oob->le_sc_data.r), r, sizeof(r));
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "OOB data:");
|
|
|
|
shell_print(sh, "%-29s %-32s %-32s", "addr", "random", "confirm");
|
|
|
|
shell_print(sh, "%29s %32s %32s", addr, r, c);
|
2020-03-16 14:38:53 +01:00
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static void connected(struct bt_conn *conn, uint8_t err)
|
2018-01-04 11:44:50 +01:00
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
conn_addr_str(conn, addr, sizeof(addr));
|
|
|
|
|
|
|
|
if (err) {
|
2020-02-02 00:42:24 +01:00
|
|
|
shell_error(ctx_shell, "Failed to connect to %s (0x%02x)", addr,
|
2018-09-24 10:59:23 +03:00
|
|
|
err);
|
2018-01-04 11:44:50 +01:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Connected: %s", addr);
|
2018-01-04 11:44:50 +01:00
|
|
|
|
|
|
|
if (!default_conn) {
|
|
|
|
default_conn = bt_conn_ref(conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
/* clear connection reference for sec mode 3 pairing */
|
|
|
|
if (pairing_conn) {
|
|
|
|
bt_conn_unref(pairing_conn);
|
|
|
|
pairing_conn = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static void disconnected(struct bt_conn *conn, uint8_t reason)
|
2018-01-04 11:44:50 +01:00
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
conn_addr_str(conn, addr, sizeof(addr));
|
2019-08-05 09:06:39 +02:00
|
|
|
shell_print(ctx_shell, "Disconnected: %s (reason 0x%02x)", addr, reason);
|
2018-01-04 11:44:50 +01:00
|
|
|
|
|
|
|
if (default_conn == conn) {
|
|
|
|
bt_conn_unref(default_conn);
|
|
|
|
default_conn = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
|
|
|
|
{
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "LE conn param req: int (0x%04x, 0x%04x) lat %d"
|
|
|
|
" to %d", param->interval_min, param->interval_max,
|
|
|
|
param->latency, param->timeout);
|
2018-01-04 11:44:50 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static void le_param_updated(struct bt_conn *conn, uint16_t interval,
|
|
|
|
uint16_t latency, uint16_t timeout)
|
2018-01-04 11:44:50 +01:00
|
|
|
{
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "LE conn param updated: int 0x%04x lat %d "
|
2018-09-27 12:49:10 +03:00
|
|
|
"to %d", interval, latency, timeout);
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP)
|
2017-05-22 11:49:31 +03:00
|
|
|
static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
|
|
|
|
const bt_addr_le_t *identity)
|
|
|
|
{
|
|
|
|
char addr_identity[BT_ADDR_LE_STR_LEN];
|
|
|
|
char addr_rpa[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
|
|
|
|
bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));
|
|
|
|
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Identity resolved %s -> %s", addr_rpa,
|
2018-09-24 10:59:23 +03:00
|
|
|
addr_identity);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2021-02-09 10:28:50 +01:00
|
|
|
static const char *security_err_str(enum bt_security_err err)
|
|
|
|
{
|
|
|
|
switch (err) {
|
|
|
|
case BT_SECURITY_ERR_SUCCESS:
|
|
|
|
return "Success";
|
|
|
|
case BT_SECURITY_ERR_AUTH_FAIL:
|
|
|
|
return "Authentication failure";
|
|
|
|
case BT_SECURITY_ERR_PIN_OR_KEY_MISSING:
|
|
|
|
return "PIN or key missing";
|
|
|
|
case BT_SECURITY_ERR_OOB_NOT_AVAILABLE:
|
|
|
|
return "OOB not available";
|
|
|
|
case BT_SECURITY_ERR_AUTH_REQUIREMENT:
|
|
|
|
return "Authentication requirements";
|
|
|
|
case BT_SECURITY_ERR_PAIR_NOT_SUPPORTED:
|
|
|
|
return "Pairing not supported";
|
|
|
|
case BT_SECURITY_ERR_PAIR_NOT_ALLOWED:
|
|
|
|
return "Pairing not allowed";
|
|
|
|
case BT_SECURITY_ERR_INVALID_PARAM:
|
|
|
|
return "Invalid parameters";
|
|
|
|
case BT_SECURITY_ERR_UNSPECIFIED:
|
|
|
|
return "Unspecified";
|
|
|
|
default:
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-19 16:20:59 +02:00
|
|
|
static void security_changed(struct bt_conn *conn, bt_security_t level,
|
|
|
|
enum bt_security_err err)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
conn_addr_str(conn, addr, sizeof(addr));
|
2019-08-19 16:20:59 +02:00
|
|
|
|
|
|
|
if (!err) {
|
|
|
|
shell_print(ctx_shell, "Security changed: %s level %u", addr,
|
|
|
|
level);
|
|
|
|
} else {
|
2021-02-09 10:28:50 +01:00
|
|
|
shell_print(ctx_shell, "Security failed: %s level %u "
|
|
|
|
"reason: %s (%d)",
|
|
|
|
addr, level, security_err_str(err), err);
|
2019-08-19 16:20:59 +02:00
|
|
|
}
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-10-07 13:34:02 +03:00
|
|
|
#if defined(CONFIG_BT_REMOTE_INFO)
|
2020-05-27 11:26:57 -05:00
|
|
|
static const char *ver_str(uint8_t ver)
|
2019-10-07 13:34:02 +03:00
|
|
|
{
|
|
|
|
const char * const str[] = {
|
|
|
|
"1.0b", "1.1", "1.2", "2.0", "2.1", "3.0", "4.0", "4.1", "4.2",
|
2021-07-15 10:59:54 +05:30
|
|
|
"5.0", "5.1", "5.2", "5.3"
|
2019-10-07 13:34:02 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
if (ver < ARRAY_SIZE(str)) {
|
|
|
|
return str[ver];
|
|
|
|
}
|
|
|
|
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void remote_info_available(struct bt_conn *conn,
|
|
|
|
struct bt_conn_remote_info *remote_info)
|
|
|
|
{
|
|
|
|
struct bt_conn_info info;
|
|
|
|
|
|
|
|
bt_conn_get_info(conn, &info);
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_BT_REMOTE_VERSION)) {
|
|
|
|
shell_print(ctx_shell,
|
|
|
|
"Remote LMP version %s (0x%02x) subversion 0x%04x "
|
|
|
|
"manufacturer 0x%04x", ver_str(remote_info->version),
|
|
|
|
remote_info->version, remote_info->subversion,
|
|
|
|
remote_info->manufacturer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.type == BT_CONN_TYPE_LE) {
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t features[8];
|
2019-10-07 13:34:02 +03:00
|
|
|
char features_str[2 * sizeof(features) + 1];
|
|
|
|
|
|
|
|
sys_memcpy_swap(features, remote_info->le.features,
|
|
|
|
sizeof(features));
|
|
|
|
bin2hex(features, sizeof(features),
|
|
|
|
features_str, sizeof(features_str));
|
|
|
|
shell_print(ctx_shell, "LE Features: 0x%s ", features_str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* defined(CONFIG_BT_REMOTE_INFO) */
|
|
|
|
|
2020-04-22 21:19:41 +02:00
|
|
|
#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
|
|
|
|
void le_data_len_updated(struct bt_conn *conn,
|
|
|
|
struct bt_conn_le_data_len_info *info)
|
|
|
|
{
|
|
|
|
shell_print(ctx_shell,
|
|
|
|
"LE data len updated: TX (len: %d time: %d)"
|
|
|
|
" RX (len: %d time: %d)", info->tx_max_len,
|
|
|
|
info->tx_max_time, info->rx_max_len, info->rx_max_time);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-04-22 20:44:35 +02:00
|
|
|
#if defined(CONFIG_BT_USER_PHY_UPDATE)
|
|
|
|
void le_phy_updated(struct bt_conn *conn,
|
|
|
|
struct bt_conn_le_phy_info *info)
|
|
|
|
{
|
|
|
|
shell_print(ctx_shell, "LE PHY updated: TX PHY %s, RX PHY %s",
|
|
|
|
phy2str(info->tx_phy), phy2str(info->rx_phy));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-12-08 16:50:01 +01:00
|
|
|
static struct bt_conn_cb conn_callbacks = {
|
2017-05-22 11:49:31 +03:00
|
|
|
.connected = connected,
|
|
|
|
.disconnected = disconnected,
|
|
|
|
.le_param_req = le_param_req,
|
|
|
|
.le_param_updated = le_param_updated,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP)
|
2017-05-22 11:49:31 +03:00
|
|
|
.identity_resolved = identity_resolved,
|
|
|
|
#endif
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.security_changed = security_changed,
|
|
|
|
#endif
|
2019-10-07 13:34:02 +03:00
|
|
|
#if defined(CONFIG_BT_REMOTE_INFO)
|
|
|
|
.remote_info_available = remote_info_available,
|
|
|
|
#endif
|
2020-04-22 21:19:41 +02:00
|
|
|
#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
|
|
|
|
.le_data_len_updated = le_data_len_updated,
|
|
|
|
#endif
|
2020-04-22 20:44:35 +02:00
|
|
|
#if defined(CONFIG_BT_USER_PHY_UPDATE)
|
|
|
|
.le_phy_updated = le_phy_updated,
|
|
|
|
#endif
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2020-02-02 00:57:09 +01:00
|
|
|
#if defined(CONFIG_BT_OBSERVER)
|
|
|
|
static struct bt_le_scan_cb scan_callbacks = {
|
|
|
|
.recv = scan_recv,
|
|
|
|
.timeout = scan_timeout,
|
|
|
|
};
|
|
|
|
#endif /* defined(CONFIG_BT_OBSERVER) */
|
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
#if defined(CONFIG_BT_EXT_ADV)
|
|
|
|
#if defined(CONFIG_BT_BROADCASTER)
|
2020-02-02 22:14:15 +01:00
|
|
|
static struct bt_le_ext_adv_cb adv_callbacks = {
|
|
|
|
.sent = adv_sent,
|
|
|
|
.scanned = adv_scanned,
|
2020-08-19 12:54:46 +05:30
|
|
|
#if defined(CONFIG_BT_PERIPHERAL)
|
|
|
|
.connected = adv_connected,
|
|
|
|
#endif /* CONFIG_BT_PERIPHERAL */
|
2022-10-13 11:27:56 +02:00
|
|
|
#if defined(CONFIG_BT_PRIVACY)
|
|
|
|
.rpa_expired = adv_rpa_expired,
|
|
|
|
#endif /* defined(CONFIG_BT_PRIVACY) */
|
|
|
|
|
2020-02-02 22:14:15 +01:00
|
|
|
};
|
2020-08-19 12:54:46 +05:30
|
|
|
#endif /* CONFIG_BT_BROADCASTER */
|
|
|
|
#endif /* CONFIG_BT_EXT_ADV */
|
2020-02-02 22:14:15 +01:00
|
|
|
|
2020-10-21 15:04:30 +02:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_PER_ADV_SYNC)
|
2020-08-12 14:22:51 +02:00
|
|
|
struct bt_le_per_adv_sync *per_adv_syncs[CONFIG_BT_PER_ADV_SYNC_MAX];
|
2020-10-21 15:04:30 +02:00
|
|
|
|
|
|
|
static void per_adv_sync_sync_cb(struct bt_le_per_adv_sync *sync,
|
|
|
|
struct bt_le_per_adv_sync_synced_info *info)
|
|
|
|
{
|
|
|
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
2020-09-23 22:39:29 +02:00
|
|
|
char past_peer[BT_ADDR_LE_STR_LEN];
|
2020-10-21 15:04:30 +02:00
|
|
|
|
|
|
|
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
2020-09-23 22:39:29 +02:00
|
|
|
|
|
|
|
if (info->conn) {
|
|
|
|
conn_addr_str(info->conn, past_peer, sizeof(past_peer));
|
|
|
|
} else {
|
|
|
|
memset(past_peer, 0, sizeof(past_peer));
|
|
|
|
}
|
|
|
|
|
2020-10-21 15:04:30 +02:00
|
|
|
shell_print(ctx_shell, "PER_ADV_SYNC[%u]: [DEVICE]: %s synced, "
|
2023-01-05 14:09:39 +01:00
|
|
|
"Interval 0x%04x (%u us), PHY %s, SD 0x%04X, PAST peer %s",
|
2020-10-21 15:04:30 +02:00
|
|
|
bt_le_per_adv_sync_get_index(sync), le_addr,
|
2023-01-05 14:09:39 +01:00
|
|
|
info->interval, BT_CONN_INTERVAL_TO_US(info->interval),
|
2020-11-11 15:09:36 +01:00
|
|
|
phy2str(info->phy), info->service_data, past_peer);
|
2020-09-23 22:39:29 +02:00
|
|
|
|
|
|
|
if (info->conn) { /* if from PAST */
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(per_adv_syncs); i++) {
|
|
|
|
if (!per_adv_syncs[i]) {
|
|
|
|
per_adv_syncs[i] = sync;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-21 15:04:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void per_adv_sync_terminated_cb(
|
|
|
|
struct bt_le_per_adv_sync *sync,
|
|
|
|
const struct bt_le_per_adv_sync_term_info *info)
|
|
|
|
{
|
|
|
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(per_adv_syncs); i++) {
|
|
|
|
if (per_adv_syncs[i] == sync) {
|
|
|
|
per_adv_syncs[i] = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
|
|
|
shell_print(ctx_shell, "PER_ADV_SYNC[%u]: [DEVICE]: %s sync terminated",
|
|
|
|
bt_le_per_adv_sync_get_index(sync), le_addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void 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)
|
|
|
|
{
|
|
|
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
|
|
|
shell_print(ctx_shell, "PER_ADV_SYNC[%u]: [DEVICE]: %s, tx_power %i, "
|
|
|
|
"RSSI %i, CTE %u, data length %u",
|
|
|
|
bt_le_per_adv_sync_get_index(sync), le_addr, info->tx_power,
|
|
|
|
info->rssi, info->cte_type, buf->len);
|
|
|
|
}
|
|
|
|
|
2020-08-12 14:22:51 +02:00
|
|
|
static void per_adv_sync_biginfo_cb(struct bt_le_per_adv_sync *sync,
|
|
|
|
const struct bt_iso_biginfo *biginfo)
|
|
|
|
{
|
|
|
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(biginfo->addr, le_addr, sizeof(le_addr));
|
2021-04-10 15:54:14 +02:00
|
|
|
shell_print(ctx_shell, "BIG_INFO PER_ADV_SYNC[%u]: [DEVICE]: %s, sid 0x%02x, num_bis %u, "
|
2023-01-05 14:09:39 +01:00
|
|
|
"nse 0x%02x, interval 0x%04x (%u us), bn 0x%02x, pto 0x%02x, irc 0x%02x, "
|
2020-08-12 14:22:51 +02:00
|
|
|
"max_pdu 0x%04x, sdu_interval 0x%04x, max_sdu 0x%04x, phy %s, framing 0x%02x, "
|
|
|
|
"%sencrypted",
|
|
|
|
bt_le_per_adv_sync_get_index(sync), le_addr, biginfo->sid, biginfo->num_bis,
|
|
|
|
biginfo->sub_evt_count, biginfo->iso_interval,
|
2023-01-05 14:09:39 +01:00
|
|
|
BT_CONN_INTERVAL_TO_US(biginfo->iso_interval), biginfo->burst_number,
|
2020-08-12 14:22:51 +02:00
|
|
|
biginfo->offset, biginfo->rep_count, biginfo->max_pdu, biginfo->sdu_interval,
|
|
|
|
biginfo->max_sdu, phy2str(biginfo->phy), biginfo->framing,
|
|
|
|
biginfo->encryption ? "" : "not ");
|
|
|
|
}
|
|
|
|
|
2020-10-21 15:04:30 +02:00
|
|
|
static struct bt_le_per_adv_sync_cb per_adv_sync_cb = {
|
|
|
|
.synced = per_adv_sync_sync_cb,
|
|
|
|
.term = per_adv_sync_terminated_cb,
|
2020-08-12 14:22:51 +02:00
|
|
|
.recv = per_adv_sync_recv_cb,
|
|
|
|
.biginfo = per_adv_sync_biginfo_cb,
|
2020-10-21 15:04:30 +02:00
|
|
|
};
|
|
|
|
#endif /* CONFIG_BT_PER_ADV_SYNC */
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
static void bt_ready(int err)
|
|
|
|
{
|
|
|
|
if (err) {
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_error(ctx_shell, "Bluetooth init failed (err %d)", err);
|
2017-05-22 11:49:31 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Bluetooth initialized");
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2021-01-19 15:41:18 +01:00
|
|
|
if (IS_ENABLED(CONFIG_SETTINGS) && !no_settings_load) {
|
2018-04-28 21:08:06 +03:00
|
|
|
settings_load();
|
2021-01-19 15:41:18 +01:00
|
|
|
shell_print(ctx_shell, "Settings Loaded");
|
2018-04-28 21:08:06 +03:00
|
|
|
}
|
|
|
|
|
2020-02-04 09:12:20 +01:00
|
|
|
if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
|
|
|
|
bt_set_oob_data_flag(true);
|
|
|
|
}
|
|
|
|
|
2020-02-02 00:57:09 +01:00
|
|
|
#if defined(CONFIG_BT_OBSERVER)
|
|
|
|
bt_le_scan_cb_register(&scan_callbacks);
|
|
|
|
#endif
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
#if defined(CONFIG_BT_CONN)
|
2017-05-29 12:54:56 +03:00
|
|
|
default_conn = NULL;
|
2021-12-08 16:50:01 +01:00
|
|
|
|
|
|
|
bt_conn_cb_register(&conn_callbacks);
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2020-10-21 15:04:30 +02:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_PER_ADV_SYNC)
|
|
|
|
bt_le_per_adv_sync_cb_register(&per_adv_sync_cb);
|
|
|
|
#endif /* CONFIG_BT_PER_ADV_SYNC */
|
2022-03-08 14:33:56 +01:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_SMP)
|
|
|
|
bt_conn_auth_info_cb_register(&auth_info_cb);
|
|
|
|
#endif /* CONFIG_BT_SMP */
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
2022-07-15 16:51:03 +02:00
|
|
|
bool sync = false;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
ctx_shell = sh;
|
2018-12-07 15:31:36 +08:00
|
|
|
|
2021-01-19 15:41:18 +01:00
|
|
|
for (size_t argn = 1; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
|
|
|
if (!strcmp(arg, "no-settings-load")) {
|
|
|
|
no_settings_load = true;
|
|
|
|
} else if (!strcmp(arg, "sync")) {
|
2022-07-15 16:51:03 +02:00
|
|
|
sync = true;
|
2021-01-19 15:41:18 +01:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2021-01-19 15:41:18 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-15 16:51:03 +02:00
|
|
|
if (sync) {
|
|
|
|
err = bt_enable(NULL);
|
|
|
|
bt_ready(err);
|
|
|
|
} else {
|
2021-01-19 15:41:18 +01:00
|
|
|
err = bt_enable(bt_ready);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Bluetooth init failed (err %d)",
|
2021-01-19 15:41:18 +01:00
|
|
|
err);
|
|
|
|
}
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2022-10-24 16:13:40 +01:00
|
|
|
static int cmd_disable(const struct shell *sh, size_t argc, char *argv[])
|
|
|
|
{
|
|
|
|
return bt_disable();
|
|
|
|
}
|
|
|
|
|
2021-01-19 15:41:18 +01:00
|
|
|
#ifdef CONFIG_SETTINGS
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_settings_load(const struct shell *sh, size_t argc,
|
2021-01-19 15:41:18 +01:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = settings_load();
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Settings load failed (err %d)", err);
|
2021-01-19 15:41:18 +01:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Settings loaded");
|
2021-01-19 15:41:18 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-07-09 13:33:07 +03:00
|
|
|
#if defined(CONFIG_BT_HCI)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_hci_cmd(const struct shell *sh, size_t argc, char *argv[])
|
2018-07-09 13:33:07 +03:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t ogf;
|
|
|
|
uint16_t ocf;
|
2018-07-09 13:33:07 +03:00
|
|
|
struct net_buf *buf = NULL, *rsp;
|
|
|
|
int err;
|
2020-05-20 16:40:57 +02:00
|
|
|
static uint8_t hex_data[HCI_CMD_MAX_PARAM];
|
|
|
|
int hex_data_len;
|
2018-07-09 13:33:07 +03:00
|
|
|
|
2020-05-20 16:40:57 +02:00
|
|
|
hex_data_len = 0;
|
2018-07-09 13:33:07 +03:00
|
|
|
ogf = strtoul(argv[1], NULL, 16);
|
|
|
|
ocf = strtoul(argv[2], NULL, 16);
|
|
|
|
|
|
|
|
if (argc > 3) {
|
2020-05-20 16:40:57 +02:00
|
|
|
size_t len;
|
2018-07-09 13:33:07 +03:00
|
|
|
|
2020-05-20 16:40:57 +02:00
|
|
|
if (strlen(argv[3]) > 2 * HCI_CMD_MAX_PARAM) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Data field too large\n");
|
2020-05-20 16:40:57 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
2018-07-09 13:33:07 +03:00
|
|
|
|
2020-05-20 16:40:57 +02:00
|
|
|
len = hex2bin(argv[3], strlen(argv[3]), &hex_data[hex_data_len],
|
|
|
|
sizeof(hex_data) - hex_data_len);
|
|
|
|
if (!len) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "HCI command illegal data field\n");
|
2020-05-20 16:40:57 +02:00
|
|
|
return -ENOEXEC;
|
2018-07-09 13:33:07 +03:00
|
|
|
}
|
2020-05-20 16:40:57 +02:00
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_OP(ogf, ocf), len);
|
|
|
|
net_buf_add_mem(buf, hex_data, len);
|
2018-07-09 13:33:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_OP(ogf, ocf), buf, &rsp);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "HCI command failed (err %d)", err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2018-07-09 13:33:07 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_hexdump(sh, rsp->data, rsp->len);
|
2018-07-09 13:33:07 +03:00
|
|
|
net_buf_unref(rsp);
|
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2018-07-09 13:33:07 +03:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_HCI */
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_name(const struct shell *sh, size_t argc, char *argv[])
|
2018-07-17 13:55:47 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Bluetooth Local Name: %s", bt_get_name());
|
2019-11-16 23:40:55 +01:00
|
|
|
return 0;
|
2018-07-17 13:55:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_set_name(argv[1]);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Unable to set name %s (err %d)", argv[1],
|
2018-11-12 15:15:20 +02:00
|
|
|
err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2018-07-17 13:55:47 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2018-07-17 13:55:47 +03:00
|
|
|
}
|
|
|
|
|
2021-11-24 12:56:08 +01:00
|
|
|
static int cmd_appearance(const struct shell *sh, size_t argc, char *argv[])
|
|
|
|
{
|
|
|
|
if (argc == 1) {
|
|
|
|
shell_print(sh, "Bluetooth Appearance: 0x%04x", bt_get_appearance());
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-24 12:56:15 +01:00
|
|
|
#if defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC)
|
|
|
|
uint16_t app;
|
|
|
|
int err;
|
|
|
|
const char *val;
|
|
|
|
|
|
|
|
val = argv[1];
|
|
|
|
if (strlen(val) != 6 || strncmp(val, "0x", 2) ||
|
|
|
|
!hex2bin(&val[2], strlen(&val[2]), ((uint8_t *)&app), sizeof(app))) {
|
|
|
|
shell_error(sh, "Argument must be 0x followed by exactly 4 hex digits.");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
app = sys_be16_to_cpu(app);
|
|
|
|
|
|
|
|
err = bt_set_appearance(app);
|
|
|
|
if (err) {
|
|
|
|
shell_error(sh, "bt_set_appearance(0x%04x) failed with err %d", app, err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif /* defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC) */
|
|
|
|
|
2021-11-24 12:56:08 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_id_create(const struct shell *sh, size_t argc, char *argv[])
|
2018-07-16 15:11:08 +03:00
|
|
|
{
|
2018-07-17 10:35:52 +03:00
|
|
|
char addr_str[BT_ADDR_LE_STR_LEN];
|
2018-07-16 15:11:08 +03:00
|
|
|
bt_addr_le_t addr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc > 1) {
|
2019-05-29 10:50:08 +02:00
|
|
|
err = bt_addr_le_from_str(argv[1], "random", &addr);
|
2018-07-16 15:11:08 +03:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid address");
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bt_addr_le_copy(&addr, BT_ADDR_LE_ANY);
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_id_create(&addr, NULL);
|
|
|
|
if (err < 0) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Creating new ID failed (err %d)", err);
|
2021-01-19 15:42:27 +01:00
|
|
|
return err;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2018-07-17 10:35:52 +03:00
|
|
|
bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "New identity (%d) created: %s", err, addr_str);
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_id_reset(const struct shell *sh, size_t argc, char *argv[])
|
2018-07-16 15:11:08 +03:00
|
|
|
{
|
2018-07-17 10:35:52 +03:00
|
|
|
char addr_str[BT_ADDR_LE_STR_LEN];
|
2018-07-16 15:11:08 +03:00
|
|
|
bt_addr_le_t addr;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t id;
|
2018-07-16 15:11:08 +03:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Identity identifier not specified");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
id = strtol(argv[1], NULL, 10);
|
|
|
|
|
|
|
|
if (argc > 2) {
|
2019-05-29 10:50:08 +02:00
|
|
|
err = bt_addr_le_from_str(argv[2], "random", &addr);
|
2018-07-16 15:11:08 +03:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Invalid address");
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bt_addr_le_copy(&addr, BT_ADDR_LE_ANY);
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_id_reset(id, &addr, NULL);
|
|
|
|
if (err < 0) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Resetting ID %u failed (err %d)", id, err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2018-07-17 10:35:52 +03:00
|
|
|
bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Identity %u reset: %s", id, addr_str);
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_id_delete(const struct shell *sh, size_t argc, char *argv[])
|
2018-08-02 12:34:39 +03:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t id;
|
2018-08-02 12:34:39 +03:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Identity identifier not specified");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2018-08-02 12:34:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
id = strtol(argv[1], NULL, 10);
|
|
|
|
|
|
|
|
err = bt_id_delete(id);
|
|
|
|
if (err < 0) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Deleting ID %u failed (err %d)", id, err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2018-08-02 12:34:39 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Identity %u deleted", id);
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2018-08-02 12:34:39 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_id_show(const struct shell *sh, size_t argc, char *argv[])
|
2018-07-16 15:11:08 +03:00
|
|
|
{
|
|
|
|
bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
|
|
|
|
size_t i, count = CONFIG_BT_ID_MAX;
|
|
|
|
|
|
|
|
bt_id_get(addrs, &count);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
2018-07-17 10:35:52 +03:00
|
|
|
char addr_str[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(&addrs[i], addr_str, sizeof(addr_str));
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "%s%zu: %s", i == selected_id ? "*" : " ", i,
|
2018-07-17 10:35:52 +03:00
|
|
|
addr_str);
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_id_select(const struct shell *sh, size_t argc, char *argv[])
|
2018-07-16 15:11:08 +03:00
|
|
|
{
|
2018-07-17 10:35:52 +03:00
|
|
|
char addr_str[BT_ADDR_LE_STR_LEN];
|
2018-07-16 15:11:08 +03:00
|
|
|
bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
|
|
|
|
size_t count = CONFIG_BT_ID_MAX;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t id;
|
2018-07-16 15:11:08 +03:00
|
|
|
|
|
|
|
id = strtol(argv[1], NULL, 10);
|
|
|
|
|
|
|
|
bt_id_get(addrs, &count);
|
|
|
|
if (count <= id) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid identity");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2018-07-17 10:35:52 +03:00
|
|
|
bt_addr_le_to_str(&addrs[id], addr_str, sizeof(addr_str));
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Selected identity: %s", addr_str);
|
2018-07-16 15:11:08 +03:00
|
|
|
selected_id = id;
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_OBSERVER)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_active_scan_on(const struct shell *sh, uint32_t options,
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t timeout)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
struct bt_le_scan_param param = {
|
2020-02-02 00:39:24 +01:00
|
|
|
.type = BT_LE_SCAN_TYPE_ACTIVE,
|
2020-11-05 17:59:10 +01:00
|
|
|
.options = BT_LE_SCAN_OPT_NONE,
|
2017-05-22 11:49:31 +03:00
|
|
|
.interval = BT_GAP_SCAN_FAST_INTERVAL,
|
2020-03-23 12:34:48 +01:00
|
|
|
.window = BT_GAP_SCAN_FAST_WINDOW,
|
|
|
|
.timeout = timeout, };
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2020-02-01 20:06:35 +01:00
|
|
|
param.options |= options;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2020-02-02 00:57:09 +01:00
|
|
|
err = bt_le_scan_start(¶m, NULL);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Bluetooth set active scan failed "
|
2018-09-27 12:49:10 +03:00
|
|
|
"(err %d)", err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Bluetooth active scan enabled");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_passive_scan_on(const struct shell *sh, uint32_t options,
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t timeout)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_le_scan_param param = {
|
2020-02-02 00:39:24 +01:00
|
|
|
.type = BT_LE_SCAN_TYPE_PASSIVE,
|
2020-02-01 20:06:35 +01:00
|
|
|
.options = BT_LE_SCAN_OPT_NONE,
|
2017-05-22 11:49:31 +03:00
|
|
|
.interval = 0x10,
|
2020-03-23 12:34:48 +01:00
|
|
|
.window = 0x10,
|
|
|
|
.timeout = timeout, };
|
2017-05-22 11:49:31 +03:00
|
|
|
int err;
|
|
|
|
|
2020-02-01 20:06:35 +01:00
|
|
|
param.options |= options;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2020-02-02 00:57:09 +01:00
|
|
|
err = bt_le_scan_start(¶m, NULL);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Bluetooth set passive scan failed "
|
2018-09-27 12:49:10 +03:00
|
|
|
"(err %d)", err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Bluetooth passive scan enabled");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_scan_off(const struct shell *sh)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = bt_le_scan_stop();
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Stopping scanning failed (err %d)", err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Scan successfully stopped");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_scan(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
const char *action;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t options = 0;
|
|
|
|
uint16_t timeout = 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
/* Parse duplicate filtering data */
|
2019-07-22 13:21:49 +02:00
|
|
|
for (size_t argn = 2; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
|
|
|
if (!strcmp(arg, "dups")) {
|
2020-02-01 20:06:35 +01:00
|
|
|
options |= BT_LE_SCAN_OPT_FILTER_DUPLICATE;
|
2019-07-22 13:21:49 +02:00
|
|
|
} else if (!strcmp(arg, "nodups")) {
|
2020-02-01 20:06:35 +01:00
|
|
|
options &= ~BT_LE_SCAN_OPT_FILTER_DUPLICATE;
|
2021-09-17 12:46:31 +02:00
|
|
|
} else if (!strcmp(arg, "fal")) {
|
2021-09-14 12:28:45 +02:00
|
|
|
options |= BT_LE_SCAN_OPT_FILTER_ACCEPT_LIST;
|
2020-02-02 23:51:14 +01:00
|
|
|
} else if (!strcmp(arg, "coded")) {
|
|
|
|
options |= BT_LE_SCAN_OPT_CODED;
|
|
|
|
} else if (!strcmp(arg, "no-1m")) {
|
|
|
|
options |= BT_LE_SCAN_OPT_NO_1M;
|
2020-03-23 12:34:48 +01:00
|
|
|
} else if (!strcmp(arg, "timeout")) {
|
|
|
|
if (++argn == argc) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-03-23 12:34:48 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
timeout = strtoul(argv[argn], NULL, 16);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-03-25 11:03:59 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
action = argv[1];
|
|
|
|
if (!strcmp(action, "on")) {
|
2021-09-20 10:58:45 +02:00
|
|
|
return cmd_active_scan_on(sh, options, timeout);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(action, "off")) {
|
2021-09-20 10:58:45 +02:00
|
|
|
return cmd_scan_off(sh);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(action, "passive")) {
|
2021-09-20 10:58:45 +02:00
|
|
|
return cmd_passive_scan_on(sh, options, timeout);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-03-25 11:03:59 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2021-12-27 15:15:41 +01:00
|
|
|
|
|
|
|
static int cmd_scan_filter_set_name(const struct shell *sh, size_t argc,
|
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
const char *name_arg = argv[1];
|
|
|
|
|
|
|
|
if (strlen(name_arg) >= sizeof(scan_filter.name)) {
|
|
|
|
shell_error(ctx_shell, "Name is too long (max %zu): %s\n",
|
|
|
|
sizeof(scan_filter.name), name_arg);
|
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(scan_filter.name, name_arg);
|
|
|
|
scan_filter.name_set = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_scan_filter_set_addr(const struct shell *sh, size_t argc,
|
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
const char *addr_arg = argv[1];
|
|
|
|
|
2022-04-22 12:43:23 +02:00
|
|
|
/* Validate length including null terminator. */
|
|
|
|
if (strlen(addr_arg) >= sizeof(scan_filter.addr)) {
|
2021-12-27 15:15:41 +01:00
|
|
|
shell_error(ctx_shell, "Invalid address string: %s\n",
|
|
|
|
addr_arg);
|
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Validate input to check if valid (subset of) BT address */
|
|
|
|
for (size_t i = 0; i < strlen(addr_arg); i++) {
|
|
|
|
const char c = addr_arg[i];
|
|
|
|
uint8_t tmp;
|
|
|
|
|
|
|
|
if (c != ':' && char2hex(c, &tmp) < 0) {
|
|
|
|
shell_error(ctx_shell,
|
|
|
|
"Invalid address string: %s\n",
|
|
|
|
addr_arg);
|
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(scan_filter.addr, addr_arg);
|
|
|
|
scan_filter.addr_set = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-05-23 15:55:40 +02:00
|
|
|
static int cmd_scan_filter_set_rssi(const struct shell *sh, size_t argc, char *argv[])
|
|
|
|
{
|
|
|
|
int err = 0;
|
|
|
|
long rssi;
|
|
|
|
|
|
|
|
rssi = shell_strtol(argv[1], 10, &err);
|
|
|
|
|
|
|
|
if (!err) {
|
|
|
|
if (IN_RANGE(rssi, INT8_MIN, INT8_MAX)) {
|
|
|
|
scan_filter.rssi = (int8_t)rssi;
|
|
|
|
scan_filter.rssi_set = true;
|
|
|
|
shell_print(sh, "RSSI cutoff set at %d dB", scan_filter.rssi);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_print(sh, "value out of bounds (%d to %d)", INT8_MIN, INT8_MAX);
|
|
|
|
err = -ERANGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_print(sh, "error %d", err);
|
|
|
|
shell_help(sh);
|
|
|
|
|
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
|
2022-12-15 20:02:15 +01:00
|
|
|
static int cmd_scan_filter_set_pa_interval(const struct shell *sh, size_t argc,
|
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
unsigned long pa_interval;
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
pa_interval = shell_strtoul(argv[1], 10, &err);
|
|
|
|
|
|
|
|
if (!err) {
|
|
|
|
if (IN_RANGE(pa_interval,
|
|
|
|
BT_GAP_PER_ADV_MIN_INTERVAL,
|
|
|
|
BT_GAP_PER_ADV_MAX_INTERVAL)) {
|
|
|
|
scan_filter.pa_interval = (uint16_t)pa_interval;
|
|
|
|
scan_filter.pa_interval_set = true;
|
|
|
|
shell_print(sh, "PA interval cutoff set at %u",
|
|
|
|
scan_filter.pa_interval);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_print(sh, "value out of bounds (%d to %d)",
|
|
|
|
BT_GAP_PER_ADV_MIN_INTERVAL,
|
|
|
|
BT_GAP_PER_ADV_MAX_INTERVAL);
|
|
|
|
|
|
|
|
err = -ERANGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_print(sh, "error %d", err);
|
|
|
|
shell_help(sh);
|
|
|
|
|
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
|
2021-12-27 15:15:41 +01:00
|
|
|
static int cmd_scan_filter_clear_all(const struct shell *sh, size_t argc,
|
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
(void)memset(&scan_filter, 0, sizeof(scan_filter));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_scan_filter_clear_name(const struct shell *sh, size_t argc,
|
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
(void)memset(scan_filter.name, 0, sizeof(scan_filter.name));
|
|
|
|
scan_filter.name_set = false;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_scan_filter_clear_addr(const struct shell *sh, size_t argc,
|
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
(void)memset(scan_filter.addr, 0, sizeof(scan_filter.addr));
|
|
|
|
scan_filter.addr_set = false;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_OBSERVER */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_BROADCASTER)
|
2022-07-22 13:03:55 +02:00
|
|
|
static ssize_t ad_init(struct bt_data *data_array, const size_t data_array_size,
|
|
|
|
const atomic_t *adv_opt)
|
|
|
|
{
|
|
|
|
const bool discoverable = atomic_test_bit(adv_opt, SHELL_ADV_OPT_DISCOVERABLE);
|
2022-09-27 15:47:48 +02:00
|
|
|
const bool appearance = atomic_test_bit(adv_opt, SHELL_ADV_OPT_APPEARANCE);
|
2022-07-22 13:03:55 +02:00
|
|
|
const bool adv_ext = atomic_test_bit(adv_opt, SHELL_ADV_OPT_EXT_ADV);
|
|
|
|
static uint8_t ad_flags;
|
|
|
|
size_t ad_len = 0;
|
|
|
|
|
|
|
|
/* Set BR/EDR Not Supported if LE-only device */
|
|
|
|
ad_flags = IS_ENABLED(CONFIG_BT_BREDR) ? 0 : BT_LE_AD_NO_BREDR;
|
|
|
|
|
|
|
|
if (discoverable) {
|
|
|
|
/* A privacy-enabled Set Member should advertise RSI values only when in
|
|
|
|
* the GAP Limited Discoverable mode.
|
|
|
|
*/
|
2022-10-11 15:13:09 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
|
|
|
|
IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER) &&
|
2022-10-13 11:46:26 +02:00
|
|
|
svc_inst != NULL) {
|
2022-07-22 13:03:55 +02:00
|
|
|
ad_flags |= BT_LE_AD_LIMITED;
|
|
|
|
} else {
|
|
|
|
ad_flags |= BT_LE_AD_GENERAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ad_flags != 0) {
|
|
|
|
__ASSERT(data_array_size > ad_len, "No space for AD_FLAGS");
|
|
|
|
data_array[ad_len].type = BT_DATA_FLAGS;
|
|
|
|
data_array[ad_len].data_len = sizeof(ad_flags);
|
|
|
|
data_array[ad_len].data = &ad_flags;
|
|
|
|
ad_len++;
|
|
|
|
}
|
|
|
|
|
2022-09-27 15:47:48 +02:00
|
|
|
if (appearance) {
|
|
|
|
const uint16_t appearance = bt_get_appearance();
|
|
|
|
static uint8_t appearance_data[sizeof(appearance)];
|
|
|
|
|
|
|
|
__ASSERT(data_array_size > ad_len, "No space for appearance");
|
|
|
|
sys_put_le16(appearance, appearance_data);
|
|
|
|
data_array[ad_len].type = BT_DATA_GAP_APPEARANCE;
|
|
|
|
data_array[ad_len].data_len = sizeof(appearance_data);
|
|
|
|
data_array[ad_len].data = appearance_data;
|
|
|
|
ad_len++;
|
|
|
|
}
|
|
|
|
|
2022-10-11 15:13:09 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER)) {
|
2022-07-22 13:03:55 +02:00
|
|
|
ssize_t csis_ad_len;
|
|
|
|
|
|
|
|
csis_ad_len = csis_ad_data_add(&data_array[ad_len],
|
|
|
|
data_array_size - ad_len, discoverable);
|
|
|
|
if (csis_ad_len < 0) {
|
|
|
|
shell_error(ctx_shell, "Failed to add CSIS data (err %d)", csis_ad_len);
|
|
|
|
return ad_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
ad_len += csis_ad_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_BT_AUDIO) && IS_ENABLED(CONFIG_BT_EXT_ADV) && adv_ext) {
|
|
|
|
const bool connectable = atomic_test_bit(adv_opt, SHELL_ADV_OPT_CONNECTABLE);
|
|
|
|
size_t audio_ad_len;
|
|
|
|
|
|
|
|
audio_ad_len = audio_ad_data_add(&data_array[ad_len], data_array_size - ad_len,
|
|
|
|
discoverable, connectable);
|
|
|
|
if (audio_ad_len < 0) {
|
|
|
|
return audio_ad_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
ad_len += audio_ad_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ad_len;
|
|
|
|
}
|
2018-01-04 11:44:50 +01:00
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_advertise(const struct shell *sh, size_t argc, char *argv[])
|
2018-01-04 11:44:50 +01:00
|
|
|
{
|
2020-04-21 11:38:11 +02:00
|
|
|
struct bt_le_adv_param param = {};
|
2022-09-27 15:47:48 +02:00
|
|
|
struct bt_data ad[3];
|
2022-07-22 13:03:55 +02:00
|
|
|
bool discoverable = true;
|
2022-09-27 15:47:48 +02:00
|
|
|
bool appearance = false;
|
2018-10-19 18:08:53 -07:00
|
|
|
size_t ad_len;
|
2018-01-04 11:44:50 +01:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "off")) {
|
|
|
|
if (bt_le_adv_stop() < 0) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to stop advertising");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2018-01-04 11:44:50 +01:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Advertising stopped");
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
2018-10-01 22:08:59 +02:00
|
|
|
return 0;
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
2018-07-16 15:11:08 +03:00
|
|
|
param.id = selected_id;
|
2018-01-04 11:44:50 +01:00
|
|
|
param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
|
|
|
|
param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "on")) {
|
2018-07-17 13:34:27 +03:00
|
|
|
param.options = (BT_LE_ADV_OPT_CONNECTABLE |
|
|
|
|
BT_LE_ADV_OPT_USE_NAME);
|
2018-01-04 11:44:50 +01:00
|
|
|
} else if (!strcmp(argv[1], "scan")) {
|
2018-07-17 13:34:27 +03:00
|
|
|
param.options = BT_LE_ADV_OPT_USE_NAME;
|
2018-01-04 11:44:50 +01:00
|
|
|
} else if (!strcmp(argv[1], "nconn")) {
|
2019-03-26 19:57:45 -06:00
|
|
|
param.options = 0U;
|
2018-01-04 11:44:50 +01:00
|
|
|
} else {
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2019-07-22 13:21:49 +02:00
|
|
|
for (size_t argn = 2; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
2022-09-27 14:14:09 +02:00
|
|
|
if (!strcmp(arg, "discov")) {
|
|
|
|
discoverable = true;
|
|
|
|
} else if (!strcmp(arg, "non_discov")) {
|
|
|
|
discoverable = false;
|
2022-09-27 15:47:48 +02:00
|
|
|
} else if (!strcmp(arg, "appearance")) {
|
|
|
|
appearance = true;
|
2021-09-17 12:46:31 +02:00
|
|
|
} else if (!strcmp(arg, "fal")) {
|
2019-07-22 13:21:49 +02:00
|
|
|
param.options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
|
|
|
|
param.options |= BT_LE_ADV_OPT_FILTER_CONN;
|
2021-09-17 12:46:31 +02:00
|
|
|
} else if (!strcmp(arg, "fal-scan")) {
|
2019-07-22 13:21:49 +02:00
|
|
|
param.options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
|
2021-09-17 12:46:31 +02:00
|
|
|
} else if (!strcmp(arg, "fal-conn")) {
|
2019-07-22 13:21:49 +02:00
|
|
|
param.options |= BT_LE_ADV_OPT_FILTER_CONN;
|
2020-01-15 16:50:45 +01:00
|
|
|
} else if (!strcmp(arg, "identity")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_USE_IDENTITY;
|
2020-05-05 14:59:34 +02:00
|
|
|
} else if (!strcmp(arg, "no-name")) {
|
|
|
|
param.options &= ~BT_LE_ADV_OPT_USE_NAME;
|
2021-08-12 13:27:03 +02:00
|
|
|
} else if (!strcmp(arg, "name-ad")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_USE_NAME;
|
|
|
|
param.options |= BT_LE_ADV_OPT_FORCE_NAME_IN_AD;
|
2020-06-25 14:32:35 +02:00
|
|
|
} else if (!strcmp(arg, "one-time")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_ONE_TIME;
|
2020-09-29 13:51:31 +02:00
|
|
|
} else if (!strcmp(arg, "disable-37")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_37;
|
|
|
|
} else if (!strcmp(arg, "disable-38")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_38;
|
|
|
|
} else if (!strcmp(arg, "disable-39")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_39;
|
2018-01-04 11:44:50 +01:00
|
|
|
} else {
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-27 14:14:09 +02:00
|
|
|
atomic_clear(adv_opt);
|
|
|
|
atomic_set_bit_to(adv_opt, SHELL_ADV_OPT_CONNECTABLE,
|
|
|
|
(param.options & BT_LE_ADV_OPT_CONNECTABLE) > 0);
|
|
|
|
atomic_set_bit_to(adv_opt, SHELL_ADV_OPT_DISCOVERABLE, discoverable);
|
2022-09-27 15:47:48 +02:00
|
|
|
atomic_set_bit_to(adv_opt, SHELL_ADV_OPT_APPEARANCE, appearance);
|
2022-09-27 14:14:09 +02:00
|
|
|
|
|
|
|
ad_len = ad_init(ad, ARRAY_SIZE(ad), adv_opt);
|
|
|
|
if (ad_len < 0) {
|
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2022-07-22 13:03:55 +02:00
|
|
|
err = bt_le_adv_start(¶m, ad_len > 0 ? ad : NULL, ad_len, NULL, 0);
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err < 0) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to start advertising (err %d)",
|
2018-09-24 10:59:23 +03:00
|
|
|
err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2018-01-04 11:44:50 +01:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Advertising started");
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
2018-10-01 22:08:59 +02:00
|
|
|
return 0;
|
2018-01-04 11:44:50 +01:00
|
|
|
|
|
|
|
fail:
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_PERIPHERAL)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_directed_adv(const struct shell *sh,
|
2019-01-07 16:51:22 +05:30
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
bt_addr_le_t addr;
|
2020-04-09 20:06:02 +02:00
|
|
|
struct bt_le_adv_param param;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2019-05-29 10:50:08 +02:00
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
2020-04-09 20:06:02 +02:00
|
|
|
param = *BT_LE_ADV_CONN_DIR(&addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)", err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2020-06-25 14:32:35 +02:00
|
|
|
for (size_t argn = 3; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
|
|
|
if (!strcmp(arg, "low")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY;
|
|
|
|
param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
|
|
|
|
param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
|
|
|
|
} else if (!strcmp(arg, "identity")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_USE_IDENTITY;
|
|
|
|
} else if (!strcmp(arg, "dir-rpa")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA;
|
2020-09-29 13:51:31 +02:00
|
|
|
} else if (!strcmp(arg, "disable-37")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_37;
|
|
|
|
} else if (!strcmp(arg, "disable-38")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_38;
|
|
|
|
} else if (!strcmp(arg, "disable-39")) {
|
|
|
|
param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_39;
|
2019-08-08 08:47:16 +05:30
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-08-08 08:47:16 +05:30
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
2019-01-07 16:51:22 +05:30
|
|
|
}
|
|
|
|
|
2020-04-09 20:06:02 +02:00
|
|
|
err = bt_le_adv_start(¶m, NULL, 0, NULL, 0);
|
2020-02-23 11:13:13 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to start directed advertising (%d)",
|
2020-02-23 11:13:13 +01:00
|
|
|
err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Started directed advertising");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_PERIPHERAL */
|
2020-02-02 23:45:32 +01:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_EXT_ADV)
|
|
|
|
static bool adv_param_parse(size_t argc, char *argv[],
|
|
|
|
struct bt_le_adv_param *param)
|
|
|
|
{
|
2020-04-21 11:38:11 +02:00
|
|
|
memset(param, 0, sizeof(struct bt_le_adv_param));
|
2020-02-02 23:45:32 +01:00
|
|
|
|
|
|
|
if (!strcmp(argv[1], "conn-scan")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_CONNECTABLE;
|
|
|
|
param->options |= BT_LE_ADV_OPT_SCANNABLE;
|
|
|
|
} else if (!strcmp(argv[1], "conn-nscan")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_CONNECTABLE;
|
|
|
|
} else if (!strcmp(argv[1], "nconn-scan")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_SCANNABLE;
|
|
|
|
} else if (!strcmp(argv[1], "nconn-nscan")) {
|
|
|
|
/* Acceptable option, nothing to do */
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t argn = 2; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
|
|
|
if (!strcmp(arg, "ext-adv")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_EXT_ADV;
|
|
|
|
} else if (!strcmp(arg, "coded")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_CODED;
|
|
|
|
} else if (!strcmp(arg, "no-2m")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_NO_2M;
|
|
|
|
} else if (!strcmp(arg, "anon")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_ANONYMOUS;
|
|
|
|
} else if (!strcmp(arg, "tx-power")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_USE_TX_POWER;
|
|
|
|
} else if (!strcmp(arg, "scan-reports")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_NOTIFY_SCAN_REQ;
|
2021-09-17 12:46:31 +02:00
|
|
|
} else if (!strcmp(arg, "fal")) {
|
2020-02-02 23:45:32 +01:00
|
|
|
param->options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
|
|
|
|
param->options |= BT_LE_ADV_OPT_FILTER_CONN;
|
2021-09-17 12:46:31 +02:00
|
|
|
} else if (!strcmp(arg, "fal-scan")) {
|
2020-02-02 23:45:32 +01:00
|
|
|
param->options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
|
2021-09-17 12:46:31 +02:00
|
|
|
} else if (!strcmp(arg, "fal-conn")) {
|
2020-02-02 23:45:32 +01:00
|
|
|
param->options |= BT_LE_ADV_OPT_FILTER_CONN;
|
|
|
|
} else if (!strcmp(arg, "identity")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_USE_IDENTITY;
|
2020-05-05 14:59:34 +02:00
|
|
|
} else if (!strcmp(arg, "name")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_USE_NAME;
|
2021-08-12 13:27:03 +02:00
|
|
|
} else if (!strcmp(arg, "name-ad")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_USE_NAME;
|
|
|
|
param->options |= BT_LE_ADV_OPT_FORCE_NAME_IN_AD;
|
2020-04-09 20:15:26 +02:00
|
|
|
} else if (!strcmp(arg, "low")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY;
|
2020-09-29 13:51:31 +02:00
|
|
|
} else if (!strcmp(arg, "disable-37")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_DISABLE_CHAN_37;
|
|
|
|
} else if (!strcmp(arg, "disable-38")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_DISABLE_CHAN_38;
|
|
|
|
} else if (!strcmp(arg, "disable-39")) {
|
|
|
|
param->options |= BT_LE_ADV_OPT_DISABLE_CHAN_39;
|
2020-04-09 20:15:26 +02:00
|
|
|
} else if (!strcmp(arg, "directed")) {
|
|
|
|
static bt_addr_le_t addr;
|
|
|
|
|
|
|
|
if ((argn + 2) >= argc) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bt_addr_le_from_str(argv[argn + 1], argv[argn + 2],
|
|
|
|
&addr)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
param->peer = &addr;
|
|
|
|
argn += 2;
|
2020-02-02 23:45:32 +01:00
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
param->id = selected_id;
|
|
|
|
param->sid = 0;
|
2020-04-09 20:15:26 +02:00
|
|
|
if (param->peer &&
|
|
|
|
!(param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
|
|
|
|
param->interval_min = 0;
|
|
|
|
param->interval_max = 0;
|
|
|
|
} else {
|
|
|
|
param->interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
|
|
|
|
param->interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
|
|
|
|
}
|
2020-02-02 23:45:32 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_adv_create(const struct shell *sh, size_t argc, char *argv[])
|
2020-02-02 23:45:32 +01:00
|
|
|
{
|
|
|
|
struct bt_le_adv_param param;
|
|
|
|
struct bt_le_ext_adv *adv;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t adv_index;
|
2020-02-02 23:45:32 +01:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv_param_parse(argc, argv, ¶m)) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2020-02-02 22:14:15 +01:00
|
|
|
err = bt_le_ext_adv_create(¶m, &adv_callbacks, &adv);
|
2020-02-02 23:45:32 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to create advertiser set (%d)", err);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
adv_index = bt_le_ext_adv_get_index(adv);
|
|
|
|
adv_sets[adv_index] = adv;
|
|
|
|
|
2022-07-22 13:03:55 +02:00
|
|
|
atomic_clear(adv_set_opt[adv_index]);
|
|
|
|
atomic_set_bit_to(adv_set_opt[adv_index], SHELL_ADV_OPT_CONNECTABLE,
|
|
|
|
(param.options & BT_LE_ADV_OPT_CONNECTABLE) > 0);
|
|
|
|
atomic_set_bit_to(adv_set_opt[adv_index], SHELL_ADV_OPT_EXT_ADV,
|
|
|
|
(param.options & BT_LE_ADV_OPT_EXT_ADV) > 0);
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Created adv id: %d, adv: %p", adv_index, adv);
|
2020-02-02 23:45:32 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_adv_param(const struct shell *sh, size_t argc, char *argv[])
|
2020-02-02 23:45:32 +01:00
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
|
|
|
struct bt_le_adv_param param;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv_param_parse(argc, argv, ¶m)) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_ext_adv_update_param(adv, ¶m);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to update advertiser set (%d)", err);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_adv_data(const struct shell *sh, size_t argc, char *argv[])
|
2020-02-02 23:45:32 +01:00
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint8_t hex_data[1650];
|
2022-09-27 15:47:48 +02:00
|
|
|
bool appearance = false;
|
2020-04-09 20:15:26 +02:00
|
|
|
struct bt_data *data;
|
2022-09-27 15:47:48 +02:00
|
|
|
struct bt_data ad[9];
|
|
|
|
struct bt_data sd[9];
|
2020-04-09 20:15:26 +02:00
|
|
|
size_t hex_data_len;
|
2022-07-22 13:03:55 +02:00
|
|
|
size_t ad_len;
|
2020-04-09 20:15:26 +02:00
|
|
|
size_t sd_len = 0;
|
2022-07-22 13:03:55 +02:00
|
|
|
bool discoverable = false;
|
2020-04-09 20:15:26 +02:00
|
|
|
size_t *data_len;
|
2020-02-02 23:45:32 +01:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2020-04-09 20:15:26 +02:00
|
|
|
hex_data_len = 0;
|
|
|
|
data = ad;
|
|
|
|
data_len = &ad_len;
|
|
|
|
|
2020-02-02 23:45:32 +01:00
|
|
|
for (size_t argn = 1; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
2020-04-09 20:15:26 +02:00
|
|
|
if (strcmp(arg, "scan-response") &&
|
|
|
|
*data_len == ARRAY_SIZE(ad)) {
|
|
|
|
/* Maximum entries limit reached. */
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Failed to set advertising data: "
|
2021-08-19 17:03:59 +02:00
|
|
|
"Maximum entries limit reached");
|
|
|
|
|
2020-04-09 20:15:26 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2020-02-02 23:45:32 +01:00
|
|
|
if (!strcmp(arg, "discov")) {
|
2022-09-27 14:14:09 +02:00
|
|
|
discoverable = true;
|
|
|
|
} else if (!strcmp(arg, "non_discov")) {
|
|
|
|
discoverable = false;
|
2022-09-27 15:47:48 +02:00
|
|
|
} else if (!strcmp(arg, "appearance")) {
|
|
|
|
appearance = true;
|
2020-04-09 20:15:26 +02:00
|
|
|
} else if (!strcmp(arg, "scan-response")) {
|
|
|
|
if (data == sd) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Failed to set advertising data: "
|
2021-08-19 17:03:59 +02:00
|
|
|
"duplicate scan-response option");
|
2020-04-09 20:15:26 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = sd;
|
|
|
|
data_len = &sd_len;
|
2020-02-02 23:45:32 +01:00
|
|
|
} else {
|
2020-04-09 20:15:26 +02:00
|
|
|
size_t len;
|
|
|
|
|
|
|
|
len = hex2bin(arg, strlen(arg), &hex_data[hex_data_len],
|
|
|
|
sizeof(hex_data) - hex_data_len);
|
|
|
|
|
|
|
|
if (!len || (len - 1) != (hex_data[hex_data_len])) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Failed to set advertising data: "
|
2021-08-19 17:03:59 +02:00
|
|
|
"malformed hex data");
|
2020-04-09 20:15:26 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
data[*data_len].type = hex_data[hex_data_len + 1];
|
2021-08-19 17:03:59 +02:00
|
|
|
data[*data_len].data_len = len - 2;
|
2020-04-09 20:15:26 +02:00
|
|
|
data[*data_len].data = &hex_data[hex_data_len + 2];
|
|
|
|
(*data_len)++;
|
|
|
|
hex_data_len += len;
|
2020-02-02 23:45:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-27 14:14:09 +02:00
|
|
|
atomic_set_bit_to(adv_set_opt[selected_adv], SHELL_ADV_OPT_DISCOVERABLE, discoverable);
|
2022-09-27 15:47:48 +02:00
|
|
|
atomic_set_bit_to(adv_set_opt[selected_adv], SHELL_ADV_OPT_APPEARANCE,
|
|
|
|
appearance);
|
2022-09-27 14:14:09 +02:00
|
|
|
|
|
|
|
ad_len = ad_init(ad, ARRAY_SIZE(ad), adv_set_opt[selected_adv]);
|
|
|
|
if (ad_len < 0) {
|
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2020-04-16 11:31:43 +02:00
|
|
|
err = bt_le_ext_adv_set_data(adv, ad_len > 0 ? ad : NULL, ad_len,
|
|
|
|
sd_len > 0 ? sd : NULL, sd_len);
|
2020-02-02 23:45:32 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Failed to set advertising set data (%d)",
|
2020-02-02 23:45:32 +01:00
|
|
|
err);
|
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_adv_start(const struct shell *sh, size_t argc, char *argv[])
|
2020-02-02 23:45:32 +01:00
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
|
|
|
struct bt_le_ext_adv_start_param param;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t num_events = 0;
|
|
|
|
int32_t timeout = 0;
|
2020-02-02 23:45:32 +01:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Advertiser[%d] not created", selected_adv);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t argn = 1; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
|
|
|
if (!strcmp(arg, "timeout")) {
|
|
|
|
if (++argn == argc) {
|
|
|
|
goto fail_show_help;
|
|
|
|
}
|
|
|
|
|
|
|
|
timeout = strtoul(argv[argn], NULL, 16);
|
|
|
|
}
|
|
|
|
|
2020-06-18 14:13:41 +02:00
|
|
|
if (!strcmp(arg, "num-events")) {
|
2020-02-02 23:45:32 +01:00
|
|
|
if (++argn == argc) {
|
|
|
|
goto fail_show_help;
|
|
|
|
}
|
|
|
|
|
|
|
|
num_events = strtoul(argv[argn], NULL, 16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
param.timeout = timeout;
|
|
|
|
param.num_events = num_events;
|
|
|
|
|
|
|
|
err = bt_le_ext_adv_start(adv, ¶m);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Failed to start advertising set (%d)", err);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Advertiser[%d] %p set started", selected_adv, adv);
|
2020-02-02 23:45:32 +01:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail_show_help:
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_adv_stop(const struct shell *sh, size_t argc, char *argv[])
|
2020-02-02 23:45:32 +01:00
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Advertiser[%d] not created", selected_adv);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_ext_adv_stop(adv);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Failed to stop advertising set (%d)", err);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Advertiser set stopped");
|
2020-02-02 23:45:32 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_adv_delete(const struct shell *sh, size_t argc, char *argv[])
|
2020-02-02 23:45:32 +01:00
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Advertiser[%d] not created", selected_adv);
|
2020-02-02 23:45:32 +01:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_ext_adv_delete(adv);
|
|
|
|
if (err) {
|
|
|
|
shell_error(ctx_shell, "Failed to delete advertiser set");
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
adv_sets[selected_adv] = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_adv_select(const struct shell *sh, size_t argc, char *argv[])
|
2020-02-02 23:45:32 +01:00
|
|
|
{
|
|
|
|
if (argc == 2) {
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t id = strtol(argv[1], NULL, 10);
|
2020-02-02 23:45:32 +01:00
|
|
|
|
|
|
|
if (!(id < ARRAY_SIZE(adv_sets))) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
selected_adv = id;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(adv_sets); i++) {
|
|
|
|
if (adv_sets[i]) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Advertiser[%d] %p", i, adv_sets[i]);
|
2020-02-02 23:45:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
2020-03-16 14:38:53 +01:00
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_adv_info(const struct shell *sh, size_t argc, char *argv[])
|
2020-03-16 14:38:53 +01:00
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
2020-08-19 12:54:46 +05:30
|
|
|
struct bt_le_ext_adv_info info;
|
2020-03-16 14:38:53 +01:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
err = bt_le_ext_adv_get_info(adv, &info);
|
2020-03-16 14:38:53 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "OOB data failed");
|
2020-03-16 14:38:53 +01:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Advertiser[%d] %p", selected_adv, adv);
|
|
|
|
shell_print(sh, "Id: %d, TX power: %d dBm", info.id, info.tx_power);
|
2022-11-22 15:32:01 +01:00
|
|
|
print_le_addr("Address", info.addr);
|
2020-03-16 14:38:53 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2020-03-27 11:31:43 +01:00
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
#if defined(CONFIG_BT_PERIPHERAL)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_adv_oob(const struct shell *sh, size_t argc, char *argv[])
|
2020-03-27 11:31:43 +01:00
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
err = bt_le_ext_adv_oob_get_local(adv, &oob_local);
|
2020-03-27 11:31:43 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "OOB data failed");
|
2020-03-27 11:31:43 +01:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
print_le_oob(sh, &oob_local);
|
2020-03-27 11:31:43 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2020-08-19 12:54:46 +05:30
|
|
|
#endif /* CONFIG_BT_PERIPHERAL */
|
2020-05-01 16:50:54 +02:00
|
|
|
|
2022-10-13 11:27:56 +02:00
|
|
|
#if defined(CONFIG_BT_PRIVACY)
|
|
|
|
static int cmd_adv_rpa_expire(const struct shell *sh, size_t argc, char *argv[])
|
|
|
|
{
|
|
|
|
if (!strcmp(argv[1], "on")) {
|
|
|
|
atomic_clear_bit(adv_set_opt[selected_adv], SHELL_ADV_OPT_KEEP_RPA);
|
|
|
|
shell_print(sh, "RPA will expire on next timeout");
|
|
|
|
} else if (!strcmp(argv[1], "off")) {
|
|
|
|
atomic_set_bit(adv_set_opt[selected_adv], SHELL_ADV_OPT_KEEP_RPA);
|
|
|
|
shell_print(sh, "RPA will not expire on RPA timeout");
|
|
|
|
} else {
|
|
|
|
shell_error(sh, "Invalid argument: %s", argv[1]);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-05-01 16:50:54 +02:00
|
|
|
#if defined(CONFIG_BT_PER_ADV)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_per_adv(const struct shell *sh, size_t argc, char *argv[])
|
2020-05-01 16:50:54 +02:00
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
|
|
|
|
|
|
|
if (!adv) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "No extended advertisement set selected");
|
2020-05-01 16:50:54 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "off")) {
|
|
|
|
if (bt_le_per_adv_stop(adv) < 0) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh,
|
2020-05-01 16:50:54 +02:00
|
|
|
"Failed to stop periodic advertising");
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Periodic advertising stopped");
|
2020-05-01 16:50:54 +02:00
|
|
|
}
|
|
|
|
} else if (!strcmp(argv[1], "on")) {
|
|
|
|
if (bt_le_per_adv_start(adv) < 0) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh,
|
2020-05-01 16:50:54 +02:00
|
|
|
"Failed to start periodic advertising");
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Periodic advertising started");
|
2020-05-01 16:50:54 +02:00
|
|
|
}
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid argument: %s", argv[1]);
|
2020-05-01 16:50:54 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_per_adv_param(const struct shell *sh, size_t argc,
|
2020-05-01 16:50:54 +02:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
|
|
|
struct bt_le_per_adv_param param;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "No extended advertisement set selected");
|
2020-05-01 16:50:54 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc > 1) {
|
|
|
|
param.interval_min = strtol(argv[1], NULL, 16);
|
|
|
|
} else {
|
|
|
|
param.interval_min = BT_GAP_ADV_SLOW_INT_MIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc > 2) {
|
|
|
|
param.interval_max = strtol(argv[2], NULL, 16);
|
|
|
|
} else {
|
|
|
|
param.interval_max = param.interval_min * 1.2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (param.interval_min > param.interval_max) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh,
|
2020-05-01 16:50:54 +02:00
|
|
|
"Min interval shall be less than max interval");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc > 3 && !strcmp(argv[3], "tx-power")) {
|
|
|
|
param.options = BT_LE_ADV_OPT_USE_TX_POWER;
|
|
|
|
} else {
|
|
|
|
param.options = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_per_adv_set_param(adv, ¶m);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to set periodic advertising "
|
2020-05-01 16:50:54 +02:00
|
|
|
"parameters (%d)", err);
|
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_per_adv_data(const struct shell *sh, size_t argc,
|
2020-05-01 16:50:54 +02:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
|
|
|
|
static struct bt_data ad;
|
|
|
|
static uint8_t hex_data[256];
|
|
|
|
uint8_t ad_len = 0;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!adv) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "No extended advertisement set selected");
|
2020-05-01 16:50:54 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2021-02-01 17:48:44 +01:00
|
|
|
memset(hex_data, 0, sizeof(hex_data));
|
2020-05-01 16:50:54 +02:00
|
|
|
ad_len = hex2bin(argv[1], strlen(argv[1]), hex_data, sizeof(hex_data));
|
|
|
|
|
|
|
|
if (!ad_len) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Could not parse adv data");
|
2020-05-01 16:50:54 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
ad.data_len = hex_data[0];
|
|
|
|
ad.type = hex_data[1];
|
|
|
|
ad.data = &hex_data[2];
|
|
|
|
|
2021-02-01 17:48:44 +01:00
|
|
|
err = bt_le_per_adv_set_data(adv, &ad, 1);
|
2020-05-01 16:50:54 +02:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh,
|
2020-05-01 16:50:54 +02:00
|
|
|
"Failed to set periodic advertising data (%d)",
|
|
|
|
err);
|
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_PER_ADV */
|
2020-10-01 09:28:58 +05:30
|
|
|
#endif /* CONFIG_BT_EXT_ADV */
|
|
|
|
#endif /* CONFIG_BT_BROADCASTER */
|
2020-05-14 17:53:53 +02:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_PER_ADV_SYNC)
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_per_adv_sync_create(const struct shell *sh, size_t argc,
|
2020-05-14 17:53:53 +02:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
struct bt_le_per_adv_sync_param create_params = { 0 };
|
|
|
|
uint32_t options = 0;
|
2020-08-16 23:04:43 +02:00
|
|
|
struct bt_le_per_adv_sync **free_per_adv_sync = NULL;
|
2020-05-14 17:53:53 +02:00
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(per_adv_syncs); i++) {
|
|
|
|
if (per_adv_syncs[i] == NULL) {
|
2020-08-16 23:04:43 +02:00
|
|
|
free_per_adv_sync = &per_adv_syncs[i];
|
2020-05-14 17:53:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == ARRAY_SIZE(per_adv_syncs)) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Cannot create more per adv syncs");
|
2020-05-14 17:53:53 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &create_params.addr);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)", err);
|
2020-05-14 17:53:53 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Default values */
|
|
|
|
create_params.timeout = 1000; /* 10 seconds */
|
|
|
|
create_params.skip = 10;
|
|
|
|
|
|
|
|
create_params.sid = strtol(argv[3], NULL, 16);
|
|
|
|
|
|
|
|
for (int i = 4; i < argc; i++) {
|
|
|
|
if (!strcmp(argv[i], "aoa")) {
|
|
|
|
options |= BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOA;
|
|
|
|
} else if (!strcmp(argv[i], "aod_1us")) {
|
|
|
|
options |= BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_1US;
|
|
|
|
} else if (!strcmp(argv[i], "aod_2us")) {
|
|
|
|
options |= BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_2US;
|
|
|
|
} else if (!strcmp(argv[i], "only_cte")) {
|
|
|
|
options |=
|
|
|
|
BT_LE_PER_ADV_SYNC_OPT_SYNC_ONLY_CONST_TONE_EXT;
|
|
|
|
} else if (!strcmp(argv[i], "timeout")) {
|
|
|
|
if (++i == argc) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-05-14 17:53:53 +02:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
create_params.timeout = strtoul(argv[i], NULL, 16);
|
|
|
|
} else if (!strcmp(argv[i], "skip")) {
|
|
|
|
if (++i == argc) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-05-14 17:53:53 +02:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
create_params.skip = strtoul(argv[i], NULL, 16);
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-05-14 17:53:53 +02:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: add support to parse using the per adv list */
|
|
|
|
}
|
|
|
|
|
|
|
|
create_params.options = options;
|
|
|
|
|
2020-09-28 10:33:07 +02:00
|
|
|
err = bt_le_per_adv_sync_create(&create_params, free_per_adv_sync);
|
2020-05-14 17:53:53 +02:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Per adv sync failed (%d)", err);
|
2020-05-14 17:53:53 +02:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Per adv sync pending");
|
2020-05-14 17:53:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_per_adv_sync_delete(const struct shell *sh, size_t argc,
|
2020-05-14 17:53:53 +02:00
|
|
|
char *argv[])
|
|
|
|
{
|
2021-03-31 15:30:40 +02:00
|
|
|
struct bt_le_per_adv_sync *per_adv_sync = NULL;
|
2021-04-01 14:32:06 +02:00
|
|
|
int index;
|
|
|
|
int err;
|
2020-05-14 17:53:53 +02:00
|
|
|
|
|
|
|
if (argc > 1) {
|
|
|
|
index = strtol(argv[1], NULL, 10);
|
2021-04-01 14:32:06 +02:00
|
|
|
} else {
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index >= ARRAY_SIZE(per_adv_syncs)) {
|
2022-03-22 13:35:44 +01:00
|
|
|
shell_error(sh, "Maximum index is %zu but %d was requested",
|
2021-04-01 14:32:06 +02:00
|
|
|
ARRAY_SIZE(per_adv_syncs) - 1, index);
|
2020-05-14 17:53:53 +02:00
|
|
|
}
|
|
|
|
|
2021-03-31 15:30:40 +02:00
|
|
|
per_adv_sync = per_adv_syncs[index];
|
2020-05-14 17:53:53 +02:00
|
|
|
|
|
|
|
if (!per_adv_sync) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2021-03-31 15:30:40 +02:00
|
|
|
err = bt_le_per_adv_sync_delete(per_adv_sync);
|
2020-05-14 17:53:53 +02:00
|
|
|
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Per adv sync delete failed (%d)", err);
|
2020-05-14 17:53:53 +02:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Per adv sync deleted");
|
2021-03-31 15:30:40 +02:00
|
|
|
per_adv_syncs[index] = NULL;
|
2020-05-14 17:53:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2020-09-23 22:39:29 +02:00
|
|
|
|
2022-10-12 14:27:09 +01:00
|
|
|
#if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_past_subscribe(const struct shell *sh, size_t argc,
|
2020-09-23 22:39:29 +02:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
struct bt_le_per_adv_sync_transfer_param param;
|
|
|
|
int err;
|
|
|
|
int i = 0;
|
|
|
|
bool global = true;
|
|
|
|
|
|
|
|
if (i == ARRAY_SIZE(per_adv_syncs)) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Cannot create more per adv syncs");
|
2020-09-23 22:39:29 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Default values */
|
|
|
|
param.options = 0;
|
|
|
|
param.timeout = 1000; /* 10 seconds */
|
|
|
|
param.skip = 10;
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
|
|
if (!strcmp(argv[i], "aoa")) {
|
|
|
|
param.options |=
|
|
|
|
BT_LE_PER_ADV_SYNC_TRANSFER_OPT_SYNC_NO_AOA;
|
|
|
|
} else if (!strcmp(argv[i], "aod_1us")) {
|
|
|
|
param.options |=
|
|
|
|
BT_LE_PER_ADV_SYNC_TRANSFER_OPT_SYNC_NO_AOD_1US;
|
|
|
|
} else if (!strcmp(argv[i], "aod_2us")) {
|
|
|
|
param.options |=
|
|
|
|
BT_LE_PER_ADV_SYNC_TRANSFER_OPT_SYNC_NO_AOD_2US;
|
|
|
|
} else if (!strcmp(argv[i], "only_cte")) {
|
|
|
|
param.options |=
|
|
|
|
BT_LE_PER_ADV_SYNC_TRANSFER_OPT_SYNC_ONLY_CTE;
|
|
|
|
} else if (!strcmp(argv[i], "timeout")) {
|
|
|
|
if (++i == argc) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-09-23 22:39:29 +02:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
param.timeout = strtoul(argv[i], NULL, 16);
|
|
|
|
} else if (!strcmp(argv[i], "skip")) {
|
|
|
|
if (++i == argc) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-09-23 22:39:29 +02:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
param.skip = strtoul(argv[i], NULL, 16);
|
|
|
|
} else if (!strcmp(argv[i], "conn")) {
|
|
|
|
if (!default_conn) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Not connected");
|
2020-09-23 22:39:29 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
global = false;
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-09-23 22:39:29 +02:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_le_per_adv_sync_cb_register(&per_adv_sync_cb);
|
|
|
|
|
|
|
|
err = bt_le_per_adv_sync_transfer_subscribe(
|
|
|
|
global ? NULL : default_conn, ¶m);
|
|
|
|
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "PAST subscribe failed (%d)", err);
|
2020-09-23 22:39:29 +02:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Subscribed to PAST");
|
2020-09-23 22:39:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_past_unsubscribe(const struct shell *sh, size_t argc,
|
2020-09-23 22:39:29 +02:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc > 1) {
|
|
|
|
if (!strcmp(argv[1], "conn")) {
|
|
|
|
if (default_conn) {
|
|
|
|
err =
|
|
|
|
bt_le_per_adv_sync_transfer_unsubscribe(
|
|
|
|
default_conn);
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Not connected");
|
2020-09-23 22:39:29 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-09-23 22:39:29 +02:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
err = bt_le_per_adv_sync_transfer_unsubscribe(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "PAST unsubscribe failed (%d)", err);
|
2020-09-23 22:39:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
2022-10-12 14:27:09 +01:00
|
|
|
#endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER */
|
2021-03-24 10:58:12 +01:00
|
|
|
|
2022-10-12 14:27:09 +01:00
|
|
|
#if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_per_adv_sync_transfer(const struct shell *sh, size_t argc,
|
2021-03-24 10:58:12 +01:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
int index;
|
|
|
|
struct bt_le_per_adv_sync *per_adv_sync;
|
|
|
|
|
|
|
|
if (argc > 1) {
|
|
|
|
index = strtol(argv[1], NULL, 10);
|
|
|
|
} else {
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
|
2021-04-01 14:32:06 +02:00
|
|
|
if (index >= ARRAY_SIZE(per_adv_syncs)) {
|
2022-03-22 13:35:44 +01:00
|
|
|
shell_error(sh, "Maximum index is %zu but %d was requested",
|
2021-04-01 14:32:06 +02:00
|
|
|
ARRAY_SIZE(per_adv_syncs) - 1, index);
|
|
|
|
}
|
|
|
|
|
2021-03-24 10:58:12 +01:00
|
|
|
per_adv_sync = per_adv_syncs[index];
|
|
|
|
if (!per_adv_sync) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_per_adv_sync_transfer(per_adv_sync, default_conn, 0);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Periodic advertising sync transfer failed (%d)", err);
|
2021-03-24 10:58:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
2022-10-12 14:27:09 +01:00
|
|
|
#endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER */
|
2020-05-14 17:53:53 +02:00
|
|
|
#endif /* CONFIG_BT_PER_ADV_SYNC */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2019-01-09 23:14:36 +05:30
|
|
|
#if defined(CONFIG_BT_CONN)
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_CENTRAL)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_connect_le(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
2019-01-07 16:51:22 +05:30
|
|
|
bt_addr_le_t addr;
|
|
|
|
struct bt_conn *conn;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t options = 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2022-05-24 16:15:59 +02:00
|
|
|
/* When no arguments are specified, connect to the last scanned device. */
|
|
|
|
if (argc == 1) {
|
|
|
|
if (auto_connect.addr_set) {
|
|
|
|
bt_addr_le_copy(&addr, &auto_connect.addr);
|
|
|
|
} else {
|
|
|
|
shell_error(sh, "No connectable adv stored, please trigger a scan first.");
|
|
|
|
shell_help(sh);
|
|
|
|
|
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
2022-08-03 08:22:19 +02:00
|
|
|
} else {
|
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
|
|
|
if (err) {
|
|
|
|
shell_error(sh, "Invalid peer address (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2020-02-02 23:51:14 +01:00
|
|
|
#if defined(CONFIG_BT_EXT_ADV)
|
|
|
|
for (size_t argn = 3; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
|
|
|
if (!strcmp(arg, "coded")) {
|
2020-04-23 11:49:17 +02:00
|
|
|
options |= BT_CONN_LE_OPT_CODED;
|
2020-02-02 23:51:14 +01:00
|
|
|
} else if (!strcmp(arg, "no-1m")) {
|
2020-04-23 11:49:17 +02:00
|
|
|
options |= BT_CONN_LE_OPT_NO_1M;
|
2020-02-02 23:51:14 +01:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-02-02 23:51:14 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* defined(CONFIG_BT_EXT_ADV) */
|
|
|
|
|
|
|
|
struct bt_conn_le_create_param *create_params =
|
|
|
|
BT_CONN_LE_CREATE_PARAM(options,
|
|
|
|
BT_GAP_SCAN_FAST_INTERVAL,
|
|
|
|
BT_GAP_SCAN_FAST_INTERVAL);
|
|
|
|
|
|
|
|
err = bt_conn_le_create(&addr, create_params, BT_LE_CONN_PARAM_DEFAULT,
|
|
|
|
&conn);
|
2020-02-01 18:13:05 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Connection failed (%d)", err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2019-01-07 16:51:22 +05:30
|
|
|
} else {
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Connection pending");
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
/* unref connection obj in advance as app user */
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-14 12:28:45 +02:00
|
|
|
#if !defined(CONFIG_BT_FILTER_ACCEPT_LIST)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_auto_conn(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
int err;
|
|
|
|
|
2019-05-29 10:50:08 +02:00
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)", err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (argc < 4) {
|
2018-10-01 22:08:59 +02:00
|
|
|
return bt_le_set_auto_conn(&addr, BT_LE_CONN_PARAM_DEFAULT);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(argv[3], "on")) {
|
2018-10-01 22:08:59 +02:00
|
|
|
return bt_le_set_auto_conn(&addr, BT_LE_CONN_PARAM_DEFAULT);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(argv[3], "off")) {
|
2018-10-01 22:08:59 +02:00
|
|
|
return bt_le_set_auto_conn(&addr, NULL);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-03-25 11:03:59 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2021-09-14 12:28:45 +02:00
|
|
|
#endif /* !defined(CONFIG_BT_FILTER_ACCEPT_LIST) */
|
2022-09-06 16:18:57 +02:00
|
|
|
|
|
|
|
static int cmd_connect_le_name(const struct shell *sh, size_t argc, char *argv[])
|
|
|
|
{
|
|
|
|
const uint16_t timeout_seconds = 10;
|
|
|
|
const struct bt_le_scan_param param = {
|
|
|
|
.type = BT_LE_SCAN_TYPE_ACTIVE,
|
|
|
|
.options = BT_LE_SCAN_OPT_NONE,
|
|
|
|
.interval = BT_GAP_SCAN_FAST_INTERVAL,
|
|
|
|
.window = BT_GAP_SCAN_FAST_WINDOW,
|
|
|
|
.timeout = timeout_seconds * 100, /* 10ms units */
|
|
|
|
};
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/* Set the name filter which we will use in the scan callback to
|
|
|
|
* automatically connect to the first device that passes the filter
|
|
|
|
*/
|
|
|
|
err = cmd_scan_filter_set_name(sh, argc, argv);
|
|
|
|
if (err) {
|
|
|
|
shell_error(sh,
|
|
|
|
"Bluetooth set scan filter name to %s failed (err %d)",
|
|
|
|
argv[1], err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_scan_start(¶m, NULL);
|
|
|
|
if (err) {
|
|
|
|
shell_error(sh, "Bluetooth scan failed (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_print(sh, "Bluetooth active scan enabled");
|
|
|
|
|
|
|
|
/* Set boolean to tell the scan callback to connect to this name */
|
|
|
|
auto_connect.connect_name = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_CENTRAL */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_disconnect(const struct shell *sh, size_t argc, char *argv[])
|
2018-08-23 12:07:56 +02:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
2019-01-07 16:51:22 +05:30
|
|
|
int err;
|
2018-08-23 12:07:56 +02:00
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
if (default_conn && argc < 3) {
|
|
|
|
conn = bt_conn_ref(default_conn);
|
|
|
|
} else {
|
|
|
|
bt_addr_le_t addr;
|
2018-08-23 12:07:56 +02:00
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
if (argc < 3) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-03-25 11:03:59 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
2019-01-07 16:51:22 +05:30
|
|
|
}
|
2018-08-23 12:07:56 +02:00
|
|
|
|
2019-05-29 10:50:08 +02:00
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
2019-01-07 16:51:22 +05:30
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)",
|
2019-01-07 16:51:22 +05:30
|
|
|
err);
|
|
|
|
return err;
|
|
|
|
}
|
2018-11-09 14:40:59 +02:00
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
conn = bt_conn_lookup_addr_le(selected_id, &addr);
|
|
|
|
}
|
2018-11-09 14:40:59 +02:00
|
|
|
|
2018-08-23 12:07:56 +02:00
|
|
|
if (!conn) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Not connected");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2019-01-07 16:51:22 +05:30
|
|
|
}
|
2018-08-23 12:07:56 +02:00
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Disconnection failed (err %d)", err);
|
2019-01-07 16:51:22 +05:30
|
|
|
return err;
|
2018-08-23 12:07:56 +02:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
2019-01-07 16:51:22 +05:30
|
|
|
bt_conn_unref(conn);
|
|
|
|
|
2018-10-01 22:08:59 +02:00
|
|
|
return 0;
|
2018-08-23 12:07:56 +02:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_select(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
int err;
|
|
|
|
|
2019-05-29 10:50:08 +02:00
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)", err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2020-07-15 12:31:49 +02:00
|
|
|
conn = bt_conn_lookup_addr_le(selected_id, &addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (!conn) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "No matching connection found");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (default_conn) {
|
|
|
|
bt_conn_unref(default_conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
default_conn = conn;
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static const char *get_conn_type_str(uint8_t type)
|
2019-08-05 09:31:20 +02:00
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case BT_CONN_TYPE_LE: return "LE";
|
|
|
|
case BT_CONN_TYPE_BR: return "BR/EDR";
|
|
|
|
case BT_CONN_TYPE_SCO: return "SCO";
|
|
|
|
default: return "Invalid";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static const char *get_conn_role_str(uint8_t role)
|
2019-08-05 09:31:20 +02:00
|
|
|
{
|
|
|
|
switch (role) {
|
2021-09-14 12:28:45 +02:00
|
|
|
case BT_CONN_ROLE_CENTRAL: return "central";
|
|
|
|
case BT_CONN_ROLE_PERIPHERAL: return "peripheral";
|
2019-08-05 09:31:20 +02:00
|
|
|
default: return "Invalid";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_info(const struct shell *sh, size_t argc, char *argv[])
|
2019-08-05 09:31:20 +02:00
|
|
|
{
|
|
|
|
struct bt_conn *conn = NULL;
|
|
|
|
struct bt_conn_info info;
|
2019-10-07 13:34:02 +03:00
|
|
|
bt_addr_le_t addr;
|
2019-08-05 09:31:20 +02:00
|
|
|
int err;
|
|
|
|
|
|
|
|
switch (argc) {
|
|
|
|
case 1:
|
|
|
|
if (default_conn) {
|
|
|
|
conn = bt_conn_ref(default_conn);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
addr.type = BT_ADDR_LE_PUBLIC;
|
|
|
|
err = bt_addr_from_str(argv[1], &addr.a);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)",
|
2019-08-05 09:31:20 +02:00
|
|
|
err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
conn = bt_conn_lookup_addr_le(selected_id, &addr);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
|
|
|
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)",
|
2019-08-05 09:31:20 +02:00
|
|
|
err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
conn = bt_conn_lookup_addr_le(selected_id, &addr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!conn) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Not connected");
|
2019-08-05 09:31:20 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_conn_get_info(conn, &info);
|
|
|
|
if (err) {
|
|
|
|
shell_print(ctx_shell, "Failed to get info");
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_print(ctx_shell, "Type: %s, Role: %s, Id: %u",
|
|
|
|
get_conn_type_str(info.type),
|
|
|
|
get_conn_role_str(info.role),
|
|
|
|
info.id);
|
|
|
|
|
|
|
|
if (info.type == BT_CONN_TYPE_LE) {
|
|
|
|
print_le_addr("Remote", info.le.dst);
|
|
|
|
print_le_addr("Local", info.le.src);
|
|
|
|
print_le_addr("Remote on-air", info.le.remote);
|
|
|
|
print_le_addr("Local on-air", info.le.local);
|
|
|
|
|
2023-01-05 14:09:39 +01:00
|
|
|
shell_print(ctx_shell, "Interval: 0x%04x (%u us)",
|
2020-11-11 15:09:36 +01:00
|
|
|
info.le.interval,
|
2023-01-05 14:09:39 +01:00
|
|
|
BT_CONN_INTERVAL_TO_US(info.le.interval));
|
|
|
|
shell_print(ctx_shell, "Latency: 0x%04x",
|
|
|
|
info.le.latency);
|
2019-08-05 09:31:20 +02:00
|
|
|
shell_print(ctx_shell, "Supervision timeout: 0x%04x (%d ms)",
|
|
|
|
info.le.timeout, info.le.timeout * 10);
|
2020-07-13 17:25:42 +02:00
|
|
|
#if defined(CONFIG_BT_USER_PHY_UPDATE)
|
|
|
|
shell_print(ctx_shell, "LE PHY: TX PHY %s, RX PHY %s",
|
|
|
|
phy2str(info.le.phy->tx_phy),
|
|
|
|
phy2str(info.le.phy->rx_phy));
|
|
|
|
#endif
|
|
|
|
#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
|
|
|
|
shell_print(ctx_shell, "LE data len: TX (len: %d time: %d)"
|
|
|
|
" RX (len: %d time: %d)",
|
|
|
|
info.le.data_len->tx_max_len,
|
|
|
|
info.le.data_len->tx_max_time,
|
|
|
|
info.le.data_len->rx_max_len,
|
|
|
|
info.le.data_len->rx_max_time);
|
|
|
|
#endif
|
2019-08-05 09:31:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_BREDR)
|
|
|
|
if (info.type == BT_CONN_TYPE_BR) {
|
|
|
|
char addr_str[BT_ADDR_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_to_str(info.br.dst, addr_str, sizeof(addr_str));
|
|
|
|
shell_print(ctx_shell, "Peer address %s", addr_str);
|
|
|
|
}
|
|
|
|
#endif /* defined(CONFIG_BT_BREDR) */
|
|
|
|
|
|
|
|
done:
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_conn_update(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_le_conn_param param;
|
|
|
|
int err;
|
|
|
|
|
2021-04-22 23:14:08 +08:00
|
|
|
if (default_conn == NULL) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh,
|
2021-04-22 23:14:08 +08:00
|
|
|
"%s: at least, one connection is required",
|
2021-09-20 10:58:45 +02:00
|
|
|
sh->ctx->active_cmd.syntax);
|
2021-04-22 23:14:08 +08:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
param.interval_min = strtoul(argv[1], NULL, 16);
|
|
|
|
param.interval_max = strtoul(argv[2], NULL, 16);
|
|
|
|
param.latency = strtoul(argv[3], NULL, 16);
|
|
|
|
param.timeout = strtoul(argv[4], NULL, 16);
|
|
|
|
|
|
|
|
err = bt_conn_le_param_update(default_conn, ¶m);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "conn update failed (err %d).", err);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "conn update initiated.");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2020-04-22 21:19:41 +02:00
|
|
|
#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint16_t tx_time_calc(uint8_t phy, uint16_t max_len)
|
2020-04-22 21:19:41 +02:00
|
|
|
{
|
|
|
|
/* Access address + header + payload + MIC + CRC */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t total_len = 4 + 2 + max_len + 4 + 3;
|
2020-04-22 21:19:41 +02:00
|
|
|
|
|
|
|
switch (phy) {
|
|
|
|
case BT_GAP_LE_PHY_1M:
|
|
|
|
/* 1 byte preamble, 8 us per byte */
|
|
|
|
return 8 * (1 + total_len);
|
|
|
|
case BT_GAP_LE_PHY_2M:
|
|
|
|
/* 2 byte preamble, 4 us per byte */
|
|
|
|
return 4 * (2 + total_len);
|
|
|
|
case BT_GAP_LE_PHY_CODED:
|
|
|
|
/* S8: Preamble + CI + TERM1 + 64 us per byte + TERM2 */
|
|
|
|
return 80 + 16 + 24 + 64 * (total_len) + 24;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_conn_data_len_update(const struct shell *sh, size_t argc,
|
2020-04-22 21:19:41 +02:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
struct bt_conn_le_data_len_param param;
|
|
|
|
int err;
|
|
|
|
|
2021-04-22 23:14:08 +08:00
|
|
|
if (default_conn == NULL) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh,
|
2021-04-22 23:14:08 +08:00
|
|
|
"%s: at least, one connection is required",
|
2021-09-20 10:58:45 +02:00
|
|
|
sh->ctx->active_cmd.syntax);
|
2021-04-22 23:14:08 +08:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2020-04-22 21:19:41 +02:00
|
|
|
param.tx_max_len = strtoul(argv[1], NULL, 10);
|
|
|
|
|
|
|
|
if (argc > 2) {
|
|
|
|
param.tx_max_time = strtoul(argv[2], NULL, 10);
|
|
|
|
} else {
|
|
|
|
/* Assume 1M if not able to retrieve PHY */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t phy = BT_GAP_LE_PHY_1M;
|
2020-04-22 21:19:41 +02:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_USER_PHY_UPDATE)
|
|
|
|
struct bt_conn_info info;
|
|
|
|
|
|
|
|
err = bt_conn_get_info(default_conn, &info);
|
|
|
|
if (!err) {
|
|
|
|
phy = info.le.phy->tx_phy;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
param.tx_max_time = tx_time_calc(phy, param.tx_max_len);
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Calculated tx time: %d", param.tx_max_time);
|
2020-04-22 21:19:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
err = bt_conn_le_data_len_update(default_conn, ¶m);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "data len update failed (err %d).", err);
|
2020-04-22 21:19:41 +02:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "data len update initiated.");
|
2020-04-22 21:19:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-04-22 20:44:35 +02:00
|
|
|
#if defined(CONFIG_BT_USER_PHY_UPDATE)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_conn_phy_update(const struct shell *sh, size_t argc,
|
2020-04-22 20:44:35 +02:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
struct bt_conn_le_phy_param param;
|
|
|
|
int err;
|
|
|
|
|
2021-04-17 09:41:45 +08:00
|
|
|
if (default_conn == NULL) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh,
|
2021-04-17 09:41:45 +08:00
|
|
|
"%s: at least, one connection is required",
|
2021-09-20 10:58:45 +02:00
|
|
|
sh->ctx->active_cmd.syntax);
|
2021-04-17 09:41:45 +08:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2020-04-22 20:44:35 +02:00
|
|
|
param.pref_tx_phy = strtoul(argv[1], NULL, 16);
|
2020-05-12 12:09:32 +02:00
|
|
|
param.pref_rx_phy = param.pref_tx_phy;
|
|
|
|
param.options = BT_CONN_LE_PHY_OPT_NONE;
|
|
|
|
|
|
|
|
for (size_t argn = 2; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
|
|
|
if (!strcmp(arg, "s2")) {
|
|
|
|
param.options |= BT_CONN_LE_PHY_OPT_CODED_S2;
|
|
|
|
} else if (!strcmp(arg, "s8")) {
|
|
|
|
param.options |= BT_CONN_LE_PHY_OPT_CODED_S8;
|
|
|
|
} else {
|
|
|
|
param.pref_rx_phy = strtoul(arg, NULL, 16);
|
|
|
|
}
|
2020-04-22 20:44:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_conn_le_phy_update(default_conn, ¶m);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "PHY update failed (err %d).", err);
|
2020-04-22 20:44:35 +02:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "PHY update initiated.");
|
2020-04-22 20:44:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-04-03 14:00:50 -04:00
|
|
|
#if defined(CONFIG_BT_CENTRAL)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_chan_map(const struct shell *sh, size_t argc, char *argv[])
|
2019-01-07 16:51:22 +05:30
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t chan_map[5] = {};
|
2019-01-07 16:51:22 +05:30
|
|
|
int err;
|
|
|
|
|
2019-05-29 10:50:08 +02:00
|
|
|
if (hex2bin(argv[1], strlen(argv[1]), chan_map, 5) == 0) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid channel map");
|
2019-01-07 16:51:22 +05:30
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
2019-05-29 10:50:08 +02:00
|
|
|
sys_mem_swap(chan_map, 5);
|
2019-01-07 16:51:22 +05:30
|
|
|
|
|
|
|
err = bt_le_set_chan_map(chan_map);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to set channel map (err %d)", err);
|
2019-01-07 16:51:22 +05:30
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Channel map set");
|
2019-01-07 16:51:22 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
2019-04-03 14:00:50 -04:00
|
|
|
#endif /* CONFIG_BT_CENTRAL */
|
2019-01-07 16:51:22 +05:30
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_oob(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2018-01-04 11:44:50 +01:00
|
|
|
int err;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2019-05-28 13:28:48 +02:00
|
|
|
err = bt_le_oob_get_local(selected_id, &oob_local);
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "OOB data failed");
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
print_le_oob(sh, &oob_local);
|
2019-05-28 13:28:48 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-19 12:54:46 +05:30
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_oob_remote(const struct shell *sh, size_t argc,
|
2019-05-28 13:28:48 +02:00
|
|
|
char *argv[])
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
|
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)", err);
|
2019-05-28 13:28:48 +02:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_addr_le_copy(&oob_remote.addr, &addr);
|
|
|
|
|
|
|
|
if (argc == 5) {
|
|
|
|
hex2bin(argv[3], strlen(argv[3]), oob_remote.le_sc_data.r,
|
|
|
|
sizeof(oob_remote.le_sc_data.r));
|
|
|
|
hex2bin(argv[4], strlen(argv[4]), oob_remote.le_sc_data.c,
|
|
|
|
sizeof(oob_remote.le_sc_data.c));
|
|
|
|
bt_set_oob_data_flag(true);
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-07-31 16:07:25 +02:00
|
|
|
return -ENOEXEC;
|
2019-05-28 13:28:48 +02:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_oob_clear(const struct shell *sh, size_t argc, char *argv[])
|
2019-07-31 16:07:25 +02:00
|
|
|
{
|
|
|
|
memset(&oob_remote, 0, sizeof(oob_remote));
|
|
|
|
bt_set_oob_data_flag(false);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2020-08-19 12:54:46 +05:30
|
|
|
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR) */
|
2019-07-31 16:07:25 +02:00
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_clear(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2018-01-04 11:44:50 +01:00
|
|
|
bt_addr_le_t addr;
|
2017-05-22 11:49:31 +03:00
|
|
|
int err;
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
if (strcmp(argv[1], "all") == 0) {
|
2018-07-16 15:11:08 +03:00
|
|
|
err = bt_unpair(selected_id, NULL);
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to clear pairings (err %d)",
|
2018-09-24 10:59:23 +03:00
|
|
|
err);
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Pairings successfully cleared");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-10-01 22:08:59 +02:00
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
if (argc < 3) {
|
|
|
|
#if defined(CONFIG_BT_BREDR)
|
|
|
|
addr.type = BT_ADDR_LE_PUBLIC;
|
2019-05-29 10:50:08 +02:00
|
|
|
err = bt_addr_from_str(argv[1], &addr.a);
|
2018-01-04 11:44:50 +01:00
|
|
|
#else
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Both address and address type needed");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2019-05-29 10:50:08 +02:00
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Invalid address");
|
2018-10-01 22:08:59 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-07-16 15:11:08 +03:00
|
|
|
err = bt_unpair(selected_id, &addr);
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to clear pairing (err %d)", err);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Pairing successfully cleared");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_security(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2018-01-04 11:44:50 +01:00
|
|
|
int err, sec;
|
2019-07-29 11:35:23 +02:00
|
|
|
struct bt_conn_info info;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2019-07-29 11:35:23 +02:00
|
|
|
if (!default_conn || (bt_conn_get_info(default_conn, &info) < 0)) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Not connected");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2022-06-03 15:40:14 +02:00
|
|
|
if (argc < 2) {
|
|
|
|
shell_print(sh, "BT_SECURITY_L%d", bt_conn_get_security(default_conn));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
sec = *argv[1] - '0';
|
|
|
|
|
2019-07-29 11:35:23 +02:00
|
|
|
if ((info.type == BT_CONN_TYPE_BR &&
|
2019-08-26 15:50:48 +02:00
|
|
|
(sec < BT_SECURITY_L0 || sec > BT_SECURITY_L3))) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid BR/EDR security level (%d)", sec);
|
2019-07-29 11:35:23 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((info.type == BT_CONN_TYPE_LE &&
|
2019-08-26 15:50:48 +02:00
|
|
|
(sec < BT_SECURITY_L1 || sec > BT_SECURITY_L4))) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid LE security level (%d)", sec);
|
2019-07-29 11:35:23 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
|
2019-08-21 16:23:31 +02:00
|
|
|
if (argc > 2) {
|
|
|
|
if (!strcmp(argv[2], "force-pair")) {
|
|
|
|
sec |= BT_SECURITY_FORCE_PAIR;
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-08-21 16:23:31 +02:00
|
|
|
return -ENOEXEC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-26 15:53:20 +02:00
|
|
|
err = bt_conn_set_security(default_conn, sec);
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Setting security failed (err %d)", err);
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_bondable(const struct shell *sh, size_t argc, char *argv[])
|
2018-09-18 09:44:57 +02:00
|
|
|
{
|
|
|
|
const char *bondable;
|
|
|
|
|
|
|
|
bondable = argv[1];
|
|
|
|
if (!strcmp(bondable, "on")) {
|
|
|
|
bt_set_bondable(true);
|
|
|
|
} else if (!strcmp(bondable, "off")) {
|
|
|
|
bt_set_bondable(false);
|
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-03-25 11:03:59 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
2018-09-18 09:44:57 +02:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2018-09-18 09:44:57 +02:00
|
|
|
}
|
|
|
|
|
2019-12-11 13:36:05 +01:00
|
|
|
static void bond_info(const struct bt_bond_info *info, void *user_data)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
int *bond_count = user_data;
|
|
|
|
|
|
|
|
bt_addr_le_to_str(&info->addr, addr, sizeof(addr));
|
|
|
|
shell_print(ctx_shell, "Remote Identity: %s", addr);
|
|
|
|
(*bond_count)++;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_bonds(const struct shell *sh, size_t argc, char *argv[])
|
2019-12-11 13:36:05 +01:00
|
|
|
{
|
|
|
|
int bond_count = 0;
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Bonded devices:");
|
2019-12-11 13:36:05 +01:00
|
|
|
bt_foreach_bond(selected_id, bond_info, &bond_count);
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Total %d", bond_count);
|
2019-12-11 13:36:05 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-17 16:40:39 -07:00
|
|
|
static const char *role_str(uint8_t role)
|
|
|
|
{
|
|
|
|
switch (role) {
|
2021-09-14 12:28:45 +02:00
|
|
|
case BT_CONN_ROLE_CENTRAL:
|
|
|
|
return "Central";
|
|
|
|
case BT_CONN_ROLE_PERIPHERAL:
|
|
|
|
return "Peripheral";
|
2021-03-17 16:40:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
|
2019-12-13 12:24:30 +01:00
|
|
|
static void connection_info(struct bt_conn *conn, void *user_data)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
int *conn_count = user_data;
|
2021-03-17 16:40:39 -07:00
|
|
|
struct bt_conn_info info;
|
|
|
|
|
|
|
|
if (bt_conn_get_info(conn, &info) < 0) {
|
|
|
|
shell_error(ctx_shell, "Unable to get info: conn %p", conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (info.type) {
|
|
|
|
#if defined(CONFIG_BT_BREDR)
|
|
|
|
case BT_CONN_TYPE_BR:
|
|
|
|
bt_addr_to_str(info.br.dst, addr, sizeof(addr));
|
|
|
|
shell_print(ctx_shell, "#%u [BR][%s] %s", info.id,
|
|
|
|
role_str(info.role), addr);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case BT_CONN_TYPE_LE:
|
|
|
|
bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
|
|
|
|
shell_print(ctx_shell, "#%u [LE][%s] %s: Interval %u latency %u"
|
|
|
|
" timeout %u", info.id, role_str(info.role), addr,
|
|
|
|
info.le.interval, info.le.latency, info.le.timeout);
|
|
|
|
break;
|
|
|
|
#if defined(CONFIG_BT_ISO)
|
|
|
|
case BT_CONN_TYPE_ISO:
|
|
|
|
bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
|
|
|
|
shell_print(ctx_shell, "#%u [ISO][%s] %s", info.id,
|
|
|
|
role_str(info.role), addr);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
}
|
2019-12-13 12:24:30 +01:00
|
|
|
|
|
|
|
(*conn_count)++;
|
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_connections(const struct shell *sh, size_t argc, char *argv[])
|
2019-12-13 12:24:30 +01:00
|
|
|
{
|
|
|
|
int conn_count = 0;
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Connected devices:");
|
2019-12-13 12:24:30 +01:00
|
|
|
bt_conn_foreach(BT_CONN_TYPE_ALL, connection_info, &conn_count);
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Total %d", conn_count);
|
2019-12-13 12:24:30 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
char passkey_str[7];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-09-27 12:49:10 +03:00
|
|
|
snprintk(passkey_str, 7, "%06u", passkey);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Passkey for %s: %s", addr, passkey_str);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
char passkey_str[7];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-09-27 12:49:10 +03:00
|
|
|
snprintk(passkey_str, 7, "%06u", passkey);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Confirm passkey for %s: %s", addr, passkey_str);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void auth_passkey_entry(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Enter passkey for %s", addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void auth_cancel(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
conn_addr_str(conn, addr, sizeof(addr));
|
|
|
|
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Pairing cancelled: %s", addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
/* clear connection reference for sec mode 3 pairing */
|
|
|
|
if (pairing_conn) {
|
|
|
|
bt_conn_unref(pairing_conn);
|
|
|
|
pairing_conn = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void auth_pairing_confirm(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Confirm pairing for %s", addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2020-02-04 09:12:20 +01:00
|
|
|
#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
|
2019-05-28 13:28:48 +02:00
|
|
|
static const char *oob_config_str(int oob_config)
|
|
|
|
{
|
|
|
|
switch (oob_config) {
|
|
|
|
case BT_CONN_OOB_LOCAL_ONLY:
|
|
|
|
return "Local";
|
|
|
|
case BT_CONN_OOB_REMOTE_ONLY:
|
|
|
|
return "Remote";
|
|
|
|
case BT_CONN_OOB_BOTH_PEERS:
|
|
|
|
return "Local and Remote";
|
|
|
|
case BT_CONN_OOB_NO_DATA:
|
|
|
|
default:
|
|
|
|
return "no";
|
|
|
|
}
|
|
|
|
}
|
2020-02-04 09:12:20 +01:00
|
|
|
#endif /* !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) */
|
2019-05-28 13:28:48 +02:00
|
|
|
|
|
|
|
static void auth_pairing_oob_data_request(struct bt_conn *conn,
|
2019-08-07 13:30:08 +02:00
|
|
|
struct bt_conn_oob_info *oob_info)
|
2019-05-28 13:28:48 +02:00
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
2019-08-07 13:30:08 +02:00
|
|
|
struct bt_conn_info info;
|
|
|
|
int err;
|
2019-05-28 13:28:48 +02:00
|
|
|
|
2019-08-07 13:30:08 +02:00
|
|
|
err = bt_conn_get_info(conn, &info);
|
|
|
|
if (err) {
|
2019-05-28 13:28:48 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-04 09:12:20 +01:00
|
|
|
#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
|
2019-08-07 13:30:08 +02:00
|
|
|
if (oob_info->type == BT_CONN_OOB_LE_SC) {
|
2019-05-28 13:28:48 +02:00
|
|
|
struct bt_le_oob_sc_data *oobd_local =
|
2019-08-07 13:30:08 +02:00
|
|
|
oob_info->lesc.oob_config != BT_CONN_OOB_REMOTE_ONLY
|
|
|
|
? &oob_local.le_sc_data
|
|
|
|
: NULL;
|
2019-05-28 13:28:48 +02:00
|
|
|
struct bt_le_oob_sc_data *oobd_remote =
|
2019-08-07 13:30:08 +02:00
|
|
|
oob_info->lesc.oob_config != BT_CONN_OOB_LOCAL_ONLY
|
|
|
|
? &oob_remote.le_sc_data
|
|
|
|
: NULL;
|
|
|
|
|
|
|
|
if (oobd_remote &&
|
2022-09-20 11:10:15 +02:00
|
|
|
!bt_addr_le_eq(info.le.remote, &oob_remote.addr)) {
|
2019-08-07 13:30:08 +02:00
|
|
|
bt_addr_le_to_str(info.le.remote, addr, sizeof(addr));
|
|
|
|
shell_print(ctx_shell,
|
|
|
|
"No OOB data available for remote %s",
|
|
|
|
addr);
|
|
|
|
bt_conn_auth_cancel(conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oobd_local &&
|
2022-09-20 11:10:15 +02:00
|
|
|
!bt_addr_le_eq(info.le.local, &oob_local.addr)) {
|
2019-08-07 13:30:08 +02:00
|
|
|
bt_addr_le_to_str(info.le.local, addr, sizeof(addr));
|
|
|
|
shell_print(ctx_shell,
|
|
|
|
"No OOB data available for local %s",
|
|
|
|
addr);
|
|
|
|
bt_conn_auth_cancel(conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_le_oob_set_sc_data(conn, oobd_local, oobd_remote);
|
2019-05-28 13:28:48 +02:00
|
|
|
|
2019-08-07 13:30:08 +02:00
|
|
|
bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
|
2019-05-28 13:28:48 +02:00
|
|
|
shell_print(ctx_shell, "Set %s OOB SC data for %s, ",
|
2019-08-07 13:30:08 +02:00
|
|
|
oob_config_str(oob_info->lesc.oob_config), addr);
|
2020-02-04 09:12:20 +01:00
|
|
|
return;
|
2019-05-28 13:28:48 +02:00
|
|
|
}
|
2020-02-04 09:12:20 +01:00
|
|
|
#endif /* CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
|
|
|
|
|
|
|
|
bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
|
|
|
|
shell_print(ctx_shell, "Legacy OOB TK requested from remote %s", addr);
|
2019-05-28 13:28:48 +02:00
|
|
|
}
|
|
|
|
|
2018-07-31 10:48:32 +03:00
|
|
|
static void auth_pairing_complete(struct bt_conn *conn, bool bonded)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "%s with %s", bonded ? "Bonded" : "Paired",
|
|
|
|
addr);
|
2018-07-31 10:48:32 +03:00
|
|
|
}
|
|
|
|
|
2021-02-09 10:28:50 +01:00
|
|
|
static void auth_pairing_failed(struct bt_conn *conn, enum bt_security_err err)
|
2018-07-31 10:48:32 +03:00
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2021-02-09 10:28:50 +01:00
|
|
|
shell_print(ctx_shell, "Pairing failed with %s reason: %s (%d)", addr,
|
|
|
|
security_err_str(err), err);
|
2018-07-31 10:48:32 +03:00
|
|
|
}
|
|
|
|
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
static void auth_pincode_entry(struct bt_conn *conn, bool highsec)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_STR_LEN];
|
|
|
|
struct bt_conn_info info;
|
|
|
|
|
|
|
|
if (bt_conn_get_info(conn, &info) < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.type != BT_CONN_TYPE_BR) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_addr_to_str(info.br.dst, addr, sizeof(addr));
|
|
|
|
|
|
|
|
if (highsec) {
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Enter 16 digits wide PIN code for %s",
|
|
|
|
addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-11-12 15:15:20 +02:00
|
|
|
shell_print(ctx_shell, "Enter PIN code for %s", addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Save connection info since in security mode 3 (link level enforced
|
|
|
|
* security) PIN request callback is called before connected callback
|
|
|
|
*/
|
|
|
|
if (!default_conn && !pairing_conn) {
|
|
|
|
pairing_conn = bt_conn_ref(conn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-01-31 17:40:52 +01:00
|
|
|
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
|
|
|
|
enum bt_security_err pairing_accept(
|
|
|
|
struct bt_conn *conn, const struct bt_conn_pairing_feat *const feat)
|
|
|
|
{
|
|
|
|
shell_print(ctx_shell, "Remote pairing features: "
|
|
|
|
"IO: 0x%02x, OOB: %d, AUTH: 0x%02x, Key: %d, "
|
|
|
|
"Init Kdist: 0x%02x, Resp Kdist: 0x%02x",
|
|
|
|
feat->io_capability, feat->oob_data_flag,
|
|
|
|
feat->auth_req, feat->max_enc_key_size,
|
|
|
|
feat->init_key_dist, feat->resp_key_dist);
|
|
|
|
|
|
|
|
return BT_SECURITY_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_SMP_APP_PAIRING_ACCEPT */
|
|
|
|
|
2020-07-15 12:33:01 +02:00
|
|
|
void bond_deleted(uint8_t id, const bt_addr_le_t *peer)
|
|
|
|
{
|
2022-07-29 14:46:48 +08:00
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
2020-07-15 12:33:01 +02:00
|
|
|
|
|
|
|
bt_addr_le_to_str(peer, addr, sizeof(addr));
|
|
|
|
shell_print(ctx_shell, "Bond deleted for %s, id %u", addr, id);
|
|
|
|
}
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
static struct bt_conn_auth_cb auth_cb_display = {
|
|
|
|
.passkey_display = auth_passkey_display,
|
|
|
|
.passkey_entry = NULL,
|
|
|
|
.passkey_confirm = NULL,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
2019-05-28 13:28:48 +02:00
|
|
|
.oob_data_request = NULL,
|
2017-05-22 11:49:31 +03:00
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
2020-01-31 17:40:52 +01:00
|
|
|
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
|
|
|
|
.pairing_accept = pairing_accept,
|
|
|
|
#endif
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct bt_conn_auth_cb auth_cb_display_yes_no = {
|
|
|
|
.passkey_display = auth_passkey_display,
|
|
|
|
.passkey_entry = NULL,
|
|
|
|
.passkey_confirm = auth_passkey_confirm,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
2019-05-28 13:28:48 +02:00
|
|
|
.oob_data_request = NULL,
|
2017-05-22 11:49:31 +03:00
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
2020-01-31 17:40:52 +01:00
|
|
|
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
|
|
|
|
.pairing_accept = pairing_accept,
|
|
|
|
#endif
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct bt_conn_auth_cb auth_cb_input = {
|
|
|
|
.passkey_display = NULL,
|
|
|
|
.passkey_entry = auth_passkey_entry,
|
|
|
|
.passkey_confirm = NULL,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
2019-05-28 13:28:48 +02:00
|
|
|
.oob_data_request = NULL,
|
2017-05-22 11:49:31 +03:00
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
2020-01-31 17:40:52 +01:00
|
|
|
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
|
|
|
|
.pairing_accept = pairing_accept,
|
|
|
|
#endif
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
|
|
|
|
2018-07-31 10:50:54 +03:00
|
|
|
static struct bt_conn_auth_cb auth_cb_confirm = {
|
|
|
|
#if defined(CONFIG_BT_BREDR)
|
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
2019-05-28 13:28:48 +02:00
|
|
|
.oob_data_request = NULL,
|
2018-07-31 10:50:54 +03:00
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
2020-01-31 17:40:52 +01:00
|
|
|
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
|
|
|
|
.pairing_accept = pairing_accept,
|
|
|
|
#endif
|
2018-07-31 10:50:54 +03:00
|
|
|
};
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
static struct bt_conn_auth_cb auth_cb_all = {
|
|
|
|
.passkey_display = auth_passkey_display,
|
|
|
|
.passkey_entry = auth_passkey_entry,
|
|
|
|
.passkey_confirm = auth_passkey_confirm,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
2019-05-28 13:28:48 +02:00
|
|
|
.oob_data_request = auth_pairing_oob_data_request,
|
2017-05-22 11:49:31 +03:00
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
2020-01-31 17:40:52 +01:00
|
|
|
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
|
|
|
|
.pairing_accept = pairing_accept,
|
|
|
|
#endif
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
|
|
|
|
2019-07-31 16:07:25 +02:00
|
|
|
static struct bt_conn_auth_cb auth_cb_oob = {
|
|
|
|
.passkey_display = NULL,
|
|
|
|
.passkey_entry = NULL,
|
|
|
|
.passkey_confirm = NULL,
|
|
|
|
#if defined(CONFIG_BT_BREDR)
|
|
|
|
.pincode_entry = NULL,
|
|
|
|
#endif
|
|
|
|
.oob_data_request = auth_pairing_oob_data_request,
|
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = NULL,
|
2020-01-31 17:40:52 +01:00
|
|
|
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
|
|
|
|
.pairing_accept = pairing_accept,
|
|
|
|
#endif
|
2019-07-31 16:07:25 +02:00
|
|
|
};
|
|
|
|
|
2021-02-09 09:03:45 +01:00
|
|
|
static struct bt_conn_auth_cb auth_cb_status = {
|
|
|
|
#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
|
|
|
|
.pairing_accept = pairing_accept,
|
|
|
|
#endif
|
|
|
|
};
|
2019-07-31 16:07:25 +02:00
|
|
|
|
2022-03-08 14:33:56 +01:00
|
|
|
static struct bt_conn_auth_info_cb auth_info_cb = {
|
|
|
|
.pairing_failed = auth_pairing_failed,
|
|
|
|
.pairing_complete = auth_pairing_complete,
|
|
|
|
.bond_deleted = bond_deleted,
|
|
|
|
};
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_auth(const struct shell *sh, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2019-08-05 12:51:47 +02:00
|
|
|
int err;
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
if (!strcmp(argv[1], "all")) {
|
2019-08-05 12:51:47 +02:00
|
|
|
err = bt_conn_auth_cb_register(&auth_cb_all);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(argv[1], "input")) {
|
2019-08-05 12:51:47 +02:00
|
|
|
err = bt_conn_auth_cb_register(&auth_cb_input);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(argv[1], "display")) {
|
2019-08-05 12:51:47 +02:00
|
|
|
err = bt_conn_auth_cb_register(&auth_cb_display);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(argv[1], "yesno")) {
|
2019-08-05 12:51:47 +02:00
|
|
|
err = bt_conn_auth_cb_register(&auth_cb_display_yes_no);
|
2018-07-31 10:50:54 +03:00
|
|
|
} else if (!strcmp(argv[1], "confirm")) {
|
2019-08-05 12:51:47 +02:00
|
|
|
err = bt_conn_auth_cb_register(&auth_cb_confirm);
|
2019-07-31 16:07:25 +02:00
|
|
|
} else if (!strcmp(argv[1], "oob")) {
|
|
|
|
err = bt_conn_auth_cb_register(&auth_cb_oob);
|
2021-02-09 09:03:45 +01:00
|
|
|
} else if (!strcmp(argv[1], "status")) {
|
|
|
|
err = bt_conn_auth_cb_register(&auth_cb_status);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(argv[1], "none")) {
|
2019-08-05 12:51:47 +02:00
|
|
|
err = bt_conn_auth_cb_register(NULL);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-03-25 11:03:59 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
2021-09-24 09:49:10 +02:00
|
|
|
if (err) {
|
|
|
|
shell_error(sh, "Failed to set auth handlers (%d)", err);
|
|
|
|
}
|
|
|
|
|
2019-08-05 12:51:47 +02:00
|
|
|
return err;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_auth_cancel(const struct shell *sh,
|
2018-09-24 10:59:23 +03:00
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
if (default_conn) {
|
|
|
|
conn = default_conn;
|
|
|
|
} else if (pairing_conn) {
|
|
|
|
conn = pairing_conn;
|
|
|
|
} else {
|
|
|
|
conn = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!conn) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Not connected");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_auth_cancel(conn);
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_auth_passkey_confirm(const struct shell *sh,
|
2018-09-24 10:59:23 +03:00
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
if (!default_conn) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Not connected");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_auth_passkey_confirm(default_conn);
|
2018-10-01 22:08:59 +02:00
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_auth_pairing_confirm(const struct shell *sh,
|
2018-09-24 10:59:23 +03:00
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
if (!default_conn) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Not connected");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_auth_pairing_confirm(default_conn);
|
2018-10-01 22:08:59 +02:00
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2021-09-14 12:28:45 +02:00
|
|
|
#if defined(CONFIG_BT_FILTER_ACCEPT_LIST)
|
2021-09-17 12:46:31 +02:00
|
|
|
static int cmd_fal_add(const struct shell *sh, size_t argc, char *argv[])
|
2019-07-22 13:21:49 +02:00
|
|
|
{
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)", err);
|
2019-07-22 13:21:49 +02:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-09-14 12:28:45 +02:00
|
|
|
err = bt_le_filter_accept_list_add(&addr);
|
2019-07-22 13:21:49 +02:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Add to fa list failed (err %d)", err);
|
2019-07-22 13:21:49 +02:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-17 12:46:31 +02:00
|
|
|
static int cmd_fal_rem(const struct shell *sh, size_t argc, char *argv[])
|
2019-07-22 13:21:49 +02:00
|
|
|
{
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Invalid peer address (err %d)", err);
|
2019-07-22 13:21:49 +02:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-09-14 12:28:45 +02:00
|
|
|
err = bt_le_filter_accept_list_remove(&addr);
|
2019-07-22 13:21:49 +02:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Remove from fa list failed (err %d)",
|
2019-07-22 13:21:49 +02:00
|
|
|
err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-17 12:46:31 +02:00
|
|
|
static int cmd_fal_clear(const struct shell *sh, size_t argc, char *argv[])
|
2019-07-22 13:21:49 +02:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
2021-09-14 12:28:45 +02:00
|
|
|
err = bt_le_filter_accept_list_clear();
|
2019-07-22 13:21:49 +02:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Clearing fa list failed (err %d)", err);
|
2019-07-22 13:21:49 +02:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-02-29 08:15:29 +01:00
|
|
|
#if defined(CONFIG_BT_CENTRAL)
|
2021-09-17 12:46:31 +02:00
|
|
|
static int cmd_fal_connect(const struct shell *sh, size_t argc, char *argv[])
|
2019-07-22 13:21:49 +02:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
const char *action = argv[1];
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t options = 0;
|
2020-02-02 23:51:14 +01:00
|
|
|
|
|
|
|
#if defined(CONFIG_BT_EXT_ADV)
|
|
|
|
for (size_t argn = 2; argn < argc; argn++) {
|
|
|
|
const char *arg = argv[argn];
|
|
|
|
|
|
|
|
if (!strcmp(arg, "coded")) {
|
2020-04-23 11:49:17 +02:00
|
|
|
options |= BT_CONN_LE_OPT_CODED;
|
2020-02-02 23:51:14 +01:00
|
|
|
} else if (!strcmp(arg, "no-1m")) {
|
2020-04-23 11:49:17 +02:00
|
|
|
options |= BT_CONN_LE_OPT_NO_1M;
|
2020-02-02 23:51:14 +01:00
|
|
|
} else {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2020-02-02 23:51:14 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* defined(CONFIG_BT_EXT_ADV) */
|
|
|
|
struct bt_conn_le_create_param *create_params =
|
|
|
|
BT_CONN_LE_CREATE_PARAM(options,
|
|
|
|
BT_GAP_SCAN_FAST_INTERVAL,
|
|
|
|
BT_GAP_SCAN_FAST_WINDOW);
|
2019-07-22 13:21:49 +02:00
|
|
|
|
|
|
|
if (!strcmp(action, "on")) {
|
2020-02-02 23:51:14 +01:00
|
|
|
err = bt_conn_le_create_auto(create_params,
|
2020-02-01 18:13:05 +01:00
|
|
|
BT_LE_CONN_PARAM_DEFAULT);
|
2019-07-22 13:21:49 +02:00
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Auto connect failed (err %d)", err);
|
2019-07-22 13:21:49 +02:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
} else if (!strcmp(action, "off")) {
|
|
|
|
err = bt_conn_create_auto_stop();
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Auto connect stop failed (err %d)",
|
2019-07-22 13:21:49 +02:00
|
|
|
err);
|
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2020-02-29 08:15:29 +01:00
|
|
|
#endif /* CONFIG_BT_CENTRAL */
|
2021-09-14 12:28:45 +02:00
|
|
|
#endif /* defined(CONFIG_BT_FILTER_ACCEPT_LIST) */
|
2019-07-22 13:21:49 +02:00
|
|
|
|
2018-07-30 20:30:26 +03:00
|
|
|
#if defined(CONFIG_BT_FIXED_PASSKEY)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_fixed_passkey(const struct shell *sh,
|
2018-09-24 10:59:23 +03:00
|
|
|
size_t argc, char *argv[])
|
2018-07-30 20:30:26 +03:00
|
|
|
{
|
|
|
|
unsigned int passkey;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
|
|
|
bt_passkey_set(BT_PASSKEY_INVALID);
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Fixed passkey cleared");
|
2018-10-01 22:08:59 +02:00
|
|
|
return 0;
|
2018-07-30 20:30:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
passkey = atoi(argv[1]);
|
|
|
|
if (passkey > 999999) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Passkey should be between 0-999999");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2018-07-30 20:30:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_passkey_set(passkey);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Setting fixed passkey failed (err %d)",
|
2018-11-12 15:15:20 +02:00
|
|
|
err);
|
2018-07-30 20:30:26 +03:00
|
|
|
}
|
2018-10-01 22:08:59 +02:00
|
|
|
|
|
|
|
return err;
|
2018-07-30 20:30:26 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_auth_passkey(const struct shell *sh,
|
2018-09-24 10:59:23 +03:00
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
unsigned int passkey;
|
2020-02-04 09:12:20 +01:00
|
|
|
int err;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
if (!default_conn) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Not connected");
|
2018-10-01 22:08:59 +02:00
|
|
|
return -ENOEXEC;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
passkey = atoi(argv[1]);
|
|
|
|
if (passkey > 999999) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_print(sh, "Passkey should be between 0-999999");
|
2018-10-18 14:52:46 +02:00
|
|
|
return -EINVAL;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2020-02-04 09:12:20 +01:00
|
|
|
err = bt_conn_auth_passkey_entry(default_conn, passkey);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to set passkey (%d)", err);
|
2020-02-04 09:12:20 +01:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_auth_oob_tk(const struct shell *sh, size_t argc, char *argv[])
|
2020-02-04 09:12:20 +01:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t tk[16];
|
2020-02-04 09:12:20 +01:00
|
|
|
size_t len;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
len = hex2bin(argv[1], strlen(argv[1]), tk, sizeof(tk));
|
|
|
|
if (len != sizeof(tk)) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "TK should be 16 bytes");
|
2020-02-04 09:12:20 +01:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_oob_set_legacy_tk(default_conn, tk);
|
|
|
|
if (err) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "Failed to set TK (%d)", err);
|
2020-02-04 09:12:20 +01:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2018-10-01 22:08:59 +02:00
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2020-02-04 09:12:20 +01:00
|
|
|
#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */
|
2017-08-09 09:21:11 +03:00
|
|
|
#endif /* CONFIG_BT_SMP) || CONFIG_BT_BREDR */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-09-27 12:49:10 +03:00
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
#define HELP_NONE "[none]"
|
2022-10-13 14:18:31 +02:00
|
|
|
#define HELP_ONOFF "<on, off>"
|
2017-05-22 11:49:31 +03:00
|
|
|
#define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
|
2017-05-22 10:17:22 +03:00
|
|
|
|
2020-02-02 23:51:14 +01:00
|
|
|
#if defined(CONFIG_BT_EXT_ADV)
|
|
|
|
#define EXT_ADV_SCAN_OPT " [coded] [no-1m]"
|
2020-02-02 23:45:32 +01:00
|
|
|
#define EXT_ADV_PARAM "<type: conn-scan conn-nscan, nconn-scan nconn-nscan> " \
|
|
|
|
"[ext-adv] [no-2m] [coded] " \
|
2021-09-17 12:46:31 +02:00
|
|
|
"[filter-accept-list: fal, fal-scan, fal-conn] [identity] [name] " \
|
2021-08-12 13:27:03 +02:00
|
|
|
"[name-ad] [directed "HELP_ADDR_LE"] [mode: low]" \
|
2020-09-29 13:51:31 +02:00
|
|
|
"[disable-37] [disable-38] [disable-39]"
|
2020-02-02 23:51:14 +01:00
|
|
|
#else
|
|
|
|
#define EXT_ADV_SCAN_OPT ""
|
|
|
|
#endif /* defined(CONFIG_BT_EXT_ADV) */
|
|
|
|
|
2021-12-27 15:15:41 +01:00
|
|
|
#if defined(CONFIG_BT_OBSERVER)
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(bt_scan_filter_set_cmds,
|
|
|
|
SHELL_CMD_ARG(name, NULL, "<name>", cmd_scan_filter_set_name, 2, 0),
|
|
|
|
SHELL_CMD_ARG(addr, NULL, "<addr>", cmd_scan_filter_set_addr, 2, 0),
|
2022-05-23 15:55:40 +02:00
|
|
|
SHELL_CMD_ARG(rssi, NULL, "<rssi>", cmd_scan_filter_set_rssi, 1, 1),
|
2022-12-15 20:02:15 +01:00
|
|
|
SHELL_CMD_ARG(pa_interval, NULL, "<pa_interval>",
|
|
|
|
cmd_scan_filter_set_pa_interval, 2, 0),
|
2021-12-27 15:15:41 +01:00
|
|
|
SHELL_SUBCMD_SET_END
|
|
|
|
);
|
|
|
|
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(bt_scan_filter_clear_cmds,
|
|
|
|
SHELL_CMD_ARG(all, NULL, "", cmd_scan_filter_clear_all, 1, 0),
|
|
|
|
SHELL_CMD_ARG(name, NULL, "", cmd_scan_filter_clear_name, 1, 0),
|
|
|
|
SHELL_CMD_ARG(addr, NULL, "", cmd_scan_filter_clear_addr, 1, 0),
|
|
|
|
SHELL_SUBCMD_SET_END
|
|
|
|
);
|
|
|
|
#endif /* CONFIG_BT_OBSERVER */
|
|
|
|
|
2019-02-13 14:53:29 +01:00
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds,
|
2021-01-19 15:41:18 +01:00
|
|
|
SHELL_CMD_ARG(init, NULL, "[no-settings-load], [sync]",
|
|
|
|
cmd_init, 1, 2),
|
2022-10-24 16:13:40 +01:00
|
|
|
SHELL_CMD_ARG(disable, NULL, HELP_NONE, cmd_disable, 1, 0),
|
2021-01-19 15:41:18 +01:00
|
|
|
#if defined(CONFIG_SETTINGS)
|
|
|
|
SHELL_CMD_ARG(settings-load, NULL, HELP_NONE, cmd_settings_load, 1, 0),
|
|
|
|
#endif
|
2018-07-09 13:33:07 +03:00
|
|
|
#if defined(CONFIG_BT_HCI)
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(hci-cmd, NULL, "<ogf> <ocf> [data]", cmd_hci_cmd, 3, 1),
|
2018-07-09 13:33:07 +03:00
|
|
|
#endif
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(id-create, NULL, "[addr]", cmd_id_create, 1, 1),
|
|
|
|
SHELL_CMD_ARG(id-reset, NULL, "<id> [addr]", cmd_id_reset, 2, 1),
|
|
|
|
SHELL_CMD_ARG(id-delete, NULL, "<id>", cmd_id_delete, 2, 0),
|
|
|
|
SHELL_CMD_ARG(id-show, NULL, HELP_NONE, cmd_id_show, 1, 0),
|
|
|
|
SHELL_CMD_ARG(id-select, NULL, "<id>", cmd_id_select, 2, 0),
|
|
|
|
SHELL_CMD_ARG(name, NULL, "[name]", cmd_name, 1, 1),
|
2021-11-24 12:56:15 +01:00
|
|
|
#if defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC)
|
|
|
|
SHELL_CMD_ARG(appearance, NULL, "[new appearance value]", cmd_appearance, 1, 1),
|
|
|
|
#else
|
|
|
|
SHELL_CMD_ARG(appearance, NULL, "", cmd_appearance, 1, 0),
|
|
|
|
#endif /* CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC */
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_OBSERVER)
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(scan, NULL,
|
2021-09-17 12:46:31 +02:00
|
|
|
"<value: on, passive, off> [filter: dups, nodups] [fal]"
|
2020-02-02 23:51:14 +01:00
|
|
|
EXT_ADV_SCAN_OPT,
|
|
|
|
cmd_scan, 2, 4),
|
2021-12-27 15:15:41 +01:00
|
|
|
SHELL_CMD_ARG(scan-filter-set, &bt_scan_filter_set_cmds,
|
|
|
|
"Scan filter set commands",
|
|
|
|
NULL, 1, 0),
|
|
|
|
SHELL_CMD_ARG(scan-filter-clear, &bt_scan_filter_clear_cmds,
|
|
|
|
"Scan filter clear commands",
|
|
|
|
NULL, 1, 0),
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_OBSERVER */
|
|
|
|
#if defined(CONFIG_BT_BROADCASTER)
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(advertise, NULL,
|
2019-07-22 13:21:49 +02:00
|
|
|
"<type: off, on, scan, nconn> [mode: discov, non_discov] "
|
2021-09-17 12:46:31 +02:00
|
|
|
"[filter-accept-list: fal, fal-scan, fal-conn] [identity] [no-name] "
|
2022-09-27 15:47:48 +02:00
|
|
|
"[one-time] [name-ad] [appearance] "
|
2021-08-12 13:27:03 +02:00
|
|
|
"[disable-37] [disable-38] [disable-39]",
|
2020-09-29 13:51:31 +02:00
|
|
|
cmd_advertise, 2, 8),
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_PERIPHERAL)
|
2020-06-25 14:32:35 +02:00
|
|
|
SHELL_CMD_ARG(directed-adv, NULL, HELP_ADDR_LE " [mode: low] "
|
|
|
|
"[identity] [dir-rpa]",
|
2020-09-29 13:51:31 +02:00
|
|
|
cmd_directed_adv, 3, 6),
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_PERIPHERAL */
|
2020-02-02 23:45:32 +01:00
|
|
|
#if defined(CONFIG_BT_EXT_ADV)
|
2020-09-29 13:51:31 +02:00
|
|
|
SHELL_CMD_ARG(adv-create, NULL, EXT_ADV_PARAM, cmd_adv_create, 2, 11),
|
|
|
|
SHELL_CMD_ARG(adv-param, NULL, EXT_ADV_PARAM, cmd_adv_param, 2, 11),
|
2020-04-09 20:15:26 +02:00
|
|
|
SHELL_CMD_ARG(adv-data, NULL, "<data> [scan-response <data>] "
|
2022-09-27 15:47:48 +02:00
|
|
|
"<type: discov, hex> [appearance] ",
|
|
|
|
cmd_adv_data, 1, 16),
|
2020-06-18 14:13:41 +02:00
|
|
|
SHELL_CMD_ARG(adv-start, NULL,
|
|
|
|
"[timeout <timeout>] [num-events <num events>]",
|
|
|
|
cmd_adv_start, 1, 4),
|
2020-02-02 23:45:32 +01:00
|
|
|
SHELL_CMD_ARG(adv-stop, NULL, "", cmd_adv_stop, 1, 0),
|
|
|
|
SHELL_CMD_ARG(adv-delete, NULL, "", cmd_adv_delete, 1, 0),
|
|
|
|
SHELL_CMD_ARG(adv-select, NULL, "[adv]", cmd_adv_select, 1, 1),
|
2020-03-27 11:31:43 +01:00
|
|
|
SHELL_CMD_ARG(adv-info, NULL, HELP_NONE, cmd_adv_info, 1, 0),
|
2020-08-19 12:54:46 +05:30
|
|
|
#if defined(CONFIG_BT_PERIPHERAL)
|
|
|
|
SHELL_CMD_ARG(adv-oob, NULL, HELP_NONE, cmd_adv_oob, 1, 0),
|
|
|
|
#endif /* CONFIG_BT_PERIPHERAL */
|
2022-10-13 11:27:56 +02:00
|
|
|
#if defined(CONFIG_BT_PRIVACY)
|
|
|
|
SHELL_CMD_ARG(adv-rpa-expire, NULL, HELP_ONOFF, cmd_adv_rpa_expire, 2, 0),
|
|
|
|
#endif
|
2020-05-01 16:50:54 +02:00
|
|
|
#if defined(CONFIG_BT_PER_ADV)
|
2022-10-13 14:18:31 +02:00
|
|
|
SHELL_CMD_ARG(per-adv, NULL, HELP_ONOFF, cmd_per_adv, 2, 0),
|
2020-05-01 16:50:54 +02:00
|
|
|
SHELL_CMD_ARG(per-adv-param, NULL,
|
|
|
|
"[<interval-min> [<interval-max> [tx_power]]]",
|
|
|
|
cmd_per_adv_param, 1, 3),
|
|
|
|
SHELL_CMD_ARG(per-adv-data, NULL, "<data>", cmd_per_adv_data, 2, 0),
|
2020-10-01 09:28:58 +05:30
|
|
|
#endif /* CONFIG_BT_PER_ADV */
|
|
|
|
#endif /* CONFIG_BT_EXT_ADV */
|
|
|
|
#endif /* CONFIG_BT_BROADCASTER */
|
2020-05-14 17:53:53 +02:00
|
|
|
#if defined(CONFIG_BT_PER_ADV_SYNC)
|
|
|
|
SHELL_CMD_ARG(per-adv-sync-create, NULL,
|
|
|
|
HELP_ADDR_LE " <sid> [skip <count>] [timeout <ms>] [aoa] "
|
|
|
|
"[aod_1us] [aod_2us] [cte_only]",
|
2020-09-21 20:54:11 +02:00
|
|
|
cmd_per_adv_sync_create, 4, 6),
|
2020-05-14 17:53:53 +02:00
|
|
|
SHELL_CMD_ARG(per-adv-sync-delete, NULL, "[<index>]",
|
2020-09-21 20:54:11 +02:00
|
|
|
cmd_per_adv_sync_delete, 1, 1),
|
2020-11-20 11:20:50 +05:30
|
|
|
#endif /* defined(CONFIG_BT_PER_ADV_SYNC) */
|
|
|
|
#if defined(CONFIG_BT_CONN)
|
2022-10-12 14:27:09 +01:00
|
|
|
#if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER)
|
2020-09-23 22:39:29 +02:00
|
|
|
SHELL_CMD_ARG(past-subscribe, NULL, "[conn] [skip <count>] "
|
|
|
|
"[timeout <ms>] [aoa] [aod_1us] [aod_2us] [cte_only]",
|
|
|
|
cmd_past_subscribe, 1, 7),
|
|
|
|
SHELL_CMD_ARG(past-unsubscribe, NULL, "[conn]",
|
|
|
|
cmd_past_unsubscribe, 1, 1),
|
2022-10-12 14:27:09 +01:00
|
|
|
#endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER */
|
|
|
|
#if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER)
|
2021-03-24 10:58:12 +01:00
|
|
|
SHELL_CMD_ARG(per-adv-sync-transfer, NULL, "[<index>]",
|
|
|
|
cmd_per_adv_sync_transfer, 1, 1),
|
2022-10-12 14:27:09 +01:00
|
|
|
#endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER */
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_CENTRAL)
|
2020-04-23 11:29:58 +02:00
|
|
|
SHELL_CMD_ARG(connect, NULL, HELP_ADDR_LE EXT_ADV_SCAN_OPT,
|
2022-05-24 16:15:59 +02:00
|
|
|
cmd_connect_le, 1, 3),
|
2021-09-14 12:28:45 +02:00
|
|
|
#if !defined(CONFIG_BT_FILTER_ACCEPT_LIST)
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(auto-conn, NULL, HELP_ADDR_LE, cmd_auto_conn, 3, 0),
|
2021-09-14 12:28:45 +02:00
|
|
|
#endif /* !defined(CONFIG_BT_FILTER_ACCEPT_LIST) */
|
2022-09-06 16:18:57 +02:00
|
|
|
SHELL_CMD_ARG(connect-name, NULL, "<name filter>",
|
|
|
|
cmd_connect_le_name, 2, 0),
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_CENTRAL */
|
2019-06-04 17:06:43 +02:00
|
|
|
SHELL_CMD_ARG(disconnect, NULL, HELP_NONE, cmd_disconnect, 1, 2),
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(select, NULL, HELP_ADDR_LE, cmd_select, 3, 0),
|
2019-08-05 09:31:20 +02:00
|
|
|
SHELL_CMD_ARG(info, NULL, HELP_ADDR_LE, cmd_info, 1, 2),
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(conn-update, NULL, "<min> <max> <latency> <timeout>",
|
|
|
|
cmd_conn_update, 5, 0),
|
2020-04-22 21:19:41 +02:00
|
|
|
#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
|
|
|
|
SHELL_CMD_ARG(data-len-update, NULL, "<tx_max_len> [tx_max_time]",
|
|
|
|
cmd_conn_data_len_update, 2, 1),
|
|
|
|
#endif
|
2020-04-22 20:44:35 +02:00
|
|
|
#if defined(CONFIG_BT_USER_PHY_UPDATE)
|
2020-05-12 12:09:32 +02:00
|
|
|
SHELL_CMD_ARG(phy-update, NULL, "<tx_phy> [rx_phy] [s2] [s8]",
|
|
|
|
cmd_conn_phy_update, 2, 3),
|
2020-04-22 20:44:35 +02:00
|
|
|
#endif
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_CENTRAL)
|
2019-05-29 10:50:08 +02:00
|
|
|
SHELL_CMD_ARG(channel-map, NULL, "<channel-map: XXXXXXXXXX> (36-0)",
|
2018-11-12 16:15:35 +02:00
|
|
|
cmd_chan_map, 2, 1),
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_CENTRAL */
|
|
|
|
SHELL_CMD_ARG(oob, NULL, NULL, cmd_oob, 1, 0),
|
2019-07-10 12:12:16 +02:00
|
|
|
SHELL_CMD_ARG(clear, NULL, "<remote: addr, all>", cmd_clear, 2, 1),
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2019-07-29 11:35:23 +02:00
|
|
|
SHELL_CMD_ARG(security, NULL, "<security level BR/EDR: 0 - 3, "
|
2019-08-21 16:23:31 +02:00
|
|
|
"LE: 1 - 4> [force-pair]",
|
2022-06-03 15:40:14 +02:00
|
|
|
cmd_security, 1, 2),
|
2022-10-13 14:18:31 +02:00
|
|
|
SHELL_CMD_ARG(bondable, NULL, HELP_ONOFF, cmd_bondable,
|
2018-11-12 16:15:35 +02:00
|
|
|
2, 0),
|
2019-12-11 13:36:05 +01:00
|
|
|
SHELL_CMD_ARG(bonds, NULL, HELP_NONE, cmd_bonds, 1, 0),
|
2019-12-13 12:24:30 +01:00
|
|
|
SHELL_CMD_ARG(connections, NULL, HELP_NONE, cmd_connections, 1, 0),
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(auth, NULL,
|
2019-07-31 16:07:25 +02:00
|
|
|
"<method: all, input, display, yesno, confirm, "
|
2021-02-09 09:03:45 +01:00
|
|
|
"oob, status, none>",
|
2018-11-12 16:15:35 +02:00
|
|
|
cmd_auth, 2, 0),
|
|
|
|
SHELL_CMD_ARG(auth-cancel, NULL, HELP_NONE, cmd_auth_cancel, 1, 0),
|
|
|
|
SHELL_CMD_ARG(auth-passkey, NULL, "<passkey>", cmd_auth_passkey, 2, 0),
|
|
|
|
SHELL_CMD_ARG(auth-passkey-confirm, NULL, HELP_NONE,
|
|
|
|
cmd_auth_passkey_confirm, 1, 0),
|
|
|
|
SHELL_CMD_ARG(auth-pairing-confirm, NULL, HELP_NONE,
|
|
|
|
cmd_auth_pairing_confirm, 1, 0),
|
2020-02-04 09:12:20 +01:00
|
|
|
#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
|
|
|
|
SHELL_CMD_ARG(auth-oob-tk, NULL, "<tk>", cmd_auth_oob_tk, 2, 0),
|
|
|
|
#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */
|
2019-05-28 13:28:48 +02:00
|
|
|
SHELL_CMD_ARG(oob-remote, NULL,
|
|
|
|
HELP_ADDR_LE" <oob rand> <oob confirm>",
|
2019-07-31 16:07:25 +02:00
|
|
|
cmd_oob_remote, 3, 2),
|
|
|
|
SHELL_CMD_ARG(oob-clear, NULL, HELP_NONE, cmd_oob_clear, 1, 0),
|
2021-09-14 12:28:45 +02:00
|
|
|
#if defined(CONFIG_BT_FILTER_ACCEPT_LIST)
|
2021-09-17 12:46:31 +02:00
|
|
|
SHELL_CMD_ARG(fal-add, NULL, HELP_ADDR_LE, cmd_fal_add, 3, 0),
|
|
|
|
SHELL_CMD_ARG(fal-rem, NULL, HELP_ADDR_LE, cmd_fal_rem, 3, 0),
|
|
|
|
SHELL_CMD_ARG(fal-clear, NULL, HELP_NONE, cmd_fal_clear, 1, 0),
|
2020-02-02 23:51:14 +01:00
|
|
|
|
2020-02-29 08:15:29 +01:00
|
|
|
#if defined(CONFIG_BT_CENTRAL)
|
2022-10-13 14:18:31 +02:00
|
|
|
SHELL_CMD_ARG(fal-connect, NULL, HELP_ONOFF EXT_ADV_SCAN_OPT,
|
2021-09-17 12:46:31 +02:00
|
|
|
cmd_fal_connect, 2, 3),
|
2020-02-29 08:15:29 +01:00
|
|
|
#endif /* CONFIG_BT_CENTRAL */
|
2021-09-14 12:28:45 +02:00
|
|
|
#endif /* defined(CONFIG_BT_FILTER_ACCEPT_LIST) */
|
2018-07-30 20:30:26 +03:00
|
|
|
#if defined(CONFIG_BT_FIXED_PASSKEY)
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(fixed-passkey, NULL, "[passkey]", cmd_fixed_passkey,
|
|
|
|
1, 1),
|
2018-07-30 20:30:26 +03:00
|
|
|
#endif
|
2017-08-09 09:21:11 +03:00
|
|
|
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR) */
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2019-01-09 23:14:36 +05:30
|
|
|
#if defined(CONFIG_BT_HCI_MESH_EXT)
|
2022-10-13 14:18:31 +02:00
|
|
|
SHELL_CMD(mesh_adv, NULL, HELP_ONOFF, cmd_mesh_adv),
|
2019-01-09 23:14:36 +05:30
|
|
|
#endif /* CONFIG_BT_HCI_MESH_EXT */
|
2020-10-22 16:19:09 +02:00
|
|
|
|
2020-10-21 17:18:39 +02:00
|
|
|
#if defined(CONFIG_BT_LL_SW_SPLIT)
|
2022-11-02 10:58:17 +05:30
|
|
|
SHELL_CMD(ll-addr, NULL, "<random|public>", cmd_ll_addr_read),
|
2020-10-22 16:19:09 +02:00
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
2019-01-07 16:51:22 +05:30
|
|
|
#if defined(CONFIG_BT_BROADCASTER)
|
2020-01-27 17:13:30 +05:30
|
|
|
SHELL_CMD_ARG(advx, NULL,
|
|
|
|
"<on hdcd ldcd off> [coded] [anon] [txp] [ad]",
|
|
|
|
cmd_advx, 2, 4),
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_BROADCASTER */
|
|
|
|
#if defined(CONFIG_BT_OBSERVER)
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(scanx, NULL, "<on passive off> [coded]", cmd_scanx,
|
|
|
|
2, 1),
|
2019-01-07 16:51:22 +05:30
|
|
|
#endif /* CONFIG_BT_OBSERVER */
|
2017-09-27 13:00:38 +02:00
|
|
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
|
|
|
#if defined(CONFIG_BT_CTLR_DTM)
|
2018-11-12 16:15:35 +02:00
|
|
|
SHELL_CMD_ARG(test_tx, NULL, "<chan> <len> <type> <phy>", cmd_test_tx,
|
|
|
|
5, 0),
|
|
|
|
SHELL_CMD_ARG(test_rx, NULL, "<chan> <phy> <mod_idx>", cmd_test_rx,
|
|
|
|
4, 0),
|
|
|
|
SHELL_CMD_ARG(test_end, NULL, HELP_NONE, cmd_test_end, 1, 0),
|
2020-07-16 14:48:38 +05:30
|
|
|
#endif /* CONFIG_BT_CTLR_DTM */
|
2020-10-21 17:18:39 +02:00
|
|
|
#endif /* CONFIG_BT_LL_SW_SPLIT */
|
2020-10-22 16:19:09 +02:00
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_SUBCMD_SET_END
|
2019-02-13 14:53:29 +01:00
|
|
|
);
|
2017-05-22 10:17:22 +03:00
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
static int cmd_bt(const struct shell *sh, size_t argc, char **argv)
|
2018-09-24 10:59:23 +03:00
|
|
|
{
|
|
|
|
if (argc == 1) {
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_help(sh);
|
2019-03-25 11:03:59 +01:00
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
2018-09-24 10:59:23 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 10:58:45 +02:00
|
|
|
shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]);
|
2018-10-02 16:18:38 +03:00
|
|
|
|
2018-10-18 14:52:46 +02:00
|
|
|
return -EINVAL;
|
2018-09-24 10:59:23 +03:00
|
|
|
}
|
|
|
|
|
2019-03-25 11:05:59 +01:00
|
|
|
SHELL_CMD_REGISTER(bt, &bt_cmds, "Bluetooth shell commands", cmd_bt);
|