2011-02-28 03:58:22

by Andre Dieb Martins

[permalink] [raw]
Subject: [PATCH v1] Fix HCI LE advertising report dump

LE advertising report event has only one data block for each report. Thus, we
can't reuse ext_inquiry_response_dump(), which loops over successive data blocks
until reaches a zero-length one.

This commit introduces ext_inquiry_data_dump(), which dumps a frame containing
data formatted according to [Vol 3] Part C, Section 8. This function is reused
by ext_inquiry_response_dump().

Also adds RSSI parsing to each advertising report.
---
parser/hci.c | 146 +++++++++++++++++++++++++++++++++------------------------
1 files changed, 84 insertions(+), 62 deletions(-)

diff --git a/parser/hci.c b/parser/hci.c
index 183fa66..e4a3633 100644
--- a/parser/hci.c
+++ b/parser/hci.c
@@ -757,67 +757,83 @@ static char *filterpolicy2str(uint8_t policy)
}
}

-static inline void ext_inquiry_response_dump(int level, struct frame *frm)
+static inline void ext_inquiry_data_dump(int level, struct frame *frm,
+ uint8_t *data)
{
- void *ptr = frm->ptr;
- uint32_t len = frm->len;
- uint8_t type, length;
+ uint8_t len = data[0];
+ uint8_t type;
char *str;
int i;

- length = get_u8(frm);
+ if (len == 0)
+ return;

- while (length > 0) {
- type = get_u8(frm);
- length--;
+ type = data[1];
+ data += 2;
+ len -= 1;

- switch (type) {
- case 0x01:
- p_indent(level, frm);
- printf("Flags:");
- for (i = 0; i < length; i++)
- printf(" 0x%2.2x", *((uint8_t *) (frm->ptr + i)));
- printf("\n");
- break;
+ switch (type) {
+ case 0x01:
+ p_indent(level, frm);
+ printf("Flags:");
+ for (i = 0; i < len; i++)
+ printf(" 0x%2.2x", data[i]);
+ printf("\n");
+ break;

- case 0x02:
- case 0x03:
- p_indent(level, frm);
- printf("%s service classes:",
- type == 0x02 ? "Shortened" : "Complete");
- for (i = 0; i < length / 2; i++) {
- uint16_t val = btohs(bt_get_unaligned((uint16_t *) (frm->ptr + (i * 2))));
- printf(" 0x%4.4x", val);
- }
- printf("\n");
- break;
+ case 0x02:
+ case 0x03:
+ p_indent(level, frm);
+ printf("%s service classes:",
+ type == 0x02 ? "Shortened" : "Complete");

- case 0x08:
- case 0x09:
- str = malloc(length + 1);
- if (str) {
- snprintf(str, length + 1, "%s", (char *) frm->ptr);
- for (i = 0; i < length; i++)
- if (!isprint(str[i]))
- str[i] = '.';
- p_indent(level, frm);
- printf("%s local name: \'%s\'\n",
- type == 0x08 ? "Shortened" : "Complete", str);
- free(str);
- }
- break;
+ for (i = 0; i < len / 2; i++) {
+ uint16_t val;

- case 0x0a:
- p_indent(level, frm);
- printf("TX power level: %d\n", *((uint8_t *) frm->ptr));
- break;
+ val = btohs(bt_get_unaligned(((uint16_t *) (data + i * 2))));
+ printf(" 0x%4.4x", val);
+ }
+ printf("\n");
+ break;

- default:
+ case 0x08:
+ case 0x09:
+ str = malloc(len + 1);
+ if (str) {
+ snprintf(str, len + 1, "%s", (char *) data);
+ for (i = 0; i < len; i++)
+ if (!isprint(str[i]))
+ str[i] = '.';
p_indent(level, frm);
- printf("Unknown type 0x%02x with %d bytes data\n",
- type, length);
- break;
+ printf("%s local name: \'%s\'\n",
+ type == 0x08 ? "Shortened" : "Complete", str);
+ free(str);
}
+ break;
+
+ case 0x0a:
+ p_indent(level, frm);
+ printf("TX power level: %d\n", *((uint8_t *) data));
+ break;
+
+ default:
+ p_indent(level, frm);
+ printf("Unknown type 0x%02x with %d bytes data\n",
+ type, len);
+ break;
+ }
+}
+
+static inline void ext_inquiry_response_dump(int level, struct frame *frm)
+{
+ void *ptr = frm->ptr;
+ uint32_t len = frm->len;
+ uint8_t length;
+
+ length = get_u8(frm);
+
+ while (length > 0) {
+ ext_inquiry_data_dump(level, frm, frm->ptr);

frm->ptr += length;
frm->len -= length;
@@ -825,8 +841,10 @@ static inline void ext_inquiry_response_dump(int level, struct frame *frm)
length = get_u8(frm);
}

- frm->ptr = ptr + (EXTENDED_INQUIRY_INFO_SIZE - INQUIRY_INFO_WITH_RSSI_SIZE);
- frm->len = len + (EXTENDED_INQUIRY_INFO_SIZE - INQUIRY_INFO_WITH_RSSI_SIZE);
+ frm->ptr = ptr +
+ (EXTENDED_INQUIRY_INFO_SIZE - INQUIRY_INFO_WITH_RSSI_SIZE);
+ frm->len = len +
+ (EXTENDED_INQUIRY_INFO_SIZE - INQUIRY_INFO_WITH_RSSI_SIZE);
}

static inline void bdaddr_command_dump(int level, struct frame *frm)
@@ -3504,14 +3522,12 @@ static inline void evt_le_conn_complete_dump(int level, struct frame *frm)

static inline void evt_le_advertising_report_dump(int level, struct frame *frm)
{
- uint8_t num = get_u8(frm);
- char addr[18];
- int i;
+ uint8_t num_reports = get_u8(frm);
+ const uint8_t RSSI_SIZE = 1;

- for (i = 0; i < num; i++) {
+ while (num_reports--) {
+ char addr[18];
le_advertising_info *info = frm->ptr;
- void *ptr = frm->ptr;
- uint32_t len = frm->len;

p_ba2str(&info->bdaddr, addr);

@@ -3522,13 +3538,19 @@ static inline void evt_le_advertising_report_dump(int level, struct frame *frm)
printf("bdaddr %s (%s)\n", addr,
bdaddrtype2str(info->bdaddr_type));

- frm->ptr += LE_ADVERTISING_INFO_SIZE;
- frm->len -= LE_ADVERTISING_INFO_SIZE;
+ if (info->length > 0) {
+ ext_inquiry_data_dump(level, frm,
+ ((uint8_t *) &info->length) + 1);
+ }

- ext_inquiry_response_dump(level, frm);
+ frm->ptr += LE_ADVERTISING_INFO_SIZE + info->length;
+ frm->len -= LE_ADVERTISING_INFO_SIZE + info->length;
+
+ p_indent(level, frm);
+ printf("RSSI: %d\n", ((int8_t *) frm->ptr)[frm->len - 1]);

- frm->ptr = ptr + 1;
- frm->len = len - 1;
+ frm->ptr += RSSI_SIZE;
+ frm->len -= RSSI_SIZE;
}
}

--
1.7.1



2011-03-01 18:59:27

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH v1] Fix HCI LE advertising report dump

Hi Andr?,

On Mon, Feb 28, 2011, Andre Dieb Martins wrote:
> LE advertising report event has only one data block for each report.
> Thus, we can't reuse ext_inquiry_response_dump(), which loops over
> successive data blocks until reaches a zero-length one.
>
> This commit introduces ext_inquiry_data_dump(), which dumps a frame
> containing data formatted according to [Vol 3] Part C, Section 8. This
> function is reused by ext_inquiry_response_dump().
>
> Also adds RSSI parsing to each advertising report.
> ---
> parser/hci.c | 146 +++++++++++++++++++++++++++++++++------------------------
> 1 files changed, 84 insertions(+), 62 deletions(-)

Pushed upstream. Thanks. I had to fix your commit message first though.
Please make sure that the lines are short enough to be properly viewable
with git log on a 80-column wide terminal (git log indents them by 4
characters).

Johan