Condividi tramite


Guida all'implementazione degli haptics per dispositivi di input

Questo documento illustra in dettaglio l'implementazione del protocollo per i dispositivi di input abilitati per l'aptico che si connettono a un host Windows 11 compatibile. Ciò non include indicazioni sui vincoli meccanici, sui vincoli elettrici o sulla selezione dei componenti per generare la risposta aptica all'interno dell'hardware del dispositivo di input.

Classi di dispositivi supportate

Windows 11 supporta le classi seguenti di dispositivi di input abilitati per l'aptico:

  • Touchpad aptico è un'estensione della classe Device Touchpad in Windows. Questa guida all'implementazione aggiunge alla Guida all'implementazione del Touchpad e si concentra sull'implementazione di aptici all'interno del digitalizzatore touchpad, quindi i touchpad aptici devono soddisfare i requisiti nella Guida all'implementazione del Touchpad oltre a quelli contenuti qui.

  • Mouse aptico è un'estensione della classe Mouse Device in Windows. I topi aptici devono soddisfare i requisiti contenuti in questa documentazione.

Nota: i dispositivi di input penna con supporto aptico sono una classe speciale di dispositivi che non verrà trattata in questo documento. Per informazioni su come implementare un dispositivo penna con feedback aptico, vedere la Guida all'implementazione della penna aptica.

Implementazione del protocollo Aptica del dispositivo di ingresso

Per comprendere le informazioni presentate qui, è necessaria una buona comprensione del protocollo HID. Per informazioni sul protocollo HID, vedere le risorse seguenti:

Il firmware del dispositivo di input abilitato alla risposta aptica deve segnalare solo gli utilizzi descritti in questo argomento. Windows userà il firmware e i relativi driver HID per abilitare il dispositivo e concedere alle applicazioni Windows l'accesso al dispositivo.

I descrittori di esempio per ogni classe di dispositivo supportata sono disponibili nella sezione Descrittori di report di esempio seguente.

Linee guida comuni

Gli elementi in questa sezione si applicano a tutte le classi di dispositivi aptici di input.

Raccolta HID richiesta

Le funzionalità correlate agli aptici devono essere incluse in una raccolta HID SimpleHapticsController (Page 0xE, Usage 0x1).

Per i dispositivi Touchpad haptico, questa raccolta deve essere un elemento figlio della raccolta principale di Windows Precision Touchpad.

Per i dispositivi Mouse aptico, questa raccolta deve essere una collezione di primo livello e una collezione sorella della collezione principale del Mouse.

Device-Initiated Feedback aptico

Un dispositivo di input abilitato per l'aptico può supportare facoltativamente l'avvio del proprio feedback aptico, ad esempio in risposta alla pressione o al rilascio di un pulsante.

Per i touchpad aptici, la sezione "Guida al touchpad aptico" di seguito descrive come il dispositivo può scegliere di supportare SET_FEATURE report per consentire la personalizzazione dell'utente del suo comportamento quando si avvia il feedback aptico.

I topi aptici possono attivare il feedback avviato dal dispositivo, ma Windows non ha alcun meccanismo per configurare questo comportamento.

Host-Initiated Feedback aptico

Un dispositivo di input dotato di funzionalità aptiche è in grado di supportare il feedback aptico avviato dall'host, che può verificarsi in qualsiasi momento dopo l'enumerazione.

I touchpad e i mouse aptici possono supportare facoltativamente il feedback avviato dall'host. Per i touchpad aptici, se è supportato il feedback avviato dall'host, è necessario supportare anche entrambi i report SET_FEATURE per la personalizzazione dei commenti e suggerimenti avviati dal dispositivo.

Il supporto per il feedback aptico avviato dall'host richiede due raccolte figlio logiche di SimpleHapticsController (Pagina 0x0E, Utilizzo 0x01). Queste raccolte logiche devono essere elementi figlio della raccolta SimpleHapticsController principale per la classe di dispositivo implementata (come documentato nella sezione "Raccolta HID obbligatoria" precedente) e deve essere separata dalla raccolta usata per configurare l'intensità del feedback aptico avviato dal dispositivo per i touchpad. Una di queste raccolte figlio logiche deve definire un report GET_FEATURE usato dall'host per eseguire query per le forme d'onda supportate e le relative durate. L'altra raccolta di figli logici deve definire un report di output utilizzato dall'host per attivare manualmente il feedback aptico.

Il dispositivo non deve dichiarare il supporto per gli aptici attivati automaticamente e il dispositivo non deve supportare alcuna forma d'onda continua.

Forme d' onda

La tabella seguente definisce le forme d'onda supportate dall'host per i dispositivi di input abilitati per l'aptico. Le forme d'onda supportate da un dispositivo sono associate a un ordinale. L'utilizzo e la durata delle forme d'onda vengono forniti all'host tramite il report delle informazioni sulle forme d'onda (vedere di seguito). Quando si attiva il feedback, l'host fornisce l'ordinale della forma d'onda desiderata come valore per l'utilizzo manuale del trigger.

Obbligatorio e facoltativo
Forma d' onda Description Pagina Documento d'identità Obbligatorio/Facoltativo
None No-op. Non dovrebbe influire sullo stato di riproduzione delle forme d'onda in corso 0x0E 0x1001 Obbligatorio
Fermati Arresta la riproduzione delle forme d'onda in corso 0x0E 0x1002 Obbligatorio
Hover Un impulso di luce usato per indicare il passaggio del mouse e segnalare il potenziale per un'azione futura 0x0E 0x1008 Obbligatorio
Collidere Un impulso morbido usato per indicare collisioni con i limiti dello schermo o le estremità dei dispositivi di scorrimento e delle barre di scorrimento 0x0E 0x1012 Obbligatorio
Align Un impulso croccante che conferma l'allineamento degli oggetti durante il trascinamento, la scala o la rotazione delle interazioni con guide o bordi di tela 0x0E 0x1013 Obbligatorio
Step Un impulso fisso usato per scorrere gli elementi in dispositivi di scorrimento, elenchi o scrubber 0x0E 0x1014 Obbligatorio
Crescere Un impulso dinamico che trasmette il movimento, le transizioni o l'attività intelligente del sistema 0x0E 0x1015 Obbligatorio
Passeggiata Segnale aptico attivato dal dispositivo quando determina che il pulsante della superficie è stato premuto. Se supportato, anche Release deve essere supportato. 0x0E 0x1006 Opzionale
Rilascio Segnale aptico attivato dal dispositivo quando determina che il pulsante della superficie è stato rilasciato. Se supportato, è necessario supportare anche Press. 0x0E 0x1007 Opzionale
Success Segnale aptico forte per avvisare l'utente che un'azione ha avuto esito positivo 0x0E 0x1009 Opzionale
Errore Segnale aptico forte per avvisare l'utente che un'azione non è riuscita o si è verificato un errore 0x0E 0x100A Opzionale
Vietato

Le forme d'onda seguenti NON DEVONO essere supportate.

Forma d' onda Documento d'identità Note
Click 0x1003 Causerebbe confusione con il feedback aptico esistente per le presse dei pulsanti.
Continuo ronzio 0x1004 Le forme d'onda continue non devono essere supportate.
Vibrazione Continua 0x1005 Le forme d'onda continue non devono essere supportate.
Input penna continuo 0x100B Applicabile solo alle penne.
Matita continua 0x100C Applicabile solo alle penne.
Marcatore continuo 0x100D Applicabile solo alle penne.
Marcatore di chisele continuo 0x100E Applicabile solo alle penne.
Pennello continuo 0x100F Applicabile solo alle penne.
Gomma continua 0x1010 Applicabile solo alle penne.
Sparkle Continuous 0x1011 Applicabile solo alle penne.

Report sulle informazioni sulle forme d'onda

L'host emetterà questo report GET_FEATURE quando si eseguono query sul dispositivo per individuare le forme d'onda supportate. Questo report di funzionalità deve avere un ID report dedicato.

La raccolta logica deve avere due raccolte logiche figlio, una per l'elenco delle forme d'onda e una per l'elenco di durata. Queste raccolte devono definire un intervallo di utilizzo nella pagina Ordinale (0x0A), che consente all'host di eseguire una query per la forma d'onda e la durata associata a ogni ordinale.

Utilizzi obbligatori e facoltativi
Membro Description Pagina Documento d'identità Obbligatorio/Facoltativo
Elenco waveform Raccolta logica contenente un elenco ordinato di forme d'onda aptice supportate dal dispositivo 0x0E 0x10 Obbligatorio
Elenco durata Raccolta logica contenente un elenco ordinato di durate per le forme d'onda nell'elenco Waveform 0x0E 0x11 Obbligatorio
Elenco waveform (obbligatorio)

Questa raccolta fornisce il mapping tra ordinali e le forme d'onda corrispondenti. Gli ordinali 1 e 2 corrispondono a WAVEFORM_NONE e WAVEFORM_STOP in modo implicito e non devono essere dichiarati nel descrittore. Pertanto, il minimo dell'intervallo d'uso della raccolta può essere 3, e il massimo deve essere sufficientemente grande da assegnare i numeri ordinali a tutte le forme d'onda supportate.

Se il valore massimo di utilizzo è maggiore del numero di forme d'onda supportate dal dispositivo, il dispositivo deve segnalare WAVEFORM_NONE per gli ordinali non supportati.

L'intervallo logico dell'intervallo di utilizzo deve includere tutti gli utilizzi delle forme d'onda supportate. L'intervallo fisico e le unità devono essere 0.

Elenco durata (obbligatorio)

Questa raccolta fornisce le durate delle forme d'onda definite nell'elenco delle forme d'onda. L'utilizzo minimo e massimo dell'intervallo di utilizzo della raccolta deve essere identico a quello dell'elenco delle forme d'onda.

Le forme d'onda discrete devono avere una durata diversa da zero. WAVEFORM_NONE e WAVEFORM_STOP, se specificato, devono avere una durata pari a zero.

Il minimo logico dell'intervallo di utilizzo deve essere zero e il valore massimo logico deve essere pari almeno alla durata della forma d'onda discreta più lunga. L'host considererà i valori logici come millisecondi. L'intervallo fisico deve essere zero o identico all'intervallo logico. Se l'intervallo fisico e l'intervallo logico corrispondono, le unità devono essere millisecondi.

Report di output trigger manuale

L'host emetterà questo report quando si attiva un feedback aptico discreto. Questo report di output deve avere un ID report dedicato.

Utilizzi obbligatori e facoltativi
Membro Description Pagina Documento d'identità Obbligatorio/Facoltativo
Trigger manuale Waveform da attivare come comando esplicito dall'host 0x0E 0x21 Obbligatorio
Intensità Intensità del feedback 0x0E 0x23 Obbligatorio
Ripeti conteggio Numero di volte in cui ripetere il feedback dopo la riproduzione iniziale 0x0E 0x24 Opzionale
Periodo di ripetizione Durata dell'attesa prima di riattivare il feedback durante la ripetizione 0x0E 0x25 Opzionale
Tempo di Interruzione della Forma d'Onda Tempo massimo di riproduzione del feedback prima di essere tagliato 0x0E 0x28 Opzionale
Utilizzi non consentiti
Usage Documento d'identità Note
Trigger automatico 0x20 Non supportato dall'host.
Controllo associato al trigger automatico 0x22 Non supportato dall'host.
Trigger manuale (obbligatorio)

Questo utilizzo contiene l'ordinale della forma d'onda, come definito dal report delle informazioni sulle forme d'onda, che è stato richiesto di essere riprodotto dall'host. Quando un report di output contenente un ordinale diverso da WAVEFORM_NONE viene inviato al dispositivo, deve iniziare immediatamente a riprodurre la forma d'onda specificata con le proprietà aggiuntive incluse nel report di output (intensità, conteggio ripetizioni, periodo di ripetizione, periodo cutoff, se supportato). Il dispositivo deve rispettare solo ordinali per forme d'onda discrete, WAVEFORM_NONE e WAVEFORM_STOP. Se l'ordinale corrisponde a WAVEFORM_STOP, è necessario arrestare qualsiasi riproduzione della forma d'onda discreta in corso. Se l'ordinale corrisponde a WAVEFORM_NONE, non deve essere eseguita alcuna azione e il feedback aptico continuo deve continuare a essere riprodotto.

L'intervallo logico deve includere tutti i possibili ordinali, inclusi i ordinali impliciti 1 (WAVEFORM_NONE) e 2 (WAVEFORM_STOP). L'intervallo fisico e le unità devono essere 0.

Intensità (obbligatorio)

Questo utilizzo rappresenta la percentuale di intensità massima da applicare alla forma d'onda richiesta, con il massimo logico che rappresenta l'intensità massima e il minimo logico che non rappresenta alcun feedback.

Il minimo logico deve essere zero e il massimo logico deve essere selezionato in base alle funzionalità del dispositivo, ad esempio se il dispositivo supporta quattro livelli di intensità, il massimo logico deve essere quattro. Se il dispositivo supporta un'intensità più granulare, il valore massimo logico può essere maggiore, ma non deve superare 100. Il dispositivo deve supportare almeno quattro livelli di intensità, quindi il massimo logico minimo è quattro. Un'intensità pari a zero indica che non deve essere riprodotto alcun feedback. L'host userà solo questo valore per WAVEFORM_STOP.

L'intervallo fisico e le unità devono essere 0.

Conteggio ripetizioni (facoltativo)

Questo utilizzo rappresenta il numero di volte in cui ripetere la forma d'onda dopo la riproduzione iniziale. Un valore pari a zero indica che la forma d'onda deve essere riprodotta una sola volta.

Se questo utilizzo è supportato, è necessario supportare anche il periodo di ripetizione e l'utilizzo del tempo di riduzione.

Il valore minimo logico deve essere zero e il valore massimo logico deve essere maggiore di zero. Il valore massimo logico deve essere limitato a un valore ridotto ,ad esempio 10. L'intervallo fisico e le unità devono essere 0.

Periodo di ripetizione del tentativo (facoltativo)

Questo utilizzo rappresenta la durata tra i tentativi della forma d'onda, misurata dall'ora di inizio del trigger precedente. Un valore pari a zero deve essere interpretato come identico alla durata predefinita per la forma d'onda, quindi il retrigger si verifica immediatamente dopo il completamento di quello precedente. I valori inferiori alla durata predefinita per la forma d'onda devono interrompere la forma d'onda e riavviarla.

Se questo utilizzo è supportato, è necessario supportare anche il conteggio delle ripetizioni e i tempi di riduzione.

L'host considererà i valori logici come millisecondi. Il minimo logico deve essere zero e il valore massimo logico deve essere almeno 1000 (che rappresenta un secondo). L'intervallo fisico deve essere zero o identico all'intervallo logico. Se l'intervallo fisico è diverso da zero, le unità devono essere millisecondi.

Time cutoff waveform (facoltativo)

Questo utilizzo rappresenta la quantità massima di tempo per cui un singolo trigger può comportare la riproduzione, tenendo conto del numero di ripetizioni e del periodo di ripetizione.

Se questo utilizzo è supportato, è necessario supportare anche il numero di ripetizioni e i tentativi di utilizzo.

L'host considererà i valori logici come millisecondi. Il valore minimo logico deve essere pari almeno alla durata della forma d'onda discreta più lunga, moltiplicata per il massimo logico dell'utilizzo del numero di ripetizioni. L'intervallo fisico deve essere zero o identico all'intervallo logico. Se l'intervallo fisico è diverso da zero, le unità devono essere millisecondi.

Linee guida per il touchpad aptico

Gli elementi in questa sezione si applicano solo ai touchpad aptici.

Device-Initiated Feedback aptico

Un touchpad aptico è responsabile dell'attivazione del feedback aptico quando determina che il pulsante della superficie del touchpad è stato premuto o rilasciato. Può scegliere di supportare i report SET_FEATURE per consentire la personalizzazione del comportamento dell'utente in questo modo:

  • L'intensità del feedback aptico
  • Forza necessaria per attivare una pressione di un pulsante

Entrambi i report delle funzionalità sono obbligatori se il touchpad supporta anche il feedback aptico avviato dall'host. Ogni report deve usare un ID report distinto, non usato con altri utilizzi.

Durante l'enumerazione, l'host valuterà l'intervallo logico e fisico supportato dal descrittore e calcola le opzioni esposte per l'interfaccia utente delle impostazioni, incluse le impostazioni predefinite. L'host rilascia il SET_FEATURE per comunicare il valore specificato dall'utente al dispositivo; questo rilascio può verificarsi in qualsiasi momento, ma deve verificarsi ogni volta che l'impostazione viene modificata, si verifica un cambio utente e quando il dispositivo viene enumerato o reimpostato.

Rapporto delle caratteristiche di intensità aptico

Questo report SET_FEATURE specifica la preferenza dell'utente per l'intensità del feedback aptico per la pressione e il rilascio dei pulsanti. Non si applica all'intensità di qualsiasi feedback avviato dall'host, se supportato dal dispositivo. Per supportare questa configurazione, il dispositivo deve definire una raccolta figlio logica SimpleHapticsController (Page 0x0E, Usage 0x01) nell'insieme di primo livello di Windows Precision Touchpad, contenente l'utilizzo dell'intensità aptico (Page 0x0E, Usage 0x23) come report delle funzionalità con un ID report dedicato. Questa raccolta figlio non deve contenere i trigger automatici (0x0E pagina, 0x20 di utilizzo) o l'attivazione manuale (0x0E pagina, utilizzo 0x21).

Il valore minimo logico deve essere uguale a zero. La preferenza dell'utente verrà ridimensionata in modo lineare nell'intervallo logico, con zero che indica che non deve essere attivato alcun feedback per la pressione e il rilascio del pulsante.

Report funzionalità pressione pulsante

Questo report SET_FEATURE specifica la preferenza dell'utente per la quantità di forza necessaria per attivare la pressione di un pulsante. Per supportare questa configurazione, il dispositivo deve definire l'utilizzo di Button Press Threshold (Page 0x0D, Usage 0xB0) come report delle funzionalità con un ID report dedicato nella raccolta principale di Windows Precision Touchpad.

L'intervallo logico deve essere mappato in modo lineare all'intervallo fisico di valori ed essere distanziato e centrato uniformemente intorno al valore predefinito. Dopo l'acquisizione dell'intervallo logico, il valore predefinito verrà calcolato usando la formula seguente:

Diagramma che mostra la formula per il calcolo della soglia di pressione del pulsante predefinita nelle unità logiche

Il valore Minimo logico, Predefinito e Massimo logico corrisponderà a 3 livelli distinti di pressione del pulsante esposti a un utente tramite l'interfaccia utente delle impostazioni di Windows (supportando rispettivamente "Low", "Medium" e "High").

L'intervallo fisico consigliato per Button Press Threshold è quello di coprire almeno l'intervallo compreso tra 110g e 190g, corrispondente rispettivamente ai valori minimo e massimo. Per un descrittore di esempio che usa un valore fisico massimo di 190g e Physical Minimum of 110g (in questo modo, in base alla formula precedente, il valore predefinito è 150g) vedere Descrittori di report di esempio.

Descrittori di report HID di esempio

Descrittore del Touchpad haptico di esempio

Il descrittore seguente supporta tutti gli utilizzi obbligatori e facoltativi. Dichiara il supporto per cinque forme d'onda, con la durata massima di 50 ms.

Tutti gli intervalli logici devono essere aggiornati in base al supporto dei dispositivi. Per supportare un numero diverso di forme d'onda:

  • L'intervallo logico dell'utilizzo del trigger manuale deve essere aggiornato
  • Gli intervalli di utilizzo e il conteggio dei report per l'elenco waveform e l'elenco di durata devono essere aggiornati

Per supportare una lunghezza massima diversa della forma d'onda, è necessario aggiornare gli intervalli logici seguenti:

  • Periodo di ripetizione del tentativo (output)
  • Time cutoff waveform (output)
  • Elenco durata (funzionalità)
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()

Il descrittore precedente è stato generato tramite il file Waratah seguente:

[[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'

Descrittore mouse aptico di esempio

Il descrittore seguente supporta tutti gli utilizzi obbligatori e facoltativi. Dichiara il supporto per otto forme d'onda, con una durata massima di 200 ms.

Tutti gli intervalli logici devono essere aggiornati in base al supporto dei dispositivi. Per supportare un numero diverso di forme d'onda:

  • L'intervallo logico dell'utilizzo del trigger manuale deve essere aggiornato
  • Gli intervalli di utilizzo e il conteggio dei report per l'elenco waveform e l'elenco di durata devono essere aggiornati

Per supportare una lunghezza massima diversa della forma d'onda, è necessario aggiornare gli intervalli logici seguenti:

  • Periodo di ripetizione del tentativo (output)
  • Time cutoff waveform (output)
  • Elenco durata (funzionalità)
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()

Il descrittore precedente è stato generato tramite il file Waratah seguente:

[[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'