Skip to content

Commit ddf518e

Browse files
demantmrrvcarlescufi
authored andcommitted
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>
1 parent 9cdc5d3 commit ddf518e

File tree

1 file changed

+119
-1
lines changed
  • subsys/bluetooth/shell

1 file changed

+119
-1
lines changed

subsys/bluetooth/shell/bt.c

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ static struct bt_scan_filter {
147147
bool pa_interval_set;
148148
} scan_filter;
149149

150+
static const char scan_response_label[] = "[DEVICE]: ";
151+
static bool scan_verbose_output;
150152

151153
/**
152154
* @brief Compares two strings without case sensitivy
@@ -194,11 +196,94 @@ static bool data_cb(struct bt_data *data, void *user_data)
194196
}
195197
}
196198

199+
static void print_data_set(uint8_t type, uint8_t set_value_len,
200+
const uint8_t *scan_data, uint8_t scan_data_len)
201+
{
202+
uint8_t min_value_len = MIN(set_value_len, scan_data_len);
203+
204+
shell_fprintf(ctx_shell, SHELL_INFO, "%*sType 0x%02x: ",
205+
strlen(scan_response_label), "",
206+
type);
207+
for (uint8_t i = 0U; i < (scan_data_len / min_value_len); i++) {
208+
if (i > 0L) {
209+
shell_fprintf(ctx_shell, SHELL_INFO, ", ");
210+
}
211+
212+
shell_fprintf(ctx_shell, SHELL_INFO, "0x");
213+
for (uint8_t j = 0U; j < min_value_len; j++) {
214+
shell_fprintf(ctx_shell, SHELL_INFO, "%02x",
215+
scan_data[i * min_value_len + j]);
216+
}
217+
}
218+
219+
shell_fprintf(ctx_shell, SHELL_INFO, "\n");
220+
}
221+
222+
static bool data_verbose_cb(struct bt_data *data, void *user_data)
223+
{
224+
switch (data->type) {
225+
case BT_DATA_UUID16_SOME:
226+
case BT_DATA_UUID16_ALL:
227+
case BT_DATA_SOLICIT16:
228+
case BT_DATA_SVC_DATA16:
229+
print_data_set(data->type, 2, data->data, data->data_len);
230+
break;
231+
case BT_DATA_UUID32_SOME:
232+
case BT_DATA_UUID32_ALL:
233+
case BT_DATA_SVC_DATA32:
234+
print_data_set(data->type, 4, data->data, data->data_len);
235+
break;
236+
case BT_DATA_UUID128_SOME:
237+
case BT_DATA_UUID128_ALL:
238+
case BT_DATA_SOLICIT128:
239+
case BT_DATA_SVC_DATA128:
240+
print_data_set(data->type, 16, data->data, data->data_len);
241+
break;
242+
case BT_DATA_NAME_SHORTENED:
243+
case BT_DATA_NAME_COMPLETE:
244+
case BT_DATA_BROADCAST_NAME:
245+
shell_info(ctx_shell, "%*sType 0x%02x: %.*s",
246+
strlen(scan_response_label), "",
247+
data->type, data->data_len, data->data);
248+
break;
249+
case BT_DATA_PUB_TARGET_ADDR:
250+
case BT_DATA_RAND_TARGET_ADDR:
251+
case BT_DATA_LE_BT_DEVICE_ADDRESS:
252+
print_data_set(data->type, BT_ADDR_SIZE, data->data, data->data_len);
253+
break;
254+
default:
255+
print_data_set(data->type, 1, data->data, data->data_len);
256+
}
257+
258+
return true;
259+
}
260+
261+
static const char *scan_response_type_txt(uint8_t type)
262+
{
263+
switch (type) {
264+
case BT_GAP_ADV_TYPE_ADV_IND:
265+
return "ADV_IND";
266+
case BT_GAP_ADV_TYPE_ADV_DIRECT_IND:
267+
return "ADV_DIRECT_IND";
268+
case BT_GAP_ADV_TYPE_ADV_SCAN_IND:
269+
return "ADV_SCAN_IND";
270+
case BT_GAP_ADV_TYPE_ADV_NONCONN_IND:
271+
return "ADV_NONCONN_IND";
272+
case BT_GAP_ADV_TYPE_SCAN_RSP:
273+
return "SCAN_RSP";
274+
case BT_GAP_ADV_TYPE_EXT_ADV:
275+
return "EXT_ADV";
276+
default:
277+
return "UNKNOWN";
278+
}
279+
}
280+
197281
static void scan_recv(const struct bt_le_scan_recv_info *info,
198282
struct net_buf_simple *buf)
199283
{
200284
char le_addr[BT_ADDR_LE_STR_LEN];
201285
char name[NAME_LEN];
286+
struct net_buf_simple buf_copy;
202287

203288
if (scan_filter.rssi_set && (scan_filter.rssi > info->rssi)) {
204289
return;
@@ -210,6 +295,11 @@ static void scan_recv(const struct bt_le_scan_recv_info *info,
210295
return;
211296
}
212297

298+
if (scan_verbose_output) {
299+
/* call to bt_data_parse consumes netbufs so shallow clone for verbose output */
300+
net_buf_simple_clone(buf, &buf_copy);
301+
}
302+
213303
(void)memset(name, 0, sizeof(name));
214304

215305
bt_data_parse(buf, data_cb, name);
@@ -223,9 +313,10 @@ static void scan_recv(const struct bt_le_scan_recv_info *info,
223313
return;
224314
}
225315

226-
shell_print(ctx_shell, "[DEVICE]: %s, AD evt type %u, RSSI %i %s "
316+
shell_print(ctx_shell, "%s%s, AD evt type %u, RSSI %i %s "
227317
"C:%u S:%u D:%d SR:%u E:%u Prim: %s, Secn: %s, "
228318
"Interval: 0x%04x (%u us), SID: 0x%x",
319+
scan_response_label,
229320
le_addr, info->adv_type, info->rssi, name,
230321
(info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
231322
(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,
236327
info->interval, BT_CONN_INTERVAL_TO_US(info->interval),
237328
info->sid);
238329

330+
if (scan_verbose_output) {
331+
shell_info(ctx_shell,
332+
"%*s[SCAN DATA START - %s]",
333+
strlen(scan_response_label), "",
334+
scan_response_type_txt(info->adv_type));
335+
bt_data_parse(&buf_copy, data_verbose_cb, NULL);
336+
shell_info(ctx_shell, "%*s[SCAN DATA END]", strlen(scan_response_label), "");
337+
}
338+
239339
/* Store address for later use */
240340
#if defined(CONFIG_BT_CENTRAL)
241341
auto_connect.addr_set = true;
@@ -1137,6 +1237,23 @@ static int cmd_scan(const struct shell *sh, size_t argc, char *argv[])
11371237
return 0;
11381238
}
11391239

1240+
static int cmd_scan_verbose_output(const struct shell *sh, size_t argc, char *argv[])
1241+
{
1242+
const char *verbose_state;
1243+
1244+
verbose_state = argv[1];
1245+
if (!strcmp(verbose_state, "on")) {
1246+
scan_verbose_output = true;
1247+
} else if (!strcmp(verbose_state, "off")) {
1248+
scan_verbose_output = false;
1249+
} else {
1250+
shell_help(sh);
1251+
return SHELL_CMD_HELP_PRINTED;
1252+
}
1253+
1254+
return 0;
1255+
}
1256+
11401257
static int cmd_scan_filter_set_name(const struct shell *sh, size_t argc,
11411258
char *argv[])
11421259
{
@@ -3735,6 +3852,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds,
37353852
SHELL_CMD(scan-filter-clear, &bt_scan_filter_clear_cmds,
37363853
"Scan filter clear commands",
37373854
cmd_default_handler),
3855+
SHELL_CMD_ARG(scan-verbose-output, NULL, "<value: on, off>", cmd_scan_verbose_output, 2, 0),
37383856
#endif /* CONFIG_BT_OBSERVER */
37393857
#if defined(CONFIG_BT_BROADCASTER)
37403858
SHELL_CMD_ARG(advertise, NULL,

0 commit comments

Comments
 (0)