I wrote a tool to parse some USB data. You put in the data packet into the tool, and it’ll translate it into something you can understand.
The reason why I made this tool is because some USB traffic sniffers do not perform parsing on USB packets (especially the freeware ones), but the binary data can still be obtained. This tool will traverse through the binary data, and translate it into something human-readable, using the official documents from USB.org. The three types of data this tool can handle are “USB Standard Descriptors”, “USB Standard Requests”, and “USB HID Report Descriptors”.
The “parse USB HID report descriptor” function is the reverse of the (horrible) “HID Descriptor Tool” provided by USB.org, and the display format is very similar.
Because USB devices are generally embedded devices, this tool is designed with the C programming language in mind. The output can be imported as an array initializer.
I was frustrated when I couldn’t find a tool for this, so I wrote it in hopes that it will become useful for everybody looking for such a tool.
Thank you for this. Great tool! I am using it to cross-check my own HID report descriptor parser.
I found a bug. In pCollection(s,v) the lookup table begins with “Undefined” and it should begin with “Physical” since that is the corresponding collection with ID = 0.
Cheers!
Thanks. Fixed as of now.
You might want to consider looking at UsbPcap , the project produced some dissectors that were included in the recent version of wireshark. While they do need improvement, and perhaps you might consider adding more functionality to them, they are quite nice for free, and since pcap format is very accessible, hopefully more analyzers will start dumping in that format natively.
I also wish Total Phase Data Center can export as pcap.
I use Wireshark very often for USB and Bluetooth but it’s a pain to generate *.pcap files since they are binary, I have to maintain several custom conversion scripts to do so. Sometimes I just want to do stuff in text/ASCII. I wish there was a XML or JSON format for pcap. (maybe there is and I haven’t found it)
I use my own parser mainly to generate sane C comments so it’s readable once I put it into C code.
Hi,
It is a great tool to decipher USB descriptors. Thank you!
I think possible_errors is incremented in pDeviceClass function regardless of whether the class is valid or not. Can you review your code?
Thanks!
Aki-
function pDeviceClass(c)
{
var tbl = [
“Use class information in the Interface Descriptors”,
…
“Vendor Specific”,
];
var str = “”;
if (c < tbl.length) {
str = tbl[c];
}
if (str != "") {
str = "(" + str + ")";
}
possible_errors++; <<<– increment the error regardlessly
return str;
}
Hi,
I tweaked the javascript locally so that possible_error is not incremented if the class is valid.
Now, the “guess” feature for a sample standard request descriptor:
81 06 00 22 00 00 D4 00
is no longer working correctly.
The script now thinks it is a standard Descriptor, not a standard Request Descriptor.
What I found was that the possible_error from standard Descriptor parser *was* 1 because of the above coding and after changing the code, both standard Descriptor parser and standard Request Descriptor parser produce 0 (means both legal) and the script thinks the input is a standard Descriptor.
Is there any way to penalize when the “81 06 00 22 00 00 D4 00” is being parsed as a standard Descriptor???
The decoded output (as a standard Descriptor) is bogus but seems legal.
Any suggestions would be greatly appreciated.
Aki-
fixed, easy, just had to detect when bLength was too long, thanks!
Hi,
Your parser seems covers a wide range of descriptor types.
But you didn’t cover a case for STRING descriptors.
I’m wondering why you omitted the case as adding the case requires only minuscule efforts.
Your comments on this would be greatly appreciated.
Aki-
No real reason why string descriptors were left out, it is not as useful to me. I might add it later.
Hi,
Me, again.
I think I found a bug in your code.
The bcd decoding was not correctly implemented.
The following bcdUSB case should be displayed as 1.10 but 1.16 was shown instead.
0x10, 0x01, // bcdUSB 1.16
Aki-
fixed, thanks!
Hey, thanks for the tool; it would be great if you could host the source on github or something. Also, I’d like to put this into a package for nodejs on npm. I sent you an email with a bit more info.
Heads up there there’s a very minor bug in your parser, the comments generated for logical and physical minimums don’t take into account negative numbers, e.g.
0x16, 0x00, 0x80, // Logical Minimum (32768)
… should be…
0x16, 0x00, 0x80, // Logical Minimum (-32768)
Thanks, fixed
Hi, Zhao, thanks for your tool. I’m now trying to develop a Force Feed Back joystick, and i almost did the same thing you do, i hope the PID (Physical Interface Device) usages can be add to the tool. I extract the definitions from the document “Device Class Definition for Physical Interface Devices (PID) Version 1.0” and that may be helpful to you:
https://github.com/beantowel/FFBMK1/blob/master/HID%20Descriptor%20tool/HID_PID_Descriptor_Definitions.py
Furthermore, i wonder if there is any tool could help the debugging in MCU programming, i mean, can we just test our code in some sort of simulation environment on PC and get debug imformation directly?
With this report descriptor:
05 01 09 04 A1 01 09 09 A1 00 05 01 09 30 09 31 09 32 09 33 09 34 09 35 09 40 09 41 09 42 09 46 95 0A 75 10 82 82 00 16 00 80 26 FF 7F C0 C0
Your script says the logical minimum should be -32768 as I’d expect, but lsusb and Linux joystick driver seem to interpret it as +32768. Any idea?
Awesome tool. I’m using it along with my DTImporter tool and between the two I can capture report descriptors from an existing device and check them for errors against USB.org’s HID Descriptor tool.
Here’s my DTImporter tool:
https://github.com/jdunne525/DTImporter
Hi everyone,
I use this tool when I need a quick HID dump. I even have this tool mentioned in my book (http://www.fysnet.net/the_universal_serial_bus.htm). Thank you to all whom have contributed to this tool.
However, I believe there is a bug in the code for HID parsing. If the code finds a “Report ID” field, it successfully parses and displays the ID, but incorrectly increments the position and skips the next byte. For example, here is the output for the first few bytes from my parser:
05 01 Usage Page (Generic Desktop)
09 02 Usage (Mouse)
A1 01 Collection (Application)
85 03 Report ID: 3
09 01 Usage (Pointer)
A1 00 Collection (Physical)
05 09 Usage Page (Button)
Here is the same sequence in the parser linked on this page:
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x03, // Report ID (3)
0x01, 0xA1, // Unknown (bTag: 0x00, bType: 0x00)
0x00, // Unknown (bTag: 0x00, bType: 0x00)
0x05, 0x09, // Usage Page (Button)
Notice that the 09 is skipped. I have not looked through the code to tell you where it is, but you might wish to look into this.
I can provide a complete HID Descriptor is needed.
Thank you,
Ben
I had a look at your code. It isn’t the Report ID as I thought. I used the following data:
05 01 09 02 A1 01 85 03-09 01 A1 00 05 09 19 01
Notice the negative sign between the 03 and the 09. This is the standard DOS debug output. Your code thinks the 09 is negative? Is this an error in the code or does it allow negative inputs? Is this something you might look for?
Thanks,
Ben
This tool is much easier for me to read than others I have seen! Would you mind providing a license for this code? I am planning to build some tools on top of it if that is okay.
Hey,
I wrote an own HID Report Deskriptor for my project and used your tool to debug and produce good looking Code.
Maybe you want to update the parser for touchscreens. There are some “new” Usages. They are Requested on this side: https://www.usb.org/sites/default/files/hutrr34.pdf
Especially these three worked for me and are Mandatory for multi-touch-devices.
0x51 Contact identifier
0x54 Contact count
0x55 Contact count maximum
Thank You for your nice Website
Shoreus
Hi Frank, I used this tool to help resolve a lot of difficulty I was having creating a custom HID device. Thank you so much!
Thank you for your tool; it is very helpful.
The following bytes:
0x27, 0xFF, 0xFF, 0x00, 0x00
are parsed as:
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534)
I believe this is incorrect and should be interpreted as:
// Logical Maximum (65535)
Agreed?
Thanks again for your work.
I had the same observation — I see no reason that the Logical Maximum should be interpreted as 65534 rather than 65535.
Hello Frank,
thanks, for providing this tool.
I noticed a small bug. Report-IDs seems to be handled as signed char, but they are unsigned chars. I got this:
0x85, 0xF3, // Report ID (-13)
instead
of
0x85, 0xF3, // Report ID (243)
KR Jörg
Shea’s comment about the logical maximum is correct. The problem is in pItemVal, which mishandles 4-byte values because Javascript ints are only 4 bytes long. Thus, (1 << (8*s)) ends up producing -1. The solution is to change the "else" to:
else if( s < 4 ) {
and move the "return" line out of the else. For 4-byte values, no adjustment is necessary.
This was a very useful tool, thanks! I’m debugging bogus report descriptors from a USB HID uninterruptible power supply — sending descriptors that indicate a range of 0..-1 such as:
0x05, 0x84, // Usage Page (Power Pages)
0x09, 0x12, // Usage (0x12)
0xA1, 0x00, // Collection (Physical)
0x95, 0x01, // Report Count (1)
0x85, 0x20, // Report ID (32)
0x05, 0x85, // Usage Page (Power Pages)
0x09, 0x85, // Usage (0x85)
0x75, 0x10, // Report Size (16)
0x15, 0x00, // Logical Minimum (0)
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534)
0x81, 0x22, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position)
0x09, 0x85, // Usage (0x85)
0xB1, 0xA2, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Volatile)
0x85, 0x21, // Report ID (33)
0x05, 0x84, // Usage Page (Power Pages)
0x09, 0x58, // Usage (0x58)
0x75, 0x08, // Report Size (8)
0x25, 0x06, // Logical Maximum (6)
0x81, 0xA2, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position)
0x09, 0x58, // Usage (0x58)
0xB1, 0xA2, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Volatile)
0x85, 0x22, // Report ID (34)
0x05, 0x85, // Usage Page (Power Pages)
0x09, 0x66, // Usage (0x66)
0x25, 0xFF, // Logical Maximum (-1)
0xB1, 0xA2, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Volatile)
0x85, 0x23, // Report ID (35)
0x09, 0x68, // Usage (0x68)
0x75, 0x10, // Report Size (16)
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534)
0x66, 0x01, 0x10, // Unit (System: SI Linear, Time: Seconds)
0xB1, 0xA2, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Volatile)
0x85, 0x24, // Report ID (36)
0x09, 0x2A, // Usage (0x2A)
0xB1, 0xA2, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Volatile)
0x85, 0x25, // Report ID (37)
0x05, 0x84, // Usage Page (Power Pages)
0x09, 0x40, // Usage (0x40)
0x67, 0x21, 0xD1, 0xF0, 0x00, // Unit (System: SI Linear, Length: Radians, Mass: Gram)
0x55, 0x05, // Unit Exponent (5)
0xB1, 0x22, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile)
0x85, 0x26, // Report ID (38)
0x09, 0x30, // Usage (0x30)
0xB1, 0xA2, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Volatile)
0xC0, // End Collection
(where I also noticed the 65534 vs 65535 bug in your decoder that others have mentioned previously)
Hi!
I noticed a bug in the units handling. When the report contains 0x65, 0x14 it reports “Unit (System: English Rotation, Length: Centimeter)” instad of “Unit (System: English Rotation, Length: Degrees)” (or perhaps Angle: Degrees). This is because in the pUnit() function you use “if (nib == […])” instead of “if (sysNib ==[…])”. You already created the variable, but then forgot to use it and used the nib variable instead. It is therefore using the current value of nib (which is the exponent) instead of the unit system.
HID Usage Tables are updated recently (version 1.22, year 2021).
Would you please release your code (though it is available on the html source) under an open source license?
Hi, I found a bug in the decoding of bcdDevice. In your example standard descriptor, 1.00 is decoded as 2.00.
0x00, 0x01, // bcdDevice 2.00
The fix is to delete the line
bcdDevice += inVals[I];
You likely forgot to remove this line when copying the fix for bcdUSB (where 1.10 was shown as 1.16).
Hi, I refactored the parsing of HID UsagePage and Usage using HidUsageTables.json, which comes from the official specification PDF file attachment, so as to update the latest specification. Since you did not create a git repository and could not submit a pull request, I published it at https://openbody.org/main/usbdescreqparser/