Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Ce document détaille l’implémentation du protocole pour les périphériques d’entrée compatibles haptic qui se connectent à un hôte Windows 11 compatible. Cela n’inclut pas de conseils sur les contraintes mécaniques, les contraintes électriques ou la sélection des composants pour générer la réponse haptique dans le matériel de l’appareil d’entrée.
Classes d’appareils pris en charge
Windows 11 prend en charge les classes suivantes d’appareils d’entrée compatibles haptic :
Haptic Touchpad est une extension de la classe d’appareil touchpad sur Windows. Ce guide d’implémentation ajoute au Guide d’implémentation du pavé tactile et se concentre sur l’implémentation de haptiques au sein du numériseur du pavé tactile. Les pavés tactiles haptiques doivent donc répondre aux exigences du Guide d’implémentation du pavé tactile en plus de ceux contenus ici.
Haptic Mouse est une extension de la classe d’appareil souris sur Windows. Les souris haptiques doivent répondre aux exigences contenues dans cette documentation.
Remarque : Les périphériques d’entrée de stylet compatibles haptic sont une classe d’appareil spéciale qui ne sera pas couverte dans ce document. Pour plus d’informations sur l’implémentation d’un appareil de stylet avec des commentaires haptiques, consultez le Guide d’implémentation du stylet Haptic.
Implémentation du protocole de retours haptiques des dispositifs d'entrée
Une bonne compréhension du protocole HID est nécessaire pour pouvoir comprendre les informations présentées ici. Pour plus d’informations sur le protocole HID, consultez les ressources suivantes :
- Définition de classe d’appareil pour les appareils d’interface humaine (HID)
- Tables d’utilisation HID
Le firmware du dispositif d'entrée à retour haptique doit uniquement signaler les usages décrits dans cette rubrique. Windows utilisera le microprogramme et ses propres pilotes HID pour activer l’appareil et accorder aux applications Windows l’accès à l’appareil.
Les exemples de descripteurs pour chaque classe d’appareil prise en charge sont fournis dans la section Exemples de descripteurs de rapport ci-dessous.
Conseils courants
Les éléments de cette section s’appliquent à toutes les classes d’appareils haptiques d’entrée.
Collection HID requise
Les fonctionnalités liées aux haptics doivent être incluses dans une collection HID SimpleHapticsController (Page 0xE, Utilisation 0x1).
Pour les appareils Haptic Touchpad, cette collection doit être un sous-ensemble de la collection de niveau supérieur Windows Precision Touchpad.
Pour les appareils Haptic Mouse, cette collection doit être une collection de niveau supérieur et parallèle à la collection de niveau supérieur de la souris.
commentaires haptiques Device-Initiated
Un appareil d’entrée haptique peut éventuellement prendre en charge le lancement de ses propres commentaires haptiques, par exemple en réponse à un bouton appuyé ou relâché.
Pour les pavés tactiles haptiques, la section « Aide au pavé tactile haptique » ci-dessous décrit comment l’appareil peut choisir de prendre en charge les rapports SET_FEATURE afin d’autoriser la personnalisation de son comportement lors du lancement de commentaires haptiques.
Les souris haptiques sont autorisées à déclencher des commentaires initiés par l’appareil, mais Windows n’a aucun mécanisme pour configurer ce comportement.
commentaires haptiques Host-Initiated
Un appareil d’entrée compatible haptique peut prendre en charge les commentaires haptiques initiés par l’hôte, qui peuvent se produire à tout moment après l’énumération.
Les pavés tactiles haptiques et les souris peuvent facultativement prendre en charge les réactions initiées par l’hôte. Pour les pavés tactiles haptiques, si les commentaires initiés par l’hôte sont pris en charge, les deux rapports SET_FEATURE pour la personnalisation des commentaires initiés par l’appareil doivent également être pris en charge.
La prise en charge de la rétroaction haptique initiée par l’hôte nécessite deux collections enfants logiques SimpleHapticsController (Page 0x0E, Usage 0x01). Ces collections logiques doivent être des enfants de la collection SimpleHapticsController principale pour la classe d’appareil implémentée (comme documenté dans la section « Collection HID requise » ci-dessus) et doivent être séparées de la collection utilisée pour configurer l’intensité des commentaires haptiques initiés par l’appareil pour les pavés tactiles. L’une de ces collections enfants logiques doit définir un rapport GET_FEATURE utilisé par l’hôte pour interroger les formes d’onde prises en charge et leurs durées. L’autre collection enfant logique doit définir un rapport de sortie utilisé par l’hôte pour déclencher manuellement des haptiques.
L’appareil ne doit PAS déclarer la prise en charge des haptics déclenchés automatiquement, et l’appareil ne doit PAS prendre en charge les formes d’ondes continues.
Ondes
Le tableau suivant définit les formes d’onde prises en charge par l’hôte pour les périphériques d’entrée compatibles haptique. Les formes d’onde prises en charge par un appareil sont associées à un ordinal. L’utilisation et la durée de la forme d’onde sont fournies à l’hôte via le rapport des fonctionnalités d’informations de forme d’onde (voir ci-dessous). Lors du déclenchement de commentaires, l’hôte fournit l’ordinal de la forme d’onde souhaitée comme valeur pour l’utilisation manuelle du déclencheur.
Obligatoire et facultatif
| Signaux | Descriptif | Page | ID | Obligatoire/facultatif |
|---|---|---|---|---|
| Aucun | Non op. Ne doit pas avoir d’impact sur l’état de jeu des formes d’ondes en cours | 0x0E | 0x1001 | Obligatoire |
| Arrêtez | Arrête la lecture des formes d’ondes en cours | 0x0E | 0x1002 | Obligatoire |
| Flotter | Impulsion légère utilisée pour indiquer le pointage et signaler le potentiel d’une action à venir | 0x0E | 0x1008 | Obligatoire |
| Entrer en collision | Impulsion douce utilisée pour indiquer les collisions avec les limites de l’écran ou les extrémités des curseurs et des barres de défilement | 0x0E | 0x1012 | Obligatoire |
| Align | Impulsion nette qui confirme l’alignement de l’objet pendant le glissement, l’échelle ou la rotation des interactions avec des repères ou des bords de canevas | 0x0E | 0x1013 | Obligatoire |
| Étape | Impulsion ferme utilisée pour parcourir les éléments dans des curseurs, des listes ou des nettoyages | 0x0E | 0x1014 | Obligatoire |
| Croître | Impulsion dynamique qui transmet le mouvement, les transitions ou l’activité système intelligente | 0x0E | 0x1015 | Obligatoire |
| Presse | Signal haptique déclenché par l’appareil lorsqu’il détermine que le bouton surface a été enfoncé. Si elle est prise en charge, la version doit également être prise en charge. | 0x0E | 0x1006 | Optional |
| Libération | Signal haptique déclenché par l’appareil lorsqu’il détermine que le bouton surface a été libéré. Si elle est prise en charge, appuyez également sur La touche Press. | 0x0E | 0x1007 | Optional |
| Success | Signal haptique fort pour alerter l’utilisateur qu’une action a réussi | 0x0E | 0x1009 | Optional |
| Erreur | Signal haptique fort pour alerter l’utilisateur qu’une action a échoué ou une erreur s’est produite | 0x0E | 0x100A | Optional |
Interdit
Les formes d’ondes suivantes NE DOIVENT PAS être prises en charge.
| Signaux | ID | Remarques |
|---|---|---|
| Click | 0x1003 | Provoquerait une confusion avec les commentaires haptiques existants pour les pressions sur les boutons. |
| Buzz Continu | 0x1004 | Les formes d’ondes continues ne doivent pas être prises en charge. |
| Rumble continu | 0x1005 | Les formes d’ondes continues ne doivent pas être prises en charge. |
| Entrée manuscrite continue | 0x100B | Applicable uniquement aux stylos. |
| Crayon continu | 0x100C | Applicable uniquement aux stylos. |
| Marqueur continu | 0x100D | Applicable uniquement aux stylos. |
| Marqueur chisel continu | 0x100E | Applicable uniquement aux stylos. |
| Pinceau continu | 0x100F | Applicable uniquement aux stylos. |
| Gomme continue | 0x1010 | Applicable uniquement aux stylos. |
| Sparkle Continu | 0x1011 | Applicable uniquement aux stylos. |
Rapport des fonctionnalités d’information waveform
L’hôte émet ce rapport GET_FEATURE lors de l’interrogation de l’appareil pour ses formes d’onde prises en charge. Ce rapport de fonctionnalités doit avoir un ID de rapport dédié.
La collection logique doit avoir deux collections logiques enfants, une pour la liste de formes d’ondes et une pour la liste de durée. Ces collections doivent définir une plage d’utilisation sur la page Ordinal (0x0A), ce qui permet à l’hôte d’interroger la forme d’onde et la durée associées à chaque ordinal.
Utilisations obligatoires et facultatives
| Membre | Descriptif | Page | ID | Obligatoire/facultatif |
|---|---|---|---|---|
| Liste de formes d’ondes | Collection logique contenant une liste ordonnée de formes d’ondes haptiques prises en charge par l’appareil | 0x0E | 0x10 | Obligatoire |
| Liste de durées | Collection logique contenant une liste ordonnée de durées pour les formes d’ondes dans la liste des formes d’ondes | 0x0E | 0x11 | Obligatoire |
Liste waveform (obligatoire)
Cette collection fournit le mappage entre les ordinals et les formes d’onde correspondantes. Les ordinals 1 et 2 correspondent à WAVEFORM_NONE et WAVEFORM_STOP implicitement et n’ont pas besoin d’être déclarés dans le descripteur. Par conséquent, la valeur minimale de la plage d'utilisation de la collection peut être de 3, et la valeur maximale doit être suffisamment grande pour attribuer des nombres ordinaux à toutes les formes d'onde prises en charge.
Si la valeur maximale d’utilisation est supérieure au nombre de formes d’onde prises en charge par l’appareil, l’appareil doit signaler WAVEFORM_NONE pour les ordinals non pris en charge.
La plage logique de la plage d’utilisation doit inclure toutes les utilisations de forme d’onde prises en charge. La plage physique et les unités doivent être 0.
Liste de durées (obligatoire)
Cette collection fournit les durées des formes d’ondes définies dans la liste des formes d’ondes. La plage d’utilisation minimale et maximale de la collection doit être identique à celle de la liste de formes d’ondes.
Les formes d’onde discrètes doivent avoir une durée non nulle. WAVEFORM_NONE et WAVEFORM_STOP, le cas échéant, doivent avoir une durée de zéro.
Le minimum logique de la plage d’utilisation doit être égal à zéro, et la valeur maximale logique doit être au moins aussi importante que la durée de la forme d’onde discrète la plus longue. L’hôte traite les valeurs logiques en millisecondes. La plage physique doit être égale à zéro ou identique à la plage logique. Si la plage physique et la plage logique correspondent, les unités doivent être en millisecondes.
Rapport de sortie de déclencheur manuel
L’hôte émet ce rapport lors du déclenchement de commentaires haptiques discrets. Ce rapport de sortie doit avoir un ID de rapport dédié.
Utilisations obligatoires et facultatives
| Membre | Descriptif | Page | ID | Obligatoire/facultatif |
|---|---|---|---|---|
| Déclencheur manuel | Forme d’onde à déclencher en tant que commande explicite à partir de l’hôte | 0x0E | 0x21 | Obligatoire |
| Intensité | Intensité des commentaires | 0x0E | 0x23 | Obligatoire |
| Nombre de répétitions | Nombre de fois où répéter les commentaires après la lecture initiale | 0x0E | 0x24 | Optional |
| Période de retrigger | Durée d’attente avant de déclencher à nouveau les commentaires lors de la répétition | 0x0E | 0x25 | Optional |
| Temps de coupure de forme d’onde | Durée maximale pendant laquelle les commentaires peuvent être lus avant d’être coupés | 0x0E | 0x28 | Optional |
Utilisations interdites
| Usage | ID | Remarques |
|---|---|---|
| Déclencheur automatique | 0x20 | Non pris en charge par l’hôte. |
| Déclencheur automatique associé au contrôle | 0x22 | Non pris en charge par l’hôte. |
Déclencheur manuel (obligatoire)
Cette utilisation contient l’ordinal de la forme d’onde, tel que défini à partir du rapport de fonctionnalités d’information de forme d’onde, qui a été demandé à être lu par l’hôte. Lorsqu’un rapport de sortie contenant un ordinal autre que WAVEFORM_NONE est envoyé à l’appareil, il doit immédiatement commencer à lire la forme d’onde spécifiée avec les propriétés supplémentaires incluses dans le rapport de sortie (intensité, nombre de répétitions, période de retrigger, délai de coupure, si prise en charge). L’appareil ne doit respecter que les ordinales pour les formes d’ondes discrètes, les WAVEFORM_NONE et les WAVEFORM_STOP. Si l’ordinal correspond à WAVEFORM_STOP, toute lecture de forme d’onde discrète en cours doit être arrêtée. Si l’ordinal correspond à WAVEFORM_NONE, aucune action ne doit être effectuée et les commentaires haptiques en cours doivent continuer à jouer.
La plage logique doit inclure tous les ordinaux possibles, y compris les ordinals implicites 1 (WAVEFORM_NONE) et 2 (WAVEFORM_STOP). La plage physique et les unités doivent être 0.
Intensité (obligatoire)
Cette utilisation représente le pourcentage d’intensité maximale à appliquer à la forme d’onde demandée, avec le maximum logique représentant l’intensité maximale et le minimum logique représentant aucun retour du tout.
Le minimum logique doit être égal à zéro et le maximum logique doit être sélectionné en fonction des fonctionnalités de l’appareil, par exemple, si l’appareil prend en charge quatre niveaux d’intensité, le maximum logique doit être de quatre. Si l’appareil prend en charge une intensité plus granulaire, le maximum logique peut être plus grand, mais il ne doit pas dépasser 100. L’appareil doit prendre en charge au moins quatre niveaux d’intensité, de sorte que le maximum logique minimal est de quatre. Une intensité de zéro indique qu’aucun retour ne doit être lu : l’hôte utilise uniquement cette valeur pour WAVEFORM_STOP.
La plage physique et les unités doivent être 0.
Nombre de répétitions (facultatif)
Cette utilisation représente le nombre de fois où répéter la forme d’onde après la lecture initiale. La valeur zéro indique que la forme d’onde ne doit être jouée qu’une seule fois.
Si cette utilisation est prise en charge, la période de retrigger et les utilisations de temps de coupure doivent également être prises en charge.
Le minimum logique doit être égal à zéro, et la valeur maximale logique doit être supérieure à zéro. La valeur maximale logique doit être limitée à une petite valeur (par exemple, 10). La plage physique et les unités doivent être 0.
Période de retrigger (facultatif)
Cette utilisation représente la durée entre les retriggers de la forme d’onde, mesurée à partir de l’heure de début du déclencheur précédent. Une valeur de zéro doit être interprétée comme identique à la durée par défaut de la forme d’onde, de sorte que le retrigger se produit immédiatement après la fin de la précédente. Les valeurs inférieures à la durée par défaut de la forme d’onde doivent interrompre la forme d’onde et la redémarrer.
Si cette utilisation est prise en charge, le nombre de répétitions et les utilisations de temps de coupure doivent également être prises en charge.
L’hôte traite les valeurs logiques en millisecondes. Le minimum logique doit être égal à zéro et le maximum logique doit être d’au moins 1 000 (représentant une seconde). La plage physique doit être égale à zéro ou identique à la plage logique. Si la plage physique n’est pas égale à zéro, les unités doivent être en millisecondes.
Temps de coupure de forme d’onde (facultatif)
Cette utilisation représente la durée maximale pendant laquelle un déclencheur unique peut entraîner la lecture, en tenant compte du nombre de répétitions et de la période de retrigueur.
Si cette utilisation est prise en charge, le nombre de répétitions et les utilisations de retrigger doivent également être prises en charge.
L’hôte traite les valeurs logiques en millisecondes. Le minimum logique doit être au moins aussi grand que la durée de la forme d’onde discrète la plus longue, multipliée par le maximum logique de l’utilisation du nombre de répétitions. La plage physique doit être égale à zéro ou identique à la plage logique. Si la plage physique n’est pas égale à zéro, les unités doivent être en millisecondes.
Guide du pavé tactile haptique
Les éléments de cette section s’appliquent uniquement aux pavés tactiles haptiques.
commentaires haptiques Device-Initiated
Un pavé tactile haptique est chargé de déclencher des commentaires haptiques lorsqu’il détermine que le bouton surface du pavé tactile a été enfoncé ou relâché. Il peut choisir de prendre en charge les rapports SET_FEATURE pour autoriser la personnalisation de son comportement par l’utilisateur lors de cette opération :
- Intensité de la rétroaction haptique
- Force requise pour déclencher une pression sur un bouton
Ces deux rapports de fonctionnalités sont obligatoires si le pavé tactile prend également en charge les commentaires haptiques initiés par l’hôte. Chaque rapport doit utiliser un ID de rapport distinct, non utilisé avec une autre utilisation.
Pendant l’énumération, l’hôte évalue la plage logique et physique prise en charge à partir du descripteur et calcule les options exposées pour l’interface utilisateur des paramètres, notamment les valeurs par défaut. L’hôte émet le SET_FEATURE pour communiquer la valeur spécifiée par l’utilisateur à l’appareil ; cette émission peut se produire à tout moment, mais doit se produire chaque fois que le paramètre est modifié, qu’un commutateur utilisateur se produit et que l’appareil est énuméré ou réinitialisé.
Rapport de caractéristiques d’intensité haptique
Ce rapport SET_FEATURE spécifie la préférence de l’utilisateur pour l’intensité des commentaires haptiques pour la pression et la mise en production du bouton. Elle ne s’applique pas à l’intensité des commentaires initiés par l’hôte, s’il est pris en charge par l’appareil. Pour prendre en charge cette configuration, l’appareil doit définir une collection enfant logique SimpleHapticsController (Page 0x0E, Utilisation 0x01) dans la collection de niveau supérieur du Pavé tactile de précision Windows, contenant l’utilisation de l’intensité haptique (Page 0x0E, Utilisation 0x23) en tant que rapport de fonctionnalités avec un ID de rapport dédié. Cette collection enfant ne doit pas contenir les utilisations de déclencheur automatique (0x0E de page, d’utilisation 0x20) ou de déclencheur manuel (page 0x0E, utilisation 0x21).
Le minimum logique doit être égal à zéro. La préférence de l’utilisateur sera mise à l’échelle linéaire dans la plage logique, avec zéro indiquant qu’aucun commentaire ne doit être déclenché pour la pression et la mise en production du bouton.
Bouton Appuyer sur le rapport de fonctionnalité seuil
Ce rapport SET_FEATURE spécifie la préférence de l’utilisateur pour la force requise pour déclencher une pression sur un bouton. Pour prendre en charge cette configuration, l’appareil doit définir l’utilisation du seuil d’appui sur le bouton (page 0x0D, utilisation 0xB0) en tant que rapport de fonctionnalités avec un ID de rapport dédié dans la collection de haut niveau du pavé tactile de précision Windows.
La plage logique doit être mappée de manière linéaire à la plage physique de valeurs, et être uniformément espacée et centrée autour de la valeur par défaut. Lors de l’acquisition de la plage logique, la valeur par défaut est calculée en utilisant formule suivante :
Le minimum logique, la valeur par défaut et le maximum logique correspondent à 3 niveaux distincts de la force de pression sur le bouton qui est exposée à un utilisateur via l’interface utilisateur des paramètres Windows (prenant en charge respectivement « Faible », « Moyen » et « Élevé »).
La plage physique recommandée pour le seuil de pression sur le bouton consiste à couvrir au moins la plage comprise entre 110 g et 190 g, correspondant respectivement aux valeurs minimales et maximales. Pour un exemple de descripteur utilisant un maximum physique de 190 g et un minimum physique de 110 g (par conséquent, selon la formule ci-dessus, la valeur par défaut sera 150 g) consultez Exemples de descripteurs de rapport.
Exemples de descripteurs de rapport HID
Exemple de descripteur de pavé tactile haptique
Le descripteur suivant prend en charge toutes les utilisations obligatoires et facultatives. Il déclare la prise en charge de cinq formes d’ondes, avec la durée la plus longue de 50 ms.
Toutes les plages logiques doivent être mises à jour en fonction de la prise en charge des appareils. Pour prendre en charge un nombre différent de formes d’ondes :
- La plage logique de l’utilisation du déclencheur manuel doit être mise à jour
- Les plages d’utilisation et le nombre de rapports pour la liste de formes d’ondes et la liste de durée doivent être mis à jour
Pour prendre en charge une longueur d’onde maximale différente, les plages logiques suivantes doivent être mises à jour :
- Période de retrigger (sortie)
- Délai de coupure de forme d’onde (sortie)
- Liste de durées (fonctionnalité)
0x05, 0x0D, // UsagePage(Digitizers[0x000D])
0x09, 0x05, // UsageId(Touch Pad[0x0005])
0xA1, 0x01, // Collection(Application)
0x85, 0x40, // ReportId(64)
0x05, 0x0D, // UsagePage(Digitizers[0x000D])
0x09, 0xB0, // UsageId(Button Press Threshold[0x00B0])
0x35, 0x6E, // PhysicalMinimum(110)
0x46, 0xBE, 0x00, // PhysicalMaximum(190)
0x66, 0x01, 0x01, // Unit('gram', SiLinear, Gram:1)
0x55, 0x00, // UnitExponent(1)
0x15, 0x01, // LogicalMinimum(1)
0x25, 0x03, // LogicalMaximum(3)
0x95, 0x01, // ReportCount(1)
0x75, 0x08, // ReportSize(8)
0xB1, 0x02, // Feature(Data, Variable, Absolute)
0x85, 0x41, // ReportId(65)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x01, // UsageId(Simple Haptic Controller[0x0001])
0xA1, 0x02, // Collection(Logical)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x23, // UsageId(Intensity[0x0023])
0x35, 0x00, // PhysicalMinimum(0)
0x45, 0x00, // PhysicalMaximum(0)
0x65, 0x00, // Unit(None)
0x55, 0x00, // UnitExponent(1)
0x15, 0x00, // LogicalMinimum(0)
0x25, 0x04, // LogicalMaximum(4)
0x95, 0x01, // ReportCount(1)
0x75, 0x08, // ReportSize(8)
0xB1, 0x02, // Feature(Data, Variable, Absolute)
0xC0, // EndCollection()
0x85, 0x42, // ReportId(66)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x01, // UsageId(Simple Haptic Controller[0x0001])
0xA1, 0x02, // Collection(Logical)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x10, // UsageId(Waveform List[0x0010])
0xA1, 0x02, // Collection(Logical)
0x05, 0x0A, // UsagePage(Ordinal[0x000A])
0x19, 0x03, // UsageIdMin(Instance 3[0x0003])
0x29, 0x07, // UsageIdMax(Instance 7[0x0007])
0x35, 0x00, // PhysicalMinimum(0)
0x45, 0x00, // PhysicalMaximum(0)
0x65, 0x00, // Unit(None)
0x55, 0x00, // UnitExponent(1)
0x16, 0x03, 0x10, // LogicalMinimum(4,099)
0x26, 0xFF, 0x2F, // LogicalMaximum(12,287)
0x95, 0x05, // ReportCount(5)
0x75, 0x10, // ReportSize(16)
0xB1, 0x02, // Feature(Data, Variable, Absolute)
0xC0, // EndCollection()
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x11, // UsageId(Duration List[0x0011])
0xA1, 0x02, // Collection(Logical)
0x05, 0x0A, // UsagePage(Ordinal[0x000A])
0x19, 0x03, // UsageIdMin(Instance 3[0x0003])
0x29, 0x07, // UsageIdMax(Instance 7[0x0007])
0x35, 0x00, // PhysicalMinimum(0)
0x45, 0x32, // PhysicalMaximum(50)
0x66, 0x01, 0x10, // Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D, // UnitExponent(0.001)
0x15, 0x00, // LogicalMinimum(0)
0x25, 0x32, // LogicalMaximum(50)
0x95, 0x05, // ReportCount(5)
0x75, 0x08, // ReportSize(8)
0xB1, 0x02, // Feature(Data, Variable, Absolute)
0xC0, // EndCollection()
0xC0, // EndCollection()
0x85, 0x43, // ReportId(67)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x01, // UsageId(Simple Haptic Controller[0x0001])
0xA1, 0x02, // Collection(Logical)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
0x35, 0x00, // PhysicalMinimum(0)
0x45, 0x00, // PhysicalMaximum(0)
0x65, 0x00, // Unit(None)
0x55, 0x00, // UnitExponent(1)
0x15, 0x01, // LogicalMinimum(1)
0x25, 0x07, // LogicalMaximum(7)
0x95, 0x01, // ReportCount(1)
0x75, 0x08, // ReportSize(8)
0x91, 0x02, // Output(Data, Variable, Absolute)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x23, // UsageId(Intensity[0x0023])
0x35, 0x00, // PhysicalMinimum(0)
0x45, 0x00, // PhysicalMaximum(0)
0x65, 0x00, // Unit(None)
0x55, 0x00, // UnitExponent(1)
0x15, 0x00, // LogicalMinimum(0)
0x25, 0x04, // LogicalMaximum(4)
0x95, 0x01, // ReportCount(1)
0x75, 0x08, // ReportSize(8)
0x91, 0x02, // Output(Data, Variable, Absolute)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x24, // UsageId(Repeat Count[0x0024])
0x35, 0x00, // PhysicalMinimum(0)
0x45, 0x00, // PhysicalMaximum(0)
0x65, 0x00, // Unit(None)
0x55, 0x00, // UnitExponent(1)
0x15, 0x00, // LogicalMinimum(0)
0x25, 0x05, // LogicalMaximum(5)
0x95, 0x01, // ReportCount(1)
0x75, 0x08, // ReportSize(8)
0x91, 0x02, // Output(Data, Variable, Absolute)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x25, // UsageId(Retrigger Period[0x0025])
0x35, 0x00, // PhysicalMinimum(0)
0x46, 0xE8, 0x03, // PhysicalMaximum(1,000)
0x66, 0x01, 0x10, // Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D, // UnitExponent(0.001)
0x15, 0x00, // LogicalMinimum(0)
0x26, 0xE8, 0x03, // LogicalMaximum(1,000)
0x95, 0x01, // ReportCount(1)
0x75, 0x10, // ReportSize(16)
0x91, 0x02, // Output(Data, Variable, Absolute)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x28, // UsageId(Waveform Cutoff Time[0x0028])
0x36, 0xE8, 0x03, // PhysicalMinimum(1,000)
0x46, 0x88, 0x13, // PhysicalMaximum(5,000)
0x66, 0x01, 0x10, // Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D, // UnitExponent(0.001)
0x16, 0xE8, 0x03, // LogicalMinimum(1,000)
0x26, 0x88, 0x13, // LogicalMaximum(5,000)
0x95, 0x01, // ReportCount(1)
0x75, 0x10, // ReportSize(16)
0x91, 0x02, // Output(Data, Variable, Absolute)
0xC0, // EndCollection()
0xC0, // EndCollection()
Le descripteur ci-dessus a été généré via le fichier Waratah suivant :
[[settings]]
packingInBytes = 1
optimize = false
[[unit]]
name = 'millisecond'
second = [0.001, 1.0]
[[applicationCollection]]
usage = ['Digitizers', 'Touch Pad']
# Button press threshold feature report
[[applicationCollection.featureReport]]
id = 0x40
[[applicationCollection.featureReport.variableItem]]
usage = ['Digitizers', 'Button Press Threshold']
logicalValueRange = [1, 3]
physicalValueRange = [110, 190]
unit = 'gram'
# Feedback intensity feature report
[[applicationCollection.featureReport]]
id = 0x41
[[applicationCollection.featureReport.logicalCollection]]
usage = ['Haptics', 'Simple Haptic Controller']
[[applicationCollection.featureReport.logicalCollection.variableItem]]
usage = ['Haptics', 'Intensity']
logicalValueRange = [0, 4]
# Host-initiated waveform information feature report
[[applicationCollection.featureReport]]
id = 0x42
[[applicationCollection.featureReport.logicalCollection]]
usage = ['Haptics', 'Simple Haptic Controller']
[[applicationCollection.featureReport.logicalCollection.logicalCollection]]
usage = ['Haptics', 'Waveform List']
[[applicationCollection.featureReport.logicalCollection.logicalCollection.variableItem]]
usageRange = ['Ordinal', 'Instance 3', 'Instance 7']
logicalValueRange = [0x1003, 0x2FFF]
[[applicationCollection.featureReport.logicalCollection.logicalCollection]]
usage = ['Haptics', 'Duration List']
[[applicationCollection.featureReport.logicalCollection.logicalCollection.variableItem]]
usageRange = ['Ordinal', 'Instance 3', 'Instance 7']
logicalValueRange = [0, 50]
physicalValueRange = [0, 50]
unit = 'millisecond'
# Host-initiated waveform manual trigger output report
[[applicationCollection.outputReport]]
id = 0x43
[[applicationCollection.outputReport.logicalCollection]]
usage = ['Haptics', 'Simple Haptic Controller']
[[applicationCollection.outputReport.logicalCollection.variableItem]]
usage = ['Haptics', 'Manual Trigger']
logicalValueRange = [1, 7]
[[applicationCollection.outputReport.logicalCollection.variableItem]]
usage = ['Haptics', 'Intensity']
logicalValueRange = [0, 4]
[[applicationCollection.outputReport.logicalCollection.variableItem]]
usage = ['Haptics', 'Repeat Count']
logicalValueRange = [0, 5]
[[applicationCollection.outputReport.logicalCollection.variableItem]]
usage = ['Haptics', 'Retrigger Period']
logicalValueRange = [0, 1000]
physicalValueRange = [0, 1000]
unit = 'millisecond'
[[applicationCollection.outputReport.logicalCollection.variableItem]]
usage = ['Haptics', 'Waveform Cutoff Time']
logicalValueRange = [1000, 5000]
physicalValueRange = [1000, 5000]
unit = 'millisecond'
Exemple de descripteur de souris Haptic
Le descripteur suivant prend en charge toutes les utilisations obligatoires et facultatives. Il déclare la prise en charge de huit formes d’ondes, avec la durée la plus longue de 200 ms.
Toutes les plages logiques doivent être mises à jour en fonction de la prise en charge des appareils. Pour prendre en charge un nombre différent de formes d’ondes :
- La plage logique de l’utilisation du déclencheur manuel doit être mise à jour
- Les plages d’utilisation et le nombre de rapports pour la liste de formes d’ondes et la liste de durée doivent être mis à jour
Pour prendre en charge une longueur d’onde maximale différente, les plages logiques suivantes doivent être mises à jour :
- Période de retrigger (sortie)
- Délai de coupure de forme d’onde (sortie)
- Liste de durées (fonctionnalité)
0x05, 0x01, // UsagePage(Generic Desktop[0x0001])
0x09, 0x02, // UsageId(Mouse[0x0002])
0xA1, 0x01, // Collection(Application)
0x85, 0x01, // ReportId(1)
0x09, 0x01, // UsageId(Pointer[0x0001])
0xA1, 0x00, // Collection(Physical)
0x09, 0x30, // UsageId(X[0x0030])
0x09, 0x31, // UsageId(Y[0x0031])
0x15, 0x80, // LogicalMinimum(-128)
0x25, 0x7F, // LogicalMaximum(127)
0x95, 0x02, // ReportCount(2)
0x75, 0x08, // ReportSize(8)
0x81, 0x06, // Input(Data, Variable, Relative)
0x05, 0x09, // UsagePage(Button[0x0009])
0x19, 0x01, // UsageIdMin(Button 1[0x0001])
0x29, 0x03, // UsageIdMax(Button 3[0x0003])
0x15, 0x00, // LogicalMinimum(0)
0x25, 0x01, // LogicalMaximum(1)
0x95, 0x03, // ReportCount(3)
0x75, 0x01, // ReportSize(1)
0x81, 0x02, // Input(Data, Variable, Absolute)
0xC0, // EndCollection()
0x95, 0x01, // ReportCount(1)
0x75, 0x05, // ReportSize(5)
0x81, 0x03, // Input(Constant, Variable, Absolute)
0xC0, // EndCollection()
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x01, // UsageId(Simple Haptic Controller[0x0001])
0xA1, 0x01, // Collection(Application)
0x85, 0x10, // ReportId(16)
0x09, 0x10, // UsageId(Waveform List[0x0010])
0xA1, 0x02, // Collection(Logical)
0x05, 0x0A, // UsagePage(Ordinal[0x000A])
0x19, 0x03, // UsageIdMin(Instance 3[0x0003])
0x29, 0x0A, // UsageIdMax(Instance 10[0x000A])
0x16, 0x03, 0x10, // LogicalMinimum(4,099)
0x26, 0xFF, 0x2F, // LogicalMaximum(12,287)
0x95, 0x08, // ReportCount(8)
0x75, 0x0E, // ReportSize(14)
0xB1, 0x02, // Feature(Data, Variable, Absolute)
0xC0, // EndCollection()
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x11, // UsageId(Duration List[0x0011])
0xA1, 0x02, // Collection(Logical)
0x05, 0x0A, // UsagePage(Ordinal[0x000A])
0x19, 0x03, // UsageIdMin(Instance 3[0x0003])
0x29, 0x0A, // UsageIdMax(Instance 10[0x000A])
0x46, 0xC8, 0x00, // PhysicalMaximum(200)
0x66, 0x01, 0x10, // Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D, // UnitExponent(0.001)
0x15, 0x00, // LogicalMinimum(0)
0x26, 0xC8, 0x00, // LogicalMaximum(200)
0x75, 0x08, // ReportSize(8)
0xB1, 0x02, // Feature(Data, Variable, Absolute)
0xC0, // EndCollection()
0x85, 0x11, // ReportId(17)
0x05, 0x0E, // UsagePage(Haptics[0x000E])
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
0x45, 0x00, // PhysicalMaximum(0)
0x65, 0x00, // Unit(None)
0x55, 0x00, // UnitExponent(1)
0x15, 0x01, // LogicalMinimum(1)
0x25, 0x0A, // LogicalMaximum(10)
0x95, 0x01, // ReportCount(1)
0x75, 0x04, // ReportSize(4)
0x91, 0x02, // Output(Data, Variable, Absolute)
0x09, 0x23, // UsageId(Intensity[0x0023])
0x15, 0x00, // LogicalMinimum(0)
0x25, 0x04, // LogicalMaximum(4)
0x75, 0x03, // ReportSize(3)
0x91, 0x02, // Output(Data, Variable, Absolute)
0x09, 0x24, // UsageId(Repeat Count[0x0024])
0x25, 0x05, // LogicalMaximum(5)
0x91, 0x02, // Output(Data, Variable, Absolute)
0x09, 0x25, // UsageId(Retrigger Period[0x0025])
0x46, 0xE8, 0x03, // PhysicalMaximum(1,000)
0x66, 0x01, 0x10, // Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D, // UnitExponent(0.001)
0x26, 0xE8, 0x03, // LogicalMaximum(1,000)
0x75, 0x0A, // ReportSize(10)
0x91, 0x02, // Output(Data, Variable, Absolute)
0x09, 0x28, // UsageId(Waveform Cutoff Time[0x0028])
0x36, 0xE8, 0x03, // PhysicalMinimum(1,000)
0x46, 0x88, 0x13, // PhysicalMaximum(5,000)
0x16, 0xE8, 0x03, // LogicalMinimum(1,000)
0x26, 0x88, 0x13, // LogicalMaximum(5,000)
0x75, 0x0D, // ReportSize(13)
0x91, 0x02, // Output(Data, Variable, Absolute)
0x75, 0x07, // ReportSize(7)
0x91, 0x03, // Output(Constant, Variable, Absolute)
0xC0, // EndCollection()
Le descripteur ci-dessus a été généré via le fichier Waratah suivant :
[[unit]]
name = 'millisecond'
second = [0.001, 1.0]
[[applicationCollection]]
usage = ['Generic Desktop', 'Mouse']
# Mouse
[[applicationCollection.inputReport]]
[[applicationCollection.inputReport.physicalCollection]]
usage = ['Generic Desktop', 'Pointer']
[[applicationCollection.inputReport.physicalCollection.variableItem]]
usage = ['Generic Desktop', 'X']
sizeInBits = 8
logicalValueRange = 'maxSignedSizeRange'
reportFlags = ['relative']
[[applicationCollection.inputReport.physicalCollection.variableItem]]
usage = ['Generic Desktop', 'Y']
sizeInBits = 8
logicalValueRange = 'maxSignedSizeRange'
reportFlags = ['relative']
[[applicationCollection.inputReport.physicalCollection.variableItem]]
usageRange = ['Button', 'Button 1', 'Button 3']
logicalValueRange = [0, 1]
[[applicationCollection]]
usage = ['Haptics', 'Simple Haptic Controller']
# Host-initiated waveform information feature report
[[applicationCollection.featureReport]]
id = 0x10
[[applicationCollection.featureReport.logicalCollection]]
usage = ['Haptics', 'Waveform List']
[[applicationCollection.featureReport.logicalCollection.variableItem]]
usageRange = ['Ordinal', 'Instance 3', 'Instance 10']
logicalValueRange = [0x1003, 0x2FFF]
[[applicationCollection.featureReport.logicalCollection]]
usage = ['Haptics', 'Duration List']
[[applicationCollection.featureReport.logicalCollection.variableItem]]
usageRange = ['Ordinal', 'Instance 3', 'Instance 10']
logicalValueRange = [0, 200]
physicalValueRange = [0, 200]
unit = 'millisecond'
# Host-initiated waveform manual trigger output report
[[applicationCollection.outputReport]]
id = 0x11
[[applicationCollection.outputReport.variableItem]]
usage = ['Haptics', 'Manual Trigger']
logicalValueRange = [1, 10]
[[applicationCollection.outputReport.variableItem]]
usage = ['Haptics', 'Intensity']
logicalValueRange = [0, 4]
[[applicationCollection.outputReport.variableItem]]
usage = ['Haptics', 'Repeat Count']
logicalValueRange = [0, 5]
[[applicationCollection.outputReport.variableItem]]
usage = ['Haptics', 'Retrigger Period']
logicalValueRange = [0, 1000]
physicalValueRange = [0, 1000]
unit = 'millisecond'
[[applicationCollection.outputReport.variableItem]]
usage = ['Haptics', 'Waveform Cutoff Time']
logicalValueRange = [1000, 5000]
physicalValueRange = [1000, 5000]
unit = 'millisecond'