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

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

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