'How to tie together an HID USB descriptor and the USB frames actually sent on the bus
I'm trying to decipher data sent on the USB bus by an HID device (an Eaton power supply to be precise)
Using Wireshark, I can capture the USB traffic. When the device is connected, I can see the HID descriptor being sent. I can parse it alright, and thanks to an external reference (http://networkupstools.org/protocols/mge/NUT_MGE_USB_Devices_Draft_AA.pdf and http://www.usb.org/developers/docs/devclass_docs/pdcv10.pdf), I've got some info regarding the different fields of the descriptor.
However, I can't seem to link the descriptor to the data inside the frames I actually capture with Wireshark: I can't really make out any clear header or pattern in the messages, tied to the descriptor. In this case, I see quite a bunch of URB Control Response messages, which probably contain the data I want, but which message contains which info is unclear.
Does anyone have some sort of method to reverse-engineer and parse the data sent by a USB HID device ?
Thanks
Solution 1:[1]
I wrote a bit of code a while back to help me decode HID report descriptors and to create C language structure definitions to describe each report. What I would do is:
- capture the USB data using Wireshark
- filter on "usb.request_in"
- select the "GET DESCRIPTOR Response HID Report" packet
- right-click the "HID Report" and choose "Copy" and "...as a Hex Stream"
Now run the decoding software and paste the hex stream after the "-c" option. For example:
rexx rd.rex -c 05010906a101854b050719e029e7250175019508810275089501810326ff0019002aff0081007501950305081901290325019102750595019103c005010902a1010901a100854d09301581257f750895018106c0c0
It will by default print the C-structures (see below). If you want to also decode the HID report descriptors then use the "-d" option.
//--------------------------------------------------------------------------------
// Keyboard/Keypad Page inputReport 4B (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x4B (75) 'K'
// Collection: Keyboard
uint8_t KB_KeyboardKeyboardLeftControl : 1; // Usage 0x000700E0: Keyboard Left Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftShift : 1; // Usage 0x000700E1: Keyboard Left Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftAlt : 1; // Usage 0x000700E2: Keyboard Left Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftGui : 1; // Usage 0x000700E3: Keyboard Left GUI, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightControl : 1; // Usage 0x000700E4: Keyboard Right Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightShift : 1; // Usage 0x000700E5: Keyboard Right Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightAlt : 1; // Usage 0x000700E6: Keyboard Right Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightGui : 1; // Usage 0x000700E7: Keyboard Right GUI, Value = 0 to 1
uint8_t pad_2; // Pad
uint8_t KB_Keyboard; // Value = 0 to 255
} inputReport4B_t;
//--------------------------------------------------------------------------------
// LED Indicator Page outputReport 4B (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x4B (75) 'K'
// Collection: Keyboard
uint8_t LED_KeyboardNumLock : 1; // Usage 0x00080001: Num Lock, Value = 0 to 1
uint8_t LED_KeyboardCapsLock : 1; // Usage 0x00080002: Caps Lock, Value = 0 to 1
uint8_t LED_KeyboardScrollLock : 1; // Usage 0x00080003: Scroll Lock, Value = 0 to 1
uint8_t : 5; // Pad
} outputReport4B_t;
//--------------------------------------------------------------------------------
// Generic Desktop Page inputReport 4D (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x4D (77) 'M'
// Collection: Mouse Pointer
int8_t GD_MousePointerX; // Usage 0x00010030: X, Value = -127 to 127
} inputReport4D_t;
Now that you have a clear idea of the possible reports that may be flowing, you can go back to your Wireshark trace (still filtered on "usb.request_in") and select "URB_INTERRUPT in" packets. The "Leftover Capture Data" should contain the payload as described by one of the C structures.
Hope this helps.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
