@ac-kit/format-hid 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +28 -0
  3. package/README.md +96 -2
  4. package/dist/descriptor/hid-field-usage.d.ts +35 -0
  5. package/dist/descriptor/hid-field-usage.d.ts.map +1 -0
  6. package/dist/descriptor/hid-field-usage.js +63 -0
  7. package/dist/descriptor/hid-field-usage.js.map +1 -0
  8. package/dist/descriptor/hid-report-descriptor.d.ts +148 -0
  9. package/dist/descriptor/hid-report-descriptor.d.ts.map +1 -0
  10. package/dist/descriptor/hid-report-descriptor.js +15 -0
  11. package/dist/descriptor/hid-report-descriptor.js.map +1 -0
  12. package/dist/descriptor/parse-hid-report-descriptor.d.ts +30 -0
  13. package/dist/descriptor/parse-hid-report-descriptor.d.ts.map +1 -0
  14. package/dist/descriptor/parse-hid-report-descriptor.js +440 -0
  15. package/dist/descriptor/parse-hid-report-descriptor.js.map +1 -0
  16. package/dist/errors.d.ts +17 -0
  17. package/dist/errors.d.ts.map +1 -0
  18. package/dist/errors.js +20 -0
  19. package/dist/errors.js.map +1 -0
  20. package/dist/field/_field-value-bit-position.d.ts +7 -0
  21. package/dist/field/_field-value-bit-position.d.ts.map +1 -0
  22. package/dist/field/_field-value-bit-position.js +24 -0
  23. package/dist/field/_field-value-bit-position.js.map +1 -0
  24. package/dist/field/create-hid-report.d.ts +9 -0
  25. package/dist/field/create-hid-report.d.ts.map +1 -0
  26. package/dist/field/create-hid-report.js +14 -0
  27. package/dist/field/create-hid-report.js.map +1 -0
  28. package/dist/field/hid-field-layout.d.ts +7 -0
  29. package/dist/field/hid-field-layout.d.ts.map +1 -0
  30. package/dist/field/hid-field-layout.js +2 -0
  31. package/dist/field/hid-field-layout.js.map +1 -0
  32. package/dist/field/hid-logical-to-physical.d.ts +14 -0
  33. package/dist/field/hid-logical-to-physical.d.ts.map +1 -0
  34. package/dist/field/hid-logical-to-physical.js +27 -0
  35. package/dist/field/hid-logical-to-physical.js.map +1 -0
  36. package/dist/field/read-hid-field-value.d.ts +18 -0
  37. package/dist/field/read-hid-field-value.d.ts.map +1 -0
  38. package/dist/field/read-hid-field-value.js +35 -0
  39. package/dist/field/read-hid-field-value.js.map +1 -0
  40. package/dist/field/write-hid-field-value-in-place.d.ts +18 -0
  41. package/dist/field/write-hid-field-value-in-place.d.ts.map +1 -0
  42. package/dist/field/write-hid-field-value-in-place.js +41 -0
  43. package/dist/field/write-hid-field-value-in-place.js.map +1 -0
  44. package/dist/field/write-hid-field-value.d.ts +18 -0
  45. package/dist/field/write-hid-field-value.d.ts.map +1 -0
  46. package/dist/field/write-hid-field-value.js +41 -0
  47. package/dist/field/write-hid-field-value.js.map +1 -0
  48. package/dist/index.d.ts +18 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +18 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/item/_read-hid-item.d.ts +18 -0
  53. package/dist/item/_read-hid-item.d.ts.map +1 -0
  54. package/dist/item/_read-hid-item.js +48 -0
  55. package/dist/item/_read-hid-item.js.map +1 -0
  56. package/dist/item/decode-hid-items.d.ts +16 -0
  57. package/dist/item/decode-hid-items.d.ts.map +1 -0
  58. package/dist/item/decode-hid-items.js +24 -0
  59. package/dist/item/decode-hid-items.js.map +1 -0
  60. package/dist/item/encode-hid-items.d.ts +17 -0
  61. package/dist/item/encode-hid-items.d.ts.map +1 -0
  62. package/dist/item/encode-hid-items.js +74 -0
  63. package/dist/item/encode-hid-items.js.map +1 -0
  64. package/dist/item/hid-item-tag.d.ts +37 -0
  65. package/dist/item/hid-item-tag.d.ts.map +1 -0
  66. package/dist/item/hid-item-tag.js +40 -0
  67. package/dist/item/hid-item-tag.js.map +1 -0
  68. package/dist/item/hid-item-value.d.ts +20 -0
  69. package/dist/item/hid-item-value.d.ts.map +1 -0
  70. package/dist/item/hid-item-value.js +36 -0
  71. package/dist/item/hid-item-value.js.map +1 -0
  72. package/dist/item/hid-item.d.ts +32 -0
  73. package/dist/item/hid-item.d.ts.map +1 -0
  74. package/dist/item/hid-item.js +2 -0
  75. package/dist/item/hid-item.js.map +1 -0
  76. package/dist/unit/decode-hid-unit.d.ts +9 -0
  77. package/dist/unit/decode-hid-unit.d.ts.map +1 -0
  78. package/dist/unit/decode-hid-unit.js +26 -0
  79. package/dist/unit/decode-hid-unit.js.map +1 -0
  80. package/dist/unit/encode-hid-unit.d.ts +10 -0
  81. package/dist/unit/encode-hid-unit.d.ts.map +1 -0
  82. package/dist/unit/encode-hid-unit.js +32 -0
  83. package/dist/unit/encode-hid-unit.js.map +1 -0
  84. package/dist/unit/hid-unit.d.ts +29 -0
  85. package/dist/unit/hid-unit.d.ts.map +1 -0
  86. package/dist/unit/hid-unit.js +11 -0
  87. package/dist/unit/hid-unit.js.map +1 -0
  88. package/package.json +60 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ # @ac-kit/format-hid
2
+
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [aca1cb1]
8
+ - @ac-kit/core@0.4.0
9
+
10
+ ## 0.1.0
11
+
12
+ ### Minor Changes
13
+
14
+ - 992cbbb: New package: USB HID 1.11 report descriptors, from the raw items to the bits of
15
+ a single field.
16
+
17
+ - `decodeHidItems`/`encodeHidItems` split a descriptor into its short and long
18
+ items and spell them back byte for byte, with `HidMainTag`, `HidGlobalTag` and
19
+ `HidLocalTag` naming every tag and `hidItemUnsigned`/`hidItemSigned` reading
20
+ an item's value.
21
+ - `parseHidReportDescriptor` runs the HID 1.11 §6.2.2 state machine — Push/Pop,
22
+ local state cleared at every main item, extended usages, delimited sets,
23
+ Report IDs — into the collections, the reports with their length as
24
+ transferred, and the fields tiling each report, padding included. It reads
25
+ descriptors the way the Linux HID core does where devices and the
26
+ specification disagree: a Maximum is unsigned unless its Minimum is negative,
27
+ a one-byte Unit Exponent is a 4-bit nibble, and physical bounds both 0 mean
28
+ the logical range. Usage ranges stay ranges, so a whole-page range costs one
29
+ slot; `hidFieldUsage` resolves the usage of one element. A malformed
30
+ descriptor throws `HidDescriptorError` with the byte offset of the offending
31
+ item.
32
+ - `readHidFieldValue`, `writeHidFieldValueInPlace` and `createHidReport` read
33
+ and build report buffers at the field offsets the parser returns, Report ID
34
+ byte included, and `hidLogicalToPhysical` converts a value to its physical
35
+ quantity. `decodeHidUnit`/`encodeHidUnit` split the unit word into its system
36
+ and the exponent of each base quantity.
package/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024-2026 Anthony Champagne and contributors
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md CHANGED
@@ -1,3 +1,97 @@
1
- # Temporary Holding Version
1
+ # @ac-kit/format-hid
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ USB HID 1.11 report descriptors: what a device's reports look like, read from
4
+ the descriptor it publishes, and the bit-level access to read and build those
5
+ reports.
6
+
7
+ A HID device describes its own reports in a compact item language. Before a
8
+ single input report can be decoded, or an output report built, that language has
9
+ to be run through the state machine of HID 1.11 §6.2.2 — global state with
10
+ Push/Pop, local state cleared after every main item, Report IDs, usage ranges,
11
+ delimited sets. This package does that once and hands back a plain layout:
12
+ which reports exist, how long each is on the wire, and where every field sits.
13
+
14
+ ```ts
15
+ import {
16
+ createHidReport,
17
+ parseHidReportDescriptor,
18
+ readHidFieldValue,
19
+ writeHidFieldValueInPlace,
20
+ } from "@ac-kit/format-hid";
21
+
22
+ const { reports } = parseHidReportDescriptor(descriptorBytes);
23
+
24
+ const input = reports.find((report) => report.kind === "input" && report.reportId === 0x01)!;
25
+ readHidFieldValue(received, input.fields[2]!, 0); // logical value of element 0
26
+
27
+ const lights = reports.find((report) => report.kind === "output" && report.reportId === 0x82)!;
28
+ const bytes = createHidReport(lights); // zeroed, bytes[0] === 0x82
29
+ writeHidFieldValueInPlace(bytes, lights.fields[0]!, 182, 127);
30
+ ```
31
+
32
+ It reads no device: get the descriptor from wherever the platform exposes it —
33
+ `/sys/class/hidraw/*/device/report_descriptor` on Linux, a USB `GET_DESCRIPTOR`
34
+ request — and move reports with whatever transport you already have.
35
+
36
+ ## Three levels
37
+
38
+ - **Items** — `decodeHidItems` splits a descriptor into raw `HidItem`s and
39
+ `encodeHidItems` spells them back, byte for byte. Use it to inspect, patch or
40
+ generate a descriptor. `HidMainTag`, `HidGlobalTag` and `HidLocalTag` name
41
+ every tag; `hidItemUnsigned`/`hidItemSigned` read an item's value.
42
+ - **Descriptor** — `parseHidReportDescriptor` returns the `collections`, the
43
+ `reports` and whether the device `usesReportIds`. Each `HidReportField` carries
44
+ its position, size, count, data flags, logical and physical ranges, unit, and
45
+ its usages, designators and strings as slots. `hidFieldUsage` gives the usage
46
+ an element refers to.
47
+ - **Field values** — `readHidFieldValue`, `writeHidFieldValueInPlace`,
48
+ `createHidReport` and `hidLogicalToPhysical` work on a report buffer.
49
+ `decodeHidUnit`/`encodeHidUnit` split the unit word into its system and
50
+ exponents.
51
+
52
+ ## Reports as transferred
53
+
54
+ Every position is counted from the first bit of the report **as it travels on
55
+ the wire**: when the descriptor uses Report IDs, the ID is byte 0, the first
56
+ field starts at bit 8, and `byteLength` includes it. That is what `read()` on a
57
+ Linux `hidraw` node returns, and what `write()` on one takes for a device using
58
+ Report IDs (for one that does not, `hidraw` wants an extra leading 0 byte).
59
+ WebHID strips the ID byte from `inputreport` events and takes it as a separate
60
+ argument to `sendReport`; put it back in front, or build the buffer with
61
+ `createHidReport`, before using the field offsets.
62
+
63
+ Padding and constant fields are kept, so a report's fields tile it completely.
64
+
65
+ ## Where real devices and the specification disagree
66
+
67
+ The parser reads descriptors the way the Linux HID core does, because that is
68
+ what devices are tested against:
69
+
70
+ - A Logical or Physical Maximum is **unsigned unless its Minimum is negative**:
71
+ `Logical Minimum (0)`, `Logical Maximum (0xFF)` is 0–255, not 0 to -1.
72
+ - A one-byte Unit Exponent of 0–15 is a 4-bit two's-complement nibble, so
73
+ `0x0E` is -2.
74
+ - A Usage declared before a later Usage Page takes the page in effect at the
75
+ main item.
76
+ - Physical Minimum and Maximum both 0 means the physical range is the logical
77
+ one.
78
+
79
+ ## Usages
80
+
81
+ A usage is an unsigned 32-bit number, `page << 16 | id`; a 4-byte Usage item is
82
+ taken whole as such an extended usage. `Usage Minimum`/`Usage Maximum` pairs stay
83
+ ranges — a field covering a whole 65 536-usage page costs one slot — and a
84
+ delimited set becomes one slot whose first usage is preferred and whose others
85
+ are its `aliases`. For a variable field with fewer usages than values, the last
86
+ usage applies to every remaining element.
87
+
88
+ ## Errors
89
+
90
+ A malformed descriptor throws `HidDescriptorError`, a `SyntaxError` carrying the
91
+ byte `offset` of the item the parser gave up at. An argument the caller built
92
+ that cannot be honoured — an item `encodeHidItems` cannot spell, a value that
93
+ does not fit its field, an index past `count` — is a `RangeError`.
94
+
95
+ See the
96
+ [generated API docs](https://anthochamp.github.io/node-essentials/api/format-hid/)
97
+ for the full reference.
@@ -0,0 +1,35 @@
1
+ import type { HidFieldFlags, HidReportField, HidSlot } from "./hid-report-descriptor.js";
2
+ /**
3
+ * The value at position `index` of a slot list once its ranges are expanded, or
4
+ * `undefined` past the end. Ranges are never materialized.
5
+ *
6
+ * Use {@link hidFieldUsage} for a field's usages, which applies the HID rule for
7
+ * a variable field with fewer usages than values.
8
+ *
9
+ * O(n) time in `slots.length`, O(1) memory.
10
+ *
11
+ * @throws {RangeError} When `index` is not a non-negative integer.
12
+ */
13
+ export declare function hidSlotValue(slots: readonly HidSlot[], index: number): number | undefined;
14
+ /**
15
+ * The usage a field's value refers to.
16
+ *
17
+ * - **Variable field** — `index` is the element, `0 ≤ index < count`. When the
18
+ * field declares fewer usages than values, the last usage applies to every
19
+ * remaining element (HID 1.11 §6.2.2.8).
20
+ * - **Array field** — `index` is a position in the usage list, i.e. a received
21
+ * value minus `logicalMinimum`. A position past the list is `undefined`, as
22
+ * is any position in a field declaring no usage (padding).
23
+ *
24
+ * Aliases of a delimited set are on {@link HidReportField.usages}; this answers
25
+ * the preferred usage only.
26
+ *
27
+ * O(n) time in `field.usages.length`, O(1) memory.
28
+ *
29
+ * @throws {RangeError} When `index` is negative or not an integer, or is
30
+ * `count` or more for a variable field.
31
+ */
32
+ export declare function hidFieldUsage(field: Pick<HidReportField, "count" | "usages"> & {
33
+ flags: Pick<HidFieldFlags, "variable">;
34
+ }, index: number): number | undefined;
35
+ //# sourceMappingURL=hid-field-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hid-field-usage.d.ts","sourceRoot":"","sources":["../../src/descriptor/hid-field-usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,aAAa,EACb,cAAc,EACd,OAAO,EACP,MAAM,4BAA4B,CAAC;AAMpC;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC3B,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,KAAK,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAiBpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC5B,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG;IACjD,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;CACvC,EACD,KAAK,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAoBpB"}
@@ -0,0 +1,63 @@
1
+ function slotLength_(slot) {
2
+ return slot.kind === "single" ? 1 : slot.maximum - slot.minimum + 1;
3
+ }
4
+ /**
5
+ * The value at position `index` of a slot list once its ranges are expanded, or
6
+ * `undefined` past the end. Ranges are never materialized.
7
+ *
8
+ * Use {@link hidFieldUsage} for a field's usages, which applies the HID rule for
9
+ * a variable field with fewer usages than values.
10
+ *
11
+ * O(n) time in `slots.length`, O(1) memory.
12
+ *
13
+ * @throws {RangeError} When `index` is not a non-negative integer.
14
+ */
15
+ export function hidSlotValue(slots, index) {
16
+ if (!Number.isInteger(index) || index < 0) {
17
+ throw new RangeError(`hidSlotValue: index ${index} is not a non-negative integer`);
18
+ }
19
+ let remaining = index;
20
+ for (const slot of slots) {
21
+ const length = slotLength_(slot);
22
+ if (remaining < length) {
23
+ return slot.kind === "single" ? slot.value : slot.minimum + remaining;
24
+ }
25
+ remaining -= length;
26
+ }
27
+ return undefined;
28
+ }
29
+ /**
30
+ * The usage a field's value refers to.
31
+ *
32
+ * - **Variable field** — `index` is the element, `0 ≤ index < count`. When the
33
+ * field declares fewer usages than values, the last usage applies to every
34
+ * remaining element (HID 1.11 §6.2.2.8).
35
+ * - **Array field** — `index` is a position in the usage list, i.e. a received
36
+ * value minus `logicalMinimum`. A position past the list is `undefined`, as
37
+ * is any position in a field declaring no usage (padding).
38
+ *
39
+ * Aliases of a delimited set are on {@link HidReportField.usages}; this answers
40
+ * the preferred usage only.
41
+ *
42
+ * O(n) time in `field.usages.length`, O(1) memory.
43
+ *
44
+ * @throws {RangeError} When `index` is negative or not an integer, or is
45
+ * `count` or more for a variable field.
46
+ */
47
+ export function hidFieldUsage(field, index) {
48
+ if (!field.flags.variable) {
49
+ return hidSlotValue(field.usages, index);
50
+ }
51
+ if (!Number.isInteger(index) || index < 0 || index >= field.count) {
52
+ throw new RangeError(`hidFieldUsage: index ${index} is outside 0–${field.count - 1}`);
53
+ }
54
+ let total = 0;
55
+ for (const slot of field.usages) {
56
+ total += slotLength_(slot);
57
+ }
58
+ if (total === 0) {
59
+ return undefined;
60
+ }
61
+ return hidSlotValue(field.usages, Math.min(index, total - 1));
62
+ }
63
+ //# sourceMappingURL=hid-field-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hid-field-usage.js","sourceRoot":"","sources":["../../src/descriptor/hid-field-usage.ts"],"names":[],"mappings":"AAMA,SAAS,WAAW,CAAC,IAAa;IACjC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAC3B,KAAyB,EACzB,KAAa;IAEb,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,UAAU,CACnB,uBAAuB,KAAK,gCAAgC,CAC5D,CAAC;IACH,CAAC;IAED,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,SAAS,GAAG,MAAM,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACvE,CAAC;QACD,SAAS,IAAI,MAAM,CAAC;IACrB,CAAC;IAED,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,aAAa,CAC5B,KAEC,EACD,KAAa;IAEb,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3B,OAAO,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QACnE,MAAM,IAAI,UAAU,CACnB,wBAAwB,KAAK,iBAAiB,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,CAC/D,CAAC;IACH,CAAC;IAED,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjC,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,OAAO,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Collection types of the Collection main item (HID 1.11 §6.2.2.6). 0x07–0x7F
3
+ * are reserved, 0x80–0xFF vendor-defined.
4
+ */
5
+ export declare enum HidCollectionType {
6
+ PHYSICAL = 0,
7
+ APPLICATION = 1,
8
+ LOGICAL = 2,
9
+ REPORT = 3,
10
+ NAMED_ARRAY = 4,
11
+ USAGE_SWITCH = 5,
12
+ USAGE_MODIFIER = 6
13
+ }
14
+ /** Which of the three report kinds a field belongs to. */
15
+ export type HidReportKind = "input" | "output" | "feature";
16
+ /**
17
+ * One position, or a run of positions, in a field's list of usages, designators
18
+ * or strings.
19
+ *
20
+ * Usages are 32-bit extended usages, `page << 16 | id`, read as unsigned.
21
+ * Designators and strings are plain indexes and never carry aliases.
22
+ */
23
+ export type HidSlot = {
24
+ kind: "single";
25
+ value: number;
26
+ /**
27
+ * The other usages of a delimited set (HID 1.11 §6.2.2.8), in declaration
28
+ * order.
29
+ */
30
+ aliases: number[];
31
+ } | {
32
+ kind: "range";
33
+ /** First value of the range, inclusive. */
34
+ minimum: number;
35
+ /** Last value of the range, inclusive. Never below `minimum`. */
36
+ maximum: number;
37
+ };
38
+ /** One collection, in a flat table in descriptor (pre-)order. */
39
+ export type HidCollection = {
40
+ /**
41
+ * A {@link HidCollectionType}, or the raw number of a reserved or
42
+ * vendor-defined type.
43
+ */
44
+ type: number;
45
+ /**
46
+ * The first usage declared before the Collection item, or `undefined` when
47
+ * there was none.
48
+ */
49
+ usage: number | undefined;
50
+ /**
51
+ * Index of the enclosing collection in the same table, or -1 at the top
52
+ * level.
53
+ */
54
+ parentIndex: number;
55
+ };
56
+ /**
57
+ * The data bits of an Input, Output or Feature main item (HID 1.11 §6.2.2.5),
58
+ * one boolean per bit.
59
+ */
60
+ export type HidFieldFlags = {
61
+ /** Bit 0: the values are fixed padding rather than data. */
62
+ constant: boolean;
63
+ /**
64
+ * Bit 1: one value per usage (variable) rather than a list of active usages
65
+ * (array).
66
+ */
67
+ variable: boolean;
68
+ /** Bit 2: values are deltas from the previous report rather than absolute. */
69
+ relative: boolean;
70
+ /** Bit 3: values wrap from one extreme to the other. */
71
+ wrap: boolean;
72
+ /** Bit 4: the data is not linear in what it measures. */
73
+ nonLinear: boolean;
74
+ /** Bit 5: the control has no rest position. */
75
+ noPreferredState: boolean;
76
+ /** Bit 6: a value outside the logical range means "no data". */
77
+ nullState: boolean;
78
+ /**
79
+ * Bit 7: the device may change the value on its own. Always `false` for an
80
+ * input field, whose bit 7 is reserved.
81
+ */
82
+ volatile: boolean;
83
+ /** Bit 8: the field is a byte stream rather than a number. */
84
+ bufferedBytes: boolean;
85
+ };
86
+ /**
87
+ * One Input, Output or Feature main item: `count` values of `bitSize` bits
88
+ * each, packed little-endian and least significant bit first.
89
+ */
90
+ export type HidReportField = {
91
+ kind: HidReportKind;
92
+ /**
93
+ * The report this field belongs to, or 0 when the descriptor declares no
94
+ * Report ID.
95
+ */
96
+ reportId: number;
97
+ /**
98
+ * Position of the field's first bit from the first bit of the report as
99
+ * transferred — the Report ID byte included when there is one.
100
+ */
101
+ bitOffset: number;
102
+ /** Report Size: bits per value. */
103
+ bitSize: number;
104
+ /** Report Count: number of values. */
105
+ count: number;
106
+ flags: HidFieldFlags;
107
+ logicalMinimum: number;
108
+ logicalMaximum: number;
109
+ /** Equal to `logicalMinimum` when the descriptor leaves both physical bounds 0. */
110
+ physicalMinimum: number;
111
+ /** Equal to `logicalMaximum` when the descriptor leaves both physical bounds 0. */
112
+ physicalMaximum: number;
113
+ /** The raw unit word; see {@link decodeHidUnit}. */
114
+ unit: number;
115
+ /** Base-10 exponent applied to physical values. */
116
+ unitExponent: number;
117
+ /**
118
+ * Usage slots in declaration order; see {@link hidFieldUsage}. Empty for
119
+ * padding.
120
+ */
121
+ usages: HidSlot[];
122
+ designators: HidSlot[];
123
+ strings: HidSlot[];
124
+ /**
125
+ * Index in {@link HidReportDescriptor.collections} of the innermost enclosing
126
+ * collection, or -1.
127
+ */
128
+ collectionIndex: number;
129
+ };
130
+ /** Every field one report carries, and its size on the wire. */
131
+ export type HidReport = {
132
+ kind: HidReportKind;
133
+ /** 0 when the descriptor declares no Report ID. */
134
+ reportId: number;
135
+ /** Bytes as transferred, the Report ID byte included. */
136
+ byteLength: number;
137
+ /** In descriptor order, padding included, so the fields tile the report. */
138
+ fields: HidReportField[];
139
+ };
140
+ /** The reports and collections a report descriptor declares. */
141
+ export type HidReportDescriptor = {
142
+ collections: HidCollection[];
143
+ /** In order of first appearance. */
144
+ reports: HidReport[];
145
+ /** Whether every report starts with a Report ID byte. */
146
+ usesReportIds: boolean;
147
+ };
148
+ //# sourceMappingURL=hid-report-descriptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hid-report-descriptor.d.ts","sourceRoot":"","sources":["../../src/descriptor/hid-report-descriptor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Collection types of the Collection main item (HID 1.11 §6.2.2.6). 0x07–0x7F
3
+ * are reserved, 0x80–0xFF vendor-defined.
4
+ */
5
+ export var HidCollectionType;
6
+ (function (HidCollectionType) {
7
+ HidCollectionType[HidCollectionType["PHYSICAL"] = 0] = "PHYSICAL";
8
+ HidCollectionType[HidCollectionType["APPLICATION"] = 1] = "APPLICATION";
9
+ HidCollectionType[HidCollectionType["LOGICAL"] = 2] = "LOGICAL";
10
+ HidCollectionType[HidCollectionType["REPORT"] = 3] = "REPORT";
11
+ HidCollectionType[HidCollectionType["NAMED_ARRAY"] = 4] = "NAMED_ARRAY";
12
+ HidCollectionType[HidCollectionType["USAGE_SWITCH"] = 5] = "USAGE_SWITCH";
13
+ HidCollectionType[HidCollectionType["USAGE_MODIFIER"] = 6] = "USAGE_MODIFIER";
14
+ })(HidCollectionType || (HidCollectionType = {}));
15
+ //# sourceMappingURL=hid-report-descriptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hid-report-descriptor.js","sourceRoot":"","sources":["../../src/descriptor/hid-report-descriptor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAN,IAAY,iBAQX;AARD,WAAY,iBAAiB;IAC5B,iEAAe,CAAA;IACf,uEAAkB,CAAA;IAClB,+DAAc,CAAA;IACd,6DAAa,CAAA;IACb,uEAAkB,CAAA;IAClB,yEAAmB,CAAA;IACnB,6EAAqB,CAAA;AACtB,CAAC,EARW,iBAAiB,KAAjB,iBAAiB,QAQ5B"}
@@ -0,0 +1,30 @@
1
+ import type { HidReportDescriptor } from "./hid-report-descriptor.js";
2
+ /**
3
+ * Reads a report descriptor into the reports a device sends and accepts, the
4
+ * fields that tile each one, and the collections around them — the HID 1.11
5
+ * §6.2.2 item state machine, with Push/Pop, delimited sets and extended
6
+ * usages.
7
+ *
8
+ * Use {@link decodeHidItems} instead to see or rewrite the items themselves.
9
+ *
10
+ * Follows the Linux reading wherever real devices and the letter of the spec
11
+ * disagree: a Logical or Physical Maximum is unsigned unless its Minimum is
12
+ * negative, so `0xFF` means 255; a one-byte Unit Exponent of 0–15 is a 4-bit
13
+ * two's-complement nibble; a Usage declared before a later Usage Page takes the
14
+ * page in effect at the main item. Long items, reserved main and local tags and
15
+ * reserved item types are skipped.
16
+ *
17
+ * Usage ranges are kept as ranges, so a field declaring `Usage Minimum (0)`,
18
+ * `Usage Maximum (0xFFFF)` costs one slot, not 65 536.
19
+ *
20
+ * O(n) time and memory in `bytes.length`.
21
+ *
22
+ * @throws {HidDescriptorError} When an item is truncated, a collection is left
23
+ * open or closed twice, `Pop` meets an empty stack, a data item has no Report
24
+ * Size or Report Count, a report grows past 65 535 bytes, a Report ID is 0, a
25
+ * data item carries no Report ID in a descriptor that declares one, a usage,
26
+ * designator or string range is unpaired or reversed, a delimited set is
27
+ * nested or unbalanced, or a reserved global tag appears.
28
+ */
29
+ export declare function parseHidReportDescriptor(bytes: Uint8Array): HidReportDescriptor;
30
+ //# sourceMappingURL=parse-hid-report-descriptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-hid-report-descriptor.d.ts","sourceRoot":"","sources":["../../src/descriptor/parse-hid-report-descriptor.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAGX,mBAAmB,EAInB,MAAM,4BAA4B,CAAC;AAokBpC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,wBAAwB,CACvC,KAAK,EAAE,UAAU,GACf,mBAAmB,CAErB"}