From 2d8aa0dd00646c084378b1d93b3a00fb33a01bdc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 26 Aug 2004 23:59:20 +0000 Subject: [PATCH] hcidump: Add CSR parser --- tools/hcidump.c | 39 +++++++++------- tools/parser/csr.c | 104 ++++++++++++++++++++++++++++++++++++++++++ tools/parser/hci.c | 35 ++++++++++++-- tools/parser/parser.c | 12 +++-- tools/parser/parser.h | 9 +++- 5 files changed, 172 insertions(+), 27 deletions(-) create mode 100644 tools/parser/csr.c diff --git a/tools/hcidump.c b/tools/hcidump.c index 3977308e4..659d730ea 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 000000000..5f2ee4cc9 --- /dev/null +++ b/tools/parser/csr.c @@ -0,0 +1,104 @@ +/* + * + * Bluetooth packet analyzer - CSR parser + * + * Copyright (C) 2004 Marcel Holtmann + * + * + * 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 +#include +#include +#include +#include + +#include +#include + +#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 9fcb6e68f..9d001e3e6 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 4863bb0c3..87f5cdf83 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 ba16ee93b..8999b411f 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) { -- 2.47.3