Head-Tracker-HID-Protokoll

Das Head-Tracker-Human-Interface-Device (HID)-Protokoll, das für Geräte mit Android 13 und höher verfügbar ist, ermöglicht es, ein Head-Tracking-Gerät über USB oder Bluetooth mit einem Android-Gerät zu verbinden und über die Sensoren dem Android-Framework und den Apps zugänglich zu machen Rahmen. Dieses Protokoll wird zur Steuerung eines Audio-Virtualisierungseffekts (3D-Audio) verwendet. Auf dieser Seite werden die Begriffe „Gerät“ und „ Host“ im Bluetooth-Sinn verwendet, wobei „ Gerät“ das Head-Tracking-Gerät und „Host“ der Android-Host bedeutet.

Gerätehersteller müssen ihre Android-Geräte so konfigurieren, dass sie die Unterstützung für das Head-Tracker-HID-Protokoll ermöglichen. Ausführlichere Informationen zur Konfiguration finden Sie in der README-Datei zu Dynamic Sensors .

Für diese Seite wird die Kenntnis der folgenden Ressourcen vorausgesetzt:

Struktur auf oberster Ebene

Das Android-Framework identifiziert das Head-Tracker-Gerät als HID-Gerät.

Ein vollständiges Beispiel eines gültigen HID-Deskriptors finden Sie in Anhang 1: Beispiel eines HID-Deskriptors .

Auf der obersten Ebene ist das Head-Tracker-Gerät eine App-Sammlung mit der Seite Sensors “ ( 0x20 ) und der Other: Custom Nutzung“ ( 0xE1 ). In dieser Sammlung befinden sich mehrere Datenfelder ( Eingaben ) und Eigenschaften ( Features ).

Eigenschaften und Datenfelder

In diesem Abschnitt werden die Eigenschaften und Datenfelder in einer Anwendungssammlung eines Head-Tracker-Geräts beschrieben.

Eigenschaft: Sensorbeschreibung ( 0x0308 )

Die Eigenschaft „Sensorbeschreibung“ ( 0x0308 ) ist eine schreibgeschützte ASCII-Zeichenfolgeneigenschaft (8 Bit), die den folgenden Wert enthalten muss:

#AndroidHeadTracker#1.0

Es wird kein Nullterminator erwartet, was bedeutet, dass die Gesamtgröße dieser Eigenschaft 23 8-Bit-Zeichen beträgt.

Diese Eigenschaft dient als Unterscheidungsmerkmal, um Kollisionen mit anderen benutzerdefinierten Sensoren zu vermeiden.

Eigenschaft: Persistente eindeutige ID ( 0x0302 )

Die Eigenschaft Persistent Unique ID ( 0x0302 ) ist ein schreibgeschütztes Array aus 16 Elementen mit jeweils 8 Bit (insgesamt 128 Bit). Es wird kein Nullterminator erwartet. Diese Eigenschaft ist optional.

Diese Eigenschaft ermöglicht es Head-Tracking-Geräten, die in Audiogeräte integriert sind, auf das Audiogerät zu verweisen, an das sie angeschlossen sind. Die folgenden Schemata werden unterstützt.

Eigenständiger Headtracker

Wenn die Eigenschaft „Persistent Unique ID ( 0x0302 )“ nicht vorhanden ist oder nur auf Nullen gesetzt ist, bedeutet dies, dass das Head-Tracker-Gerät nicht dauerhaft an ein Audiogerät angeschlossen ist und separat verwendet werden kann, indem es beispielsweise dem Benutzer manuell gestattet wird Verknüpfen Sie das Head-Tracker-Gerät mit einem separaten Audiogerät.

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

In diesem Schema müssen die ersten 8 Oktette 0 sein, die Oktette 8 und 9 müssen die ASCII-Werte B bzw. T enthalten und die folgenden 6 Oktette werden als Bluetooth-MAC-Adresse interpretiert, vorausgesetzt, das Head-Tracker-Gerät gilt für jedes Audiogerät mit diese MAC-Adresse.

Referenz mit UUID

Immer wenn das höchstwertige Bit (MSB) von Oktett 8 gesetzt ist ( ≥0x80 ), wird das Feld als UUID interpretiert, wie in RFC-4122 angegeben. Das entsprechende Audiogerät stellt über einen nicht spezifizierten Mechanismus, der für die verwendete Transportart spezifisch ist, dieselbe UUID bereit, die im Android-Framework registriert ist.

Eigenschaft: Meldestaat ( 0x0316 )

Die Eigenschaft Reporting State ( 0x0316 ) ist eine Lese-/Schreibeigenschaft mit der Standardsemantik, wie sie in der HID-Spezifikation definiert ist. Der Host verwendet diese Eigenschaft, um dem Gerät anzugeben, welche Ereignisse gemeldet werden sollen. Es werden nur die Werte No Events ( 0x0840 ) und All Events ( 0x0841 ) verwendet.

Der Anfangswert für dieses Feld muss „Keine Ereignisse“ lauten und darf niemals vom Gerät, sondern nur vom Host geändert werden.

Eigenschaft: Power State ( 0x0319 )

Die Eigenschaft Power State ( 0x0319 ) ist eine Lese-/Schreibeigenschaft mit der in der HID-Spezifikation definierten Standardsemantik. Der Host verwendet diese Eigenschaft, um dem Gerät anzuzeigen, in welchem ​​Energiezustand es sich befinden muss. Es werden nur die Werte Full Power ( 0x0851 ) und Power Off ( 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.

Eigenschaft: Berichtsintervall ( 0x030E )

Die Eigenschaft „Berichtsintervall“ ( 0x030E ) ist eine Lese-/Schreibeigenschaft mit der in der HID-Spezifikation definierten Standardsemantik. Der Host verwendet diese Eigenschaft, um dem Gerät anzugeben, wie oft seine Datenablesungen gemeldet werden sollen. Einheiten sind Sekunden. Der gültige Bereich für diesen Wert wird vom Gerät bestimmt und mithilfe des physikalischen Min/Max-Mechanismus beschrieben. Es muss eine Melderate von mindestens 50 Hz unterstützt werden, die empfohlene maximale Melderate beträgt 100 Hz. Daher muss das minimale Berichtsintervall kleiner oder gleich 20 ms sein und wird empfohlen, größer oder gleich 10 ms zu sein.

Datenfeld: Benutzerdefinierter Wert 1 ( 0x0544 )

Das Feld „Benutzerdefinierter Wert 1“ ( 0x0544 ) ist ein Eingabefeld, das zum Melden der tatsächlichen Head-Tracking-Informationen verwendet wird. Es handelt sich um ein Array mit drei Elementen, das gemäß den normalen HID-Regeln für physikalische Werte interpretiert wird, wie in Abschnitt 6.2.2.7 der HID-Spezifikation angegeben. Der gültige Bereich für jedes Element ist [-π, π] rad. Einheiten sind immer das Bogenmaß.

Die Elemente werden wie folgt interpretiert: [rx, ry, rz] , sodass [rx, ry, rz] ein Rotationsvektor ist, der die Transformation vom Referenzrahmen zum Kopfrahmen darstellt. Die Größe muss im Bereich [0..π] liegen.

Der Referenzrahmen ist willkürlich, aber im Allgemeinen fest und muss rechtshändig sein. Eine kleine Drift ist akzeptabel. Die Kopfachsen sind:

  • X vom linken Ohr zum rechten
  • Y vom Hinterkopf bis zur Nase (von hinten nach vorne)
  • Z vom Hals bis zur Oberseite des Kopfes

Datenfeld: Benutzerdefinierter Wert 2 ( 0x0545 )

Das Feld „Benutzerdefinierter Wert 2“ ( 0x0545 ) ist ein Eingabefeld, das zum Melden der tatsächlichen Head-Tracking-Informationen verwendet wird. Es handelt sich um ein Festkomma-Array mit drei Elementen, das gemäß den normalen HID-Regeln für physikalische Werte interpretiert wird. Einheiten sind immer Bogenmaß/Sekunde.

Die Elemente werden wie folgt interpretiert: [vx, vy, vz] , sodass [vx, vy, vz] ein Rotationsvektor ist, der die Winkelgeschwindigkeit des Kopfrahmens (relativ zu sich selbst) darstellt.

Datenfeld: Benutzerdefinierter Wert 3 ( 0x0546 )

Das Feld „Benutzerdefinierter Wert 3“ ( 0x0546 ) ist ein Eingabefeld, das zum Verfolgen von Diskontinuitäten im Referenzrahmen verwendet wird. Es handelt sich um eine skalare Ganzzahl mit einer Größe von 8 Bit. Er muss vom Gerät jedes Mal erhöht werden (mit Umlauf), wenn der Bezugsrahmen geändert wird, beispielsweise wenn der Status eines Ausrichtungsfilteralgorithmus zur Bestimmung der Ausrichtung zurückgesetzt wurde. Dieser Wert wird gemäß den normalen HID-Regeln für physikalische Werte interpretiert. Der physische Wert und die Einheiten spielen jedoch keine Rolle. Die einzige für den Host relevante Information ist ein geänderter Wert. Um numerische Probleme im Zusammenhang mit Präzisionsverlusten bei der Konvertierung von logischen in physikalische Einheiten zu vermeiden, wird empfohlen, die Werte für das physikalische Minimum, das physikalische Maximum und den Einheitenexponenten für dieses Feld auf Null zu setzen.

Berichtsstruktur

Die Gruppierung von Eigenschaften in Berichten (durch Zuweisung von Berichts-IDs) ist flexibel. Aus Effizienzgründen empfehlen wir, die schreibgeschützten Eigenschaften von den Lese-/Schreibeigenschaften zu trennen.

Für die Datenfelder müssen sich die Felder „Benutzerdefinierter Wert 1“, „2“ und „3“ im selben Bericht befinden und dürfen nur in einem Bericht für ein bestimmtes Gerät (App-Sammlung) enthalten sein.

Eingabeberichte senden

Das Gerät muss regelmäßig und asynchron (über HID INPUT-Nachrichten) Eingabeberichte senden, wenn alle diese Bedingungen erfüllt sind:

  • Die Eigenschaft Power State ist auf Full Power eingestellt.
  • Die Eigenschaft „Meldestatus“ ist auf „Alle Ereignisse“ festgelegt.
  • Die Eigenschaft „Berichtsintervall“ ist ungleich Null.

Die Eigenschaft „Berichtsintervall“ bestimmt, 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

Das Head-Tracker-HID-Protokoll verwendet ein Versionierungsschema, das Aktualisierungen ermöglicht und gleichzeitig die Interoperabilität zwischen einem Host und einem Gerät ermöglicht, die unterschiedliche Versionen des Protokolls verwenden. Versionen für das Protokoll werden durch zwei Nummern identifiziert, die Haupt- und die Nebennummer, die eine unterschiedliche Semantik haben, wie in den folgenden Abschnitten beschrieben.

Die von einem Gerät unterstützten Versionen können durch Untersuchen der Eigenschaft „Sensorbeschreibung“ ( 0x0308 ) ermittelt werden.

Kompatibilität mit Nebenversionen

Änderungen an der Nebenversion sind abwärtskompatibel mit früheren Nebenversionen, die auf derselben Hauptversion basieren. Bei Updates auf die Nebenversion ignoriert der Host zusätzliche Datenfelder und Eigenschaften. Beispielsweise ist ein Gerät, das die Protokollversion 1.6 verwendet, mit einem Host kompatibel, der die Protokollversion 1.x, einschließlich Version 1.5, unterstützt.

Kompatibilität mit Hauptversionen

Für Änderungen an Hauptversionen sind nicht abwärtskompatible Änderungen zulässig. Um mehrere Hauptversionen für die Interoperabilität mit alten und neuen Hosts zu unterstützen, können Geräte in ihren Berichtsdeskriptoren mehrere App-Sammlungen angeben. Zum 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 verschiedenen App-Sammlungen aufzählen, die vom Gerät angekündigt werden, indem er deren Sensorbeschreibungseigenschaft untersucht, um die Protokollversionen zu ermitteln, die sie jeweils implementieren, und dann die neueste Protokollversion auszuwählen, die der Host unterstützt. Bei Auswahl arbeitet der Host mit dem einzigen Protokoll, das für die Lebensdauer der Geräteverbindung ausgewählt wurde.

Anhang: Beispiel eines HID-Deskriptors

Das folgende Beispiel veranschaulicht einen typischen gültigen HID-Deskriptor. Es verwendet die häufig verwendeten C-Makros, die in HID-Sensorverwendungen (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,
};