হেড ট্র্যাকার HID প্রোটোকল

হেড ট্র্যাকার হিউম্যান ইন্টারফেস ডিভাইস (এইচআইডি) প্রোটোকল, অ্যান্ড্রয়েড 13 এবং উচ্চতর সংস্করণে চালিত ডিভাইসগুলির জন্য উপলব্ধ, একটি হেড-ট্র্যাকিং ডিভাইসকে ইউএসবি বা ব্লুটুথের মাধ্যমে একটি অ্যান্ড্রয়েড ডিভাইসের সাথে সংযুক্ত হতে এবং সেন্সরগুলির মাধ্যমে অ্যান্ড্রয়েড ফ্রেমওয়ার্ক এবং অ্যাপগুলির সাথে উন্মুক্ত করার অনুমতি দেয়। কাঠামো এই প্রোটোকলটি একটি অডিও ভার্চুয়ালাইজার প্রভাব (3D অডিও) নিয়ন্ত্রণের জন্য ব্যবহৃত হয়। এই পৃষ্ঠাটি তাদের ব্লুটুথ অর্থে ডিভাইস এবং হোস্ট শব্দগুলি ব্যবহার করে, যেখানে ডিভাইস মানে হেড-ট্র্যাকিং ডিভাইস এবং হোস্ট মানে Android হোস্ট।

হেড ট্র্যাকার HID প্রোটোকলের জন্য সমর্থন সক্ষম করতে ডিভাইস নির্মাতাদের অবশ্যই তাদের Android ডিভাইসগুলি কনফিগার করতে হবে। কনফিগারেশন সম্পর্কে আরও বিস্তারিত তথ্যের জন্য, ডায়নামিক সেন্সর README দেখুন।

এই পৃষ্ঠাটি নিম্নলিখিত সংস্থানগুলির সাথে পরিচিতি অনুমান করে:

শীর্ষ স্তরের কাঠামো

অ্যান্ড্রয়েড ফ্রেমওয়ার্ক হেড ট্র্যাকার ডিভাইসটিকে একটি HID ডিভাইস হিসাবে চিহ্নিত করে।

একটি বৈধ HID বর্ণনাকারীর সম্পূর্ণ উদাহরণের জন্য, পরিশিষ্ট 1 দেখুন: HID বর্ণনাকারীর উদাহরণ

শীর্ষ স্তরে, হেড ট্র্যাকার ডিভাইসটি Sensors পৃষ্ঠা ( 0x20 ) এবং Other: Custom ব্যবহার ( 0xE1 ) সহ একটি অ্যাপ সংগ্রহ। এই সংগ্রহের অভ্যন্তরে বেশ কয়েকটি ডেটা ক্ষেত্র ( ইনপুট ) এবং বৈশিষ্ট্য ( বৈশিষ্ট্য ) রয়েছে।

বৈশিষ্ট্য এবং তথ্য ক্ষেত্র

এই বিভাগটি হেড ট্র্যাকার ডিভাইসের একটি অ্যাপ্লিকেশন সংগ্রহের বৈশিষ্ট্য এবং ডেটা ক্ষেত্রগুলি বর্ণনা করে।

সম্পত্তি: সেন্সর বিবরণ ( 0x0308 )

সেন্সর বিবরণ ( 0x0308 ) বৈশিষ্ট্য হল একটি পঠনযোগ্য ASCII (8-বিট) স্ট্রিং বৈশিষ্ট্য যাতে নিম্নলিখিত মান থাকতে হবে:

#AndroidHeadTracker#1.0

কোনো নাল-টার্মিনেটর প্রত্যাশিত নয়, অর্থাৎ এই সম্পত্তির মোট আকার হল 23 8-বিট অক্ষর।

অন্যান্য কাস্টম সেন্সরগুলির সাথে সংঘর্ষ এড়াতে এই সম্পত্তিটি বৈষম্যকারী হিসাবে কাজ করে।

সম্পত্তি: স্থায়ী অনন্য আইডি ( 0x0302 )

Persistent Unique ID ( 0x0302 ) প্রপার্টি হল 16 টি উপাদানের একটি পঠনযোগ্য অ্যারে, প্রতিটি 8 বিট (মোট 128 বিট)। কোন নাল টার্মিনেটর প্রত্যাশিত. এই সম্পত্তি ঐচ্ছিক.

এই বৈশিষ্ট্যটি হেড-ট্র্যাকিং ডিভাইসগুলিকে অনুমতি দেয় যেগুলি অডিও ডিভাইসে একত্রিত করা অডিও ডিভাইসটিকে রেফারেন্স করার জন্য যা তারা সংযুক্ত রয়েছে। নিম্নলিখিত স্কিম সমর্থিত হয়.

স্বতন্ত্র হেড ট্র্যাকার

যদি Persistent Unique ID ( 0x0302 ) প্রপার্টিটি বিদ্যমান না থাকে বা সমস্ত জিরোতে সেট করা থাকে, তাহলে এর মানে হল যে হেড ট্র্যাকার ডিভাইসটি স্থায়ীভাবে একটি অডিও ডিভাইসের সাথে সংযুক্ত নয় এবং আলাদাভাবে ব্যবহার করা যেতে পারে, উদাহরণস্বরূপ, ব্যবহারকারীকে ম্যানুয়ালি অনুমতি দিয়ে হেড ট্র্যাকার ডিভাইসটিকে একটি পৃথক অডিও ডিভাইসের সাথে সংযুক্ত করুন।

ব্লুটুথ MAC ঠিকানা ব্যবহার করে রেফারেন্স

অক্টেট 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
মান 0 0 0 0 0 0 0 0 টি ব্লুটুথ ম্যাক

এই স্কিমে, প্রথম 8টি অক্টেট অবশ্যই 0 হতে হবে, অক্টেট 8 এবং 9 তে যথাক্রমে ASCII মান B এবং T থাকতে হবে এবং নিম্নলিখিত 6টি অক্টেটগুলিকে একটি ব্লুটুথ MAC ঠিকানা হিসাবে ব্যাখ্যা করা হয়েছে, ধরে নেওয়া হচ্ছে যে হেড ট্র্যাকার ডিভাইসটি যে কোনও অডিও ডিভাইসে প্রযোজ্য। এই MAC ঠিকানা।

UUID ব্যবহার করে রেফারেন্স

যখনই অক্টেট 8-এর সবচেয়ে উল্লেখযোগ্য বিট (MSB) সেট করা হয় ( ≥0x80 ), ক্ষেত্রটিকে UUID হিসাবে ব্যাখ্যা করা হয়, যেমনটি RFC-4122 এ উল্লেখ করা হয়েছে। সংশ্লিষ্ট অডিও ডিভাইস একই UUID প্রদান করে, যা অ্যান্ড্রয়েড ফ্রেমওয়ার্কে নিবন্ধিত, একটি অনির্দিষ্ট প্রক্রিয়ার মাধ্যমে যা ব্যবহৃত পরিবহনের ধরণের জন্য নির্দিষ্ট।

সম্পত্তি: রিপোর্টিং স্টেট ( 0x0316 )

রিপোর্টিং স্টেট ( 0x0316 ) প্রপার্টি হল একটি রিড/রাইট প্রপার্টি যা HID স্পেসিফিকেশনে সংজ্ঞায়িত স্ট্যান্ডার্ড সিমেন্টিকস আছে। হোস্ট এই বৈশিষ্ট্যটি ব্যবহার করে ডিভাইসে কোন ইভেন্টের রিপোর্ট করতে হবে তা নির্দেশ করতে। শুধুমাত্র কোন ইভেন্ট ( 0x0840 ) এবং সমস্ত ইভেন্ট ( 0x0841 ) মান ব্যবহার করা হয়।

এই ক্ষেত্রের জন্য প্রাথমিক মান হতে হবে কোনো ইভেন্ট নয় এবং এটি কখনোই ডিভাইস দ্বারা পরিবর্তন করা উচিত নয়, শুধুমাত্র হোস্ট দ্বারা।

সম্পত্তি: পাওয়ার স্টেট ( 0x0319 )

পাওয়ার স্টেট ( 0x0319 ) প্রপার্টি হল একটি রিড/রাইট প্রপার্টি যা HID স্পেসিফিকেশনে সংজ্ঞায়িত স্ট্যান্ডার্ড সিমেন্টিকস রয়েছে। হোস্ট এই বৈশিষ্ট্যটি ব্যবহার করে ডিভাইসটিকে নির্দেশ করার জন্য যে কোন পাওয়ার স্টেটে এটি থাকতে হবে৷ শুধুমাত্র ফুল পাওয়ার ( 0x0851 ) এবং পাওয়ার অফ ( 0x0855 ) মানগুলি ব্যবহার করা হয়৷

এই ক্ষেত্রের জন্য প্রাথমিক মান ডিভাইস দ্বারা নির্ধারিত হয় এবং ডিভাইস দ্বারা পরিবর্তন করা উচিত নয়, শুধুমাত্র হোস্ট দ্বারা।

সম্পত্তি: রিপোর্ট ব্যবধান ( 0x030E )

রিপোর্ট ইন্টারভাল ( 0x030E ) প্রপার্টি হল একটি রিড/রাইট প্রপার্টি যা HID স্পেসিফিকেশনে সংজ্ঞায়িত স্ট্যান্ডার্ড সিমেন্টিকস আছে। হোস্ট এই প্রপার্টি ব্যবহার করে ডিভাইসটিকে নির্দেশ করতে কত ঘন ঘন তার ডেটা রিডিং রিপোর্ট করতে হবে। একক সেকেন্ড। এই মানের জন্য বৈধ পরিসর ডিভাইস দ্বারা নির্ধারিত হয় এবং শারীরিক ন্যূনতম/সর্বোচ্চ প্রক্রিয়া ব্যবহার করে বর্ণনা করা হয়। কমপক্ষে 50 Hz রিপোর্টিং রেট সমর্থিত হতে হবে এবং প্রস্তাবিত সর্বোচ্চ রিপোর্টিং রেট হল 100 Hz। তাই, রিপোর্টের ন্যূনতম ব্যবধান 20 ms-এর কম বা সমান হতে হবে এবং 10 ms-এর বেশি বা সমান হওয়ার পরামর্শ দেওয়া হয়।

ডেটা ক্ষেত্র: কাস্টম মান 1 ( 0x0544 )

কাস্টম মান 1 ( 0x0544 ) ক্ষেত্র হল একটি ইনপুট ক্ষেত্র যা প্রকৃত হেড-ট্র্যাকিং তথ্য রিপোর্ট করার জন্য ব্যবহৃত হয়। এটি একটি 3-এলিমেন্ট অ্যারে, যা HID স্পেসিফিকেশনের ধারা 6.2.2.7-এ উল্লেখিত শারীরিক মানগুলির জন্য সাধারণ HID নিয়ম অনুসারে ব্যাখ্যা করা হয়েছে। প্রতিটি উপাদানের জন্য বৈধ পরিসর হল [-π, π] rad। একক সবসময় রেডিয়ান হয়।

উপাদানগুলিকে এভাবে ব্যাখ্যা করা হয়: [rx, ry, rz] , যেমন [rx, ry, rz] হল একটি ঘূর্ণন ভেক্টর , যা রেফারেন্স ফ্রেম থেকে হেড ফ্রেমে রূপান্তরকে প্রতিনিধিত্ব করে। মাত্রা অবশ্যই [0..π] পরিসরে হতে হবে।

রেফারেন্স ফ্রেমটি নির্বিচারে, তবে এটি সাধারণত স্থির এবং ডান হাতে থাকা আবশ্যক। প্রবাহ একটি ছোট পরিমাণ গ্রহণযোগ্য. মাথার অক্ষগুলি হল:

  • X বাম কান থেকে ডানে
  • Y মাথার পেছন থেকে নাক পর্যন্ত (পিছনে সামনে)
  • ঘাড় থেকে মাথার উপরের দিকে জেড

ডেটা ক্ষেত্র: কাস্টম মান 2 ( 0x0545 )

কাস্টম মান 2 ( 0x0545 ) ক্ষেত্র হল একটি ইনপুট ক্ষেত্র যা প্রকৃত হেড-ট্র্যাকিং তথ্য রিপোর্ট করার জন্য ব্যবহৃত হয়। এটি একটি 3-উপাদানের ফিক্সড-পয়েন্ট অ্যারে, যা শারীরিক মানগুলির জন্য সাধারণ HID নিয়ম অনুসারে ব্যাখ্যা করা হয়। একক সর্বদা রেডিয়ান/সেকেন্ড হয়।

উপাদানগুলিকে এভাবে ব্যাখ্যা করা হয়: [vx, vy, vz] , যেমন [vx, vy, vz] হল একটি ঘূর্ণন ভেক্টর , যা মাথার ফ্রেমের কৌণিক বেগ (নিজের সাথে আপেক্ষিক) প্রতিনিধিত্ব করে।

ডেটা ক্ষেত্র: কাস্টম মান 3 ( 0x0546 )

কাস্টম মান 3 ( 0x0546 ) ক্ষেত্র হল একটি ইনপুট ক্ষেত্র যা রেফারেন্স ফ্রেমে বিরতি ট্র্যাক করার জন্য ব্যবহৃত হয়। এটি একটি স্কেলার পূর্ণসংখ্যা 8 বিট আকারের। প্রতিবার রেফারেন্সের ফ্রেম পরিবর্তিত হলে এটি অবশ্যই ডিভাইসের দ্বারা বৃদ্ধি করা উচিত (র্যাপরাউন্ড সহ), উদাহরণস্বরূপ, যদি অভিযোজন নির্ধারণের জন্য ব্যবহৃত একটি ওরিয়েন্টেশন ফিল্টার অ্যালগরিদম তার স্টেট রিসেট করে থাকে। এই মানটি শারীরিক মানগুলির জন্য সাধারণ HID নিয়ম অনুসারে ব্যাখ্যা করা হয়। যাইহোক, শারীরিক মান এবং ইউনিট কোন ব্যাপার না. হোস্টের সাথে প্রাসঙ্গিক একমাত্র তথ্য হল পরিবর্তিত মান। লজিক্যাল থেকে ভৌত ইউনিটে রূপান্তর করার সময় নির্ভুলতা হারানোর সাথে সম্পর্কিত সংখ্যাগত সমস্যাগুলি এড়াতে, এই ক্ষেত্রের জন্য ফিজিক্যাল মিন, ফিজিক্যাল ম্যাক্স এবং ইউনিট এক্সপোনেন্টের মান শূন্যে সেট করার পরামর্শ দেওয়া হয়।

রিপোর্ট গঠন

প্রতিবেদনে বৈশিষ্ট্যের গ্রুপিং (রিপোর্ট আইডির নিয়োগ দ্বারা) নমনীয়। দক্ষতার জন্য, আমরা পঠন/লেখা বৈশিষ্ট্যগুলি থেকে শুধুমাত্র পঠনযোগ্য বৈশিষ্ট্যগুলিকে আলাদা করার পরামর্শ দিই।

ডেটা ক্ষেত্রগুলির জন্য, কাস্টম মান 1, 2, এবং 3 ক্ষেত্রগুলি অবশ্যই একই রিপোর্টে থাকতে হবে এবং একটি প্রদত্ত ডিভাইসের (অ্যাপ সংগ্রহ) জন্য শুধুমাত্র একটি প্রতিবেদনে থাকতে হবে৷

ইনপুট রিপোর্ট পাঠান

এই সমস্ত শর্ত পূরণ হলে ডিভাইসটিকে পর্যায়ক্রমে এবং অ্যাসিঙ্ক্রোনাসভাবে (HID INPUT বার্তাগুলির মাধ্যমে) ইনপুট রিপোর্ট পাঠাতে হবে:

  • পাওয়ার স্টেট সম্পত্তি সম্পূর্ণ পাওয়ার সেট করা আছে।
  • রিপোর্টিং স্টেট সম্পত্তি সমস্ত ইভেন্টে সেট করা আছে।
  • রিপোর্টিং ব্যবধান বৈশিষ্ট্য অ-শূন্য.

রিপোর্টিং ইন্টারভাল প্রপার্টি নির্ধারণ করে কত ঘন ঘন রিপোর্ট পাঠাতে হবে। যখন উপরের কোন শর্ত পূরণ করা হয় না, ডিভাইসটি অবশ্যই কোন রিপোর্ট পাঠাবে না।

এগিয়ে এবং পিছনে সামঞ্জস্য

হেড ট্র্যাকার এইচআইডি প্রোটোকল একটি ভার্সনিং স্কিম ব্যবহার করে যা আপডেটের জন্য অনুমতি দেয়, যখন একটি হোস্ট এবং প্রোটোকলের বিভিন্ন সংস্করণ ব্যবহার করে এমন একটি ডিভাইসের মধ্যে ইন্টারঅপারেবিলিটির অনুমতি দেয়। প্রোটোকলের সংস্করণ দুটি সংখ্যা দ্বারা চিহ্নিত করা হয়, বড় এবং ছোট, যেগুলির স্বতন্ত্র শব্দার্থ আছে যা নিম্নলিখিত বিভাগে বর্ণিত হয়েছে।

একটি ডিভাইস দ্বারা সমর্থিত সংস্করণগুলি তার সেন্সর বিবরণ ( 0x0308 ) বৈশিষ্ট্য পরীক্ষা করে নির্ধারণ করা যেতে পারে৷

ছোট সংস্করণ সামঞ্জস্য

ছোট সংস্করণের পরিবর্তনগুলি একই প্রধান সংস্করণের উপর ভিত্তি করে আগের ছোট সংস্করণগুলির সাথে পশ্চাদমুখী সামঞ্জস্যপূর্ণ। ছোট সংস্করণের আপডেটে, হোস্ট অতিরিক্ত ডেটা ক্ষেত্র এবং বৈশিষ্ট্য উপেক্ষা করে। উদাহরণস্বরূপ, প্রোটোকল সংস্করণ 1.6 ব্যবহার করা একটি ডিভাইস একটি হোস্টের সাথে সামঞ্জস্যপূর্ণ যা সংস্করণ 1.5 সহ প্রোটোকল সংস্করণ 1.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,
};

এই ক্ষেত্রে, হোস্ট ডিভাইস দ্বারা বিজ্ঞাপিত সমস্ত বিভিন্ন অ্যাপ সংগ্রহের গণনা করতে পারে, তাদের সেন্সর বিবরণ সম্পত্তি পরীক্ষা করে প্রোটোকল সংস্করণগুলি নির্ধারণ করতে যা তারা প্রতিটি প্রয়োগ করে, তারপরে হোস্ট সমর্থন করে এমন সর্বশেষ প্রোটোকল সংস্করণটি বেছে নিতে পারে। যখন নির্বাচিত হয়, হোস্ট ডিভাইস সংযোগের আজীবনের জন্য নির্বাচিত একক প্রোটোকলের সাথে কাজ করে।

পরিশিষ্ট: একটি HID বর্ণনাকারীর উদাহরণ

নিম্নলিখিত উদাহরণটি একটি সাধারণ বৈধ HID বর্ণনাকারীকে চিত্রিত করে। এটি HID সেন্সর ব্যবহারে (বিভাগ 4.1) দেওয়া সাধারণত ব্যবহৃত C ম্যাক্রো ব্যবহার করে।

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