פרוטוקול HID Head Tracker

פרוטוקול ה-head tracker human interface device (HID), הזמין למכשירים המריצים אנדרואיד 13 ומעלה, מאפשר לחבר מכשיר מעקב ראש למכשיר אנדרואיד באמצעות USB או בלוטות' ולהיחשף למסגרת האנדרואיד ולאפליקציות דרך החיישנים מִסגֶרֶת. פרוטוקול זה משמש לשליטה באפקט וירטואליזר אודיו (שמע 3D). דף זה משתמש במונחים מכשיר ומארח במובן ה-Bluetooth שלהם, כאשר מכשיר פירושו התקן מעקב ראש ומארח פירושו מארח אנדרואיד.

יצרני התקנים חייבים להגדיר את מכשירי האנדרואיד שלהם כדי לאפשר תמיכה בפרוטוקול HID של head tracker. למידע מפורט יותר על תצורה, ראה README של חיישנים דינמיים .

דף זה מניח היכרות עם המשאבים הבאים:

מבנה ברמה העליונה

מסגרת האנדרואיד מזהה את מכשיר ה-head tracker כמכשיר HID.

לדוגמא מלאה של מתאר HID חוקי, ראה נספח 1: דוגמה של מתאר HID .

ברמה העליונה, מכשיר ה-head tracker הוא אוסף אפליקציות עם דף Sensors ( 0x20 ) והאחר Other: Custom ( 0xE1 ). בתוך אוסף זה ישנם מספר שדות נתונים ( קלט ) ומאפיינים ( תכונות ).

מאפיינים ושדות נתונים

סעיף זה מתאר את המאפיינים ושדות הנתונים באוסף יישומים של התקן מעקב ראש.

מאפיין: תיאור חיישן ( 0x0308 )

המאפיין תיאור חיישן ( 0x0308 ) הוא מאפיין מחרוזת ASCII לקריאה בלבד (8 סיביות) שחייב להכיל את הערך הבא:

#AndroidHeadTracker#1.0

לא צפוי terminator null, כלומר הגודל הכולל של מאפיין זה הוא 23 תווים של 8 סיביות.

מאפיין זה משמש כמאפיין כדי למנוע התנגשויות עם חיישנים מותאמים אישית אחרים.

מאפיין: מזהה ייחודי מתמשך ( 0x0302 )

המאפיין Persistent Unique ID ( 0x0302 ) הוא מערך לקריאה בלבד של 16 אלמנטים, 8 סיביות כל אחד (סה"כ 128 סיביות). לא צפוי terminator null. נכס זה הוא אופציונלי.

מאפיין זה מאפשר להתקני מעקב ראשים המשולבים בהתקני שמע להתייחס להתקן השמע שאליו הם מחוברים. התוכניות הבאות נתמכות.

גשש ראש עצמאי

אם המאפיין Persistent Unique ID ( 0x0302 ) אינו קיים או מוגדר לאפסים, פירוש הדבר שהתקן ה-head tracker אינו מחובר לצמיתות להתקן שמע וניתן להשתמש בו בנפרד, לדוגמה, על ידי מתן אפשרות למשתמש באופן ידני. שייך את מכשיר הגשש הראש להתקן שמע נפרד.

הפניה באמצעות כתובת 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 ב ט Bluetooth MAC

בסכימה זו, 8 האוקטטים הראשונים חייבים להיות 0 , אוקטטים 8 ו-9 חייבים להכיל את ערכי ה-ASCII B ו- T בהתאמה, ו-6 האוקטטים הבאים מתפרשים ככתובת Bluetooth MAC, בהנחה שמכשיר המעקב הראשי חל על כל מכשיר שמע שיש לו כתובת MAC זו.

הפניה באמצעות UUID

בכל פעם שהביט המשמעותי ביותר (MSB) של אוקטט 8 מוגדר ( ≥0x80 ), השדה מתפרש כ-UUID, כמפורט ב- RFC-4122 . מכשיר האודיו המתאים מספק את אותו UUID, אשר רשום במסגרת אנדרואיד, באמצעות מנגנון לא מוגדר, הספציפי לסוג התחבורה בו נעשה שימוש.

נכס: מצב דיווח ( 0x0316 )

המאפיין Reporting State ( 0x0316 ) הוא מאפיין קריאה/כתיבה בעל הסמנטיקה הסטנדרטית כפי שהוגדרה במפרט HID. המארח משתמש במאפיין זה כדי לציין למכשיר אילו אירועים לדווח. נעשה שימוש רק בערכים No Events ( 0x0840 ) ו- All Events ( 0x0841 ).

הערך ההתחלתי של שדה זה חייב להיות ללא אירועים ולעולם אין לשנות אותו על ידי המכשיר, רק על ידי המארח.

מאפיין: Power State ( 0x0319 )

המאפיין Power State ( 0x0319 ) הוא מאפיין קריאה/כתיבה בעל הסמנטיקה הסטנדרטית כפי שהוגדרה במפרט HID. המארח משתמש במאפיין זה כדי לציין למכשיר באיזה מצב הפעלה הוא חייב להיות. נעשה שימוש רק בערכים Full Power ( 0x0851 ) ו- Power Off ( 0x0855 ).

הערך ההתחלתי של שדה זה נקבע על ידי המכשיר ולעולם אין לשנותו על ידי המכשיר, רק על ידי המארח.

מאפיין: מרווח דיווח ( 0x030E )

המאפיין Report Interval ( 0x030E ) הוא מאפיין קריאה/כתיבה בעל הסמנטיקה הסטנדרטית כפי שהוגדרה במפרט HID. המארח משתמש במאפיין זה כדי לציין למכשיר באיזו תדירות לדווח על קריאות הנתונים שלו. יחידות הן שניות. הטווח התקף עבור ערך זה נקבע על ידי המכשיר ומתואר באמצעות מנגנון המינימום/מקס הפיזי. יש לתמוך בקצב דיווח של 50 הרץ לפחות, וקצב הדיווח המרבי המומלץ הוא 100 הרץ. לכן, מרווח הדיווח המינימלי חייב להיות קטן או שווה ל-20 אלפיות השנייה, ומומלץ להיות גדול או שווה ל-10 שניות.

שדה נתונים: ערך מותאם אישית 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.
  • המאפיין מצב דיווח מוגדר לכל האירועים.
  • מאפיין מרווח הדיווח אינו אפס.

המאפיין Reporting Interval קובע באיזו תדירות לשלוח את הדוחות. כאשר אחד מהתנאים לעיל אינו מתקיים, אסור למכשיר לשלוח דיווחים כלשהם.

תאימות קדימה ואחורה

פרוטוקול ה-head tracker 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,
};