Baş takip cihazı HID protokolü

Android 13 ve sonraki sürümleri çalıştıran cihazlar için kullanılabilen kafa izleyici insan arayüz cihazı (HID) protokolü, baş izleme cihazının USB veya Bluetooth aracılığıyla bir Android cihaza bağlanmasına ve sensörler çerçevesi üzerinden Android çerçevesine ve uygulamalarına maruz kalmasına olanak tanır. Bu protokol, ses sanallaştırıcı efektini (3D ses) kontrol etmek için kullanılır. Bu sayfa, Bluetooth anlamında cihaz ve ana makine terimlerini kullanmaktadır. Burada cihaz baş izleme cihazı, ana makine terimi Android ana makinesi anlamına gelmektedir.

Cihaz üreticilerinin, Android cihazlarını kafa izleyici HID protokolü desteğini etkinleştirecek şekilde yapılandırmaları gerekir. Yapılandırma hakkında daha ayrıntılı bilgi için Dinamik Sensörler README dosyasını inceleyin.

Bu sayfada aşağıdaki kaynaklara aşina olduğunuz varsayılı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 Ek 1: HID Açıklayıcı Örneği bölümüne bakın.

Üst seviyede baş takip cihazı cihazı, Sensors sayfası (0x20) ve Other: Custom kullanımı (0xE1) içeren bir uygulama koleksiyonudur. Bu koleksiyonda çeşitli veri alanları (girişler) ve özellikler (ö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:

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) ve LE Audio desteği şunları içerir:

#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ş sonlayıcı beklenmemektedir. Diğer bir deyişle, bu mülkün toplam boyutu 1.0 sürümü için 23 8 bit karakterdir.

Bu özellik, diğer özel sensörlerle çarpışmamak için bir ayırıcı işlevi görür.

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 baş takip cihazı

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. Örneğin, kullanıcının kafa hareketi algılama cihazını ayrı bir ses cihazıyla manuel olarak ilişkilendirmesine izin verilebilir.

Bluetooth MAC adresi kullanarak 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 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. Bu adres, cihaz bağlantı kurmak için rastgele bir MAC adresi kullansa bile 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

Sekizli 8'in en anlamlı biti (MSB) ayarlandığında (≥0x80) alan, RFC-4122'de belirtildiği gibi bir UUID olarak yorumlanır. Karşılık gelen ses cihazı, Android çerçevesine kayıtlı olan aynı UUID'yi, kullanılan taşıma türüne özel, belirtilmemiş bir mekanizma aracılığıyla sağlar.

Mülk: Raporlama Durumu (0x0316)

Raporlama Durumu (0x0316) özelliği, HID spesifikasyonunda tanımlanan standart semantiklere sahip bir okuma/yazma özelliğidir. Barındırıcı, cihaza hangi etkinliklerin raporlanacağını 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ımlandığı gibi standart anlamlara 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ğiştirilmemelidir. Yalnızca ana makine tarafından değiştirilmemelidir.

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 cihaza göre belirlenir ve Fiziksel Min/Maks mekanizması kullanılarak tanımlanı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.

Mülk: Tedarikçi firma tarafından ayrılmış LE Transport (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 raporlamak 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]. Burada [rx, ry, rz], referans çerçevesinden ana çerçeveye dönüşümü temsil eden bir döndürme vektörüdür. Büyüklük, [0..karma] aralığında olmalıdır.

Referans çerçevesi rastgele olsa da genellikle sabittir ve sağ el kullanılmalıdır. Az miktarda kayma kabul edilebilir. Baş eksenleri şunlardır:

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

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 noktalı bir dizidir. Birimler her zaman radyan/saniyedir.

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

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

Özel Değer 3 (0x0546) alanı, referans çerçevesindeki süreksizlikleri izlemek için kullanılan bir giriş alanıdır. Bu, 8 bit boyutunda skaler bir tam sayıdır. Referans çerçevesi her değiştiğinde (ör. yönü belirlemek için kullanılan bir yön filtresi algoritmasının durumu sıfırlanmışsa) bu değer, cihaz tarafından sarmalanarak artırılmalıdır. 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ştirilmiş bir değerdir. Mantıksal birimden fiziksel birimlere dönüştürme sırasında hassasiyet kaybıyla ilgili sayısal sorunlardan kaçınmak için bu alan için fiziksel minimum, fiziksel maks ve birim üs değerlerini sıfır olarak ayarlamanız ö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 için yalnızca bir raporda (uygulama koleksiyonu) 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 özelliği, Tam Güç olarak ayarlanı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 sürümleri, aşağıdaki bölümlerde açıklandığı gibi farklı anlamlara sahip ana ve küçük olmak üzere iki sayıyla 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ümdeki 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, ev sahibi ek veri alanlarını ve özelliklerini yoksayar. Örneğin, protokol sürümü 1.6'yı kullanan bir cihaz, 1.5 sürümü de dahil olmak üzere protokol 1.x 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 ana 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ı numaralandırabilir, her birinin uyguladığı protokol sürümlerini belirlemek için Sensör Açıklaması özelliğini inceleyip ana makinenin desteklediği en son protokol sürümünü seçebilir. Ana makine, seçildiğinde cihaz bağlantısının ömrü boyunca seçilen tek protokolle çalışır.

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

Aşağıdaki örnekte tipik bir geçerli HID tanımlayıcısı gösterilmektedir. HID Sensör Kullanımları bölümünde (bölüm 4.1) belirtilen, 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ı örneği

Aşağıdaki örnekte yalnızca Bluetooth LE ACL aktarımını destekleyen bir cihazın v2.0 HID tanımlayıcısı 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,
};