aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Dieb Martins <andre.dieb@signove.com>2011-02-28 00:58:22 -0300
committerJohan Hedberg <johan.hedberg@nokia.com>2011-03-01 15:49:24 -0300
commit71406a5fddcc17f54c22f19bc1166ecbc510d64a (patch)
tree688be60e2aff59d7e4d46ffd6e4be40b9b6c7b39
parent1a80b5446a797dfb99795e9b16a5561dc47ee8e6 (diff)
downloadhcidump-71406a5fddcc17f54c22f19bc1166ecbc510d64a.tar.gz
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.
-rw-r--r--parser/hci.c146
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;
}
}