Udostępnij przez


Napisz sterownik klienta kontrolera funkcji

W tym artykule opisano różne zadania wykonywane przez sterownik klienta kontrolera funkcji podczas interakcji z rozszerzeniem kontrolera funkcji USB (UFX).

Ważne interfejsy API

Opisuje różne zadania wykonywane przez sterownik klienta kontrolera funkcji podczas interakcji z rozszerzeniem kontrolera funkcji USB (UFX). UFX i sterownik klienta komunikują się ze sobą przy użyciu metod eksportu i funkcji wywołania zwrotnego zdarzeń. Metody eksportu (o nazwie UfxDeviceXxx lub UfxEndpointXxx) są eksportowane przez UFX i wywoływane przez sterownik klienta. Funkcje wywołania zwrotnego (nazwane EVT_UFX_Xxx) są implementowane w sterowniku klienta i wywoływane przez UFX.

UFX wywołuje funkcje wywołania zwrotnego asynchronicznie dla wszystkich sterowników klienta i jedno wywołanie zwrotne na raz w odniesieniu do obiektu. Na przykład istnieje obiekt urządzenia USB i trzy obiekty punktu końcowego. Co najwyżej cztery funkcje wywołania zwrotnego (jeden dla urządzenia i jeden dla każdego punktu końcowego) mogą być jednocześnie wywoływane. Dla każdej metody wywołania zwrotnego UFX czeka, aż sterownik klienta wywoła ufxDeviceEventComplete , aby wskazać, że sterownik zakończył żądanie. Jedyną inną metodą eksportu, którą UFX nasłuchuje podczas oczekiwania na eksport, jest UfxDeviceNotifyHardwareFailure. Wiele funkcji zwrotnych klienta jest opcjonalnych. Wymagane funkcje są następujące:

Inicjalizacja

  1. Sterownik klienta kontrolera funkcji uruchamia proces inicjowania, gdy program Windows Driver Foundation (WDF) wywołuje implementację sterownika klienta EVT_WDF_DRIVER_DEVICE_ADD wywołania zwrotnego. W tej implementacji sterownik klienta powinien wywołać element UfxFdoInit , a następnie utworzyć obiekt urządzenia przez wywołanie funkcji WdfDeviceCreate.
  2. Sterownik klienta wywołuje UfxDeviceCreate, aby utworzyć obiekt urządzenia USB i pobrać uchwyt UFXDEVICE.
  3. Sterownik klienta wywołuje UfxDeviceNotifyHardwareReady, aby wskazać UFX, że może teraz wywoływać funkcje wywołania zwrotnego sterownika klienta.
  4. UFX wykonuje zadania inicjowania, takie jak:
    • UFX wywołuje implementację EVT_UFX_DEVICE_DEFAULT_ENDPOINT_ADD sterownika klienta w celu utworzenia domyślnego punktu końcowego.
    • UFX tworzy podrzędne obiekty fizyczne urządzenia (PDO) dla interfejsów obsługiwanych przez urządzenie.
    • UFX czeka na aktywację sterownika klasy urządzenia po wysłaniu żądania IOCTL_INTERNAL_USBFN_ACTIVATE_USB_BUS . Oczekuje również na wywołanie sterownika klienta UfxDeviceNotifyAttach , który wskazuje, że urządzenie zostało dołączone.

Powiadomienie o sterowniku typu klasy

Aby otrzymywać powiadomienia o pakietach instalacyjnych i stanie magistrali, sterownik klasy powinien wysyłać żądania IOCTL_INTERNAL_USBFN_ACTIVATE_USB_BUS . UFX umieszcza te żądania w kolejkach powiadomień specyficznych dla sterowników klasy. Po otrzymaniu powiadomienia o zdarzeniu autobusu od sterownika klienta, UFX usuwa elementy z każdej odpowiedniej kolejki i kończy żądanie. Aby zapobiec braku powiadomień sterowników klas, UFX przechowuje kolejkę powiadomień o stałym rozmiarze dla sterownika klasy.

Zdarzenia dołączania i odłączania urządzenia

UFX zakłada, że urządzenie jest odłączone, dopóki sterownik klienta kontrolera funkcji nie wywołuje UfxDeviceNotifyAttach.

Po tym wywołaniu UFX ustawia stan urządzenia na Zasilane zgodnie ze specyfikacją USB. Aby powiadomić sterownik klienta o zmianie stanu, UFX wywołuje implementację EVT_UFX_DEVICE_USB_STATE_CHANGE sterownika klienta.

UFX powiadamia sterownik ładowarki (Cad.sys) w celu ułatwienia ładowania urządzenia. UFX również powiadamia sterowniki klasowe, kończąc wcześniejsze żądania IOCTL_INTERNAL_USBFN_BUS_EVENT_NOTIFICATION wysłane przez te sterowniki.

Sterownik klienta musi wywołać UfxDeviceNotifyDetach, gdy magistrala jest odpięta. Klient musi wywołać funkcję detach tylko raz po każdym wywołaniu funkcji UfxDeviceNotifyAttach. Po wywołaniu UfxDeviceNotifyDetach UFX wywołuje EVT_UFX_DEVICE_HOST_DISCONNECT (jeśli nie jest to zmiana interfejsu). Następnie program UFX wykonuje wszystkie zadania oczyszczania, takie jak czyszczenie wszystkich kolejek punktów końcowych i uruchamianie domyślnej kolejki punktu końcowego. UFX wywołuje EVT_UFX_DEVICE_USB_STATE_CHANGE i powiadamia sterowniki klas, poprzez ukończenie żądań IOCTL_INTERNAL_USBFN_BUS_EVENT_NOTIFICATION.

Awaria sprzętu

W przypadku wystąpienia błędu sprzętowego sterownik klienta powinien wywołać metodę UfxDeviceNotifyHardwareFailure. W odpowiedzi UFX usunie stos urządzenia i może spróbować wyjść z tej sytuacji, wywołując EVT_UFX_DEVICE_CONTROLLER_RESET sterownika klienta. Klient powinien zresetować kontroler do stanu początkowego. Jeśli wystąpi inna awaria sprzętowa, klient powinien ponownie wywołać metodę UfxDeviceNotifyHardwareFailure. Podczas drugiego wywołania UFX zarejestruje swój stan i przeprowadzi diagnostykę błędów.

Wykrywanie portów

Wykrywanie portów jest wykonywane przez UFX. Wywołuje funkcję EVT_UFX_DEVICE_PORT_DETECT wywołania zwrotnego sterownika kontrolera funkcji, aby określić typ portu, do którego jest dołączone urządzenie. Klient odpowiada, wywołując UfxDevicePortDetectComplete lub UfxDevicePortDetectCompleteEx z jednym z typów portów zdefiniowanych w USBFN_PORT_TYPE.

Jeśli klient nie może określić typu portu, klient powinien zgłosić port UsbfnUnknownPort. Jeśli port jest nieznany lub port podrzędny, ufX wywołuje funkcję EVT_UFX_DEVICE_HOST_CONNECT sterownika klienta. UFX nasłuchuje dźwięków autobusu przez jakiś czas. Jeśli port jest nieznany, ale istnieje ruch, taki jak pakiet instalacyjny, wówczas UFX przyjmie port UsbfnStandardDownstreamPort. W przeciwnym razie UFX przypisuje port jako UsbfnInvalidDedicatedChargingPort. Po ustaleniu typu portu UFX powiadamia Cad.sys i wywołuje funkcję EVT_UFX_DEVICE_PORT_CHANGE sterownika klienta. W funkcji oczekuje się, że sterownik klienta zmieni stan sprzętu, aby odpowiadał typowi portu UFX.

Tworzenie punktu końcowego

UFX tworzy domyślny punkt końcowy (punkt końcowy 0) przez wywołanie EVT_UFX_DEVICE_DEFAULT_ENDPOINT_ADD sterownika klienta, aby mógł obsługiwać pakiety instalacyjne wysyłane przez hosta. UFX tworzy inne punkty końcowe przez wywołanie EVT_UFX_DEVICE_ENDPOINT_ADD. UFX tworzy punkty końcowe tylko po wywołaniu sterownika klienta UfxDeviceNotifyHardwareReady. W tych funkcjach wywołania zwrotnego sterownik klienta ma wywołać metodę UfxEndpointCreate dla obiektu punktu końcowego i uzyskać jego uchwyt UFXENDPOINT. UFX ustawia element nadrzędny na obiekt PDO sterownika klasy skojarzony z interfejsem, do którego należy punkt końcowy. Obiektem nadrzędnym dla domyślnego punktu końcowego jest obiekt urządzenia USB. Punkt końcowy zawiera dwa obiekty kolejki w ramach struktury: kolejkę transferową i kolejkę poleceń, do których można uzyskać dostęp tylko wtedy, gdy urządzenie znajduje się w stanie skonfigurowanym (z wyjątkiem punktu końcowego 0, do którego można uzyskać dostęp po wywołaniach UFX EVT_UFX_DEVICE_HOST_CONNECT).

Enumeracja urządzeń

Sterownik klienta nie powinien zezwalać na połączenia z hostem, zanim usługa UFX wywoła funkcję sterownika EVT_UFX_DEVICE_HOST_CONNECT. Wyliczenie urządzenia rozpoczyna się, gdy sterownik klienta wywołuje UfxDeviceNotifyReset. W domyślnym stanie UFX obsługuje standardowe pakiety instalacyjne.

Resetować

UFX czyści wszystkie kolejki punktów końcowych i wysyła żądanie IOCTL_INTERNAL_USBFN_DESCRIPTOR_UPDATE do sterownika klienta w celu zaktualizowania wMaxPacketSize punktu końcowego 0. UfX uruchamia kolejkę domyślnego punktu końcowego i ustawia stan na Domyślny.

Wartość domyślna

UFX wywołuje funkcję EVT_UFX_DEVICE_USB_STATE_CHANGE sterownika klienta. Powiadamia również sterowniki klasy o stanie. Po odebraniu standardowego pakietu instalacyjnego SET_ADDRESS, UFX ustawia stan na Zaadresowany.

Skierowana

UFX wywołuje funkcję EVT_UFX_DEVICE_ADDRESSED sterownika klienta, aby wskazać klientowi, którego adresu należy użyć. - Jeśli adres ma wartość 0, UFX ustawia stan z powrotem na Wartość domyślna i wywołuje EVT_UFX_DEVICE_USB_STATE_CHANGE i powiadamia sterowniki klas. Po otrzymaniu standardowego pakietu instalacyjnego SET_CONFIGURATION ufX ustawia stan na Skonfigurowany.

Skonfigurowany

Jeśli wybrana konfiguracja to 0, UFX czyści punkty końcowe interfejsu i ustawia stan na Zaadresowany. UFX wysyła żądanie IOCTL_INTERNAL_USBFN_DESCRIPTOR_UPDATE do sterownika klienta w celu zaktualizowania wMaxPacketSize punktów końcowych interfejsu. UFX zapewnia, że wszystkie kolejki punktów końcowych interfejsu zakończyły przeczyszczanie i rozpoczynają działanie. Jeśli typ portu nie jest UsbfnStandardDownstreamPort lub UsbfnChargingDownstreamPort, UFX zmień typ portu na UsbfnStandardDownstreamPort i informuje Cad.sys; sterownik klienta przez wywołanie EVT_UFX_DEVICE_PORT_CHANGE i EVT_UFX_DEVICE_USB_STATE_CHANGE w celu zaktualizowania stanu; sterowniki klas skonfigurowanego stanu.

Standardowe transfery kontrolek

UfX może obsługiwać transfery kontrolek w domyślnym punkcie końcowym w dowolnym momencie po wywołaniu EVT_UFX_DEVICE_DEFAULT_ENDPOINT_ADD, w którym sterownik klienta tworzy domyślny punkt końcowy przy użyciu. Wszystkie transfery sterujące zaczynają się od 8-bajtowego pakietu inicjującego. Aby wysłać pakiet instalacyjny do hosta, sterownik klienta powinien wywołać metodę UfxEndpointNotifySetup. Standardowe transfery sterowania są wykonywane przez UFX. Jeśli istnieją dane skojarzone z transferem sterowania, UFX odczytuje i zapisuje do domyślnego punktu końcowego sterowania w odpowiedni sposób.

Transfery kontrolek spoza standardu

Jeśli UFX nie może obsłużyć transferu kontrolnego, transfer jest przekazywany do odpowiedniego sterownika klasy poprzez ukończenie żądania IOCTL_INTERNAL_USBFN_BUS_EVENT_NOTIFICATION. Transfery kontrolek mogą wystąpić w dowolnym punkcie końcowym zdefiniowanym jako punkt końcowy sterowania w deskryptorze punktu końcowego. Przesyłanie sterowania w punktach końcowych innych niż domyślny punkt końcowy sterowania jest zawsze niestandardowym przesyłaniem sterowania. Jeśli punkt końcowy kontroli jest domyślnym punktem końcowym kontroli, UFX powiadomi sterowniki klas o pakietach konfiguracji, które są oznaczone jako żądania klasy dla danego sterownika. Jeśli punkt końcowy sterowania należy do interfejsu, ufX powiadamia sterownik klasy skojarzony z tym interfejsem. W razie potrzeby sterowniki klas powinny odczytywać i zapisywać do punktu końcowego sterowania.

Transfery danych

Transfery danych są inicjowane przez sterowniki klasowe poprzez wysyłanie żądań IOCTL_INTERNAL_USBFN_TRANSFER_IN, IOCTL_INTERNAL_USBFN_TRANSFER_IN_APPEND_ZERO_PKT lub IOCTL_INTERNAL_USBFN_TRANSFER_OUT. Po zweryfikowaniu każdego z tych żądań UFX przekazuje go do odpowiedniej kolejki punktu końcowego do obsługi przez sterownik klienta. Oczekuje się, że sterownik klienta wykona dodatkową walidację. Sterownik klienta odbiera żądania transferu w kolejkach punktów końcowych. Sterownik klienta może pobierać tyle żądań z tej kolejki, ile jest potrzebne do zmaksymalizowania wykorzystania magistrali. Sterownik klienta powinien pomyślnie zakończyć żądania ze statusem STATUS_SUCCESS. Sterownik powinien dołożyć wszelkich starań, aby anulować żądania i zakończyć anulowane żądania ze statusem STATUS_CANCELLED, jeśli zostały one anulowane. Jeśli przekazano nieprawidłowe parametry, sterownik klienta kończy żądanie za pomocą STATUS_INVALID_PARAMETER.

Przenoszenie kontroli

Transfery sterowania zaczynają się od 8-bajtowego pakietu konfiguracji. Aby wysłać pakiet instalacyjny do hosta, sterownik klienta powinien wywołać metodę UfxEndpointNotifySetup. UFX powiadamia sterowniki klas o niestandardowych transferach kontrolek, wypełniając żądania powiadomień. Zarówno klienci, jak i UFX używają IOCTL_INTERNAL_USBFN_TRANSFER_IN, IOCTL_INTERNAL_USBFN_TRANSFER_IN_APPEND_ZERO_PKT lub IOCTL_INTERNAL_USBFN_TRANSFER_OUT do odczytu i zapisu do domyślnego punktu końcowego sterowania. Interfejs może jednak definiować inne punkty końcowe sterowania, których może używać tylko odpowiedni sterownik klasy. Punkty końcowe sterowania można zatrzymać w odpowiedzi na pakiet konfiguracyjny. Sterowniki klas wysyłają żądanie IOCTL_INTERNAL_USBFN_SET_PIPE_STATE , aby zatrzymać punkt końcowy. Oczekuje się, że sprzęt lub sterownik klienta natychmiast wznowi ruch na punkcie końcowym po wystąpieniu przerwania. Punkty końcowe kontroli mogą również wysyłać i odbierać pakiety o zerowej długości (ZLP) bez żadnych wcześniejszych danych. Sterownik klienta i UFX mogą to zrobić przy użyciu IOCTL_INTERNAL_USBFN_CONTROL_STATUS_HANDSHAKE_IN i IOCTL_INTERNAL_USBFN_CONTROL_STATUS_HANDSHAKE_OUT.

Transfery zbiorcze i przerywane

Transfery zbiorcze gwarantują dostarczanie danych i są używane do wysyłania dużych ilości danych. Transfery można wysyłać na masowym punkcie końcowym przy użyciu IOCTL_INTERNAL_USBFN_TRANSFER_IN, IOCTL_INTERNAL_USBFN_TRANSFER_IN_APPEND_ZERO_PKT lub IOCTL_INTERNAL_USBFN_TRANSFER_OUT. Zbiorcze punkty końcowe można zatrzymać podobnie do punktów końcowych sterujących przy użyciu IOCTL_INTERNAL_USBFN_SET_PIPE_STATE. Oczekuje się, że sterownik klienta wyśle pakiet STALL w odpowiedzi na wszystkie żądania hosta i wstrzymać żądania IOCTL. W przeciwieństwie do punktów końcowych kontrolnych, zatrzymany punkt końcowy zbiorczy pozostaje zatrzymany do momentu jawnego wyczyszczenia stanu zatrzymania.

Transfery przerwań są podobne do transferów zbiorczych, ale mają zagwarantowane opóźnienie. Transfery przerwań mają ten sam interfejs co transfery zbiorcze, ale nie mają możliwości przesyłania strumieniowego.

Transfery izochroniczne

Sterownik klienta nie powinien obsługiwać transferów izochronicznych w tej wersji.

Zarządzanie energią

Sterownik klienta zarządza wszystkimi aspektami zarządzania energią. Ponieważ funkcje wywołania zwrotnego są asynchroniczne, sterownik klienta powinien wrócić do odpowiedniego stanu zasilania i ukończyć żądanie przed wywołaniem odpowiedniej funkcji eksportu zakończenia zdarzeń, takiej jak UfxDeviceEventComplete.

UFX jest w stanie roboczym, jeśli stan urządzenia (zdefiniowany w USBFN_DEVICE_STATE) to UsbfnDeviceStateSuspended i UsbfnDeviceStateAttached i nie zgłosił typu portu. Alternatywnie UFX zgłosił typ portu (zdefiniowany w USBFN_PORT_TYPE) UsbfnStandardDownstreamPort lub UsbfnChargingDownstreamPort.

Interfejs UFX wchodzi w stan roboczy i opuszcza go przez wywołanie EVT_UFX_DEVICE_USB_STATE_CHANGE lub EVT_UFX_DEVICE_PORT_CHANGE. Przejście do lub ze stanu roboczego jest ukończone, gdy sterownik klienta wywołuje funkcję UfxDeviceEventComplete.

W stanie roboczym UFX może wywołać dowolne wywołanie zwrotne. Jeśli nie jest w stanie roboczym, UFX wywołuje tylko EVT_UFX_DEVICE_USB_STATE_CHANGE, aby przejść do stanu roboczego, oraz EVT_UFX_DEVICE_REMOTE_WAKEUP_SIGNAL, aby wykonać zdalne wznawianie podczas wstrzymania (jeśli jest obsługiwane).

Wstrzymanie urządzenia

Wstrzymanie urządzenia występuje, gdy w autobusie nie ma ruchu przez 3 milisekundy. W takim przypadku sterownik klienta musi poinformować UFX o wykryciu zawieszenia i wznowienia przez wywołanie polecenia UfxDeviceNotifySuspend i UfxDeviceNotifyResume. Po otrzymaniu tych połączeń UFX wywołuje EVT_UFX_DEVICE_USB_STATE_CHANGE i powiadamia sterowniki klas, realizując żądania IOCTL_INTERNAL_USBFN_BUS_EVENT_NOTIFICATION. Jeśli zdalne wznawianie jest obsługiwane przez urządzenie i włączone przez hosta, UFX może wywoływać wywołania EVT_UFX_DEVICE_USB_STATE_CHANGE podczas wstrzymania w celu wystawienia sygnału zdalnego wznawiania.