Protocolo HID para seguimiento de cabeza

El protocolo de dispositivo de interfaz humana (HID) para seguimiento de cabeza, disponible para dispositivos con Android 13 y versiones posteriores, permite una dispositivo de seguimiento de cabeza para que se conecte a un dispositivo Android mediante USB o Bluetooth y conéctate al framework y a las apps de Android a través de la sensors. Este protocolo se usa para controlar 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 device se refiere al dispositivo de seguimiento de 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 configuración, consulta la Archivos dinámicos README.

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 ver un ejemplo completo de un descriptor HID válido, consulta 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 el siguiente valor:

#AndroidHeadTracker#1.0

No se espera que termine el valor nulo, lo que significa que el tamaño total de esta propiedad es de 23 caracteres de 8 bits.

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 de 8 bits cada uno (128 bits en total). No se espera un terminador nulo. Esta es opcional.

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

Monitor de cabeza independiente

Si la propiedad de ID único persistente (0x0302) no existe o se establece en toda ceros, significa que el dispositivo de seguimiento de cabeza no está conectado permanentemente a una de audio y se pueden usar de forma independiente, por ejemplo, permitiendo que el usuario asociar manualmente el dispositivo de seguimiento de cabeza con otro dispositivo de audio.

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 MAC de Bluetooth

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.

Referencia con UUID

Cuando se establece el bit más significativo (MSB) del octeto 8 (≥0x80), el campo se interpreta como un UUID, según 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 para indicar 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 ser modificado por el dispositivo, solo por el host.

Propiedad: Intervalo de informes (0x030E)

La propiedad Report Interval (0x030E) es una propiedad de lectura/escritura que tiene el semántica estándar, como se define en la especificación HID. El host usa para indicar al dispositivo con qué frecuencia debe informar las lecturas de los 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.

Campo de datos: valor personalizado 1 (0x0544)

El campo Valor personalizado 1 (0x0544) 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 que se interpreta de acuerdo a 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. 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 dentro del rango [0..π].

El marco de referencia es arbitrario, pero generalmente es fijo y debe ser para diestros. Se acepta una pequeña cantidad de desvío. 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 mientras conviertes de unidades lógicas a físicas, se recomienda establecer la valores para el mínimo físico, el máximo físico y el exponente unitario en cero en 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 de forma periódica y asíncrona (a través de mensajes HID INPUT). enviar informes de entrada 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 de intervalo de informes no es 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 admitidas por un dispositivo, puedes examinar su propiedad de descripción del sensor (0x0308).

Compatibilidad con versiones secundarias

Los cambios en la versión secundaria son retrocompatibles con los anteriores que se basan en la misma versión principal. En actualizaciones del menor , el host ignora los campos de datos y propiedades 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 su informe. descriptores de archivo. 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 ilustra un descriptor HID válido típico. Utiliza el las macros de C de uso general, proporcionadas 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,
};