頭部追踪器 HID 協議

頭部跟踪器人機接口設備 (HID) 協議適用於運行 Android 13 及更高版本的設備,允許頭部跟踪設備通過 USB 或藍牙連接到 Android 設備,並通過傳感器暴露給 Android 框架和應用程序框架。該協議用於控制音頻虛擬器效果(3D 音頻)。本頁面使用藍牙意義上的術語“設備”“主機” ,其中“設備”表示頭部跟踪設備,“主機”表示 Android 主機。

設備製造商必須配置其 Android 設備以支持頭部跟踪器 HID 協議。有關配置的更多詳細信息,請參閱動態傳感器自述文件

本頁假設您熟悉以下資源:

頂層結構

Android 框架將頭部跟踪器設備識別為 HID 設備。

有關有效 HID 描述符的完整示例,請參閱附錄 1:HID 描述符示例

在頂層,頭部跟踪器設備是一個應用程序集合,其中包含Sensors頁面 ( 0x20 ) 和Other: Custom用法 ( 0xE1 )。該集合中有幾個數據字段(輸入)和屬性(特徵)。

屬性和數據字段

本節介紹頭部跟踪器設備的應用程序集合中的屬性和數據字段。

屬性:傳感器描述( 0x0308

傳感器描述 ( 0x0308 ) 屬性是只讀 ASCII(8 位)字符串屬性,必須包含以下值:

#AndroidHeadTracker#1.0

不需要空終止符,這意味著該屬性的總大小為 23 個 8 位字符。

此屬性用作鑑別器,以避免與其他自定義傳感器發生衝突。

屬性:持久唯一 ID ( 0x0302 )

持久唯一 ID ( 0x0302 ) 屬性是一個包含 16 個元素的只讀數組,每個元素 8 位(總共 128 位)。預計不會出現空終止符。該屬性是可選的。

此屬性允許集成在音頻設備中的頭部跟踪設備引用它們所連接的音頻設備。支持以下方案。

獨立頭部追踪器

如果持久唯一 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時間藍牙MAC

在此方案中,前 8 個八位位組必須為0 ,第 8 個八位位組和第 9 個八位位組必須分別包含 ASCII 值BT ,接下來的6 個八位位組被解釋為藍牙MAC 地址,假設頭部跟踪器設備適用於具有以下功能的任何音頻設備:這個MAC地址。

使用 UUID 的參考

每當設置八位字節 8 的最高有效位 (MSB) ( ≥0x80 ) 時,該字段就會被解釋為 UUID,如RFC-4122中所指定。相應的音頻設備提供相同的 UUID,該 UUID 通過特定於所使用的傳輸類型的未指定機制在 Android 框架上註冊。

屬性:報告狀態( 0x0316

報告狀態 ( 0x0316 ) 屬性是一個讀/寫屬性,具有 HID 規範中定義的標準語義。主機使用此屬性向設備指示要報告哪些事件。僅使用值“無事件”( 0x0840 ) 和“所有事件”( 0x0841 )。

該字段的初始值必須是“無事件”,並且絕不能由設備修改,只能由主機修改。

屬性:電源狀態( 0x0319

電源狀態 ( 0x0319 ) 屬性是一個讀/寫屬性,具有 HID 規範中定義的標準語義。主機使用此屬性向設備指示它必須處於哪種電源狀態。僅使用值“Full Power”( 0x0851 )和“Power Off”( 0x0855 )。

該字段的初始值由設備確定,並且絕不能由設備修改,只能由主機修改。

屬性:報告間隔( 0x030E

報告間隔 ( 0x030E ) 屬性是一個讀/寫屬性,具有 HID 規範中定義的標準語義。主機使用此屬性向設備指示報告其數據讀數的頻率。單位是秒。該值的有效範圍由設備確定並使用物理最小/最大機制進行描述。必須支持至少 50 Hz 報告速率,建議最大報告速率為 100 Hz。因此,最小上報時間間隔必須小於或等於20ms,建議大於或等於10ms。

數據字段:自定義值 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 規則進行解釋。然而,物理值和單位並不重要。與主機相關的唯一信息是更改的值。為了避免從邏輯單位轉換為物理單位時與精度損失相關的數字問題,建議將此字段的物理最小值、物理最大值和單位指數的值設置為零。

報告結構

將屬性分組到報告中(通過分配報告 ID)是靈活的。為了提高效率,我們建議將只讀屬性與讀/寫屬性分開。

對於數據字段,自定義值 1、2 和 3 字段必須位於同一報告中,並且僅位於給定設備(應用集合)的一份報告中。

發送輸入報告

當滿足以下所有條件時,設備必須定期異步(通過 HID INPUT 消息)發送輸入報告:

  • 電源狀態屬性設置為全功率。
  • “報告狀態”屬性設置為“所有事件”。
  • 報告間隔屬性不為零。

報告間隔屬性決定發送報告的頻率。當不滿足上述任何條件時,設備不得發送任何報告。

向前和向後兼容性

頭部跟踪器 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,
};

在這種情況下,主機可以枚舉設備通告的所有不同應用程序集合,檢查其傳感器描述屬性以確定它們各自實現的協議版本,然後選擇主機支持的最新協議版本。選擇後,主機將使用為設備連接的生命週期選擇的單一協議。

附錄 1: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,
};