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, ses sanallaştırıcı efektini (3D ses) kontrol etmek için kullanılır. Bu sayfada cihaz ve ana makine terimleri Bluetooth bağlamında kullanılmaktadır. Cihaz, kafa hareketi izleme cihazı, ana makine ise Android ana makinesidir.

Cihaz üreticileri, Android cihazlarını kafa hareketi algılayıcı HID protokolü desteğini etkinleştirecek şekilde yapılandırmalıdır. Yapılandırma hakkında daha ayrıntılı bilgi için Dinamik Sensörler README dosyasını inceleyin.

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ı örneği için Ek 1: HID Tanımlayıcısı Örneği'ne bakın.

Üst düzeyde, kafa hareketi izleyici cihazı, Sensors sayfasını (0x20) ve Other: Custom kullanımını (0xE1) içeren bir uygulama koleksiyonudur. Bu koleksiyonda çeşitli veri alanları (girişler) ve mülkler (özellikler) bulunur.

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, aşağıdaki değerleri içermesi gereken salt okunur bir ASCII (8 bit) dize özelliğidir:

Baş takip cihazı 1.0 sürümü:

#AndroidHeadTracker#1.0

LE Audio desteği içeren 2.0 sürüm kafa takip cihazı (Android 15 veya sonraki sürümlerde kullanılabilir):

#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, 1.0 sürümü için bu mülkün toplam boyutunun 23 adet 8 bitlik karakter olduğu anlamına gelir.

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

Mülk: Kalıcı Benzersiz Kimlik (0x0302)

Kalıcı Benzersiz Kimlik (0x0302) özelliği, her biri 8 bit olan 16 öğeden oluşan salt okunur bir dizidir (toplam 128 bit). Boş sonlandırıcı beklenmez. Bu özellik isteğe bağlıdır.

Bu özellik, ses cihazlarına entegre edilmiş kafa hareketi izleme cihazlarının, bağlı oldukları ses cihazını referans almasına olanak tanı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ı

Sekizlik 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 bayt 0, 8. ve 9. baytlar sırasıyla B ve T ASCII değerlerini içermelidir. Kafa hareketi izleme cihazının bu MAC adresine sahip tüm ses cihazları için geçerli olduğu varsayılarak sonraki 6 bayt Bluetooth MAC adresi olarak yorumlanır. 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 kullanarak referans verme

8. baytın en önemli biti (MSB) ayarlandığında (≥0x80), alan RFC-4122'de belirtildiği gibi bir UUID olarak yorumlanır. İlgili ses cihazı, kullanılan aktarım türüne özgü, belirtilmemiş bir mekanizma aracılığıyla Android çerçevesine kaydedilen aynı UUID'yi sağlar.

Mülk: Raporlama Eyaleti (0x0316)

Raporlama Durumu (0x0316) mülkü, HID spesifikasyonunda tanımlanan standart semantiklere sahip bir okuma/yazma mülküdür. 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 No Events (Etkinlik Yok) olmalıdır ve hiçbir zaman cihaz tarafından değil, yalnızca ana makine tarafından değiştirilmelidir.

Özellik: Güç Durumu (0x0319)

Güç Durumu (0x0319) özelliği, HID spesifikasyonunda tanımlanan standart semantiklere sahip bir okuma/yazma özelliğidir. Ana makine, cihaza hangi güç durumunda olması gerektiğini belirtmek için bu özelliği kullanır. 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.

Tesis: 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. Birim 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 kafa izleme bilgilerini bildirmek için kullanılan bir giriş alanıdır. 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]. [rx, ry, rz], referans çerçeveden kafa çerçevesine dönüşümü temsil eden bir dönme vektörüdür. Büyüklük [0..π] aralığında olmalıdır.

Referans çerçevesi keyfidir ancak genellikle sabittir ve sağ ellidir. Az miktarda kayma kabul edilebilir. Kafa eksenleri şunlardır:

  • Sol kulaktan sağ kulağa X
  • Y, başın arka kısmından burna (arkadan öne)
  • Z, boyundan başın üst kısmına

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

Özel Değer 2 (0x0545) alanı, gerçek kafa izleme bilgilerini bildirmek için kullanılan bir giriş alanıdır. Fiziksel değerler için normal HID kurallarına göre yorumlanan 3 öğeli sabit nokta dizisidir. 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 kesintilerin izlenmesi için kullanılan bir giriş alanıdır. 8 bit boyutunda bir skaler tam sayıdır. 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 raporlara göre gruplandırılması (rapor kimlikleri atayarak) esnektir. 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ı raporda olmalı ve belirli bir cihaz (uygulama koleksiyonu) için yalnızca bir raporda yer almalıdır.

Giriş raporlarını gönderme

Cihaz, aşağıdaki koşulların tümü karşılandığında giriş raporlarını düzenli olarak ve eşzamansız olarak (HID INPUT mesajları aracılığıyla) göndermelidir:

  • 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. Yukarıdaki koşullardan hiçbiri karşılanmadığında cihaz herhangi bir rapor göndermemelidir.

İleri ve geriye dönük uyumluluk

Baş takip cihazı HID protokolü, güncellemelere izin veren ve aynı zamanda ana makine ile protokolün farklı sürümlerini kullanan bir cihaz arasında birlikte çalışabilirlik sağlayan bir sürüm şeması kullanır. 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

Alt sürümde yapılan değişiklikler, aynı ana sürüme dayalı önceki alt sürümlerle geriye dönük uyumludur. Küçük sürümdeki güncellemelerde, ana makine ek veri alanlarını ve özelliklerini yoksayar. Örneğin, 1.6 protokol sürümünü kullanan bir cihaz, 1.5 sürümü dahil olmak üzere 1.x protokol sürümünü destekleyen bir ana makineyle uyumludur.

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, geçerli bir HID tanımlayıcısı gösterilmektedir. HID Sensör Kullanımları bölümünde (bölüm 4.1) sağlanan yaygın olarak kullanılan C makrolarını kullanır.

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