Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Sterowniki mogą definiować interfejsy specyficzne dla urządzenia, do których mogą uzyskiwać dostęp inne sterowniki. Te interfejsy zdefiniowane przez sterownik mogą składać się z zestawu procedur wywoływanych, zestawu struktur danych lub obu tych metod. Sterownik zazwyczaj dostarcza wskaźniki do tych procedur i struktur w strukturze interfejsu zdefiniowanego przez sterownik, który sterownik udostępnia innym sterownikom.
Na przykład sterownik autobusu może dostarczyć jedną lub więcej procedur, które sterowniki wyższego poziomu mogą wywołać w celu uzyskania informacji o urządzeniu podrzędnym, jeśli te informacje nie są dostępne na liście zasobów urządzenia podrzędnego.
Aby zapoznać się z przykładem zestawu interfejsów zdefiniowanych przez sterowniki, które są udokumentowane w zestawie WDK, zobacz procedury USB. Zobacz również wersję opartą na frameworku przykładu toster.
Tworzenie interfejsu
Każdy interfejs zdefiniowany przez sterownik jest określony przez:
Identyfikator GUID
Numer wersji
Struktura interfejsu zdefiniowanego przez sterownik
Procedury odwołań i dereferencji
Aby utworzyć interfejs i udostępnić go innym sterownikom, sterowniki oparte na strukturze mogą wykonać następujące czynności:
Definiowanie struktury interfejsu.
Pierwszym członem tej struktury zdefiniowanej przez sterownik musi być struktura nagłówka INTERFACE. Członkowie dodatkowi mogą obejmować dane interfejsu i wskaźniki do dodatkowych struktur lub procedur, które inny sterownik może wywołać.
Sterownik musi podać WDF_QUERY_INTERFACE_CONFIG strukturę, która opisuje zdefiniowany interfejs.
Uwaga
W przypadku korzystania z WDF_QUERY_INTERFACE_CONFIG, WDF nie obsługuje wielu wersji pojedynczego interfejsu, które używają tego samego identyfikatora GUID interfejsu.
W związku z tym podczas wprowadzania nowej wersji istniejącego interfejsu zalecamy utworzenie nowego identyfikatora GUID zamiast zmiany pól Rozmiaru lub Wersji struktury INTERFACE.
Jeśli sterownik ponownie wykorzystuje ten sam identyfikator GUID interfejsu ze zmodyfikowanymi polami Size lub Version, to sterownik nie powinien dostarczać WDF_QUERY_INTERFACE_CONFIG, lecz zamiast tego powinien zapewnić EvtDeviceWdmIrpPreprocess funkcjonalność wywołania zwrotnego dla IRP_MN_QUERY_INTERFACE.
Wywołaj WdfDeviceAddQueryInterface.
MetodaWdfDeviceAddQueryInterface wykonuje następujące czynności:
- Przechowuje informacje o interfejsie, takie jak identyfikator GUID, numer wersji i rozmiar struktury, dzięki czemu platforma może rozpoznać żądanie innego sterownika dla interfejsu.
- Rejestruje opcjonalną funkcję wywołania zwrotnego zdarzenia EvtDeviceProcessQueryInterfaceRequest, którą struktura wywołuje, gdy inny sterownik żąda interfejsu.
Każde wystąpienie interfejsu zdefiniowanego przez sterownik jest skojarzone z pojedynczym urządzeniem, dlatego sterowniki zazwyczaj wywołują WdfDeviceAddQueryInterface w funkcji EvtDriverDeviceAdd lub EvtChildListCreateDevice jako funkcji wywołania zwrotnego.
Uzyskiwanie dostępu do interfejsu
Jeśli sterownik zdefiniował interfejs, inny sterownik oparty na strukturze może zażądać dostępu do interfejsu, wywołując WdfFdoQueryForInterface i przekazując identyfikator GUID, numer wersji, wskaźnik do struktury i rozmiar struktury. Struktura tworzy żądanie we/wy i wysyła je do góry stosu sterowników.
Sterownik zwykle wywołuje WdfFdoQueryForInterface z poziomu funkcji wywołania zwrotnego EvtDriverDeviceAdd. Alternatywnie, jeśli sterownik musi zwolnić interfejs, gdy urządzenie nie jest w stanie pracy, sterownik może wywołać WdfFdoQueryForInterface z poziomu funkcji wywołania zwrotnego EvtDevicePrepareHardware i wywołać rutynę dereferencji interfejsu z poziomu funkcji wywołania zwrotnego EvtDeviceReleaseHardware.
Jeśli sterownik A prosi sterownik B o interfejs zdefiniowany przez sterownik B, platforma obsługuje żądanie dla sterownika B. Platforma sprawdza, czy identyfikator GUID i wersja reprezentują obsługiwany interfejs oraz czy rozmiar struktury dostarczony przez sterownik A jest wystarczająco duży, aby pomieścić interfejs.
Gdy sterownik wywołuje WdfFdoQueryForInterface, żądanie we/wy tworzone przez framework przechodzi aż do najniższego poziomu stosu sterowników. Jeśli prosty stos sterowników składa się z trzech sterowników — A, B i C — i jeśli sterownik A prosi o interfejs, zarówno sterownik B, jak i sterownik C mogą obsługiwać interfejs. Na przykład sterownik B może wypełnić strukturę interfejsu sterownika A przed przekazaniem żądania do sterownika C. Sterownik C może zapewnić EvtDeviceProcessQueryInterfaceRequest funkcji wywołania zwrotnego, która analizuje zawartość struktury interfejsu i ewentualnie je modyfikuje.
Jeśli sterownik A musi uzyskać dostęp do interfejsu sterownika B, a sterownik B jest zdalnym elementem docelowym we/wy (czyli sterownikiem znajdującym się w innym stosie sterowników), sterownik A powinien wywołać WdfIoTargetQueryForInterface zamiast WdfFdoQueryForInterface.
Korzystanie z komunikacji One-Way lub Two-Way
Można zdefiniować interfejs zapewniający komunikację jednokierunkową lub taki, który zapewnia dwukierunkową komunikację. Aby określić dwukierunkową komunikację, sterownik ustawia członek ImportInterface w strukturze WDF_QUERY_INTERFACE_CONFIG na TRUE.
Jeśli interfejs zapewnia komunikację jednokierunkową, a sterownik A prosi o interfejs sterownika B, dane interfejsu przepływa tylko ze sterownika B do sterownika A. Gdy platforma odbiera żądanie sterownika A dla interfejsu obsługującego komunikację jednokierunkową, struktura kopiuje wartości interfejsu zdefiniowanego przez sterownik do struktury interfejsu A sterownika. Następnie wywołuje EvtDeviceProcessQueryInterfaceRequest funkcję wywołania zwrotnego sterownika B, jeśli istnieje, aby można było sprawdzić i ewentualnie zmodyfikować wartości interfejsu.
Jeśli interfejs zapewnia dwukierunkową komunikację, struktura interfejsu zawiera niektóre elementy członkowskie, które sterownik A wypełnia przed wysłaniem żądania do sterownika B. Sterownik B może odczytać wartości parametrów podanych przez sterownik A i dokonać wyborów, na podstawie tych wartości, o których informacje należy dostarczyć sterownikowi A. Gdy platforma odbiera żądanie sterownika A dla interfejsu obsługującego komunikację dwukierunkową, platforma wywołuje funkcję wywołania zwrotnego EvtDeviceProcessQueryInterfaceRequest, aby umożliwić sprawdzenie odebranych wartości i podanie wartości wyjściowych. W przypadku komunikacji dwukierunkowej funkcja wywołania zwrotnego jest wymagana, ponieważ struktura nie kopiuje żadnych wartości interfejsu do struktury interfejsu sterownika A.
Utrzymanie liczby odwołań
Każdy interfejs musi zawierać funkcję zwiększania liczników i funkcję zmniejszania liczników, które zwiększają i zmniejszają liczbę odwołań dla interfejsu. Sterownik definiujący interfejs określa adresy tych funkcji w strukturze INTERFACE.
Gdy sterownik A prosi sterownik B o interfejs, framework wywołuje funkcję referencyjną interfejsu przed udostępnieniem go sterownikowi A. Gdy sterownik A zakończył korzystanie z interfejsu, musi wywołać funkcję dereferencji interfejsu.
Funkcje odwołań i wyłuszeń dla większości interfejsów mogą być funkcjami no-op, które nic nie robią. Framework udostępnia funkcje zliczania odwołań no-op, WdfDeviceInterfaceReferenceNoOp i WdfDeviceInterfaceDereferenceNoOp, których można używać w większości sterowników.
Jedynym momentem, kiedy sterowniki muszą śledzić liczbę odwołań interfejsu i zapewnić prawdziwe funkcje referencji i dereferencji, jest to, gdy sterownik A żąda interfejsu od zdalnego celu I/O (czyli sterownika, który znajduje się w innym stosie sterowników). W takim przypadku sterownik B (w innym stosie) musi zaimplementować licznik referencji, aby uniemożliwić usunięcie urządzenia, gdy sterownik A korzysta z interfejsu sterownika B.
Jeśli projektujesz sterownik B, który definiuje interfejs, musisz zdecydować, czy interfejs sterownika będzie uzyskiwany z innego stosu sterowników. (Sterownik B nie może ustalić, czy żądanie interfejsu pochodzi z lokalnego stosu sterowników lub z stosu zdalnego). Jeśli sterownik będzie obsługiwać żądania interfejsu z stosu zdalnego, sterownik musi zaimplementować liczbę odwołań.
Jeśli projektujesz sterownik A, który uzyskuje dostęp do interfejsu na zdalnym obiekcie docelowym we/wy, sterownik musi zapewnić funkcję wywołania zwrotnego EvtIoTargetQueryRemove, która zwalnia interfejs, gdy urządzenie sterownika B ma zostać usunięte, funkcję wywołania zwrotnego EvtIoTargetRemoveComplete, która zwalnia interfejs, gdy urządzenie sterownika B jest niespodziewanie usunięte, oraz funkcję wywołania zwrotnego EvtIoTargetRemoveCanceled, która ponownie uzyskuje dostęp do interfejsu, jeśli próba usunięcia urządzenia została anulowana.