diff --git a/tools/hcidump.c b/tools/hcidump.c
index 3977308..659d730 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
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;
" -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"
}
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 }
};
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);
defpsm = atoi(optarg);
break;
+ case 'm':
+ defcompid = atoi(optarg);
+ break;
+
case 'w':
mode = WRITE;
dump_file = strdup(optarg);
switch (mode) {
case PARSE:
- init_parser(flags, filter, defpsm);
+ init_parser(flags, filter, defpsm, defcompid);
process_frames(device, open_socket(device), -1);
break;
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
+/*
+ *
+ * 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
#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",
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
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
#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))
#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)
{
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)
{