diff --git a/tools/hcidump.c b/tools/hcidump.c
index 701fc88..e324293 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
#include <bluetooth/hci.h>
#include <bluetooth/l2cap.h>
-#define HEXDUMP 0
-#define ANALYZE 1
-
/* Default options */
-int action = ANALYZE;
-
-char * hci_pkt_type[] = {
- "Unknown",
- "Command",
- "ACL Data",
- "SCO Data",
- "Event"
-};
+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 hex_dump(char *pref, unsigned char *buf, int len)
+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++ ){
+ for (i=0; i<len; i++) {
ptr += sprintf(ptr, " %2.2X", buf[i]);
- if( i && !((i+1)%20) ){
+ if (i && !((i+1)%20)) {
printf("%s%s\n", pref, line);
ptr = line; *ptr = 0;
}
}
- if( line[0] )
+ if (line[0])
printf("%s%s\n", pref, line);
}
-void inline command_dump(void *ptr, int len)
+static inline void command_dump(void *ptr, int len)
{
hci_command_hdr *hdr = ptr;
__u16 opcode = __le16_to_cpu(hdr->opcode);
- printf("ogf 0x%x ocf 0x%x plen %d\n",
+
+ 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);
}
-void inline event_dump(void *ptr, int len)
+static inline void event_dump(void *ptr, int len)
{
hci_event_hdr *hdr = ptr;
- printf("code 0x%2.2x plen %d\n", hdr->evt, hdr->plen);
+
+ 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);
}
-void inline l2cap_dump(void *ptr, int 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);
- printf(" L2CAP: cid 0x%x len %d\n", cid, dlen);
-
ptr += L2CAP_HDR_SIZE;
+ len -= L2CAP_HDR_SIZE;
+
if (cid == 0x1) {
l2cap_cmd_hdr *hdr = ptr;
__u16 len = __le16_to_cpu(hdr->len);
- printf(" signaling: code 0x%x ident %d len %d\n",
+
+ 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);
}
}
-void inline acl_dump(void *ptr, int 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("handle 0x%x flags 0x%x dlen %d\n",
+ printf("ACL data: handle 0x%x flags 0x%x dlen %d\n",
acl_handle(handle), acl_flags(handle), dlen);
ptr += HCI_ACL_HDR_SIZE;
l2cap_dump(ptr, len);
}
-void analyze(int type, unsigned char *ptr, int len)
+static inline void analyze(int type, unsigned char *ptr, int len)
{
switch( type ){
case HCI_COMMAND_PKT:
break;
default:
- printf("\n");
+ 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;
+ struct cmsghdr *cmsg;
+ struct msghdr msg;
+ struct iovec iv;
+ int len, type, in;
+
+ if (snap_len > sizeof(data))
+ snap_len = sizeof(data);
+ else if (snap_len < 20)
+ snap_len = 20;
+
+ printf("device: hci%d snap_len: %d filter: none\n", dev, snap_len);
+
+ while (1) {
+ iv.iov_base = data;
+ iv.iov_len = snap_len;
+
+ msg.msg_iov = &iv;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ctrl;
+ msg.msg_controllen = sizeof(ctrl);
+
+ if( (len = recvmsg(fd, &msg, 0)) < 0 ){
+ perror("Receive failed");
+ exit(1);
+ }
+
+ /* Process control message */
+ in = 0;
+ cmsg = CMSG_FIRSTHDR(&msg);
+ while( cmsg ){
+ switch(cmsg->cmsg_type){
+ case HCI_CMSG_DIR:
+ in = *((int *)CMSG_DATA(cmsg));
+ break;
+ }
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ }
+
+ ptr = data;
+ type = *ptr++; len--;
+
+ /* Print data direction */
+ printf("%c ", (in ? '>' : '<'));
+
+ analyze(type, ptr, len);
+
+ fflush(stdout);
+ }
+}
+
extern int optind,opterr,optopt;
extern char *optarg;
int main(int argc, char *argv[])
{
- char data[HCI_MAX_FRAME_SIZE], ctrl[100], *ptr;
- int s, len, type, opt, dev, in;
struct sockaddr_hci addr;
struct hci_filter flt;
- struct cmsghdr *cmsg;
- struct msghdr msg;
- struct iovec iv;
+ int s, opt, dev;
dev = 0;
- while( (opt=getopt(argc, argv,"i:h")) != EOF ) {
+ while( (opt=getopt(argc, argv,"i:s:h")) != EOF ) {
switch(opt) {
case 'i':
dev = atoi(optarg+3);
break;
case 'h':
- action = HEXDUMP;
+ dump_type = 1;
break;
- case 'a':
- action = ANALYZE;
+ case 's':
+ snap_len = atoi(optarg);
break;
default:
addr.hci_family = AF_BLUETOOTH;
addr.hci_dev = dev;
if( bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ) {
- printf("Can't attach to device hci%d. %s(%d)\n", dev, strerror(errno), errno);
+ printf("Can't attach to device hci%d. %s(%d)\n",
+ dev, strerror(errno), errno);
exit(1);
}
- printf("HCIDump version %s\n", VERSION);
+ printf("HCIDump - HCI packet analyzer ver %s.\n", VERSION);
- while( 1 ) {
- iv.iov_base = data;
- iv.iov_len = sizeof(data);
+ process_frames(dev, s);
- msg.msg_iov = &iv;
- msg.msg_iovlen = 1;
- msg.msg_control = ctrl;
- msg.msg_controllen = sizeof(ctrl);
-
- if( (len = recvmsg(s, &msg, 0)) < 0 ){
- perror("Receive failed");
- exit(1);
- }
-
- /* Process controll message */
- in = 0;
- cmsg = CMSG_FIRSTHDR(&msg);
- while( cmsg ){
- switch(cmsg->cmsg_type){
- case HCI_CMSG_DIR:
- in = *((int *)CMSG_DATA(cmsg));
- break;
- }
- cmsg = CMSG_NXTHDR(&msg, cmsg);
- }
-
- ptr = data;
- type = *ptr++; len--;
- if( type < 0 || type > 4 )
- type = 0;
-
- switch (action) {
- case ANALYZE:
- printf("%c %s: ", (in ? '>' : '<'),
- hci_pkt_type[type] );
-
- analyze(type, ptr, len);
- break;
-
- case HEXDUMP:
- printf("%c type 0x%2.2x len %d\n",
- (in ? '>' : '<'),
- (__u8) type, len);
-
- hex_dump(" ", ptr, len);
- break;
- }
-
- fflush(stdout);
- }
+ close(s);
+ return 0;
}