Diff between b6442a63bd405bb16516edf9211139a3d403d241 and 7a12d391ef572783b6a02194cfdab266fcfacf17

Changed Files

File Additions Deletions Status
tools/hcidump.c +198 -0 added

Full Patch

diff --git a/tools/hcidump.c b/tools/hcidump.c
new file mode 100644
index 0000000..9e54cbc
--- /dev/null
+++ b/tools/hcidump.c
@@ -0,0 +1,198 @@
+/* 
+	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 <termios.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <string.h>
+
+#include <asm/types.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+#define HEXDUMP		0
+#define ANALYZE		1
+
+/* Default options */
+int action = ANALYZE;
+
+char * hci_pkt_type[] = {
+	"Unknown ",
+	"Command ",
+	"ACL Data",
+	"SCO Data",
+	"Event   "
+};
+
+void usage(void)
+{
+	printf("HCIDump - HCI packet analyzer ver %s\n", VERSION);
+	printf("Usage:\n");
+	printf("\thcidump <-i hciX> [-h]\n");
+}
+
+void hex_dump(char *pref, unsigned char *buf, int len)
+{
+	register 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) ){
+			printf("%s%s\n", pref, line);
+			ptr = line; *ptr = 0;
+		}
+	}
+	if( line[0] )
+		printf("%s%s\n", pref, line);
+}
+
+void inline event_dump(void *ptr, int len)
+{
+	hci_event_hdr *hdr = ptr;
+	printf("  code: 0x%x plen: %d\n", hdr->evt, hdr->plen);
+}
+
+void analyze(int type, unsigned char *ptr, int len)
+{
+	switch( type ){
+		case HCI_EVENT_PKT:
+			event_dump(ptr, len);
+			break;
+	}
+}
+
+extern int optind,opterr,optopt;
+extern char *optarg;
+
+int main(int argc, char *argv[])
+{
+	char data[4096], ctrl[100], *ptr;
+	int s, len, type, opt, dev, in;
+	struct sockaddr_hci addr;
+	struct cmsghdr *cmsg;
+	struct msghdr msg;
+	struct iovec  iv;
+
+	dev = 0;
+	while( (opt=getopt(argc, argv,"i:h")) != EOF ) {
+		switch(opt) {
+			case 'i':
+				dev = atoi(optarg+3);
+				break;
+
+			case 'h':
+				action = HEXDUMP;
+				break;
+
+			case 'a':
+				action = ANALYZE;
+				break;
+
+			default:
+				usage();
+				exit(1);
+		}
+	}
+
+	/* Create HCI socket */
+	if( (s=socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0 ) {
+		perror("Can't create HCI socket");
+		exit(1);
+	}
+	
+	opt = 1;
+	if( setsockopt(s, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0 ) {
+		perror("Can't enable data direction info");
+		exit(1);
+	}
+
+	/* Bind socket to the HCI device */
+	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);
+		exit(1);
+	}
+
+	printf("HCIDump version %s\n", VERSION);
+
+	while( 1 ) {
+		iv.iov_base = data;
+		iv.iov_len  = sizeof(data);
+
+		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;
+
+		printf("%c %s(0x%2.2x), len %d\n", 
+			(in ? '>' : '<'), hci_pkt_type[type], (__u8)type, len);
+
+		switch( action ){
+			case ANALYZE:
+				analyze(type, ptr, len);
+				break;
+
+			case HEXDUMP:
+				hex_dump("  ", ptr, len);
+				break;
+		}
+
+		fflush(stdout);
+	}
+}