'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