หัวติดตามโปรโตคอล HID

โปรโตคอลอุปกรณ์เชื่อมต่อมนุษย์ (HID) ตัวติดตามศีรษะใช้งานได้กับอุปกรณ์ที่ใช้ Android 13 ขึ้นไป ช่วยให้อุปกรณ์ติดตามศีรษะเชื่อมต่อกับอุปกรณ์ Android ผ่าน USB หรือบลูทูธ และสัมผัสกับเฟรมเวิร์ก Android และแอปผ่าน เซ็นเซอร์ ได้ กรอบ. โปรโตคอลนี้ใช้สำหรับควบคุมเอฟเฟกต์เสียงเสมือนจริง (เสียง 3 มิติ) หน้านี้ใช้คำว่า อุปกรณ์ และ โฮสต์ ในแง่บลูทูธ โดยที่ อุปกรณ์ หมายถึงอุปกรณ์ติดตามศีรษะ และ โฮสต์ หมายถึงโฮสต์ Android

ผู้ผลิตอุปกรณ์จะต้องกำหนดค่าอุปกรณ์ Android ของตนเพื่อให้รองรับโปรโตคอล HID ตัวติดตามส่วนหัว สำหรับข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับการกำหนดค่า โปรดดูที่ Dynamic Sensors README

หน้านี้ถือว่ามีความคุ้นเคยกับแหล่งข้อมูลต่อไปนี้:

โครงสร้างระดับบนสุด

กรอบงาน Android ระบุอุปกรณ์ติดตามส่วนหัวเป็นอุปกรณ์ HID

สำหรับตัวอย่างที่สมบูรณ์ของตัวอธิบาย HID ที่ถูกต้อง โปรดดู ภาคผนวก 1: ตัวอย่างของตัวอธิบาย HID

ที่ระดับบนสุด อุปกรณ์ติดตามส่วนหัวคือคอลเลกชันแอปที่มีหน้า Sensors ( 0x20 ) และ Other: Custom ( 0xE1 ) ภายในคอลเลกชันนี้ประกอบด้วยช่องข้อมูลหลายช่อง ( อินพุต ) และคุณสมบัติ ( คุณสมบัติ )

คุณสมบัติและฟิลด์ข้อมูล

ส่วนนี้อธิบายคุณสมบัติและฟิลด์ข้อมูลในคอลเลกชันแอปพลิเคชันของอุปกรณ์ติดตามส่วนหัว

คุณสมบัติ: คำอธิบายเซนเซอร์ ( 0x0308 )

คุณสมบัติ Sensor Description ( 0x0308 ) เป็นคุณสมบัติสตริง ASCII (8 บิต) แบบอ่านอย่างเดียวซึ่งต้องมีค่าต่อไปนี้:

#AndroidHeadTracker#1.0

คาดว่าจะไม่มีตัวสิ้นสุดค่า null ซึ่งหมายความว่าขนาดรวมของคุณสมบัตินี้คือ 23 อักขระ 8 บิต

คุณสมบัตินี้ทำหน้าที่เป็นตัวแบ่งแยกเพื่อหลีกเลี่ยงการชนกับเซ็นเซอร์แบบกำหนดเองอื่นๆ

คุณสมบัติ: ID เฉพาะถาวร ( 0x0302 )

คุณสมบัติ Persistent Unique ID ( 0x0302 ) เป็นอาร์เรย์แบบอ่านอย่างเดียวที่มี 16 องค์ประกอบ แต่ละองค์ประกอบ 8 บิต (รวม 128 บิต) คาดว่าจะไม่มีตัวยุติที่เป็นค่าว่าง คุณสมบัตินี้เป็นทางเลือก

คุณสมบัตินี้อนุญาตให้อุปกรณ์ติดตามศีรษะที่รวมอยู่ในอุปกรณ์เสียงสามารถอ้างอิงอุปกรณ์เสียงที่เชื่อมต่ออยู่ รองรับโครงร่างต่อไปนี้

เครื่องติดตามศีรษะแบบสแตนด์อโลน

หากไม่มีคุณสมบัติ Persistent Unique ID ( 0x0302 ) หรือตั้งค่าเป็นศูนย์ทั้งหมด หมายความว่าอุปกรณ์ติดตามส่วนหัวไม่ได้เชื่อมต่อกับอุปกรณ์เสียงอย่างถาวร และสามารถใช้แยกต่างหากได้ เช่น โดยให้ผู้ใช้ด้วยตนเอง เชื่อมโยงอุปกรณ์ติดตามศีรษะกับอุปกรณ์เสียงแยกต่างหาก

อ้างอิงโดยใช้ที่อยู่ MAC ของ Bluetooth

ออคเต็ต 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

เมื่อใดก็ตามที่ตั้งค่าบิตที่สำคัญที่สุด (MSB) ของ octet 8 ( ≥0x80 ) ฟิลด์จะถูกตีความว่าเป็น UUID ตามที่ระบุไว้ใน RFC-4122 อุปกรณ์เสียงที่เกี่ยวข้องจะมี UUID เดียวกันซึ่งลงทะเบียนบนเฟรมเวิร์ก Android ผ่านกลไกที่ไม่ระบุรายละเอียดซึ่งเฉพาะเจาะจงกับประเภทของการขนส่งที่ใช้

คุณสมบัติ: สถานะการรายงาน ( 0x0316 )

คุณสมบัติ Reporting State ( 0x0316 ) เป็นคุณสมบัติการอ่าน/เขียนที่มีความหมายมาตรฐานตามที่กำหนดไว้ในข้อกำหนด HID โฮสต์ใช้คุณสมบัตินี้เพื่อระบุให้อุปกรณ์ทราบว่าเหตุการณ์ใดที่จะรายงาน ใช้เฉพาะค่า No Events ( 0x0840 ) และ All Events ( 0x0841 ) เท่านั้น

ค่าเริ่มต้นสำหรับฟิลด์นี้จะต้องเป็น No Events และอุปกรณ์จะต้องไม่ได้รับการแก้ไข โดยโฮสต์เท่านั้น

คุณสมบัติ: สถานะพลังงาน ( 0x0319 )

คุณสมบัติ Power State ( 0x0319 ) เป็นคุณสมบัติการอ่าน/เขียนที่มีความหมายมาตรฐานตามที่กำหนดไว้ในข้อกำหนด HID โฮสต์ใช้คุณสมบัตินี้เพื่อระบุอุปกรณ์ว่าจะต้องอยู่ในสถานะพลังงานใด โดยจะใช้เฉพาะค่า Full Power ( 0x0851 ) และ Power Off ( 0x0855 ) เท่านั้น

ค่าเริ่มต้นสำหรับฟิลด์นี้จะถูกกำหนดโดยอุปกรณ์และจะต้องไม่ได้รับการแก้ไขโดยอุปกรณ์ มีเพียงโฮสต์เท่านั้น

คุณสมบัติ: ช่วงเวลารายงาน ( 0x030E )

คุณสมบัติ Report Interval ( 0x030E ) เป็นคุณสมบัติการอ่าน/เขียนที่มีความหมายมาตรฐานตามที่กำหนดไว้ในข้อกำหนด HID โฮสต์ใช้คุณสมบัตินี้เพื่อระบุให้อุปกรณ์ทราบว่าจะรายงานการอ่านข้อมูลบ่อยเพียงใด หน่วยเป็นวินาที ช่วงที่ถูกต้องสำหรับค่านี้จะถูกกำหนดโดยอุปกรณ์และอธิบายโดยใช้กลไก Physical Min/Max ต้องรองรับอัตราการรายงานอย่างน้อย 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 จากด้านหลังศีรษะถึงจมูก (ด้านหลังไปด้านหน้า)
  • Z จากคอถึงด้านบนของศีรษะ

ช่องข้อมูล: ค่าที่กำหนดเอง 2 ( 0x0545 )

ช่องค่าที่กำหนดเอง 2 ( 0x0545 ) เป็นช่องป้อนข้อมูลที่ใช้สำหรับรายงานข้อมูลการติดตามส่วนหัวจริง เป็นอาร์เรย์จุดคงที่แบบ 3 องค์ประกอบ ซึ่งตีความตามกฎ HID ปกติสำหรับค่าฟิสิคัล หน่วยเป็นเรเดียน/วินาทีเสมอ

องค์ประกอบต่างๆ ถูกตีความว่าเป็น: [vx, vy, vz] โดยที่ [vx, vy, vz] เป็น เวกเตอร์การหมุน ซึ่งแสดงถึงความเร็วเชิงมุมของกรอบส่วนหัว (สัมพันธ์กับตัวมันเอง)

ช่องข้อมูล: ค่าที่กำหนดเอง 3 ( 0x0546 )

ฟิลด์ค่าที่กำหนดเอง 3 ( 0x0546 ) เป็นฟิลด์อินพุตที่ใช้สำหรับการติดตามความไม่ต่อเนื่องในหน้าต่างอ้างอิง เป็นจำนวนเต็มสเกลาร์ขนาด 8 บิต อุปกรณ์จะต้องเพิ่มขึ้น (โดยมีการพันรอบ) ทุกครั้งที่กรอบอ้างอิงมีการเปลี่ยนแปลง ตัวอย่างเช่น หากอัลกอริธึมตัวกรองการวางแนวที่ใช้สำหรับกำหนดการวางแนวมีการรีเซ็ตสถานะแล้ว ค่านี้ถูกตีความตามกฎ HID ปกติสำหรับค่าฟิสิคัล อย่างไรก็ตาม มูลค่าทางกายภาพและหน่วยไม่สำคัญ ข้อมูลเดียวที่เกี่ยวข้องกับโฮสต์คือค่าที่เปลี่ยนแปลง เพื่อหลีกเลี่ยงปัญหาตัวเลขที่เกี่ยวข้องกับการสูญเสียความแม่นยำในขณะที่แปลงจากหน่วยลอจิคัลไปเป็นหน่วยฟิสิคัล ขอแนะนำให้ตั้งค่าสำหรับค่าต่ำสุดจริง ค่าสูงสุดจริง และเลขชี้กำลังหน่วยเป็นศูนย์สำหรับฟิลด์นี้

โครงสร้างรายงาน

การจัดกลุ่มคุณสมบัติลงในรายงาน (ตามการกำหนดรหัสรายงาน) มีความยืดหยุ่น เพื่อประสิทธิภาพ เราขอแนะนำให้แยกคุณสมบัติอ่านอย่างเดียวออกจากคุณสมบัติอ่าน/เขียน

สำหรับช่องข้อมูล ช่องค่าที่กำหนดเอง 1, 2 และ 3 ต้องอยู่ในรายงานเดียวกันและอยู่ในรายงานเดียวเท่านั้นสำหรับอุปกรณ์ที่กำหนด (คอลเลกชั่นแอป)

ส่งรายงานอินพุต

อุปกรณ์จะต้องส่งรายงานอินพุตเป็นระยะและไม่พร้อมกัน (ผ่านข้อความ HID INPUT) เมื่อตรงตามเงื่อนไขทั้งหมดเหล่านี้:

  • คุณสมบัติ Power State ถูกตั้งค่าเป็น Full Power
  • คุณสมบัติสถานะการรายงานถูกตั้งค่าเป็นเหตุการณ์ทั้งหมด
  • คุณสมบัติช่วงการรายงานไม่เป็นศูนย์

คุณสมบัติช่วงเวลาการรายงานจะกำหนดความถี่ในการส่งรายงาน เมื่อไม่เป็นไปตามเงื่อนไขใดๆ ข้างต้น อุปกรณ์จะต้องไม่ส่งรายงานใดๆ

ความเข้ากันได้ไปข้างหน้าและย้อนกลับ

โปรโตคอล HID ตัวติดตามส่วนหัวใช้รูปแบบการกำหนดเวอร์ชันที่ช่วยให้สามารถอัปเดตได้ ในขณะเดียวกันก็อนุญาตให้มีการทำงานร่วมกันระหว่างโฮสต์และอุปกรณ์ที่ใช้โปรโตคอลเวอร์ชันต่างกัน เวอร์ชันสำหรับโปรโตคอลจะถูกระบุด้วยตัวเลขสองตัว หลักและรอง ซึ่งมีความหมายที่แตกต่างกันตามที่อธิบายไว้ในส่วนต่อไปนี้

เวอร์ชันที่อุปกรณ์รองรับสามารถกำหนดได้โดยการตรวจสอบคุณสมบัติคำอธิบายเซ็นเซอร์ ( 0x0308 )

ความเข้ากันได้ของเวอร์ชันรอง

การเปลี่ยนแปลงในเวอร์ชันรองจะเข้ากันได้แบบย้อนหลังกับเวอร์ชันรองก่อนหน้าซึ่งใช้เวอร์ชันหลักเดียวกัน ในการอัปเดตเวอร์ชันรอง โฮสต์จะละเว้นฟิลด์ข้อมูลเพิ่มเติมและคุณสมบัติ ตัวอย่างเช่น อุปกรณ์ที่ใช้โปรโตคอลเวอร์ชัน 1.6 เข้ากันได้กับโฮสต์ที่รองรับโปรโตคอลเวอร์ชัน 1.x รวมถึงเวอร์ชัน 1.5 ด้วย

ความเข้ากันได้ของเวอร์ชันหลัก

อนุญาตให้ทำการเปลี่ยนแปลงที่เข้ากันไม่ได้กับการเปลี่ยนแปลงเวอร์ชันหลัก เพื่อรองรับเวอร์ชันหลักหลายเวอร์ชันสำหรับการทำงานร่วมกันกับโฮสต์เก่าและใหม่ อุปกรณ์สามารถระบุคอลเลกชันแอปได้หลายรายการในตัวอธิบายรายงาน ตัวอย่างเช่น:

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 ที่ถูกต้องโดยทั่วไป โดยจะใช้มาโคร C ที่ใช้กันทั่วไป ซึ่งมีอยู่ใน การใช้งานเซ็นเซอร์ HID (ส่วนที่ 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,
};