Protokol HID pelacak kepala

Protokol perangkat antarmuka manusia (HID) head tracker, yang tersedia untuk perangkat yang menjalankan Android 13 dan yang lebih tinggi, memungkinkan perangkat pelacakan kepala terhubung ke perangkat Android melalui USB atau Bluetooth dan diekspos ke framework dan aplikasi Android melalui framework sensors. Protokol ini digunakan untuk mengontrol efek virtualizer audio (audio 3D). Halaman ini menggunakan istilah perangkat dan host dalam arti Bluetooth, dengan perangkat berarti perangkat pelacakan kepala dan host berarti host Android.

Produsen perangkat harus mengonfigurasi perangkat Android mereka untuk mengaktifkan dukungan untuk protokol HID pelacak kepala. Untuk informasi selengkapnya tentang konfigurasi, lihat README Sensor Dinamis.

Halaman ini mengasumsikan Anda sudah memahami resource berikut:

Struktur tingkat atas

Framework Android mengidentifikasi perangkat pelacak kepala sebagai perangkat HID.

Untuk contoh lengkap deskripsi HID yang valid, lihat Lampiran 1: Contoh Deskripsi HID.

Di tingkat teratas, perangkat pelacak kepala adalah koleksi aplikasi dengan halaman Sensors (0x20) dan penggunaan Other: Custom (0xE1). Di dalam koleksi ini terdapat beberapa kolom data (input) dan properti (fitur).

Properti dan kolom data

Bagian ini menjelaskan properti dan kolom data dalam koleksi aplikasi perangkat head tracker.

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 audio LE:

#AndroidHeadTracker#2.0#x

x adalah bilangan bulat (1, 2, 3) yang menunjukkan transpor dukungan:

  • 1: ACL
  • 2: ISO
  • 3: ACL + ISO

Tidak ada terminal null yang diharapkan, yang berarti ukuran total properti ini adalah 23 karakter 8-bit untuk versi 1.0.

Properti ini berfungsi sebagai diskriminator untuk menghindari konflik dengan sensor kustom lainnya.

Properti: ID Unik yang Persisten (0x0302)

Properti ID Unik Persisten (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 pelacakan kepala yang terintegrasi dalam perangkat audio untuk mereferensikan perangkat audio yang terhubung. Skema berikut didukung.

Pelacak kepala mandiri

Jika properti ID Unik yang Persisten (0x0302) tidak ada atau disetel ke semua nol, artinya 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

Oktet 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 octet pertama harus 0, octet 8 dan 9 harus berisi nilai ASCII B dan T, dan 6 octet berikut ditafsirkan sebagai alamat MAC Bluetooth, dengan asumsi perangkat 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) octet 8 ditetapkan (≥0x80), kolom akan 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 transpor 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 akan dilaporkan. Hanya nilai Tidak Ada Peristiwa (0x0840) dan Semua Peristiwa (0x0841) yang digunakan.

Nilai awal untuk kolom ini harus No Events 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 dimilikinya. 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 Laporan (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 melaporkan pembacaan datanya. Satuan dalam detik. Rentang yang valid untuk nilai ini ditentukan oleh perangkat dan dijelaskan menggunakan mekanisme Min/Max Fisik. Setidaknya rasio pelaporan 50 Hz harus didukung, dan frekuensi pelaporan maksimum yang direkomendasikan adalah 100 Hz. Oleh karena itu, interval laporan minimum harus kurang dari atau sama dengan 20 milidetik, dan direkomendasikan agar lebih besar dari atau sama dengan 10 milidetik.

Properti: LE Transport yang direservasi ke vendor (0xF410)

Properti Transport 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 ACL nilai (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. Array 3 elemen, yang ditafsirkan sesuai dengan aturan HID normal untuk nilai fisik sebagaimana ditetapkan dalam bagian 6.2.2.7 dari spesifikasi HID. Rentang yang valid untuk setiap elemen adalah [-π, π] rad. Satuan selalu radian.

Elemen ditafsirkan sebagai: [rx, ry, rz], sehingga [rx, ry, rz] merupakan vektor rotasi, yang mewakili transformasi dari frame referensi ke frame head. Magnitudo harus berada dalam rentang [0..π].

Frame referensi bersifat arbitrer, tetapi umumnya bersifat tetap dan harus menggunakan tangan kanan. Sedikit penyimpangan dapat diterima. Sumbu kepala adalah:

  • X dari telinga kiri ke kanan
  • Y dari belakang kepala ke hidung (belakang ke depan)
  • Z dari leher ke 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. Array adalah array titik tetap 3 elemen, yang ditafsirkan sesuai dengan aturan HID normal untuk nilai fisik. Satuan selalu radian/detik.

Elemen ditafsirkan sebagai: [vx, vy, vz], sehingga [vx, vy, vz] adalah vektor rotasi, yang mewakili 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 frame referensi. Ini adalah bilangan bulat skalar dengan ukuran 8 bit. Nilai ini harus bertambah (dengan pengulangan) 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 fisik dan unit tidak menjadi masalah. Satu-satunya informasi yang relevan dengan host adalah nilai yang diubah. Untuk menghindari masalah numerik yang terkait dengan hilangnya presisi saat melakukan konversi dari unit logis ke fisik, sebaiknya tetapkan nilai untuk min fisik, maksimum fisik, dan eksponen satuan ke nol untuk kolom ini.

Struktur laporan

Pengelompokan properti ke dalam laporan (menurut penetapan ID laporan) bersifat fleksibel. Untuk efisiensi, 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 ada dalam satu laporan untuk perangkat tertentu (kumpulan aplikasi).

Mengirim laporan input

Perangkat harus secara berkala dan asinkron (melalui pesan HID INPUT) mengirim laporan input jika semua kondisi ini terpenuhi:

  • Properti Status Daya disetel ke Daya Penuh.
  • Properti Status Pelaporan ditetapkan 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 mengirim laporan apa pun.

Kompatibilitas maju dan mundur

Protokol HID head tracker 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 yang berbeda seperti yang dijelaskan di bagian berikut.

Versi yang didukung oleh perangkat dapat ditentukan dengan memeriksa properti Deskripsi Sensor (0x0308)-nya.

Kompatibilitas versi minor

Perubahan pada versi minor kompatibel dengan versi minor sebelumnya yang didasarkan pada versi utama yang sama. Dalam update pada versi minor, host mengabaikan kolom data dan properti tambahan. Misalnya, perangkat yang menggunakan protokol versi 1.6 kompatibel dengan host yang mendukung protokol versi 1.x, termasuk versi 1.5.

Kompatibilitas versi utama

Perubahan yang tidak kompatibel dengan versi lama diizinkan untuk perubahan pada versi utama. Guna mendukung beberapa versi utama untuk interoperabilitas 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 berbagai koleksi aplikasi yang diiklankan oleh perangkat, memeriksa properti Deskripsi Sensor mereka untuk menentukan versi protokol yang diterapkan masing-masing, lalu memilih versi protokol terbaru yang didukung oleh host. Jika dipilih, host bekerja dengan satu protokol yang dipilih selama masa aktif koneksi perangkat.

Lampiran: Contoh deskripsi HID

Contoh berikut mengilustrasikan deskripsi HID standar yang valid. Fungsi ini menggunakan makro C yang umum digunakan, yang disediakan di 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 deskripsi HID v2.0 untuk perangkat yang hanya mendukung transpor 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,
};