Skip to main content

python-hid-parser

checks tests codecov PyPI version

Typed pure Python library to parse HID report descriptors

Example

>>> import hid_parser
>>> simple_mouse_rdesc_raw = [
...     0x05, 0x01,  # .Usage Page (Generic Desktop)        0
...     0x09, 0x02,  # .Usage (Mouse)                       2
...     0xa1, 0x01,  # .Collection (Application)            4
...     0x09, 0x02,  # ..Usage (Mouse)                      6
...     0xa1, 0x02,  # ..Collection (Logical)               8
...     0x09, 0x01,  # ...Usage (Pointer)                   10
...     0xa1, 0x00,  # ...Collection (Physical)             12
...     0x05, 0x09,  # ....Usage Page (Button)              14
...     0x19, 0x01,  # ....Usage Minimum (1)                16
...     0x29, 0x03,  # ....Usage Maximum (3)                18
...     0x15, 0x00,  # ....Logical Minimum (0)              20
...     0x25, 0x01,  # ....Logical Maximum (1)              22
...     0x75, 0x01,  # ....Report Size (1)                  24
...     0x95, 0x03,  # ....Report Count (3)                 26
...     0x81, 0x02,  # ....Input (Data,Var,Abs)             28
...     0x75, 0x05,  # ....Report Size (5)                  30
...     0x95, 0x01,  # ....Report Count (1)                 32
...     0x81, 0x03,  # ....Input (Cnst,Var,Abs)             34
...     0x05, 0x01,  # ....Usage Page (Generic Desktop)     36
...     0x09, 0x30,  # ....Usage (X)                        38
...     0x09, 0x31,  # ....Usage (Y)                        40
...     0x15, 0x81,  # ....Logical Minimum (-127)           42
...     0x25, 0x7f,  # ....Logical Maximum (127)            44
...     0x75, 0x08,  # ....Report Size (8)                  46
...     0x95, 0x02,  # ....Report Count (2)                 48
...     0x81, 0x06,  # ....Input (Data,Var,Rel)             50
...     0xc0,        # ...End Collection                    52
...     0xc0,        # ..End Collection                     53
...     0xc0,        # .End Collection                      54
... ]
>>> rdesc = hid_parser.ReportDescriptor(simple_mouse_rdesc_raw)
>>> rdesc.get_input_report_size()
3bytes
>>> for item in rdesc.get_input_items():
...     print(item)
...
VariableItem(offset=0bits, size=1bit, usage=Usage(page=Button, usage=Button 1 (primary/trigger)))
VariableItem(offset=1bit, size=1bit, usage=Usage(page=Button, usage=Button 2 (secondary)))
VariableItem(offset=2bits, size=1bit, usage=Usage(page=Button, usage=Button 3 (tertiary)))
PaddingItem(offset=3bits, size=5bits)
VariableItem(offset=1byte, size=1byte, usage=Usage(page=Generic Desktop Controls, usage=X))
VariableItem(offset=2bytes, size=1byte, usage=Usage(page=Generic Desktop Controls, usage=Y))
>>> for usage, value in rdesc.parse_input_report([0b10100000, 0x50, 0x60]):
...     print(f'{usage} = {value}')
...
Usage(page=Button, usage=Button 2 (secondary)) = False
Usage(page=Button, usage=Button 3 (tertiary)) = True
Usage(page=Button, usage=Button 1 (primary/trigger)) = True
Usage(page=Generic Desktop Controls, usage=X) = 80
Usage(page=Generic Desktop Controls, usage=Y) = 96
>>> import hid_parser
>>> keyboard_rdesc_raw = [
...     0x05, 0x01,        # Usage Page (Generic Desktop)        0
...     0x09, 0x06,        # Usage (Keyboard)                    2
...     0xa1, 0x01,        # Collection (Application)            4
...     0x05, 0x07,        #  Usage Page (Keyboard)              6
...     0x19, 0xe0,        #  Usage Minimum (224)                8
...     0x29, 0xe7,        #  Usage Maximum (231)                10
...     0x15, 0x00,        #  Logical Minimum (0)                12
...     0x25, 0x01,        #  Logical Maximum (1)                14
...     0x75, 0x01,        #  Report Size (1)                    16
...     0x95, 0x08,        #  Report Count (8)                   18
...     0x81, 0x02,        #  Input (Data,Var,Abs)               20
...     0x95, 0x01,        #  Report Count (1)                   22
...     0x75, 0x08,        #  Report Size (8)                    24
...     0x81, 0x01,        #  Input (Cnst,Arr,Abs)               26
...     0x95, 0x03,        #  Report Count (3)                   28
...     0x75, 0x01,        #  Report Size (1)                    30
...     0x05, 0x08,        #  Usage Page (LEDs)                  32
...     0x19, 0x01,        #  Usage Minimum (1)                  34
...     0x29, 0x03,        #  Usage Maximum (3)                  36
...     0x91, 0x02,        #  Output (Data,Var,Abs)              38
...     0x95, 0x05,        #  Report Count (5)                   40
...     0x75, 0x01,        #  Report Size (1)                    42
...     0x91, 0x01,        #  Output (Cnst,Arr,Abs)              44
...     0x95, 0x06,        #  Report Count (6)                   46
...     0x75, 0x08,        #  Report Size (8)                    48
...     0x15, 0x00,        #  Logical Minimum (0)                50
...     0x26, 0xff, 0x00,  #  Logical Maximum (255)              52
...     0x05, 0x07,        #  Usage Page (Keyboard)              55
...     0x19, 0x00,        #  Usage Minimum (0)                  57
...     0x2a, 0xff, 0x00,  #  Usage Maximum (255)                59
...     0x81, 0x00,        #  Input (Data,Arr,Abs)               62
...     0xc0,              # End Collection                      64
... ]
>>> rdesc = hid_parser.ReportDescriptor(keyboard_rdesc_raw)
>>> for item in rdesc.get_input_items():
...     print(item)
...
VariableItem(offset=0bits, size=1bit, usage=Usage(page=Keyboard/Keypad, usage=Keyboard LeftControl))
VariableItem(offset=1bit, size=1bit, usage=Usage(page=Keyboard/Keypad, usage=Keyboard LeftShift))
VariableItem(offset=2bits, size=1bit, usage=Usage(page=Keyboard/Keypad, usage=Keyboard LeftAlt))
VariableItem(offset=3bits, size=1bit, usage=Usage(page=Keyboard/Keypad, usage=Keyboard Left GUI))
VariableItem(offset=4bits, size=1bit, usage=Usage(page=Keyboard/Keypad, usage=Keyboard RightControl))
VariableItem(offset=5bits, size=1bit, usage=Usage(page=Keyboard/Keypad, usage=Keyboard RightShift))
VariableItem(offset=6bits, size=1bit, usage=Usage(page=Keyboard/Keypad, usage=Keyboard RightAlt))
VariableItem(offset=7bits, size=1bit, usage=Usage(page=Keyboard/Keypad, usage=Keyboard Right GUI))
PaddingItem(offset=1byte, size=1byte)
ArrayItem(
    offset=2bytes, size=1byte, count=6,
    usages=[
        Usage(page=Keyboard/Keypad, usage=No event indicated),
        ...
        Usage(page=Keyboard/Keypad, usage=0x00ff),
    ],
)
>>> for usage, value in rdesc.parse_input_report([0b10100101, 0x00, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00]):
...     print(f'{usage} = {value}')
...
Usage(page=Keyboard/Keypad, usage=Keyboard Left GUI) = 0
Usage(page=Keyboard/Keypad, usage=Keyboard LeftAlt) = 1
Usage(page=Keyboard/Keypad, usage=Keyboard RightControl) = 0
Usage(page=Keyboard/Keypad, usage=Keyboard RightShift) = 1
Usage(page=Keyboard/Keypad, usage=Keyboard RightAlt) = 0
Usage(page=Keyboard/Keypad, usage=Keyboard Right GUI) = 1
Usage(page=Keyboard/Keypad, usage=Keyboard a and A) = True
Usage(page=Keyboard/Keypad, usage=Keyboard b and B) = True
Usage(page=Keyboard/Keypad, usage=Keyboard c and C) = True
Usage(page=Keyboard/Keypad, usage=Keyboard LeftShift) = 0
Usage(page=Keyboard/Keypad, usage=Keyboard LeftControl) = 1
>>> import hid_parser
>>> vendor_command_rdesc_raw = [
...     0x06, 0x00, 0xff,  # .Usage Page (Vendor Defined Page 1)  0
...     0x09, 0x01,        # .Usage (Vendor Usage 1)              3
...     0xa1, 0x01,        # .Collection (Application)            5
...     0x85, 0x10,        # ..Report ID (16)                     7
...     0x75, 0x08,        # ..Report Size (8)                    9
...     0x95, 0x06,        # ..Report Count (6)                   11
...     0x15, 0x00,        # ..Logical Minimum (0)                12
...     0x26, 0xff, 0x00,  # ..Logical Maximum (255)              15
...     0x09, 0x01,        # ..Usage (Vendor Usage 1)             18
...     0x81, 0x00,        # ..Input (Data,Arr,Abs)               20
...     0x09, 0x01,        # ..Usage (Vendor Usage 1)             22
...     0x91, 0x00,        # ..Output (Data,Arr,Abs)              24
...     0xc0,              # .End Collection                      26
... ]
>>> rdesc = hid_parser.ReportDescriptor(vendor_command_rdesc_raw)
>>> rdesc.get_input_report_size(0x10)
6bytes
>>> for item in rdesc.get_input_items(0x10):
...     print(item)
...
ArrayItem(
    offset=0bits, size=1byte, count=6,
    usages=[
        Usage(page=Vendor Page, usage=0x0001),
    ],
)
>>> for usage, value in rdesc.parse_input_report([0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]))
...     print(f'{usage} = {value}')
...
Usage(page=Vendor Page, usage=0x0001) = 257
Usage(page=Vendor Page, usage=0x0002) = 514
Usage(page=Vendor Page, usage=0x0003) = 771
Usage(page=Vendor Page, usage=0x0004) = 1028
Usage(page=Vendor Page, usage=0x0005) = 1285
Usage(page=Vendor Page, usage=0x0006) = 1542

Metadata

Release files for hid-parser 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hid-parser 0.1.0
File Size Uploaded
hid_parser-0.1.0.tar.gz 36.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hid-parser 0.1.0
File Interpreter ABI Platform
hid_parser-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 63.0 kB

Release files / hid_parser-0.1.0.tar.gz

Download URL hid_parser-0.1.0.tar.gz
Size 36.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e7e96dd7c91772cf2de528e1200c40e571d9a5277ff4e6e04fe82dce1be5db99
BLAKE2b-256 checksum
How to use checksums
d1c80f496dd0fd047c1796c73bdf713d954a28245d8af6f97c4b16105235942c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.3

Release files / hid_parser-0.1.0-py3-none-any.whl

Download URL hid_parser-0.1.0-py3-none-any.whl
Size 26.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
65111ea2eefb44e526f30e126db626ad6c6a8b83366573670cc07cffb3931665
BLAKE2b-256 checksum
How to use checksums
1aea956a1545c6e2602b6dca99924859e33fcbbf4d3532e7a2fc65f3918e7363
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page