Zuweisung und Erstellung von URBs

Ein USB-Client-Treiber kann Windows Driver Model (WDM)-Treiberroutinen verwenden, um ein URB zuzuweisen und zu formatieren, bevor er die Anfrage an den von Microsoft bereitgestellten USB-Treiber-Stack sendet.

Der Client-Treiber verwendet einen URB, um alle Informationen zu packen, die von den unteren Treibern im USB-Treiber Stack benötigt werden, um die Anfrage zu verarbeiten. Im Windows-Betriebssystem wird ein URB durch eine URB-Struktur beschrieben.

Microsoft stellt eine Bibliothek von Routinen für USB-Client-Treiber zur Verfügung. Mithilfe dieser Routinen können USB-Client-Treiber URB-Anfragen für bestimmte Vorgänge erstellen und diese über den USB-Stack weiterleiten. Wenn Sie möchten, können Sie Ihren Client-Treiber so gestalten, dass er die Bibliotheksroutinen für die unterstützten Vorgänge aufruft, anstatt eigene URB-Anfragen zu erstellen.

URB-Zuweisung in Windows 7 und früheren Versionen

Um eine USB-Anfrage mit Hilfe der im Windows Driver Kit (WDK) für Windows 7 und frühere Windows-Versionen enthaltenen Funktionen zu senden, weist ein Client-Treiber in der Regel eine URB-Struktur zu und füllt sie, verknüpft die URB-Struktur mit einem neuen IRP und sendet das IRP an den USB-Treiber-Stack.

Für bestimmte Arten von Anfragen stellt Microsoft Hilfsfunktionen zur Verfügung (exportiert von Usbd.sys), die die URB-Struktur zuweisen und formatieren. Zum Beispiel weist die Funktion USBD_CreateConfigurationRequestEx Speicher für eine URB-Struktur zu, formatiert den URB für eine Select-Konfigurationsanfrage und gibt die Adresse der URB-Struktur an den Client-Treiber zurück. Die Funktionen der Hilfsprogramme können jedoch nicht für alle Arten von Anfragen verwendet werden.

Microsoft stellt auch Makros zur Verfügung, die URBs für einige Arten von Anfragen formatieren. Für diese Makros muss der Client-Treiber die URB-Struktur durch den Aufruf von ExAllocatePoolWithTag zuweisen oder die Struktur auf dem Stack zuweisen. Nachdem der Client-Treiber beispielsweise eine URB zugewiesen hat, kann er UsbBuildSelectConfigurationRequest aufrufen, um den URB für eine Select-Konfigurationsanfrage zu formatieren oder um die Konfiguration zu löschen.

Bei anderen Anfragen muss der Client-Treiber den URB manuell zuweisen und formatieren, indem er je nach Art der Anfrage verschiedene Elemente der URB-Struktur festlegt.

Wenn eine USB-Anfrage abgeschlossen ist, muss der Client-Treiber die URB-Struktur freigeben. Wenn der URB im Stack zugewiesen ist, wird er freigegeben, wenn er den Bereich verlässt. Wenn der URB im nicht ausgelagerten Pool zugewiesen ist, muss der Client-Treiber ExFreePool aufrufen, um den URB freizugeben.

URB-Zuweisung in Windows 8

Das WDK für Windows 8 bietet eine neue statische Bibliothek, Usbdex.lib, die Funktionen zum Zuweisen, Formatieren und Freigeben von URBs exportiert. Darüber hinaus gibt es eine neue Möglichkeit, einen URB mit einem IRP zu verknüpfen. Die neuen Funktionen können von einem Client-Treiber aufgerufen werden, der für Windows Vista und spätere Versionen von Windows bestimmt ist.

Ein Client-Treiber, der unter Windows Vista und neueren Versionen ausgeführt wird, muss die neuen Funktionen verwenden, damit der zugrunde liegende USB-Treiber-Stack bestimmte Leistungs- und Zuverlässigkeitsverbesserungen nutzen kann. Diese Verbesserungen gelten für den neuen USB-Treiber-Stack, der in Windows 8 eingeführt wurde, um USB 3.0-Geräte und Host-Controller zu unterstützen. Bei USB 2.0-Host-Controllern lädt Windows eine frühere Version des Treiber-Stacks, die die Verbesserungen nicht unterstützt. Unabhängig von der Version des zugrunde liegenden Treiber-Stacks oder der vom Host-Controller unterstützten Protokollversion müssen Sie immer die neuen URB-Routinen aufrufen.

Bevor Sie eine der neuen Funktionen aufrufen, vergewissern Sie sich, dass Sie ein USBD-Handle für die Registrierung Ihres Client-Treibers beim USB-Treiber-Stack haben. Um ein USBD-Handle abzurufen, rufen Sie USBD_CreateHandle auf.

Die folgenden Funktionen sind mit dem WDK für Windows 8 verfügbar. Diese Funktionen sind in Usbdlib.h definiert.

Die Zuweisungsroutinen in der vorstehenden Liste geben einen Zeiger auf eine neue URB-Struktur zurück, die vom Stack des USB-Treibers zugewiesen wird. Je nach der von Windows geladenen Version des USB-Treiber-Stacks kann die URB-Struktur mit einem intransparenten URB-Kontext gekoppelt sein. Ein URB-Kontext ist ein Block mit Informationen über den URB. Sie können den Inhalt des URB-Headers nicht einsehen. Die Informationen sind dazu gedacht, intern vom USB-Treiber-Stack verwendet zu werden, um die URB-Verfolgung und -Verarbeitung zu verbessern. Der URB-Kontext wird nur vom USB-Treiber-Stack für Windows 8 verwendet. Wenn der URB-Kontext verfügbar ist, verwendet der USB-Treiber-Stack ihn, um die URB-Verarbeitung sicherer und effizienter zu machen. So muss der USB-Treiber-Stack zum Beispiel sicherstellen, dass der Client-Treiber keinen URB sendet und dann versucht, denselben URB erneut zu verwenden, bevor die erste Anfrage abgeschlossen ist. Um diese Art von Fehler zu erkennen, speichert der USB-Treiber-Stack Statusinformationen im URB-Kontext. Ohne die Statusinformationen müsste der USB-Treiber-Stack den eingehenden URB mit allen derzeit laufenden URBs vergleichen. Die Statusinformationen werden auch vom USB-Treiber-Stack verwendet, wenn der Client-Treiber versucht, den URB freizugeben. Bevor er den URB freigibt, prüft der USB-Treiber-Stack den Status, um sicherzustellen, dass der URB nicht anhängig ist.

Der URB-Kontext bietet einen offiziellen Mechanismus zum Speichern von zusätzlichen URB-Informationen. Die Verwendung von URB-Kontext ist der Zuweisung von zusätzlichem Speicher nach Bedarf oder dem Speichern von zusätzlichen Informationen in reservierten Mitgliedern der URB-Struktur vorzuziehen. Der USB-Treiber-Stack weist URBs und den zugehörigen URB-Kontext in einem nicht ausgelagerten Pool zu, sodass in Zukunft, wenn ein größerer URB-Kontext benötigt wird, nur die Größe der Pool-Zuweisung angepasst werden muss.

URB-Routine-Migration

Die folgende Tabelle fasst die Änderungen in den URB-Funktionen zusammen.

Anwendungsfall Verfügbar im WDK für Windows 7 und früher Verfügbar im WDK für Windows 8 und später
  Für Windows 7 und frühere Versionen des Betriebssystems Für Windows 8 und spätere Versionen des Betriebssystems
So erstellen Sie einen URB Der Client-Treiber ordnet eine URB-Struktur zu und formatiert die Struktur je nach Anfrage.

Der Client-Treiber weist die URB-Struktur auf dem Stack zu, oder der Treiber weist die Struktur im nicht ausgelagerten Pool zu, indem er ExAllocatePoolWithTag aufruft.
Der Client-Treiber ruft USBD_UrbAllocate auf und erhält einen Zeiger auf die neue URB-Struktur, die vom Stack des USB-Treibers zugewiesen wird. Der URB kann mit einem URB-Kontext verbunden sein, abhängig von der USBD-Schnittstellenversion des zugrunde liegenden USB-Treiber-Stacks.
So erstellen Sie einen URB für eine Select-Konfigurationsanfrage Der Client-Treiber ruft die Funktion USBD_CreateConfigurationRequestEx auf, die einen Zeiger auf den neuen URB zurückgibt, der vom USB-Treiber-Stack erstellt und formatiert wird. Der Client-Treiber ruft USBD_SelectConfigUrbAllocateAndBuild auf und erhält einen Zeiger auf die neue URB-Struktur, die (für die Select-Konfigurationsanfrage) vom USB-Treiber Stack zugewiesen und formatiert wird. Der URB kann mit einem URB-Kontext verbunden sein, abhängig von der USBD-Schnittstellenversion des zugrunde liegenden USB-Treiber-Stacks.
So erstellen Sie einen URB für eine Select-Interface-Anfrage Der Client-Treiber weist eine URB-Struktur zu und verwendet die _URB_SELECT_INTERFACE-Struktur, um das Format eines Select-Interface-Befehls für ein USB-Gerät zu definieren. Der Client-Treiber ruft USBD_SelectInterfaceUrbAllocateAndBuild auf und erhält einen Zeiger auf die neue URB-Struktur, die vom Stack des USB-Treibers zugewiesen und (für die Select-Interface-Anfrage) formatiert wird. Der URB kann mit einem URB-Kontext verbunden sein, abhängig von der USBD-Schnittstellenversion des zugrunde liegenden USB-Treiber-Stacks.
So verknüpfen Sie einen URB mit einer IRP Der Client-Treiber erhält einen Zeiger auf den nächsten IRP-Stack-Speicherort durch den Aufruf von IoGetNextIrpStackLocation. Dann legt der Client-Treiber das Element Parameters.Others.Argument1 des Stack-Speicherplatzes manuell auf die Adresse der URB-Struktur fest. Der Client-Treiber erhält einen Zeiger auf den nächsten IRP-Stack-Speicherort durch den Aufruf von IoGetNextIrpStackLocation. Dann ruft der Client-Treiber USBD_AssignUrbToIoStackLocation auf, um den URB mit dem Stack- Speicherort zu verknüpfen.
So geben Sie ein URB frei Wenn der Client-Treiber einen URB auf dem Stack zuweist, verschwindet die Variable aus dem Geltungsbereich, nachdem die Anfrage abgeschlossen ist.

Um eine URB-Struktur freizugeben, die der Client-Treiber oder der USB-Treiber-Stack im nicht ausgelagerten Pool zugewiesen hat, ruft der Client-Treiber ExFreePool auf.
Der Client-Treiber ruft USBD_UrbFree auf.