Протокол HID трекера головы

Протокол HID (Human Interface Device) для отслеживания положения головы (Head Tracker), доступный для устройств под управлением Android 13 и более поздних версий, позволяет подключать устройство отслеживания положения головы к устройству Android через USB или Bluetooth и использовать его для взаимодействия с фреймворком и приложениями Android через фреймворк датчиков . Этот протокол используется для управления эффектом виртуализации звука (3D-аудио). На этой странице термины «устройство» и «хост» используются в значении Bluetooth, где «устройство» означает устройство отслеживания положения головы, а « хост» — хост Android.

Производители устройств должны настроить свои устройства Android для поддержки протокола HID для отслеживания положения головы. Подробнее о настройке см. в файле README для динамических датчиков .

Эта страница предполагает знакомство со следующими ресурсами:

Структура верхнего уровня

Платформа Android идентифицирует устройство отслеживания положения головы как HID-устройство.

Полный пример допустимого дескриптора HID см. в Приложении 1: Пример дескриптора HID .

На верхнем уровне устройство отслеживания положения головы представляет собой коллекцию приложений со страницей Sensors ( 0x20 ) и страницей Other: Custom использование» ( 0xE1 ). Внутри этой коллекции находится несколько полей данных ( входов ) и свойств ( функций ).

Свойства и поля данных

В этом разделе описываются свойства и поля данных в коллекции приложений устройства отслеживания положения головы.

Свойство: Описание датчика ( 0x0308 )

Свойство Описание датчика ( 0x0308 ) — это строковое свойство ASCII (8-бит), доступное только для чтения, которое должно содержать следующие значения:

Версия хед-трекера 1.0:

#AndroidHeadTracker#1.0

Версия Head Tracker 2.0 (доступна в Android 15 и выше), которая включает поддержку LE-аудио:

#AndroidHeadTracker#2.0#x

x — целое число ( 1 , 2 , 3 ), указывающее на транспортную опору:

  • 1: ACL
  • 2: ИСО
  • 3: ACL + ISO

Нулевой терминатор не предполагается, что означает, что общий размер этого свойства составляет 23 8-битных символа для версии 1.0.

Это свойство служит дискриминатором, позволяющим избежать столкновений с другими пользовательскими датчиками.

Свойство: Постоянный уникальный идентификатор ( 0x0302 )

Свойство «Постоянный уникальный идентификатор» ( 0x0302 ) — это массив из 16 элементов, каждый по 8 бит (всего 128 бит), доступный только для чтения. Нулевой символ-терминатор не требуется. Это свойство необязательно.

Это свойство позволяет устройствам отслеживания положения головы, интегрированным в аудиоустройства, обращаться к аудиоустройству, к которому они подключены. Поддерживаются следующие схемы.

Автономный хед-трекер

Если свойство Persistent Unique ID ( 0x0302 ) не существует или установлено на все нули, это означает, что устройство отслеживания положения головы не постоянно подключено к аудиоустройству и может использоваться отдельно, например, позволяя пользователю вручную связать устройство отслеживания положения головы с отдельным аудиоустройством.

Ссылка с использованием MAC-адреса Bluetooth

Октет 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Ценить 0 0 0 0 0 0 0 0 Б Т Bluetooth MAC

В этой схеме первые 8 октетов должны быть 0 , октеты 8 и 9 должны содержать значения ASCII B и T соответственно, а следующие 6 октетов интерпретируются как MAC-адрес Bluetooth, предполагая, что устройство отслеживания положения головы относится к любому аудиоустройству с этим MAC-адресом. Этот адрес должен быть адресом идентификации, даже если устройство использует случайный MAC-адрес для установления соединения. Двухрежимные устройства, подключаемые по Bluetooth classic (формат HID v1.0) и Bluetooth LE (формат HID v2.0), должны предоставлять два дескриптора HID с одинаковым адресом идентификации. Двухрежимные устройства с раздельными левым и правым устройствами должны предоставлять Bluetooth LE HID, используя первичное двухрежимное устройство вместо вторичного устройства, работающего только с LE.

Ссылка с использованием UUID

Всякий раз, когда старший бит (MSB) октета 8 установлен ( ≥0x80 ), поле интерпретируется как UUID, как указано в RFC-4122 . Соответствующее аудиоустройство предоставляет тот же UUID, который зарегистрирован в фреймворке Android, через неопределённый механизм, специфичный для используемого типа транспорта.

Свойство: Состояние отчета ( 0x0316 )

Свойство Reporting State ( 0x0316 ) доступно для чтения и записи и имеет стандартную семантику, определенную в спецификации HID. Хост использует это свойство, чтобы указать устройству, о каких событиях следует сообщать. Используются только значения No Events ( 0x0840 ) и All Events ( 0x0841 ).

Начальное значение этого поля должно быть «Нет событий», и оно никогда не должно изменяться устройством, только хостом.

Свойство: Состояние питания ( 0x0319 )

Свойство Power State ( 0x0319 ) доступно для чтения и записи и имеет стандартную семантику, определенную в спецификации HID. Хост использует это свойство, чтобы указать устройству, в каком состоянии питания оно должно находиться. Используются только значения Full Power ( 0x0851 ) и Power Off ( 0x0855 ).

Начальное значение этого поля определяется устройством и никогда не должно изменяться устройством, только хостом.

Свойство: Интервал отчета ( 0x030E )

Свойство Report Interval ( 0x030E ) доступно для чтения и записи и имеет стандартную семантику, определенную в спецификации HID. Хост использует это свойство, чтобы указать устройству периодичность отправки показаний данных. Единицы измерения — секунды. Допустимый диапазон этого значения определяется устройством и описывается с помощью механизма Physical Min/Max. Должна поддерживаться частота отправки данных не менее 50 Гц, а рекомендуемая максимальная частота отправки данных — 100 Гц. Следовательно, минимальный интервал отправки данных должен быть меньше или равен 20 мс, а рекомендуется быть больше или равен 10 мс.

Свойство: Зарезервированный поставщиком LE Transport ( 0xF410 )

Свойство LE Transport ( 0xF410 ), зарезервированное поставщиком, доступно для чтения и записи и имеет стандартную семантику, определенную в спецификации HID. Хост использует это свойство для указания выбранного транспорта (ACL или ISO). Используются только значения ACL ( 0xF800 ) и ISO ( 0xF801 ), и оба должны быть включены в логическую коллекцию.

Это свойство настраивается до состояний питания или отчетности.

Поле данных: Пользовательское значение 1 ( 0x0544 )

Поле «Пользовательское значение 1» ( 0x0544 ) — это поле ввода, используемое для отображения фактической информации о слежении за положением головы. Это массив из трёх элементов, интерпретируемый в соответствии со стандартными правилами HID для физических величин, указанными в разделе 6.2.2.7 спецификации HID. Допустимый диапазон для каждого элемента — [-π, π] рад. Единицы измерения — радианы.

Элементы интерпретируются как: [rx, ry, rz] , где [rx, ry, rz]вектор вращения , представляющий преобразование из исходной системы отсчёта в головную систему. Величина должна находиться в диапазоне [0..π].

Система отсчёта произвольна, но обычно фиксирована и должна быть правосторонней. Небольшой дрейф допустим. Головные оси:

  • X от левого уха к правому
  • Y от затылка к носу (сзади вперед)
  • Z от шеи до макушки головы

Поле данных: Пользовательское значение 2 ( 0x0545 )

Поле «Пользовательское значение 2» ( 0x0545 ) — это поле ввода, используемое для отображения фактической информации о слежении за положением головы. Это трёхэлементный массив с фиксированной точкой, интерпретируемый в соответствии со стандартными правилами HID для физических величин. Единицы измерения — радианы в секунду.

Элементы интерпретируются как: [vx, vy, vz] , где [vx, vy, vz]вектор вращения , представляющий угловую скорость головной рамы (относительно самой себя).

Поле данных: Пользовательское значение 3 ( 0x0546 )

Поле Custom Value 3 ( 0x0546 ) — это поле ввода, используемое для отслеживания разрывов в системе отсчёта. Это скалярное целое число размером 8 бит. Оно должно увеличиваться (с циклическим переходом) устройством каждый раз при изменении системы отсчёта, например, если алгоритм фильтра ориентации, используемый для определения ориентации, сбросил своё состояние. Это значение интерпретируется в соответствии с обычными правилами HID для физических величин. Однако физическое значение и единицы измерения не имеют значения. Единственной информацией, имеющей отношение к хосту, является изменённое значение. Чтобы избежать числовых проблем, связанных с потерей точности при преобразовании из логических единиц в физические, рекомендуется установить значения физического минимума, физического максимума и показателя степени единицы в этом поле равными нулю.

Структура отчета

Группировка свойств в отчёты (путём назначения идентификаторов отчётов) является гибкой. Для эффективности рекомендуется разделить свойства, доступные только для чтения, и свойства, доступные для чтения и записи.

Для полей данных поля «Пользовательское значение 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,
};

В этом случае хост может перечислить все различные коллекции приложений, предлагаемые устройством, проверяя их свойство «Описание датчика» для определения версий протокола, которые они реализуют, а затем выбрать последнюю версию протокола, поддерживаемую хостом. После выбора хост будет работать с единственным протоколом, выбранным на весь срок действия соединения с устройством.

Приложение: Пример дескриптора HID

Следующий пример иллюстрирует типичный допустимый дескриптор HID. Он использует распространённые макросы C, представленные в разделе «Использование датчиков HID» (раздел 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,
};

Приложение 2: Пример дескриптора HID версии 2.0

В следующем примере показан дескриптор HID версии 2.0 для устройства, поддерживающего только транспорт Bluetooth 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,
};