0
votes

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

1

1 Answers

2
votes

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.