Protokół HID urządzenia śledzącego głowy

Protokół HID (ludzki interfejs urządzenia śledzącego) dostępny na urządzeniach z Androidem 13 lub nowszym, śledzące ruchy głowy, które należy podłączyć do urządzenia z Androidem przez USB lub Bluetooth oraz dostęp do platformy i aplikacji Androida za pomocą sensors. Protokół ten służy do kontrolowania efekt wirtualizacji dźwięku (dźwięk 3D). Na tej stronie używamy haseł urządzenie i hosta w technologii Bluetooth, gdzie urządzenie oznacza urządzenie śledzące ruch głowy a host oznacza hosta Androida.

Producenci urządzeń muszą skonfigurować swoje urządzenia z Androidem, aby umożliwić obsługę dla protokołu HID trackera. Aby uzyskać bardziej szczegółowe informacje: konfiguracji, zapoznaj się z Plik README dotyczący czujników dynamicznych.

Zakładamy, że znasz te zasoby:

Struktura najwyższego poziomu

Platforma Androida identyfikuje urządzenie śledzące na głowie jako urządzenie HID.

Pełny przykład prawidłowego deskryptora HID znajdziesz w sekcji Załącznik 1. Przykład deskryptora HID

Najwyższy poziom trackera to kolekcja aplikacji z Sensors (0x20) i użycie usługi Other: Custom (0xE1). Wewnątrz zbiór danych obejmuje różne pola 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 aplikacji kolekcji trackerów na głowie.

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

Właściwość Sensor Opis (0x0308) jest ciągiem 8-bitowym (tylko do odczytu) ASCII. właściwość, która musi zawierać tę wartość:

#AndroidHeadTracker#1.0

Nie oczekuje się wartości null-terminator, co oznacza, że całkowity rozmiar tej usługi ma 23 znaki 8-bitowe.

Ta właściwość służy jako dyskryminator, aby uniknąć kolizji z innymi za pomocą niestandardowych czujników.

Usługa: stały unikalny identyfikator (0x0302)

Właściwość stałego unikalnego identyfikatora (0x0302) to tablica tylko do odczytu zawierająca 16 elementów elementów, po 8 bitów (łącznie 128 bitów). Nie oczekuje się zakończenia o wartości null. Ten jest opcjonalna.

Ta właściwość zezwala na urządzenia śledzące ruchy głowy, które są zintegrowane z dźwiękiem. urządzeń, aby wskazać urządzenie audio, do którego są podłączone. Obsługiwane są poniższe schematy.

Samodzielny tracker na głowę

Jeśli właściwość Persistent Unique ID (0x0302) nie istnieje lub została ustawiona na wszystkie oznacza to, że tracker nie jest na stałe podłączony do urządzenia audio i można jej używać oddzielnie, np. umożliwiając ręcznie powiązać go z osobnym urządzeniem audio.

Odniesienie z użyciem adresu MAC Bluetootha

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 Adres MAC Bluetooth

W tym schemacie pierwsze 8 oktetów musi zawierać ciąg 0, oktety 8 i 9 muszą zawierać wartości ASCII odpowiednio B i T, a następujących 6 oktetów jest interpretowane jako adres MAC Bluetootha przy założeniu, że urządzenie śledzące dotyczy wszystkich urządzeń audio z tym adresem MAC.

Odwołanie z użyciem identyfikatora UUID

Gdy ustawiony jest najbardziej znaczący bit (MSB) oktetu 8 (≥0x80), pole jest interpretowany jako identyfikator UUID, jak określono w RFC-4122. odpowiednie urządzenie audio udostępnia ten sam identyfikator UUID zarejestrowany na platformy Androida za pomocą nieokreślonego mechanizmu charakterystycznego dla z jakiegoś rodzaju transportu.

Usługa: stan raportowania (0x0316)

Właściwość Stan raportowania (0x0316) to właściwość do odczytu/zapisu, w której występuje wartość standardowej semantyki zdefiniowanej w specyfikacji HID. Używany przez gospodarza aby wskazać urządzeniu, które zdarzenia mają być zgłaszane. Tylko wartości Nie Użyto Zdarzenia (0x0840) i Wszystkie zdarzenia (0x0841).

Początkowa wartość tego pola musi wynosić Brak zdarzeń i nigdy nie może modyfikowane przez urządzenie, tylko przez gospodarza.

Usługa: stan zasilania (0x0319)

Właściwość Power State (0x0319) to właściwość do odczytu/zapisu, która zawiera atrybut standardowej semantyki zdefiniowanej w specyfikacji HID. Używany przez gospodarza we właściwości, aby wskazać urządzeniu, w jakim musi być ono stanie zasilania. Tylko używane są wartości Pełne zasilanie (0x0851) i Wyłącz (0x0855).

Początkowa wartość tego pola zależy od urządzenia i nie można jej nigdy modyfikowane przez urządzenie, tylko przez gospodarza.

Usługa: interwał raportów (0x030E)

Właściwość Interwał raportów (0x030E) to właściwość do odczytu/zapisu, w której parametr standardowej semantyki zdefiniowanej w specyfikacji HID. Używany przez gospodarza właściwość wskazującą urządzenie, jak często ma ono raportować odczyty danych. Jednostki są wyrażone w sekundach. Prawidłowy zakres tej wartości jest określany przez urządzenie i opisane z użyciem mechanizmu minimalne/maksymalnej wartości fizycznej. Co najmniej 50 Hz częstotliwość raportowania musi być obsługiwana, a zalecana maksymalna częstotliwość raportowania to 100 Hz. W związku z tym minimalny odstęp czasu między raportem musi być mniejszy niż lub równy do 20 ms, a zalecana wartość to co najmniej 10 ms.

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

Pole Wartość niestandardowa 1 (0x0544) to pole do wprowadzania danych służące do raportowania wartości prawdziwych danych na temat śledzenia ruchów głowy. Jest to 3-elementowa tablica interpretowana jako do normalnych reguł HID dla wartości fizycznych, zgodnie z sekcją 6.2.2.7 ze specyfikacją HID. Prawidłowy zakres dla każdego elementu to [-π, π] rad. Jednostki zawsze są radiany.

Elementy są interpretowane w taki sposób: [rx, ry, rz], więc [rx, ry, rz] to wektor obrotu, reprezentujący przekształcenie z ramki referencyjnej w ramkę nagłówka. Magnituda musi należeć do zakresu [0..π].

Układ odniesienia jest dowolny, ale zwykle jest stały i musi być dla prawej ręki. Dopuszczalna jest niewielka wartość dryfu. Osie głowy:

  • X od lewego ucha do prawej
  • Y od tylnej części głowy do nosa (od tyłu do przodu)
  • Z od szyi do góry głowy

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

Pole Wartość niestandardowa 2 (0x0545) to pole do wprowadzania danych służące do raportowania wartości prawdziwych danych na temat śledzenia ruchów głowy. Jest to 3-elementowa macierz punktowa interpretowane zgodnie ze normalnymi regułami HID dla wartości fizycznych. Jednostki to zawsze radiany na sekundę.

Elementy są interpretowane w taki sposób: [vx, vy, vz], więc [vx, vy, vz] to wektor obrotu, reprezentujący prędkość kątową ramy głowy (względem siebie).

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

Pole Wartość niestandardowa 3 (0x0546) to pole do wprowadzania danych używane do śledzenia nieciągłości w ramce referencyjnej. Jest to skalarna liczba całkowita 8-bitowa rozmiaru. Musi zostać zwiększona (z zawijaniem) za każdym razem, gdy obszar odniesienia ulegnie zmianie, np. gdy algorytm filtra orientacji zostanie zmieniony. służy do określenia, że stan orientacji został zresetowany. Ta wartość to interpretowane zgodnie ze normalnymi regułami HID dla wartości fizycznych. Pamiętaj jednak: wartość fizyczna i jednostki nie mają znaczenia. Jedyne istotne informacje host to zmieniona wartość. Aby uniknąć problemów liczbowych związanych z utratą dokładności przy konwertowaniu jednostek logicznych na fizyczne zalecamy ustawienie dla fizycznego minimum, fizycznego maksimum i wykładnika jednostki do zera dla tego pola.

Struktura raportu

Grupowanie usług w raporty (przez przypisanie identyfikatorów raportów) to i elastyczności. Aby zwiększyć wydajność, najlepiej oddzielić właściwości tylko do odczytu z właściwości do odczytu/zapisu.

W przypadku pól danych pola Wartość niestandardowa 1, 2 i 3 muszą być w tym samym widoku i wyświetlać tylko jeden raport dla danego urządzenia (kolekcja aplikacji).

Wysyłaj raporty wejściowe

Urządzenie musi okresowo i asynchronicznie (za pomocą komunikatów HID INPUT) wysyłaj raporty wejściowe, gdy są spełnione wszystkie poniższe warunki:

  • Właściwość stanu zasilania ma wartość Pełne zasilanie.
  • Właściwość Stan raportowania jest ustawiona na Wszystkie zdarzenia.
  • Właściwość Interwał raportowania ma wartość różną od zera.

Właściwość Interwał raportowania określa, jak często mają być wysyłane raporty. Kiedy żaden z powyższych warunków nie jest spełniony, urządzenie nie może wysyłać żadnych raportów.

Zgodność do przodu i do tyłu

Protokół HID trackera korzysta ze schematu obsługi wersji, który umożliwia aktualizacji przy jednoczesnym umożliwieniu współdziałania hosta i urządzenia korzystającego różnych wersji protokołu. Zidentyfikowano wersje protokołu dzielone na dwie liczby, większe i mniejsze. Mają one odmienne semantyki: opisane w dalszej części tego artykułu.

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

Zgodność wersji podrzędnych

Zmiany w wersji podrzędnej są zgodne wstecznie z wcześniejszymi wersjami podrzędnymi opartych na tej samej wersji głównej. Informacje dotyczące osoby nieletniej wersji, host ignoruje dodatkowe pola danych i właściwości. Przykład: urządzenie korzystające z protokołu w wersji 1.6 jest zgodne z hostem obsługującym protokołu w wersji 1.x, w tym wersji 1.5.

Zgodność wersji głównej

Zmiany niekompatybilne wstecznie są dozwolone w przypadku zmian w wersjach głównych. Do obsługują wiele wersji głównych w celu interoperacyjności ze starymi i nowymi hostami, urządzeń mogą określać w raporcie wiele kolekcji aplikacji deskryptory. 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 tym przypadku host może wyliczyć wszystkie różne kolekcje aplikacji które są reklamowane przez urządzenie, sprawdzając właściwość „Opis czujnika”, aby określić wersje protokołów wdrażane przez każdy z nich, a następnie wybrać Najnowsza wersja protokołu obsługiwana przez hosta. Po jej wybraniu host będzie działać korzystając z pojedynczego protokołu wybranego przez cały okres użytkowania urządzenia połączenia.

Dodatek: przykład deskryptora HID

Przykład poniżej pokazuje typowy prawidłowy deskryptor HID. Wykorzystuje często używane makra C, udostępniane w Wykorzystanie czujników HID (art. 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,
};