Bluetooth: Shell: Extend the shell output of scan data

Add verbose output of scan data to output all received data types as
hex values. This is turned off by default and can be toggled using
the bt scan-verbose-output <on|off> command.

Signed-off-by: Martin Rieva <mrrv@demant.com>
This commit is contained in:
Martin Rieva 2023-03-31 14:11:40 +02:00 committed by Carles Cufí
parent 9cdc5d38b2
commit ddf518e706

View file

@ -147,6 +147,8 @@ static struct bt_scan_filter {
bool pa_interval_set;
} scan_filter;
static const char scan_response_label[] = "[DEVICE]: ";
static bool scan_verbose_output;
/**
* @brief Compares two strings without case sensitivy
@ -194,11 +196,94 @@ static bool data_cb(struct bt_data *data, void *user_data)
}
}
static void print_data_set(uint8_t type, uint8_t set_value_len,
const uint8_t *scan_data, uint8_t scan_data_len)
{
uint8_t min_value_len = MIN(set_value_len, scan_data_len);
shell_fprintf(ctx_shell, SHELL_INFO, "%*sType 0x%02x: ",
strlen(scan_response_label), "",
type);
for (uint8_t i = 0U; i < (scan_data_len / min_value_len); i++) {
if (i > 0L) {
shell_fprintf(ctx_shell, SHELL_INFO, ", ");
}
shell_fprintf(ctx_shell, SHELL_INFO, "0x");
for (uint8_t j = 0U; j < min_value_len; j++) {
shell_fprintf(ctx_shell, SHELL_INFO, "%02x",
scan_data[i * min_value_len + j]);
}
}
shell_fprintf(ctx_shell, SHELL_INFO, "\n");
}
static bool data_verbose_cb(struct bt_data *data, void *user_data)
{
switch (data->type) {
case BT_DATA_UUID16_SOME:
case BT_DATA_UUID16_ALL:
case BT_DATA_SOLICIT16:
case BT_DATA_SVC_DATA16:
print_data_set(data->type, 2, data->data, data->data_len);
break;
case BT_DATA_UUID32_SOME:
case BT_DATA_UUID32_ALL:
case BT_DATA_SVC_DATA32:
print_data_set(data->type, 4, data->data, data->data_len);
break;
case BT_DATA_UUID128_SOME:
case BT_DATA_UUID128_ALL:
case BT_DATA_SOLICIT128:
case BT_DATA_SVC_DATA128:
print_data_set(data->type, 16, data->data, data->data_len);
break;
case BT_DATA_NAME_SHORTENED:
case BT_DATA_NAME_COMPLETE:
case BT_DATA_BROADCAST_NAME:
shell_info(ctx_shell, "%*sType 0x%02x: %.*s",
strlen(scan_response_label), "",
data->type, data->data_len, data->data);
break;
case BT_DATA_PUB_TARGET_ADDR:
case BT_DATA_RAND_TARGET_ADDR:
case BT_DATA_LE_BT_DEVICE_ADDRESS:
print_data_set(data->type, BT_ADDR_SIZE, data->data, data->data_len);
break;
default:
print_data_set(data->type, 1, data->data, data->data_len);
}
return true;
}
static const char *scan_response_type_txt(uint8_t type)
{
switch (type) {
case BT_GAP_ADV_TYPE_ADV_IND:
return "ADV_IND";
case BT_GAP_ADV_TYPE_ADV_DIRECT_IND:
return "ADV_DIRECT_IND";
case BT_GAP_ADV_TYPE_ADV_SCAN_IND:
return "ADV_SCAN_IND";
case BT_GAP_ADV_TYPE_ADV_NONCONN_IND:
return "ADV_NONCONN_IND";
case BT_GAP_ADV_TYPE_SCAN_RSP:
return "SCAN_RSP";
case BT_GAP_ADV_TYPE_EXT_ADV:
return "EXT_ADV";
default:
return "UNKNOWN";
}
}
static void scan_recv(const struct bt_le_scan_recv_info *info,
struct net_buf_simple *buf)
{
char le_addr[BT_ADDR_LE_STR_LEN];
char name[NAME_LEN];
struct net_buf_simple buf_copy;
if (scan_filter.rssi_set && (scan_filter.rssi > info->rssi)) {
return;
@ -210,6 +295,11 @@ static void scan_recv(const struct bt_le_scan_recv_info *info,
return;
}
if (scan_verbose_output) {
/* call to bt_data_parse consumes netbufs so shallow clone for verbose output */
net_buf_simple_clone(buf, &buf_copy);
}
(void)memset(name, 0, sizeof(name));
bt_data_parse(buf, data_cb, name);
@ -223,9 +313,10 @@ static void scan_recv(const struct bt_le_scan_recv_info *info,
return;
}
shell_print(ctx_shell, "[DEVICE]: %s, AD evt type %u, RSSI %i %s "
shell_print(ctx_shell, "%s%s, AD evt type %u, RSSI %i %s "
"C:%u S:%u D:%d SR:%u E:%u Prim: %s, Secn: %s, "
"Interval: 0x%04x (%u us), SID: 0x%x",
scan_response_label,
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,
@ -236,6 +327,15 @@ static void scan_recv(const struct bt_le_scan_recv_info *info,
info->interval, BT_CONN_INTERVAL_TO_US(info->interval),
info->sid);
if (scan_verbose_output) {
shell_info(ctx_shell,
"%*s[SCAN DATA START - %s]",
strlen(scan_response_label), "",
scan_response_type_txt(info->adv_type));
bt_data_parse(&buf_copy, data_verbose_cb, NULL);
shell_info(ctx_shell, "%*s[SCAN DATA END]", strlen(scan_response_label), "");
}
/* Store address for later use */
#if defined(CONFIG_BT_CENTRAL)
auto_connect.addr_set = true;
@ -1137,6 +1237,23 @@ static int cmd_scan(const struct shell *sh, size_t argc, char *argv[])
return 0;
}
static int cmd_scan_verbose_output(const struct shell *sh, size_t argc, char *argv[])
{
const char *verbose_state;
verbose_state = argv[1];
if (!strcmp(verbose_state, "on")) {
scan_verbose_output = true;
} else if (!strcmp(verbose_state, "off")) {
scan_verbose_output = false;
} else {
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
return 0;
}
static int cmd_scan_filter_set_name(const struct shell *sh, size_t argc,
char *argv[])
{
@ -3735,6 +3852,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds,
SHELL_CMD(scan-filter-clear, &bt_scan_filter_clear_cmds,
"Scan filter clear commands",
cmd_default_handler),
SHELL_CMD_ARG(scan-verbose-output, NULL, "<value: on, off>", cmd_scan_verbose_output, 2, 0),
#endif /* CONFIG_BT_OBSERVER */
#if defined(CONFIG_BT_BROADCASTER)
SHELL_CMD_ARG(advertise, NULL,