Baş takip cihazı HID protokolü

Android 13 ve sonraki sürümleri çalıştıran cihazlarda kullanılabilen kafa hareketi algılayıcı insan arayüz cihazı (HID) protokolü, kafa hareketi algılayıcı cihazın USB veya Bluetooth üzerinden bir Android cihaza bağlanmasına ve sensörler çerçevesi aracılığıyla Android çerçevesine ve uygulamalara erişmesine olanak tanır. Bu protokol şunlar için kullanılır: kontrol ediyor Ses sanallaştırıcı efekti (3D ses). Bu sayfada cihaz ve Bluetooth anlamında ana makine (cihaz, baş izleme cihazı anlamına gelir) host ise Android ana makinesi anlamına gelir.

Cihaz üreticilerinin Android cihazlarını desteğin etkinleştirilmesi için yapılandırmaları gerekir: baş takip cihazı HID protokolüyle uyumlu. Ayrıntılı bilgi için daha fazla bilgi için Dinamik Sensörler BENİOKU).

Bu sayfada, aşağıdaki kaynaklar hakkında bilgi sahibi olduğunuz varsayılmaktadır:

Üst düzey yapı

Android çerçevesi, kafa hareketi algılama cihazını HID cihaz olarak tanımlar.

Geçerli bir HID tanımlayıcısının tam örneği için bkz. Ek 1: HID Açıklayıcı örneği.

Üst düzeyde, baş takip cihazı, şuna sahip bir uygulama koleksiyonudur: Sensors sayfası (0x20) ve Other: Custom kullanımı (0xE1). İçinde çeşitli veri alanları (girişler) ve özelliklerden (özellikler) oluşur.

Mülkler ve veri alanları

Bu bölümde, bir kafa hareketi izleyici cihazının uygulama koleksiyonundaki özellikler ve veri alanları açıklanmaktadır.

Özellik: Sensör Açıklaması (0x0308)

Sensör Açıklaması (0x0308) özelliği, salt okunur bir ASCII (8 bit) dizesidir özelliği ekleyin:

Head takip cihazı sürüm 1.0:

#AndroidHeadTracker#1.0

Baş takip cihazı sürüm 2.0 (Android 15 veya sonraki sürümlerde kullanılabilir. yüksek) şunları sağlar:

#AndroidHeadTracker#2.0#x

x, destek taşıma işlemini belirten bir tam sayıdır (1, 2, 3):

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

Boşluk sonlandırıcı beklenmez. Bu, bu mülkün toplam boyutunun 1.0 sürümü için 23 8 bit karakter olduğu anlamına gelir.

Bu özellik, diğer özel sensörlerle çakışmaları önlemek için ayırt edici bir özelliktir.

Özellik: Kalıcı Benzersiz Kimlik (0x0302)

Kalıcı Benzersiz Kimlik (0x0302) özelliği, 16'lık salt okunur bir dizidir öğeler, her biri 8 bit (toplam 128 bit). Boş sonlandırıcı beklenmemektedir. Bu özelliği isteğe bağlıdır.

Bu özellik, sese entegre edilmiş baş izleme cihazlarına izin verir. cihazları, bağlı oldukları ses cihazına referans göstermek için kullanır. Aşağıdaki şemalar desteklenir.

Bağımsız kafa hareketi izleyici

Kalıcı Benzersiz Kimlik (0x0302) mülkü mevcut değilse veya tümüyle sıfır olarak ayarlanmışsa kafa hareketi algılama cihazı bir ses cihazına kalıcı olarak bağlı değildir ve ayrı olarak kullanılabilir (ör. kullanıcının kafa hareketi algılama cihazını ayrı bir ses cihazıyla manuel olarak ilişkilendirmesine izin verilerek).

Bluetooth MAC adresini kullanma referansı

Sekiz 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Değer 0 0 0 0 0 0 0 0 B T Bluetooth MAC

Bu şemada, ilk 8 sekizlik 0, 8 ve 9 sekizlikleri şunları içermelidir sırasıyla B ve T ASCII değerleri ve aşağıdaki 6 sekizlik bir Bluetooth MAC adresi olarak yorumlanır ve baş takip cihazının bu MAC adresine sahip tüm ses sistemleri için geçerlidir. Cihaz bağlantı kurmak için rastgele bir MAC adresi kullansa bile bu adres, kimlik adresi olmalıdır. Bluetooth klasik (v1.0 HID biçimi) ve Bluetooth LE (v2.0 HID biçimi) üzerinden bağlanan çift modlu cihazlar, aynı kimlik adresine sahip iki HID tanımlayıcısı göstermelidir. Ayrı sol ve sağ cihazlara sahip çift modlu cihazlar, yalnızca LE olan ikincil cihaz yerine birincil çift modlu cihazı kullanarak Bluetooth LE HID'yi göstermelidir.

UUID kullanan referans

8. baytın en önemli biti (MSB) ayarlandığında (≥0x80), alan RFC-4122'de belirtildiği gibi bir UUID olarak yorumlanır. İlgili içeriği oluşturmak için kullanılan ses cihazında kayıtlı olan UUID'nin aynısını sağlar sisteme özgü belirtilmemiş bir mekanizma aracılığıyla, kullanılan ulaşım türünü ifade eder.

Mülk: Raporlama Durumu (0x0316)

Raporlama Durumu (0x0316) özelliği, aşağıdakileri içeren bir okuma/yazma özelliğidir: HID spesifikasyonunda tanımlandığı gibi standart anlamlar. Barındırıcı, hangi etkinliklerin raporlanacağını cihaza belirtmek için bu özelliği kullanır. Yalnızca Etkinlik Yok (0x0840) ve Tüm Etkinlikler (0x0841) değerleri kullanılır.

Bu alanın ilk değeri Etkinlik Yok olmalı ve hiçbir zaman olmamalıdır cihaz tarafından değiştirildiğinde yalnızca ana makine tarafından değiştirilir.

Özellik: Güç Durumu (0x0319)

Güç Durumu (0x0319) özelliği, HID spesifikasyonunda tanımlandığı gibi standart anlamlar. Ana makine, bunu özelliğini kullanarak cihazın hangi güç durumunda olması gerektiğini belirtir. Yalnızca Tam Güç (0x0851) ve Kapat (0x0855) değerleri kullanılır.

Bu alanın ilk değeri cihaz tarafından belirlenir ve hiçbir zaman cihaz tarafından değil, yalnızca ana makine tarafından değiştirilmelidir.

Mülk: Rapor Aralığı (0x030E)

Rapor Aralığı (0x030E) mülkü, HID spesifikasyonunda tanımlanan standart semantiklere sahip bir okuma/yazma mülküdür. Ana makine, cihaza veri okumalarını ne sıklıkta bildireceğini belirtmek için bu özelliği kullanır. Birimler saniyedir. Bu değer için geçerli aralık cihaz tarafından belirlenir ve fiziksel minimum/maksimum mekanizması kullanılarak açıklanır. En az 50 Hz raporlama hızı desteklenmelidir ve önerilen maksimum raporlama hızı 100 Hz'dir. Bu nedenle, minimum rapor aralığı 20 ms'den az veya eşit olmalıdır ve 10 ms'den büyük veya eşit olması önerilir.

Özellik: Satıcı tarafından ayrılmış LE Taşıma (0xF410)

Tedarikçi firma tarafından ayrılmış LE Aktarım (0xF410) özelliği, HID spesifikasyonunda tanımlanan standart semantiklere sahip bir okuma/yazma özelliğidir. Ana makine, seçili taşımayı (ACL veya ISO) belirtmek için bu mülkü kullanır. Yalnızca değerler ACL'si (0xF800) ve ISO (0xF801) kullanılır ve her ikisi de mantıksal koleksiyona dahil edilmelidir.

Bu özellik, güç veya raporlama durumlarından önce yapılandırılır.

Veri alanı: Özel Değer 1 (0x0544)

Özel Değer 1 (0x0544) alanı, gerçek baş izleme bilgileridir. HID spesifikasyonunun 6.2.2.7 numaralı bölümünde belirtildiği gibi fiziksel değerler için normal HID kurallarına göre yorumlanan 3 öğeli bir dizidir. Her öğe için geçerli aralık [-π, π] rad'dir. Birim her zaman radyan olarak belirtilir.

Öğeler şu şekilde yorumlanır: [rx, ry, rz]. Böylece [rx, ry, rz], bir rotasyon vektörü için , referans çerçeveden ana çerçeveye dönüştürmeyi temsil eder. Büyüklük [0..π] aralığında olmalıdır.

Referans çerçevesi rastgeledir ancak genellikle sabittir ve sağ elle kullanılıyor. Az miktarda kayma kabul edilebilir. Baş eksenleri şunlardır:

  • Sol kulaktan sağ kulağa X
  • kafanın arkasından buruna kadar Y (geriye doğru)
  • Boyundan başın üst kısmına kadar Z

Veri alanı: Özel Değer 2 (0x0545)

Özel Değer 2 (0x0545) alanı, gerçek baş izleme bilgileridir. Bu, 3 öğeli sabit noktalı bir dizidir, Fiziksel değerler için normal HID kurallarına göre yorumlanır. Birimler her zaman radyan/saniyedir.

Öğeler şu şekilde yorumlanır: [vx, vy, vz]. [vx, vy, vz], kafa çerçevesinin açısal hızını (kendisine göre) temsil eden bir dönme vektörüdür.

Veri alanı: Özel Değer 3 (0x0546)

Özel Değer 3 (0x0546) alanı, referans çerçevesindeki kesintileri izlemek için kullanılan bir giriş alanıdır. Bu, 8 bitlik skaler bir tam sayıdır seçin. Referans çerçevesi her değiştiğinde cihaz tarafından artırılmalıdır (sarmalama ile). Örneğin, yönelimi belirlemek için kullanılan bir yönelim filtresi algoritmasının durumu sıfırlandıysa. Bu değer, fiziksel değerler için normal HID kurallarına göre yorumlanır. Ancak fiziksel değer ve birimler önemli değildir. Ana makineyle ilgili tek bilgi, değiştirilen değerdir. Mantıksal birimlerden fiziksel birimlere dönüştürme işlemi sırasında hassasiyet kaybıyla ilgili sayısal sorunları önlemek için bu alan için fiziksel minimum, fiziksel maksimum ve birim üssü değerlerinin sıfır olarak ayarlanması önerilir.

Rapor yapısı

Mülklerin raporlar halinde gruplandırılması (rapor kimliklerinin atamasına göre) daha esnek hale getirebilirsiniz. Verimliliği artırmak için salt okunur mülkleri salt okunur/yazılabilir mülklerden ayırmanızı öneririz.

Veri alanları için Özel Değer 1, 2 ve 3 alanları aynı olmalıdır belirli bir cihaz için (uygulama koleksiyonu) tek bir raporda yer alması gerekir.

Giriş raporlarını gönderme

Cihaz periyodik ve eşzamansız olarak (HID INPUT mesajlarıyla) olmalıdır tüm şu koşullar karşılandığında giriş raporları gönder:

  • Güç Durumu mülkü Tam Güç olarak ayarlanmıştır.
  • Raporlama Durumu mülkü Tüm Etkinlikler olarak ayarlanmıştır.
  • Raporlama Aralığı özelliği sıfırdan farklı.

Raporlama Aralığı özelliği, raporların ne sıklıkta gönderileceğini belirler. Zaman yukarıdaki koşullardan hiçbiri karşılanmadığında, cihazın herhangi bir rapor göndermemesi gerekir.

İleri ve geri uyumluluk

Ana izleyici HID protokolü, bir ana makine ile cihaz kullanan bir cihaz arasında birlikte çalışabilirlik sağlar. farklı sürümleri olabilir. Protokolün sürümleri, aşağıdaki bölümlerde açıklandığı gibi farklı anlamlara sahip olan büyük ve küçük olmak üzere iki sayı ile tanımlanır.

Bir cihazın desteklediği sürümler, Sensör Açıklaması (0x0308) özelliği incelenerek belirlenebilir.

Alt sürüm uyumluluğu

Ara sürümdeki değişiklikler, aynı ana sürüme dayalı önceki ara sürümlerle geriye dönük olarak uyumludur. Küçük sürümdeki güncellemelerde, ev sahibi ek veri alanlarını ve özelliklerini yoksayar. Örneğin, Protokol sürümü 1.6 kullanan bir cihazın, aşağıdakini destekleyen bir ana makineyle uyumlu olması: protokol sürümü 1.x (1.5 sürümü dahil).

Ana sürüm uyumluluğu

Ana sürümlerde yapılan değişikliklerde geriye dönük uyumlu olmayan değişikliklere izin verilir. Cihazlar, eski ve yeni ana makinelerle birlikte çalışabilirlik için birden fazla büyük sürümü desteklemek amacıyla rapor tanımlayıcılarında birden fazla uygulama koleksiyonu belirtebilir. Örnek:

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

Bu durumda, ana makine, cihaz tarafından reklamı yapılan tüm farklı uygulama koleksiyonlarını sayabilir, her birinin uyguladığı protokol sürümlerini belirlemek için Sensör Açıklaması mülkünü inceleyebilir ve ardından ana makinenin desteklediği en son protokol sürümünü seçebilir. Seçildiğinde ana makine, cihaz bağlantısının kullanım ömrü boyunca seçilen tek protokolle çalışır.

Ek: HID tanımlayıcı örneği

Aşağıdaki örnekte tipik bir geçerli HID tanımlayıcısı gösterilmektedir. Şunu kullanır: kullanılan C makroları, HID Sensör Kullanımları (bölüm 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,
};

Ek 2: v2.0 HID tanımlayıcısı örneği

Aşağıdaki örnekte, yalnızca Bluetooth LE ACL aktarımını destekleyen bir cihaz için v2.0 HID tanımlayıcı gösterilmektedir.

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