diff --git a/tools/hcidump.c b/tools/hcidump.c
index 75707d5..b3b7150 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
#include "parser.h"
/* Default options */
-int snap_len = 1 + HCI_ACL_HDR_SIZE + L2CAP_HDR_SIZE + 40;
+#define SNAP_LEN (1 + HCI_ACL_HDR_SIZE + L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + 60)
+int snap_len = SNAP_LEN;
void usage(void)
{
printf("HCIDump - HCI packet analyzer ver %s\n", VERSION);
printf("Usage:\n");
- printf("\thcidump <-i hciX> [-h]\n");
+ printf("\thcidump <-i hciX> [-ah]\n");
}
void process_frames(int dev, int fd)
struct iovec iv;
int len, in;
- if (snap_len < 20)
- snap_len = 20;
+ if (snap_len < SNAP_LEN)
+ snap_len = SNAP_LEN;
if (!(data = malloc(snap_len))) {
perror("Can't allocate data buffer");
diff --git a/tools/parser/hci.c b/tools/parser/hci.c
index 5c945d6..3d1dabc 100644
--- a/tools/parser/hci.c
+++ b/tools/parser/hci.c
ptr += HCI_COMMAND_HDR_SIZE;
len -= HCI_COMMAND_HDR_SIZE;
- printf("Command: ogf 0x%x ocf 0x%x plen %d\n",
+ printf("HCI Command: ogf 0x%x ocf 0x%x plen %d\n",
cmd_opcode_ogf(opcode), cmd_opcode_ocf(opcode), hdr->plen);
raw_dump(1, ptr, len);
}
ptr += HCI_EVENT_HDR_SIZE;
len -= HCI_EVENT_HDR_SIZE;
- printf("Event: code 0x%2.2x plen %d\n", hdr->evt, hdr->plen);
+ printf("HCI Event: code 0x%2.2x plen %d\n", hdr->evt, hdr->plen);
raw_dump(1, ptr, len);
}
hci_acl_hdr *hdr = ptr;
__u16 handle = __le16_to_cpu(hdr->handle);
__u16 dlen = __le16_to_cpu(hdr->dlen);
-
- printf("ACL data: handle 0x%x flags 0x%x dlen %d\n",
- acl_handle(handle), acl_flags(handle), dlen);
+ __u8 flags = acl_flags(handle);
+
+ printf("ACL data: handle 0x%4.4x flags 0x%2.2x dlen %d\n",
+ acl_handle(handle), flags, dlen);
ptr += HCI_ACL_HDR_SIZE;
len -= HCI_ACL_HDR_SIZE;
- l2cap_dump(1, ptr, len, acl_flags(handle));
+
+ if (flags & ACL_START) {
+ l2cap_dump(1, ptr, len, flags);
+ } else {
+ raw_dump(1, ptr, len);
+ }
}
void hci_dump(int level, __u8 *data, int len)
diff --git a/tools/parser/l2cap.c b/tools/parser/l2cap.c
index 61bd621..cd77e0d 100644
--- a/tools/parser/l2cap.c
+++ b/tools/parser/l2cap.c
#include "parser.h"
+static inline void command_rej(int level, __u8 *ptr, int len)
+{
+ l2cap_cmd_rej *h = (void *) ptr;
+ printf("Command rej: reason %d\n",
+ btohs(h->reason));
+}
+
+static inline void conn_req(int level, __u8 *ptr, int len)
+{
+ l2cap_conn_req *h = (void *) ptr;
+ printf("Connect req: psm %d scid 0x%4.4x\n",
+ btohs(h->psm), btohs(h->scid));
+}
+
+static inline void conn_rsp(int level, __u8 *ptr, int len)
+{
+ l2cap_conn_rsp *h = (void *) ptr;
+ printf("Connect rsp: dcid 0x%4.4x scid 0x%4.4x result %d status %d\n",
+ btohs(h->dcid), btohs(h->scid),
+ btohs(h->result), btohs(h->status));
+}
+
+static __u32 conf_opt_val(__u8 *ptr, __u8 len)
+{
+ switch (len) {
+ case 1:
+ return *ptr;
+
+ case 2:
+ return btohs(*(__u16 *)ptr);
+
+ case 4:
+ return btohl(*(__u32 *)ptr);
+ }
+ return 0;
+}
+
+static void conf_opt(int level, __u8 *ptr, int len)
+{
+ indent(level);
+ while (len > 0) {
+ l2cap_conf_opt *h = (void *) ptr;
+
+ ptr += L2CAP_CONF_OPT_SIZE + h->len;
+ len -= L2CAP_CONF_OPT_SIZE + h->len;
+
+ switch (h->type) {
+ case L2CAP_CONF_MTU:
+ printf("mtu %d ", conf_opt_val(h->val, h->len));
+ break;
+ case L2CAP_CONF_FLUSH_TO:
+ printf("flush_to %d ", conf_opt_val(h->val, h->len));
+ break;
+ default:
+ printf("unknown (type %2.2x, len %d) ", h->type, h->len);
+ break;
+ }
+ }
+ printf("\n");
+}
+
+static inline void conf_req(int level, l2cap_cmd_hdr *cmd, __u8 *ptr, int len)
+{
+ l2cap_conf_req *h = (void *) ptr;
+ int clen = btohs(cmd->len) - L2CAP_CONF_REQ_SIZE;
+ printf("Config req: dcid 0x%4.4x flags 0x%4.4x clen %d\n",
+ btohs(h->dcid), btohs(h->flags), clen);
+ if (clen)
+ conf_opt(level+1, h->data, clen);
+}
+
+static inline void conf_rsp(int level, l2cap_cmd_hdr *cmd, __u8 *ptr, int len)
+{
+ l2cap_conf_rsp *h = (void *) ptr;
+ int clen = btohs(cmd->len) - L2CAP_CONF_RSP_SIZE;
+ printf("Config rsp: scid 0x%4.4x flags 0x%4.4x result %d clen %d\n",
+ btohs(h->scid), btohs(h->flags), btohs(h->result), clen);
+ if (clen)
+ conf_opt(level+1, h->data, clen);
+}
+
+static inline void disconn_req(int level, __u8 *ptr, int len)
+{
+ l2cap_disconn_req *h = (void *) ptr;
+ printf("Disconn req: dcid 0x%4.4x scid 0x%4.4x\n",
+ btohs(h->dcid), btohs(h->scid));
+}
+
+static inline void disconn_rsp(int level, __u8 *ptr, int len)
+{
+ l2cap_disconn_rsp *h = (void *) ptr;
+ printf("Disconn rsp: dcid 0x%4.4x scid 0x%4.4x\n",
+ btohs(h->dcid), btohs(h->scid));
+}
+
+static inline void echo_req(int level, l2cap_cmd_hdr *cmd, __u8 *ptr, int len)
+{
+ printf("Echo req: dlen %d\n",
+ btohs(cmd->len));
+ raw_dump(level, ptr, len);
+}
+
+static inline void echo_rsp(int level, l2cap_cmd_hdr *cmd, __u8 *ptr, int len)
+{
+ printf("Echo rsp: dlen %d\n",
+ btohs(cmd->len));
+ raw_dump(level, ptr, len);
+}
+
void l2cap_dump(int level, __u8 *ptr, int len, __u8 flags)
{
l2cap_hdr *hdr = (void *) ptr;
- __u16 dlen = __le16_to_cpu(hdr->len);
- __u16 cid = __le16_to_cpu(hdr->cid);
+ __u16 dlen = btohs(hdr->len);
+ __u16 cid = btohs(hdr->cid);
ptr += L2CAP_HDR_SIZE;
len -= L2CAP_HDR_SIZE;
indent(level);
if (cid == 0x1) {
l2cap_cmd_hdr *hdr = (void *) ptr;
- __u16 len = __le16_to_cpu(hdr->len);
ptr += L2CAP_CMD_HDR_SIZE;
len -= L2CAP_CMD_HDR_SIZE;
- printf("L2CAP signaling: code 0x%2.2x ident %d len %d\n",
- hdr->code, hdr->ident, len);
- raw_dump(level, ptr, len);
+ printf("L2CAP(s): ");
+
+ switch (hdr->code) {
+ case L2CAP_COMMAND_REJ:
+ command_rej(level, ptr, len);
+ break;
+
+ case L2CAP_CONN_REQ:
+ conn_req(level, ptr, len);
+ break;
+
+ case L2CAP_CONN_RSP:
+ conn_rsp(level, ptr, len);
+ break;
+
+ case L2CAP_CONF_REQ:
+ conf_req(level, hdr, ptr, len);
+ break;
+
+ case L2CAP_CONF_RSP:
+ conf_rsp(level, hdr, ptr, len);
+ break;
+
+ case L2CAP_DISCONN_REQ:
+ disconn_req(level, ptr, len);
+ break;
+
+ case L2CAP_DISCONN_RSP:
+ disconn_rsp(level, ptr, len);
+ break;
+
+ case L2CAP_ECHO_REQ:
+ echo_req(level, hdr, ptr, len);
+ break;
+
+ case L2CAP_ECHO_RSP:
+ echo_rsp(level, hdr, ptr, len);
+ break;
+/*
+ case L2CAP_INFO_REQ:
+ info_req(level, ptr, len);
+ break;
+
+ case L2CAP_INFO_RSP:
+ info_rsp(level, ptr, len);
+ break;
+*/
+ default:
+ printf("code 0x%2.2x ident %d len %d\n",
+ hdr->code, hdr->ident, btohs(hdr->len));
+ raw_dump(level, ptr, len);
+ }
} else {
- printf("L2CAP data: cid 0x%x len %d\n", cid, dlen);
+ printf("L2CAP(d): cid 0x%x len %d\n", cid, dlen);
raw_dump(level, ptr, len);
}
}
diff --git a/tools/parser/parser.c b/tools/parser/parser.c
index f6177ae..fae7c5e 100644
--- a/tools/parser/parser.c
+++ b/tools/parser/parser.c
#include <unistd.h>
#include <errno.h>
#include <string.h>
+#include <ctype.h>
#include <sys/types.h>
#include <asm/types.h>
static inline void hex_dump(int level, unsigned char *buf, int len)
{
- register unsigned char *ptr;
- register int i;
- char line[100];
+ register int i,n;
- ptr = line; *ptr = 0;
- for (i=0; i<len; i++) {
- ptr += sprintf(ptr, "%2.2X ", buf[i]);
- if (i && !((i+1)%20)) {
- indent(level); printf("%s\n", line);
- ptr = line; *ptr = 0;
+ for (i=0, n=1; i<len; i++, n++) {
+ if (n == 1)
+ indent(level);
+ printf("%2.2X ", buf[i]);
+ if (n == DUMP_WIDTH) {
+ printf("\n");
+ n = 0;
}
}
- if (line[0])
- indent(level); printf("%s\n", line);
+ if (i && n!=1)
+ printf("\n");
}
static inline void ascii_dump(int level, unsigned char *buf, int len)
{
- register unsigned char *ptr;
- register int i;
- char line[100];
+ register int i,n;
- ptr = line; *ptr = 0;
- for (i=0; i<len; i++) {
- ptr += sprintf(ptr, "%1c", buf[i]);
- if (i && !((i+1)%20)) {
- indent(level); printf("%s\n", line);
- ptr = line; *ptr = 0;
+ for (i=0, n=1; i<len; i++, n++) {
+ if (n == 1)
+ indent(level);
+ printf("%1c ", isprint(buf[i]) ? buf[1] : '.');
+ if (n == DUMP_WIDTH) {
+ printf("\n");
+ n = 0;
}
}
- if (line[0])
- indent(level); printf("%s\n", line);
+ if (i && n!=1)
+ printf("\n");
}
void raw_dump(int level, unsigned char *buf, int len)
diff --git a/tools/parser/parser.h b/tools/parser/parser.h
index 9f1e5d8..4670f0b 100644
--- a/tools/parser/parser.h
+++ b/tools/parser/parser.h
* $Id$
*/
-#define indent(l) printf("%*c", (l*2), ' ')
+#define DUMP_WIDTH 20
#define DUMP_HEX 0x01
#define DUMP_ASCII 0x02
#define DUMP_TYPE_MASK (DUMP_HEX | DUMP_ASCII)
+#define indent(l) printf("%*c", (l*2), ' ')
+
void init_parser(long flags);
#define parse(data, len) hci_dump(0, data, len)