Giao thức HID của trình theo dõi đầu

Giao thức thiết bị giao diện con người (HID) theo dõi đầu, có sẵn cho các thiết bị chạy Android 13 trở lên, cho phép thiết bị theo dõi đầu được kết nối với thiết bị Android thông qua USB hoặc Bluetooth và tiếp xúc với khung và ứng dụng Android thông qua các cảm biến khuôn khổ. Giao thức này được sử dụng để kiểm soát hiệu ứng ảo hóa âm thanh (âm thanh 3D). Trang này sử dụng thuật ngữ thiết bịmáy chủ theo nghĩa Bluetooth, trong đó thiết bị có nghĩa là thiết bị theo dõi chuyển động đầu và máy chủ có nghĩa là máy chủ Android.

Các nhà sản xuất thiết bị phải định cấu hình thiết bị Android của họ để hỗ trợ giao thức HID theo dõi đầu. Để biết thêm thông tin chi tiết về cấu hình, hãy xem Cảm biến động README .

Trang này giả định bạn đã quen thuộc với các tài nguyên sau:

Cấu trúc cấp cao nhất

Khung Android xác định thiết bị theo dõi đầu là thiết bị HID.

Để biết ví dụ đầy đủ về bộ mô tả HID hợp lệ, hãy xem Phụ lục 1: Ví dụ về bộ mô tả HID .

Ở cấp cao nhất, thiết bị theo dõi đầu là một bộ sưu tập ứng dụng có trang Sensors ( 0x20 ) và Other: Custom ( 0xE1 ). Bên trong bộ sưu tập này có một số trường dữ liệu ( đầu vào ) và thuộc tính ( tính năng ).

Thuộc tính và trường dữ liệu

Phần này mô tả các thuộc tính và trường dữ liệu trong bộ sưu tập ứng dụng của thiết bị theo dõi đầu.

Thuộc tính: Mô tả cảm biến ( 0x0308 )

Thuộc tính Mô tả cảm biến ( 0x0308 ) là thuộc tính chuỗi ASCII (8 bit) chỉ đọc phải chứa giá trị sau:

#AndroidHeadTracker#1.0

Không có dấu kết thúc null nào được mong đợi, nghĩa là tổng kích thước của thuộc tính này là 23 ký tự 8 bit.

Thuộc tính này đóng vai trò là yếu tố phân biệt để tránh va chạm với các cảm biến tùy chỉnh khác.

Thuộc tính: ID duy nhất liên tục ( 0x0302 )

Thuộc tính ID duy nhất liên tục ( 0x0302 ) là một mảng chỉ đọc gồm 16 phần tử, mỗi phần tử 8 bit (tổng cộng 128 bit). Không có bộ kết thúc null nào được mong đợi. Thuộc tính này là tùy chọn.

Thuộc tính này cho phép các thiết bị theo dõi đầu được tích hợp trong thiết bị âm thanh tham chiếu đến thiết bị âm thanh mà chúng được gắn vào. Các chương trình sau đây được hỗ trợ.

Máy theo dõi đầu độc lập

Nếu thuộc tính ID duy nhất liên tục ( 0x0302 ) không tồn tại hoặc được đặt thành tất cả số 0, điều đó có nghĩa là thiết bị theo dõi đầu không được gắn vĩnh viễn vào thiết bị âm thanh và có thể được sử dụng riêng, chẳng hạn như bằng cách cho phép người dùng theo cách thủ công liên kết thiết bị theo dõi đầu với một thiết bị âm thanh riêng.

Tham chiếu sử dụng địa chỉ MAC Bluetooth

Octet 0 1 2 3 4 5 6 7 số 8 9 10 11 12 13 14 15
Giá trị 0 0 0 0 0 0 0 0 B T Bluetooth MAC

Trong sơ đồ này, 8 octet đầu tiên phải là 0 , octet 8 và 9 phải chứa các giá trị ASCII BT tương ứng và 6 octet sau được hiểu là địa chỉ MAC Bluetooth, giả sử thiết bị theo dõi đầu áp dụng cho bất kỳ thiết bị âm thanh nào có địa chỉ MAC này.

Tham khảo sử dụng UUID

Bất cứ khi nào bit quan trọng nhất (MSB) của octet 8 được đặt ( ≥0x80 ), trường này được hiểu là UUID, như được chỉ định trong RFC-4122 . Thiết bị âm thanh tương ứng cung cấp cùng một UUID, được đăng ký trên khung Android, thông qua một cơ chế không xác định dành riêng cho loại phương tiện truyền tải được sử dụng.

Thuộc tính: Trạng thái báo cáo ( 0x0316 )

Thuộc tính Trạng thái báo cáo ( 0x0316 ) là thuộc tính đọc/ghi có ngữ nghĩa tiêu chuẩn như được xác định trong đặc tả HID. Máy chủ sử dụng thuộc tính này để cho thiết bị biết những sự kiện nào cần báo cáo. Chỉ các giá trị Không có sự kiện ( 0x0840 ) và Tất cả sự kiện ( 0x0841 ) được sử dụng.

Giá trị ban đầu cho trường này phải là Không có sự kiện và nó không bao giờ được sửa đổi bởi thiết bị mà chỉ bởi máy chủ.

Thuộc tính: Trạng thái nguồn ( 0x0319 )

Thuộc tính Power State ( 0x0319 ) là thuộc tính đọc/ghi có ngữ nghĩa tiêu chuẩn như được xác định trong đặc tả HID. Máy chủ sử dụng thuộc tính này để cho thiết bị biết trạng thái nguồn của thiết bị. Chỉ sử dụng các giá trị Toàn quyền ( 0x0851 ) và Tắt nguồn ( 0x0855 ).

Giá trị ban đầu cho trường này được xác định bởi thiết bị và không bao giờ được sửa đổi bởi thiết bị mà chỉ bởi máy chủ.

Thuộc tính: Khoảng thời gian báo cáo ( 0x030E )

Thuộc tính Khoảng thời gian báo cáo ( 0x030E ) là thuộc tính đọc/ghi có ngữ nghĩa tiêu chuẩn như được xác định trong đặc tả HID. Máy chủ sử dụng thuộc tính này để cho thiết bị biết tần suất báo cáo kết quả đọc dữ liệu của nó. Đơn vị là giây. Phạm vi hợp lệ cho giá trị này được thiết bị xác định và được mô tả bằng cơ chế Tối thiểu/Tối đa Vật lý. Tốc độ báo cáo tối thiểu phải được hỗ trợ là 50 Hz và tốc độ báo cáo tối đa được đề xuất là 100 Hz. Do đó, khoảng thời gian báo cáo tối thiểu phải nhỏ hơn hoặc bằng 20 mili giây và được khuyến nghị lớn hơn hoặc bằng 10 mili giây.

Trường dữ liệu: Giá trị tùy chỉnh 1 ( 0x0544 )

Trường Giá trị tùy chỉnh 1 ( 0x0544 ) là trường đầu vào được sử dụng để báo cáo thông tin theo dõi chuyển động đầu thực tế. Đó là mảng 3 phần tử, được diễn giải theo quy tắc HID thông thường cho các giá trị vật lý như được chỉ định trong phần 6.2.2.7 của đặc tả HID. Phạm vi hợp lệ cho mỗi phần tử là [-π, π] rad. Đơn vị luôn là radian.

Các phần tử được hiểu là: [rx, ry, rz] , sao cho [rx, ry, rz] là một vectơ xoay , biểu thị sự biến đổi từ khung tham chiếu sang khung đầu. Độ lớn phải nằm trong phạm vi [0..π].

Hệ quy chiếu là tùy ý nhưng nhìn chung nó cố định và phải thuận tay phải. Một lượng nhỏ trôi dạt là chấp nhận được. Trục đầu là:

  • X từ tai trái sang phải
  • Y từ sau đầu đến mũi (sau ra trước)
  • Z từ cổ đến đỉnh đầu

Trường dữ liệu: Giá trị tùy chỉnh 2 ( 0x0545 )

Trường Giá trị tùy chỉnh 2 ( 0x0545 ) là trường đầu vào được sử dụng để báo cáo thông tin theo dõi chuyển động đầu thực tế. Đó là mảng điểm cố định 3 phần tử, được diễn giải theo quy tắc HID thông thường cho các giá trị vật lý. Đơn vị luôn là radian/giây.

Các phần tử được hiểu là: [vx, vy, vz] , sao cho [vx, vy, vz] là một vectơ quay , biểu thị vận tốc góc của khung đầu (so với chính nó).

Trường dữ liệu: Giá trị tùy chỉnh 3 ( 0x0546 )

Trường Giá trị tùy chỉnh 3 ( 0x0546 ) là trường đầu vào được sử dụng để theo dõi sự gián đoạn trong khung tham chiếu. Đó là một số nguyên vô hướng có kích thước 8 bit. Nó phải được thiết bị tăng lên (với tính năng bao quanh) mỗi khi khung tham chiếu được thay đổi, ví dụ: nếu thuật toán lọc hướng được sử dụng để xác định hướng đã được đặt lại trạng thái. Giá trị này được diễn giải theo quy tắc HID thông thường đối với các giá trị vật lý. Tuy nhiên, giá trị vật lý và đơn vị không quan trọng. Thông tin duy nhất liên quan đến máy chủ là giá trị đã thay đổi. Để tránh các vấn đề về số liên quan đến việc mất độ chính xác khi chuyển đổi từ đơn vị logic sang đơn vị vật lý, bạn nên đặt các giá trị cho giá trị tối thiểu vật lý, giá trị tối đa vật lý và số mũ đơn vị về 0 cho trường này.

Cấu trúc báo cáo

Việc nhóm các thuộc tính thành báo cáo (bằng cách gán ID báo cáo) rất linh hoạt. Để đạt hiệu quả, chúng tôi khuyên bạn nên tách thuộc tính chỉ đọc khỏi thuộc tính đọc/ghi.

Đối với các trường dữ liệu, các trường Giá trị tùy chỉnh 1, 2 và 3 phải nằm trong cùng một báo cáo và chỉ nằm trong một báo cáo cho một thiết bị nhất định (bộ sưu tập ứng dụng).

Gửi báo cáo đầu vào

Thiết bị phải gửi báo cáo đầu vào theo định kỳ và không đồng bộ (thông qua tin nhắn HID INPUT) khi đáp ứng tất cả các điều kiện sau:

  • Thuộc tính Power State được đặt thành Full Power.
  • Thuộc tính Trạng thái báo cáo được đặt thành Tất cả sự kiện.
  • Thuộc tính Khoảng thời gian báo cáo khác không.

Thuộc tính Khoảng thời gian báo cáo xác định tần suất gửi báo cáo. Khi không đáp ứng bất kỳ điều kiện nào ở trên, thiết bị không được gửi bất kỳ báo cáo nào.

Khả năng tương thích tiến và lùi

Giao thức HID theo dõi đầu sử dụng sơ đồ phiên bản cho phép cập nhật, đồng thời cho phép khả năng tương tác giữa máy chủ và thiết bị sử dụng các phiên bản khác nhau của giao thức. Các phiên bản của giao thức được xác định bằng hai số, chính và phụ, có ngữ nghĩa riêng biệt như được mô tả trong các phần sau.

Có thể xác định các phiên bản được thiết bị hỗ trợ bằng cách kiểm tra thuộc tính Mô tả cảm biến ( 0x0308 ) của thiết bị đó.

Khả năng tương thích phiên bản nhỏ

Những thay đổi đối với phiên bản phụ tương thích ngược với các phiên bản phụ trước đó dựa trên cùng một phiên bản chính. Trong các bản cập nhật lên phiên bản nhỏ, máy chủ sẽ bỏ qua các trường và thuộc tính dữ liệu bổ sung. Ví dụ: một thiết bị sử dụng giao thức phiên bản 1.6 tương thích với máy chủ hỗ trợ giao thức phiên bản 1.x, bao gồm cả phiên bản 1.5.

Khả năng tương thích phiên bản chính

Những thay đổi không tương thích ngược được phép thay đổi các phiên bản chính. Để hỗ trợ nhiều phiên bản chính cho khả năng tương tác với máy chủ cũ và mới, các thiết bị có thể chỉ định nhiều bộ sưu tập ứng dụng trong phần mô tả báo cáo của chúng. Ví dụ:

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

Trong trường hợp này, máy chủ có thể liệt kê tất cả các bộ sưu tập ứng dụng khác nhau được thiết bị quảng cáo, kiểm tra thuộc tính Mô tả cảm biến của chúng để xác định phiên bản giao thức mà từng bộ sưu tập đó triển khai, sau đó chọn phiên bản giao thức mới nhất mà máy chủ hỗ trợ. Khi được chọn, máy chủ sẽ hoạt động với giao thức duy nhất đã được chọn trong suốt thời gian kết nối thiết bị.

Phụ lục: Ví dụ về bộ mô tả HID

Ví dụ sau minh họa một bộ mô tả HID hợp lệ điển hình. Nó sử dụng các macro C thường được sử dụng, được cung cấp trong Cách sử dụng cảm biến HID (phần 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,
};