Protokół urządzenia HID (Human Interface Device) śledzącego ruch głowy, dostępny na urządzeniach z Androidem 13 lub nowszym, umożliwia podłączenie urządzenia śledzącego ruch głowy do urządzenia z Androidem przez USB lub Bluetooth i ujawnienie go w ramach frameworku Androida i aplikacji za pomocą frameworku sensorów. Protokół ten jest używany do sterowanie 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ę protokołu HID lokalizatora głowy. Więcej informacji o konfiguracji znajdziesz w pliku README Dynamic Sensors (w języku angielskim).
Ta strona zakłada, że znasz te zasoby:
Struktura najwyższego poziomu
Platforma Android rozpoznaje urządzenie śledzące ruch głowy 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 zbiorze aplikacji urządzenia śledzącego ruch głowy.
Właściwość: Opis czujnika (0x0308
)
Właściwość Opis czujnika (0x0308
) to tylko do odczytu ciąg znaków ASCII (8-bitowy), który musi zawierać te wartości:
Śledzik w wersji 1.0:
#AndroidHeadTracker#1.0
Lokalizator w wersji 2.0 (dostępny na urządzeniach z Androidem 15 lub , która obejmuje obsługę LE Audio:
#AndroidHeadTracker#2.0#x
Wartość x
jest liczbą całkowitą (1
, 2
, 3
) wskazującą transport wspierający:
- 1: Lista kontroli dostępu (ACL)
- 2: ISO
- 3: ACL + ISO
Nie jest wymagany żaden terminator null, co oznacza, że łączny rozmiar tej właściwości w wersji 1.0 wynosi 23 8-bitowe znaki.
Ta właściwość służy do rozróżniania czujników, aby uniknąć kolizji z innymi czujnikami niestandardowymi.
Usługa: stały unikalny identyfikator (0x0302
)
Właściwość trwały identyfikator unikalny (0x0302
) to tablica tylko do odczytu zawierająca 16 elementów, z których każdy ma 8 bitów (razem 128 bitów). Nie jest wymagany terminator null. Ten
jest opcjonalna.
Ta właściwość umożliwia urządzeniom śledzącym ruch głowy, które są zintegrowane z urządzeniami audio, odwoływanie się do urządzenia audio, do którego są podłączone. Obsługiwane są te schematy:
Samodzielny lokalizator ruchów głowy
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.
Odwoływanie się do adresu MAC Bluetooth
Octet | 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 być 0
, oktety 8 i 9 muszą zawierać odpowiednio wartości ASCII B
i T
, a kolejne 6 oktetów są interpretowane jako adres MAC Bluetooth, przy założeniu, że urządzenie śledzące ruchy głowy dotyczy dowolnego urządzenia audio mającego ten adres MAC. Ten adres musi być
adresu tożsamości, nawet jeśli urządzenie używa losowego adresu MAC do ustalania
połączeń. Urządzenia w trybie podwójnym łączące się przez klasyczny Bluetooth (w formacie HID w wersji 1.0) i Bluetooth LE (w formacie HID w wersji 2.0) muszą udostępniać 2 deskryptory HID z tym samym adresem tożsamości. Urządzenia z 2 trybami oddzielone
urządzenia lewe i prawe muszą udostępniać Bluetooth LE HID za pomocą podstawowego
urządzenia w trybie online, a nie dodatkowego urządzenia obsługującego tylko LE.
Odwoływanie się za pomocą 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. Używane są tylko wartości Brak zdarzeń (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.
Właściwość: 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. Host używa tej właściwości, aby wskazać urządzeniu, w jakim stanie zasilania ma się ono znajdować. Używane są tylko wartości Pełna moc (0x0851
) i Wyłącz zasilanie (0x0855
).
Początkowa wartość tego pola zależy od urządzenia i nie można jej nigdy modyfikowane przez urządzenie, tylko przez gospodarza.
Właściwość: Interwał raportowania (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. Host używa tej właściwości, aby wskazać urządzeniu, jak często ma 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. Musi być obsługiwana częstotliwość raportowania co najmniej 50 Hz, a zalecana maksymalna częstotliwość raportowania to 100 Hz. Dlatego minimalny interwał raportowania musi być krótszy lub równy 20 ms, a zalecany interwał powinien być dłuższy lub równy 10 ms.
Usługa: zarezerwowane przez dostawcę LE Transport (0xF410
)
Właściwość LE Transport (0xF410
) zarezerwowana przez dostawcę to właściwość do odczytu/zapisu.
o standardowej semantyce zdefiniowanej w specyfikacji HID. Gospodarz
używa tej właściwości do wskazania wybranego transportu (ACL lub ISO). Tylko
używane są wartości ACL (0xF800
) i ISO (0xF801
), które trzeba uwzględnić
w zbiorze logicznym.
Ta właściwość jest konfigurowana przed stanem zasilania lub raportowania.
Pole danych: niestandardowa wartość 1 (0x0544
)
Pole Wartość niestandardowa 1 (0x0544
) to pole danych służące do raportowania rzeczywistych informacji o śledzeniu ruchem głowy. Jest to tablica o 3 elementach interpretowana zgodnie ze zwykłymi regułami HID dotyczącymi wartości fizycznych określonymi w sekcji 6.2.2.7 specyfikacji 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.
Wielkość musi mieścić się w zakresie [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 prawego
- 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-elementowy tablica o stałym punkcie, interpretowana zgodnie ze zwykłymi regułami HID dla wartości fizycznych.
Jednostkami są 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: niestandardowa wartość 3 (0x0546
)
Pole Wartość niestandardowa 3 (0x0546
) to pole wejściowe służące do śledzenia przerw w ramce odniesienia. Jest to liczba całkowita skalarna o długości 8 bitów. Musi być zwiększany (z przewijaniem) przez urządzenie za każdym razem, gdy zmienia się układ odniesienia, na przykład gdy stan algorytmu filtra orientacji używanego do określania orientacji został zresetowany. Ta wartość jest interpretowana zgodnie ze zwykłymi regułami HID dotyczącymi wartości fizycznych. Wartość fizyczna i jednostki nie mają jednak znaczenia. Jedynymi informacjami istotnymi dla hosta jest zmieniona wartość. Aby uniknąć problemów związanych z utratą dokładności podczas konwertowania z jednostek logicznych na fizyczne, zalecamy ustawienie w tym polu wartości minimalnej, maksymalnej i wykładniczej jednostki na zero.
Struktura raportu
Grupowanie usług w raporty (poprzez przypisywanie identyfikatorów raportów) jest elastyczne. Ze względu na wydajność zalecamy oddzielenie właściwości tylko do odczytu od właściwości tylko 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łanie raportów o błędach
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ść Stan zasilania ma wartość Pełna moc.
- 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. Jeśli którekolwiek z tych warunków nie jest spełnione, urządzenie nie może wysyłać żadnych raportów.
Zgodność do przodu i do tyłu
Protokół HID śledzącego ruch głowy używa schematu wersji, który umożliwia aktualizacje, a także interoperacyjność między hostem a urządzeniem, które używają różnych wersji protokołu. Wersje protokołu są identyfikowane za pomocą 2 liczb: głównej i podrzędnej, które mają odmienną semantykę, jak opisano w poniższych sekcjach.
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. W aktualizacjach do wersji podrzędnej host ignoruje dodatkowe pola danych i właściwości. Na przykład urządzenie korzystające z wersji 1.6 protokołu jest zgodne z hostem obsługującym wersję 1.x protokołu, w tym wersję 1.5.
Zgodność z wersją główną
W przypadku zmian w głównych wersjach dozwolone są zmiany niezgodne ze starszymi wersjami. Aby obsługiwać wiele głównych wersji w celu zapewnienia interoperacyjności ze starymi i nowymi hostami, urządzenia mogą określać w swoich deskryptorach raportów wiele kolekcji aplikacji. 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,
};
Załącznik 2. Przykład opisu HID w wersji 2.0
Przykład poniżej pokazuje deskryptor HID w wersji 2.0 dla urządzenia obsługującego tylko transport Bluetooth LE ACL.
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,
};