hid
stableEncode and decode USB HID reports, parse HID report descriptors, and look up usage page names, usage names, and vendor identifiers.
use plugin hid::{encode_report, decode_report, usage_page_name, …} Functions (11)
- encode_report Prepend report ID to data bytes
- decode_report Split bytes into report ID and data
- usage_page_name Look up HID usage page name by ID
- usage_name Look up HID usage name by page and usage ID
- report_type_name Map report type integer to name string
- parse_short_item Parse one HID descriptor short item
- build_device_info Build a device info table from IDs and strings
- vendor_name Look up well-known USB vendor name by vendor ID
- parse_keyboard_report Parse an 8-byte standard keyboard HID report
- parse_mouse_report Parse a 3–4 byte standard mouse HID report
- parse_descriptor Parse all items from a full HID report descriptor
Overview
hid is a pure-data toolkit for working with the USB Human Interface Device
protocol without touching any real hardware. It operates entirely on byte
sequences and integers: you hand it the raw bytes of a report or a report
descriptor and it gives you back plain Zolo tables, and it turns the magic
numbers in the HID spec (usage pages, usages, vendor IDs, report types) into
readable names. There is no stateful device handle to open or close — every
function is a stand-alone, side-effect-free transform.
Use it whenever you are decoding captured HID traffic, building or inspecting report descriptors, presenting keyboard and mouse reports in human terms, or labelling a device from its vendor and product identifiers.
Common patterns
Decode a captured input report and label its parts:
use plugin hid::{decode_report, report_type_name}
let raw = [0x01, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00]
let r = decode_report(raw)
print("report id {r["id"]} ({report_type_name(1)})")
Turn a raw keyboard report into a readable description:
use plugin hid::{parse_keyboard_report}
let report = [0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00]
let kb = parse_keyboard_report(report)
if kb["modifiers"]["left_shift"] {
print("shift held, keycode {kb["keys"][1]}")
}
Identify a device and name the usage page it reports on:
use plugin hid::{build_device_info, vendor_name, usage_page_name}
let dev = build_device_info(0x046D, 0xC52B, "Logitech", "Unifying Receiver")
print("{vendor_name(dev["vendor_id"])} {dev["product_hex"]}")
print("reports on: {usage_page_name(0x01)}")
Prepend report ID to data bytes
Prepends the report_id byte to data, producing a complete HID output report byte sequence (returned as bytes).
use plugin hid::{encode_report}
let report = encode_report(1, [0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00])
print(report.len())
Split bytes into report ID and data
Splits a raw HID report byte sequence into {id, data} where id is the first byte and data is the remainder.
use plugin hid::{encode_report, decode_report}
let raw = encode_report(2, [0x01, 0x00, 0x10])
let r = decode_report(raw)
print(r["id"])
Look up HID usage page name by ID
Returns the human-readable name of an HID usage page by its numeric ID, such as "Generic Desktop" (0x01) or "Keyboard/Keypad" (0x07).
use plugin hid::{usage_page_name}
print(usage_page_name(0x01))
print(usage_page_name(0x0C))
Look up HID usage name by page and usage ID
Returns the usage name for a given usage page and usage ID combination. Covers Generic Desktop axes, buttons, consumer controls, and LED indicators.
use plugin hid::{usage_name}
print(usage_name(0x01, 0x30))
print(usage_name(0x0C, 0xCD))
Any usage on the Button page (0x09) is named positionally, so button index 1
becomes "Button 1":
use plugin hid::{usage_name}
print(usage_name(0x09, 1))
print(usage_name(0x09, 5))
Map report type integer to name string
Maps a report type integer (1, 2, or 3) to its name: "Input", "Output", or "Feature".
use plugin hid::{report_type_name}
print(report_type_name(1))
print(report_type_name(3))
Parse one HID descriptor short item
Parses the first HID descriptor short item from bytes. Returns {type, tag, size, data} where type is "Main", "Global", or "Local" and tag is the item name.
use plugin hid::{parse_short_item}
let item = parse_short_item([0x05, 0x01])
print(item["type"])
print(item["tag"])
The two low bits of the prefix encode the data size, so a Usage Page item with a
one-byte payload reports size 1 and carries that byte in data:
use plugin hid::{parse_short_item}
let item = parse_short_item([0x05, 0x01])
print("{item["tag"]} size={item["size"]}")
Build a device info table from IDs and strings
Builds a device info table containing vendor_id, product_id, vendor_hex, product_hex, manufacturer, and product fields.
use plugin hid::{build_device_info, vendor_name}
let dev = build_device_info(0x046D, 0xC52B, "Logitech", "Unifying Receiver")
print(dev["vendor_hex"])
print(vendor_name(dev["vendor_id"]))
Look up well-known USB vendor name by vendor ID
Returns the well-known company name for a USB vendor ID. Covers common vendors including Logitech, Microsoft, Apple, Sony, Razer, Arduino, and others.
use plugin hid::{vendor_name}
print(vendor_name(0x046D))
print(vendor_name(0x2341))
Parse an 8-byte standard keyboard HID report
Parses a standard 8-byte USB keyboard HID report. Returns {modifiers, modifiers_raw, keys} where modifiers has named boolean fields (left_ctrl, left_shift, etc.) and keys is a list of active keycodes.
use plugin hid::{parse_keyboard_report}
let report = [0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00]
let parsed = parse_keyboard_report(report)
print(parsed["modifiers"]["left_shift"])
print(parsed["keys"][1])
Parse a 3–4 byte standard mouse HID report
Parses a standard 3–4 byte USB mouse HID report. Returns {left, right, middle, buttons_raw, dx, dy, wheel}.
use plugin hid::{parse_mouse_report}
let report = [0x01, 0x05, 0xFF, 0x00]
let m = parse_mouse_report(report)
print(m["left"])
print(m["dx"])
The X and Y deltas are signed, so a high byte like 0xFF decodes as -1 rather
than 255, and the optional fourth byte carries the scroll wheel:
use plugin hid::{parse_mouse_report}
let m = parse_mouse_report([0x00, 0xFF, 0x01, 0xFF])
print("dx {m["dx"]} dy {m["dy"]} wheel {m["wheel"]}")
Parse all items from a full HID report descriptor
Iterates all short items in a complete HID report descriptor byte sequence. Returns a list of items each with type, tag, size, value, data, and offset.
use plugin hid::{parse_descriptor}
let items = parse_descriptor(descriptor_bytes)
print(items[1]["tag"])
print(items[1]["value"])
Each item also carries the little-endian numeric value and its byte offset,
so you can walk a short descriptor and label every entry by usage page name:
use plugin hid::{parse_descriptor, usage_page_name}
let items = parse_descriptor([0x05, 0x01, 0x09, 0x02])
print("{items[1]["tag"]} = {usage_page_name(items[1]["value"])}")
print("{items[2]["tag"]} at offset {items[2]["offset"]}")