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