Protocole HID du coach électronique

Le protocole HID (Human Interface Device) du coach électronique, disponible pour les appareils. exécutant Android 13 ou une version ultérieure, de suivi de la tête doit être connecté à un appareil Android via USB ou Bluetooth et être exposé au framework et aux applications Android via le sensors. Ce protocole est utilisé pour contrôler un effet de virtualisation audio (audio 3D). Cette page utilise les termes appareil et host dans son sens du Bluetooth, où device désigne l'appareil qui suit les mouvements de la tête et hôte désigne l'hôte Android.

Les fabricants d'appareils doivent configurer leurs appareils Android de façon à activer la prise en charge de le protocole HID du coach électronique. Pour en savoir plus sur consultez la documentation Fichier README des capteurs dynamiques.

Cette page suppose que vous connaissez les ressources suivantes:

Structure de premier niveau

Le framework Android identifie l'appareil de suivi des mouvements de la tête en tant que dispositif HID.

Pour obtenir un exemple complet de descripteur HID valide, consultez Annexe 1: Exemple de descripteur HID

Au niveau de premier niveau, le moniteur d'activité physique est une collection d'applications contenant le Sensors (0x20) et l'utilisation de Other: Custom (0xE1). Au cœur de ce collection sont constitués de plusieurs champs de données (entrées) et propriétés (caractéristiques).

Propriétés et champs de données

Cette section décrit les propriétés et les champs de données d'une application. ensemble d'un système de suivi des mouvements de la tête.

Propriété: description du capteur (0x0308)

La propriété de description du capteur (0x0308) est une chaîne ASCII (8 bits) en lecture seule. qui doit contenir les valeurs suivantes:

Head Tracker version 1.0:

#AndroidHeadTracker#1.0

Coach électronique version 2.0 (disponible sous Android 15 ou supérieure), ce qui inclut la prise en charge de LE Audio:

#AndroidHeadTracker#2.0#x

x est un entier (1, 2, 3) indiquant le transport accepté:

  • 1: LCA
  • 2: ISO
  • 3: LCA + ISO

Aucun opérateur de valeur nulle n'est attendu, ce qui signifie que la taille totale de cette propriété est de 23 caractères 8 bits pour la version 1.0.

Cette propriété sert de discriminateur pour éviter les collisions avec d’autres des capteurs personnalisés.

Propriété: ID unique persistant (0x0302)

La propriété d'ID unique persistant (0x0302) est un tableau en lecture seule de 16 éléments, 8 bits chacun (128 bits au total). Aucun terminaison nulle n'est attendu. Ce est facultative.

Cette propriété autorise les appareils avec suivi de la tête intégrés à l'audio périphériques pour référencer l'appareil audio auquel ils sont connectés. Les schémas suivants sont acceptés.

Moniteur de tête autonome

Si la propriété d'ID unique persistant (0x0302) n'existe pas ou qu'elle est définie sur zéros, cela signifie que le coach électronique n'est pas fixé en permanence sur un et peuvent être utilisées séparément, par exemple, en laissant associer manuellement le coach électronique à un autre appareil audio.

Référence utilisant une adresse MAC Bluetooth

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

Dans ce schéma, les 8 premiers octets doivent être 0, les octets 8 et 9 doivent contenir les valeurs ASCII B et T respectivement, et les 6 octets suivants sont respectivement interprétée comme une adresse MAC Bluetooth, en supposant que le coach électronique s’applique à tout appareil audio ayant cette adresse MAC. Il doit s'agir de d'identité, même si l'appareil utilise une adresse MAC aléatoire pour établir connexions externes. Appareils double mode se connectant via le Bluetooth classique (format HID v1.0) et Bluetooth LE (format HID v2.0) doivent exposer deux appareils de descripteurs avec la même adresse d'identité. Les appareils bi-modes avec des les appareils gauche et droit doivent exposer Bluetooth LE HID à l'aide de l'appareil au lieu de l'appareil secondaire à LE uniquement.

Référence utilisant un UUID

Chaque fois que le bit le plus significatif (MSB) de l'octet 8 est défini (≥0x80), le champ est interprété comme un UUID, comme spécifié dans RFC-4122 La l'appareil audio correspondant fournit le même UUID, qui est enregistré sur le framework Android, par le biais d'un mécanisme non spécifié propre à la le type de transport utilisé.

Propriété: état des rapports (0x0316)

La propriété d'état des rapports (0x0316) est une propriété en lecture/écriture qui possède le paramètre comme définie dans la spécification HID. L'hôte utilise cette pour indiquer à l'appareil les événements à signaler. Seules les valeurs Non Les options "Événements" (0x0840) et "Tous les événements" (0x0841) sont utilisées.

La valeur initiale de ce champ doit être "Aucun événement" et ne doit jamais être modifiée par l'appareil, uniquement par l'hôte.

Propriété: état de l'alimentation (0x0319)

La propriété "Power State" (0x0319) est une propriété en lecture/écriture qui possède le paramètre comme définie dans la spécification HID. L'hôte utilise cette pour indiquer à l'appareil dans quel état d'alimentation il doit se trouver. Seuls les les valeurs Pleine puissance (0x0851) et Éteindre (0x0855) sont utilisées.

La valeur initiale de ce champ est déterminée par l'appareil et ne doit jamais être modifiée par l'appareil, uniquement par l'hôte.

Propriété: intervalle du rapport (0x030E)

La propriété "Intervalle entre les rapports" (0x030E) est une propriété en lecture/écriture qui possède le paramètre comme définie dans la spécification HID. L'hôte utilise cette pour indiquer à l'appareil la fréquence à laquelle il doit consigner ses lectures de données. Les unités sont exprimées en secondes. La plage valide pour cette valeur est déterminée par l'appareil et décrit à l'aide du mécanisme de minimum/max. physique. Au moins 50 Hz le taux de signalement doit être accepté, et le taux de signalement maximal recommandé est 100 Hz Par conséquent, l'intervalle minimal entre les rapports doit être inférieur ou égal à 20 ms. Nous vous recommandons de définir une valeur supérieure ou égale à 10 ms.

Propriété: LE Transport réservé par le fournisseur (0xF410)

La propriété LE Transport réservée par le fournisseur (0xF410) est une propriété en lecture/écriture. qui possède la sémantique standard telle que définie dans la spécification HID. L'organisateur utilise cette propriété pour indiquer le transport sélectionné (LCA ou ISO). Seuls les les valeurs LCA (0xF800) et ISO (0xF801) sont utilisées, et doivent toutes les deux être incluses dans la collection logique.

Cette propriété est configurée avant l'activation de l'alimentation ou l'activation des rapports.

Champ de données: valeur personnalisée 1 (0x0544)

Le champ "Valeur personnalisée 1" (0x0544) est un champ de saisie utilisé pour signaler le des informations réelles de suivi de la tête. Il s'agit d'un tableau à 3 éléments, interprété selon aux règles HID normales pour les valeurs physiques, comme spécifié dans la section 6.2.2.7 de la spécification HID. La plage valide pour chaque élément est [-π, π] rad. Unités sont toujours des radians.

Les éléments sont interprétés comme suit: [rx, ry, rz], de sorte que [rx, ry, rz] est une vecteur de rotation, représentant la transformation de la trame de référence vers la trame principale. La pente doit être comprise dans la plage [0..π].

La trame de référence est arbitraire, mais elle est généralement fixe et doit être pour droitiers. Une petite dérive est acceptable. Les axes principaux sont les suivants:

  • X de l'oreille gauche vers la droite
  • Y de l'arrière de la tête jusqu'au nez (de l'arrière vers l'avant)
  • Z du cou jusqu'au haut de la tête

Champ de données: valeur personnalisée 2 (0x0545)

Le champ "Valeur personnalisée 2" (0x0545) est un champ de saisie utilisé pour signaler le des informations réelles de suivi de la tête. Il s'agit d'un tableau à 3 éléments à virgule fixe, interprété conformément aux règles HID normales pour les valeurs physiques. Les unités sont toujours exprimées en radians par seconde.

Les éléments sont interprétés comme suit: [vx, vy, vz], de sorte que [vx, vy, vz] est une vecteur de rotation, représentant la vitesse angulaire du cadre principal (par rapport à lui-même).

Champ de données: valeur personnalisée 3 (0x0546)

Le champ "Valeur personnalisée 3" (0x0546) est utilisé pour le suivi des discontinuités dans le cadre de référence. C'est un entier scalaire de 8 bits la taille de l'image. Il doit être incrémenté (avec enveloppement) par l'appareil chaque fois que cadre de référence est modifié, par exemple si un algorithme de filtre d'orientation utilisée pour déterminer l'orientation avait son état réinitialisé. Cette valeur est interprété conformément aux règles HID normales pour les valeurs physiques. Toutefois, la valeur physique et les unités n'ont pas d'importance. Les seules informations pertinentes "host" est une valeur modifiée. Pour éviter les problèmes numériques liés à la perte de précision lors de la conversion d'unités logiques en unités physiques, nous vous recommandons de définir les valeurs minimale et maximale physique, et l'exposant unitaire à zéro pour ce champ.

Structure du rapport

Le regroupement de propriétés dans des rapports (par attribution d'ID de rapport) est le suivant : flexible. Pour plus d'efficacité, nous vous recommandons de séparer les propriétés en lecture seule à partir des propriétés de lecture/écriture.

Pour les champs de données, les champs "Valeur personnalisée 1", "2" et "3" doivent figurer au même et ne figurer que dans un seul rapport pour un appareil donné (collection d'applications).

Envoyer les rapports d'entrée

L'appareil doit effectuer régulièrement et de manière asynchrone (via des messages HID INPUT) envoyer des rapports d'entrée lorsque toutes ces conditions sont remplies:

  • La propriété "État de la puissance" est définie sur "Pleine puissance".
  • La propriété "État des rapports" est définie sur "Tous les événements".
  • La propriété Intervalle de création de rapports n'est pas nulle.

La propriété "Intervalle entre les rapports" détermine la fréquence d'envoi des rapports. Quand ? si l'une des conditions ci-dessus n'est pas remplie, l'appareil ne doit envoyer aucun rapport.

Compatibilité ascendante et rétrocompatible

Le protocole HID du Head Tracker utilise un schéma de gestion des versions qui permet les mises à jour, tout en permettant l'interopérabilité entre un hôte et un appareil utilisant différentes versions du protocole. Les versions du protocole sont identifiées par deux nombres, majeur et mineur, qui ont une sémantique distincte comme décrites dans les sections suivantes.

Les versions compatibles avec un appareil peuvent être déterminées en examinant sa propriété "Description du capteur" (0x0308).

Compatibilité des versions mineures

Les modifications apportées à la version mineure sont rétrocompatibles avec les versions mineures antérieures basées sur la même version majeure. Dans les mises à jour , l'hôte ignore les autres champs de données et propriétés. Par exemple : un appareil utilisant le protocole version 1.6 est compatible avec un hôte qui prend en charge version 1.x du protocole, y compris la version 1.5.

Compatibilité avec les versions majeures

Les modifications non rétrocompatibles sont autorisées pour les modifications apportées aux versions majeures. À prendre en charge plusieurs versions majeures d’interopérabilité avec les anciens et nouveaux hôtes, les appareils peuvent spécifier plusieurs collections d'applications dans leur rapport de descripteurs. Exemple :

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

Dans ce cas, l'hôte peut énumérer toutes les différentes collections d'applications annoncé par l'appareil, en examinant la propriété "Description du capteur" pour déterminer les versions de protocole qu'ils mettent en œuvre chacune, puis choisir la dernière version du protocole compatible avec l'hôte. Lorsqu'il est choisi, l'hôte fonctionne avec le protocole unique qui a été choisi pour la durée de vie de l'appareil .

Annexe: Exemple de descripteur HID

L'exemple suivant illustre un descripteur HID valide type. Elle utilise le les macros C couramment utilisées, fournies dans Utilisations du capteur HID (section 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,
};

Annexe 2: Exemple de descripteur HID dans la version 2.0

L'exemple suivant illustre un descripteur HID v2.0 pour un périphérique compatible uniquement le transport Bluetooth LE ACL.

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