O protocolo de dispositivo de interface humana (HID, na sigla em inglês) do monitor da posição da cabeça do usuário, disponível para dispositivos com o Android 13 e versões mais recentes, permite que um dispositivo de rastreamento da posição da cabeça seja conectado a um dispositivo Android por USB ou Bluetooth e exposto ao framework e aos apps Android pelo framework de sensores. Esse protocolo é usado para controlar um efeito de virtualizador de áudio (áudio 3D). Esta página usa os termos dispositivo e host no sentido de Bluetooth, em que dispositivo significa o dispositivo de rastreamento da cabeça e host significa o host do Android.
Os fabricantes de dispositivos precisam configurar os dispositivos Android para ativar o suporte ao protocolo HID do rastreador de cabeça. Para informações mais detalhadas sobre a configuração, consulte o README dos sensores dinâmicos.
Nesta página, consideramos que você esteja familiarizado com os seguintes recursos:
Estrutura de nível superior
O framework do Android identifica o dispositivo de monitor da posição da cabeça como um dispositivo HID.
Para conferir um exemplo completo de um descritor HID válido, consulte Apêndice 1: exemplo de um descritor HID.
No nível superior, o dispositivo rastreador principal é uma coleção de apps com a
página Sensors
(0x20
) e o uso de Other: Custom
(0xE1
). Dentro dessa
coleção há vários campos de dados (entradas) e propriedades (recursos).
Propriedades e campos de dados
Esta seção descreve as propriedades e os campos de dados em uma coleção de aplicativos de um dispositivo de rastreamento de cabeça.
Propriedade: descrição do sensor (0x0308
)
A propriedade de descrição do sensor (0x0308
) é uma propriedade de string ASCII (8 bits) somente leitura
que precisa conter os seguintes valores:
Head Tracker versão 1.0:
#AndroidHeadTracker#1.0
Head Tracker versão 2.0 (disponível no Android 15 ou mais recente), que inclui suporte para áudio LE:
#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
Nenhum terminador nulo é esperado, o que significa que o tamanho total dessa propriedade é de 23 caracteres de 8 bits para a versão 1.0.
Essa propriedade serve como um discriminador para evitar colisões com outros sensores personalizados.
Propriedade: ID exclusivo persistente (0x0302
)
A propriedade de ID exclusivo persistente (0x0302
) é uma matriz somente leitura de 16 elementos, de 8 bits cada (total de 128 bits). Nenhum terminador nulo é esperado. Essa
propriedade é opcional.
Essa propriedade permite que dispositivos de rastreamento da cabeça integrados a dispositivos de áudio façam referência ao dispositivo de áudio ao qual estão conectados. Os esquemas a seguir são compatíveis.
Rastreador de cabeça independente
Se a propriedade Persistent Unique ID (0x0302
) não existir ou estiver definida como todos
zeros, significa que o dispositivo de rastreamento da cabeça não está permanentemente conectado a um
dispositivo de áudio e pode ser usado separadamente, por exemplo, permitindo que o usuário
associe manualmente o dispositivo de rastreamento da cabeça a um dispositivo de áudio separado.
Referência que usa o endereço MAC do Bluetooth
Octet | 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 |
Nesse esquema, os primeiros 8 octetos precisam ser 0
, os octetos 8 e os 9 precisam conter
os valores ASCII B
e T
, respectivamente, e os seis octetos a seguir são interpretados como um endereço MAC Bluetooth, supondo que o dispositivo de rastreamento principal
se aplique a qualquer dispositivo de áudio que tenha esse endereço MAC. Esse endereço precisa ser o
endereço de identidade, mesmo que o dispositivo use um endereço MAC aleatório para estabelecer
conexões. Dispositivos de modo duplo que se conectam por Bluetooth clássico
(formato HID v1.0) e Bluetooth LE (formato HID v2.0) precisam expor dois descritores
HID com o mesmo endereço de identidade. Dispositivos de modo duplo com dispositivos
esquerdo e direito separados precisam expor o HID Bluetooth LE usando o dispositivo de modo duplo
principal 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
será interpretado como um UUID, conforme especificado na
RFC-4122. O
dispositivo de áudio correspondente fornece o mesmo UUID, que é registrado no
framework do Android, usando um mecanismo não especificado específico para o
tipo de transporte usado.
Propriedade: estado do relatório (0x0316
)
A propriedade "Reporting State" (0x0316
) é uma propriedade de leitura/gravação que tem a
semântica padrão conforme definido na especificação HID. O host usa essa
propriedade para indicar ao dispositivo quais eventos relatar. Somente os valores "No Events" (0x0840
) e "All Events" (0x0841
) são usados.
O valor inicial desse campo precisa ser "Sem eventos" e nunca ser modificado pelo dispositivo, apenas pelo host.
Propriedade: estado de energia (0x0319
)
A propriedade "Estado de energia" (0x0319
) é uma propriedade de leitura/gravação que tem a
semântica padrão conforme definido na especificação HID. O host usa essa
propriedade para indicar ao dispositivo em qual estado de energia ele precisa estar. Somente os
valores "Full Power" (0x0851
) e "Power Off" (0x0855
) são usados.
O valor inicial desse campo é determinado pelo dispositivo e nunca pode 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 com a
semântica padrão, conforme definido na especificação HID. O host usa essa
propriedade para indicar ao dispositivo com que frequência relata as leituras de dados.
As unidades são informadas em segundos. O intervalo válido para esse valor é determinado pelo dispositivo
e descrito usando o mecanismo mínimo/máximo físico. É necessário oferecer suporte a uma taxa de relatório de pelo menos 50 Hz, e a taxa máxima recomendada é de 100 Hz. Portanto, o intervalo mínimo de relatório precisa ser menor ou igual a 20 ms, e é recomendável que seja maior ou igual a 10 ms.
Propriedade: transporte LE reservado pelo fornecedor (0xF410
)
A propriedade de transporte LE reservada pelo fornecedor (0xF410
) é uma propriedade de leitura/gravação
que tem a semântica padrão conforme definido na especificação HID. O host
usa essa propriedade para indicar o transporte selecionado (ACL ou ISO). Somente os
valores ACL (0xF800
) e ISO (0xF801
) são usados, e ambos precisam ser incluídos
na coleção lógica.
Essa propriedade é configurada antes dos estados de energia ou de geração de relatórios.
Campo de dados: valor personalizado 1 (0x0544
)
O campo "Valor personalizado 1" (0x0544
) é um campo de entrada usado para relatar as
informações reais de rastreamento da cabeça. É uma matriz de três elementos, interpretada de acordo
com as regras normais de HID para valores físicos, conforme especificado na seção 6.2.2.7 da
especificação HID. O intervalo válido para cada elemento é [-π, π] rad. As unidades são sempre radianos.
Os elementos são interpretados como: [rx, ry, rz]
, de modo que [rx, ry, rz]
seja um
vetor de rotação,
que representa a transformação do frame de referência para o frame da cabeça.
A magnitude precisa estar no intervalo [0..π].
O frame de referência é arbitrário, mas geralmente é fixo e precisa ser direito. Uma pequena quantidade de deslocamento é aceitável. Os eixos da cabeça são:
- X do ouvido esquerdo para o direito
- 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 relatar as
informações reais de rastreamento da cabeça. É uma matriz de ponto fixo de três elementos,
interpretada 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]
é um
vetor de rotação,
que representa a velocidade angular do frame principal (em relação a si mesmo).
Campo de dados: valor personalizado 3 (0x0546
)
O campo "Valor personalizado 3" (0x0546
) é um campo de entrada usado para rastrear descontinuidades no frame de referência. É um número inteiro escalar de 8 bits. Ele precisa ser incrementado (com o recurso de wraparound) pelo dispositivo sempre que o
frame de referência for alterado, por exemplo, se um algoritmo de filtro de orientação
usado para determinar a orientação tiver o estado redefinido. 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. A única informação relevante para o 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 os
valores de mínimo físico, máximo físico e expoente de unidade como zero para esse campo.
Estrutura do relatório
O agrupamento de propriedades em relatórios (por atribuição de IDs de relatórios) é flexível. Para eficiência, recomendamos separar as propriedades somente leitura das propriedades de leitura/gravação.
Para os campos de dados, os campos "Valor personalizado 1", "Valor personalizado 2" e "Valor personalizado 3" precisam estar no mesmo relatório e em apenas um relatório para um determinado dispositivo (coleção de apps).
Enviar relatórios de entrada
O dispositivo precisa enviar relatórios de entrada de forma periódica e assíncrona (por mensagens HID INPUT) quando todas essas condições forem atendidas:
- A propriedade "Estado de energia" está definida como "Potência total".
- A propriedade "Estado do relatório" está definida como "Todos os eventos".
- A propriedade "Intervalo de relatórios" não é igual a 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 futuras
O protocolo HID do rastreador de posições da cabeça usa um esquema de controle de versões que permite atualizações, além de permitir 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, principal e secundário, que têm semânticas distintas, conforme descrito nas seções a seguir.
As versões com suporte a um dispositivo podem ser determinadas examinando
a propriedade Sensor Description (0x0308
).
Compatibilidade com versões secundárias
As mudanças na versão secundária são compatíveis com versões secundárias anteriores com base na mesma versão principal. Nas atualizações da versão secundária, 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 à versão 1.x do protocolo, incluindo a versão 1.5.
Compatibilidade com a versão principal
Mudanças não compatíveis com versões anteriores são permitidas para mudanças em 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 nos descritores do relatório. 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 divulgadas pelo dispositivo, examinando a propriedade "Sensor Description" para determinar as versões de protocolo que cada uma implementa e escolhendo a versão mais recente do protocolo compatível com o host. Quando escolhido, o host funciona com o único protocolo escolhido para o ciclo de vida da conexão do dispositivo.
Apêndice: exemplo de um descritor HID
O exemplo a seguir ilustra um descritor HID válido típico. Ele usa as macros C usadas com frequência, fornecidas em 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 que oferece suporte apenas ao transporte de ACL 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,
};