Protocolo HID para seguimiento de cabeza

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 controlando un efecto de virtualización de audio (audio en 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 para seguimiento 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 asume que conoces los siguientes recursos:

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 seguimiento de cabeza es una colección de apps con la Página Sensors (0x20) y el uso de Other: Custom (0xE1). Dentro de este colección son varios campos de datos (entradas) y propiedades (atributos).

Propiedades y campos de datos

En esta sección, se describen las propiedades y los campos de datos de una aplicación. colección de un dispositivo de seguimiento de cabeza.

Propiedad: Descripción del sensor (0x0308)

La propiedad de descripción del sensor (0x0308) es una cadena ASCII (de 8 bits) de solo lectura que debe contener los siguientes valores:

Seguidor de 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 admitido:

  • 1: LCA
  • 2: ISO
  • 3: LCA + 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 discriminador para evitar colisiones con otras personalizados.

Propiedad: ID único persistente (0x0302)

La propiedad de 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 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, y los octetos 8 y 9 deben contener los valores ASCII B y T respectivamente, y los siguientes 6 octetos se interpretado como una dirección MAC de Bluetooth, suponiendo que el dispositivo de seguimiento de cabeza se aplica a cualquier dispositivo de audio con 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. Dispositivos en modo dual que se conectan por Bluetooth clásico (formato HID v1.0) y Bluetooth LE (formato HID v2.0) deben exponer dos HID descriptores de archivo con la misma dirección de identidad. Los dispositivos de modo dual con dispositivos izquierdo y derecho separados deben exponer el HID 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 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 específico del el tipo de transporte utilizado.

Propiedad: Estado de los informes (0x0316)

La propiedad de estado de los informes (0x0316) es una propiedad de lectura/escritura que tiene los siguientes elementos: 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 los valores No Se usan Eventos (0x0840) y Todos los eventos (0x0841).

El valor inicial de este campo debe ser Sin eventos y nunca debe ser modificado por el dispositivo, solo por el host.

Propiedad: Estado de energía (0x0319)

La propiedad de estado de energía (0x0319) es una propiedad de lectura/escritura que tiene los siguientes elementos: semántica estándar, como se define en la especificación HID. El host usa para indicar al dispositivo en qué estado de energía debe estar. Solo los valores de potencia completa (0x0851) y apagado (0x0855).

El dispositivo determina el valor inicial de este campo y nunca debe modificarlo, solo el host.

Propiedad: Intervalo de informes (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 están en segundos. El dispositivo determina el rango válido para este valor y se describe con el mecanismo de Mínimo/Máximo físico. Al menos 50 Hz tasa de generación de informes debe ser compatible, y la tasa máxima recomendada de estos debe ser 100 Hz. Por lo tanto, el intervalo mínimo del informe debe ser menor o igual que a 20 ms y se recomienda que sea mayor o igual que 10 ms.

Propiedad: Transporte LE reservado por el proveedor (0xF410)

La propiedad de LE Transport reservada por el proveedor (0xF410) es una propiedad de lectura/escritura que tenga la semántica estándar tal como se define en la especificación HID. El anfitrión usa esta propiedad para indicar el transporte seleccionado (LCA 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. Unidades son siempre radianes.

Los elementos se interpretan como [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 generalmente es fijo y debe ser para diestros. Se acepta una pequeña cantidad de deriva. Los ejes principales son los siguientes:

  • X de oreja izquierda a derecha
  • 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 Valor personalizado 2 (0x0545) es un campo de entrada que se utiliza para informar el información real sobre el seguimiento de la cabeza. Es un array de 3 elementos de punto fijo, interpretarse de acuerdo con las reglas normales de HID para 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 utiliza para el seguimiento. y discontinuidades en el marco de referencia. Es un número entero escalar de 8 bits de tamaño del ensamble. El dispositivo debe aumentarlo (con ajuste) cada vez que marco de referencia cambia, por ejemplo, si un algoritmo de filtro de orientación que se usó para determinar si se restableció el estado de la orientación. Este valor es de interpretarse de acuerdo con las reglas normales de HID para 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 (por asignación de IDs de informes) es flexible. Para mayor eficiencia, te recomendamos separar las propiedades de solo lectura. de las propiedades de lectura y escritura.

En los campos de datos, los campos Valor personalizado 1, 2 y 3 deben estar en el mismo y estar en un solo informe para un dispositivo determinado (colección de aplicaciones).

Enviar informes de entrada

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 Estado de energía se establece en Alimentación completa.
  • La propiedad Estado de los informes se establece 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. Cuándo 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 para seguimiento de cabeza usa un esquema de control de versiones que permite actualizaciones, a la vez que permite la interoperabilidad entre un host y un dispositivo que usa diferentes versiones del protocolo. Se identifican las versiones del protocolo por dos números, mayor y menor, que tienen una semántica distinta, ya que que 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 de protocolo es compatible con un host que admite protocolo versión 1.x, incluida la versión 1.5.

Compatibilidad con versiones principales

Se permiten los cambios no retrocompatibles para las modificaciones en 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 colecciones de apps diferentes que anuncia el dispositivo, examinando la propiedad de descripción del sensor para determinar las versiones del protocolo que implementa cada uno y, luego, elegir a la última versión que admite el host. Cuando se elige, el host trabaja con el protocolo único que se eligió para toda la vida útil del dispositivo conexión.

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