Freigeben über


Senden einer USB-Steuerungsübertragung

In diesem Artikel wird die Struktur einer Steuerungsübertragung erläutert und erläutert, wie ein Clienttreiber eine Steuerelementanforderung an das Gerät senden soll.

Informationen zum Standardendpunkt

Alle USB-Geräte müssen mindestens einen Endpunkt unterstützen, der als Standardendpunkt bezeichnet wird. Jede Übertragung, die auf den Standardendpunkt abzielt, wird als Steuerelementübertragung bezeichnet. Der Zweck einer Steuerungsübertragung besteht darin, dem Host das Abrufen von Geräteinformationen, das Konfigurieren des Geräts oder das Ausführen von Steuerungsvorgängen zu ermöglichen, die für das Gerät eindeutig sind.

Beginnen wir damit, diese Merkmale des Standardendpunkts zu untersuchen.

  • Die Adresse des Standardendpunkts ist 0.
  • Der Standardendpunkt ist bidirektional, d. h. der Host kann Daten an den Endpunkt senden und Daten von ihr innerhalb einer Übertragung empfangen.
  • Der Standardendpunkt ist auf Geräteebene verfügbar und wird nicht in einer Schnittstelle des Geräts definiert.
  • Der Standardendpunkt ist aktiv, sobald eine Verbindung zwischen dem Host und dem Gerät hergestellt wird. Sie ist auch vor der Auswahl einer Konfiguration aktiv.
  • Die maximale Paketgröße des Standardendpunkts hängt von der Busgeschwindigkeit des Geräts ab. Niedrige Geschwindigkeit, 8 Byte; volle und hohe Geschwindigkeit, 64 Bytes; SuperSpeed, 512 Bytes.

Layout einer Steuerelementübertragung

Da Kontrollübertragungen Übertragungen mit hoher Priorität sind, wird eine bestimmte Bandbreite auf dem Bus vom Host reserviert. Für Geräte mit niedriger und voller Geschwindigkeit, 10 % der Bandbreite; 20 % für High- und SuperSpeed-Übertragungsgeräte. Sehen wir uns nun das Layout einer Steuerelementübertragung an.

Diagramm einer USB-Steuerübertragung.

Eine Steuerungsübertragung ist in drei Transaktionen unterteilt: Setuptransaktion, Datentransaktion und Statustransaktion. Jede Transaktion enthält drei Arten von Paketen: Tokenpaket, Datenpaket und Handshake-Paket.

Bestimmte Felder sind für alle Pakete gemeinsam. Die Felder lauten:

  • Synchronisierungsfeld, das den Anfang des Pakets angibt.
  • Paketbezeichner (PID), der den Pakettyp, die Richtung der Transaktion und im Falle eines Handshake-Pakets angibt, gibt es Erfolg oder Fehler der Transaktion an.
  • EOP-Feld gibt das Ende des Pakets an.

Andere Felder hängen vom Pakettyp ab.

Tokenpaket

Jede Setuptransaktion beginnt mit einem Tokenpaket. Dies ist die Struktur des Pakets. Der Host sendet immer das Tokenpaket.

Diagramm eines Tokenpaketlayouts.

Der PID-Wert gibt den Typ des Tokenpakets an. Die folgenden Werte sind möglich:

  • SETUP: Gibt den Start einer Setuptransaktion in einer Steuerungsübertragung an.
  • IN: Gibt an, dass der Host Daten vom Gerät anfordert (Lesefall).
  • OUT: Gibt an, dass der Host Daten an das Gerät sendet (Schreibfall).
  • SOF: Gibt den Anfang des Frames an. Dieser Tokenpakettyp enthält eine 11-Bit-Framenummer. Der Host sendet das SOF-Paket. Die Häufigkeit, mit der dieses Paket gesendet wird, hängt von der Busgeschwindigkeit ab. Für volle Geschwindigkeit sendet der Host das Paket alle 1millisekunden; alle 125 Mikrosekunden auf einem Hochgeschwindigkeitsbus.

Datenpaket

Unmittelbar nach dem Tokenpaket handelt es sich um das Datenpaket, das die Nutzlast enthält. Die Anzahl der Bytes, die jedes Datenpaket enthalten kann, hängt von der maximalen Paketgröße des Standardendpunkts ab. Das Datenpaket kann je nach Richtung der Übertragung vom Host oder vom Gerät gesendet werden.

Diagramm eines Datenpaketlayouts.

Handshake-Paket

Unmittelbar nach dem Datenpaket handelt es sich um das Handshake-Paket. Die PID des Pakets gibt an, ob das Paket vom Host oder gerät empfangen wurde. Das Handshake-Paket kann je nach Richtung der Übertragung vom Host oder vom Gerät gesendet werden.

Diagramm eines Handshake-Paketlayouts.

Sie können die Struktur von Transaktionen und Paketen mithilfe eines beliebigen USB-Analyzers sehen, z. B. Beagle, Ellisys, LeCroy USB-Protokollanalysatoren. Ein Analysegerät zeigt, wie Daten über das Kabel an ein USB-Gerät gesendet oder empfangen werden. In diesem Beispiel untersuchen wir einige Spuren, die von einem LeCroy-USB-Analysegerät erfasst wurden. Dieses Beispiel ist nur für Informationen vorgesehen. Dies ist keine Bestätigung durch Microsoft.

Setuptransaktion

Der Host initiiert immer eine Steuerelementübertragung. Dies geschieht durch Senden einer Setuptransaktion. Diese Transaktion enthält ein Tokenpaket, das als Setuptoken bezeichnet wird, gefolgt von einem 8-Byte-Datenpaket. Dieser Screenshot zeigt eine Beispiel-Setuptransaktion.

Screenshot einer Ablaufverfolgung einer Setuptransaktion.

In der vorherigen Ablaufverfolgung initiiert der Host (angegeben durch H–) die Steuerungsübertragung durch Senden des Setuptokenpakets #434. Beachten Sie, dass die PID SETUP angibt, die ein Setuptoken angibt. Die PID folgt der Geräteadresse und der Adresse des Endpunkts. Bei Steuerungsübertragungen ist diese Endpunktadresse immer 0.

Als Nächstes sendet der Host das Datenpaket #435. Die PID ist DATA0 und dieser Wert wird für die Paketsequenzierung verwendet (zu besprechen). Auf die PID folgen 8 Byte, die die Hauptinformationen zu dieser Anforderung enthalten. Diese 8 Bytes geben den Anforderungstyp und die Größe des Puffers an, in dem das Gerät seine Antwort schreibt.

Alle Bytes werden in umgekehrter Reihenfolge empfangen. Wie in Abschnitt 9.3 beschrieben, werden die folgenden Felder und Werte angezeigt:

Feld Größe Wert Beschreibung
bmRequestType (Siehe 9.3.1 bmRequestType) 1 0x80 Die Datenübertragungsrichtung ist vom Gerät zum Host (D7 ist 1)

Die Anforderung ist eine Standardanforderung (D6... D5 ist 0)

Der Empfänger der Anforderung ist DAS GERÄT (D4 ist 0)
bRequest (Siehe Abschnitt 9.3.2 und Tabelle 9-4) 1 0x06 Der Anforderungstyp ist GET_DESCRIPTOR.
wValue (Siehe Tabelle 9-5) 2 0x0100 Der Anforderungswert gibt an, dass der Deskriptortyp DEVICE ist.
wIndex (Siehe Abschnitt 9.3.4) 2 0x0000 Die Richtung liegt vom Host zum Gerät (D7 ist 1)

Die Endpunktnummer ist 0.
wLength (Siehe Abschnitt 9.3.5) 2 0x0012 Die Anforderung besteht darin, 18 Bytes abzurufen.

Daher können wir daraus schließen, dass der Host bei dieser Steuerungsübertragung eine Anforderung zum Abrufen des Gerätedeskriptors sendet und 18 Bytes als Übertragungslänge angibt, um diesen Deskriptor zu speichern. Die Art und Weise, wie das Gerät diese 18 Bytes sendet, hängt davon ab, wie viel Daten der Standardendpunkt in einer Transaktion senden kann. Diese Informationen sind in der Gerätebeschreibung enthalten, die vom Gerät in der Datentransaktion zurückgegeben wird.

Als Antwort sendet das Gerät ein Handshake-Paket (#436 angegeben durch D%).). Beachten Sie, dass der PID-Wert ACK (ACK-Paket) ist. Dies gibt an, dass das Gerät die Transaktion bestätigt hat.

Datentransaktion

Sehen wir uns nun an, was das Gerät als Reaktion auf die Anforderung zurückgibt. Die tatsächlichen Daten werden in einer Datentransaktion übertragen.

Dies ist die Ablaufverfolgung für die Datentransaktion.

Screenshot einer Ablaufverfolgung einer Beispieldatentransaktion.

Beim Empfangen des ACK-Pakets initiiert der Host die Datentransaktion. Um die Transaktion zu initiieren, sendet sie ein Tokenpaket (#450) mit Richtung als IN (als IN-Token bezeichnet).

Als Antwort sendet das Gerät ein Datenpaket (#451), das dem IN-Token folgt. Dieses Datenpaket enthält den tatsächlichen Gerätedeskriptor. Das erste Byte gibt die Länge des Gerätedeskriptors an, 18 Byte (0x12). Das letzte Byte in diesem Datenpaket gibt die maximale Paketgröße an, die vom Standardendpunkt unterstützt wird. In diesem Fall sehen wir, dass das Gerät jeweils 8 Byte über seinen Standardendpunkt senden kann.

Hinweis

Die maximale Paketgröße des Standardendpunkts hängt von der Geschwindigkeit des Geräts ab. Der Standardendpunkt eines Hochgeschwindigkeitsgeräts beträgt 64 Byte; Low-Speed-Gerät beträgt 8 Byte.

Der Host erkennt die Datentransaktion an, indem ein ACK-Paket (#452) an das Gerät gesendet wird.

Berechnen wir die zurückgegebene Datenmenge. Im wLength-Feld des Datenpakets (#435) in der Setuptransaktion hat der Host 18 Bytes angefordert. In der Datentransaktion sehen wir, dass nur die ersten 8 Byte des Gerätedeskriptors vom Gerät empfangen wurden. Wie empfängt der Host also Informationen, die in den verbleibenden 10 Bytes gespeichert sind? Das Gerät führt dies in zwei Transaktionen durch: 8 Byte und dann letzte 2 Bytes.

Da der Host nun die maximale Paketgröße des Standardendpunkts kennt, initiiert der Host eine neue Datentransaktion und fordert den nächsten Teil basierend auf der Paketgröße an.

Hier ist die nächste Datentransaktion:

Screenshot, der eine Ablaufverfolgung der neuen Datentransaktion zeigt.

Der Host initiiert die vorherige Datentransaktion, indem ein IN-Token (#463) gesendet und die nächsten 8 Bytes vom Gerät angefordert werden. Das Gerät antwortet mit einem Datenpaket (#464), das die nächsten 8 Byte des Gerätedeskriptors enthält.

Beim Empfang der 8 Bytes sendet der Host ein ACK-Paket (#465) an das Gerät.

Als Nächstes fordert der Host die letzten 2 Bytes in einer anderen Datentransaktion wie folgt an:

Screenshot der Ablaufverfolgung der neuen Beispieldatentransaktion, in der der Host die letzten 2 Bytes anfordert.

Daher sehen wir, dass der Host für die Übertragung von 18 Bytes vom Gerät an den Host die Anzahl der übertragenen Und initiierten drei Datentransaktionen nachverfolgt (8+8+2).

Hinweis

Beachten Sie die PID der Datenpakete in Datentransaktionen 19, 23, 26. Die PID wechselt zwischen DATA0 und DATA1. Diese Sequenz wird als Daten-Umschaltung bezeichnet. In Fällen, in denen mehrere Datentransaktionen vorhanden sind, wird die Datensteuerung verwendet, um die Paketsequenz zu überprüfen. Diese Methode stellt sicher, dass die Datenpakete nicht dupliziert oder verloren gehen.

Durch Zuordnen der konsolidierten Datenpakete zur Struktur des Gerätedeskriptors (siehe Tabelle 9-8) werden die folgenden Felder und Werte angezeigt:

Feld Größe Wert Beschreibung
bLength 1 0x12 Länge des Gerätedeskriptors, der 18 Bytes beträgt.
bDescriptorType 1 0x01 Der Deskriptortyp ist gerät.
bcdUSB 2 0x0100 Die Versionsnummer der Spezifikation ist 1.00.
bDeviceClass 1 0x00 Die Geräteklasse ist 0. Jede Schnittstelle in der Konfiguration weist die Klasseninformationen auf.
bDeviceSubClass 1 0x00 Die Unterklasse ist 0, da die Geräteklasse 0 ist.
bProtocol 1 0x00 Protokoll ist 0. Dieses Gerät verwendet keine klassenspezifischen Protokolle.
bMaxPacketSize0 1 0x08 Die maximale Paketgröße des Endpunkts beträgt 8 Bytes.
idVendor 2 0x0562 Telex Communications.
idProduct 2 0x0002 USB-Mikrofon.
bcdDevice 2 0x0100 Gibt die Gerätefreigabenummer an.
iManufacturer 1 0x01 Herstellerzeichenfolge.
iProduct 1 0x02 Produktzeichenfolge.
iSerialNumber 1 0x03 Seriennummer
bNumConfigurations 1 0x01 Anzahl der Konfigurationen.

Durch Die Untersuchung dieser Werte haben wir einige vorläufige Informationen über das Gerät. Das Gerät ist ein Usb-Mikrofon mit niedriger Geschwindigkeit. Die maximale Paketgröße des Standardendpunkts beträgt 8 Byte. Das Gerät unterstützt eine Konfiguration.

Statustransaktion

Schließlich schließt der Host die Steuerungsübertragung ab, indem die letzte Transaktion initiiert wird: Statustransaktion.

Screenshot einer Ablaufverfolgung einer Beispieldatentransaktion.

Der Host startet die Transaktion mit einem OUT-Tokenpaket (#481). Der Zweck dieses Pakets besteht darin, zu überprüfen, ob das Gerät alle angeforderten Daten gesendet hat. In dieser Statustransaktion werden keine Datenpakete gesendet. Das Gerät antwortet mit einem ACK-Paket. Wenn ein Fehler aufgetreten ist, konnte die PID entweder NAK oder STALL sein.

Treibermodelle

Voraussetzungen

Bevor der Clienttreiber Rohre aufzählen kann, stellen Sie sicher, dass diese Anforderungen erfüllt sind:

  • Der Client-Treiber muss das Objekt Framework USB-Zielgerät erstellt haben.

    Wenn Sie die USB-Vorlagen verwenden, die mit Microsoft Visual Studio Professional 2012 bereitgestellt werden, führt der Vorlagencode diese Aufgaben aus. Der Vorlagencode erhält das Handle zum Zielgeräteobjekt und speichert es im Gerätekontext.

KMDF-Clienttreiber

Ein KMDF-Client-Treiber muss ein WDFUSBDEVICE-Handle erhalten, indem er die Methode WdfUsbTargetDeviceCreateWithParameters anfragt. Weitere Informationen finden Sie unter „Geräte-Quellcode“ in Verstehen der Codestruktur des USB-Client-Treibers (KMDF).

UMDF-Clienttreiber

Ein UMDF-Clienttreiber muss einen IWDFUsbTargetDevice-Zeiger durch Abfragen des Framework-Zielgeräteobjekts abrufen. Weitere Informationen finden Sie unter "IPnpCallbackHardware-Implementierung und USB-spezifische Aufgaben" unter Grundlegendes zur USB-Clienttreibercodestruktur (UMDF).For more information, see "IPnpCallbackHardware implementation and USB-specific tasks" in Understanding the USB client driver code structure (UMDF).

Der wichtigste Aspekt für eine Steuerungsübertragung besteht darin, das Setuptoken entsprechend zu formatieren. Bevor Sie die Anforderung senden, sammeln Sie diese Gruppe von Informationen:

  • Richtung der Anforderung: Host auf Gerät oder Gerät hosten.
  • Empfänger der Anforderung: Gerät, Schnittstelle, Endpunkt oder andere.
  • Anforderungskategorie: Standard, Klasse oder Lieferant.
  • Anforderungstyp, z. B. eine GET_DESCRIPTPOR Anforderung. Weitere Informationen finden Sie unter Abschnitt 9.5 in der USB-Spezifikation.
  • wValue - und wIndex-Werte . Diese Werte hängen vom Anforderungstyp ab.

Sie können alle diese Informationen aus der offiziellen USB-Spezifikation abrufen.

Wenn Sie einen UMDF-Treiber schreiben, rufen Sie die Headerdatei ab, Usb_hw.h vom UMDF-Beispieltreiber für OSR USB Fx2 Learning Kit. Diese Headerdatei enthält nützliche Makros und Struktur zum Formatieren des Setuppakets für die Steuerungsübertragung.

Alle UMDF-Treiber müssen mit einem Kernelmodustreiber kommunizieren, um Daten von Geräten zu senden und zu empfangen. Bei einem USB-UMDF-Treiber ist der Kernelmodustreiber immer der von Microsoft bereitgestellte Treiber WinUSB (Winusb.sys).

Wenn ein UMDF-Treiber eine Anforderung für den USB-Treiberstapel sendet, sendet der Windows-E/A-Manager die Anforderung an WinUSB. Nach erhalt der Anforderung verarbeitet WinUSB entweder die Anforderung oder leitet sie an den USB-Treiberstapel weiter.

Von Microsoft definierte Methoden zum Senden von Kontrollübertragungsanforderungen

Ein USB-Clienttreiber auf dem Host initiiert die meisten Steuerelementanforderungen, um Informationen über das Gerät abzurufen, das Gerät zu konfigurieren oder Anbietersteuerungsbefehle zu senden. Alle diese Anforderungen können kategorisiert werden in:

  • Standardanforderungen werden in der USB-Spezifikation definiert. Der Zweck des Sendens von Standardanforderungen besteht darin, Informationen über das Gerät, seine Konfigurationen, Schnittstellen und Endpunkte zu erhalten. Der Empfänger jeder Anforderung hängt vom Typ der Anforderung ab. Der Empfänger kann das Gerät, eine Schnittstelle oder ein Endpunkt sein.

    Hinweis

    Das Ziel jeder Steuerelementübertragung ist immer der Standardendpunkt. Der Empfänger ist die Entität des Geräts, deren Informationen (Deskriptor, Status usw.) der Host interessiert ist.

    Anforderungen können weiter in klassifiziert werden: Konfigurationsanforderungen, Featureanforderungen und Statusanforderungen.

    • Konfigurationsanforderungen werden gesendet, um Informationen vom Gerät abzurufen, damit der Host sie konfigurieren kann, z. B. eine GET_DESCRIPTOR Anforderung. Diese Anforderungen können auch Schreibanforderungen sein, die vom Host gesendet werden, um eine bestimmte Konfiguration oder alternative Einstellung auf dem Gerät festzulegen.
    • Featureanforderungen werden vom Clienttreiber gesendet, um bestimmte vom Gerät, der Schnittstelle oder einem Endpunkt unterstützte boolesche Geräteeinstellungen zu aktivieren oder zu deaktivieren.
    • Statusanforderungen ermöglichen dem Host das Abrufen oder Festlegen der USB-definierten Statusbits eines Geräts, Endpunkts oder einer Schnittstelle.

    Weitere Informationen finden Sie in Abschnitt 9.4 in der USB-Spezifikation, Version 2.0. Die Standardanforderungstypen werden die Headerdatei Usbspec.h definiert.

  • Klassenanforderungen werden durch eine bestimmte Geräteklassenspezifikation definiert.

  • Lieferantenanforderungen werden vom Anbieter bereitgestellt und hängen von den vom Gerät unterstützten Anforderungen ab.

Der von Microsoft bereitgestellte USB-Stapel verarbeitet die gesamte Protokollkommunikation mit dem Gerät, wie in den vorherigen Ablaufverfolgungen gezeigt. Der Treiber macht Gerätetreiberschnittstellen (Device Driver Interfaces, DDIs) verfügbar, die es einem Clienttreiber ermöglichen, Steuerungsübertragungen auf vielfältige Weise zu senden. Wenn Ihr Clienttreiber ein Windows Driver Foundation (WDF)-Treiber ist, kann er Routinen direkt aufrufen, um die allgemeinen Typen von Steuerelementanforderungen zu senden. WDF unterstützt steuerungsinterne Übertragungen sowohl für KMDF als auch FÜR UMDF.

Bestimmte Arten von Steuerelementanforderungen werden nicht über WDF verfügbar gemacht. Für diese Anforderungen kann der Clienttreiber das WDF-Hybridmodell verwenden. Mit diesem Modell kann der Clienttreiber WDM-URB-Formatanforderungen erstellen und formatieren und diese Anforderungen dann mithilfe von WDF-Frameworkobjekten senden. Das Hybridmodell gilt nur für Kernelmodustreiber.

Für UMDF-Treiber:

Verwenden Sie die in usb_hw.h definierten Hilfsmakros und -struktur. Dieser Header ist im UMDF-Beispieltreiber für OSR USB Fx2 Learning Kit enthalten.

Verwenden Sie diese Tabelle, um die beste Methode zum Senden von Steuerelementanforderungen an den USB-Treiberstapel zu ermitteln. Wenn Sie diese Tabelle nicht anzeigen können, lesen Sie die Tabelle in diesem Artikel.

Wenn Sie eine Steuerelementanforderung senden möchten... Für einen KMDF-Treiber... Für einen UMDF-Treiber... Erstellen Sie für einen WDM-Treiber eine URB-Struktur (Hilfsroutine)
CLEAR_FEATURE: Deaktivieren Sie bestimmte Featureeinstellungen im Gerät, deren Konfigurationen, Schnittstellen und Endpunkte. Siehe Abschnitt 9.4.1 in der USB-Spezifikation.
  1. Deklarieren Sie ein Setuppaket. Siehe WDF_USB_CONTROL_SETUP_PACKET Struktur.
  2. Initialisieren Sie das Setuppaket, indem Sie WDF_USB_CONTROL_SETUP_PACKET_INIT_FEATURE aufrufen.
  3. Geben Sie einen in WDF_USB_BMREQUEST_RECIPIENT definierten Empfängerwert an.
  4. Geben Sie die Featureauswahl (wValue) an. Siehe USB_FEATURE_XXX Konstanten in Usbspec.h. Siehe auch Tabelle 9-6 in der USB-Spezifikation.
  5. SetFeature auf FALSE festlegen.
  6. Senden Sie die Anforderung, indem Sie WdfUsbTargetDeviceSendControlTransferSynchronously oder WdfUsbTargetDeviceFormatRequestForControlTransfer aufrufen.
  1. Deklarieren Sie ein Setuppaket. Siehe die in usb_hw.h deklarierte WINUSB_CONTROL_SETUP_PACKET-Struktur .
  2. Initialisieren Sie das Setuppaket, indem Sie das Hilfsmakro WINUSB_CONTROL_SETUP_PACKET_INIT_FEATURE aufrufen, das in usb_hw.h definiert ist.
  3. Geben Sie einen in WINUSB_BMREQUEST_RECIPIENT definierten Empfängerwert an.
  4. Geben Sie die Featureauswahl (wValue) an. Siehe USB_FEATURE_XXX Konstanten in Usbspec.h. Siehe auch Tabelle 9-6 in der USB-Spezifikation.
  5. SetFeature auf FALSE festlegen.
  6. Erstellen Sie die Anforderung, indem Sie das initialisierte Setuppaket mit dem Framework-Anforderungsobjekt und dem Übertragungspuffer verknüpfen, indem Sie IWDFUsbTargetDevice::FormatRequestForControlTransfer-Methode aufrufen.
  7. Senden Sie die Anforderung, indem Sie die IWDFIoRequest::Send-Methode aufrufen.
_URB_CONTROL_FEATURE_REQUEST

(UsbBuildFeatureRequest)

URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE

URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE

URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT

URB_FUNCTION_CLEAR_FEATURE_TO_OTHER
GET_CONFIGURATION: Abrufen der aktuellen USB-Konfiguration. Siehe Abschnitt 9.4.2 in der USB-Spezifikation. KMDF wählt standardmäßig die erste Konfiguration aus. So rufen Sie die vom Gerät definierte Konfigurationsnummer ab:

  1. Formatieren Sie eine WDF_USB_CONTROL_SETUP_PACKET , und legen Sie das bRequest-Element auf USB_REQUEST_GET_CONFIGURATION fest.
  2. Senden Sie die Anforderung, indem Sie WdfUsbTargetDeviceSendControlTransferSynchronously oder WdfUsbTargetDeviceFormatRequestForControlTransfer aufrufen.
UMDF wählt standardmäßig die erste Konfiguration aus. So rufen Sie die vom Gerät definierte Konfigurationsnummer ab:

  1. Deklarieren Sie ein Setuppaket. Siehe die in usb_hw.h deklarierte WINUSB_CONTROL_SETUP_PACKET-Struktur .
  2. Initialisieren Sie das Setuppaket, indem Sie das Hilfsmakro WINUSB_CONTROL_SETUP_PACKET_INIT aufrufen, das in usb_hw.h definiert ist.
  3. Geben Sie BmRequestToDevice als Richtung an, BmRequestToDevice als Empfänger und USB_REQUEST_GET_CONFIGURATION als Anforderung.
  4. Erstellen Sie die Anforderung, indem Sie das initialisierte Setuppaket mit dem Framework-Anforderungsobjekt und dem Übertragungspuffer verknüpfen, indem Sie IWDFUsbTargetDevice::FormatRequestForControlTransfer-Methode aufrufen.
  5. Senden Sie die Anforderung, indem Sie die IWDFIoRequest::Send-Methode aufrufen.
  6. Empfangen der Konfigurationsnummer im Übertragungspuffer. Greifen Sie auf diesen Puffer zu, indem Sie IWDFMemory-Methoden aufrufen.
_URB_CONTROL_GET_CONFIGURATION_REQUEST

URB_FUNCTION_GET_CONFIGURATION
GET_DESCRIPTOR: Abrufen von Geräte-, Konfigurations-, Schnittstellen- und Endpunktdeskriptoren. Siehe Abschnitt 9.4.3 in der USB-Spezifikation.

Weitere Informationen finden Sie unter USB-Deskriptoren.
Rufen Sie die folgenden Methoden auf:

Rufen Sie die folgenden Methoden auf:

_URB_CONTROL_DESCRIPTOR_REQUEST

(UsbBuildGetDescriptorRequest)

URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE

URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT

URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
GET_INTERFACE: Abrufen der aktuellen alternativen Einstellung für eine Schnittstelle. Siehe Abschnitt 9.4.4 in der USB-Spezifikation.

  1. Rufen Sie ein WDFUSBINTERFACE-Handle auf das Zielschnittstellenobjekt ab, indem Sie die WdfUsbTargetDeviceGetInterface-Methode aufrufen.
  2. Rufen Sie die WdfUsbInterfaceGetConfiguredSettingIndex-Methode auf.
  1. Rufen Sie einen IWDFUsbInterface-Zeiger auf das Zielschnittstellenobjekt ab.
  2. Rufen Sie die IWDFUsbInterface::GetConfiguredSettingIndex-Methode auf.
_URB_CONTROL_GET_INTERFACE_REQUEST

URB_FUNCTION_GET_INTERFACE
GET_STATUS: Abrufen von Statusbits von einem Gerät, einem Endpunkt oder einer Schnittstelle. Siehe Abschnitt 9.4.5. in der USB-Spezifikation.
  1. Deklarieren Sie ein Setuppaket. Siehe WDF_USB_CONTROL_SETUP_PACKET Struktur.
  2. Initialisieren Sie das Setuppaket, indem Sie WDF_USB_CONTROL_SETUP_PACKET_INIT_GET_STATUS aufrufen.
  3. Geben Sie den in WDF_USB_BMREQUEST_RECIPIENT definierten Empfängerwert an.
  4. Geben Sie an, welchen Status Sie abrufen möchten: Gerät, Schnittstelle oder Endpunkt (wIndex).
  5. Senden Sie die Anforderung, indem Sie WdfUsbTargetDeviceSendControlTransferSynchronously oder WdfUsbTargetDeviceFormatRequestForControlTransfer aufrufen.
  1. Deklarieren Sie ein Setuppaket. Siehe die in usb_hw.h deklarierte WINUSB_CONTROL_SETUP_PACKET-Struktur .
  2. Initialisieren Sie das Setuppaket, indem Sie das Hilfsmakro WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS aufrufen, das in usb_hw.h definiert ist.
  3. Geben Sie einen in WINUSB_BMREQUEST_RECIPIENT definierten Empfängerwert an.
  4. Geben Sie an, welchen Status Sie abrufen möchten: Gerät, Schnittstelle oder Endpunkt (wIndex).
  5. Erstellen Sie die Anforderung, indem Sie das initialisierte Setuppaket mit dem Framework-Anforderungsobjekt und dem Übertragungspuffer verknüpfen, indem Sie IWDFUsbTargetDevice::FormatRequestForControlTransfer-Methode aufrufen.
  6. Senden Sie die Anforderung, indem Sie die IWDFIoRequest::Send-Methode aufrufen.
  7. Empfangen des Statuswerts im Übertragungspuffer. Greifen Sie auf diesen Puffer zu, indem Sie IWDFMemory-Methoden aufrufen.
  8. Verwenden Sie die in der WINUSB_DEVICE_TRAITS Enumeration definierten Werte, um zu ermitteln, ob der Status selbstbetriebene Remote-Reaktivierung angibt:
_URB_CONTROL_GET_STATUS_REQUEST

(UsbBuildGetStatusRequest)

URB_FUNCTION_GET_STATUS_FROM_DEVICE

URB_FUNCTION_GET_STATUS_FROM_INTERFACE

URB_FUNCTION_GET_STATUS_FROM_ENDPOINT

URB_FUNCTION_GET_STATUS_FROM_OTHER.
SET_ADDRESS: Siehe Abschnitt 9.4.6 in usb-Spezifikation. Diese Anforderung wird vom USB-Treiberstapel verarbeitet. Der Clienttreiber kann diesen Vorgang nicht ausführen. Diese Anforderung wird vom USB-Treiberstapel verarbeitet. Der Clienttreiber kann diesen Vorgang nicht ausführen. Diese Anforderung wird vom USB-Treiberstapel verarbeitet. Der Clienttreiber kann diesen Vorgang nicht ausführen.
SET_CONFIGURATION: Festlegen einer Konfiguration. Siehe Abschnitt 9.4.7 in usb-Spezifikation.

Weitere Informationen finden Sie unter Auswählen einer Konfiguration für ein USB-Gerät.
Standardmäßig wählt KMDF die Standardkonfiguration und erste alternative Einstellung in jeder Schnittstelle aus. Der Clienttreiber kann die Standardkonfiguration ändern, indem die WdfUsbTargetDeviceSelectConfigType-Methode aufgerufen und WdfUsbTargetDeviceSelectConfigTypeUrb als Anforderungsoption angegeben wird. Anschließend müssen Sie eine URB für diese Anforderung formatieren und an den USB-Treiberstapel übermitteln. Standardmäßig wählt UMDF die Standardkonfiguration und die erste alternative Einstellung in jeder Schnittstelle aus. Der Clienttreiber kann die Konfiguration nicht ändern. _URB_SELECT_CONFIGURATION

(USBD_SelectConfigUrbAllocateAndBuild)

URB_FUNCTION_SELECT_CONFIGURATION
SET_DESCRIPTOR: Aktualisieren eines vorhandenen Geräts, einer Konfiguration oder eines Zeichenfolgendeskriptors. Siehe Abschnitt 9.4.8 in usb-Spezifikation.

Diese Anforderung wird häufig nicht verwendet. Der USB-Treiberstapel akzeptiert jedoch eine solche Anforderung vom Clienttreiber.
  1. Weisen Sie eine URB für die Anforderung zu, und erstellen Sie sie.
  2. Geben Sie die Übertragungsinformationen in einer _URB_CONTROL_DESCRIPTOR_REQUEST Struktur an.
  3. Senden Sie die Anforderung, indem Sie WdfUsbTargetDeviceFormatRequestForUrb oder WdfUsbTargetDeviceSendUrbSynchronously aufrufen.
  1. Deklarieren Sie ein Setuppaket. Siehe die in usb_hw.h deklarierte WINUSB_CONTROL_SETUP_PACKET-Struktur .
  2. Geben Sie die Übertragungsinformationen gemäß der USB-Spezifikation an.
  3. Erstellen Sie die Anforderung, indem Sie das initialisierte Setuppaket mit dem Framework-Anforderungsobjekt und dem Übertragungspuffer verknüpfen, indem Sie IWDFUsbTargetDevice::FormatRequestForControlTransfer-Methode aufrufen.
  4. Senden Sie die Anforderung, indem Sie die IWDFIoRequest::Send-Methode aufrufen.
_URB_CONTROL_DESCRIPTOR_REQUEST

URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE

URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT

URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE
SET_FEATURE: Aktivieren Sie bestimmte Featureeinstellungen im Gerät, deren Konfigurationen, Schnittstellen und Endpunkte. Siehe Abschnitt 9.4.9 in der USB-Spezifikation.
  1. Deklarieren Sie ein Setuppaket. Siehe WDF_USB_CONTROL_SETUP_PACKET Struktur.
  2. Initialisieren Sie das Setuppaket, indem Sie WDF_USB_CONTROL_SETUP_PACKET_INIT_FEATURE aufrufen.
  3. Geben Sie den Empfängerwert (Gerät, Schnittstelle, Endpunkt) an, der in WDF_USB_BMREQUEST_RECIPIENT definiert ist.
  4. Geben Sie die Featureauswahl (wValue) an. Siehe USB_FEATURE_XXX Konstanten in Usbspec.h. Siehe auch Tabelle 9-6 in der USB-Spezifikation.
  5. SetFeature auf TRUE festlegen
  6. Senden Sie die Anforderung, indem Sie WdfUsbTargetDeviceSendControlTransferSynchronously oder WdfUsbTargetDeviceFormatRequestForControlTransfer aufrufen.
  1. Deklarieren Sie ein Setuppaket. Siehe die in usb_hw.h deklarierte WINUSB_CONTROL_SETUP_PACKET-Struktur .
  2. Initialisieren Sie das Setuppaket, indem Sie das Hilfsmakro WINUSB_CONTROL_SETUP_PACKET_INIT_FEATURE aufrufen, das in usb_hw.h definiert ist.
  3. Geben Sie einen in WINUSB_BMREQUEST_RECIPIENT definierten Empfängerwert an.
  4. Geben Sie die Featureauswahl (wValue) an. Siehe USB_FEATURE_XXX Konstanten in Usbspec.h. Siehe auch Tabelle 9-6 in der USB-Spezifikation.
  5. SetFeature auf TRUE festlegen.
  6. Erstellen Sie die Anforderung, indem Sie das initialisierte Setuppaket mit dem Framework-Anforderungsobjekt und dem Übertragungspuffer verknüpfen, indem Sie IWDFUsbTargetDevice::FormatRequestForControlTransfer-Methode aufrufen.
  7. Senden Sie die Anforderung, indem Sie die IWDFIoRequest::Send-Methode aufrufen.
_URB_CONTROL_FEATURE_REQUEST

(UsbBuildFeatureRequest)

URB_FUNCTION_SET_FEATURE_TO_DEVICE

URB_FUNCTION_SET_FEATURE_TO_INTERFACE

URB_FUNCTION_SET_FEATURE_TO_ENDPOINT

URB_FUNCTION_SET_FEATURE_TO_OTHER
SET_INTERFACE: Ändert die alternative Einstellung in einer Schnittstelle. Siehe Abschnitt 9.4.9 in der USB-Spezifikation.

Weitere Informationen finden Sie unter Auswählen einer alternativen Einstellung in einer USB-Schnittstelle.
WdfUsbTargetDeviceSelectConfig
  1. Rufen Sie ein WDFUSBINTERFACE-Handle auf das Zielschnittstellenobjekt ab.
  2. Rufen Sie die WdfUsbInterfaceSelectSetting-Methode auf.
  1. Rufen Sie einen IWDFUsbInterface-Zeiger auf das Zielschnittstellenobjekt ab.
  2. Rufen Sie die IWDFUsbInterface::SelectSetting-Methode auf.
_URB_SELECT_INTERFACE

(USBD_SelectInterfaceUrbAllocateAndBuild)

URB_FUNCTION_SELECT_INTERFACE
SYNC_FRAME: Festlegen und Abrufen und Abrufen der Synchronisierungsframenummer des Endpunkts. Siehe Abschnitt 9.4.10 in der USB-Spezifikation. Diese Anforderung wird vom USB-Treiberstapel verarbeitet. Der Clienttreiber kann diesen Vorgang nicht ausführen. Diese Anforderung wird vom USB-Treiberstapel verarbeitet. Der Clienttreiber kann diesen Vorgang nicht ausführen. Diese Anforderung wird vom USB-Treiberstapel verarbeitet. Der Clienttreiber kann diesen Vorgang nicht ausführen.
Für Geräteklassenspezifische Anforderungen und Anbieterbefehle.
  1. Deklarieren Sie ein Setuppaket. Siehe WDF_USB_CONTROL_SETUP_PACKET Struktur.
  2. Initialisieren Sie das Setuppaket, indem Sie WDF_USB_CONTROL_SETUP_PACKET_INIT_CLASS spezifische Anforderungen oder WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR für Anbieterbefehle aufrufen.
  3. Geben Sie den Empfängerwert (Gerät, Schnittstelle, Endpunkt) an, der in WDF_USB_BMREQUEST_RECIPIENT definiert ist.
  4. Senden Sie die Anforderung, indem Sie WdfUsbTargetDeviceSendControlTransferSynchronously oder WdfUsbTargetDeviceFormatRequestForControlTransfer aufrufen.
  1. Deklarieren Sie ein Setuppaket. Siehe die in usb_hw.h deklarierte WINUSB_CONTROL_SETUP_PACKET-Struktur .
  2. Initialisieren Sie das Setuppaket, indem Sie das Hilfsmakro, WINUSB_CONTROL_SETUP_PACKET_INIT_CLASS oder WINUSB_CONTROL_SETUP_PACKET_INIT_VENDOR aufrufen, das in usb_hw.h definiert ist.
  3. Geben Sie die Richtung (siehe WINUSB_BMREQUEST_DIRECTION-Aufzählung ), den Empfänger (siehe WINUSB_BMREQUEST_RECIPIENT Enumeration) und die Anforderung an, wie in der Klasse oder der Hardwarespezifikation beschrieben.
  4. Erstellen Sie die Anforderung, indem Sie das initialisierte Setuppaket mit dem Framework-Anforderungsobjekt und dem Übertragungspuffer verknüpfen, indem Sie IWDFUsbTargetDevice::FormatRequestForControlTransfer-Methode aufrufen.
  5. Senden Sie die Anforderung, indem Sie die IWDFIoRequest::Send-Methode aufrufen.
  6. Empfangen sie die Informationen vom Gerät im Übertragungspuffer. Greifen Sie auf diesen Puffer zu, indem Sie IWDFMemory-Methoden aufrufen.
_URB_CONTROL_VENDOR_OR_CLASS_REQUEST

(UsbBuildVendorRequest)

URB_FUNCTION_VENDOR_DEVICE

URB_FUNCTION_VENDOR_INTERFACE

URB_FUNCTION_VENDOR_ENDPOINT

URB_FUNCTION_VENDOR_OTHER

URB_FUNCTION_CLASS_DEVICE

URB_FUNCTION_CLASS_INTERFACE

URB_FUNCTION_CLASS_ENDPOINT

URB_FUNCTION_CLASS_OTHER

Senden einer Steuerelementübertragung für Lieferantenbefehle – KMDF

Dieses Verfahren zeigt, wie ein Clienttreiber eine Steuerungsübertragung senden kann. In diesem Beispiel sendet der Clienttreiber einen Anbieterbefehl, der die Firmwareversion vom Gerät abruft.

  1. Deklarieren Sie eine Konstante für den Lieferantenbefehl. Untersuchen Sie die Hardwarespezifikation, und bestimmen Sie den Anbieterbefehl, den Sie verwenden möchten.

  2. Deklarieren Sie eine WDF_MEMORY_DESCRIPTOR Struktur, und initialisieren Sie sie, indem Sie das WDF_MEMORY_DESCRIPTOR_INIT_BUFFER-Makro aufrufen. Diese Struktur empfängt die Antwort vom Gerät, nachdem der USB-Treiber die Anforderung abgeschlossen hat.

  3. Je nachdem, ob Sie die Anforderung synchron oder asynchron senden, geben Sie Die Sendeoptionen an:

    • Wenn Sie die Anforderung synchron senden, indem Sie WdfUsbTargetDeviceSendControlTransferSynchronly aufrufen, geben Sie einen Timeoutwert an. Dieser Wert ist wichtig, da Sie den Thread ohne Timeout auf unbestimmte Zeit blockieren können.

      Deklarieren Sie dazu eine WDF_REQUEST_SEND_OPTIONS Struktur, und initialisieren Sie sie durch Aufrufen des WDF_REQUEST_SEND_OPTIONS_INIT-Makros . Geben Sie die Option als WDF_REQUEST_SEND_OPTION_TIMEOUT an.

      Legen Sie als Nächstes den Timeoutwert fest, indem Sie das makro WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT aufrufen.

    • Wenn Sie die Anforderung asynchron senden, implementieren Sie eine Abschlussroutine. Geben Sie alle zugeordneten Ressourcen in der Abschlussroutine frei.

  4. Deklarieren Sie eine WDF_USB_CONTROL_SETUP_PACKET Struktur, um das Setuptoken zu enthalten und die Struktur zu formatieren. Rufen Sie dazu das WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR-Makro auf, um das Setuppaket zu formatieren. Geben Sie im Aufruf die Richtung der Anforderung, den Empfänger, die Optionen für die gesendete Anforderung (in Schritt3 initialisiert) und die Konstante für den Anbieterbefehl an.

  5. Senden Sie die Anforderung, indem Sie WdfUsbTargetDeviceSendControlTransferSynchronously oder WdfUsbTargetDeviceFormatRequestForControlTransfer aufrufen.

  6. Überprüfen Sie den vom Framework zurückgegebenen NTSTATUS-Wert, und überprüfen Sie den empfangenen Wert.

In diesem Codebeispiel wird eine Steuerungsübertragungsanforderung an ein USB-Gerät gesendet, um die Firmwareversion abzurufen. Die Anforderung wird synchron gesendet, und der Clienttreiber gibt einen relativen Timeoutwert von 5 Sekunden an (in 100-Nanosekundeneinheiten). Der Treiber speichert die empfangene Antwort im vom Treiber definierten Gerätekontext.

enum {
    USBFX2_GET_FIRMWARE_VERSION = 0x1,
....

} USBFX2_VENDOR_COMMANDS; 

#define WDF_TIMEOUT_TO_SEC              ((LONGLONG) 1 * 10 * 1000 * 1000)  // defined in wdfcore.h

const __declspec(selectany) LONGLONG
            DEFAULT_CONTROL_TRANSFER_TIMEOUT = 5 * -1 * WDF_TIMEOUT_TO_SEC; 


typedef struct _DEVICE_CONTEXT
{

    ...
       union {
        USHORT      VersionAsUshort;
        struct {
            BYTE Minor;
            BYTE Major;
        } Version;
    } Firmware; // Firmware version.

} DEVICE_CONTEXT, *PDEVICE_CONTEXT;


__drv_requiresIRQL(PASSIVE_LEVEL)
VOID  GetFirmwareVersion(
    __in PDEVICE_CONTEXT DeviceContext
)
{
    NTSTATUS                        status;
    WDF_USB_CONTROL_SETUP_PACKET    controlSetupPacket;
    WDF_REQUEST_SEND_OPTIONS        sendOptions;
    USHORT                          firmwareVersion;
    WDF_MEMORY_DESCRIPTOR           memoryDescriptor;

    PAGED_CODE();

    firmwareVersion = 0;

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor, (PVOID) &firmwareVersion, sizeof(firmwareVersion));

    WDF_REQUEST_SEND_OPTIONS_INIT(
                                  &sendOptions,
                                  WDF_REQUEST_SEND_OPTION_TIMEOUT
                                  );

    WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(
                                         &sendOptions,
                                         DEFAULT_CONTROL_TRANSFER_TIMEOUT
                                         );

    WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
                                        BmRequestDeviceToHost,       // Direction of the request
                                        BmRequestToDevice,           // Recipient
                                        USBFX2_GET_FIRMWARE_VERSION, // Vendor command
                                        0,                           // Value
                                        0);                          // Index 

    status = WdfUsbTargetDeviceSendControlTransferSynchronously(
                                        DeviceContext->UsbDevice,
                                        WDF_NO_HANDLE,               // Optional WDFREQUEST
                                        &sendOptions,
                                        &controlSetupPacket,
                                        &memoryDescriptor,           // MemoryDescriptor
                                        NULL);                       // BytesTransferred 

    if (!NT_SUCCESS(status)) 
    {
        KdPrint(("Device %d: Failed to get device firmware version 0x%x\n", DeviceContext->DeviceNumber, status));
        TraceEvents(DeviceContext->DebugLog,
                    TRACE_LEVEL_ERROR,
                    DBG_RUN,
                    "Device %d: Failed to get device firmware version 0x%x\n",
                    DeviceContext->DeviceNumber,
                    status);
    }
    else 
    {
        DeviceContext->Firmware.VersionAsUshort = firmwareVersion;
        TraceEvents(DeviceContext->DebugLog,
                    TRACE_LEVEL_INFORMATION,
                    DBG_RUN,
                    "Device %d: Get device firmware version : 0x%x\n",
                    DeviceContext->DeviceNumber,
                    firmwareVersion);
    }

    return;
}

So senden Sie eine Steuerungsübertragung für GET_STATUS – UMDF

Dieses Verfahren zeigt, wie ein Clienttreiber eine Steuerungsübertragung für einen GET_STATUS-Befehl senden kann. Der Empfänger der Anforderung ist das Gerät und die Anforderung ruft Informationen in Bits D1-D0 ab. Weitere Informationen finden Sie in Abbildung 9-4 in der USB-Spezifikation.

  1. Schließen Sie die Headerdatei Usb_hw.h ein, die mit dem UMDF-Beispieltreiber für OSR USB Fx2 Learning Kit verfügbar ist.

  2. Deklarieren Sie eine WINUSB_CONTROL_SETUP_PACKET Struktur.

  3. Initialisieren Sie das Setuppaket, indem Sie das Hilfsmakro WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS aufrufen.

  4. Geben Sie BmRequestToDevice als Empfänger an.

  5. Geben Sie 0 im Indexwert an.

  6. Rufen Sie die Hilfsmethode SendControlTransferSynchronously auf, um die Anforderung synchron zu senden.

    Die Hilfsmethode erstellt die Anforderung, indem das initialisierte Setuppaket dem Framework-Anforderungsobjekt und dem Übertragungspuffer zugeordnet wird, indem IWDFUsbTargetDevice::FormatRequestForControlTransfer-Methode aufgerufen wird. Die Hilfsmethode sendet dann die Anforderung durch Aufrufen der IWDFIoRequest::Send-Methode . Überprüfen Sie nach dem Zurückgeben der Methode den zurückgegebenen Wert.

  7. Um zu ermitteln, ob der Status selbstbetriebene Remote-Reaktivierung angibt, verwenden Sie die folgenden Werte, die in der WINUSB_DEVICE_TRAITS Enumeration definiert sind:

In diesem Codebeispiel wird eine Steuerelementübertragungsanforderung an den Status des Geräts gesendet. Im Beispiel wird die Anforderung synchron gesendet, indem eine Hilfsmethode namens "SendControlTransferSynchronously" aufgerufen wird.

HRESULT
CDevice::GetDeviceStatus ()
{

    HRESULT hr = S_OK;

    USHORT deviceStatus;
    ULONG bytesTransferred;

    TraceEvents(TRACE_LEVEL_INFORMATION,
                DRIVER_ALL_INFO,
                "%!FUNC!: entry");

    // Setup the control packet.

    WINUSB_CONTROL_SETUP_PACKET setupPacket;

    WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS(
                                      &setupPacket,
                                      BmRequestToDevice,
                                      0);

    hr = SendControlTransferSynchronously(
                 &(setupPacket.WinUsb),
                 & deviceStatus,
                 sizeof(USHORT),
                 &bytesReturned
                );

     if (SUCCEEDED(hr))
    {
        if (deviceStatus & USB_GETSTATUS_SELF_POWERED)
        {
             m_Self_Powered = true;
        } 
        if (deviceStatus & USB_GETSTATUS_REMOTE_WAKEUP_ENABLED)
        {
             m_remote_wake-enabled = true;
        }
    }

    return hr;
 }

Das folgende Codebeispiel zeigt die Implementierung der Hilfsmethode "SendControlTransferSynchronously". Diese Methode sendet eine Anforderung synchron.

HRESULT
CDevice::SendControlTransferSynchronously(
    _In_ PWINUSB_SETUP_PACKET SetupPacket,
    _Inout_ PBYTE Buffer,
    _In_ ULONG BufferLength,
    _Out_ PULONG LengthTransferred
    )
{
    HRESULT hr = S_OK;
    IWDFIoRequest *pWdfRequest = NULL;
    IWDFDriver * FxDriver = NULL;
    IWDFMemory * FxMemory = NULL;
    IWDFRequestCompletionParams * FxComplParams = NULL;
    IWDFUsbRequestCompletionParams * FxUsbComplParams = NULL;

    *LengthTransferred = 0;

    hr = m_FxDevice->CreateRequest( NULL, //pCallbackInterface
                                    NULL, //pParentObject
                                    &pWdfRequest);

    if (SUCCEEDED(hr))
    {
        m_FxDevice->GetDriver(&FxDriver);

        hr = FxDriver->CreatePreallocatedWdfMemory( Buffer,
                                                    BufferLength,
                                                    NULL,        //pCallbackInterface
                                                    pWdfRequest, //pParetObject
                                                    &FxMemory );
    }

    if (SUCCEEDED(hr))
    {
        hr = m_pIUsbTargetDevice->FormatRequestForControlTransfer( pWdfRequest,
                                                                   SetupPacket,
                                                                   FxMemory,
                                                                   NULL); //TransferOffset
    }

    if (SUCCEEDED(hr))
    {
        hr = pWdfRequest->Send( m_pIUsbTargetDevice,
                                WDF_REQUEST_SEND_OPTION_SYNCHRONOUS,
                                0); //Timeout
    }

    if (SUCCEEDED(hr))
    {
        pWdfRequest->GetCompletionParams(&FxComplParams);

        hr = FxComplParams->GetCompletionStatus();
    }

    if (SUCCEEDED(hr))
    {
        HRESULT hrQI = FxComplParams->QueryInterface(IID_PPV_ARGS(&FxUsbComplParams));
        WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrQI));

        WUDF_TEST_DRIVER_ASSERT( WdfUsbRequestTypeDeviceControlTransfer ==
                            FxUsbComplParams->GetCompletedUsbRequestType() );

        FxUsbComplParams->GetDeviceControlTransferParameters( NULL,
                                                             LengthTransferred,
                                                             NULL,
                                                             NULL );
    }

    SAFE_RELEASE(FxUsbComplParams);
    SAFE_RELEASE(FxComplParams);
    SAFE_RELEASE(FxMemory);

    pWdfRequest->DeleteWdfObject(); 
    SAFE_RELEASE(pWdfRequest);

    SAFE_RELEASE(FxDriver);

    return hr;
}

Wenn Sie Winusb.sys als Funktionstreiber für Ihr Gerät verwenden, können Sie Steuerübertragungen von einer Anwendung senden. Verwenden Sie zum Formatieren des Setuppakets in WinUSB die in der Tabelle in diesem Artikel beschriebenen UMDF-Hilfsmakros und -strukturen. Rufen Sie WinUsb_ControlTransfer Funktion auf , um die Anforderung zu senden.