Udostępnij przez


Przewodnik implementacji haptyki urządzenia wejściowego

Ten dokument zawiera szczegółowe informacje na temat implementacji protokołu dla haptycznych urządzeń wejściowych łączących się z zgodnym hostem systemu Windows 11. Nie obejmuje to wskazówek dotyczących ograniczeń mechanicznych, ograniczeń elektrycznych lub wyboru składników do generowania odpowiedzi haptycznej w sprzęcie urządzenia wejściowego.

Obsługiwane klasy urządzeń

System Windows 11 obsługuje następujące klasy urządzeń wejściowych z haptyczną obsługą.

  • Haptic Touchpad to rozszerzenie klasy urządzenia Touchpad w systemie Windows. Ten przewodnik implementacji dodaje do przewodnika implementacji touchpad i koncentruje się na implementowaniu haptyki w cyferyzatorze touchpad, więc dotykowe tablety dotykowe muszą spełniać wymagania w Przewodniku implementacji touchpad oprócz tych zawartych w tym miejscu.

  • Haptic Mouse to rozszerzenie klasy Urządzenia myszy w systemie Windows. Myszy haptyczne muszą spełniać wymagania zawarte w tej dokumentacji.

Uwaga: urządzenia wejściowe pióra z obsługą haptycznej są specjalną klasą urządzeń, która nie zostanie omówiona w tym dokumencie. Aby uzyskać informacje na temat implementacji urządzenia pióra z haptycznym sprzężeniem zwrotnym, zobacz w Przewodniku po implementacji haptycznego pióra.

Implementacja protokołu urządzenia wejściowego Haptics

Aby zrozumieć przedstawione tutaj informacje, należy dobrze zrozumieć protokół HID. Aby uzyskać informacje o protokole HID, zobacz następujące zasoby:

Oprogramowanie układowe urządzenia wejściowego z obsługą haptyczną musi zgłaszać tylko użycia opisane w tym temacie. System Windows będzie używać oprogramowania układowego i własnych sterowników HID, aby włączyć urządzenie i zapewnić aplikacjom systemu Windows dostęp do urządzenia.

Przykładowe deskryptory dla każdej obsługiwanej klasy urządzeń znajdują się w poniższej sekcji Przykładowe deskryptory raportów.

Typowe wskazówki

Elementy w tej sekcji dotyczą wszystkich klas haptycznych urządzeń wejściowych.

Wymagana kolekcja HID

Funkcje związane z haptyki muszą być zawarte w kolekcji HID SimpleHapticsController (Page 0xE, Usage 0x1).

W przypadku urządzeń Haptic Touchpad kolekcja ta musi być elementem podrzędnym najwyższego poziomu kolekcji Windows Precision Touchpad.

W przypadku urządzeń myszy haptycznej ta kolekcja musi być główną kolekcją i elementem równorzędnym do głównej kolekcji myszy.

Device-Initiated haptic feedback

Urządzenie wejściowe z obsługą haptycznych może opcjonalnie obsługiwać inicjowanie własnych opinii haptycznych, np. w odpowiedzi na naciśnięcie lub zwolnienie przycisku.

W przypadku dotykowych gładzików, w sekcji "Wskazówki dotyczące haptycznego gładzika" poniżej opisano sposób, w jaki urządzenie może wybrać obsługę raportów SET_FEATURE, aby umożliwić użytkownikowi dostosowanie jego zachowania podczas inicjowania informacji zwrotnej haptycznej.

Myszy haptyczne mogą wyzwalać sprzężenie zwrotne inicjowane przez urządzenie, ale system Windows nie ma mechanizmu do konfigurowania tego zachowania.

Host-Initiated haptic feedback

Urządzenie wejściowe z obsługą haptyczną może obsługiwać informacje zwrotne haptyczne inicjowane przez hosta, które mogą wystąpić w dowolnej chwili po wyliczeniu.

Haptic touchpady i myszy mogą opcjonalnie wspierać informację zwrotną inicjowaną przez hosta. W przypadku gładzików dotykowych, jeśli obsługiwana jest informacja zwrotna inicjowana przez hosta, muszą być również obsługiwane oba raporty SET_FEATURE dotyczące dostosowywania informacji zwrotnej inicjowanej przez urządzenie.

Obsługa haptycznych opinii inicjowanych przez hosta wymaga dwóch kolekcji logicznych elementów podrzędnych SimpleHapticsController (page 0x0E, Usage 0x01). Te kolekcje logiczne muszą być elementami podrzędnymi głównej kolekcji SimpleHapticsController dla implementowanych klas urządzeń (zgodnie z opisem w powyższej sekcji "Wymagana kolekcja HID") i muszą być oddzielone od kolekcji używanej do konfigurowania intensywności sprzężenia zwrotnego haptycznego inicjowanego przez urządzenie dla płytek dotykowych. Jedna z tych logicznych kolekcji podrzędnych musi zdefiniować raport GET_FEATURE używany przez hosta do wykonywania zapytań dotyczących obsługiwanych kształtów falowych i ich czasów trwania. Drugi podrzędny zbiór logiczny musi zdefiniować raport wyjściowy używany przez hosta do ręcznego uruchamiania funkcji haptycznych.

Urządzenie nie może zadeklarować obsługi automatycznie wyzwalanych haptyki, a urządzenie nie może obsługiwać żadnych ciągłych kształtów fal.

Przebiegów

W poniższej tabeli zdefiniowano kształty fal sygnału obsługiwane przez hosta dla urządzeń wejściowych z funkcją haptyczną. Kształty fali obsługiwane przez urządzenie są skojarzone z porządkowymi. Użycie i czas trwania kształtów falowych są udostępniane hostowi za pośrednictwem raportu funkcji informacji o formach falowych (patrz poniżej). Podczas wyzwalania opinii host udostępnia porządkowy żądany kształt fali jako wartość użycia wyzwalacza ręcznego.

Obowiązkowe i opcjonalne
Przebiegu Description Strona identyfikator Obowiązkowe/opcjonalne
Żaden Brak operacji. Nie należy wpływać na stan odtwarzania bieżących kształtów fali 0x0E 0x1001 Mandatory
Zatrzymaj Zatrzymuje odtwarzanie trwających kształtów fal 0x0E 0x1002 Mandatory
Hover Impuls światła używany do wskazywania aktywowania i sygnalizowania potencjału nadchodzącej akcji 0x0E 0x1008 Mandatory
Zderzają się Impuls miękki używany do wskazywania kolizji z granicami ekranu lub końcami suwaków i pasków przewijania 0x0E 0x1012 Mandatory
Align Ostry impuls, który potwierdza wyrównanie obiektu podczas przeciągania, skalowania lub obracania interakcji z prowadnicami lub krawędziami kanwy 0x0E 0x1013 Mandatory
Step Mocny impuls używany do przechodzenia przez elementy w suwakach, listach lub szorach 0x0E 0x1014 Mandatory
Rosnąć Impuls dynamiczny, który przekazuje ruch, przejścia lub inteligentną aktywność systemu 0x0E 0x1015 Mandatory
Prasa Sygnał haptyczny wyzwalany przez urządzenie, gdy określa, że przycisk powierzchni został naciśnięty. Jeśli jest obsługiwana, wersja musi być również obsługiwana. 0x0E 0x1006 Opcjonalnie
Uwolnij Sygnał haptyczny wyzwalany przez urządzenie, gdy określa, że przycisk powierzchni został zwolniony. Jeśli jest obsługiwana, naciśnięcie musi być również obsługiwane. 0x0E 0x1007 Opcjonalnie
Powodzenie Silny sygnał haptyczny ostrzegawczego użytkownika, że akcja powiodła się 0x0E 0x1009 Opcjonalnie
Error Silny sygnał haptyczny ostrzegawcy użytkownika, że akcja nie powiodła się lub wystąpił błąd 0x0E 0x100A Opcjonalnie
Zakazany

Następujące kształty fali NIE MOGĄ być obsługiwane.

Przebiegu identyfikator Notatki
Kliknij 0x1003 Spowodowałoby to zamieszanie z istniejącymi haptycznymi opiniami dotyczącymi naciśnięcia przycisków.
Buzz Continuous 0x1004 Ciągłe kształty fal nie powinny być obsługiwane.
Ciągłe rumble 0x1005 Ciągłe kształty fal nie powinny być obsługiwane.
Ciągłe pisma odwłocznego 0x100B Dotyczy tylko długopisów.
Ołówek ciągły 0x100C Dotyczy tylko długopisów.
Znacznik ciągły 0x100D Dotyczy tylko długopisów.
Znacznik szselowy ciągły 0x100E Dotyczy tylko długopisów.
Szczotka ciągła 0x100F Dotyczy tylko długopisów.
Gumka ciągła 0x1010 Dotyczy tylko długopisów.
Sparkle Ciągły 0x1011 Dotyczy tylko długopisów.

Raport funkcji informacji o kształtach falowych

Host wyda ten raport GET_FEATURE podczas wykonywania zapytań dotyczących urządzenia pod kątem obsługiwanych kształtów fali. Ten raport funkcji musi mieć dedykowany identyfikator raportu.

Kolekcja logiczna musi mieć dwie podrzędne kolekcje logiczne, jedną dla listy kształtów falowych i jedną dla listy czasu trwania. Te kolekcje muszą definiować zakres użycia na stronie porządkowej (0x0A), która umożliwia hostowi wykonywanie zapytań o kształt fali i czas trwania skojarzony z każdą porządkową.

Obowiązkowe i opcjonalne użycie
Członek Description Strona identyfikator Obowiązkowe/opcjonalne
Lista kształtów falowych Kolekcja logiczna zawierająca uporządkowaną listę haptycznych kształtów fali obsługiwanych przez urządzenie 0x0E 0x10 Mandatory
Lista czasu trwania Kolekcja logiczna zawierająca uporządkowaną listę czasów trwania kształtów falowych na liście kształtów fali 0x0E 0x11 Mandatory
Lista kształtów falowych (obowiązkowe)

Ta kolekcja zawiera mapowanie między regułami i odpowiednimi kształtami fal. Reguły 1 i 2 odpowiadają WAVEFORM_NONE i WAVEFORM_STOP niejawnie i nie muszą być deklarowane w deskryptorze. W związku z tym minimalna wartość użycia zakresu użycia kolekcji może wynosić 3, a maksymalny rozmiar użycia powinien być wystarczająco duży, aby przypisać reguły do wszystkich obsługiwanych kształtów falowych.

Jeśli wartość maksymalna użycia jest większa niż liczba kształtów fal obsługiwanych przez urządzenie, urządzenie powinno zgłosić WAVEFORM_NONE dla nieobsługiwanych wartości zwykłych.

Zakres logiczny zakresu użycia powinien obejmować wszystkie obsługiwane użycie kształtów falowych. Zakres fizyczny i jednostki muszą mieć wartość 0.

Lista czasu trwania (obowiązkowe)

Ta kolekcja zawiera czasy trwania kształtów fal zdefiniowanych na liście kształtów falowych. Minimalne i maksymalne użycie zakresu użycia kolekcji muszą być identyczne z wartościami listy kształtów falowych.

Dyskretne kształty fali muszą mieć niezerowy czas trwania. WAVEFORM_NONE i WAVEFORM_STOP, jeśli określono, muszą mieć czas trwania zero.

Logiczne minimum zakresu użycia musi wynosić zero, a wartość logiczna musi być co najmniej tak duża, jak czas trwania najdłuższego dyskretnego kształt fali. Host będzie traktować wartości logiczne jako milisekundy. Zakres fizyczny musi być zerowy lub identyczny z zakresem logicznym. Jeśli zakres fizyczny i zakres logiczny są zgodne, jednostki powinny być milisekundami.

Raport wyjściowy wyzwalacza ręcznego

Host wyda ten raport podczas wyzwalania dyskretnych opinii haptycznych. Ten raport wyjściowy musi mieć dedykowany identyfikator raportu.

Obowiązkowe i opcjonalne użycie
Członek Description Strona identyfikator Obowiązkowe/opcjonalne
Wyzwalacz ręczny Kształt fali do wyzwolenia jako jawne polecenie z hosta 0x0E 0x21 Mandatory
Intensywność Intensywność opinii 0x0E 0x23 Mandatory
Liczba powtórzeń Liczba powtórzeń opinii po początkowym odtwarzaniu 0x0E 0x24 Opcjonalnie
Okres ponownego pobierania Czas oczekiwania przed ponownym wyzwoleniem opinii podczas powtarzania 0x0E 0x25 Opcjonalnie
Czas odcięcia kształtów falowych Maksymalny czas odtwarzania opinii przed odcięciem 0x0E 0x28 Opcjonalnie
Zabronione użycie
Usage identyfikator Notatki
Wyzwalacz automatyczny 0x20 Nieobsługiwane przez hosta.
Kontrolka skojarzona z automatycznym wyzwalaczem 0x22 Nieobsługiwane przez hosta.
Wyzwalacz ręczny (obowiązkowy)

To użycie zawiera porządkowość kształtów fali, zgodnie z definicją w raporcie funkcji informacji o formach falowych, który został poproszony o odtworzenie przez hosta. Gdy raport wyjściowy zawierający porządkowy inny niż WAVEFORM_NONE jest wysyłany do urządzenia, powinien natychmiast rozpocząć odtwarzanie określonego kształta fali z dodatkowymi właściwościami zawartymi w raporcie wyjściowym (intensywność, liczba powtórzeń, okres pobierania, czas odcięcia, jeśli jest obsługiwany). Urządzenie powinno uwzględniać tylko reguły dyskretnych kształtów fal, WAVEFORM_NONE i WAVEFORM_STOP. Jeśli porządkowy odpowiada WAVEFORM_STOP, wszelkie trwające dyskretne odtwarzanie kształtów falowych powinno zostać zatrzymane. Jeśli porządkowy odpowiada WAVEFORM_NONE, nie należy wykonywać żadnych działań, a ciągłe opinie zwrotne powinny nadal działać.

Zakres logiczny musi zawierać wszystkie możliwe reguły, w tym niejawne reguły 1 (WAVEFORM_NONE) i 2 (WAVEFORM_STOP). Zakres fizyczny i jednostki muszą mieć wartość 0.

Intensywność (obowiązkowe)

To użycie reprezentuje wartość procentową maksymalnej intensywności, która ma być stosowana do żądanego kształtów falowych, z wartością logiczną maksymalną reprezentującą maksymalną intensywność i wartość logiczną reprezentującą w ogóle brak opinii.

Minimum logiczne musi wynosić zero, a wartość logiczna powinna być wybierana na podstawie możliwości urządzenia — na przykład jeśli urządzenie obsługuje cztery poziomy intensywności, wartość logiczna powinna wynosić cztery. Jeśli urządzenie obsługuje bardziej szczegółową intensywność, wartość logiczna może być większa, ale nie powinna przekraczać 100. Urządzenie musi obsługiwać co najmniej cztery poziomy intensywności, więc minimalna wartość logiczna wynosi cztery. Intensywność zerowa wskazuje, że nie należy odtwarzać żadnych opinii — host będzie używać tej wartości tylko dla WAVEFORM_STOP.

Zakres fizyczny i jednostki muszą mieć wartość 0.

Liczba powtórzeń (opcjonalnie)

To użycie reprezentuje liczbę powtórzeń kształt fali po początkowym odtwarzaniu. Wartość zero wskazuje, że kształt fali powinien być odtwarzany tylko raz.

Jeśli to użycie jest obsługiwane, okres ponownego pobierania i użycie czasu redukcji również musi być obsługiwane.

Wartość minimalna logiczna musi być równa zero, a wartość logiczna musi być większa niż zero. Maksymalna wartość logiczna powinna być ograniczona do małej wartości (na przykład 10). Zakres fizyczny i jednostki muszą mieć wartość 0.

Okres ponownego pobierania (opcjonalnie)

To użycie reprezentuje czas trwania między ponawianiami kształtów fal, mierzony od czasu rozpoczęcia poprzedniego wyzwalacza. Wartość zero powinna być interpretowana jako identyczna z domyślnym czasem trwania dla kształtów fali, więc ponowne pobieranie następuje natychmiast po zakończeniu poprzedniego. Wartości mniejsze niż domyślny czas trwania kształt fali powinny przerwać kształt fali i ponownie go uruchomić.

Jeśli to użycie jest obsługiwane, należy również obsługiwać użycie liczby powtórzeń i czasu redukcji.

Host będzie traktować wartości logiczne jako milisekundy. Wartość logiczna musi wynosić zero, a wartość logiczna musi wynosić co najmniej 1000 (reprezentując jedną sekundę). Zakres fizyczny musi być zerowy lub identyczny z zakresem logicznym. Jeśli zakres fizyczny jest inny niż zero, jednostki powinny być milisekundami.

Czas odcięcia kształtów falowych (opcjonalnie)

To użycie reprezentuje maksymalny czas, przez jaki pojedynczy wyzwalacz może spowodować odtwarzanie, biorąc pod uwagę liczbę powtórzeń i okres ponownego pobierania.

Jeśli to użycie jest obsługiwane, liczba powtórzeń i ponowne pobieranie użycia muszą być również obsługiwane.

Host będzie traktować wartości logiczne jako milisekundy. Minimum logiczne musi być co najmniej tak duże, jak czas trwania najdłuższego dyskretnego kształt fali, pomnożony przez logiczne maksymalne użycie liczby powtórzeń. Zakres fizyczny musi być zerowy lub identyczny z zakresem logicznym. Jeśli zakres fizyczny jest inny niż zero, jednostki powinny być milisekundami.

Wskazówki dotyczące haptycznego panelu dotykowego

Elementy w tej sekcji dotyczą tylko dotykowych tabletów dotykowych.

Device-Initiated haptic feedback

Haptic touchpad jest odpowiedzialny za wyzwalanie haptycznych opinii, gdy określa, że przycisk powierzchni touchpad został naciśnięty lub zwolniony. Może on obsługiwać raporty SET_FEATURE, aby umożliwić użytkownikom dostosowywanie jego zachowania podczas wykonywania tych czynności:

  • Intensywność haptycznych opinii
  • Siła wymagana do wyzwolenia naciśnięcia przycisku

Oba te raporty funkcji są obowiązkowe, jeśli touchpad obsługuje również opinie haptyczne inicjowane przez hosta. Każdy raport musi używać odrębnego identyfikatora raportu, który nie jest używany z żadnym innym użyciem.

Podczas wyliczania host oceni obsługiwany zakres logiczny i fizyczny z deskryptora i obliczy uwidocznione opcje interfejsu użytkownika ustawień, w tym wartości domyślne. Host wydaje SET_FEATURE, aby przekazać użytkownikowi określoną wartość do urządzenia; wystawianie może wystąpić w dowolnym momencie, ale występuje za każdym razem, gdy ustawienie zostanie zmienione, nastąpi przełączenie użytkownika i gdy urządzenie zostanie wyliczone lub zresetowane.

Raport funkcji intensywności haptycznej

Ten raport SET_FEATURE określa preferencje użytkownika dotyczące intensywności haptycznej opinii na temat naciśnięcia i wydania przycisku. Nie ma zastosowania do intensywności jakiejkolwiek opinii zainicjowanej przez hosta, jeśli jest obsługiwana przez urządzenie. Aby obsługiwać tę konfigurację, urządzenie musi zdefiniować logiczną kolekcję podrzędną SimpleHapticsController (page 0x0E, Usage 0x01) w kolekcji najwyższego poziomu windows Precision Touchpad zawierającą użycie intensywności haptic (Page 0x0E, Usage 0x23) jako raport funkcji z dedykowanym identyfikatorem raportu. Ta kolekcja podrzędna nie może zawierać użycia wyzwalacza automatycznego (0x0E strony, 0x20 użycia) ani wyzwalacza ręcznego (0x0E strony, 0x21 użycia).

Minimum logiczne musi być równe zero. Preferencja użytkownika będzie liniowo skalowana do zakresu logicznego z zerowym wskazującym, że żadne opinie nie powinny być wyzwalane dla naciśnięcia i zwolnienia przycisku.

Raport funkcji naciśnięcia przycisku— próg

Ten raport SET_FEATURE określa preferencje użytkownika dotyczące ilości siły wymaganej do wyzwolenia naciśnięcia przycisku. Aby obsługiwać tę konfigurację, urządzenie musi zdefiniować użycie przycisku Naciśnij próg (strona 0x0D, użycie 0xB0) jako raport funkcji z dedykowanym identyfikatorem raportu w kolekcji najwyższego poziomu windows Precision Touchpad.

Zakres logiczny jest liniowo mapowany na fizyczny zakres wartości i równomiernie rozmieszczony i wyśrodkowany wokół wartości domyślnej. Po uzyskaniu zakresu logicznego wartość domyślna zostanie obliczona przy użyciu następującej formuły:

Diagram przedstawiający formułę obliczania domyślnego progu naciśnięcia przycisku w jednostkach logicznych

Wartość Minimum logiczne, Wartość domyślna i Wartość logiczna odpowiada 3 odrębnym poziomom naciśnięcia przycisku uwidocznionemu użytkownikowi za pośrednictwem interfejsu użytkownika ustawień systemu Windows (obsługującego odpowiednio "Niski", "Średni" i "Wysoki").

Zalecany zakres fizyczny dla progu naciśnięcia przycisku jest co najmniej pokrycie zakresu od 110g do 190g, co odpowiada odpowiednio minimalnym i maksymalnym wartościom. W przypadku deskryptora próbki korzystającego z wartości Fizycznej maksymalnej 190g i fizycznej minimalnej 110g (w związku z tym na podstawie powyższej formuły domyślna wartość domyślna to 150g), zobacz Przykładowe deskryptory raportów.

Przykładowe deskryptory raportów HID

Przykładowy deskryptor haptycznego touchpada

Poniższy deskryptor obsługuje wszystkie obowiązkowe i opcjonalne użycie. Deklaruje wsparcie dla pięciu kształtów fal, z najdłuższym okresem trwania 50 ms.

Wszystkie zakresy logiczne powinny być aktualizowane na podstawie obsługi urządzeń. Aby obsługiwać inną liczbę kształtów fal:

  • Należy zaktualizować zakres logiczny użycia wyzwalacza ręcznego
  • Należy zaktualizować zakresy użycia i liczbę raportów dla listy kształtów falowych i listy czasu trwania

Aby obsługiwać inną maksymalną długość kształtów fali, należy zaktualizować następujące zakresy logiczne:

  • Okres pobierania (dane wyjściowe)
  • Czas odcięcia kształtów falowych (dane wyjściowe)
  • Lista czasu trwania (funkcja)
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()

Powyższy deskryptor został wygenerowany za pośrednictwem następującego pliku Waratah :

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

Przykładowy opis myszy haptycznej

Poniższy deskryptor obsługuje wszystkie obowiązkowe i opcjonalne użycie. Deklaruje wsparcie dla ośmiu kształtów fali, z najdłuższym okresem trwania 200 ms.

Wszystkie zakresy logiczne powinny być aktualizowane na podstawie obsługi urządzeń. Aby obsługiwać inną liczbę kształtów fal:

  • Należy zaktualizować zakres logiczny użycia wyzwalacza ręcznego
  • Należy zaktualizować zakresy użycia i liczbę raportów dla listy kształtów falowych i listy czasu trwania

Aby obsługiwać inną maksymalną długość kształtów fali, należy zaktualizować następujące zakresy logiczne:

  • Okres pobierania (dane wyjściowe)
  • Czas odcięcia kształtów falowych (dane wyjściowe)
  • Lista czasu trwania (funkcja)
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()

Powyższy deskryptor został wygenerowany za pośrednictwem następującego pliku Waratah :

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