Protocolo HID de rastreador de cabeza

El protocolo del dispositivo de interfaz humana (HID) del rastreador de cabeza, disponible para dispositivos con Android 13 y versiones posteriores, permite conectar un dispositivo de seguimiento de la cabeza a un dispositivo Android a través de USB o Bluetooth y exponerlo al marco y las aplicaciones de Android a través de los sensores. estructura. Este protocolo se utiliza para controlar un efecto de virtualizador de audio (audio 3D). Esta página utiliza los términos dispositivo y host en su sentido Bluetooth, donde dispositivo significa el dispositivo de seguimiento de cabeza y host significa el host de Android.

Los fabricantes de dispositivos deben configurar sus dispositivos Android para habilitar la compatibilidad con el protocolo HID del rastreador de cabeza. Para obtener información más detallada sobre la configuración, consulte el archivo README de sensores dinámicos .

Esta página asume familiaridad con los siguientes recursos:

Estructura de alto nivel

El marco de Android identifica el dispositivo de seguimiento de cabeza como un dispositivo HID.

Para obtener un ejemplo completo de un descriptor HID válido, consulte el Apéndice 1: Ejemplo de un descriptor HID .

En el nivel superior, el dispositivo de seguimiento de cabeza es una colección de aplicaciones con la página Sensors ( 0x20 ) y Other: Custom ( 0xE1 ). Dentro de esta colección hay varios campos de datos ( entradas ) y propiedades ( características ).

Propiedades y campos de datos

Esta sección describe las propiedades y los campos de datos en una colección de aplicaciones de un dispositivo de seguimiento de cabeza.

Propiedad: Descripción del sensor ( 0x0308 )

La propiedad Descripción del sensor ( 0x0308 ) es una propiedad de cadena ASCII (8 bits) de solo lectura que debe contener el siguiente valor:

#AndroidHeadTracker#1.0

No se espera ningún terminador nulo, lo que significa que el tamaño total de esta propiedad es de 23 caracteres de 8 bits.

Esta propiedad sirve como discriminador para evitar colisiones con otros sensores personalizados.

Propiedad: ID único persistente ( 0x0302 )

La propiedad ID único persistente ( 0x0302 ) es una matriz de solo lectura de 16 elementos, de 8 bits cada uno (128 bits en total). No se espera ningún terminador nulo. Esta propiedad es opcional.

Esta propiedad permite que los dispositivos de seguimiento de cabeza integrados en dispositivos de audio hagan referencia al dispositivo de audio al que están conectados. Se admiten los siguientes esquemas.

Rastreador de cabeza independiente

Si la propiedad ID única persistente ( 0x0302 ) no existe o está configurada solo en ceros, significa que el dispositivo de seguimiento de cabeza no está conectado permanentemente a un dispositivo de audio y se puede usar por separado, por ejemplo, permitiendo al usuario manualmente asocie el dispositivo de seguimiento de cabeza con un dispositivo de audio independiente.

Referencia usando 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, asumiendo que el dispositivo de seguimiento de cabeza se aplica a cualquier dispositivo de audio que tenga esta dirección MAC.

Referencia usando UUID

Siempre 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 está registrado en el marco de Android, a través de un mecanismo no especificado y específico del tipo de transporte utilizado.

Propiedad: Estado de informe ( 0x0316 )

La propiedad Reporting State ( 0x0316 ) es una propiedad de lectura/escritura que tiene la semántica estándar definida en la especificación HID. El host utiliza esta propiedad para indicar al dispositivo qué eventos informar. Solo se utilizan los valores Sin 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 Power State ( 0x0319 ) es una propiedad de lectura/escritura que tiene la semántica estándar definida en la especificación HID. El host utiliza esta propiedad para indicar al dispositivo en qué estado de energía debe estar. Solo se utilizan los valores Potencia máxima ( 0x0851 ) y Apagado ( 0x0855 ).

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

Propiedad: Intervalo de informe ( 0x030E )

La propiedad Intervalo de informe ( 0x030E ) es una propiedad de lectura/escritura que tiene la semántica estándar definida en la especificación HID. El host utiliza esta propiedad para indicarle al dispositivo con qué frecuencia informar sus lecturas de datos. Las unidades son segundos. El rango válido para este valor lo determina el dispositivo y se describe mediante el mecanismo físico mínimo/máximo. Se debe admitir una tasa de informes de al menos 50 Hz y la tasa de informes máxima recomendada es de 100 Hz. Por lo tanto, el intervalo mínimo de informe debe ser menor o igual a 20 ms, y se recomienda que sea mayor o igual a 10 ms.

Campo de datos: Valor personalizado 1 ( 0x0544 )

El campo Valor personalizado 1 ( 0x0544 ) es un campo de entrada que se utiliza para informar la información real de seguimiento de la cabeza. Es una matriz de 3 elementos, interpretada de acuerdo con las reglas HID normales para valores físicos como se especifica en la sección 6.2.2.7 de la especificación HID. El rango válido para cada elemento es [-π, π] rad. Las unidades siempre son 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 diestro. Es aceptable una pequeña cantidad de deriva. Los ejes de cabeza son:

  • 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 la información real de seguimiento de la cabeza. Es una matriz de punto fijo de 3 elementos, interpretada de acuerdo con las reglas HID normales para valores físicos. Las unidades siempre son radianes/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 cabezal (con respecto a sí mismo).

Campo de datos: Valor personalizado 3 ( 0x0546 )

El campo Valor personalizado 3 ( 0x0546 ) es un campo de entrada que se utiliza para rastrear discontinuidades en el marco de referencia. Es un número entero escalar de 8 bits de tamaño. El dispositivo debe incrementarlo (con envoltura) cada vez que se cambia el marco de referencia, por ejemplo, si se restablece el estado de un algoritmo de filtro de orientación utilizado para determinar la orientación. Este valor se interpreta de acuerdo con las reglas HID normales 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 al convertir 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 (mediante asignación de ID de informe) es flexible. Para mayor eficiencia, recomendamos separar las propiedades de solo lectura de las propiedades de lectura/escritura.

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

Enviar informes de entrada

El dispositivo debe enviar periódicamente y de forma asíncrona (a través de mensajes HID INPUT) informes de entrada cuando se cumplan todas estas condiciones:

  • La propiedad Estado de energía está establecida en Potencia máxima.
  • La propiedad Estado de informe está establecida en Todos los eventos.
  • La propiedad Intervalo de informes no es 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 hacia adelante y hacia atrás

El protocolo HID del rastreador de cabeza utiliza un esquema de control de versiones que permite actualizaciones y, al mismo tiempo, permite la interoperabilidad entre un host y un dispositivo que utiliza diferentes versiones del protocolo. Las versiones del protocolo se identifican mediante dos números, mayor y menor, que tienen una semántica distinta, como se describe en las siguientes secciones.

Las versiones admitidas por un dispositivo se pueden determinar examinando su propiedad Descripción del sensor ( 0x0308 ).

Compatibilidad de versiones menores

Los cambios realizados en la versión secundaria son compatibles con versiones menores anteriores que se basan en la misma versión principal. En las actualizaciones de la versión secundaria, el host ignora propiedades y campos de datos adicionales. Por ejemplo, un dispositivo que utiliza 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 de versiones principales

Se permiten cambios no compatibles con versiones anteriores para cambios en versiones principales. Para admitir múltiples versiones principales para la interoperabilidad con hosts nuevos y antiguos, los dispositivos pueden especificar múltiples colecciones de aplicaciones 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 aplicaciones anunciadas por el dispositivo, examinando su propiedad Descripción del sensor para determinar las versiones de protocolo que implementa cada una y luego seleccionando la última versión del protocolo que admite el host. Cuando se elige, el host funciona con el protocolo único que se eligió durante la vida útil de la conexión del dispositivo.

Apéndice: Ejemplo de un descriptor HID

El siguiente ejemplo ilustra un descriptor HID válido típico. Utiliza las macros C de uso común, que se proporcionan en Usos de sensores 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,
};