Protokol perangkat antarmuka manusia (HID) pelacak kepala, yang tersedia untuk perangkat yang menjalankan Android 13 dan yang lebih tinggi, memungkinkan perangkat pelacak kepala terhubung ke perangkat Android melalui USB atau Bluetooth dan diekspos ke framework dan aplikasi Android melalui framework sensor. Protokol ini digunakan untuk mengontrol efek virtualisasi audio (audio 3D). Halaman ini menggunakan istilah perangkat dan host dalam pengertian Bluetooth, dengan perangkat berarti perangkat pelacakan kepala dan host berarti host Android.
Produsen perangkat harus mengonfigurasi perangkat Android mereka untuk mengaktifkan dukungan bagi protokol HID pelacak kepala. Untuk mengetahui informasi selengkapnya tentang konfigurasi, lihat README Sensor Dinamis.
Halaman ini mengasumsikan pemahaman tentang resource berikut:
Struktur tingkat teratas
Framework Android mengidentifikasi perangkat pelacak kepala sebagai perangkat HID.
Untuk contoh lengkap deskriptor HID yang valid, lihat Lampiran 1: Contoh Deskriptor HID.
Di tingkat teratas, perangkat pelacak kepala adalah pengumpulan aplikasi dengan halaman
Sensors
(0x20
) dan penggunaan Other: Custom
(0xE1
). Di dalam pengumpulan ini
terdapat beberapa kolom data (input) dan properti (fitur).
Properti dan kolom data
Bagian ini menjelaskan properti dan kolom data dalam pengumpulan aplikasi perangkat pelacak kepala.
Properti: Deskripsi Sensor (0x0308
)
Properti Deskripsi Sensor (0x0308
) adalah properti string ASCII (8-bit) hanya baca yang harus berisi nilai berikut:
Pelacak kepala versi 1.0:
#AndroidHeadTracker#1.0
Pelacak kepala versi 2.0 (tersedia di Android 15 atau yang lebih tinggi), yang mencakup dukungan untuk LE audio:
#AndroidHeadTracker#2.0#x
x
adalah bilangan bulat (1
, 2
, 3
) yang menunjukkan transportasi dukungan:
- 1: ACL
- 2: ISO
- 3: ACL + ISO
Tidak ada null-terminator yang diharapkan, yang berarti ukuran total properti ini adalah 23 karakter 8-bit untuk versi 1.0.
Properti ini berfungsi sebagai pembeda untuk menghindari konflik dengan sensor kustom lainnya.
Properti: ID Unik Persisten (0x0302
)
Properti Persistent Unique ID (0x0302
) adalah array hanya baca yang terdiri dari 16 elemen, masing-masing 8 bit (total 128 bit). Tidak ada terminator null yang diharapkan. Properti
ini bersifat opsional.
Properti ini memungkinkan perangkat pelacak kepala yang terintegrasi dalam perangkat audio untuk mereferensikan perangkat audio yang terhubung dengannya. Skema berikut didukung.
Pelacak kepala mandiri
Jika properti ID Unik Persisten (0x0302
) tidak ada atau disetel ke semua nol, berarti perangkat pelacak kepala tidak terpasang secara permanen ke perangkat audio dan dapat digunakan secara terpisah, misalnya, dengan mengizinkan pengguna mengaitkan perangkat pelacak kepala secara manual dengan perangkat audio terpisah.
Referensi menggunakan alamat MAC Bluetooth
Octet | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Nilai | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | B | T | MAC Bluetooth |
Dalam skema ini, 8 oktet pertama harus 0
, oktet 8 dan 9 harus berisi
nilai ASCII B
dan T
masing-masing, dan 6 oktet berikutnya
ditafsirkan sebagai alamat MAC Bluetooth, dengan asumsi aplikasi pelacak kepala
berlaku untuk perangkat audio apa pun yang memiliki alamat MAC ini. Alamat ini harus berupa alamat identitas, meskipun perangkat menggunakan alamat MAC acak untuk membuat koneksi. Perangkat mode ganda yang terhubung melalui Bluetooth klasik
(format HID v1.0) dan Bluetooth LE (format HID v2.0) harus mengekspos dua deskriptor
HID dengan alamat identitas yang sama. Perangkat mode ganda dengan perangkat kiri dan kanan yang terpisah harus mengekspos Bluetooth LE HID menggunakan perangkat mode ganda utama, bukan perangkat sekunder khusus LE.
Referensi menggunakan UUID
Setiap kali bit paling signifikan (MSB) dari oktet 8 disetel (≥0x80
), kolom ditafsirkan sebagai UUID, seperti yang ditentukan dalam RFC-4122. Perangkat audio yang sesuai memberikan UUID yang sama, yang terdaftar di framework Android, melalui mekanisme yang tidak ditentukan yang khusus untuk jenis transportasi yang digunakan.
Properti: Status Pelaporan (0x0316
)
Properti Status Pelaporan (0x0316
) adalah properti baca/tulis yang memiliki
semantik standar seperti yang ditentukan dalam spesifikasi HID. Host menggunakan properti ini untuk menunjukkan kepada perangkat peristiwa mana yang harus dilaporkan. Hanya nilai Tidak Ada Peristiwa (0x0840
) dan Semua Peristiwa (0x0841
) yang digunakan.
Nilai awal untuk kolom ini harus berupa Tidak Ada Acara dan tidak boleh diubah oleh perangkat, hanya oleh host.
Properti: Status Daya (0x0319
)
Properti Status Daya (0x0319
) adalah properti baca/tulis yang memiliki
semantik standar seperti yang ditentukan dalam spesifikasi HID. Host menggunakan properti ini untuk menunjukkan kepada perangkat status daya yang harus digunakan. Hanya nilai Daya Penuh (0x0851
) dan Nonaktif (0x0855
) yang digunakan.
Nilai awal untuk kolom ini ditentukan oleh perangkat dan tidak boleh diubah oleh perangkat, hanya oleh host.
Properti: Interval Laporan (0x030E
)
Properti Interval Pelaporan (0x030E
) adalah properti baca/tulis yang memiliki
semantik standar seperti yang ditentukan dalam spesifikasi HID. Host menggunakan properti ini untuk menunjukkan kepada perangkat seberapa sering harus melaporkan pembacaan datanya.
Unit dalam hitungan detik. Rentang yang valid untuk nilai ini ditentukan oleh perangkat
dan dijelaskan menggunakan mekanisme Min/Maksimum Fisik. Frekuensi pelaporan minimal 50 Hz harus didukung, dan frekuensi pelaporan maksimum yang direkomendasikan adalah 100 Hz. Oleh karena itu, interval pelaporan minimum harus kurang dari atau sama dengan 20 md, dan direkomendasikan agar lebih besar atau sama dengan 10 md.
Properti: Transportasi LE yang dicadangkan vendor (0xF410
)
Properti Transportasi LE yang Dicadangkan Vendor (0xF410
) adalah properti baca/tulis
yang memiliki semantik standar seperti yang ditentukan dalam spesifikasi HID. Host
menggunakan properti ini untuk menunjukkan transport yang dipilih (ACL atau ISO). Hanya nilai ACL (0xF800
) dan ISO (0xF801
) yang digunakan, dan keduanya harus disertakan dalam koleksi logis.
Properti ini dikonfigurasi sebelum status daya atau pelaporan.
Kolom data: Nilai Kustom 1 (0x0544
)
Kolom Nilai Kustom 1 (0x0544
) adalah kolom input yang digunakan untuk melaporkan
informasi pelacakan kepala yang sebenarnya. Ini adalah array 3 elemen, yang ditafsirkan sesuai dengan aturan HID normal untuk nilai fisik seperti yang ditentukan dalam bagian 6.2.2.7 spesifikasi HID. Rentang yang valid untuk setiap elemen adalah [-π, π] rad. Unit
selalu dalam radian.
Elemen ditafsirkan sebagai: [rx, ry, rz]
, sehingga [rx, ry, rz]
adalah
vektor rotasi,
yang merepresentasikan transformasi dari frame referensi ke frame kepala.
Magnitudo harus dalam rentang [0..π].
Bingkai referensi bersifat arbitrer, tetapi umumnya tetap dan harus bersifat tangan kanan. Perbedaan kecil dapat diterima. Sumbu kepala adalah:
- X dari telinga kiri ke kanan
- Y dari bagian belakang kepala ke hidung (belakang ke depan)
- Z dari leher hingga bagian atas kepala
Kolom data: Nilai Kustom 2 (0x0545
)
Kolom Nilai Kustom 2 (0x0545
) adalah kolom input yang digunakan untuk melaporkan
informasi pelacakan kepala yang sebenarnya. Ini adalah array titik tetap 3 elemen,
ditafsirkan sesuai dengan aturan HID normal untuk nilai fisik.
Unit selalu berupa radian/detik.
Elemen ditafsirkan sebagai: [vx, vy, vz]
, sehingga [vx, vy, vz]
adalah
vektor rotasi,
yang merepresentasikan kecepatan sudut frame kepala (relatif terhadap dirinya sendiri).
Kolom data: Nilai Kustom 3 (0x0546
)
Kolom Nilai Kustom 3 (0x0546
) adalah kolom input yang digunakan untuk melacak
diskontinuitas dalam kerangka referensi. Ini adalah bilangan bulat skalar 8 bit dalam
ukuran. Nilai ini harus di-increment (dengan wraparound) oleh perangkat setiap kali
frame referensi diubah, misalnya, jika algoritma filter orientasi
yang digunakan untuk menentukan orientasi telah direset statusnya. Nilai ini ditafsirkan sesuai dengan aturan HID normal untuk nilai fisik. Namun,
nilai dan unit fisik tidak menjadi masalah. Satu-satunya informasi yang relevan dengan
host adalah nilai yang diubah. Untuk menghindari masalah numerik terkait hilangnya presisi saat mengonversi dari unit logis ke fisik, sebaiknya tetapkan nilai untuk minimum fisik, maksimum fisik, dan eksponen unit ke nol untuk kolom ini.
Struktur laporan
Pengelompokan properti ke dalam laporan (berdasarkan penetapan ID laporan) bersifat fleksibel. Agar efisien, sebaiknya pisahkan properti hanya baca dari properti baca/tulis.
Untuk kolom data, kolom Nilai Kustom 1, 2, dan 3 harus berada dalam laporan yang sama dan hanya berada dalam satu laporan untuk perangkat tertentu (pengumpulan aplikasi).
Mengirim laporan input
Perangkat harus mengirim laporan input secara berkala dan asinkron (melalui pesan INPUT HID) saat semua kondisi ini terpenuhi:
- Properti Status Daya disetel ke Daya Penuh.
- Properti Status Pelaporan disetel ke Semua Peristiwa.
- Properti Interval Pelaporan bukan nol.
Properti Interval Pelaporan menentukan frekuensi pengiriman laporan. Jika salah satu kondisi di atas tidak terpenuhi, perangkat tidak boleh mengirimkan laporan apa pun.
Kompatibilitas maju dan mundur
Protokol HID pelacak kepala menggunakan skema pembuatan versi yang memungkinkan update, sekaligus memungkinkan interoperabilitas antara host dan perangkat yang menggunakan versi protokol yang berbeda. Versi untuk protokol diidentifikasi oleh dua angka, mayor dan minor, yang memiliki semantik berbeda seperti yang dijelaskan di bagian berikut.
Versi yang didukung oleh perangkat dapat ditentukan dengan memeriksa
properti Deskripsi Sensor (0x0308
).
Kompatibilitas versi minor
Perubahan pada versi minor kompatibel mundur dengan versi minor sebelumnya yang didasarkan pada versi utama yang sama. Dalam pembaruan versi minor, host mengabaikan kolom dan properti data tambahan. Misalnya, perangkat yang menggunakan versi protokol 1.6 kompatibel dengan host yang mendukung versi protokol 1.x, termasuk versi 1.5.
Kompatibilitas versi utama
Perubahan yang tidak kompatibel dengan versi lama diizinkan untuk perubahan pada versi utama. Untuk mendukung beberapa versi utama agar dapat beroperasi dengan host lama dan baru, perangkat dapat menentukan beberapa koleksi aplikasi dalam deskriptor laporannya. Contoh:
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,
};
Dalam hal ini, host dapat menghitung semua koleksi aplikasi berbeda yang diiklankan oleh perangkat, memeriksa properti Deskripsi Sensornya untuk menentukan versi protokol yang diterapkan masing-masing, lalu memilih versi protokol terbaru yang didukung host. Jika dipilih, host akan berfungsi dengan satu protokol yang dipilih selama masa aktif koneksi perangkat.
Lampiran: Contoh deskripsi HID
Contoh berikut mengilustrasikan deskriptor HID valid yang umum. API ini menggunakan makro C yang umum digunakan, yang disediakan dalam Penggunaan Sensor HID (bagian 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,
};
Lampiran 2: Contoh deskriptor HID v2.0
Contoh berikut mengilustrasikan deskriptor HID v2.0 untuk perangkat yang hanya mendukung transportasi ACL Bluetooth LE.
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,
};