Bluetooth: shell: Add shell commands for advertising sets

Add shell commands to create advertising sets, add advertising data,
start advertising, stop advertising, and delete advertising set.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2020-02-02 23:45:32 +01:00 committed by Johan Hedberg
commit 7c92ffdcb3

View file

@ -56,6 +56,11 @@ static struct bt_le_oob oob_remote;
#define KEY_STR_LEN 33
#if defined(CONFIG_BT_EXT_ADV)
static u8_t selected_adv;
struct bt_le_ext_adv *adv_sets[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
#endif
#if defined(CONFIG_BT_OBSERVER)
static bool data_cb(struct bt_data *data, void *user_data)
{
@ -760,6 +765,261 @@ static int cmd_directed_adv(const struct shell *shell,
return 0;
}
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_EXT_ADV)
static bool adv_param_parse(size_t argc, char *argv[],
struct bt_le_adv_param *param)
{
param->options = 0;
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;
} else if (!strcmp(arg, "wl")) {
param->options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
param->options |= BT_LE_ADV_OPT_FILTER_CONN;
} else if (!strcmp(arg, "wl-scan")) {
param->options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
} else if (!strcmp(arg, "wl-conn")) {
param->options |= BT_LE_ADV_OPT_FILTER_CONN;
} else if (!strcmp(arg, "identity")) {
param->options |= BT_LE_ADV_OPT_USE_IDENTITY;
} else {
return false;
}
}
param->id = selected_id;
param->sid = 0;
param->interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
param->interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
return true;
}
static int cmd_adv_create(const struct shell *shell, size_t argc, char *argv[])
{
struct bt_le_adv_param param;
struct bt_le_ext_adv *adv;
u8_t adv_index;
int err;
if (!adv_param_parse(argc, argv, &param)) {
shell_help(shell);
return -ENOEXEC;
}
err = bt_le_ext_adv_create(&param, NULL, &adv);
if (err) {
shell_error(shell, "Failed to create advertiser set (%d)", err);
return -ENOEXEC;
}
adv_index = bt_le_ext_adv_get_index(adv);
adv_sets[adv_index] = adv;
shell_print(shell, "Created adv id: %d, adv: %p", adv_index, adv);
return 0;
}
static int cmd_adv_param(const struct shell *shell, size_t argc, char *argv[])
{
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
struct bt_le_adv_param param;
int err;
if (!adv_param_parse(argc, argv, &param)) {
shell_help(shell);
return -ENOEXEC;
}
err = bt_le_ext_adv_update_param(adv, &param);
if (err) {
shell_error(shell, "Failed to update advertiser set (%d)", err);
return -ENOEXEC;
}
return 0;
}
static int cmd_adv_data(const struct shell *shell, size_t argc, char *argv[])
{
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
struct bt_data ad[4];
size_t ad_len = 0;
u8_t discov_data = (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR);
int err;
if (!adv) {
return -EINVAL;
}
for (size_t argn = 1; argn < argc; argn++) {
const char *arg = argv[argn];
if (!strcmp(arg, "discov")) {
ad[ad_len].type = BT_DATA_FLAGS;
ad[ad_len].data_len = sizeof(discov_data);
ad[ad_len].data = &discov_data;
ad_len++;
} else if (!strcmp(arg, "name")) {
const char *name = bt_get_name();
ad[ad_len].type = BT_DATA_NAME_COMPLETE;
ad[ad_len].data_len = strlen(name);
ad[ad_len].data = name;
ad_len++;
} else {
shell_help(shell);
return -ENOEXEC;
}
}
err = bt_le_ext_adv_set_data(adv, ad, ad_len, NULL, 0);
if (err) {
shell_print(shell, "Failed to set advertising set data (%d)",
err);
return -ENOEXEC;
}
return 0;
}
static int cmd_adv_start(const struct shell *shell, size_t argc, char *argv[])
{
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
struct bt_le_ext_adv_start_param param;
u8_t num_events = 0;
s32_t timeout = 0;
int err;
if (!adv) {
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);
}
if (!strcmp(arg, "num_events")) {
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, &param);
if (err) {
shell_print(shell, "Failed to start advertising set (%d)", err);
return -ENOEXEC;
}
shell_print(shell, "Advertiser[%d] %p set started", selected_adv, adv);
return 0;
fail_show_help:
shell_help(shell);
return -ENOEXEC;
}
static int cmd_adv_stop(const struct shell *shell, size_t argc, char *argv[])
{
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
int err;
if (!adv) {
return -EINVAL;
}
err = bt_le_ext_adv_stop(adv);
if (err) {
shell_print(shell, "Failed to stop advertising set (%d)", err);
return -ENOEXEC;
}
shell_print(shell, "Advertiser set stopped");
return 0;
}
static int cmd_adv_delete(const struct shell *shell, size_t argc, char *argv[])
{
struct bt_le_ext_adv *adv = adv_sets[selected_adv];
int err;
if (!adv) {
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;
}
static int cmd_adv_select(const struct shell *shell, size_t argc, char *argv[])
{
if (argc == 2) {
u8_t id = strtol(argv[1], NULL, 10);
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]) {
shell_print(shell, "Advertiser[%d] %p", i, adv_sets[i]);
}
}
return -ENOEXEC;
}
#endif /* CONFIG_BT_EXT_ADV */
#endif /* CONFIG_BT_BROADCASTER */
#if defined(CONFIG_BT_CONN)
@ -1838,6 +2098,9 @@ static int cmd_auth_oob_tk(const struct shell *shell, size_t argc, char *argv[])
#if defined(CONFIG_BT_EXT_ADV)
#define EXT_ADV_SCAN_OPT " [coded] [no-1m]"
#define EXT_ADV_CONN_OPT " [coded] [2m] [no-1m]"
#define EXT_ADV_PARAM "<type: conn-scan conn-nscan, nconn-scan nconn-nscan> " \
"[ext-adv] [no-2m] [coded] " \
"[whitelist: wl, wl-scan, wl-conn] [identity]"
#else
#define EXT_ADV_SCAN_OPT ""
#define EXT_ADV_CONN_OPT ""
@ -1869,6 +2132,17 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds,
SHELL_CMD_ARG(directed-adv, NULL, HELP_ADDR_LE " [mode: low]",
cmd_directed_adv, 3, 1),
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_EXT_ADV)
SHELL_CMD_ARG(adv-create, NULL, EXT_ADV_PARAM, cmd_adv_create, 2, 5),
SHELL_CMD_ARG(adv-param, NULL, EXT_ADV_PARAM, cmd_adv_param, 2, 5),
SHELL_CMD_ARG(adv-data, NULL, "<type: discov, name>", cmd_adv_data,
1, 2),
SHELL_CMD_ARG(adv-start, NULL, "[timeout] [num_events]", cmd_adv_start,
1, 2),
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),
#endif
#endif /* CONFIG_BT_BROADCASTER */
#if defined(CONFIG_BT_CONN)
#if defined(CONFIG_BT_CENTRAL)