Skip to content

Waratah Keys

Matthew Williams edited this page Aug 3, 2023 · 5 revisions

count

Semantic meaning dependant on context from encompassing section.

Types

Type MinValue MaxValue Example Additional
int16 1 2^16 - 1 count = 1

cppDescriptorName

C++ variable name given to the descriptor byte array. Having this name definable, makes it easier for firmware developers to ingest into their products.

Types

Type Example Additional
string cppDescriptorName = 'myCustomDescriptorName' Can only include characters (Aa-Zz) and digits (0-9), no special characters. Can sometimes contain spaces.
static const uint8_t myCustomDescriptorName [] = 
{
    0x05, 0x0C,          // UsagePage(Consumer[12])
    0x09, 0x01,          // UsageId(Consumer Control[1])

cppDescriptorVariableModifier

C++ variable modifier given to the descriptor byte array. Having this definable, makes it easier for firmware developers to specify memory type. (e.g. for Arduino devices, it would be common to define this as PROGMEM such the descriptor is stored in (the much larger) flash memory (rather than SRAM))

Types

Type Example Additional
string cppDescriptorVariableModifier = 'myCustomDescriptorVariableModifier' Can only include characters (Aa-Zz) and digits (0-9), no special characters.
static const myCustomDescriptorVariableModifier uint8_t myCustomDescriptorName [] = 
{
    0x05, 0x0C,          // UsagePage(Consumer[12])
    0x09, 0x01,          // UsageId(Consumer Control[1])

generateCpp

Whether to generate a C++ compatible byte array and supporting structs, or plain-text.

If packingInBytes is not set, supporting structs are not defined.

Types

Type Example Additional
bool generateCpp = true Defaults to true.

Example: 1

generateCpp == true, C++ generated.

Source:

[[settings]]
generateCpp = true

[[applicationCollection]]
usage = ['Generic Desktop', 'Joystick']

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.variableItem]]
        usage = ['Generic Desktop', 'Hat Switch']
        logicalValueRange = [0, 3]

C++ Output:

#include <memory>

static const uint8_t hidReportDescriptor [] = 
{
    0x05, 0x01,    // UsagePage(Generic Desktop[1])
    0x09, 0x04,    // UsageId(Joystick[4])
    0xA1, 0x01,    // Collection(Application)
    0x85, 0x01,    //     ReportId(1)
    0x09, 0x39,    //     UsageId(Hat Switch[57])
    0x15, 0x00,    //     LogicalMinimum(0)
    0x25, 0x03,    //     LogicalMaximum(3)
    0x95, 0x01,    //     ReportCount(1)
    0x75, 0x08,    //     ReportSize(8)
    0x81, 0x02,    //     Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
    0xC0,          // EndCollection()
};

Example: 2

generateCpp == false, plain-text generated.

Source:

[[settings]]
generateCpp = false

[[applicationCollection]]
usage = ['Generic Desktop', 'Joystick']

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.variableItem]]
        usage = ['Generic Desktop', 'Hat Switch']
        logicalValueRange = [0, 3]

Plain-text Output:

05-01....UsagePage(Generic Desktop[1])
09-04....UsageId(Joystick[4])
A1-01....Collection(Application)
85-01........ReportId(1)
09-39........UsageId(Hat Switch[57])
15-00........LogicalMinimum(0)
25-03........LogicalMaximum(3)
95-01........ReportCount(1)
75-02........ReportSize(2)
81-02........Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
75-06........ReportSize(6)
81-03........Input(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0.......EndCollection()

id

Specifies the id of the section defined. Must be unique across sections of that type.

Types

Type MinValue MaxValue Example Additional
int16 1 2^16 - 1 id = 1
int32 1 2^32 - 1 id = 12345

logicalValueRange

Describes the Logical Range (min/max) of an item. This is the permitted range of values than can be sent in a report control. The Logical Range can never exceed the hard-boundaries imposed by the associated bit size.

For the simplicity of cross platform support, the min/max values supported are of a signed 32bit integer (int32). While HID can support an unsigned 32bit integer (uint32), not all platforms can interpret this value correctly.

When absent from sections, will default to maxSignedSizeRange, inferring actual range from sizeInBits.

Types

Type MinValue MaxValue Example Additional
int32[2] [-2^31, x] [x, 2^31 - 1] logicalValueRange = [0, 255] Min is always 1st value, Max always 2nd.
maxSignedSizeRange logicalValueRange = 'maxSignedSizeRange' Logical range is inferred as largest signed range permitted by sizeInBits
maxUnsignedSizeRange logicalValueRange = 'maxUnsignedSizeRange' Logical range is interred as largest unsigned range permitted by sizeInBits

name

Semantic meaning dependant on context from encompassing section.

Types

Type Example Additional
string name = 'SampleName1' Can only include characters (Aa-Zz) and digits (0-9), no special characters. Can sometimes contain spaces.

optimize

Whether to optimize descriptor generation for the most compact/condensed size. Redundant GlobalItems are removed and MainItems/LocalItems condensed where possible. Optimized/non-optimized descriptors are functionally identical, and report controls have identical attributes.

Debugging descriptor generation is the only expected false use case.

Types

Type Example Additional
bool optimize = true Defaults to true.

physicalValueRange

Describes the Physical Range (min/max) of an item. This is used to calculate the offset/scaling factor to the value sent in the report, who's bounds are described by logicalValueRange

For the simplicity of cross platform support, the min/max values supported of a signed 32bit integer (int32). While HID can support an unsigned 32bit integer (uint32), not all platforms can interpret this value correctly.

Types

Type MinValue MaxValue Example Additional
int32[2] [-2^31, x] [x, 2^31 - 1] physicalValueRange = [0, 10000] Min is always 1st value, Max always 2nd.

packingInBytes

Describes the number of bytes that all controls will be packed/aligned to. (e.g. if set to 2, all controls will be padded (as needed) to be sized to multiples of 16bits)

Currently, C++ struct generation will only be performed if this is set to a non-zero value.

Types

Type MinValue MaxValue Example Additional
int 1 4 packingInBytes = 1 Valid values, 1, 2 and 4

reportFlags

Array of flags to apply to the variableItem/arrayItem. Note: Not all flags can apply to every item type or for every report type.

Every flag has an alternate, which describes the opposite meaning if present.

Type Example Additional
string[] reportFlags = ['data', 'absolute'] Refer to table below for invalid combinations.

Flags

Flag Alternate Default Input Items Output Items Feature Items Description
Data Constant ✔️ ✔️ ✔️ ✔️ Item defines report fields that contain modifiable device data
Constant Data ✔️ ✔️ ✔️ Item is a static read-only/constant field in a report and cannot be modified (written) by the Host.
Absolute Relative ✔️ ✔️ ✔️ ✔️ Item is based on a fixed origin (e.g. touch-pad data)
Relative Absolute ✔️ ✔️ ✔️ Indicates value of item is the change in value from the last report (e.g. mouse data).
NoWrap Wrap ✔️ ✔️ ✔️ ✔️ Indicates the value of the item does not wrap.
Wrap NoWrap ❌(Array) ✔️ ✔️ Indicates the value of the item does wrap.
Linear NonLinear ✔️ ❌(Array) ✔️ ✔️ Indicates the data has not been processed to represent something other than a linear relationship to what was captured
NonLinear Linear ❌(Array) ✔️ ✔️ Indicates the data has been processed on the device and no longer represents a linear relationship between what was captured and the data reported
PreferredState NoPreferredState ✔️ ❌(Array) ✔️ ✔️ Indicates the underlying control has a preferred state (e.g. push-buttons, self-centering joysticks)
NoPreferredState PreferredState ❌(Array) ✔️ ✔️ Indicates the underlying control does not have a preferred state (e.g. toggle-button)
NoNullPosition Nullstate ✔️ ❌(Array) ✔️ ✔️ Indicates any value of this field is meaningful
NullState NoNullPosition ❌(Array) ✔️ ✔️ Indicates any value outside of the LogicalMin/Max is a logical null-value
NonVolatile Volatile ✔️ ✔️ ✔️ Indicates the value shouldn't/cannot be changed by the Host
Volatile NonVolatile ✔️ ✔️ Indicates the value can change with or without Host interaction
BitField BufferedBytes ✔️ ❌(Array) ✔️ ✔️ Indicates the value should be interpreted as a numeric value
BufferedBytes BitField ❌(Array) ✔️ ✔️ Indicates the value should be interpreted as a series of opaque bits

sizeInBits

Size of the item in bits.

Note: HID permits items to be fractional-byte sizes (e.g. 2, 27), to decrease report size.

Type MinValue MaxValue Example
int 1 32 sizeInBits = 4

types

Usage types to associate with a newly defined Usage (via usage section).

Types

Type Example Additional
string[] types = ['DV', 'SV'] Must be composed of pre-defined types.

Pre-defined Usage Types

Usage Type Description Kind
LC Linear Control Button
OOC On/off Control Button
MC Momentary Control Button
OSC One-shot Control Button
RTC Retrigger Control Button
Sel Selector Data
SV Static Value Data
SF Static Flag Data
DV Dynamic Value Data
DF Dynamic Flag Data
BufferedBytes Buffered Bytes Data
NAry Named Array Collection
CA Application Collection Collection
CL Logical Collection Collection
CP Physical Collection Collection
US Usage Switch Collection
UM Usage Modifier Collection

unit

Specifies a unit to be associated with the item.

Cannot be used in conjunction with usageUnitMultiplier

Types

Type Example Additional
string unit = 'centimeter' Must be a unit either predefined, or newly composed

Pre-defined units

Unit Type
centimeter length
inch length
radians length
degrees length
gram mass
slug mass
second time
kelvin temperature
fahrenheit temperature
ampere current
candela luminousity

Additonal units may be defined by composing these primitives together (via unit section).

usageRelation

Links multiple reports together under within a single PhysicalCollection. This exists only as a back-compat for Sensors, so may may only be used for 'Sensors' Usages.

Types

Type Example
string[2] usageRelation = ['Sensors', 'Biometric: Human Presence']

Example: 1

usageRelation, C++ generated.

Source:

[[applicationCollection]]
usage = ['Sensors', 'Sensor']

        [[applicationCollection.featureReport]]
        usageRelation = ['Sensors', 'Biometric: Human Presence']

            [[applicationCollection.featureReport.logicalCollection]]
            usage = ['Sensors', 'Property: Sensor Connection Type']

                [[applicationCollection.featureReport.logicalCollection.arrayItem]]
                usageRange = ['Sensors', 'Connection Type: PC Integrated', 'Connection Type: PC External']

        [[applicationCollection.inputReport]]
        usageRelation = ['Sensors', 'Biometric: Human Presence']

            [[applicationCollection.inputReport.logicalCollection]]
            usage = ['Sensors', 'Event: Sensor State']

                [[applicationCollection.inputReport.logicalCollection.arrayItem]]
                usageRange = ['Sensors', 'Sensor State: Undefined', 'Sensor State: Error']

C++ Output:

static const uint8_t hidReportDescriptor [] = 
{
    0x05, 0x20,          // UsagePage(Sensors[0x0020])
    0x09, 0x01,          // UsageId(Sensor[0x0001])
    0xA1, 0x01,          // Collection(Application)
    0x09, 0x11,          //     UsageId(Biometric: Human Presence[0x0011])
    0xA1, 0x00,          //     Collection(Physical)
    0x85, 0x01,          //         ReportId(1)
    0x0A, 0x09, 0x03,    //         UsageId(Property: Sensor Connection Type[0x0309])
    0xA1, 0x02,          //         Collection(Logical)
    0x1A, 0x30, 0x08,    //             UsageIdMin(Connection Type: PC Integrated[0x0830])
    0x2A, 0x32, 0x08,    //             UsageIdMax(Connection Type: PC External[0x0832])
    0x15, 0x01,          //             LogicalMinimum(1)
    0x25, 0x03,          //             LogicalMaximum(3)
    0x95, 0x01,          //             ReportCount(1)
    0x75, 0x08,          //             ReportSize(8)
    0xB1, 0x00,          //             Feature(Data, Array, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
    0xC0,                //         EndCollection()
    0x0A, 0x01, 0x02,    //         UsageId(Event: Sensor State[0x0201])
    0xA1, 0x02,          //         Collection(Logical)
    0x1A, 0x00, 0x08,    //             UsageIdMin(Sensor State: Undefined[0x0800])
    0x2A, 0x06, 0x08,    //             UsageIdMax(Sensor State: Error[0x0806])
    0x25, 0x07,          //             LogicalMaximum(7)
    0x81, 0x00,          //             Input(Data, Array, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
    0xC0,                //         EndCollection()
    0xC0,                //     EndCollection()
    0xC0,                // EndCollection()
};

usageTransform

Transforms a single Usage to be a combination of the two delcared Usages. Functionally, this ORs the UsageIds together. This is used extensively by Sensors, which uses modifiers (e.g. Modifier: Change Sensitivity Absolute).

All Usages (strings/integers) are the same as defined in the public HID Usage Table (HUT)

Types

Type Example
string[3] usageTransform = ['Sensors', 'Data Field: Angular Velocity', 'Modifier: Change Sensitivity Absolute']

usageRange

Describes a contiguous range of Usages within a specific UsagePage.

Usages can be either described with integers or with strings. Formats cannot be intermixed within a single key.

All Usages (strings/integers) are the same as defined in the public HID Usage Table (HUT)

Types

Type Example Additional
string[2] usageRange = ['Button', 'Button 1', 'Button 10'] Smallest UsageId must always precede larger UsageId
uint16[2] usageRange = [9, 1, 10] Smallest UsageId must always precede larger UsageId

usage

Describes a specific Usage within a UsagePage.

Usages can be either described with integers or with strings. Formats cannot be intermixed within a single key.

All Usages (strings/integers) are the same as defined in the public HID Usage Table (HUT)

Types

Type Example Additional
string[2] usage = ['Button', 'Button 1'] UsagePage always precedes the UsageId
uint16[2] usage = [9, 1] UsagePage always precedes the UsageId

usages

Describes an array of (not-necessarily contiguous) Usages. Usages may be from different UsagePages

Usages can be either described with integers or with strings. Formats cannot be intermixed within a single key.

All Usages (strings/integers) are the same as defined in the public HID Usage Table (HUT)

Types

Type Example
string[2][] usages = [ ['Consumer', 'AL Email Reader'], ['Consumer', 'AL Calculator'], ['Button', 'Button 3'] ]
uint16[2][] usages = [ [0xC, 0x18A], [0xC, 0x192], [0x9, 0x3] ]

usageUnitMultiplier

Alternative to unit, where the unit explcitly defined with the Usage is maintained, but a multiplier is applied by the Host on the control's reported value. This allows the description of numbers larger than an int32 and of non-decimal, fractional values.

Cannot be used in conjunction with unit

Value must always be a multiple of 10

Types

Type MinValue MaxValue Example
float 0.00000001 10000000.0 usageUnitMultiplier = 1000.0