پروتکل HID ردیاب سر

پروتکل دستگاه رابط انسانی ردیاب سر (HID) که برای دستگاه‌های دارای اندروید ۱۳ و بالاتر در دسترس است، به دستگاه ردیاب سر اجازه می‌دهد تا از طریق USB یا بلوتوث به دستگاه اندروید متصل شود و از طریق چارچوب حسگرها در معرض چارچوب و برنامه‌های اندروید قرار گیرد. این پروتکل برای کنترل جلوه مجازی‌ساز صوتی (صدای سه‌بعدی) استفاده می‌شود. این صفحه از اصطلاحات دستگاه و میزبان به معنای بلوتوث آنها استفاده می‌کند، که در آن دستگاه به معنای دستگاه ردیاب سر و میزبان به معنای میزبان اندروید است.

تولیدکنندگان دستگاه باید دستگاه‌های اندروید خود را طوری پیکربندی کنند که پشتیبانی از پروتکل HID ردیاب سر را فعال کنند. برای اطلاعات بیشتر در مورد پیکربندی، به فایل راهنمای حسگرهای پویا مراجعه کنید.

این صفحه آشنایی با منابع زیر را فرض می‌کند:

ساختار سطح بالا

چارچوب اندروید، دستگاه ردیاب سر را به عنوان یک دستگاه HID شناسایی می‌کند.

برای مثال کاملی از یک توصیفگر HID معتبر، به پیوست 1: مثالی از یک توصیفگر HID مراجعه کنید.

در سطح بالا، دستگاه ردیاب سر یک مجموعه برنامه با صفحه Sensors ( 0x20 ) و صفحه Other: Custom ( 0xE1 ) است. درون این مجموعه چندین فیلد داده ( ورودی ) و ویژگی ( ویژگی ) وجود دارد.

ویژگی‌ها و فیلدهای داده

این بخش، ویژگی‌ها و فیلدهای داده را در یک مجموعه برنامه از یک دستگاه ردیاب سر شرح می‌دهد.

Property: Sensor Description ( 0x0308 )

ویژگی توضیحات حسگر ( 0x0308 ) یک ویژگی رشته‌ای ASCII (8 بیتی) فقط خواندنی است که باید حاوی مقادیر زیر باشد:

ردیاب سر نسخه ۱.۰:

#AndroidHeadTracker#1.0

ردیاب سر نسخه ۲.۰ (موجود در اندروید ۱۵ یا بالاتر)، که شامل پشتیبانی از صدای LE می‌شود:

#AndroidHeadTracker#2.0#x

x یک عدد صحیح ( 1 ، 2 ، 3 ) است که نشان دهنده انتقال پشتیبانی است:

  • ۱: لیگامان صلیبی قدامی
  • ۲: ایزو
  • ۳: ACL + ISO

هیچ پایانه تهی انتظار نمی‌رود، به این معنی که اندازه کل این ویژگی برای نسخه ۱.۰، ۲۳ کاراکتر ۸ بیتی است.

این ویژگی به عنوان یک تمایز دهنده برای جلوگیری از برخورد با سایر حسگرهای سفارشی عمل می‌کند.

ویژگی: شناسه منحصر به فرد پایدار ( 0x0302 )

ویژگی Persistent Unique ID ( 0x0302 ) یک آرایه فقط خواندنی با ۱۶ عنصر است که هر کدام ۸ بیت (در مجموع ۱۲۸ بیت) طول دارند. هیچ پایانه تهی (null terminator) مورد انتظار نیست. این ویژگی اختیاری است.

این ویژگی به دستگاه‌های ردیابی سر که در دستگاه‌های صوتی ادغام شده‌اند، اجازه می‌دهد تا به دستگاه صوتی که به آن متصل هستند، ارجاع دهند. طرح‌های زیر پشتیبانی می‌شوند.

ردیاب سر مستقل

اگر ویژگی Persistent Unique ID ( 0x0302 ) وجود نداشته باشد یا روی همه صفرها تنظیم شده باشد، به این معنی است که دستگاه ردیاب سر به طور دائم به یک دستگاه صوتی متصل نیست و می‌تواند به طور جداگانه مورد استفاده قرار گیرد، به عنوان مثال، با اجازه دادن به کاربر برای مرتبط کردن دستی دستگاه ردیاب سر با یک دستگاه صوتی جداگانه.

مرجع با استفاده از آدرس MAC بلوتوث

هشت‌تایی 0 ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰ ۱۱ ۱۲ ۱۳ ۱۴ ۱۵
ارزش 0 0 0 0 0 0 0 0 ب تی بلوتوث مک

در این طرح، ۸ اکتت اول باید 0 باشند، اکتت‌های ۸ و ۹ باید به ترتیب حاوی مقادیر ASCII B و T باشند و ۶ اکتت بعدی به عنوان یک آدرس MAC بلوتوث تفسیر می‌شوند، با فرض اینکه دستگاه ردیاب سر برای هر دستگاه صوتی دارای این آدرس MAC اعمال می‌شود. این آدرس باید آدرس هویت باشد، حتی اگر دستگاه از یک آدرس MAC تصادفی برای برقراری اتصال استفاده کند. دستگاه‌های دو حالته که از طریق بلوتوث کلاسیک (فرمت HID نسخه ۱.۰) و بلوتوث LE (فرمت HID نسخه ۲.۰) متصل می‌شوند، باید دو توصیفگر HID با آدرس هویت یکسان را نمایش دهند. دستگاه‌های دو حالته با دستگاه‌های چپ و راست جدا از هم باید بلوتوث LE HID را با استفاده از دستگاه حالت دوگانه اولیه به جای دستگاه ثانویه فقط LE نمایش دهند.

ارجاع با استفاده از UUID

هر زمان که مهم‌ترین بیت (MSB) از اکتت ۸ برابر با ( ≥0x80 ) تنظیم شود، این فیلد به عنوان یک UUID تفسیر می‌شود، همانطور که در RFC-4122 مشخص شده است. دستگاه صوتی مربوطه، UUID مشابهی را ارائه می‌دهد که در چارچوب اندروید ثبت شده است، از طریق یک مکانیسم نامشخص که مختص نوع انتقال مورد استفاده است.

ویژگی: ایالت گزارش‌دهنده ( 0x0316 )

ویژگی وضعیت گزارش‌دهی ( 0x0316 ) یک ویژگی خواندن/نوشتن است که معنای استاندارد آن مطابق با مشخصات HID تعریف شده است. میزبان از این ویژگی برای نشان دادن به دستگاه مبنی بر اینکه کدام رویدادها را گزارش کند، استفاده می‌کند. فقط از مقادیر No Events ( 0x0840 ) و All Events ( 0x0841 ) استفاده می‌شود.

مقدار اولیه این فیلد باید No Events باشد و هرگز نباید توسط دستگاه تغییر کند، فقط توسط میزبان.

ویژگی: وضعیت برق ( 0x0319 )

ویژگی وضعیت برق ( 0x0319 ) یک ویژگی خواندن/نوشتن است که معنای استاندارد آن مطابق با مشخصات HID تعریف شده است. میزبان از این ویژگی برای نشان دادن وضعیت برق دستگاه به آن استفاده می‌کند. فقط مقادیر Full Power ( 0x0851 ) و Power Off ( 0x0855 ) استفاده می‌شوند.

مقدار اولیه این فیلد توسط دستگاه تعیین می‌شود و هرگز نباید توسط دستگاه تغییر کند، فقط توسط میزبان.

ویژگی: بازه گزارش ( 0x030E )

ویژگی فاصله گزارش ( 0x030E ) یک ویژگی خواندن/نوشتن است که معنای استاندارد آن مطابق با مشخصات HID تعریف شده است. میزبان از این ویژگی برای نشان دادن به دستگاه استفاده می‌کند که هر چند وقت یکبار داده‌های خوانده شده خود را گزارش دهد. واحدها ثانیه هستند. محدوده معتبر برای این مقدار توسط دستگاه تعیین می‌شود و با استفاده از مکانیسم حداقل/حداکثر فیزیکی توصیف می‌شود. حداقل نرخ گزارش 50 هرتز باید پشتیبانی شود و حداکثر نرخ گزارش توصیه شده 100 هرتز است. بنابراین، حداقل فاصله گزارش باید کمتر یا مساوی 20 میلی‌ثانیه باشد و توصیه می‌شود بیشتر یا مساوی 10 میلی‌ثانیه باشد.

ملک: شرکت حمل و نقل LE ( 0xF410 ) متعلق به فروشنده

ویژگی LE Transport ( 0xF410 ) که توسط فروشنده رزرو شده است، یک ویژگی خواندن/نوشتن است که دارای معنای استاندارد تعریف شده در مشخصات HID است. میزبان از این ویژگی برای نشان دادن انتقال انتخاب شده (ACL یا ISO) استفاده می‌کند. فقط مقادیر ACL ( 0xF800 ) و ISO ( 0xF801 ) استفاده می‌شوند و هر دو باید در مجموعه منطقی گنجانده شوند.

این ویژگی قبل از حالت‌های روشن یا خاموش شدن دستگاه پیکربندی می‌شود.

فیلد داده: مقدار سفارشی ۱ ( 0x0544 )

فیلد مقدار سفارشی ۱ ( 0x0544 ) یک فیلد ورودی است که برای گزارش اطلاعات واقعی ردیابی سر استفاده می‌شود. این یک آرایه ۳ عنصری است که طبق قوانین معمول HID برای مقادیر فیزیکی، همانطور که در بخش ۶.۲.۲.۷ از مشخصات HID مشخص شده است، تفسیر می‌شود. محدوده معتبر برای هر عنصر [-π، π] رادیان است. واحدها همیشه رادیان هستند.

عناصر به صورت [rx, ry, rz] تفسیر می‌شوند، به طوری که [rx, ry, rz] یک بردار چرخش است که نشان دهنده تبدیل از چارچوب مرجع به چارچوب سر است. بزرگی باید در محدوده [0..π] باشد.

چارچوب مرجع دلخواه است، اما معمولاً ثابت است و باید راستگرد باشد. مقدار کمی انحراف قابل قبول است. محورهای هد عبارتند از:

  • X از گوش چپ به راست
  • Y از پشت سر تا بینی (از عقب به جلو)
  • Z از گردن تا بالای سر

فیلد داده: مقدار سفارشی ۲ ( 0x0545 )

فیلد مقدار سفارشی ۲ ( 0x0545 ) یک فیلد ورودی است که برای گزارش اطلاعات واقعی ردیابی سر استفاده می‌شود. این یک آرایه نقطه ثابت ۳ عنصری است که طبق قوانین معمول HID برای مقادیر فیزیکی تفسیر می‌شود. واحدها همیشه رادیان بر ثانیه هستند.

عناصر به صورت [vx, vy, vz] تفسیر می‌شوند، به طوری که [vx, vy, vz] یک بردار چرخش است که نشان دهنده سرعت زاویه‌ای قاب سر (نسبت به خودش) است.

فیلد داده: مقدار سفارشی ۳ ( 0x0546 )

فیلد مقدار سفارشی ۳ ( 0x0546 ) یک فیلد ورودی است که برای ردیابی ناپیوستگی‌ها در فریم مرجع استفاده می‌شود. این یک عدد صحیح اسکالر با اندازه ۸ بیت است. هر بار که فریم مرجع تغییر می‌کند، باید توسط دستگاه (با wraparound) افزایش یابد، به عنوان مثال، اگر یک الگوریتم فیلتر جهت‌گیری که برای تعیین جهت‌گیری استفاده می‌شود، حالت خود را بازنشانی کند. این مقدار طبق قوانین معمول HID برای مقادیر فیزیکی تفسیر می‌شود. با این حال، مقدار فیزیکی و واحدها مهم نیستند. تنها اطلاعات مربوط به میزبان، یک مقدار تغییر یافته است. برای جلوگیری از مشکلات عددی مربوط به از دست دادن دقت هنگام تبدیل از واحدهای منطقی به فیزیکی، توصیه می‌شود مقادیر مربوط به حداقل فیزیکی، حداکثر فیزیکی و توان واحد را برای این فیلد روی صفر تنظیم کنید.

ساختار گزارش

گروه‌بندی ویژگی‌ها در گزارش‌ها (با اختصاص شناسه‌های گزارش) انعطاف‌پذیر است. برای کارایی بیشتر، توصیه می‌کنیم ویژگی‌های فقط خواندنی را از ویژگی‌های خواندنی/نوشتنی جدا کنید.

برای فیلدهای داده، فیلدهای مقدار سفارشی ۱، ۲ و ۳ باید در یک گزارش باشند و فقط در یک گزارش برای یک دستگاه مشخص (مجموعه برنامه) باشند.

ارسال گزارش‌های ورودی

دستگاه باید به صورت دوره‌ای و غیرهمزمان (از طریق پیام‌های HID INPUT) در صورت برآورده شدن همه این شرایط، گزارش‌های ورودی ارسال کند:

  • ویژگی Power State روی Full Power تنظیم شده است.
  • ویژگی Reporting State روی All Events تنظیم شده است.
  • ویژگی Reporting Interval غیر صفر است.

ویژگی Reporting Interval تعیین می‌کند که گزارش‌ها هر چند وقت یکبار ارسال شوند. وقتی هر یک از شرایط بالا برقرار نباشد، دستگاه نباید هیچ گزارشی ارسال کند.

سازگاری رو به جلو و رو به عقب

پروتکل HID ردیاب سر، از یک طرح نسخه‌بندی استفاده می‌کند که امکان به‌روزرسانی‌ها را فراهم می‌کند، ضمن اینکه امکان همکاری بین میزبان و دستگاهی را که از نسخه‌های مختلف پروتکل استفاده می‌کنند، فراهم می‌کند. نسخه‌های این پروتکل با دو عدد، اصلی و فرعی، مشخص می‌شوند که همانطور که در بخش‌های بعدی توضیح داده شده است، معنای متمایزی دارند.

نسخه‌های پشتیبانی‌شده توسط یک دستگاه را می‌توان با بررسی ویژگی Sensor Description ( 0x0308 ) آن تعیین کرد.

سازگاری نسخه‌های جزئی

تغییرات در نسخه فرعی با نسخه‌های فرعی قبلی که بر اساس همان نسخه اصلی هستند، سازگار به عقب هستند. در به‌روزرسانی‌های نسخه فرعی، میزبان فیلدهای داده و ویژگی‌های اضافی را نادیده می‌گیرد. به عنوان مثال، دستگاهی که از نسخه پروتکل ۱.۶ استفاده می‌کند با میزبانی که از نسخه پروتکل ۱.x، از جمله نسخه ۱.۵، پشتیبانی می‌کند، سازگار است.

سازگاری نسخه اصلی

تغییرات غیر سازگار با نسخه‌های قبلی برای تغییرات در نسخه‌های اصلی مجاز است. برای پشتیبانی از چندین نسخه اصلی برای قابلیت همکاری با میزبان‌های قدیمی و جدید، دستگاه‌ها می‌توانند چندین مجموعه برنامه را در توصیف‌گرهای گزارش خود مشخص کنند. به عنوان مثال:

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

در این حالت، میزبان می‌تواند تمام مجموعه‌های مختلف برنامه‌های اعلام‌شده توسط دستگاه را بشمارد و ویژگی Sensor Description آنها را بررسی کند تا نسخه‌های پروتکلی را که هر کدام پیاده‌سازی می‌کنند تعیین کند، سپس آخرین نسخه پروتکلی را که میزبان پشتیبانی می‌کند، انتخاب کند. پس از انتخاب، میزبان با پروتکل واحدی که برای کل طول عمر اتصال دستگاه انتخاب شده است، کار می‌کند.

Appendix: Example of a HID descriptor

مثال زیر یک توصیفگر HID معتبر معمولی را نشان می‌دهد. این مثال از ماکروهای رایج C که در بخش «کاربردهای حسگر HID » (بخش ۴.۱) ارائه شده است، استفاده می‌کند.

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

پیوست ۲: نمونه‌ای از توصیفگر HID نسخه ۲.۰

مثال زیر یک توصیفگر HID نسخه ۲.۰ را برای دستگاهی که فقط از انتقال Bluetooth LE ACL پشتیبانی می‌کند، نشان می‌دهد.

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