Protocolo HID do rastreador de posições da cabeça

Protocolo de dispositivo de interface humana (HID, na sigla em inglês) do monitor de posições da cabeça, disponível para dispositivos com o Android 13 e versões mais recentes, um dispositivo de rastreamento de cabeça seja conectado a um dispositivo Android por USB ou Bluetooth e ser exposto ao framework e aos apps do Android por meio do de sensores. Esse protocolo é usado para controlando um efeito de virtualizador de áudio (áudio 3D). Esta página usa os termos dispositivo e host no sentido de Bluetooth, em que device significa o dispositivo de rastreamento da cabeça e host significa o host do Android.

Os fabricantes de dispositivos precisam configurar seus dispositivos Android para ativar o suporte para protocolo HID do monitor de posições da cabeça. Para informações mais detalhadas sobre do Terraform, consulte a README de sensores dinâmicos (link em inglês).

Para acompanhar esta página, você precisa estar familiarizado com os seguintes recursos:

Estrutura de nível superior

O framework do Android identifica o rastreador de posições da cabeça como um dispositivo HID.

Para ver um exemplo completo de um descritor HID válido, consulte Apêndice 1: exemplo de um descritor HID

No nível superior, o rastreador da cabeça é uma coleção de aplicativos com o Sensors página (0x20) e o uso de Other: Custom (0xE1). Dentro são diversos campos de dados (entradas) e propriedades (recursos).

Propriedades e campos de dados

Esta seção descreve as propriedades e os campos de dados em um aplicativo de um rastreador de posições da cabeça.

Propriedade: descrição do sensor (0x0308)

A propriedade de descrição do sensor (0x0308) é uma string ASCII somente leitura (8 bits) , que precisa conter os seguintes valores:

Versão 1.0 do monitor de posições da cabeça:

#AndroidHeadTracker#1.0

Versão 2.0 do monitor de posições da cabeça (disponível no Android 15 ou superior), o que inclui compatibilidade com LE Audio:

#AndroidHeadTracker#2.0#x

O x é um número inteiro (1, 2, 3) que indica o transporte de suporte:

  • 1: ACL
  • 2: ISO
  • 3: ACL + ISO

Não é esperado um "null-terminator", o que significa que o tamanho total dessa propriedade tem 23 caracteres de 8 bits para a versão 1.0.

Essa propriedade serve como um discriminador para evitar colisões com outros com sensores personalizados.

Propriedade: ID exclusivo persistente (0x0302)

A propriedade do ID exclusivo permanente (0x0302) é uma matriz somente leitura de 16 , 8 bits cada (total de 128 bits). Nenhum terminador nulo é esperado. Isso é opcional.

Essa propriedade permite dispositivos de rastreamento da cabeça integrados em áudio para fazer referência ao dispositivo de áudio ao qual estão conectados. Há suporte para os esquemas a seguir.

Rastreador de cabeça independente

Se a propriedade de ID exclusivo persistente (0x0302) não existir ou estiver definida como "todos" zeros, isso significa que o rastreador da cabeça não está permanentemente conectado a um dispositivo de áudio e podem ser usados separadamente, por exemplo, permitindo que o usuário associar manualmente o tracker principal a um dispositivo de áudio separado.

Referência usando endereço MAC do 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 do Bluetooth

Neste esquema, os primeiros 8 octetos precisam ser 0, e os octetos 8 e 9 precisam conter os valores ASCII B e T respectivamente e os seis octetos a seguir são interpretado como um endereço MAC Bluetooth, supondo que o rastreador principal se aplica a qualquer dispositivo de áudio que tenha esse endereço MAC. Esse endereço precisa ser endereço MAC aleatório, mesmo se o dispositivo usar um endereço MAC aleatório para estabelecer conexões de rede. Dispositivos dual modo conectados por Bluetooth clássico (formato HID v1.0) e Bluetooth LE (formato HID v2.0) precisam expor dois HID descritores com o mesmo endereço de identidade. Dispositivos de modo birregional com controles separados os dispositivos esquerdo e direito precisam expor o Bluetooth LE HID usando o dispositivo duplo em vez do dispositivo secundário somente LE.

Referência usando UUID

Sempre que o bit mais significativo (MSB) do octeto 8 for definido (≥0x80), o campo é interpretado como um UUID, conforme especificado em RFC-4122. A dispositivo de áudio correspondente fornece o mesmo UUID, que é registrado no framework do Android, por meio de um mecanismo não especificado que é específico da tipo de transporte usado.

Propriedade: estado do relatório (0x0316)

O estado do relatório (0x0316) é uma propriedade de leitura/gravação que tem o semântica padrão, conforme definido na especificação HID. O host usa este para indicar ao dispositivo quais eventos serão relatados. Somente os valores Não Os eventos (0x0840) e "Todos os eventos" (0x0841) são usados.

O valor inicial desse campo precisa ser "No Events" e nunca deve ser modificado pelo dispositivo, apenas pelo host.

Propriedade: estado da energia (0x0319)

A propriedade Estado de potência (0x0319) é uma propriedade de leitura/gravação que tem o semântica padrão, conforme definido na especificação HID. O host usa este para indicar ao dispositivo em qual estado de energia ele deve estar. Somente o Os valores Full Power (0x0851) e Power Off (0x0855) são usados.

O valor inicial deste campo é determinado pelo dispositivo e nunca deve ser modificado pelo dispositivo, apenas pelo host.

Propriedade: intervalo do relatório (0x030E)

A propriedade Intervalo do relatório (0x030E) é uma propriedade de leitura/gravação que tem o semântica padrão, conforme definido na especificação HID. O host usa este para indicar ao dispositivo com que frequência informar as leituras de dados. As unidades são informadas em segundos. O intervalo válido para este valor é determinado pelo dispositivo e são descritos usando o mecanismo Mín./Máx. físico. Pelo menos 50 Hz deve ser suportada, e a taxa máxima recomendada de relatórios é 100 Hz. Portanto, o intervalo mínimo do relatório precisa ser menor ou igual a 20 ms e recomendamos que seja maior ou igual a 10 ms.

Propriedade: transporte LE reservado pelo fornecedor (0xF410)

A propriedade do LE Transport reservada pelo fornecedor (0xF410) é uma propriedade de leitura/gravação que tem a semântica padrão, conforme definido na especificação HID. O organizador usa essa propriedade para indicar o transporte selecionado (ACL ou ISO). Somente o de valores ACL (0xF800) e ISO (0xF801) são usados, e ambos devem ser incluídos na coleção lógica.

Essa propriedade é configurada antes dos estados de alimentação ou do relatório.

Campo de dados: valor personalizado 1 (0x0544)

O campo "Valor personalizado 1" (0x0544) é um campo de entrada usado para informar o informações reais de rastreamento da cabeça. É uma matriz de 3 elementos, interpretada de acordo às regras HID normais para valores físicos, conforme especificado na seção 6.2.2.7 do a especificação HID. O intervalo válido para cada elemento é [-π, π] rad. Unidades são sempre radianos.

Os elementos são interpretados como: [rx, ry, rz], de modo que [rx, ry, rz] é uma vetor de rotação, que representa a transformação do frame de referência para o frame principal. A magnitude precisa estar no intervalo [0..π].

O frame de referência é arbitrário, mas geralmente é fixo e precisa ser destro. Uma pequena quantidade de deslocamento é aceitável. Os eixos da cabeça são:

  • X da orelha esquerda para a direita
  • Y da parte de trás da cabeça até o nariz (de trás para a frente)
  • Z do pescoço até o topo da cabeça

Campo de dados: valor personalizado 2 (0x0545)

O campo "Valor personalizado 2" (0x0545) é um campo de entrada usado para informar o informações reais de rastreamento da cabeça. É uma matriz de ponto fixo de três elementos, interpretado de acordo com as regras normais de HID para valores físicos. As unidades são sempre radianos/segundo.

Os elementos são interpretados como: [vx, vy, vz], de modo que [vx, vy, vz] é uma vetor de rotação, que representa a velocidade angular do frame da cabeça (em relação a si mesma).

Campo de dados: valor personalizado 3 (0x0546)

O campo "Valor personalizado 3" (0x0546) é um campo de entrada usado para rastreamento descontinuidades no frame de referência. É um número inteiro escalar de 8 bits tamanho. Deve ser incrementado (com encapsulamento) pelo dispositivo sempre que o o frame de referência for alterado, por exemplo, se um algoritmo de filtro de orientação for alterado usada para determinar se a orientação foi redefinida. Esse valor é interpretado de acordo com as regras normais de HID para valores físicos. No entanto, o valor físico e as unidades não importam. As únicas informações relevantes para host é um valor alterado. Para evitar problemas numéricos relacionados à perda de precisão. ao converter de unidades lógicas para físicas, é recomendável definir valores para mínimo físico, máximo físico e expoente da unidade a zero neste campo.

Estrutura do relatório

O agrupamento de propriedades em relatórios (por atribuição dos IDs de relatório) é flexível. Para aumentar a eficiência, recomendamos separar as propriedades somente leitura das propriedades de leitura/gravação.

Para os campos de dados, os campos do valor personalizado 1, 2 e 3 devem estar no mesmo e estar em apenas um relatório para um determinado dispositivo (coleção de apps).

Enviar relatórios de entrada

O dispositivo precisa periodicamente e de modo assíncrono (por mensagens HID INPUT) enviar relatórios de entrada quando todas estas condições forem atendidas:

  • A propriedade Estado de potência está definida como Potência total.
  • A propriedade "Estado do relatório" está definida como "Todos os eventos".
  • A propriedade Intervalo do relatório é diferente de zero.

A propriedade "Intervalo do relatório" determina a frequência de envio dos relatórios. Quando qualquer uma das condições acima não for atendida, o dispositivo não poderá enviar relatórios.

Compatibilidade com versões anteriores e anteriores

O protocolo HID do monitor de posições da cabeça usa um esquema de controle de versão que permite do Google, permitindo a interoperabilidade entre um host e um dispositivo que usa versões diferentes do protocolo. As versões do protocolo são identificadas por dois números, maior e menor, que têm semânticas distintas como descritos nas seções a seguir.

As versões com suporte em um dispositivo podem ser determinadas examinando-se a propriedade "Descrição do sensor" (0x0308).

Compatibilidade de versão secundária

As mudanças à versão secundária são compatíveis com versões anteriores. com base na mesma versão principal. Em atualizações para o item menor versão, o host ignora campos e propriedades de dados adicionais. Por exemplo: um dispositivo que usa a versão 1.6 do protocolo é compatível com um host que oferece suporte a versão 1.x, incluindo a versão 1.5.

Compatibilidade da versão principal

Alterações não compatíveis com versões anteriores são permitidas para alterações nas versões principais. Para oferecer suporte a várias versões principais para interoperabilidade com hosts antigos e novos, os dispositivos podem especificar várias coleções de apps no relatório descritores. Exemplo:

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

Nesse caso, o host pode enumerar todas as diferentes coleções de apps anunciada pelo dispositivo, examinando a propriedade "Descrição do sensor" para determinar as versões de protocolo que cada uma implementa e escolher as versão mais recente do protocolo compatível com o host. Quando escolhido, o host funciona com o protocolo único escolhido para o ciclo de vida do dispositivo. uma conexão com a Internet.

Apêndice: exemplo de um descritor HID

O exemplo a seguir ilustra um descritor HID válido típico. Ele usa o as macros C mais usadas, fornecidas nas Usos do sensor HID (seção 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: exemplo de um descritor HID v2.0

O exemplo a seguir ilustra um descritor HID v2.0 para um dispositivo compatível com apenas o transporte 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,
};