Das HID-Protokoll (Human Interface Device) für den Head-Tracker, das für Geräte mit Android 13 und höher verfügbar ist, ermöglicht die Verbindung eines Head-Tracking-Geräts über USB oder Bluetooth mit einem Android-Gerät und die Bereitstellung für das Android-Framework und Apps über das Sensors-Framework. Dieses Protokoll wird für steuern einen Audio-Virtualizer-Effekt (3D-Audio). Auf dieser Seite werden die Begriffe Gerät und Host im Bluetooth-Sinne verwendet. Dabei steht Gerät für das Gerät zur Kopfverfolgung und Host für den Android-Host.
Gerätehersteller müssen ihre Android-Geräte so konfigurieren, dass sie die Unterstützung für das HID-Protokoll des Kopf-Trackers. Nähere Informationen über finden Sie in der README-Datei für dynamische Sensoren
Auf dieser Seite wird davon ausgegangen, dass Sie mit den folgenden Ressourcen vertraut sind:
Struktur der obersten Ebene
Das Android-Framework identifiziert das Kopf-Tracker-Gerät als HID-Gerät.
Ein vollständiges Beispiel für einen gültigen HID-Descriptor finden Sie unter Anhang 1: Beispiel für einen HID-Descriptor.
Auf der obersten Ebene ist das Kopf-Tracker-Gerät eine App-Sammlung mit dem
Sensors
Seite (0x20
) und die Other: Custom
-Nutzung (0xE1
). In diesem
Sammlung besteht aus mehreren Datenfeldern (Eingaben) und Eigenschaften (Features).
Eigenschaften und Datenfelder
In diesem Abschnitt werden die Eigenschaften und Datenfelder in einer Anwendungssammlung eines Kopf-Trackers beschrieben.
Eigenschaft: Sensorbeschreibung (0x0308
)
Die Eigenschaft „Sensor Description“ (0x0308
) ist ein schreibgeschütztes ASCII-String-Attribut (8 Bit), das die folgenden Werte enthalten muss:
Kopf-Tracker Version 1.0:
#AndroidHeadTracker#1.0
Kopf-Tracker-Version 2.0 (verfügbar mit Android 15 oder )), wobei auch LE Audio unterstützt wird:
#AndroidHeadTracker#2.0#x
x
ist eine Ganzzahl (1
, 2
, 3
), die den unterstützten Transport angibt:
- 1: ACL
- 2: ISO
- 3: ACL und ISO
Es wird kein Nullterminator erwartet. Die Gesamtgröße dieses Attributs beträgt also 23 8‑Bit-Zeichen für Version 1.0.
Diese Property dient als Unterscheidungsmerkmal, um Kollisionen mit anderen benutzerdefinierten Sensoren zu vermeiden.
Property: Persistent Unique ID (0x0302
)
Die Eigenschaft „Persistent Unique ID“ (0x0302
) ist ein schreibgeschütztes Array mit 16 Elementen mit jeweils 8 Bit (insgesamt 128 Bit). Es wird kein Nullabschlusszeichen erwartet. Dieses Attribut ist optional.
Mit dieser Eigenschaft sind Headtracking-Geräte möglich, die in Audio integriert sind. Geräte so, dass sie auf das Audiogerät verweisen, mit dem sie verbunden sind. Die folgenden Schemas werden unterstützt.
Eigenständiger Kopf-Tracker
Wenn das Attribut „Persistente eindeutige ID“ (0x0302
) nicht vorhanden oder auf „Alle“ festgelegt ist
bedeutet dies, dass der Kopf-Tracker nicht dauerhaft mit einem
Audiogerät und kann separat verwendet werden, z. B. indem der Nutzer
den Kopf-Tracker manuell mit einem separaten Audiogerät verknüpfen.
Referenz mit Bluetooth-MAC-Adresse
Oktett | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Wert | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | B | T | Bluetooth-MAC |
Bei diesem Schema müssen die ersten acht Oktette 0
sein, die Oktette 8 und 9 müssen
die ASCII-Werte B
bzw. T
und die folgenden 6 Oktette sind
als Bluetooth-MAC-Adresse interpretiert, unter der Annahme, dass das Kopf-Tracker-Gerät
gilt für alle Audiogeräte mit dieser MAC-Adresse. Diese Adresse muss die Identitätsadresse sein, auch wenn das Gerät eine zufällige MAC-Adresse zum Herstellen von Verbindungen verwendet. Dual-Mode-Geräte, die sich über Bluetooth Classic verbinden
(HID-Format v1.0) und Bluetooth LE (HID-Format v2.0) müssen zwei HID verfügbar machen.
Deskriptoren mit derselben Identitätsadresse. Dual-Mode-Geräte mit getrennten
das linke und das rechte Gerät muss Bluetooth LE HID über die primäre Dual-
Gerät im Modus statt auf das sekundäre Gerät nur für LE.
Referenz mit UUID
Wenn das höchstwertige Bit (MSB) von Oktett 8 (≥0x80
) festgelegt wird, wird das Feld
als UUID interpretiert, wie in
RFC-4122. Die
dasselbe Audiogerät dieselbe UUID auf, die unter
des Android-Frameworks mithilfe eines nicht angegebenen Mechanismus für die
Art des verwendeten Transportmittels.
Property: Meldestatus (0x0316
)
Das Attribut „Reporting State“ (0x0316
) ist ein Lese-/Schreibattribut mit der Standardsemantik, wie in der HID-Spezifikation definiert. Der Host verwendet dieses Attribut, um dem Gerät mitzuteilen, welche Ereignisse gemeldet werden sollen. Nur die Werte „Nein“
Es werden die Ereignisse "0x0840
" und "Alle Ereignisse" (0x0841
) verwendet.
Der Anfangswert dieses Feldes darf „No Events“ (Keine Ereignisse) sein. vom Gerät, nur vom Host verändert.
Property: Leistungszustand (0x0319
)
Das Attribut „Leistungsstatus“ (0x0319
) ist ein Lese-/Schreibattribut mit
Standardsemantik, wie in der HID-Spezifikation definiert. Der Host verwendet diese Property, um dem Gerät mitzuteilen, in welchem Betriebsstatus es sich befinden muss. Es werden nur die Werte „Vollständig ein“ (0x0851
) und „Aus“ (0x0855
) verwendet.
Der Anfangswert für dieses Feld wird vom Gerät bestimmt und darf niemals vom Gerät, sondern nur vom Host geändert werden.
Property: Berichtszeitraum (0x030E
)
Das Attribut „Berichtsintervall“ (0x030E
) ist eine Lese-/Schreibeigenschaft mit folgendem Wert:
Standardsemantik, wie in der HID-Spezifikation definiert. Der Host gibt mit dieser Property an, wie oft das Gerät seine Datenwerte melden soll.
Die Einheit sind Sekunden. Der gültige Bereich für diesen Wert wird vom Gerät bestimmt und mit dem Mechanismus „Physikalisches Minimum/Maximum“ beschrieben. Mindestens 50 Hz
Reporting-Rate muss unterstützt werden und die empfohlene maximale Reporting-Rate ist
100 Hz. Daher muss das minimale Berichtsintervall kleiner oder gleich sein
auf 20 ms und wird empfohlen, größer oder gleich 10 ms zu sein.
Property: Vendor-reserved LE Transport (0xF410
)
Das Attribut für den vom Anbieter reservierten LE-Transport (0xF410
) ist ein Lese-/Schreibattribut
die die in der HID-Spezifikation definierte Standardsemantik hat. Der Host verwendet diese Property, um den ausgewählten Transport (ACL oder ISO) anzugeben. Nur die
Die Werte ACL (0xF800
) und ISO (0xF801
) werden verwendet und müssen beide angegeben werden
in der logischen Sammlung.
Diese Eigenschaft wird vor dem Ein/Aus- oder Berichterstellungsstatus konfiguriert.
Datenfeld: Benutzerdefinierter Wert 1 (0x0544
)
Das Feld Benutzerdefinierter Wert 1 (0x0544
) ist ein Eingabefeld für die
Informationen zur Erfassung von Kopfbewegungen. Es ist ein Array mit drei Elementen,
die normalen HID-Regeln für physikalische Werte, wie in Abschnitt 6.2.2.7
die HID-Spezifikation. Der gültige Bereich für jedes Element ist [-hol, pi] rad. Einheiten
sind immer Radianten.
Die Elemente werden so interpretiert: [rx, ry, rz]
, wobei [rx, ry, rz]
ein
Rotationsvektor,
die die Transformation vom Referenzframe zum Headframe darstellt.
Die Magnitude muss im Bereich [0–...] liegen.
Der Referenzrahmen ist beliebig, aber in der Regel fixiert und muss rechtshänderisch sein. Eine geringe Abweichung ist akzeptabel. Die Kopfachsen sind:
- X vom linken Ohr nach rechts
- Y vom Hinterkopf zur Nase (hinten nach vorne)
- Z vom Hals bis zum Scheitel
Datenfeld: Benutzerdefinierter Wert 2 (0x0545
)
Das Feld „Benutzerdefinierter Wert 2“ (0x0545
) ist ein Eingabefeld, in dem die tatsächlichen Informationen zur Kopfverfolgung erfasst werden. Es ist ein 3-Element-Fixpunktarray, das gemäß den normalen HID-Regeln für physikalische Werte interpretiert wird.
Die Einheiten sind immer Radian/Sekunde.
Die Elemente werden als [vx, vy, vz]
interpretiert, wobei [vx, vy, vz]
ein Drehvektor ist, der die Winkelgeschwindigkeit des Kopf-Frames (relativ zu sich selbst) darstellt.
Datenfeld: Benutzerdefinierter Wert 3 (0x0546
)
Das Feld „Benutzerdefinierter Wert 3“ (0x0546
) ist ein Eingabefeld, mit dem Unterbrechungen im Referenzrahmen erfasst werden. Es ist eine skalare Ganzzahl 8 Bit
Größe. Er muss jedes Mal vom Gerät inkrementiert (mit Überlauf) werden, wenn sich der Referenzrahmen ändert, z. B. wenn der Status eines Algorithmus für den Ausrichtungsfilter zurückgesetzt wurde, der zur Bestimmung der Ausrichtung verwendet wird. Dieser Wert ist
wird gemäß den normalen HID-Regeln für physikalische Werte interpretiert. Sie können jedoch
der physikalische Wert
und die Einheiten spielen keine Rolle. Die einzigen Informationen, die für den
„host“ ein geänderter Wert ist. Um Probleme mit der Genauigkeit bei der Umwandlung von logischen in physikalische Einheiten zu vermeiden, sollten Sie die Werte für „Physikalisches Minimum“, „Physikalisches Maximum“ und „Einheitsexponent“ für dieses Feld auf null setzen.
Berichtsstruktur
Die Gruppierung von Properties in Berichten (durch Zuweisung von Berichts-IDs) ist flexibel. Aus Effizienzgründen empfehlen wir, die schreibgeschützten Eigenschaften zu trennen. aus den Lese-/Schreib-Attributen.
Bei den Datenfeldern müssen die Felder „Benutzerdefinierter Wert 1“, „Benutzerdefinierter Wert 2“ und „Benutzerdefinierter Wert 3“ im selben Bericht und nur in einem Bericht für ein bestimmtes Gerät (App-Sammlung) enthalten sein.
Eingabeberichte senden
Das Gerät muss Eingabeberichte regelmäßig und asynchron (über HID-Eingabenachrichten) senden, wenn alle folgenden Bedingungen erfüllt sind:
- Die Property „Power State“ ist auf „Full Power“ gesetzt.
- Die Eigenschaft Berichtsstatus ist auf "Alle Ereignisse" festgelegt.
- Die Eigenschaft Reporting-Intervall ist ungleich null.
Mit der Eigenschaft "Berichtsintervall" wird festgelegt, wie oft die Berichte gesendet werden. Wenn eine der oben genannten Bedingungen nicht erfüllt ist, darf das Gerät keine Berichte senden.
Vorwärts- und Abwärtskompatibilität
Für das HID-Protokoll des Kopf-Trackers wird ein Versionierungsschema verwendet, und gleichzeitig die Interoperabilität zwischen einem Host und einem Gerät, Versionen des Protokolls. Versionen für das Protokoll sind identifiziert zwei Zahlen, Dur und Moll, die eine unterschiedliche Semantik haben, die in den folgenden Abschnitten beschrieben werden.
Welche Versionen von einem Gerät unterstützt werden, kann ermittelt werden, indem
seine Eigenschaft „Sensorbeschreibung“ (0x0308
).
Kompatibilität mit Nebenversionen
Änderungen an der Nebenversion sind abwärtskompatibel mit früheren Nebenversionen Versionen, die auf derselben Hauptversion basieren. Bei Updates der Minorversion ignoriert der Host zusätzliche Datenfelder und -eigenschaften. Beispiel: Ein Gerät, das die Protokollversion 1.6 verwendet, ist mit einem Host kompatibel, der Protokollversion 1.x, einschließlich Version 1.5.
Kompatibilität mit Hauptversionen
Nicht abwärtskompatible Änderungen sind für Änderungen an Hauptversionen zulässig. Bis mehrere Hauptversionen für die Interoperabilität mit alten und neuen Hosts, Geräte können in ihrem Bericht mehrere App-Sammlungen angeben. Beschreibungen. Beispiel:
const unsigned char ReportDescriptor[] = {
HID_USAGE_PAGE_SENSOR,
HID_USAGE_SENSOR_TYPE_OTHER_CUSTOM,
HID_COLLECTION(HID_APPLICATION),
// Feature report 2 (read-only).
HID_REPORT_ID(2),
// Magic value: "#AndroidHeadTracker#1.5"
HID_USAGE_SENSOR_PROPERTY_SENSOR_DESCRIPTION,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(23),
HID_FEATURE(HID_CONST_VAR_ABS),
...
HID_END_COLLECTION,
HID_COLLECTION(HID_APPLICATION),
// Feature report 12 (read-only).
HID_REPORT_ID(12),
// Magic value: "#AndroidHeadTracker#2.4"
HID_USAGE_SENSOR_PROPERTY_SENSOR_DESCRIPTION,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(23),
HID_FEATURE(HID_CONST_VAR_ABS),
...
HID_END_COLLECTION,
};
In diesem Fall kann der Host alle vom Gerät beworbenen App-Sammlungen auflisten, die Sensorbeschreibungseigenschaft prüfen, um die jeweils implementierten Protokollversionen zu ermitteln, und dann die neueste Protokollversion auswählen, die der Host unterstützt. Bei der Auswahl funktioniert der Organisator mit dem einzelnen Protokoll, das für die Lebensdauer des Geräts ausgewählt wurde
Anhang: Beispiel für einen HID-Deskriptor
Das folgende Beispiel zeigt einen typischen gültigen HID-Deskriptor. Es verwendet die gängigen C-Makros, die in HID-Sensornutzungen (Abschnitt 4.1) bereitgestellt werden.
const unsigned char ReportDescriptor[] = {
HID_USAGE_PAGE_SENSOR,
HID_USAGE_SENSOR_TYPE_OTHER_CUSTOM,
HID_COLLECTION(HID_APPLICATION),
// Feature report 2 (read-only).
HID_REPORT_ID(2),
// Magic value: "#AndroidHeadTracker#1.0"
HID_USAGE_SENSOR_PROPERTY_SENSOR_DESCRIPTION,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(23),
HID_FEATURE(HID_CONST_VAR_ABS),
// UUID.
HID_USAGE_SENSOR_PROPERTY_PERSISTENT_UNIQUE_ID,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(16),
HID_FEATURE(HID_CONST_VAR_ABS),
// Feature report 1 (read/write).
HID_REPORT_ID(1),
// 1-bit on/off reporting state.
HID_USAGE_SENSOR_PROPERTY_REPORTING_STATE,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(1),
HID_REPORT_SIZE(1),
HID_REPORT_COUNT(1),
HID_COLLECTION(HID_LOGICAL),
HID_USAGE_SENSOR_PROPERTY_REPORTING_STATE_NO_EVENTS,
HID_USAGE_SENSOR_PROPERTY_REPORTING_STATE_ALL_EVENTS,
HID_FEATURE(HID_DATA_ARR_ABS),
HID_END_COLLECTION,
// 1-bit on/off power state.
HID_USAGE_SENSOR_PROPERTY_POWER_STATE,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(1),
HID_REPORT_SIZE(1),
HID_REPORT_COUNT(1),
HID_COLLECTION(HID_LOGICAL),
HID_USAGE_SENSOR_PROPERTY_POWER_STATE_D4_POWER_OFF,
HID_USAGE_SENSOR_PROPERTY_POWER_STATE_D0_FULL_POWER,
HID_FEATURE(HID_DATA_ARR_ABS),
HID_END_COLLECTION,
// 6-bit reporting interval, with values [0x00..0x3F] corresponding to [10ms..100ms].
HID_USAGE_SENSOR_PROPERTY_REPORT_INTERVAL,
HID_LOGICAL_MIN_8(0x00),
HID_LOGICAL_MAX_8(0x3F),
HID_PHYSICAL_MIN_8(10),
HID_PHYSICAL_MAX_8(100),
HID_REPORT_SIZE(6),
HID_REPORT_COUNT(1),
HID_USAGE_SENSOR_UNITS_SECOND,
HID_UNIT_EXPONENT(0xD), // 10^-3
HID_FEATURE(HID_DATA_VAR_ABS),
// Input report 1
// Orientation as rotation vector (scaled to [-pi..pi] rad).
HID_USAGE_SENSOR_DATA_CUSTOM_VALUE_1,
HID_LOGICAL_MIN_16(0x01, 0x80), // LOGICAL_MINIMUM (-32767)
HID_LOGICAL_MAX_16(0xFF, 0x7F), // LOGICAL_MAXIMUM (32767)
HID_PHYSICAL_MIN_32(0x60, 0x4F, 0x46, 0xED), // -314159265
HID_PHYSICAL_MAX_32(0xA1, 0xB0, 0xB9, 0x12), // 314159265
HID_UNIT_EXPONENT(0x08), // 10^-8
HID_REPORT_SIZE(16),
HID_REPORT_COUNT(3),
HID_INPUT(HID_DATA_VAR_ABS),
// Angular velocity as rotation vector (scaled to [-32..32] rad/sec).
HID_USAGE_SENSOR_DATA_CUSTOM_VALUE_2,
HID_LOGICAL_MIN_16(0x01, 0x80), // LOGICAL_MINIMUM (-32767)
HID_LOGICAL_MAX_16(0xFF, 0x7F), // LOGICAL_MAXIMUM (32767)
HID_PHYSICAL_MIN_8(0xE0),
HID_PHYSICAL_MAX_8(0x20),
HID_UNIT_EXPONENT(0x00), // 10^0
HID_REPORT_SIZE(16),
HID_REPORT_COUNT(3),
HID_INPUT(HID_DATA_VAR_ABS),
// Reference frame reset counter.
HID_USAGE_SENSOR_DATA_CUSTOM_VALUE_3,
HID_LOGICAL_MIN_16(0x00, 0x00), // LOGICAL_MINIMUM (0)
HID_LOGICAL_MAX_16(0xFF, 0x00), // LOGICAL_MAXIMUM (255)
HID_PHYSICAL_MIN_8(0x00),
HID_PHYSICAL_MAX_8(0x00),
HID_UNIT_EXPONENT(0x00), // 10^0
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(1),
HID_INPUT(HID_DATA_VAR_ABS),
HID_END_COLLECTION,
};
Anhang 2: Beispiel eines HID-Deskriptors in Version 2.0
Das folgende Beispiel zeigt einen v2.0-HID-Deskriptor für ein Gerät, das die nur den Bluetooth LE ACL-Transport.
const unsigned char ReportDescriptor[] = {
HID_USAGE_PAGE_SENSOR,
HID_USAGE_SENSOR_TYPE_OTHER_CUSTOM,
HID_COLLECTION(HID_APPLICATION),
// Feature report 2 (read-only).
HID_REPORT_ID(2),
// Magic value: "#AndroidHeadTracker#2.0#1"
HID_USAGE_SENSOR_PROPERTY_SENSOR_DESCRIPTION,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(25),
HID_FEATURE(HID_CONST_VAR_ABS),
// UUID.
HID_USAGE_SENSOR_PROPERTY_PERSISTENT_UNIQUE_ID,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(16),
HID_FEATURE(HID_CONST_VAR_ABS),
// Feature report 1 (read/write).
HID_REPORT_ID(1),
// 1-bit on/off reporting state.
HID_USAGE_SENSOR_PROPERTY_REPORTING_STATE,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(1),
HID_REPORT_SIZE(1),
HID_REPORT_COUNT(1),
HID_COLLECTION(HID_LOGICAL),
HID_USAGE_SENSOR_PROPERTY_REPORTING_STATE_NO_EVENTS,
HID_USAGE_SENSOR_PROPERTY_REPORTING_STATE_ALL_EVENTS,
HID_FEATURE(HID_DATA_ARR_ABS),
HID_END_COLLECTION,
// 1-bit on/off power state.
HID_USAGE_SENSOR_PROPERTY_POWER_STATE,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(1),
HID_REPORT_SIZE(1),
HID_REPORT_COUNT(1),
HID_COLLECTION(HID_LOGICAL),
HID_USAGE_SENSOR_PROPERTY_POWER_STATE_D4_POWER_OFF,
HID_USAGE_SENSOR_PROPERTY_POWER_STATE_D0_FULL_POWER,
HID_FEATURE(HID_DATA_ARR_ABS),
HID_END_COLLECTION,
// 6-bit reporting interval, with values [0x00..0x3F] corresponding to [10ms..100ms].
HID_USAGE_SENSOR_PROPERTY_REPORT_INTERVAL,
HID_LOGICAL_MIN_8(0x00),
HID_LOGICAL_MAX_8(0x3F),
HID_PHYSICAL_MIN_8(10),
HID_PHYSICAL_MAX_8(100),
HID_REPORT_SIZE(6),
HID_REPORT_COUNT(1),
HID_USAGE_SENSOR_UNITS_SECOND,
HID_UNIT_EXPONENT(0xD), // 10^-3
HID_FEATURE(HID_DATA_VAR_ABS),
// 1-bit transport selection
HID_USAGE_SENSOR_PROPERTY_VENDOR_LE_TRANSPORT,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(1),
HID_REPORT_SIZE(1),
HID_REPORT_COUNT(1),
HID_COLLECTION(HID_LOGICAL),
HID_USAGE_SENSOR_PROPERTY_VENDOR_LE_TRANSPORT_ACL,
HID_USAGE_SENSOR_PROPERTY_VENDOR_LE_TRANSPORT_ISO,
HID_FEATURE(HID_DATA_ARR_ABS),
HID_END_COLLECTION,
// Input report 1
// Orientation as rotation vector (scaled to [-pi..pi] rad).
HID_USAGE_SENSOR_DATA_CUSTOM_VALUE_1,
HID_LOGICAL_MIN_16(0x01, 0x80), // LOGICAL_MINIMUM (-32767)
HID_LOGICAL_MAX_16(0xFF, 0x7F), // LOGICAL_MAXIMUM (32767)
HID_PHYSICAL_MIN_32(0x60, 0x4F, 0x46, 0xED), // -314159265
HID_PHYSICAL_MAX_32(0xA1, 0xB0, 0xB9, 0x12), // 314159265
HID_UNIT_EXPONENT(0x08), // 10^-8
HID_REPORT_SIZE(16),
HID_REPORT_COUNT(3),
HID_INPUT(HID_DATA_VAR_ABS),
// Angular velocity as rotation vector (scaled to [-32..32] rad/sec).
HID_USAGE_SENSOR_DATA_CUSTOM_VALUE_2,
HID_LOGICAL_MIN_16(0x01, 0x80), // LOGICAL_MINIMUM (-32767)
HID_LOGICAL_MAX_16(0xFF, 0x7F), // LOGICAL_MAXIMUM (32767)
HID_PHYSICAL_MIN_8(0xE0),
HID_PHYSICAL_MAX_8(0x20),
HID_UNIT_EXPONENT(0x00), // 10^0
HID_REPORT_SIZE(16),
HID_REPORT_COUNT(3),
HID_INPUT(HID_DATA_VAR_ABS),
// Reference frame reset counter.
HID_USAGE_SENSOR_DATA_CUSTOM_VALUE_3,
HID_LOGICAL_MIN_16(0x00, 0x00), // LOGICAL_MINIMUM (0)
HID_LOGICAL_MAX_16(0xFF, 0x00), // LOGICAL_MAXIMUM (255)
HID_PHYSICAL_MIN_8(0x00),
HID_PHYSICAL_MAX_8(0x00),
HID_UNIT_EXPONENT(0x00), // 10^0
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(1),
HID_INPUT(HID_DATA_VAR_ABS),
HID_END_COLLECTION,
};