Diff between eae7ac26253066b9dfabb638943a484c99658032 and 2d8aa0dd00646c084378b1d93b3a00fb33a01bdc

Changed Files

File Additions Deletions Status
tools/hcidump.c +23 -16 modified
tools/parser/csr.c +104 -0 added
tools/parser/hci.c +31 -4 modified
tools/parser/parser.c +7 -5 modified
tools/parser/parser.h +7 -2 modified

Full Patch

diff --git a/tools/hcidump.c b/tools/hcidump.c
index 3977308..659d730 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
@@ -65,6 +65,7 @@ enum {
 static int  device;
 static int  snap_len = SNAP_LEN;
 static int  defpsm = 0;
+static int  defcompid = DEFAULT_COMPID;
 static int  mode = PARSE;
 static long flags;
 static long filter;
@@ -332,6 +333,7 @@ static void usage(void)
 	"  -i, --device=hci_dev       HCI device\n"
 	"  -s, --snap-len=len         Snap len (in bytes)\n"
 	"  -p, --psm=psm              Default PSM\n"
+	"  -m, --manufacturer=compid  Default manufacturer\n"
 	"  -w, --save-dump=file       Save dump to a file\n"
 	"  -r, --read-dump=file       Read dump from a file\n"
 	"  -t, --ts                   Display time stamps\n"
@@ -347,19 +349,20 @@ static void usage(void)
 }
 
 static struct option main_options[] = {
-	{ "device",	1, 0, 'i' },
-	{ "snap-len",	1, 0, 's' },
-	{ "psm",	1, 0, 'p' },
-	{ "save-dump",	1, 0, 'w' },
-	{ "read-dump",	1, 0, 'r' },
-	{ "ts",		0, 0, 't' },
-	{ "ascii",	0, 0, 'a' },
-	{ "hex",	0, 0, 'x' },
-	{ "ext",	0, 0, 'X' },
-	{ "raw",	0, 0, 'R' },
-	{ "cmtp",	1, 0, 'C' },
-	{ "hcrp",	1, 0, 'H' },
-	{ "help",	0, 0, 'h' },
+	{ "device",		1, 0, 'i' },
+	{ "snap-len",		1, 0, 's' },
+	{ "psm",		1, 0, 'p' },
+	{ "manufacturer",	1, 0, 'm' },
+	{ "save-dump",		1, 0, 'w' },
+	{ "read-dump",		1, 0, 'r' },
+	{ "ts",			0, 0, 't' },
+	{ "ascii",		0, 0, 'a' },
+	{ "hex",		0, 0, 'x' },
+	{ "ext",		0, 0, 'X' },
+	{ "raw",		0, 0, 'R' },
+	{ "cmtp",		1, 0, 'C' },
+	{ "hcrp",		1, 0, 'H' },
+	{ "help",		0, 0, 'h' },
 	{ 0 }
 };
 
@@ -369,7 +372,7 @@ int main(int argc, char *argv[])
 
 	printf("HCIDump - HCI packet analyzer ver %s\n", VERSION);
 
-	while ((opt=getopt_long(argc, argv, "i:s:p:w:r:taxXRC:H:h", main_options, NULL)) != -1) {
+	while ((opt=getopt_long(argc, argv, "i:s:p:m:w:r:taxXRC:H:h", main_options, NULL)) != -1) {
 		switch(opt) {
 		case 'i':
 			device = atoi(optarg + 3);
@@ -383,6 +386,10 @@ int main(int argc, char *argv[])
 			defpsm = atoi(optarg);
 			break;
 
+		case 'm':
+			defcompid = atoi(optarg);
+			break;
+
 		case 'w':
 			mode = WRITE;
 			dump_file = strdup(optarg);
@@ -441,7 +448,7 @@ int main(int argc, char *argv[])
 
 	switch (mode) {
 	case PARSE:
-		init_parser(flags, filter, defpsm);
+		init_parser(flags, filter, defpsm, defcompid);
 		process_frames(device, open_socket(device), -1);
 		break;
 
@@ -450,7 +457,7 @@ int main(int argc, char *argv[])
 		break;
 
 	case READ:
-		init_parser(flags, filter, defpsm);
+		init_parser(flags, filter, defpsm, defcompid);
 		read_dump(open_file(dump_file, mode));
 		break;
 	}
diff --git a/tools/parser/csr.c b/tools/parser/csr.c
new file mode 100644
index 0000000..5f2ee4c
--- /dev/null
+++ b/tools/parser/csr.c
@@ -0,0 +1,104 @@
+/*
+ *
+ *  Bluetooth packet analyzer - CSR parser
+ *
+ *  Copyright (C) 2004  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ *  $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "parser.h"
+
+static char *cid2str(uint8_t cid)
+{
+	switch (cid & 0x3f) {
+	case 0:
+		return "BCSP Internal";
+	case 1:
+		return "BCSP Link";
+	case 2:
+		return "BCCMD";
+	case 3:
+		return "HQ";
+	case 4:
+		return "Device Mgt";
+	case 5:
+		return "HCI Cmd/Evt";
+	case 6:
+		return "HCI ACL";
+	case 7:
+		return "HCI SCO";
+	case 8:
+		return "L2CAP";
+	case 9:
+		return "RFCOMM";
+	case 10:
+		return "SDP";
+	case 11:
+		return "Debug";
+	case 12:
+		return "DFU";
+	case 13:
+		return "VM";
+	case 14:
+		return "Unused";
+	case 15:
+		return "Reserved";
+	default:
+		return "Unknown";
+	}
+}
+
+static char *frag2str(uint8_t frag)
+{
+	switch (frag & 0xc0) {
+	case 0x00:
+		return " middle fragment";
+	case 0x40:
+		return " first fragment";
+	case 0x80:
+		return " last fragment";
+	default:
+		return "";
+	}
+}
+
+void csr_dump(int level, struct frame *frm)
+{
+	uint8_t desc, cid;
+
+	desc = get_u8(frm);
+
+	cid = desc & 0x3f;
+
+	p_indent(level, frm);
+
+	printf("CSR: %s (channel %d)%s\n", cid2str(cid), cid, frag2str(desc));
+
+	raw_dump(level, frm);
+}
diff --git a/tools/parser/hci.c b/tools/parser/hci.c
index 9fcb6e6..9d001e3 100644
--- a/tools/parser/hci.c
+++ b/tools/parser/hci.c
@@ -39,6 +39,13 @@
 
 #include "parser.h"
 
+static uint16_t manufacturer = DEFAULT_COMPID;
+
+static inline uint16_t get_manufacturer(void)
+{
+	return (manufacturer == DEFAULT_COMPID ? parser.defcompid : manufacturer);
+}
+
 static char *event_map[] = {
 	"Unknown",
 	"Inquiry Complete",
@@ -329,31 +336,51 @@ static inline void command_dump(int level, struct frame *frm)
 	frm->ptr += HCI_COMMAND_HDR_SIZE;
 	frm->len -= HCI_COMMAND_HDR_SIZE;
 
+	if (ogf == OGF_VENDOR_CMD && ocf == 0 && get_manufacturer() == 10) {
+		csr_dump(level + 1, frm);
+		return;
+	}
+
 	raw_dump(level, frm);
 }
 
 static inline void event_dump(int level, struct frame *frm)
 {
 	hci_event_hdr *hdr = frm->ptr;
+	uint8_t event = hdr->evt;
 
 	if (p_filter(FILT_HCI))
 		return;
 
 	p_indent(level, frm);
 
-	if (hdr->evt <= EVENT_NUM)
+	if (hdr->evt <= EVENT_NUM) {
 		printf("HCI Event: %s (0x%2.2x) plen %d\n",
 			event_map[hdr->evt], hdr->evt, hdr->plen);
-	else if (hdr->evt == EVT_TESTING)
+	} else if (hdr->evt == EVT_TESTING) {
 		printf("HCI Event: Testing (0x%2.2x) plen %d\n", hdr->evt, hdr->plen);
-	else if (hdr->evt == EVT_VENDOR)
+	} else if (hdr->evt == EVT_VENDOR) {
 		printf("HCI Event: Vendor (0x%2.2x) plen %d\n", hdr->evt, hdr->plen);
-	else
+		if (get_manufacturer() == 10) {
+			frm->ptr += HCI_EVENT_HDR_SIZE;
+			frm->len -= HCI_EVENT_HDR_SIZE;
+			csr_dump(level + 1, frm);
+			return;
+		}
+	} else
 		printf("HCI Event: code 0x%2.2x plen %d\n", hdr->evt, hdr->plen);
 
 	frm->ptr += HCI_EVENT_HDR_SIZE;
 	frm->len -= HCI_EVENT_HDR_SIZE;
 
+	if (event == EVT_CMD_COMPLETE) {
+		evt_cmd_complete *cc = frm->ptr;
+		if (cc->opcode == cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION)) {
+			read_local_version_rp *rp = frm->ptr + EVT_CMD_COMPLETE_SIZE;
+			manufacturer = rp->manufacturer;
+		}
+	}
+
 	raw_dump(level, frm);
 }
 
diff --git a/tools/parser/parser.c b/tools/parser/parser.c
index 4863bb0..87f5cdf 100644
--- a/tools/parser/parser.c
+++ b/tools/parser/parser.c
@@ -38,15 +38,17 @@
 
 struct parser_t parser;
 
-void init_parser(unsigned long flags, unsigned long filter, unsigned int defpsm)
+void init_parser(unsigned long flags, unsigned long filter,
+		unsigned short defpsm, unsigned short defcompid)
 {
 	if ((flags & DUMP_RAW) && !(flags & DUMP_TYPE_MASK))
 		flags |= DUMP_HEX;
 
-	parser.flags  = flags;
-	parser.filter = filter;
-	parser.defpsm = defpsm;
-	parser.state  = 0;
+	parser.flags     = flags;
+	parser.filter    = filter;
+	parser.defpsm    = defpsm;
+	parser.defcompid = defcompid;
+	parser.state     = 0;
 }
 
 #define PROTO_TABLE_SIZE 20
diff --git a/tools/parser/parser.h b/tools/parser/parser.h
index ba16ee9..8999b41 100644
--- a/tools/parser/parser.h
+++ b/tools/parser/parser.h
@@ -64,6 +64,7 @@ struct frame {
 #define FILT_AVDTP	0x0200
 
 #define FILT_CAPI	0x00010000
+#define FILT_CSR	0x1000000f
 
 #define STRUCT_OFFSET(type, member)  ((uint8_t *)&(((type *)NULL)->member) - \
                                      (uint8_t *)((type *)NULL))
@@ -71,17 +72,20 @@ struct frame {
 #define STRUCT_END(type, member)     (STRUCT_OFFSET(type, member) + \
                                      sizeof(((type *)NULL)->member))
 
+#define DEFAULT_COMPID	65535
+
 struct parser_t {
 	unsigned long flags;
 	unsigned long filter;
-	unsigned int defpsm;
+	unsigned short defpsm;
+	unsigned short defcompid;
 	int state;
 };
 
 extern struct parser_t parser;
 
 void init_parser(unsigned long flags, unsigned long filter, 
-	unsigned int assume_psm);
+		unsigned short defpsm, unsigned short defcompid);
 
 static inline int p_filter(unsigned long f)
 {
@@ -172,6 +176,7 @@ void hcrp_dump(int level, struct frame *frm);
 void avdtp_dump(int level, struct frame *frm);
 
 void capi_dump(int level, struct frame *frm);
+void csr_dump(int level, struct frame *frm);
 
 static inline void parse(struct frame *frm)
 {