頭戴式追蹤器 HID 通訊協定

頭部追蹤人機介面裝置 (HID) 通訊協定適用於搭載 Android 13 以上版本的裝置,可讓頭部追蹤裝置透過 USB 或藍牙連線至 Android 裝置,並透過 sensors 架構公開至 Android 架構和應用程式。這個通訊協定用於控制音訊虛擬化效果 (3D 音訊)。本頁使用了「device」host 保持藍牙狀態,其中「device」是指頭部追蹤裝置 和 host 表示 Android 主機。

裝置製造商必須設定 Android 裝置,才能支援頭戴式追蹤器 HID 通訊協定。如要進一步瞭解設定,請參閱 Dynamic Sensors README

本頁面假設您熟悉下列資源:

頂層結構

Android 架構會將頭戴式追蹤器裝置識別為 HID 裝置。

如需有效 HID 描述元的完整範例,請參閱 附錄 1:HID 描述元範例

在頂層,頭戴式追蹤裝置是應用程式集合,其中包含 Sensors 頁面 (0x20) 和 Other: Custom 用途 (0xE1)。這個集合內含多個資料欄 (輸入內容) 和資源 (功能)。

屬性和資料欄位

本節說明頭戴式追蹤裝置應用程式集合中的屬性和資料欄位。

屬性:感應器說明 (0x0308)

感應器說明 (0x0308) 屬性是只讀 ASCII (8 位元) 字串屬性,必須包含下列值:

Head Tracker 1.0 版:

#AndroidHeadTracker#1.0

頭戴式追蹤器 2.0 版 (適用於 Android 15 以上版本),支援 LE 音訊:

#AndroidHeadTracker#2.0#x

x 是整數 (123),用於指出支援的傳輸方式:

  • 1:ACL
  • 2:ISO
  • 3:ACL + ISO

系統不會預期空值終止符,也就是說,在 1.0 版中,這個屬性的總大小為 23 個 8 位元字元。

這個屬性可做為鑑別器,避免與其他資源發生衝突 自訂感應器

屬性:永久專屬 ID (0x0302)

永久專屬 ID (0x0302) 屬性是 16 的唯讀陣列 各 8 位元 (共 128 位元)。不應有空值的結束字元。這個 屬性為選用項目。

這個屬性允許使用音訊中整合的頭部追蹤裝置 裝置,以參照目前附加的音訊裝置。 支援下列機制。

獨立頭部追蹤器

如果永久專屬 ID (0x0302) 屬性不存在或設為全部 0,表示頭部追蹤器裝置不會永久連接至 音訊裝置,並可以單獨使用,例如 手動將頭部智慧手環裝置與個別音訊裝置建立關聯。

使用藍牙 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 分 B 藍牙 MAC

在這個配置中,前 8 個位元組必須是 0,位元組 8 和 9 必須分別包含 ASCII 值 BT,而後續 6 個位元組會解讀為藍牙 MAC 位址,假設頭戴式追蹤器裝置適用於任何具有此 MAC 位址的音訊裝置。即使裝置使用隨機 MAC 位址建立連線,這個位址仍必須是 ID 位址。透過藍牙連線的雙模式裝置 (1.0 HID 格式) 和藍牙 LE (v2.0 HID 格式) 必須公開兩組 HID 由同一個身分位址的描述元所導致。雙模式裝置 (左、右裝置分開) 必須使用主要雙模式裝置,而非僅限 LE 的次要裝置,公開顯示藍牙 LE HID。

使用 UUID

只要 8 位元組的最高位元 (MSB) 已設為 ≥0x80,系統就會依 RFC-4122 的規定,將欄位解讀為 UUID。對應的音訊裝置會提供相同的 UUID,並透過特定傳輸機制 (依據所用傳輸類型而定) 在 Android 架構中註冊。

屬性:報表狀態 (0x0316)

「報表狀態」(0x0316) 屬性是讀取/寫入屬性,具有 HID 規格中定義的標準語意主機會使用這個屬性,向裝置指出要回報哪些事件。系統只會使用「No Events」(0x0840) 和「All Events」(0x0841) 的值。

這個欄位的初始值必須為「No Events」,且裝置不得修改該值,只能由主機修改。

屬性:電源狀態 (0x0319)

電源狀態 (0x0319) 屬性是具有 HID 規格中定義的標準語意主機會使用這個 屬性,指示裝置應處於電源狀態。只有 值為 Full Power (0x0851) 和關機 (0x0855)。

這個欄位的初始值是由裝置決定,一律不得 僅由裝置修改。

資源:報表間隔 (0x030E)

「報表間隔」(0x030E) 屬性是讀取/寫入屬性, HID 規格中定義的標準語意主機會使用這個屬性,向裝置指出要多久回報一次資料讀數。單位為秒。這個值的有效範圍由裝置決定 並使用實體最低/最大數量機制描述。必須支援至少 50 Hz 的回報率,建議的最高回報率為 100 Hz。因此,最小回報間隔必須小於或等於 20 毫秒,建議為大於或等於 10 毫秒。

資源:供應商保留 LE Transport (0xF410)

供應商保留的 LE Transport (0xF410) 屬性為讀取/寫入屬性 而且具有 HID 規格中定義的標準語意主辦人 會使用這個屬性來表示所選的傳輸方式 (ACL 或 ISO)。只會使用值 ACL (0xF800) 和 ISO (0xF801),且兩者都必須納入邏輯集合。

這項屬性會在電源或回報狀態之前設定。

資料欄位:自訂值 1 (0x0544)

「自訂值 1」(0x0544) 欄位是用來回報實際頭部追蹤資訊的輸入欄位。這是一個 3 元素陣列,會根據 HID 規格第 6.2.2.7 節所述的一般 HID 規則,解讀物理值。每個元素的有效範圍為 [-π, π] 。單位 一律為弧度

元素會解讀為:[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 訊息) 滿足下列條件時,才傳送輸入報告:

  • 電源狀態屬性已設為「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 描述元。這項程式碼使用 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,
};

附錄 2:v2.0 HID 描述元範例

以下範例說明支援裝置的 v2.0 HID 描述元 只有藍牙 LE ACL 傳輸

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#2.0#1"
        HID_USAGE_SENSOR_PROPERTY_SENSOR_DESCRIPTION,
        HID_LOGICAL_MIN_8(0),
        HID_LOGICAL_MAX_8(0xFF),
        HID_REPORT_SIZE(8),
        HID_REPORT_COUNT(25),
        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),

        // 1-bit transport selection
        HID_USAGE_SENSOR_PROPERTY_VENDOR_LE_TRANSPORT,
        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_VENDOR_LE_TRANSPORT_ACL,
            HID_USAGE_SENSOR_PROPERTY_VENDOR_LE_TRANSPORT_ISO,
            HID_FEATURE(HID_DATA_ARR_ABS),
        HID_END_COLLECTION,

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