Протокол устройства с человеческим интерфейсом (HID) для отслеживания положения головы, доступный для устройств под управлением 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-разрядное), доступное только для чтения, которое должно содержать следующие значения:
Head tracker версия 1.0:
#AndroidHeadTracker#1.0
Head tracker версии 2.0 (доступен в Android 15 или более поздней версии), включающий поддержку звука LE:
#AndroidHeadTracker#2.0#x
x
— целое число ( 1
, 2
, 3
), обозначающее поддерживающий транспорт:
- 1: список управления доступом
- 2: ИСО
- 3: ACL + ISO
Нулевой символ-терминатор не ожидается, а это означает, что общий размер этого свойства составляет 23 8-битных символа для версии 1.0.
Это свойство служит дискриминатором, позволяющим избежать конфликтов с другими пользовательскими датчиками.
Свойство: постоянный уникальный идентификатор ( 0x0302
).
Свойство Persistent Unique ID ( 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 (формат HID версии 1.0) и Bluetooth LE (формат HID версии 2.0), должны предоставлять два дескриптора HID с одним и тем же идентификационным адресом. Двухрежимные устройства с разделенными левым и правым устройствами должны предоставлять Bluetooth LE HID с использованием основного двухрежимного устройства вместо вторичного устройства только с LE.
Ссылка с использованием UUID
Всякий раз, когда устанавливается старший бит (MSB) октета 8 ( ≥0x80
), поле интерпретируется как UUID, как указано в RFC-4122 . Соответствующее аудиоустройство предоставляет тот же UUID, который зарегистрирован в платформе Android, с помощью неуказанного механизма, специфичного для типа используемого транспорта.
Свойство: Состояние отчетности ( 0x0316
)
Свойство Reporting State ( 0x0316
) — это свойство чтения/записи, имеющее стандартную семантику, определенную в спецификации HID. Хост использует это свойство, чтобы указать устройству, о каких событиях следует сообщать. Используются только значения «Нет событий» ( 0x0840
) и «Все события» ( 0x0841
).
Начальное значение этого поля должно быть «Нет событий», и оно никогда не должно изменяться устройством, а только хостом.
Свойство: Состояние питания ( 0x0319
)
Свойство Power State ( 0x0319
) — это свойство чтения/записи, имеющее стандартную семантику, определенную в спецификации HID. Хост использует это свойство, чтобы указать устройству, в каком состоянии питания оно должно находиться. Используются только значения «Полная мощность» ( 0x0851
) и «Выключение питания» ( 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
).
Поле Custom Value 1 ( 0x0544
) — это поле ввода, используемое для сообщения фактической информации об отслеживании головы. Это массив из трех элементов, интерпретируемый в соответствии с обычными правилами HID для физических величин, как указано в разделе 6.2.2.7 спецификации HID. Допустимый диапазон для каждого элемента — [-π, π] рад. Единицы измерения всегда радианы.
Элементы интерпретируются как: [rx, ry, rz]
, так что [rx, ry, rz]
— вектор вращения , представляющий преобразование из опорного кадра в головной кадр. Величина должна находиться в диапазоне [0..π].
Система отсчета произвольна, но обычно она фиксирована и должна быть правосторонней. Небольшой дрейф допустим. Головные оси бывают:
- X от левого уха к правому
- Y от затылка к носу (сзади вперед)
- Z от шеи до макушки головы
Поле данных: пользовательское значение 2 ( 0x0545
).
Поле Custom Value 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,
};
Протокол устройства с интерфейсом человека (HID) для отслеживания положения головы, доступный для устройств под управлением 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-разрядное), доступное только для чтения, которое должно содержать следующие значения:
Head tracker версия 1.0:
#AndroidHeadTracker#1.0
Head tracker версии 2.0 (доступен в Android 15 или более поздней версии), включающий поддержку звука LE:
#AndroidHeadTracker#2.0#x
x
— целое число ( 1
, 2
, 3
), обозначающее поддерживающий транспорт:
- 1: список управления доступом
- 2: ИСО
- 3: ACL + ISO
Нулевой терминатор не ожидается, а это означает, что общий размер этого свойства составляет 23 8-битных символа для версии 1.0.
Это свойство служит дискриминатором, позволяющим избежать конфликтов с другими пользовательскими датчиками.
Свойство: постоянный уникальный идентификатор ( 0x0302
).
Свойство Persistent Unique ID ( 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 (формат HID версии 1.0) и Bluetooth LE (формат HID версии 2.0), должны предоставлять два дескриптора HID с одним и тем же идентификационным адресом. Двухрежимные устройства с разделенными левым и правым устройствами должны предоставлять Bluetooth LE HID с использованием основного двухрежимного устройства вместо вторичного устройства только с LE.
Ссылка с использованием UUID
Всякий раз, когда устанавливается старший бит (MSB) октета 8 ( ≥0x80
), поле интерпретируется как UUID, как указано в RFC-4122 . Соответствующее аудиоустройство предоставляет тот же UUID, который зарегистрирован в платформе Android, с помощью неуказанного механизма, специфичного для типа используемого транспорта.
Свойство: Состояние отчетности ( 0x0316
)
Свойство Reporting State ( 0x0316
) — это свойство чтения/записи, имеющее стандартную семантику, определенную в спецификации HID. Хост использует это свойство, чтобы указать устройству, о каких событиях следует сообщать. Используются только значения «Нет событий» ( 0x0840
) и «Все события» ( 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
).
Поле Custom Value 1 ( 0x0544
) — это поле ввода, используемое для сообщения фактической информации об отслеживании головы. Это массив из трех элементов, интерпретируемый в соответствии с обычными правилами HID для физических величин, как указано в разделе 6.2.2.7 спецификации HID. Допустимый диапазон для каждого элемента — [-π, π] рад. Единицы измерения всегда радианы.
Элементы интерпретируются как: [rx, ry, rz]
, так что [rx, ry, rz]
— вектор вращения , представляющий преобразование из опорного кадра в головной кадр. Величина должна находиться в диапазоне [0..π].
Система отсчета произвольна, но обычно она фиксирована и должна быть правосторонней. Небольшой дрейф допустим. Головные оси бывают:
- X от левого уха к правому
- Y от затылка к носу (сзади вперед)
- Z от шеи до макушки головы
Поле данных: пользовательское значение 2 ( 0x0545
).
Поле Custom Value 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.
- Для свойства «Состояние отчетности» установлено значение «Все события».
- Свойство «Интервал отчетности» не равно нулю.
Свойство Reporting Interval определяет, как часто отправлять отчеты. Если какое-либо из вышеперечисленных условий не выполнено, устройство не должно отправлять никаких отчетов.
Прямая и обратная совместимость
Протокол 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,
};