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 Android 13 e versões mais recentes, permite que um dispositivo de monitoramento da posição da cabeça seja conectado a um dispositivo Android via USB ou Bluetooth e exposto ao framework e aos apps Android usando o framework de sensores. Esse protocolo é usado para controlar um efeito de virtualização de áudio (áudio 3D). Nesta página, usamos os termos dispositivo e host no sentido do Bluetooth, em que dispositivo significa o dispositivo de rastreamento da cabeça e host significa o host Android.
Os fabricantes de dispositivos precisam configurar os aparelhos 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 Android identifica o dispositivo de monitor da posição da cabeça como um dispositivo HID.
Para um exemplo completo de um descritor HID válido, consulte Apêndice 1: exemplo de um descritor HID.
No nível superior, o dispositivo de rastreamento da 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 (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 "Descrição do sensor" (0x0308) é uma string ASCII (8 bits) somente leitura que precisa conter os seguintes valores:
Rastreamento da cabeça versão 1.0:
#AndroidHeadTracker#1.0
Rastreamento da cabeça 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
Não é esperado um terminador nulo, 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 Persistent Unique ID (0x0302) é uma matriz somente leitura de 16 elementos, cada um de 8 bits (total de 128 bits). Não é esperado um terminador nulo. 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 a que estão conectados. Os seguintes esquemas são compatíveis.
Rastreador de cabeça independente
Se a propriedade ID exclusivo persistente (0x0302) não existir ou estiver definida como todos os zeros, isso significa que o dispositivo de rastreamento da cabeça não está conectado permanentemente 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 usando 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 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 de cabeça se aplique a qualquer dispositivo de áudio com esse endereço MAC. Esse endereço precisa ser 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 principal de modo
duplo em vez do dispositivo secundário somente LE.
Referência usando UUID
Sempre que o bit mais significativo (MSB) do octeto 8 é definido (≥0x80), o campo é 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 que é específico do tipo de transporte usado.
Propriedade: estado do relatório (0x0316)
A propriedade "Estado do relatório" (0x0316) é de leitura/gravação e tem a semântica padrão definida na especificação HID. O host usa essa propriedade para indicar ao dispositivo quais eventos devem ser informados. Somente os valores "Nenhum evento" (0x0840) e "Todos os eventos" (0x0841) são usados.
O valor inicial desse campo precisa ser "Nenhum evento" e nunca pode ser modificado pelo dispositivo, apenas pelo host.
Propriedade: estado de energia (0x0319)
A propriedade Power State (0x0319) é de leitura/gravação e tem a semântica padrão definida na especificação HID. O host usa essa propriedade para indicar ao dispositivo em qual estado de energia ele precisa estar. Apenas os valores "Potência máxima" (0x0851) e "Desligar" (0x0855) são usados.
O valor inicial desse campo é determinado pelo dispositivo e nunca deve ser modificado por ele, apenas pelo host.
Propriedade: intervalo do relatório (0x030E)
A propriedade "Intervalo de relatório" (0x030E) é de leitura/gravação e tem a semântica padrão definida na especificação HID. O host usa essa propriedade para indicar ao dispositivo com que frequência ele deve 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 atualização de pelo menos 50 Hz, e a taxa máxima recomendada é de 100 Hz. Portanto, o intervalo mínimo de atualização precisa ser menor ou igual a 20 ms e é recomendado que seja maior ou igual a 10 ms.
Propriedade: transporte LE reservado pelo fornecedor (0xF410)
A propriedade de transporte LE reservada pelo fornecedor (0xF410) é de leitura/gravação
e tem a semântica padrão definida na especificação HID. O host
usa essa propriedade para indicar o transporte selecionado (ACL ou ISO). Somente a ACL de valores (0xF800) e ISO (0xF801) são usadas, e ambas precisam ser incluídas 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 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 de 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] é 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 sistema de referência é arbitrário, mas geralmente é fixo e precisa ser destro. Uma pequena quantidade de deriva é aceitável. Os eixos principais 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 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 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, representando a velocidade angular da estrutura da cabeça (relativa a ela mesma).
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 inteiro escalar de 8 bits. Ele precisa ser incrementado (com retorno) pelo dispositivo sempre que o
sistema 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 "physical min", "physical max" e "unit exponent" como zero para esse campo.
Estrutura do relatório
O agrupamento de propriedades em relatórios (por atribuição de IDs de relatório) é 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", "2" e "3" precisam estar no mesmo relatório e em apenas um relatório para um determinado dispositivo (coleta de apps).
Enviar relatórios de entrada
O dispositivo precisa enviar relatórios de entrada periodicamente e de forma assíncrona (por mensagens HID INPUT) quando todas estas 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 é 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 anteriores e futuras
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 da 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.
Para determinar as versões compatíveis com um dispositivo, examine a propriedade
Descrição do sensor (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 outros campos de dados e propriedades. 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, incluindo a 1.5.
Compatibilidade com versões principais
Mudanças não compatíveis com versões anteriores são permitidas para mudanças em versões principais. Para compatibilidade com 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ó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 anunciadas pelo dispositivo, examinando a propriedade "Descrição do sensor" para determinar as versões de protocolo que cada uma implementa e, em seguida, escolher a versão mais recente compatível com o host. Quando escolhido, o host funciona com o único protocolo selecionado 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 comumente usadas, fornecidas em Usos de sensores 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,
};