hidtools.hid module — hid-tools documentation

# hidtools.hid module

class HidCollection(value: Annotated[int, ValueRange(min=0, max=255)])

  Bases: `object`

  class Type(*values)

    Bases: `IntEnum`

    APPLICATION: Final = 1
    LOGICAL: Final = 2
    NAMED_ARRAY: Final = 4
    PHYSICAL: Final = 0
    REPORT: Final = 3
    USAGE_MODIFIER: Final = 6
    USAGE_SWITCH: Final = 5
  classmethod from_str(string: str) → Annotated[int, ValueRange(min=0, max=65535)]

    Return the value of this HidCollection given the human-readable string

  property is_reserved: bool
  property is_vendor_defined: bool

class HidField(report_ID: Annotated[int, ValueRange(min=0, max=255)], logical: Annotated[int, ValueRange(min=0, max=4294967295)] | None, physical: Annotated[int, ValueRange(min=0, max=4294967295)] | None, application: Annotated[int, ValueRange(min=0, max=4294967295)] | None, collection: Tuple[Annotated[int, ValueRange(min=0, max=4294967295)], Annotated[int, ValueRange(min=0, max=4294967295)], Annotated[int, ValueRange(min=0, max=4294967295)]] | None, value: Annotated[int, ValueRange(min=0, max=4294967295)], usage_page: Annotated[int, ValueRange(min=0, max=65535)], usage: Annotated[int, ValueRange(min=0, max=4294967295)], logical_min: Annotated[int, ValueRange(min=0, max=4294967295)], logical_max: Annotated[int, ValueRange(min=0, max=4294967295)], physical_min: Annotated[int, ValueRange(min=0, max=4294967295)], physical_max: Annotated[int, ValueRange(min=0, max=4294967295)], unit: Annotated[int, ValueRange(min=0, max=65535)], unit_exp: Annotated[int, ValueRange(min=0, max=255)], item_size: Annotated[int, ValueRange(min=0, max=255)], count: Annotated[int, ValueRange(min=0, max=255)])

  Bases: `object`

  Represents one field in a HID report. A field is one element of a HID report that matches a specific set of bits in that report.

  usage

    The numerical HID field’s Usage, e.g. 0x38 for “Wheel”. If the field has multiple usages, this refers to the first one.

  usage_page

    The numerical HID field’s Usage Page, e.g. 0x01 for “Generic Desktop”

  report_ID

    The numeric Report ID this HID field belongs to

  logical_min

    The logical minimum of this HID field

  logical_max

    The logical maximum of this HID field

  physical_min

    The physical minimum of this HID field

  physical_max

    The physical maximum of this HID field

  unit

    The unit of this HID field

  unit_exp

    The unit exponent of this HID field

  size

    Report Size in bits for this HID field

  count

    Report Count for this HID field

  copy() → HidField

    Return a full copy of this `HIDField`.

  fill_values(report: List[Annotated[int, ValueRange(min=0, max=255)]], data: List[Annotated[int, ValueRange(min=0, max=4294967295)]]) → None

    Assuming `data` is the value for this HID field and `report` is a HID report’s bytes, this method sets those bits in `report` that are his HID field to `value`.

    Example:

    - if this field is Usage `X` , use `fill_values(report, [x-value])`

    - if this field is Usage `X`, `Y`, use `fill_values(report, [x, y])`

    - if this field is a button mask, use `fill_values(report, [1, 0, 1, ...]`, i.e. one value for each button

    `data` must have at least `count` elements, matching this field’s Report Count.

    Parameters:

      - report (list) – an integer array representing this report, modified in place

      - data (list) – the data for this hid field with one element for each Usage.

  fill_values_array(report: List[Annotated[int, ValueRange(min=0, max=255)]], data: List[Any]) → None

    Assuming `data` is the value for this HID field array and `report` is a HID report’s bytes, this method sets those bits in `report` that are his HID field to `value`.

    Example: - if this field is an array of keys, use

    > `fill_values(report, ['a or A', 'b or B', ...]`, i.e. one string representation for each pressed key

    `data` must have at most `count` elements, matching this field’s Report Count.

    Parameters:

      - report (list) – an integer array representing this report, modified in place

      - data (list) – the data for this hid field with one element for each Usage.

  classmethod getHidFields(report_ID: Annotated[int, ValueRange(min=0, max=255)], logical: Annotated[int, ValueRange(min=0, max=4294967295)] | None, physical: Annotated[int, ValueRange(min=0, max=4294967295)] | None, application: Annotated[int, ValueRange(min=0, max=4294967295)] | None, collection: Tuple[Annotated[int, ValueRange(min=0, max=4294967295)], Annotated[int, ValueRange(min=0, max=4294967295)], Annotated[int, ValueRange(min=0, max=4294967295)]] | None, value: Annotated[int, ValueRange(min=0, max=4294967295)], usage_page: Annotated[int, ValueRange(min=0, max=65535)], usages: List[Annotated[int, ValueRange(min=0, max=4294967295)]], usage_min: Annotated[int, ValueRange(min=0, max=4294967295)], usage_max: Annotated[int, ValueRange(min=0, max=4294967295)], logical_min: Annotated[int, ValueRange(min=0, max=4294967295)], logical_max: Annotated[int, ValueRange(min=0, max=4294967295)], physical_min: Annotated[int, ValueRange(min=0, max=4294967295)], physical_max: Annotated[int, ValueRange(min=0, max=4294967295)], unit: Annotated[int, ValueRange(min=0, max=65535)], unit_exp: Annotated[int, ValueRange(min=0, max=255)], item_size: Annotated[int, ValueRange(min=0, max=255)], count: int)

    This is a function to be called by a HID report descriptor parser.

    Given the current parser state and the various arguments, create the required number of `HidField` objects.

    Returns:

      a list of `HidField` objects

  get_usage_name(index: int) → str | None

    Return the Usage name for this field at the given index. Use this function when the HID field has multiple Usages.

  get_values(report: List[Annotated[int, ValueRange(min=0, max=255)]]) → List[Annotated[int, ValueRange(min=0, max=4294967295)] | str]

    Assume `report` is a list of bytes that are a full HID report, extract the values that are this HID field.

    Example:

    - if this field is Usage `X` , this returns `[x-value]`

    - if this field is Usage `X`, `Y`, this returns `[x, y]`

    - if this field is a button mask, this returns `[1, 0, 1, ...]`, i.e. one value for each button

    Parameters:

      report (list) – a list of bytes that are a HID report

    Returns:

      a list of integer values of len `count`

  property is_array: bool

    `True` if this HID field is an array

  property is_const: bool

    `True` if this HID field is const

  property is_null: bool

    `True` if this HID field is null

  property logical_name: str | None

    The logical name or `None`

  property physical_name: str | None

    The physical name or `None`

  property usage_name: str

    The Usage name for this field (e.g. “Wheel”).

  property usage_page_name: str

    The Usage Page name for this field, e.g. “Generic Desktop”

class HidReport(report_ID: Annotated[int, ValueRange(min=0, max=255)], application: Annotated[int, ValueRange(min=0, max=4294967295)] | None, type: Type)

  Bases: `object`

  Represents a HidReport, one of `Input`, `Output`, `Feature`. A `ReportDescriptor` may contain one or more HidReports of different types. These comprise of a number of `HidField` making up the exact description of a report.

  Parameters:

    - report_ID (int) – the report ID

    - application (int) – the HID application

  fields

    The `HidField` elements comprising this report

  class Type(*values)

    Bases: `Enum`

    The type of a `HidReport`

    FEATURE: Final = 3
    INPUT: Final = 1
    OUTPUT: Final = 2
  append(field: HidField) → None

    Add a `HidField` to this report

    Parameters:

      field (HidField) – the object to add to this report

  property application_name: str
  property bitsize: int

    The size of the HidReport in bits

  create_report(data: List[Any], global_data: Any) → List[Annotated[int, ValueRange(min=0, max=255)]]

    Convert the data object to an array of ints representing this report. Each property of the given data object is matched against the field usage name (using `hasattr`) and filled in accordingly.:

        mouse = MouseData()
        mouse.b1 = int(l)
        mouse.b2 = int(r)
        mouse.b3 = int(m)
        mouse.x = x
        mouse.y = y

        data_bytes = hid_report.create_report(mouse)

    The HidReport will create the report according to the device’s report descriptor.

  extend(fields: List[HidField]) → None

    Extend this report by the list of `HidField` objects

    Parameters:

      fields (list) – a list of objects to append to this report

  format_report(data: List[Any], split_lines: bool = True) → str

    Format the HID Report provided as a list of 8-bit integers into a human-readable format.

    Parameters:

      - data (list) – a list of 8-bit integers that are this report

      - split_lines (boolean) – `True` if the format can be split across multiple lines. This makes for easier reading but harder automated processing.

  property numbered: bool

    True if the HidReport was initialized with a report ID

  property size: int

    The size of the HidReport in bytes

  property type: Type

    One of the types in `HidReport.Type`

class HidUnit(system: System, units: Dict[Unit | None, Annotated[int, ValueRange(min=0, max=65535)]])

  Bases: `object`

  A parsed field of a HID Report Descriptor Unit specification.

  units

    A dict of { unit: exponent } of the applicable units. Where the Unit is `None`, the return value is `None`.

  system

    The system the units belong to, one of `HidUnit.System`.

  NONE: Final = None
  class System(*values)

    Bases: `IntEnum`

    ENGLISH_LINEAR: Final = 3
    ENGLISH_ROTATION: Final = 4
    NONE: Final = 0
    SI_LINEAR: Final = 1
    SI_ROTATION: Final = 2
    property current: Unit | None

      Returns the right `Unit` for the current measurement in this system.

    classmethod from_string(string: str) → System | None

      Returns the correct `HidUnit.System` given the string.

    property length: Unit | None

      Returns the right `Unit` for the length measurement in this system.

    property luminous_intensity: Unit | None

      Returns the right `Unit` for the luminous intensity measurement in this system.

    property mass: Unit | None

      Returns the right `Unit` for the mass measurement in this system.

    property temperature: Unit | None

      Returns the right `Unit` for the temperature measurement in this system.

    property time: Unit | None

      Returns the right `Unit` for the time measurement in this system.

  classmethod from_bytes(data: bytes) → HidUnit

    Converts the given data bytes into a `HidUnit` object. The data bytes must not include the 0b011001nn prefix byte.

    Where the HID unit system is None, the returned value is None.

  classmethod from_string(string: str) → HidUnit

    The inverse of __str__()

  classmethod from_value(value: Annotated[int, ValueRange(min=0, max=255)] | Annotated[int, ValueRange(min=0, max=65535)] | Annotated[int, ValueRange(min=0, max=4294967295)]) → HidUnit

    Converts the given 8, 16 or 32-bit value into a `HidUnit` object.

    Where the HID unit system is None, the returned value is None.

  property value: Annotated[int, ValueRange(min=0, max=4294967295)]

    Returns the numerical value for this unit as required by the HID specification.

exception ParseError

  Bases: `Exception`

  Exception thrown during report descriptor parsing

exception RangeError(field: HidField, value: int)

  Bases: `Exception`

  Exception thrown for an out-of-range value

  value

    The invalid value

  range

    A `(min, max)` tuple for the allowed logical range

  field

    The `HidField` that triggered this exception

class ReportDescriptor(items: List[_HidRDescItem])

  Bases: `object`

  Represents a fully parsed HID report descriptor.

  When creating a `ReportDescriptor` object,

  - if your source is a stream of bytes, use `from_bytes()`

  - if your source is a human-readable descriptor, use `from_human_descr()`

  win8

    `True` if the device is Windows8 compatible, `False` otherwise

  input_reports

    All `HidReport` of type `Input`, addressable by the report ID

  output_reports

    All `HidReport` of type `Output`, addressable by the report ID

  feature_reports

    All `HidReport` of type `Feature`, addressable by the report ID

  property bytes: List[Annotated[int, ValueRange(min=0, max=255)]]

    This report descriptor as a list of 8-bit integers.

  create_report(data: Any, global_data: Any | None = None, reportID: Annotated[int, ValueRange(min=0, max=255)] | None = None, application: str | Annotated[int, ValueRange(min=0, max=4294967295)] | None = None) → List[Annotated[int, ValueRange(min=0, max=255)]]

    Convert the data object to an array of ints representing the report. Each property of the given data object is matched against the field usage name (think `hasattr`) and filled in accordingly.

        rdesc = ReportDescriptor.from_bytes([10, ab, 20, cd, ...])

        mouse = MouseData()
        mouse.b1 = int(l)
        mouse.b2 = int(r)
        mouse.b3 = int(m)
        mouse.x = x
        mouse.y = y

        data_bytes = rdesc.create_report(mouse)

    The UHIDDevice will create the report according to the device’s report descriptor.

  dump(dump_file=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>, output_type='default') → None

    Write this ReportDescriptor into the given file

    The “default” format prints each item as hexadecimal format with a double-slash comment, e.g.

        0x05, 0x01,                    // Usage Page (Generic Desktop)        0
        0x09, 0x02,                    // Usage (Mouse)                       2

    The “kernel” format prints each item in valid C format, for easy copy-paste into a kernel or C source file:

        0x05, 0x01,         /* Usage Page (Generic Desktop)         */
        0x09, 0x02,         /* Usage (Mouse)                        */

    Parameters:

      - dump_file (File) – the file to write to

      - output_type (str) – the output format, one of “default” or “kernel”

  format_report(data, split_lines=True)

    Format the HID Report provided as a list of 8-bit integers into a human-readable format.

    Parameters:

      - data (list) – a list of 8-bit integers that are this report

      - split_lines (boolean) – `True` if the format can be split across multiple lines. This makes for easier reading but harder automated processing.

  classmethod from_bytes(rdesc: bytes | List[Annotated[int, ValueRange(min=0, max=255)]]) → ReportDescriptor

    Parse the given list of 8-bit integers.

    Parameters:

      rdesc (list) – a list of bytes that are this report descriptor

  classmethod from_human_descr(rdesc_str: str) → ReportDescriptor

    Parse the given human-readable report descriptor, e.g.

        Usage Page (Digitizers)
        Usage (Finger)
        Collection (Logical)
         Report Size (1)
         Report Count (1)
         Logical Minimum (0)
         Logical Maximum (1)
         Usage (Tip Switch)
         Input (Data,Var,Abs)
         Report Size (7)
         Logical Maximum (127)
         Input (Cnst,Var,Abs)
         Report Size (8)
         Logical Maximum (255)
         Usage (Contact Id)

  classmethod from_string(rdesc: str) → ReportDescriptor

    Parse a string in the format of series of hex numbers:

        12 34 ab cd ...

    and the first number in that series is the count of bytes, excluding that first number. This is the format returned by your `/dev/hidraw` event node, so just pass it along.

    Parameters:

      rdesc (list) – a string that represents the list of bytes

  get(reportID: Annotated[int, ValueRange(min=0, max=255)], reportSize: int) → HidReport | None

    Return the input report with the given Report ID or `None`

  get_report_from_application(application: str | Annotated[int, ValueRange(min=0, max=4294967295)]) → HidReport | None

    Return the Input report that matches the application or `None`

  property size: int

    Returns the size of the report descriptor in bytes.

class Unit(*values)

  Bases: `Enum`

  AMPERE: Final = 'A'
  CANDELA: Final = 'cd'
  CENTIMETER: Final = 'cm'
  DEGREES: Final = 'deg'
  FAHRENHEIT: Final = 'F'
  GRAM: Final = 'g'
  INCH: Final = 'in'
  KELVIN: Final = 'K'
  RADIANS: Final = 'rad'
  RESERVED: Final = 'reserved'
  SECONDS: Final = 's'
  SLUG: Final = 'slug'