Friday, February 28, 2014

USB HID Report Descriptor Parser in Python

1 Introduction

This is a similar tool as HID Descriptor Tool that is avaliable in USB-IF. Not intended to re-create the wheel, my purpose is to quickly create an utility that can parse the following USB HID Report Descriptors:
  1. descriptors which are binaries
  2. descriptors for an USB Sensor HUB
A script language (python) is chosen because of the need of writing it in a quick way.

2 Usage

What the tool does is simply to parse the input files into items, and translate the data into human readable wordings. It is not a true parser; it doesn't parse items into hierarchical objects.
Usage:
% ./rd-parser.py -h
usage: rd-parser.py [-h] [-v] file

positional arguments:
  file           file path to the report descriptor

optional arguments:
  -h, --help     show this help message and exit
  -v, --verbose  increase output verbosity
Two types of files are supported:
  1. binary files
% hexdump mouse.bin
0000000 0105 0209 01a1 0109 00a1 0905 0119 0329
0000010 0015 0125 0395 0175 0281 0195 0575 0381
0000020 0105 3009 3109 8115 7f25 0875 0295 0681
0000030 c0c0
0000032

% ./rd-parser.py mouse.bin
Usage Page (Generic Desktop Controls)
Usage (Mouse)
Collection (Application)
    Usage (Pointer)
    Collection (Physical)
        Usage Page (Button)
        Usage Minimum (1)
        Usage Maximum (3)
        Logical Minimum (0)
        Logical Maximum (1)
        Report Count (3)
        Report Size (1)
        Input (Data, Variable, Absolute)
        Report Count (1)
        Report Size (5)
        Input (Constant, Variable, Absolute)
        Usage Page (Generic Desktop Controls)
        Usage (X)
        Usage (Y)
        Logical Minimum (-127)
        Logical Maximum (127)
        Report Size (8)
        Report Count (2)
        Input (Data, Variable, Relative)
    End Collection
End Collection
  1. hex strings
% cat keybrd.dat
05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 95 01 75 08 81 03 95 05 75 01 05 08 19 01 29 05 91 02 95 01 75 03 91 03 95 06 75 08 15 00 25 65 05 07 19 00 29 65 81 00 C0

% ./rd-parser.py keybrd.dat
Usage Page (Generic Desktop Controls)
Usage (Keyboard)
Collection (Application)
    Usage Page (Keyboard/Keypad)
    Usage Minimum (-32)
    Usage Maximum (-25)
    Logical Minimum (0)
    Logical Maximum (1)
    Report Size (1)
    Report Count (8)
    Input (Data, Variable, Absolute)
    Report Count (1)
    Report Size (8)
    Input (Constant, Variable, Absolute)
    Report Count (5)
    Report Size (1)
    Usage Page (LEDs)
    Usage Minimum (1)
    Usage Maximum (5)
    Output (Data, Variable, Absolute)
    Report Count (1)
    Report Size (3)
    Output (Constant, Variable, Absolute)
    Report Count (6)
    Report Size (8)
    Logical Minimum (0)
    Logical Maximum (101)
    Usage Page (Keyboard/Keypad)
    Usage Minimum (0)
    Usage Maximum (101)
    Input (Data, Array, Absolute)
End Collection
HID Sensor Usage Tables are supported.
% ./rd-parser.py -v st-sensor-hub.bin
05 20          : G- Usage Page (Sensor)
09 01          : L- Usage (Sensor Type Collection)
a1 01          : M- Collection (Application)
85 01          :     G- Report ID (1)
05 20          :     G- Usage Page (Sensor)
09 e1          :     L- Usage (Other: Custom)
a1 00          :     M- Collection (Physical)
05 20          :         G- Usage Page (Sensor)
0a 09 03       :         L- Usage (Sensor Connection Type)
15 00          :         G- Logical Minimum (0)
25 02          :         G- Logical Maximum (2)
75 08          :         G- Report Size (8)
95 01          :         G- Report Count (1)
a1 02          :         M- Collection (Logical)
0a 30 08       :             L- Usage (Connection Type: PC Integrated)
0a 31 08       :             L- Usage (Connection Type: PC Attached)
0a 32 08       :             L- Usage (Connection Type: PC External)
b1 00          :             M- Feature (Data, Array, Absolute)
c0             :         M- End Collection
0a 16 03       :         L- Usage (Reporting State)
15 00          :         G- Logical Minimum (0)
25 05          :         G- Logical Maximum (5)
...... omitted

3 Build the Win32 Executable

This would only be needed if you need a win32 executable, to be executed on a Windows without python installed.
Download and install pywin32 from sourceforge. Make sure to download the correct pywin32 package according to the version (and architecture) of python that is installed in your system. Please reference README.txt.
Download and install PyInstaller. For more details, see the PyInstaller manual.
Usage:
python pyinstaller.py /path/to/rd-parser.py
The win32 exectuable will be built under .\rd-parser\dist\rd-parser\rd-parser.exe. Please copy the rd-parser.exe along with python27.dll, and you shall able to run it on another Windows without installing python.
FYI, provide my executable that is built on a 32-bit Windows and is able to be executed under both 32-bit and 64-bit Windows.

4 Download the source code and the win32 executable

Date: 2014-02-27 Thu
Author: Winfred Lu
Created: 2014-02-28 Fri 23:06
Emacs 24.3.50.1 (Org mode 8.2.4)

1 comment:

Anonymous said...

Links to downloads no longer work :-(