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 usando o 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 de 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 mais alto, o dispositivo de rastreamento de cabeça é 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 (inputs) e propriedades (features).
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: Sensor Description (0x0308
)
A propriedade Sensor Description (0x0308
) é uma propriedade de string ASCII (8 bits)
de leitura somente, 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, cada um de 8 bits (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
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 |
Nesse esquema, os primeiros 8 octetos precisam ser 0
, os octetos 8 e 9 precisam conter
os valores ASCII B
e T
, respectivamente, e os 6 octetos seguintes são
interpretados como um endereço MAC Bluetooth, supondo que o dispositivo de rastreamento da cabeça
seja aplicado 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, por um mecanismo não especificado específico do
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 "Nenhum evento" 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 por ele, apenas pelo host.
Propriedade: Intervalo do relatório (0x030E
)
A propriedade Intervalo de relatório (0x030E
) é 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 com que frequência informar 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 de 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 informar as
informações reais de rastreamento de 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,
representando 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 informar as
informações reais de rastreamento de 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]
seja um
vetor de rotação,
que representa a velocidade angular do frame da cabeça (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
de tamanho. 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 maior 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 de relatórios 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 futuras e anteriores
O protocolo HID do monitor 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 usam 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 de 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 baseadas 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 de relatórios. 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 anunciadas pelo dispositivo, examinando a propriedade Sensor Description para determinar as versões do protocolo que cada uma implementa e, em seguida, escolher a versão mais recente do protocolo com suporte ao 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 mais usadas, 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 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,
};