El protocolo de dispositivo de interfaz humana (HID) con seguimiento de cabeza, disponible para dispositivos que ejecutan Android 13 y versiones posteriores, permite que un dispositivo de seguimiento de cabeza se conecte a uno Android mediante USB o Bluetooth y que se exponga al framework y las apps de Android a través del framework de sensores. Este protocolo se usa para controlar un efecto de virtualizador de audio (audio 3D). En esta página, se usan los términos dispositivo y host en el sentido de Bluetooth, en el que dispositivo se refiere al dispositivo de seguimiento de la cabeza y host se refiere al host de Android.
Los fabricantes de dispositivos deben configurar sus dispositivos Android para habilitar la compatibilidad con el protocolo HID del dispositivo de rastreo de cabeza. Para obtener información más detallada sobre la configuración, consulta el archivo README de los sensores dinámicos.
En esta página, se supone que conoces los siguientes recursos:
- Definición de la clase de dispositivo para HID
- Tablas de uso de HID para USB
- Usos de los sensores HID
Estructura de nivel superior
El framework de Android identifica el dispositivo de seguimiento de cabeza como un dispositivo HID.
Para obtener un ejemplo completo de un descriptor HID válido, consulta el Apéndice 1: Ejemplo de un descriptor HID.
En el nivel superior, el dispositivo de rastreo de cabeza es una colección de apps con la página Sensors
(0x20
) y el uso de Other: Custom
(0xE1
). Dentro de esta colección, hay varios campos de datos (entradas) y propiedades (funciones).
Propiedades y campos de datos
En esta sección, se describen las propiedades y los campos de datos de una recopilación de aplicaciones de un dispositivo de seguimiento de la cabeza.
Propiedad: Descripción del sensor (0x0308
)
La propiedad Sensor Description (0x0308
) es una propiedad de cadena ASCII (8 bits) de solo lectura que debe contener los siguientes valores:
Seguimiento de la cabeza versión 1.0:
#AndroidHeadTracker#1.0
Seguidor de cabeza versión 2.0 (disponible en Android 15 o versiones posteriores), que incluye compatibilidad con audio LE:
#AndroidHeadTracker#2.0#x
x
es un número entero (1
, 2
, 3
) que indica el transporte de compatibilidad:
- 1: ACL
- 2: ISO
- 3: ACL + ISO
No se espera un terminador nulo, lo que significa que el tamaño total de esta propiedad es de 23 caracteres de 8 bits para la versión 1.0.
Esta propiedad funciona como un discriminador para evitar colisiones con otros sensores personalizados.
Propiedad: ID único persistente (0x0302
)
La propiedad ID único persistente (0x0302
) es un array de solo lectura de 16 elementos, cada uno de 8 bits (128 bits en total). No se espera un terminador nulo. Esta propiedad es opcional.
Esta propiedad permite que los dispositivos de seguimiento de la cabeza integrados en dispositivos de audio hagan referencia al dispositivo de audio al que están conectados. Se admiten los siguientes esquemas.
Seguimiento de cabeza independiente
Si la propiedad ID único persistente (0x0302
) no existe o está configurada en todos los ceros, significa que el dispositivo de seguimiento de la cabeza no está conectado de forma permanente a un dispositivo de audio y se puede usar por separado, por ejemplo, permitiendo que el usuario asocie manualmente el dispositivo de seguimiento de la cabeza con un dispositivo de audio independiente.
Referencia con la dirección MAC de Bluetooth
Octeto | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Valor | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | B | T | Bluetooth MAC |
En este esquema, los primeros 8 octetos deben ser 0
, los octetos 8 y 9 deben contener los valores ASCII B
y T
, respectivamente, y los siguientes 6 octetos se interpretan como una dirección MAC de Bluetooth, siempre que el dispositivo de seguimiento de la cabeza se aplique a cualquier dispositivo de audio que tenga esta dirección MAC. Esta dirección debe ser la dirección de identidad, incluso si el dispositivo usa una dirección MAC aleatoria para establecer conexiones. Los dispositivos de modo dual que se conectan a través de Bluetooth clásico (formato HID v1.0) y Bluetooth LE (formato HID v2.0) deben exponer dos descriptores HID con la misma dirección de identidad. Los dispositivos de modo dual con dispositivos izquierdo y derecho separados deben exponer el HID de Bluetooth LE con el dispositivo principal de modo dual en lugar del dispositivo secundario solo para LE.
Referencia con UUID
Cada vez que se establece el bit más significativo (MSB) del octeto 8 (≥0x80
), el campo se interpreta como un UUID, como se especifica en RFC-4122. El dispositivo de audio correspondiente proporciona el mismo UUID, que se registra en el framework de Android, a través de un mecanismo no especificado que es específico del tipo de transporte que se usa.
Propiedad: Estado de los informes (0x0316
)
La propiedad Estado de informes (0x0316
) es una propiedad de lectura y escritura que tiene la semántica estándar como se define en la especificación HID. El host usa esta propiedad para indicarle al dispositivo qué eventos informar. Solo se usan los valores Sin eventos (0x0840
) y Todos los eventos (0x0841
).
El valor inicial de este campo debe ser No Events y el dispositivo nunca debe modificarlo, solo el host.
Propiedad: Estado de energía (0x0319
)
La propiedad de estado de la batería (0x0319
) es una propiedad de lectura y escritura que tiene la semántica estándar como se define en la especificación de HID. El host usa esta propiedad para indicarle al dispositivo en qué estado de energía debe estar. Solo se usan los valores Full Power (0x0851
) y Power Off (0x0855
).
El dispositivo determina el valor inicial de este campo y nunca debe modificarlo, solo el host.
Propiedad: Intervalo del informe (0x030E
)
La propiedad Intervalo de informes (0x030E
) es una propiedad de lectura y escritura que tiene la semántica estándar como se define en la especificación de HID. El host usa esta propiedad para indicarle al dispositivo con qué frecuencia informar sus lecturas de datos.
Las unidades son segundos. El dispositivo determina el rango válido para este valor y lo describe con el mecanismo de mínimo y máximo físico. Se debe admitir una frecuencia de informes de al menos 50 Hz, y la frecuencia máxima recomendada es de 100 Hz. Por lo tanto, el intervalo de informes mínimo debe ser inferior o igual a 20 ms, y se recomienda que sea superior o igual a 10 ms.
Propiedad: Transporte LE reservado por el proveedor (0xF410
)
La propiedad de transporte LE reservado por el proveedor (0xF410
) es una propiedad de lectura y escritura que tiene la semántica estándar como se define en la especificación de HID. El host usa esta propiedad para indicar el transporte seleccionado (ACL o ISO). Solo se usan los valores de ACL (0xF800
) e ISO (0xF801
), y ambos deben incluirse en la colección lógica.
Esta propiedad se configura antes de los estados de energía o informes.
Campo de datos: Valor personalizado 1 (0x0544
)
El campo Custom Value 1 (0x0544
) es un campo de entrada que se usa para informar la información real del seguimiento de la cabeza. Es un array de 3 elementos, interpretado según las reglas normales de HID para valores físicos, como se especifica en el artículo 6.2.2.7 de la especificación de HID. El rango válido para cada elemento es [-π, π] rad. Las unidades siempre son radianes.
Los elementos se interpretan de la siguiente manera: [rx, ry, rz]
, de modo que [rx, ry, rz]
es un vector de rotación que representa la transformación del marco de referencia al marco principal.
La magnitud debe estar en el rango [0..π].
El marco de referencia es arbitrario, pero, por lo general, es fijo y debe ser derecho. Se acepta una pequeña cantidad de deriva. Los ejes de la cabeza son los siguientes:
- X del oído izquierdo al derecho
- Y desde la parte posterior de la cabeza hasta la nariz (de atrás hacia adelante)
- Z desde el cuello hasta la parte superior de la cabeza
Campo de datos: Valor personalizado 2 (0x0545
)
El campo Custom Value 2 (0x0545
) es un campo de entrada que se usa para informar la información real del seguimiento de la cabeza. Es un array de punto fijo de 3 elementos, que se interpreta según las reglas normales de HID para los valores físicos.
Las unidades siempre son radianes por segundo.
Los elementos se interpretan como [vx, vy, vz]
, de modo que [vx, vy, vz]
es un vector de rotación que representa la velocidad angular del marco de la cabeza (en relación con sí mismo).
Campo de datos: Valor personalizado 3 (0x0546
)
El campo Valor personalizado 3 (0x0546
) es un campo de entrada que se usa para hacer un seguimiento de las discontinuidades en el marco de referencia. Es un número entero escalar de 8 bits de tamaño. El dispositivo debe incrementarlo (con unión) cada vez que se cambia el marco de referencia, por ejemplo, si se restablece el estado de un algoritmo de filtro de orientación que se usa para determinar la orientación. Este valor se interpreta según las reglas normales de HID para los valores físicos. Sin embargo, el valor físico y las unidades no importan. La única información relevante para el host es un valor modificado. Para evitar problemas numéricos relacionados con la pérdida de precisión durante la conversión de unidades lógicas a físicas, se recomienda establecer los valores de mínimo físico, máximo físico y exponente de unidad en cero para este campo.
Estructura del informe
La agrupación de propiedades en informes (a través de la asignación de IDs de informes) es flexible. Para mejorar la eficiencia, te recomendamos que separes las propiedades de solo lectura de las propiedades de lectura y escritura.
En el caso de los campos de datos, los campos de valor personalizado 1, 2 y 3 deben estar en el mismo informe y en un solo informe para un dispositivo determinado (colección de aplicaciones).
Cómo enviar informes de entradas
El dispositivo debe enviar informes de entrada de forma periódica y asíncrona (a través de mensajes de entrada HID) cuando se cumplan todas estas condiciones:
- La propiedad Power State está configurada en Full Power.
- La propiedad Estado de los informes está configurada en Todos los eventos.
- La propiedad Reporting Interval no es igual a cero.
La propiedad Intervalo de informes determina la frecuencia con la que se envían los informes. Cuando no se cumple alguna de las condiciones anteriores, el dispositivo no debe enviar ningún informe.
Compatibilidad con versiones anteriores y posteriores
El protocolo HID del dispositivo de seguimiento de cabeza usa un esquema de control de versiones que permite actualizaciones y, al mismo tiempo, interoperabilidad entre un host y un dispositivo que usan diferentes versiones del protocolo. Las versiones del protocolo se identifican con dos números, principales y secundarios, que tienen semánticas distintas, como se describe en las siguientes secciones.
Para determinar las versiones compatibles con un dispositivo, examina su propiedad Sensor Description (0x0308
).
Compatibilidad con versiones secundarias
Los cambios en la versión secundaria son retrocompatibles con versiones secundarias anteriores que se basan en la misma versión principal. En las actualizaciones de la versión menor, el host ignora los campos y las propiedades de datos adicionales. Por ejemplo, un dispositivo que usa la versión 1.6 del protocolo es compatible con un host que admite la versión 1.x del protocolo, incluida la versión 1.5.
Compatibilidad con versiones principales
Se permiten cambios incompatibles con versiones anteriores para los cambios en las versiones principales. Para admitir varias versiones principales para la interoperabilidad con hosts nuevos y antiguos, los dispositivos pueden especificar varias colecciones de apps en sus descriptores de informes. Por ejemplo:
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,
};
En este caso, el host puede enumerar todas las diferentes colecciones de apps que anuncia el dispositivo y examinar su propiedad Sensor Description para determinar las versiones de protocolo que implementa cada una y, luego, elegir la versión de protocolo más reciente que admite el host. Cuando se elige, el host funciona con el único protocolo que se eligió para toda la vida útil de la conexión del dispositivo.
Apéndice: Ejemplo de un descriptor HID
En el siguiente ejemplo, se muestra un descriptor HID válido típico. Usa las macros C de uso general, que se proporcionan en Usos del sensor HID (secció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,
};
Apéndice 2: Ejemplo de un descriptor HID v2.0
En el siguiente ejemplo, se ilustra un descriptor HID v2.0 para un dispositivo que solo admite el transporte de ACL de Bluetooth LE.
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,
};