Protocollo HID del tracker per la testa

Il protocollo Human Interface Device (HID) per il rilevamento della postura della testa, disponibile per i dispositivi con Android 13 e versioni successive, consente di collegare un dispositivo di rilevamento della postura della testa a un dispositivo Android tramite USB o Bluetooth ed esporlo al framework e alle app Android tramite il framework Sensori. Questo protocollo viene utilizzato per controllare un effetto di virtualizzazione audio (audio 3D). Questa pagina utilizza i termini dispositivo e host nel loro significato Bluetooth, dove dispositivo indica il dispositivo di monitoraggio della testa e host indica l'host Android.

I produttori di dispositivi devono configurare i propri dispositivi Android per attivare il supporto del protocollo HID per il rilevamento della testa. Per informazioni più dettagliate sulla configurazione, consulta il file README di Dynamic Sensors.

Questa pagina presuppone la familiarità con le seguenti risorse:

Struttura di primo livello

Il framework Android identifica il dispositivo di monitoraggio della testa come dispositivo HID.

Per un esempio completo di un descrittore HID valido, consulta Appendice 1: Esempio di descrittore HID.

Al livello superiore, il dispositivo di monitoraggio della testa è una raccolta di app con la pagina Sensors (0x20) e l'utilizzo di Other: Custom (0xE1). All'interno di questa raccolta si trovano diversi campi di dati (input) e proprietà (funzionalità).

Proprietà e campi di dati

Questa sezione descrive le proprietà e i campi di dati in una raccolta di applicazioni di un dispositivo di monitoraggio della testa.

Proprietà: Descrizione sensore (0x0308)

La proprietà Descrizione sensore (0x0308) è una stringa ASCII (8 bit) di sola lettura che deve contenere i seguenti valori:

Head tracker versione 1.0:

#AndroidHeadTracker#1.0

Head Tracker versione 2.0 (disponibile in Android 15 o versioni successive), che include il supporto di LE Audio:

#AndroidHeadTracker#2.0#x

x è un numero intero (1, 2, 3) che indica il trasporto di supporto:

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

Non è previsto alcun carattere di terminazione null, il che significa che la dimensione totale di questa proprietà è di 23 caratteri a 8 bit per la versione 1.0.

Questa proprietà funge da discriminatore per evitare conflitti con altri sensori personalizzati.

Proprietà: ID univoco persistente (0x0302)

La proprietà ID univoco persistente (0x0302) è un array di 16 elementi di sola lettura, ciascuno di 8 bit (totale 128 bit). Non è previsto alcun terminatore nullo. Questa proprietà è facoltativa.

Questa proprietà consente ai dispositivi di monitoraggio della testa integrati nei dispositivi audio di fare riferimento al dispositivo audio a cui sono collegati. Sono supportati i seguenti schemi.

Tracker della testa autonomo

Se la proprietà ID univoco persistente (0x0302) non esiste o è impostata su tutti zeri, significa che il dispositivo di monitoraggio della testa non è collegato in modo permanente a un dispositivo audio e può essere utilizzato separatamente, ad esempio consentendo all'utente di associare manualmente il dispositivo di monitoraggio della testa a un dispositivo audio separato.

Riferimento tramite l'indirizzo MAC Bluetooth

Ottetto 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Valore 0 0 0 0 0 0 0 0 B T MAC Bluetooth

In questo schema, i primi 8 ottetti devono essere 0, gli ottetti 8 e 9 devono contenere i valori ASCII B e T rispettivamente e i 6 ottetti successivi sono interpretati come un indirizzo MAC Bluetooth, supponendo che il dispositivo di monitoraggio della testa si applichi a qualsiasi dispositivo audio con questo indirizzo MAC. Questo indirizzo deve essere l'indirizzo di identità, anche se il dispositivo utilizza un indirizzo MAC casuale per stabilire le connessioni. I dispositivi dual-mode che si connettono tramite Bluetooth classico (formato HID v1.0) e Bluetooth LE (formato HID v2.0) devono esporre due descrittori HID con lo stesso indirizzo di identità. I dispositivi dual-mode con dispositivi sinistro e destro separati devono esporre HID Bluetooth LE utilizzando il dispositivo dual-mode principale anziché il dispositivo secondario solo LE.

Riferimento tramite UUID

Ogni volta che viene impostato il bit più significativo (MSB) dell'ottetto 8 (≥0x80), il campo viene interpretato come un UUID, come specificato in RFC-4122. Il dispositivo audio corrispondente fornisce lo stesso UUID, registrato nel framework Android, tramite un meccanismo non specificato specifico per il tipo di trasporto utilizzato.

Proprietà: stato del report (0x0316)

La proprietà Reporting State (0x0316) è una proprietà di lettura/scrittura che ha la semantica standard definita nella specifica HID. L'host utilizza questa proprietà per indicare al dispositivo quali eventi segnalare. Vengono utilizzati solo i valori Nessun evento (0x0840) e Tutti gli eventi (0x0841).

Il valore iniziale di questo campo deve essere Nessun evento e non deve mai essere modificato dal dispositivo, ma solo dall'host.

Proprietà: Stato alimentazione (0x0319)

La proprietà Power State (0x0319) è una proprietà di lettura/scrittura che ha la semantica standard definita nella specifica HID. L'host utilizza questa proprietà per indicare al dispositivo in quale stato di alimentazione deve trovarsi. Vengono utilizzati solo i valori Potenza massima (0x0851) e Spegnimento (0x0855).

Il valore iniziale di questo campo è determinato dal dispositivo e non deve mai essere modificato dal dispositivo, ma solo dall'host.

Proprietà: intervallo report (0x030E)

La proprietà Report Interval (0x030E) è una proprietà di lettura/scrittura che ha la semantica standard definita nella specifica HID. L'host utilizza questa proprietà per indicare al dispositivo la frequenza con cui deve segnalare le letture dei dati. Le unità sono in secondi. L'intervallo valido per questo valore è determinato dal dispositivo e descritto utilizzando il meccanismo Min/Max fisico. Deve essere supportata una frequenza di segnalazione di almeno 50 Hz e la frequenza di segnalazione massima consigliata è 100 Hz. Pertanto, l'intervallo di segnalazione minimo deve essere inferiore o uguale a 20 ms ed è consigliabile che sia maggiore o uguale a 10 ms.

Proprietà: Vendor-reserved LE Transport (0xF410)

La proprietà Vendor-reserved LE Transport (0xF410) è una proprietà di lettura/scrittura che ha la semantica standard definita nella specifica HID. L'host utilizza questa proprietà per indicare il trasporto selezionato (ACL o ISO). Vengono utilizzati solo i valori ACL (0xF800) e ISO (0xF801) ed entrambi devono essere inclusi nella raccolta logica.

Questa proprietà è configurata prima degli stati di alimentazione o dei report.

Campo dati: Valore personalizzato 1 (0x0544)

Il campo Valore personalizzato 1 (0x0544) è un campo di input utilizzato per generare report sulle informazioni effettive sul monitoraggio della testa. È un array di tre elementi, interpretato in base alle normali regole HID per i valori fisici specificate nella sezione 6.2.2.7 della specifica HID. L'intervallo valido per ogni elemento è [-π, π] rad. Le unità sono sempre radianti.

Gli elementi vengono interpretati come: [rx, ry, rz], in modo che [rx, ry, rz] sia un vettore di rotazione, che rappresenta la trasformazione dal sistema di riferimento al sistema di riferimento della testa. La magnitudo deve essere compresa nell'intervallo [0..π].

Il sistema di riferimento è arbitrario, ma in genere è fisso e deve essere destro. È accettabile una piccola quantità di deriva. Gli assi della testa sono:

  • X dall'orecchio sinistro a quello destro
  • Y dalla parte posteriore della testa al naso (da dietro a davanti)
  • Z dal collo alla sommità della testa

Campo dati: Valore personalizzato 2 (0x0545)

Il campo Valore personalizzato 2 (0x0545) è un campo di input utilizzato per segnalare le informazioni effettive sul monitoraggio della testa. È un array a virgola fissa di tre elementi, interpretato in base alle normali regole HID per i valori fisici. Le unità sono sempre radianti al secondo.

Gli elementi vengono interpretati come: [vx, vy, vz], in modo che [vx, vy, vz] sia un vettore di rotazione, che rappresenta la velocità angolare del frame della testa (rispetto a se stesso).

Campo dati: Valore personalizzato 3 (0x0546)

Il campo Valore personalizzato 3 (0x0546) è un campo di input utilizzato per il monitoraggio delle discontinuità nel sistema di riferimento. È un numero intero scalare a 8 bit. Deve essere incrementato (con wraparound) dal dispositivo ogni volta che viene modificato il sistema di riferimento, ad esempio se lo stato di un algoritmo di filtro dell'orientamento utilizzato per determinare l'orientamento è stato reimpostato. Questo valore viene interpretato in base alle normali regole HID per i valori fisici. Tuttavia, il valore fisico e le unità non sono importanti. L'unica informazione pertinente per l'host è un valore modificato. Per evitare problemi numerici relativi alla perdita di precisione durante la conversione da unità logiche a fisiche, è consigliabile impostare i valori di min fisico, max fisico ed esponente unità su zero per questo campo.

Struttura del report

Il raggruppamento delle proprietà nei report (tramite l'assegnazione degli ID report) è flessibile. Per efficienza, ti consigliamo di separare le proprietà di sola lettura da quelle di lettura/scrittura.

Per i campi di dati, i campi Valore personalizzato 1, 2 e 3 devono trovarsi nello stesso report e in un solo report per un determinato dispositivo (raccolta di app).

Inviare report sugli input

Il dispositivo deve inviare periodicamente e in modo asincrono (tramite messaggi HID INPUT) report di input quando tutte queste condizioni sono soddisfatte:

  • La proprietà Stato di alimentazione è impostata su Alimentazione completa.
  • La proprietà Stato dei report è impostata su Tutti gli eventi.
  • La proprietà Intervallo di reporting è diversa da zero.

La proprietà Intervallo di generazione dei report determina la frequenza di invio dei report. Quando una delle condizioni sopra indicate non viene soddisfatta, il dispositivo non deve inviare alcun report.

Compatibilità con le versioni precedenti e successive

Il protocollo HID del rilevamento della testa utilizza uno schema di controllo delle versioni che consente gli aggiornamenti, garantendo al contempo l'interoperabilità tra un host e un dispositivo che utilizzano versioni diverse del protocollo. Le versioni del protocollo sono identificate da due numeri, principale e secondario, che hanno semantiche distinte come descritto nelle sezioni seguenti.

Le versioni supportate da un dispositivo possono essere determinate esaminando la proprietà Descrizione sensore (0x0308).

Compatibilità con la versione secondaria

Le modifiche alla versione secondaria sono compatibili con le versioni secondarie precedenti basate sulla stessa versione principale. Negli aggiornamenti alla versione secondaria, l'host ignora i campi e le proprietà di dati aggiuntivi. Ad esempio, un dispositivo che utilizza la versione 1.6 del protocollo è compatibile con un host che supporta la versione 1.x del protocollo, inclusa la versione 1.5.

Compatibilità con la versione principale

Sono consentite modifiche non compatibili con le versioni precedenti per le modifiche alle versioni principali. Per supportare più versioni principali per l'interoperabilità con host vecchi e nuovi, i dispositivi possono specificare più raccolte di app nei descrittori dei report. Ad esempio:

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

In questo caso, l'host può enumerare tutte le diverse raccolte di app pubblicizzate dal dispositivo, esaminando la proprietà Descrizione sensore per determinare le versioni del protocollo implementate da ciascuna, quindi scegliere la versione del protocollo più recente supportata dall'host. Se selezionato, l'host funziona con il singolo protocollo scelto per la durata della connessione del dispositivo.

Appendice: esempio di descrittore HID

L'esempio seguente illustra un tipico descrittore HID valido. Utilizza le macro C comunemente usate, fornite in Utilizzi dei sensori HID (sezione 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,
};

Appendice 2: Esempio di descrittore HID v2.0

L'esempio seguente illustra un descrittore HID v2.0 per un dispositivo che supporta solo il trasporto 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,
};