diff --git a/tools/hcidump.c b/tools/hcidump.c
index e324293..75707d5 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
#include <bluetooth/hci.h>
#include <bluetooth/l2cap.h>
+#include "parser.h"
+
/* Default options */
int snap_len = 1 + HCI_ACL_HDR_SIZE + L2CAP_HDR_SIZE + 40;
-int dump_type = 0;
void usage(void)
{
printf("\thcidump <-i hciX> [-h]\n");
}
-void raw_dump(char *pref, unsigned char *buf, int len)
-{
- register char *ptr;
- register int i;
- char line[100];
-
- if (!dump_type)
- return;
-
- ptr = line; *ptr = 0;
- for (i=0; i<len; i++) {
- ptr += sprintf(ptr, " %2.2X", buf[i]);
- if (i && !((i+1)%20)) {
- printf("%s%s\n", pref, line);
- ptr = line; *ptr = 0;
- }
- }
- if (line[0])
- printf("%s%s\n", pref, line);
-}
-
-static inline void command_dump(void *ptr, int len)
-{
- hci_command_hdr *hdr = ptr;
- __u16 opcode = __le16_to_cpu(hdr->opcode);
-
- ptr += HCI_COMMAND_HDR_SIZE;
- len -= HCI_COMMAND_HDR_SIZE;
-
- printf("Command: ogf 0x%x ocf 0x%x plen %d\n",
- cmd_opcode_ogf(opcode), cmd_opcode_ocf(opcode), hdr->plen);
- raw_dump(" ", ptr, len);
-}
-
-static inline void event_dump(void *ptr, int len)
-{
- hci_event_hdr *hdr = ptr;
-
- ptr += HCI_EVENT_HDR_SIZE;
- len -= HCI_EVENT_HDR_SIZE;
-
- printf("Event: code 0x%2.2x plen %d\n", hdr->evt, hdr->plen);
- raw_dump(" ", ptr, len);
-}
-
-static inline void l2cap_dump(void *ptr, int len)
-{
- l2cap_hdr *hdr = ptr;
- __u16 dlen = __le16_to_cpu(hdr->len);
- __u16 cid = __le16_to_cpu(hdr->cid);
-
- ptr += L2CAP_HDR_SIZE;
- len -= L2CAP_HDR_SIZE;
-
- if (cid == 0x1) {
- l2cap_cmd_hdr *hdr = 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(" ", ptr, len);
- } else {
- printf(" L2CAP data: cid 0x%x len %d\n", cid, dlen);
- raw_dump(" ", ptr, len);
- }
-}
-
-static inline void acl_dump(void *ptr, int 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);
-
- ptr += HCI_ACL_HDR_SIZE;
- len -= HCI_ACL_HDR_SIZE;
- l2cap_dump(ptr, len);
-}
-
-static inline void analyze(int type, unsigned char *ptr, int len)
-{
- switch( type ){
- case HCI_COMMAND_PKT:
- command_dump(ptr, len);
- break;
-
- case HCI_EVENT_PKT:
- event_dump(ptr, len);
- break;
-
- case HCI_ACLDATA_PKT:
- acl_dump(ptr, len);
- break;
-
- default:
- printf("Unknown: type 0x%2.2x len %d\n",
- (__u8) type, len);
-
- raw_dump(" ", ptr, len);
- break;
- }
-}
-
void process_frames(int dev, int fd)
{
- char data[HCI_MAX_FRAME_SIZE], ctrl[100], *ptr;
+ char *data, *ctrl;
struct cmsghdr *cmsg;
struct msghdr msg;
struct iovec iv;
- int len, type, in;
+ int len, in;
- if (snap_len > sizeof(data))
- snap_len = sizeof(data);
- else if (snap_len < 20)
+ if (snap_len < 20)
snap_len = 20;
+ if (!(data = malloc(snap_len))) {
+ perror("Can't allocate data buffer");
+ exit(1);
+ }
+
+ if (!(ctrl = malloc(100))) {
+ perror("Can't allocate control buffer");
+ exit(1);
+ }
+
printf("device: hci%d snap_len: %d filter: none\n", dev, snap_len);
while (1) {
msg.msg_iov = &iv;
msg.msg_iovlen = 1;
msg.msg_control = ctrl;
- msg.msg_controllen = sizeof(ctrl);
+ msg.msg_controllen = 100;
if( (len = recvmsg(fd, &msg, 0)) < 0 ){
perror("Receive failed");
cmsg = CMSG_NXTHDR(&msg, cmsg);
}
- ptr = data;
- type = *ptr++; len--;
-
/* Print data direction */
printf("%c ", (in ? '>' : '<'));
- analyze(type, ptr, len);
+ parse(data, len);
fflush(stdout);
}
}
-extern int optind,opterr,optopt;
-extern char *optarg;
-
int main(int argc, char *argv[])
{
+ extern int optind, opterr, optopt;
+ extern char *optarg;
struct sockaddr_hci addr;
struct hci_filter flt;
int s, opt, dev;
+ long flags;
dev = 0;
- while( (opt=getopt(argc, argv,"i:s:h")) != EOF ) {
+ flags = 0;
+
+ while ((opt=getopt(argc, argv,"i:s:ha")) != EOF) {
switch(opt) {
- case 'i':
- dev = atoi(optarg+3);
- break;
+ case 'i':
+ dev = atoi(optarg+3);
+ break;
- case 'h':
- dump_type = 1;
- break;
+ case 'h':
+ flags |= DUMP_HEX;
+ break;
+
+ case 'a':
+ flags |= DUMP_ASCII;
+ break;
- case 's':
- snap_len = atoi(optarg);
- break;
+ case 's':
+ snap_len = atoi(optarg);
+ break;
- default:
- usage();
- exit(1);
+ default:
+ usage();
+ exit(1);
}
}
printf("HCIDump - HCI packet analyzer ver %s.\n", VERSION);
+ init_parser(flags);
process_frames(dev, s);
close(s);
diff --git a/tools/parser/hci.c b/tools/parser/hci.c
new file mode 100644
index 0000000..5c945d6
--- /dev/null
+++ b/tools/parser/hci.c
+/*
+ HCIDump - HCI packet analyzer
+ Copyright (C) 2000-2001 Maxim Krasnyansky <maxk@qualcomm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM,
+ OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.
+*/
+
+/*
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <asm/types.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+#include "parser.h"
+
+static inline void command_dump(void *ptr, int len)
+{
+ hci_command_hdr *hdr = ptr;
+ __u16 opcode = __le16_to_cpu(hdr->opcode);
+
+ ptr += HCI_COMMAND_HDR_SIZE;
+ len -= HCI_COMMAND_HDR_SIZE;
+
+ printf("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);
+}
+
+static inline void event_dump(void *ptr, int len)
+{
+ hci_event_hdr *hdr = ptr;
+
+ ptr += HCI_EVENT_HDR_SIZE;
+ len -= HCI_EVENT_HDR_SIZE;
+
+ printf("Event: code 0x%2.2x plen %d\n", hdr->evt, hdr->plen);
+ raw_dump(1, ptr, len);
+}
+
+static inline void acl_dump(void *ptr, int 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);
+
+ ptr += HCI_ACL_HDR_SIZE;
+ len -= HCI_ACL_HDR_SIZE;
+ l2cap_dump(1, ptr, len, acl_flags(handle));
+}
+
+void hci_dump(int level, __u8 *data, int len)
+{
+ unsigned char *ptr = data;
+ __u8 type;
+
+ type = *ptr++; len--;
+
+ switch (type) {
+ case HCI_COMMAND_PKT:
+ command_dump(ptr, len);
+ break;
+
+ case HCI_EVENT_PKT:
+ event_dump(ptr, len);
+ break;
+
+ case HCI_ACLDATA_PKT:
+ acl_dump(ptr, len);
+ break;
+
+ default:
+ printf("Unknown: type 0x%2.2x len %d\n", type, len);
+ raw_dump(1, ptr, len);
+ break;
+ }
+}
diff --git a/tools/parser/l2cap.c b/tools/parser/l2cap.c
new file mode 100644
index 0000000..61bd621
--- /dev/null
+++ b/tools/parser/l2cap.c
+/*
+ HCIDump - HCI packet analyzer
+ Copyright (C) 2000-2001 Maxim Krasnyansky <maxk@qualcomm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM,
+ OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.
+*/
+
+/*
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <asm/types.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/l2cap.h>
+
+#include "parser.h"
+
+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);
+
+ 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);
+ } else {
+ printf("L2CAP data: 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
new file mode 100644
index 0000000..f6177ae
--- /dev/null
+++ b/tools/parser/parser.c
+/*
+ HCIDump - HCI packet analyzer
+ Copyright (C) 2000-2001 Maxim Krasnyansky <maxk@qualcomm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM,
+ OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.
+*/
+
+/*
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <asm/types.h>
+
+#include "parser.h"
+
+static long parser_flags;
+
+void init_parser(long flags)
+{
+ parser_flags = flags;
+}
+
+static inline void hex_dump(int level, unsigned char *buf, int len)
+{
+ register unsigned char *ptr;
+ register int i;
+ char line[100];
+
+ 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;
+ }
+ }
+ if (line[0])
+ indent(level); printf("%s\n", line);
+}
+
+static inline void ascii_dump(int level, unsigned char *buf, int len)
+{
+ register unsigned char *ptr;
+ register int i;
+ char line[100];
+
+ 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;
+ }
+ }
+ if (line[0])
+ indent(level); printf("%s\n", line);
+}
+
+void raw_dump(int level, unsigned char *buf, int len)
+{
+ switch (parser_flags & DUMP_TYPE_MASK) {
+ case DUMP_HEX:
+ hex_dump(level, buf, len);
+ break;
+
+ case DUMP_ASCII:
+ ascii_dump(level, buf, len);
+ break;
+ }
+}
diff --git a/tools/parser/parser.h b/tools/parser/parser.h
new file mode 100644
index 0000000..9f1e5d8
--- /dev/null
+++ b/tools/parser/parser.h
+/*
+ HCIDump - HCI packet analyzer
+ Copyright (C) 2000-2001 Maxim Krasnyansky <maxk@qualcomm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM,
+ OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.
+*/
+
+/*
+ * $Id$
+ */
+
+#define indent(l) printf("%*c", (l*2), ' ')
+
+#define DUMP_HEX 0x01
+#define DUMP_ASCII 0x02
+#define DUMP_TYPE_MASK (DUMP_HEX | DUMP_ASCII)
+
+void init_parser(long flags);
+#define parse(data, len) hci_dump(0, data, len)
+
+void raw_dump(int level, __u8 *data, int len);
+void hci_dump(int level, __u8 *data, int len);
+void l2cap_dump(int level, __u8 *data, int len, __u8 flags);