Expand description
A wrapper around the HID Usage Tables (HUT).
In this document and unless stated otherwise, a reference to
- “HID Section a.b.c” refers to the HID Device Class Definition for HID 1.11
- “HUT Section a.b.c” refers to the HID Usage Tables (HUT) version 1.5
This module is created through code generation from the HID Usage Tables.
§Terminology
See HID Section 5.5: a HID Usage is a 32 bit value comprising of a 16-bit Usage Page (MSB) and a 16-bit Usage ID (LSB) so that:
let usage: u32 = (usage_page << 16) | usage_id;
Note that the HID encoding requires little endian byte order on the wire.
In this module:
- “Usage Page” refers to the 16-bit value. Where the Usage Page is converted
to or from a 32-bit value the Usage Page is in the upper 16 bits of that value and
the lower 16 bits are ignored or set to zero.
let usage_page: u16 = (usage >> 16) as u16 & 0xffff;
- “Usage ID” refers to the 16-bit value. Where the Usage ID is converted to
or from a 32-bit value the Usage is in the lower 16 bits of that value and
the upper 16 bits are ignored or set to zero.
let usage_id: u16 = (usage & 0xffff) as u16;
- “Usage” refers to the 32-bit value comprising a Usage Page and a Usage.
§Converting between types
All defined Usages and UsagePages implement AsUsagePage and (if applicable) AsUsage as
well as the From<u16>
, From<u32>
, TryFrom<u16>
, and TryFrom<u32>
conversions so that:
let usage_page_value: u16 = 0x01; // Generic Desktop
let usage_id_value: u16 = 0x02; // Mouse
let usage_value: u32 = (usage_page_value as u32) << 16 | usage_id_value as u32;
// Create a known Usage from a 32-bit value
let u: Usage = Usage::try_from(usage_value).unwrap();
assert!(matches!(u, Usage::GenericDesktop(GenericDesktop::Mouse)));
// Create a known Usage from the Usage Page and Usage ID values
let u2 = Usage::new_from_page_and_id(usage_page_value, usage_id_value).unwrap();
assert_eq!(u, u2);
// Create a known Usage from an individual Usage Page enum item
let u3 = Usage::from(GenericDesktop::Mouse);
assert_eq!(u, u3);
// Create a known Usage from an known Usage Page enum item
let gd_mouse = GenericDesktop::try_from(usage_id_value).unwrap();
let u4 = Usage::from(gd_mouse);
assert_eq!(u, u4);
// Convert to and fro the Usage either via u32 or the AsUsage trait
let u = GenericDesktop::Mouse;
assert_eq!(u32::from(&u), usage_value);
assert_eq!(u.usage_value(), usage_value);
// Extract the 16-bit Usage ID either via u16 or the AsUsage trait
assert_eq!(u16::from(&u), usage_id_value);
assert_eq!(u.usage_id_value(), usage_id_value);
// Extract the Usage Page from the Usage enum value
let up = u.usage_page();
assert!(matches!(up, UsagePage::GenericDesktop));
let up: UsagePage = UsagePage::from(&u);
assert!(matches!(up, UsagePage::GenericDesktop));
// Get the Usage Page numeric value is via the AsUsagePage
assert_eq!(u16::from(&up), usage_page_value);
assert_eq!(up.usage_page_value(), usage_page_value);
Naming Usages (e.g. GenericDesktop::Mouse
) above works for Defined Usage
Pages, Generated Usage Pages (see below) need to be destructured via their
individual elements:
let usage_page_value: u16 = 0x09; // Button
let usage_id_value: u16 = 8; // Button number 8
let usage_value: u32 = (usage_page_value as u32) << 16 | usage_id_value as u32;
let u = Usage::try_from(usage_value).unwrap();
let button = Usage::Button(Button::Button(8));
assert!(matches!(Usage::try_from(usage_value).unwrap(), button));
// or via from() or into()
let button: Usage = Button::Button(8).into();
assert!(matches!(Usage::try_from(usage_value).unwrap(), button));
Once a Usage is created, the AsUsagePage and AsUsage traits and conversion to and from u16 and u32 work the same as for a Defined Usage Page.
§Names of Usage Pages and Usage IDs
All defined Usages and UsagePages implement name()
to return a string
representing that page or usage:
let up = UsagePage::GenericDesktop;
assert_eq!(up.name(), "Generic Desktop");
let up = UsagePage::SimulationControls;
assert_eq!(up.name(), "Simulation Controls");
let usage = GenericDesktop::Mouse;
assert_eq!(usage.name(), "Mouse");
let usage = SimulationControls::CyclicControl;
assert_eq!(usage.name(), "Cyclic Control");
§Generated Usage Pages
The HUT differ between “Defined” and “Generated” Usage Pages. The former define Usage ID values and their meanings, the latter define a Usage ID range, with the actual Usage ID simply referring to “nth thing in this usage page”. One example for this is the Button Usage Page (0x09) where a Usage ID of 3 means “Button 3”.
let b = Button::Button(3);
let o = Ordinal::Ordinal(23);
Unlike Defined Usage Pages these Generated Usage Pages need to be destructured in match
statements:
let b = Button::Button(3);
match b {
Button::Button(b) => println!("Button {b}"),
_ => {},
}
The following usage pages are Generated:
- Usage Page 0x9 - Button
- Usage Page 0xA - Ordinal
- Usage Page 0x10 - Unicode
- Usage Page 0x81 - MonitorEnumerated
A further special case of this is the Unicode usage page which is not in the HUT document and was inserted during code generation.
§Vendor Defined Usage Pages (0xFF00 to 0xFFFF)
Vendor Defined Usage Pages and VendorUsages are not autogenerated and thus
follow a different approach: the Usage inside the Usage Page is a simple
numeric usage that needs to be destructured in match
statements.
let v = Usage::VendorDefinedPage {
vendor_page: VendorPage::try_from(0xff00 as u16).unwrap(),
usage: VendorDefinedPage::VendorUsage { usage_id: 0x01 },
};
match v {
Usage::VendorDefinedPage {
vendor_page,
usage,
} => println!("Vendor Usage ID {usage}"),
_ => {},
}
A notable exception is the Wacom (0xFF0D
) which is technically a
Vendor-defined page but with defined Usages. Converting from a UsagePage
or Usage numeric value will produce the correct or Wacom Usage, not a VendorDefinedPage::VendorUsage.
§Reserved Usage Pages
Reserved Usage Pages and ReservedUsages are
not autogenerated and thus follow a different approach: the Usage inside the Usage Page is a simple
numeric usage that needs to be destructured in match
statements.
Unlike the Vendor Defined Usage Pages a Reserved Usage Page may become a defined page in a later version of the HUT standard and thus in a future version of this crate. A caller must not rely on a Reserved Usage Page or Reserved Usage to remain so.
The following Usage Pages are reserved as of HUT 1.5 (see HUT Section 3, p15):
0x13
,0x15-0x1F
0x21-0x3F
0x42-0x58
0x5A-0x7F
0x83-0x83
0x86-0x8B
0x8F-0x8F
0x93-0xF1CF
0xF1D1-0xFEFF
§Renames
For technical reasons, spaces, (
), dashes (-
), and slashes (/
) are
stripped out of Usage Page and Usage names. The string representation via
the Display
trait will have the unmodified value.
Structs§
- Represents a Reserved Page number value of in the current range of reserved values. See ReservedUsagePage.
- Represents a Vendor Defined Page number value of in the range
0xFF00..=0xFFFF
. See VendorDefinedPage.
Enums§
- Usage Page
0x91
: “Arcade” - Usage Page
0x14
: “Auxiliary Display” - Usage Page
0x8C
: “Barcode Scanner” - Usage Page
0x85
: “Battery System” - Usage Page
0x41
: “Braille Display” - Usage Page
0x9
: “Button” - Usage Page
0x90
: “Camera Control” - Usage Page
0xC
: “Consumer” - Usage Page
0xD
: “Digitizers” - Usage Page
0x12
: “Eye and Head Trackers” - Usage Page
0xF1D0
: “FIDO Alliance” - Usage Page
0x5
: “Game Controls” - Usage Page
0x1
: “Generic Desktop” - Usage Page
0x6
: “Generic Device Controls” - Usage Page
0xE
: “Haptics” - Error raised if conversion between HUT elements fails.
- Usage Page
0x7
: “Keyboard/Keypad” - Usage Page
0x8
: “LED” - Usage Page
0x59
: “Lighting And Illumination” - Usage Page
0x8E
: “Magnetic Stripe Reader” - Usage Page
0x40
: “Medical Instrument” - Usage Page
0x80
: “Monitor” - Usage Page
0x81
: “Monitor Enumerated” - Usage Page
0xA
: “Ordinal” - Usage Page
0xF
: “Physical Input Device” - Usage Page
0x84
: “Power” - Reserved Usage Pages
- Usage Page
0x8D
: “Scales” - Usage Page
0x20
: “Sensors” - Usage Page
0x2
: “Simulation Controls” - Usage Page
0x11
: “SoC” - Usage Page
0x4
: “Sport Controls” - Usage Page
0xB
: “Telephony Device” - Usage Page
0x10
: “Unicode” - An enum wrapping all known Usages in the HUT.
- Usage Page
0x82
: “VESA Virtual Controls” - Usage Page
0x3
: “VR Controls” - Usage Page
0xFF00
to0xFFFF
: The Vendor Defined Pages - Usage Page
0xFF0D
: “Wacom”
Traits§
- A trait to return the Usage and Usage ID as numeric value
- A trait to return the Usage Page as numeric value