頭部跟踪器人機接口設備 (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
)
Persistent Unique ID ( 0x0302
) 屬性是一個只讀數組,包含 16 個元素,每個元素 8 位(總共 128 位)。預計沒有空終止符。該屬性是可選的。
此屬性允許集成在音頻設備中的頭部跟踪設備引用它們所連接的音頻設備。支持以下方案。
獨立頭部追踪器
如果 Persistent Unique 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 值B
和T
,接下來的 6 個八位字節被解釋為藍牙 MAC 地址,假設頭部跟踪器設備適用於任何具有這個 MAC 地址。
使用 UUID 引用
每當設置八位字節的最高有效位 (MSB) ( ≥0x80
) 時,該字段就被解釋為 UUID,如RFC-4122中所指定。相應的音頻設備通過特定於所用傳輸類型的未指定機制提供相同的 UUID,該 UUID 在 Android 框架上註冊。
屬性:報告狀態( 0x0316
)
報告狀態 ( 0x0316
) 屬性是具有 HID 規範中定義的標準語義的讀/寫屬性。主機使用此屬性向設備指示要報告哪些事件。僅使用值 No Events ( 0x0840
) 和 All Events ( 0x0841
)。
此字段的初始值必須為 No Events,並且不得由設備修改,只能由主機修改。
屬性:電源狀態 ( 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 消息)發送輸入報告:
- 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,
};
在這種情況下,主機可以枚舉設備發布的所有不同應用程序集合,檢查其傳感器描述屬性以確定它們各自實現的協議版本,然後選擇主機支持的最新協議版本。選擇後,主機將使用為設備連接的生命週期選擇的單一協議。
附錄 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,
};