Protokół HID śledzenia głowy

Protokół urządzenia do śledzenia głowy (HID), dostępny dla urządzeń z systemem Android 13 i nowszym, umożliwia podłączenie urządzenia do śledzenia głowy do urządzenia z systemem Android przez USB lub Bluetooth i wystawienie go na działanie platformy i aplikacji systemu Android za pośrednictwem czujników struktura. Protokół ten służy do kontrolowania efektu wirtualizacji dźwięku (dźwięk 3D). Na tej stronie terminy urządzenie i host są używane w znaczeniu Bluetooth, gdzie urządzenie oznacza urządzenie śledzące głowę, a host oznacza hosta z systemem Android.

Producenci urządzeń muszą skonfigurować swoje urządzenia z systemem Android, aby umożliwić obsługę protokołu HID modułu śledzenia głowy. Bardziej szczegółowe informacje na temat konfiguracji można znaleźć w pliku README dotyczącym czujników dynamicznych .

Na tej stronie zakłada się znajomość następujących zasobów:

Struktura na najwyższym poziomie

Struktura systemu Android identyfikuje urządzenie do śledzenia głowy jako urządzenie HID.

Pełny przykład prawidłowego deskryptora HID znajduje się w Dodatku 1: Przykład deskryptora HID .

Na najwyższym poziomie urządzenie do śledzenia głowy to zbiór aplikacji ze stroną Sensors ( 0x20 ) i stroną Other: Custom ( 0xE1 ). Wewnątrz tej kolekcji znajduje się kilka pól danych ( dane wejściowe ) i właściwości ( funkcje ).

Właściwości i pola danych

W tej sekcji opisano właściwości i pola danych w zbiorze aplikacji urządzenia do śledzenia głowy.

Właściwość: Opis czujnika ( 0x0308 )

Właściwość Opis czujnika ( 0x0308 ) to właściwość ciągu ASCII (8-bitowego) przeznaczona tylko do odczytu, która musi zawierać następującą wartość:

#AndroidHeadTracker#1.0

Nie oczekuje się żadnego terminatora zerowego, co oznacza, że ​​całkowity rozmiar tej właściwości wynosi 23 8-bitowe znaki.

Ta właściwość służy jako dyskryminator pozwalający uniknąć kolizji z innymi czujnikami niestandardowymi.

Właściwość: Trwały unikalny identyfikator ( 0x0302 )

Właściwość Persistent Unique ID ( 0x0302 ) jest tablicą tylko do odczytu składającą się z 16 elementów, każdy po 8 bitów (w sumie 128 bitów). Nie oczekuje się żadnego terminatora zerowego. Ta właściwość jest opcjonalna.

Ta właściwość umożliwia urządzeniom śledzącym ruch głowy zintegrowanym z urządzeniami audio odwoływanie się do urządzenia audio, do którego są podłączone. Obsługiwane są następujące schematy.

Samodzielny moduł śledzący głowę

Jeżeli właściwość Persistent Unique ID ( 0x0302 ) nie istnieje lub jest ustawiona na same zera, oznacza to, że urządzenie śledzące ruch głowy nie jest na stałe podłączone do urządzenia audio i może być używane oddzielnie, na przykład poprzez umożliwienie użytkownikowi ręcznego powiązać urządzenie do śledzenia głowy z oddzielnym urządzeniem audio.

Odniesienie przy użyciu adresu MAC Bluetooth

Oktet 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Wartość 0 0 0 0 0 0 0 0 B T Bluetooth MAC

W tym schemacie pierwsze 8 oktetów musi mieć 0 , oktety 8 i 9 muszą zawierać odpowiednio wartości ASCII B i T , a kolejnych 6 oktetów jest interpretowanych jako adres MAC Bluetooth, zakładając, że urządzenie śledzące ruch głowy ma zastosowanie do dowolnego urządzenia audio posiadającego ten adres MAC.

Odniesienie przy użyciu UUID

Ilekroć ustawiony jest najbardziej znaczący bit (MSB) oktetu 8 ( ≥0x80 ), pole jest interpretowane jako UUID, jak określono w RFC-4122 . Odpowiednie urządzenie audio zapewnia ten sam identyfikator UUID, który jest zarejestrowany w środowisku Android, poprzez nieokreślony mechanizm specyficzny dla rodzaju używanego transportu.

Właściwość: Stan raportowania ( 0x0316 )

Właściwość Stan raportowania ( 0x0316 ) to właściwość do odczytu/zapisu, która ma standardową semantykę zdefiniowaną w specyfikacji HID. Host używa tej właściwości, aby wskazać urządzeniu, które zdarzenia mają zostać zgłoszone. Używane są tylko wartości Brak zdarzeń ( 0x0840 ) i Wszystkie zdarzenia ( 0x0841 ).

Początkowa wartość tego pola musi wynosić Brak zdarzeń i nie może być nigdy modyfikowana przez urządzenie, a jedynie przez hosta.

Właściwość: Stan zasilania ( 0x0319 )

Właściwość Power State ( 0x0319 ) to właściwość do odczytu/zapisu, która ma standardową semantykę zdefiniowaną w specyfikacji HID. Host używa tej właściwości, aby wskazać urządzeniu, w jakim stanie zasilania musi się znajdować. Używane są tylko wartości Full Power ( 0x0851 ) i Power Off ( 0x0855 ).

Początkowa wartość tego pola jest ustalana przez urządzenie i nie może być nigdy modyfikowana przez urządzenie, a jedynie przez hosta.

Właściwość: Interwał raportowania ( 0x030E )

Właściwość Report Interval ( 0x030E ) to właściwość do odczytu/zapisu, która ma standardową semantykę zdefiniowaną w specyfikacji HID. Host używa tej właściwości, aby wskazać urządzeniu, jak często raportować odczyty danych. Jednostki to sekundy. Prawidłowy zakres tej wartości jest określany przez urządzenie i opisywany za pomocą mechanizmu Fizycznego Min./Maks. Musi być obsługiwana częstotliwość raportowania co najmniej 50 Hz, a zalecana maksymalna częstotliwość raportowania wynosi 100 Hz. Dlatego minimalny odstęp między raportami musi być mniejszy lub równy 20 ms i zaleca się, aby był większy lub równy 10 ms.

Pole danych: Wartość niestandardowa 1 ( 0x0544 )

Pole Wartość niestandardowa 1 ( 0x0544 ) jest polem wejściowym używanym do raportowania rzeczywistych informacji o śledzeniu ruchu głowy. Jest to tablica 3-elementowa, interpretowana zgodnie ze zwykłymi regułami HID dotyczącymi wartości fizycznych, jak określono w sekcji 6.2.2.7 specyfikacji HID. Prawidłowy zakres dla każdego elementu to [-π, π] rad. Jednostką są zawsze radiany.

Elementy są interpretowane jako: [rx, ry, rz] , tak że [rx, ry, rz] jest wektorem obrotu , reprezentującym transformację z układu odniesienia do układu głównego. Wielkość musi mieścić się w zakresie [0..π].

Ramka odniesienia jest dowolna, ale generalnie jest stała i musi być prawoskrętna. Dopuszczalna jest niewielka ilość znoszenia. Osie głowy to:

  • X od lewego ucha do prawego
  • Y od tyłu głowy do nosa (od tyłu do przodu)
  • Z od szyi do czubka głowy

Pole danych: Wartość niestandardowa 2 ( 0x0545 )

Pole Wartość niestandardowa 2 ( 0x0545 ) jest polem wejściowym używanym do raportowania rzeczywistych informacji o śledzeniu ruchu głowy. Jest to 3-elementowa tablica stałoprzecinkowa, interpretowana zgodnie z normalnymi regułami HID dla wartości fizycznych. Jednostką są zawsze radiany/sekundę.

Elementy są interpretowane jako: [vx, vy, vz] , tak że [vx, vy, vz] jest wektorem obrotu , reprezentującym prędkość kątową ramy czołowej (względem siebie).

Pole danych: Wartość niestandardowa 3 ( 0x0546 )

Pole Wartość niestandardowa 3 ( 0x0546 ) jest polem wejściowym używanym do śledzenia nieciągłości w układzie odniesienia. Jest to skalarna liczba całkowita o rozmiarze 8 bitów. Musi być zwiększany (z zawijaniem) przez urządzenie za każdym razem, gdy zmienia się układ odniesienia, na przykład jeśli stan algorytmu filtra orientacji użytego do określenia orientacji został zresetowany. Wartość ta jest interpretowana zgodnie z normalnymi zasadami HID dotyczącymi wartości fizycznych. Jednak wartość fizyczna i jednostki nie mają znaczenia. Jedyną informacją istotną dla hosta jest zmieniona wartość. Aby uniknąć problemów numerycznych związanych z utratą precyzji podczas konwersji jednostek logicznych na fizyczne, zaleca się ustawienie wartości minimalnej fizycznej, maksymalnej fizycznej i wykładnika jednostek na zero w tym polu.

Struktura raportu

Grupowanie właściwości w raporty (poprzez przypisanie identyfikatorów raportów) jest elastyczne. Aby zapewnić wydajność, zalecamy oddzielenie właściwości tylko do odczytu od właściwości do odczytu/zapisu.

W przypadku pól danych pola Wartość niestandardowa 1, 2 i 3 muszą znajdować się w tym samym raporcie i tylko w jednym raporcie dla danego urządzenia (kolekcji aplikacji).

Wysyłaj raporty wejściowe

Urządzenie musi okresowo i asynchronicznie (poprzez komunikaty HID INPUT) wysyłać raporty wejściowe, gdy spełnione są wszystkie poniższe warunki:

  • Właściwość Stan zasilania jest ustawiona na Pełna moc.
  • Właściwość Stan raportowania jest ustawiona na Wszystkie zdarzenia.
  • Właściwość Interwał raportowania jest różna od zera.

Właściwość Interwał raportowania określa częstotliwość wysyłania raportów. Jeżeli którykolwiek z powyższych warunków nie jest spełniony, urządzenie nie może wysyłać żadnych raportów.

Kompatybilność w przód i wstecz

Protokół HID modułu śledzenia głowy wykorzystuje schemat wersjonowania, który umożliwia aktualizacje, jednocześnie umożliwiając interoperacyjność między hostem a urządzeniem korzystającym z różnych wersji protokołu. Wersje protokołu są identyfikowane za pomocą dwóch liczb, głównej i pobocznej, które mają odrębną semantykę, jak opisano w poniższych sekcjach.

Wersje obsługiwane przez urządzenie można określić, sprawdzając jego właściwość Opis czujnika ( 0x0308 ).

Drobna kompatybilność wersji

Zmiany w wersji pomocniczej są wstecznie kompatybilne z wcześniejszymi wersjami pomocniczymi opartymi na tej samej wersji głównej. W aktualizacjach wersji pomocniczej host ignoruje dodatkowe pola danych i właściwości. Na przykład urządzenie korzystające z protokołu w wersji 1.6 jest kompatybilne z hostem obsługującym wersję protokołu 1.x, w tym wersję 1.5.

Zgodność wersji głównej

Zmiany niezgodne wstecznie są dozwolone w przypadku zmian wersji głównych. Aby obsługiwać wiele głównych wersji w celu zapewnienia współdziałania ze starymi i nowymi hostami, urządzenia mogą określać wiele kolekcji aplikacji w swoich deskryptorach raportów. Na przykład:

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,
};

W takim przypadku host może wyliczyć wszystkie kolekcje aplikacji reklamowane przez urządzenie, sprawdzając ich właściwość Opis czujnika, aby określić wersje protokołów, które każda z nich implementuje, a następnie wybrać najnowszą wersję protokołu obsługiwaną przez host. Po wybraniu host działa z jednym protokołem, który został wybrany na czas trwania połączenia urządzenia.

Dodatek: Przykład deskryptora HID

Poniższy przykład ilustruje typowy prawidłowy deskryptor HID. Wykorzystuje powszechnie używane makra C, opisane w sekcji Użycie czujnika HID (sekcja 4.1).

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,
};