Skip to content

Waratah Sections

Matthew Williams edited this page Jul 10, 2023 · 7 revisions

Waratah sections are used to define relationships (i.e. reports/collections), controls and global state. All sections are instantiated using TOML Array-Tables, so composition is of the format [[sectionname1.sectionname2.sectionname3]]. Intermediate sections must be defined, even if no keys are part of the section (i.e. cannot define [[sectionname1.sectionname2.sectionname3]], without a preceding [[sectionname1.sectionname2]] definition.)

Section Structure

[[relationshipSection1]]
key1 = 'string'

    [[relationshipSection1.relationshipSection2]]
    key2 = [0, 10]

        [[relationshipSection1.relationshipSection2.reportItemSection1]]
        key3 = ['string', 'string']

        [[relationshipSection1.relationshipSection2.reportItemSection2]]
        key4 = 123

    [[relationshipSection1.relationshipSection3]]

        [[relationshipSection1.relationshipSection3.reportItemSection3]]
        key5 = true

Relationship Sections

Relationship sections are used to compose relationships between report items. Each section permits/requires different child sections/keys; refer to individual definitions.

Item Sections

Item sections describe HID report items, who's parameters can be modified with keys. Different keys are permitted for each section. No section may be defined as a child of an Item section, they are leaf/terminal sections.

Extension Sections

All USB-IF HID-WG approved Usages and Units are in-built (as of the timing of last release). To add unincorporated Usages/Units or custom Vendor Usages/Units, use the below sections to compose new Usages/Units so they will be recognized and encoded correctly.

applicationCollection

Describes a single HID Application Collection, which corresponds to a single Windows HID device. Multiple [[applicationCollection]] may be defined at the root, but cannot be composed of one another.

An [[applicationCollection]] must have an associated usage key and at least 1 child report section.

Permitted Keys

Key Optional Description
usage Usage associated with this Application Collection.

Permitted child sections

Section Description
inputReport Input Report associated with this Application Collection. Limited to 254 of this type across all Application Collections in the descriptor.
outputReport Output Report associated with this Application Collection. Limited to 254 of this type across all Application Collections in the descriptor.
featureReport Feature Report associated with this Application Collection. Limited to 254 of this type across all Application Collections in the descriptor.

Example

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

    [[applicationCollection.inputReport]]
    ...

    [[applicationCollection.outputReport]]
    ...

    [[applicationCollection.inputReport]]
    ...

[[applicationCollection]]
usage = ['Lighting And Illumination', 'LampArray']

    [[applicationCollection.featureReport]]
    ...

arrayItem

Describes a value that's an index into an array of Usages (i.e. an enumeration). A non-zero value means the Usage at that index is asserted. Since only assertion of a Usage is expressible, the effective type of each Usage is a bool/Button.

When count > 1, multiple Usages can be asserted simultaneously, with each value specifying a different index in the usageRange or usages.

Permitted Keys

Key Optional Additional
count ✔️ Report count of this item. Defaults to 1 if absent.
name ✔️ Generated code variable name. If absent, one will be (poorly) generated.
reportFlags ✔️ If absent, default flags used.
usageRange ✔️ Usages to include in this array. Must be contiguous.
usages ✔️ Usages to include in this array. Need not be contiguous.

Permitted child sections

No child sections permitted.

Example

Simple Consumer Control device with 2 sets of mechanically-linked radio buttons (i.e. can only assert a single button at a time, and assertion clears other buttons). For the first, only one of three values will be asserted: Media Select Computer, Media Select DVD, or Media Select WWW. For the second, only one of two values will be asserted: AL Email Reader, AL Calculator.

Source

[[applicationCollection]]
usage = ['Consumer', 'Consumer Control']

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.arrayItem]]
        usageRange = ['Consumer', 'Media Select Computer', 'Media Select WWW']

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.arrayItem]]
        usages = [ ['Consumer', 'AL Email Reader'], ['Consumer', 'AL Calculator'] ]

Plain-text output

05-0C....UsagePage(Consumer[12])
09-01....UsageId(Consumer Control[1])
A1-01....Collection(Application)
85-01........ReportId(1)
19-88........UsageIdMin(Media Select Computer[136])
29-8A........UsageIdMax(Media Select WWW[138])
15-01........LogicalMinimum(1)
25-03........LogicalMaximum(3)
95-01........ReportCount(1)
75-02........ReportSize(2)
81-00........Input(Data, Array, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
75-06........ReportSize(6)
81-03........Input(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0.......EndCollection()

featureReport

Describes a single HID Feature Report. Feature Reports contain data that are not to/from the user, but instead to/from the device (e.g. device settings, battery status, senor connection type).

The Host must explicitly request a Feature Report from the device, or send a report to the device. A device can never send a Feature Report without an explicit Host request (unlike an Input Report).

Can only ever be a child of an [[applicationCollection]] section, and can never nest or span.

A [[featureReport]] must have at least 1 child section.

Permitted Keys

Key Optional Description
id ✔️ Unique id for this report, across all Feature Reports of all Application Collections. Will be auto-generated if missing.
name ✔️ Generated code variable name. If absent, one will be (poorly) generated.
usageRelation ✔️ Sensor UsageRelation to link multiple reports under a single PhysicalCollection.

Permitted child sections

Section Description
arrayItem HID Array Item. No limit on number of this item.
logicalCollection HID Logical Collection. No limit on number of this item.
paddingItem HID Padding Item. No limit on number of this item.
physicalCollection HID Physical Collection. No limit on number of this item.
variableItem HID Variable Item. No limit on number of this item.

Example

Simple haptic controller (extract) with a single Feature Report describing supported WaveForms.

Source

[[applicationCollection]]
usage = ['Haptics', 'Simple Haptic Controller']

    [[applicationCollection.featureReport]]

        [[applicationCollection.featureReport.logicalCollection]]
        usage = ['Haptics', 'Waveform List']

            [[applicationCollection.featureReport.logicalCollection.variableItem]]
            usageRange = ['Ordinal', 'Instance 3', 'Instance 16']
            logicalValueRange = [4099, 4113]

            ...

Plain-text Output

05-0E.......UsagePage(Haptics[14])
09-01.......UsageId(Simple Haptic Controller[1])
A1-01.......Collection(Application)
85-01...........ReportId(1)
09-10...........UsageId(Waveform List[16])
A1-02...........Collection(Logical)
05-0A...............UsagePage(Ordinal[10])
19-03...............UsageIdMin(Instance 3[3])
29-10...............UsageIdMax(Instance 16[16])
16-03-10............LogicalMinimum(4,099)
26-11-10............LogicalMaximum(4,113)
95-0E...............ReportCount(14)
75-0D...............ReportSize(13)
B1-02...............Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
C0..............EndCollection()
95-01...........ReportCount(1)
75-02...........ReportSize(2)
B1-03...........Feature(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
C0..........EndCollection()

inputReport

Describes a single HID Input Report. Input Reports describe user-generated data sent from the Device to the Host.

The Host can explicitly request any Input Report from the Device at any time.

Can only ever be a child of an [[applicationCollection]] section, and can never nest or span.

An [[inputReport]] must have at least 1 child section.

Permitted Keys

Key Optional Description
id ✔️ Unique id for this report, across all Input Reports of all Application Collections. Will be auto-generated if missing.
name ✔️ Generated code variable name. If absent, one will be (poorly) generated.
usageRelation ✔️ Sensor UsageRelation to link multiple reports under a single PhysicalCollection.

Permitted child sections

Section Description
arrayItem HID Array Item. No limit on number of this item.
logicalCollection HID Logical Collection. No limit on number of this item.
paddingItem HID Padding Item. No limit on number of this item.
physicalCollection HID Physical Collection. No limit on number of this item.
variableItem HID Variable Item. No limit on number of this item.

Example

Simple keyboard (extract) with a single Input Report describing actuated buttons.

Source

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

    [[applicationCollection.inputReport]]

        # Special buttons
        #
        # N.B. Windows applies special buttons only to subsequent keys, so
        # must appear in report beforehand.
        [[applicationCollection.inputReport.variableItem]]
        usageRange = ['Keyboard/Keypad', 'Keyboard LeftControl', 'Keyboard Right GUI']
        logicalValueRange = [0, 1]

        # Regular Buttons
        [[applicationCollection.inputReport.arrayItem]]
        usageRange = ['Keyboard/Keypad', 'ErrorRollOver', 'Keyboard Application']
        count = 8

        ...

Plain-text Output

05-01....UsagePage(Generic Desktop[1])
09-06....UsageId(Keyboard[6])
A1-01....Collection(Application)
85-01........ReportId(1)
05-07........UsagePage(Keyboard/Keypad[7])
19-E0........UsageIdMin(Keyboard LeftControl[224])
29-E7........UsageIdMax(Keyboard Right GUI[231])
15-00........LogicalMinimum(0)
25-01........LogicalMaximum(1)
95-08........ReportCount(8)
75-01........ReportSize(1)
81-02........Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
19-01........UsageIdMin(ErrorRollOver[1])
29-65........UsageIdMax(Keyboard Application[101])
15-01........LogicalMinimum(1)
25-65........LogicalMaximum(101)
75-07........ReportSize(7)
81-00........Input(Data, Array, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0.......EndCollection()

logicalCollection

Groups discrete items to form a composite data-structure. (e.g. a data-buffer and a byte count of the data). In comparison, a PhysicalCollection represents items from a specific geometric point.

A [[logicalCollection]] must have either an associated usage or usageTransform key and at least 1 child section.

Permitted Keys

Key Optional Description
usage ✔️ Usage associated with this Logical Collection.
usageTransform ✔️ (transformed) Usage associated with this Logical Collection.

Permitted child sections

Section Description
arrayItem HID Array Item. No limit on number of this item.
logicalCollection HID Logical Collection. No limit on number of this item.
paddingItem HID Padding Item. No limit on number of this item.
physicalCollection HID Physical Collection. No limit on number of this item.
variableItem HID Variable Item. No limit on number of this item.

Example

Consumer-control device with a Play LED that can indicate On/Blinking/Off, with colors Red/Green/Amber.

Source

[[applicationCollection]]
usage = ['Consumer', 'Consumer Control']

    [[applicationCollection.featureReport]]

        [[applicationCollection.featureReport.logicalCollection]]
        usage = ['Consumer', 'Play']

            [[applicationCollection.featureReport.logicalCollection.logicalCollection]]
            usage = ['LED', 'Usage Multi Mode Indicator']

                [[applicationCollection.featureReport.logicalCollection.logicalCollection.arrayItem]]
                usageRange = ['LED', 'Indicator On', 'Indicator Off']

            [[applicationCollection.featureReport.logicalCollection.logicalCollection]]
            usage = ['LED', 'Usage Indicator Color']

                [[applicationCollection.featureReport.logicalCollection.logicalCollection.arrayItem]]
                usageRange = ['LED', 'Indicator Red', 'Indicator Amber']

Plain-text output

05-0C....UsagePage(Consumer[12])
09-01....UsageId(Consumer Control[1])
A1-01....Collection(Application)
85-01........ReportId(1)
09-B0........UsageId(Play[176])
A1-02........Collection(Logical)
05-08............UsagePage(LED[8])
09-3C............UsageId(Usage Multi Mode Indicator[60])
A1-02............Collection(Logical)
19-3D................UsageIdMin(Indicator On[61])
29-41................UsageIdMax(Indicator Off[65])
15-01................LogicalMinimum(1)
25-05................LogicalMaximum(5)
95-01................ReportCount(1)
75-03................ReportSize(3)
B1-00................Feature(Data, Array, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
C0...............EndCollection()
09-47............UsageId(Usage Indicator Color[71])
A1-02............Collection(Logical)
19-48................UsageIdMin(Indicator Red[72])
29-4A................UsageIdMax(Indicator Amber[74])
25-03................LogicalMaximum(3)
75-02................ReportSize(2)
B1-00................Feature(Data, Array, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
C0...............EndCollection()
C0...........EndCollection()
75-03........ReportSize(3)
B1-03........Feature(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
C0.......EndCollection()

outputReport

Describes a single HID Output Report. Output Reports describe data sent to the Device from the Host for the user.

The Host cna send an Output Report to the Device at any time.

Can only ever be a child of an [[applicationCollection]] section, and can never nest or span.

An [[outputReport]] must have at least 1 child section.

Permitted Keys

Key Optional Description
id ✔️ Unique id for this report, across all Output Reports of all Application Collections. Will be auto-generated if missing.
name ✔️ Generated code variable name. If absent, one will be (poorly) generated.
usageRelation ✔️ Sensor UsageRelation to link multiple reports under a single PhysicalCollection.

Permitted child sections

Section Description
arrayItem HID Array Item. No limit on number of this item.
logicalCollection HID Logical Collection. No limit on number of this item.
paddingItem HID Padding Item. No limit on number of this item.
physicalCollection HID Physical Collection. No limit on number of this item.
variableItem HID Variable Item. No limit on number of this item.

Example

Simple keyboard (extract) with a single Output Report describing asserted LEDs.

Source

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

    # LEDS
    [[applicationCollection.outputReport]]

        [[applicationCollection.outputReport.variableItem]]
        usageRange = ['LED', 'Num Lock', 'Kana']
        logicalValueRange = [0, 1]

        ...

Plain-text Output

05-01....UsagePage(Generic Desktop[1])
09-06....UsageId(Keyboard[6])
A1-01....Collection(Application)
85-01........ReportId(1)
05-08........UsagePage(LED[8])
19-01........UsageIdMin(Num Lock[1])
29-05........UsageIdMax(Kana[5])
15-00........LogicalMinimum(0)
25-01........LogicalMaximum(1)
95-05........ReportCount(5)
75-01........ReportSize(1)
91-02........Output(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
95-01........ReportCount(1)
75-03........ReportSize(3)
91-03........Output(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
C0.......EndCollection()

paddingItem

Describes a simple, single field that takes up space in the report but cannot be assigned a value. This is useful for manual bit alignment of items within a report.

Should never strictly be necessary to add, as report padding is generated automatically, and packingInBytes can be used for gross alignment.

Permitted Keys

Key Optional Additional
sizeInBits

Permitted child sections

No child sections permitted.

Example

Joystick with a single button. Without paddingItem, 7bits padding would automatically be added at the end. Since [[paddingItem]] was previously defined, 7bits padding are explicitly added at the start.

Source

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

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.paddingItem]]
        sizeInBits = 7

        [[applicationCollection.inputReport.variableItem]]
        usage = ['Button', 'Button 1']
        logicalValueRange = [0, 1]

Plain-text Output

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

physicalCollection

Groups discrete items that are associated with a specific geometric point. (e.g. X and Y axis on a mouse).

A [[physicalCollection]] must have either an associated usage or usageTransform key and at least 1 child section.

Permitted Keys

Key Optional Description
usage ✔️ Usage associated with this Physical Collection.
usageTransform ✔️ (transformed) Usage associated with this Physical Collection.

Permitted child sections

Section Description
arrayItem HID Array Item. No limit on number of this item.
logicalCollection HID Logical Collection. No limit on number of this item.
paddingItem HID Padding Item. No limit on number of this item.
physicalCollection HID Physical Collection. No limit on number of this item.
variableItem HID Variable Item. No limit on number of this item.

Example

Simple mouse with 3 buttons.

Source

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

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.physicalCollection]]
        usage = ['Generic Desktop', 'Pointer']

            [[applicationCollection.inputReport.physicalCollection.variableItem]]
            usage = ['Generic Desktop', 'X']
            sizeInBits = 8
            logicalValueRange = 'maxSignedSizeRange'
            reportFlags = ['relative']

            [[applicationCollection.inputReport.physicalCollection.variableItem]]
            usage = ['Generic Desktop', 'Y']
            sizeInBits = 8
            logicalValueRange = 'maxSignedSizeRange'
            reportFlags = ['relative']

            [[applicationCollection.inputReport.physicalCollection.variableItem]]
            usageRange = ['Button', 'Button 1', 'Button 3']
            logicalValueRange = [0, 1]

Plain-text output

05-01....UsagePage(Generic Desktop[1])
09-02....UsageId(Mouse[2])
A1-01....Collection(Application)
85-01........ReportId(1)
09-01........UsageId(Pointer[1])
A1-00........Collection(Physical)
09-30............UsageId(X[48])
09-31............UsageId(Y[49])
15-80............LogicalMinimum(-128)
25-7F............LogicalMaximum(127)
95-02............ReportCount(2)
75-08............ReportSize(8)
81-06............Input(Data, Variable, Relative, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
05-09............UsagePage(Button[9])
19-01............UsageIdMin(Button 1[1])
29-03............UsageIdMax(Button 3[3])
15-00............LogicalMinimum(0)
25-01............LogicalMaximum(1)
95-03............ReportCount(3)
75-01............ReportSize(1)
81-02............Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0...........EndCollection()
95-01........ReportCount(1)
75-05........ReportSize(5)
81-03........Input(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0.......EndCollection()

settings

Settings for the generation of this descriptor.

Can only ever be a single root section and can never nest or span.

Permitted Keys

Key Optional Description
packingInBytes ✔️ Packs every defined control/item to specified bytes. Default is off.
optimize ✔️ Performs optimization on descriptor. Default is true
generateCpp ✔️ Generates C++ output file. Structs only generated if packingInBytes also set.
cppDescriptorName ✔️ C++ variable of generated descriptor byte array. Default is hidReportDescriptor.
cppDescriptorVariableModifier ✔️ C++ variable modifier of generated descriptor byte array. Absent by default.

Permitted child sections

No child sections permitted.

Example

Settings section with no [[applicationCollections]]

Source

[[settings]]
packingInBytes = 2
optimize = true
generateCpp = true
cppDescriptorName = 'exampleDescriptorName'
cppDescriptorVariableModifier = 'PROGMEM'

unit

Allows the composition of primitive units into new, named units, that can later be referred to. Newly defined units can also be used to compose additional new units. See Custom Units for more details on creating custom units.

Permitted Keys

Key Optional Description
name Name of the new unit, must be unique across all units.
<unitName> Name of previously defined unit.

Permitted child sections

No child sections permitted.

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

Example

Sensor that measures weight (in kilograms).

Source

[[unit]]
name = 'kilogram'
gram = [1000.0, 1.0]

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

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.variableItem]]
        usage = ['Sensors', 'Data Field: Weight']
        logicalValueRange = [0, 200]
        unit = 'kilogram'

Plain-text output

05-20.......UsagePage(Sensors[32])
09-01.......UsageId(Sensor[1])
A1-01.......Collection(Application)
85-01...........ReportId(1)
0A-98-04........UsageId(Data Field: Weight[1,176])
66-01-01........Unit('kilogram', SiLinear, Gram:1)
55-03...........UnitExponent(1,000)
15-00...........LogicalMinimum(0)
26-C8-00........LogicalMaximum(200)
95-01...........ReportCount(1)
75-08...........ReportSize(8)
81-02...........Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0..........EndCollection()

usagePage

Defines a new/existing Usage Page for vendor defined Usages.

Permitted Keys

Key Optional Description
id Id of the new UsagePage, must be unique across all UsagePages.
name Name of the new UsagePage, must be unique across all UsagePages.

Permitted child sections

Section Description
usage New Usage/UsageId belonging to this UsagePage.

Example

Vendor device with custom UsagePage and Usages.

Source

[[usagePage]]
id = 99
name = 'Vendor Usage Page 1'

    [[usagePage.usage]]
    id = 1
    name = 'Vendor Usage 1'
    types = ['CA']

    [[usagePage.usage]]
    id = 2
    name = 'Vendor Usage 2'
    types = ['Sel', 'OOC', 'MC']

[[applicationCollection]]
usage = ['Vendor Usage Page 1', 'Vendor Usage 1']

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.variableItem]]
        usage = ['Vendor Usage Page 1', 'Vendor Usage 2']
        sizeInBits = 8

Plain-text output

05-63....UsagePage(Vendor Usage Page 1[99])
09-01....UsageId(Vendor Usage 1[1])
A1-01....Collection(Application)
85-01........ReportId(1)
09-02........UsageId(Vendor Usage 2[2])
15-80........LogicalMinimum(-128)
25-7F........LogicalMaximum(127)
95-01........ReportCount(1)
75-08........ReportSize(8)
81-02........Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0.......EndCollection()

usage

Defines a Usage/UsageId for a vendor defined UsagePage.

Permitted Keys

Key Optional Description
id Id of the new Usage/UsageId, must be unique within UsagePage.
name Name of the new Usage/UsageId, must be unique within UsagePage.
types Types associated with this Usage/UsageId.

Permitted child sections

No child sections permitted.

Example

Vendor device with custom UsagePage and Usages.

Source

[[usagePage]]
id = 99
name = 'Vendor Usage Page 1'

    [[usagePage.usage]]
    id = 1
    name = 'Vendor Usage 1'
    types = ['CA']

    [[usagePage.usage]]
    id = 2
    name = 'Vendor Usage 2'
    types = ['Sel', 'OOC', 'MC']

[[applicationCollection]]
usage = ['Vendor Usage Page 1', 'Vendor Usage 1']

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.variableItem]]
        usage = ['Vendor Usage Page 1', 'Vendor Usage 2']
        sizeInBits = 8

Plain-text output

05-63....UsagePage(Vendor Usage Page 1[99])
09-01....UsageId(Vendor Usage 1[1])
A1-01....Collection(Application)
85-01........ReportId(1)
09-02........UsageId(Vendor Usage 2[2])
15-80........LogicalMinimum(-128)
25-7F........LogicalMaximum(127)
95-01........ReportCount(1)
75-08........ReportSize(8)
81-02........Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0.......EndCollection()

variableItem

Describes a simple, single data field. Called Variable, as the value in the report can be any in the defined range (as scoped by logicalValueRange, or inferred by usageRange or sizeInBits).

In comparison, an arrayItem, may only be an index (0 -> n-1) into the array of Usages defined by a usageRange, hence an Array describes bools/Buttons (i.e. an enumeration), with Usages optionally asserted.

Permitted Keys

Key Optional Invalid Combination Additional
count ✔️ usageRange Report count of this item. Defaults to 1 if absent.
logicalValueRange ✔️ If absent, defaults to maximum signed range permitted by size bits.
physicalValueRange ✔️
name ✔️ Generated code variable name. If absent, one will be (poorly) generated.
reportFlags ✔️ If absent, default flags used.
sizeInBits ✔️ If absent, defaults to minimum bits required to describe logicalValueRange.
unit ✔️ usageUnitMultiplier Discrete unit to apply to item.
usage ✔️ usageRange, usageTransform Usage of the item.
usageRange ✔️ usage, usageTransform Shortcut to defining many variableItems in a contiguous Usage range. count is calculated from the number of Usages in the range.
usageTransform ✔️ usage, usageRange Usage of the item with a transform applied.
usageUnitMultiplier ✔️ unit Unit multiplier to apply.

Permitted child sections

No child sections permitted.

Example 1

Simple transducer that can send it's serial-number. Only usage and sizeInBits are specified. count, logicalValueRange, reportFlags are inferred.

Source

[[applicationCollection]]
usage = ['Digitizers', 'Stylus']

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.variableItem]]
        usage = ['Digitizers', 'Transducer Serial Number']
        sizeInBits = 32
        logicalValueRange = 'maxUnsignedSizeRange'

Plain-text Output

05-0D.............UsagePage(Digitizers[13])
09-20.............UsageId(Stylus[32])
A1-01.............Collection(Application)
85-01.................ReportId(1)
09-5B.................UsageId(Transducer Serial Number[91])
15-00.................LogicalMinimum(0)
27-FF-FF-FF-7F........LogicalMaximum(2,147,483,647)
95-01.................ReportCount(1)
75-20.................ReportSize(32)
81-02.................Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0................EndCollection()

Example 2

Simple consumer-control with 2 buttons; Volume Increment/Decrement. Only the usageRange and logicalValueRange are specified. count, sizeInBits, reportFlags are inferred.

Source

[[applicationCollection]]
usage = ['Consumer', 'Consumer Control']

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.variableItem]]
        usageRange = ['Consumer', 'Volume Increment', 'Volume Decrement']
        logicalValueRange = [0, 1]

Plain-text Output

05-0C....UsagePage(Consumer[12])
09-01....UsageId(Consumer Control[1])
A1-01....Collection(Application)
85-01........ReportId(1)
19-E9........UsageIdMin(Volume Increment[233])
29-EA........UsageIdMax(Volume Decrement[234])
15-00........LogicalMinimum(0)
25-01........LogicalMaximum(1)
95-02........ReportCount(2)
75-01........ReportSize(1)
81-02........Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
95-01........ReportCount(1)
75-06........ReportSize(6)
81-03........Input(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
C0.......EndCollection()

Example 3

Extract of a joystick descriptor, implementing 3 hat switches. Each 'step' 0-3 (as described by logicalValueRange) corresponds to 90° of movement (as described by unit). Total permitted movement is 270°. sizeInBits is inferred.

Source

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

    [[applicationCollection.inputReport]]

        [[applicationCollection.inputReport.variableItem]]
        usage = ['Generic Desktop', 'Hat Switch']
        logicalValueRange = [0, 3]
        physicalValueRange = [0, 270]
        unit = 'degrees'
        count = 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])
46-0E-01........PhysicalMaximum(270)
65-14...........Unit('degrees', EnglishRotation, Degrees:1)
55-00...........UnitExponent(1)
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()