Skip to content

Latest commit

 

History

History
272 lines (208 loc) · 7.03 KB

descriptor.rst

File metadata and controls

272 lines (208 loc) · 7.03 KB

High-level descriptor language

Let's take the following input file:

 1 from hrdc.usage import *
 2 from hrdc.descriptor import *
 3 
 4 descriptor = Collection(Collection.Application, desktop.Mouse,
 5     Value(Value.Input, desktop.X, 8, flags = Value.Variable | Value.Relative, logicalMin = -127, logicalMax = 127),
 6     Value(Value.Input, desktop.Y, 8, flags = Value.Variable | Value.Relative, logicalMin = -127, logicalMax = 127),
 7     Value(Value.Input, button.Button(1), 1, logicalMin = 0, logicalMax = 1),
 8     Value(Value.Input, button.Button(2), 1, logicalMin = 0, logicalMax = 1),
 9     Value(Value.Input, button.Button(3), 1, logicalMin = 0, logicalMax = 1),
10 )
11 
12 if __name__ == "__main__":
13     compile_main(descriptor)
from hrdc.usage import *
from hrdc.descriptor import *
if __name__ == "__main__":
    compile_main(descriptor)

At the end of the script, this code handles the command line only if the script is invoked as main python script. Using this construct has a benefical side-effect: script may still be imported from another one as a library. This way, you may write various device descriptors and merge them as a composite device through imports, but yet be able to compile them separatly.

Values define Data items in a descriptor. For each value declared, all the relevant parameters should be defined, not considering if they are actually serialized as local or global items. There is no global parameter in this descriptor format.

Value(way, usage, size,
      flags = Data | Variable | Absolute,
      logicalMin = 1, logicalMax = None,
      physicalMin = None, physicalMax = None,
      namedArray = None,
      unit = 0, unitExponent = 0,
      designator = 0,
      string = 0,
      count = 1,
      alignment = None)
way
This is the Data Item type, either Value.Input, Value.Output or Value.Feature
usage
This is the Usage for the value. For named arrays, this is the usage for the surrounding logical collection.
size
Data item size in bits
logicalMin, logicalMax
Logical bounds, i.e. value range that device may encode in the size-bits data field
physicalMin, physicalMax
Physical bounds, i.e. semantic value range reported to HID stack clients. If left to None, they will match logical bounds
namedArray
Must be a list of Usage constants, or a UsageRange object. When set, value becomes a Named Array. Physical bounds are invalid for a Named Array, and only logicalMin is relevant to set the logical value for first array item. This defaults to 1 but may be set to another value for specific purposes (0 most of the time)
unit
Physical value unit, see units below
unitExponent
Base-10 exponent to apply to physical value
designator
Designator index, for physical descriptors
string
String index, for string descriptors
count
Useful for array-of-Named-Arrays only, like in keyboard descriptors
alignment
Alignment to enforce before inserting this value

Padding() is a short-hand for constant Value() for a given bit width.

For instance the following values will be on two consecutive bytes, each at lower bit:

Value(Value.Input, button.Button(1), 1, logicalMin = 0, logicalMax = 1),
Padding(Value.Input, 7),
Value(Value.Input, button.Button(2), 1, logicalMin = 0, logicalMax = 1),

Align() construct is a short-hand for Padding() where report data is aligned on next bit size boundary.

For instance the following values will be on two consecutive bytes, each at lower bit:

Value(Value.Input, button.Button(1), 1, logicalMin = 0, logicalMax = 1),
Align(Value.Input, 8),
Value(Value.Input, button.Button(2), 1, logicalMin = 0, logicalMax = 1),

Collection() generates Collection and End Collection global items. This hierarchical object needs a type (Physical, Application, Logical, Report, NamedArray, UsageSwitch or UsageModifier) and a Usage constant.

Collection(Logical, desktop.Keyboard,
  Value(...),
  ...
)

TopLevel() is a pseudo-collection that generates no Item, but allows to have more than one top-level collection.

TopLevel(
  Collection(Logical, desktop.Keyboard,
    Value(...),
    ...
  ),
  Collection(Logical, consumer.ConsumerControl,
    Value(...),
    ...
  ),
)

Report() is a collection that generates no Item, but sets report ID for subtree.

Collection(Logical, desktop.Keyboard,
  Report(1,
    Value(...),
    Value(...),
    Value(...),
  ),

  Report(2,
    Value(...),
    Value(...),
    Value(...),
  ),
)

Usage constants are defined as symbolic values. They refer to objects that behave like ints, but also have a stringifiable correspondance:

>>> from hrdc.usage import *
>>> desktop.X
<hrdc.usage.usage.Usage instance at 0x104f523f8>
>>> str(desktop.X)
'desktop.X'
>>> hex(int(desktop.X))
'0x10030'

Usage class can also resolve named constants from the numerical value:

>>> from hrdc.usage import *
>>> u = Usage.lookup(0x10031)
>>> str(u)
'desktop.Y'

For Named-Array Values, constants can be assembled in a Python list, but when numerous contiguous Usage constants have to be used, you may use UsageRange utility. It behaves like a Python list (operators len, [] and iterable), but avoids explicitly enumerating all intermediate constants. For instance, a PC keyboard key value is defined as:

Value(Value.Input, usage = None, size = 8,
      namedArray = UsageRange(keyboard.NoEvent, keyboard.KeypadHexadecimal),
      logicalMin = 0)
>>> from hrdc.usage import *
>>> r = UsageRange(keyboard.NoEvent, keyboard.KeypadHexadecimal)
>>> str(r[0])
'keyboard.NoEvent'
>>> str(r[32])
'keyboard.ThreeAndNumber'

Units can either be constructed from system and various dimensions (as in spec), or from well-known constants:

>>> from hrdc.descriptor import *
>>> si_length = Unit.SILinear | Unit.length(1)
>>> hex(si_length)
'0x11'
>>> si_length == Unit.Centimeter
True

Dimensions are: length, mass, time, temperature, current, luminousintensity. They take an exponent in range [-8, 7] as argument.

Well known constants are: Centimeter, Radian, Inch, Degree, Gram, Slug, Second, Kelvin, Fahrenheit, Ampere, Candela, CmPerSec, Momentum, G, Newton, Joule, Volt.