USBD_QueryUsbCapability-Funktion (usbdlib.h)

Die USBD_QueryUsbCapability Routine wird von einem WDM-Clienttreiber aufgerufen, um zu bestimmen, ob der zugrunde liegende USB-Treiberstapel und die Hostcontrollerhardware eine bestimmte Funktion unterstützen. Hinweis für WDF-Treiber (Windows Driver Framework): Wenn ihr Clienttreiber ein WDF-basierter Treiber ist, müssen Sie anstelle von USBD_QueryUsbCapability die WdfUsbTargetDeviceQueryUsbCapability-Methode aufrufen.

Syntax

NTSTATUS USBD_QueryUsbCapability(
  [in]            USBD_HANDLE USBDHandle,
  [in]            const GUID  *CapabilityType,
  [in]            ULONG       OutputBufferLength,
  [in, out]       PUCHAR      OutputBuffer,
  [out, optional] PULONG      ResultLength
);

Parameter

[in] USBDHandle

USBD-Handle, das vom Clienttreiber in einem vorherigen Aufruf der USBD_CreateHandle-Routine abgerufen wird.

[in] CapabilityType

Zeiger auf eine GUID, die die Funktion darstellt, für die der Clienttreiber Informationen abrufen möchte. Die möglichen PGUID-Werte sind wie folgt:

  • GUID_USB_CAPABILITY_CHAINED_MDLS
  • GUID_USB_CAPABILITY_STATIC_STREAMS
  • GUID_USB_CAPABILITY_SELECTIVE_SUSPEND
  • GUID_USB_CAPABILITY_FUNCTION_SUSPEND
  • GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE
  • GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE
  • GUID_USB_CAPABILITY_TIME_SYNC

[in] OutputBufferLength

Länge des Puffers in Bytes, auf den outputBuffer verweist.

[in, out] OutputBuffer

Zeiger auf einen vom Aufrufer zugewiesenen Puffer. Bestimmte Funktionsanforderungen geben zusätzliche Informationen in einem Ausgabepuffer zurück. Für diese Anforderungen müssen Sie den Puffer zuordnen und einen Zeiger auf den Puffer im OutputBuffer-Parameter angeben. Derzeit erfordert nur die Static-Streams-Funktionsanforderung einen Ausgabepuffer vom Typ USHORT. Der Puffer wird von USBD_QueryUsbCapability mit der maximalen Anzahl von Datenströmen gefüllt, die pro Endpunkt unterstützt werden.

Für andere Funktionsanforderungen ist kein Ausgabepuffer erforderlich. Für diese Anforderungen müssen Sie OutputBuffer auf NULL und OutputBufferLength auf 0 festlegen.

[out, optional] ResultLength

Zeiger auf eine ULONG-Variable, die die tatsächliche Anzahl von Bytes im Puffer empfängt, auf die outputBuffer verweist. Der Aufrufer kann NULL in ResultLength übergeben. Wenn ResultLength nicht NULL ist, ist der empfangene Wert kleiner oder gleich dem OutputBufferLength-Wert .

Rückgabewert

Die USBD_QueryUsbCapability-Routine gibt einen NT-status-Code zurück.

Mögliche Werte sind unter anderem die in der folgenden Tabelle aufgeführten status Codes.

Rückgabecode Beschreibung
STATUS_SUCCESS
Die Anforderung war erfolgreich, und die angegebene Funktion wird unterstützt.
STATUS_INVALID_PARAMETER
Der Aufrufer hat einen ungültigen Parameterwert übergeben.
  • USBDHandle oder CapabilityType ist NULL.
  • OutputBuffer ist NULL, aber OutputBufferLength gibt einen Wert ungleich null an. Umgekehrt hat der Aufrufer einen Ausgabepuffer bereitgestellt, aber die Pufferlänge ist 0.
STATUS_NOT_IMPLEMENTED
Die angegebene Funktion wird vom zugrunde liegenden USB-Treiberstapel nicht unterstützt.
STATUS_NOT_SUPPORTED
Die angegebene Funktion wird weder von der Hostcontrollerhardware noch vom USB-Treiberstapel unterstützt.

Hinweise

Windows 8 enthält einen neuen USB-Treiberstapel zur Unterstützung von USB 3.0-Geräten. Der neue USB-Treiberstapel bietet mehrere neue Funktionen, die definiert sind, z. B. Streamunterstützung und verkettete MDLs, die von einem Clienttreiber verwendet werden können.

Ein Clienttreiber kann die Version des zugrunde liegenden USB-Treiberstapels ermitteln, indem er die IsInterfaceVersionSupported-Routine aufruft .

Der Clienttreiber kann die neuen Funktionen nur verwenden, wenn der zugrunde liegende USB-Treiberstapel und die Hardware sie unterstützen. Um beispielsweise E/A-Anforderungen an einen bestimmten Stream zu senden, der einem Massenendpunkt zugeordnet ist, müssen der zugrunde liegende USB-Treiberstapel, der Endpunkt und die Hostcontrollerhardware die Funktion statische Datenströme unterstützen. Der Clienttreiber darfIsInterfaceVersionSupported nicht aufrufen und die Funktionen des Treiberstapels annehmen. Stattdessen muss der Clienttreiber immer USBD_QueryUsbCapability aufrufen, um zu bestimmen, ob der USB-Treiberstapel und die Hardware eine bestimmte Funktion unterstützen.

In der folgenden Tabelle werden die USB-spezifischen Funktionen beschrieben, die ein Clienttreiber über einen USBD_QueryUsbCapability-Aufruf abfragen kann.

Funktions-GUID BESCHREIBUNG
GUID_USB_CAPABILITY_CHAINED_MDLS Wenn der USB-Treiberstapel verkettete MDLs unterstützt, kann der Clienttreiber die Übertragungsdaten als Kette von MDLs bereitstellen, die auf segmentierte Puffer im physischen Speicher verweisen. Weitere Informationen finden Sie unter MDL. Verkettete MDLs schließen die Notwendigkeit aus, Arbeitsspeicher zuzuweisen und zu kopieren, um praktisch zusammenhängende Puffer zu erstellen, wodurch E/A-Übertragungen effizienter werden. Weitere Informationen finden Sie unter Senden verketteter MDLs.
GUID_USB_CAPABILITY_STATIC_STREAMS Falls unterstützt, kann der Clienttreiber E/A-Anforderungen an Streams in einem Massenendpunkt senden.

Für die Abfrageanforderung für statische Streams muss der Clienttreiber einen Ausgabepuffer (USHORT) bereitstellen. Nach Abschluss des Aufrufs und wenn die Funktion statische Datenströme unterstützt wird, empfängt der Ausgabepuffer die maximale Anzahl unterstützter Datenströme vom Hostcontroller.

Der Ausgabepufferwert gibt nicht die maximale Anzahl von Streams an, die vom Massenendpunkt auf dem Gerät unterstützt werden. Um diese Zahl zu ermitteln, muss der Clienttreiber den Endpunkt-Begleitdeskriptor überprüfen.

Der USB-Treiberstapel in Windows 8 unterstützt bis zu 255 Streams.

Wenn statische Datenströme unterstützt werden, kann der Clienttreiber E/A-Anforderungen an den ersten Stream (auch als Standarddatenstrom bezeichnet) senden, indem er das Pipehandle verwendet, das über eine Select-Configuration-Anforderung abgerufen wurde. Für andere Datenströme im Endpunkt muss der Clienttreiber diese Datenströme öffnen und Pipehandles für sie abrufen, um E/A-Anforderungen zu senden. Weitere Informationen zum Öffnen von Streams finden Sie unter Öffnen und Schließen statischer Datenströme in einem USB-Massenendpunkt.

GUID_USB_CAPABILITY_FUNCTION_SUSPEND Diese Funktion bestimmt, ob der zugrunde liegende USB-Treiberstapel die Funktionen USB Function Suspend und Remote Wake-Up unterstützt. Falls unterstützt, kann der Treiberstapel ein Fortsetzungssignal (für das Remotereaktivieren) von einer einzelnen Funktion in einem USB 3.0-Verbundgerät verarbeiten. Basierend auf diesem Signal kann ein einzelner Funktionstreiber den Low-Power-Zustand seiner Funktion verlassen.

Die Funktion soll von einem zusammengesetzten Treiber verwendet werden: dem Treiber, der als Funktionsgeräteobjekt (Function Device Object, FDO) im Gerätestapel für das zusammengesetzte Gerät geladen wird. Standardmäßig wird der von Microsoft bereitgestellte generische übergeordnete USB-Treiber (Usbccgp.sys) als FDO geladen.

Wenn Ihr Treiber Usbccgp.sys ersetzt, muss der Treiber die Remotereaktivierung anfordern und das Fortsetzungssignal vom USB-Treiberstapel weitergeben können. Vor der Implementierung dieser Logik muss der Treiber die Unterstützung des USB-Treiberstapels für die Funktion zum Anhalten der Funktion ermitteln, indem er USBD_QueryUsbCapability aufruft. Usbccgp.sys in Windows 8 implementiert das Anhalten von Funktionen.

Ein Codebeispiel und weitere Informationen zum Angehalten von Funktionen finden Sie unter Implementieren des Anhaltens von Funktionen in einem zusammengesetzten Treiber.

GUID_USB_CAPABILITY_SELECTIVE_SUSPEND Bestimmt, ob der zugrunde liegende USB-Treiberstapel das selektive Anhalten unterstützt.

Informationen zum selektiven Anhalten finden Sie unter Selektives Anhalten von USB.

GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE Bestimmt, ob der Bus mit hoher Geschwindigkeit oder höher betrieben wird.
GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE Bestimmt, ob der Bus mit SuperSpeed oder höher betrieben wird.
GUID_USB_CAPABILITY_TIME_SYNC Bestimmt, ob die Framenummer und das QPC-Zuordnungsfeature auf dem Controller unterstützt werden. 
 

Beispiele

Der Codeausschnitt zeigt, wie Sie USBD_QueryUsbCapability aufrufen, um die Funktionen des zugrunde liegenden USB-Treiberstapels zu bestimmen.


/*++

Routine Description:
This helper routine queries the underlying USB driver stack
for specific capabilities. This code snippet assumes that 
USBD handle was retrieved by the client driver in a 
previous call to the USBD_CreateHandle routine.

Parameters:

fdo: Pointer to the device object that is the current top
of the stack as reported by IoAttachDeviceToDeviceStack.

Return Value: VOID
--*/

VOID QueryUsbDriverStackCaps (PDEVICE_OBJECT fdo)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;   
    PDEVICE_EXTENSION deviceExtension;

    deviceExtension = (PDEVICE_EXTENSION)fdo->DeviceExtension;

    if (!deviceExtension->UsbdHandle)
    {
        return;
    }

    // Check if the underlying USB driver stack
    // supports USB 3.0 devices.

    if (!USBD_IsInterfaceVersionSupported(
        deviceExtension->UsbdHandle,                                       
        USBD_INTERFACE_VERSION_602))
    {
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Old USB stack loaded.\n" ));
    }
    else
    {
        // Call USBD_QueryUsbCapability to determine 
        // function suspend support.     
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "New USB stack loaded.\n" ));
        ntStatus = USBD_QueryUsbCapability ( deviceExtension->UsbdHandle,  
            (GUID*)&GUID_USB_CAPABILITY_FUNCTION_SUSPEND,  
            0,  
            NULL,
            NULL);

        if (NT_SUCCESS(ntStatus)) 
        {
            deviceExtension->FunctionSuspendSupported = TRUE;
            KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Function suspend supported.\n" ));
        } 
        else 
        {
            deviceExtension->FunctionSuspendSupported  = FALSE;
            ntStatus = STATUS_SUCCESS;
            KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Function suspend not supported.\n" ));
        }
    }

    // Call USBD_QueryUsbCapability to determine 
    // chained MDL support. 

    ntStatus = USBD_QueryUsbCapability(
        deviceExtension->UsbdHandle,
        (GUID*)&GUID_USB_CAPABILITY_CHAINED_MDLS,
        0,
        NULL,
        NULL);

    if (NT_SUCCESS(ntStatus)) 
    {
        deviceExtension->ChainedMDLSupport = TRUE;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Chained MDLs supported.\n" ));
    } 
    else 
    {
        deviceExtension->ChainedMDLSupport = FALSE;
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Chained MDLs not supported.\n" ));
    }

    // Call USBD_QueryUsbCapability to determine 
    // stream support. 

    ntStatus = USBD_QueryUsbCapability (deviceExtension->UsbdHandle, 
        (GUID*)&GUID_USB_CAPABILITY_STATIC_STREAMS, 
        sizeof(ULONG), 
        (PUCHAR) &deviceExtension->MaxSupportedStreams, 
        NULL);  


    if (!NT_SUCCESS(ntStatus)) 
    {
        deviceExtension->MaxSupportedStreams = 0;
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Static streams not supported.\n" ));
    }

    // Call USBD_QueryUsbCapability to determine 
    // selective suspend support. 

    ntStatus = USBD_QueryUsbCapability (deviceExtension->UsbdHandle, 
        (GUID*)&GUID_USB_CAPABILITY_SELECTIVE_SUSPEND, 
        0, 
        NULL, 
        NULL);

    if (!NT_SUCCESS(ntStatus)) 
    {
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Selective suspend not supported.\n" ));
    }
    else
    {
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Selective suspend supported.\n" ));
    }

    // Call USBD_QueryUsbCapability to determine 
    // device speed. 
    ntStatus = USBD_QueryUsbCapability (deviceExtension->UsbdHandle, 
        (GUID*)&GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE, 
        0, 
        NULL, 
        NULL);

    if (!NT_SUCCESS(ntStatus)) 
    {
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "The device is operating at full speed or lower.\n The device can operate at high speed or higher." ));
    }
    else
    {
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "The device is operating at high speed or higher.\n" ));
    }

    // Call USBD_QueryUsbCapability to determine 
    // device speed. 
    ntStatus = USBD_QueryUsbCapability (deviceExtension->UsbdHandle, 
        (GUID*)&GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE, 
        0, 
        NULL, 
        NULL);

    if (!NT_SUCCESS(ntStatus)) 
    {
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "The device is operating at high speed or lower.\n The device can operate at Superspeed or higher." ));
    }
    else
    {
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "The device is operating at SuperSpeed or higher.\n" ));
    }

    return;

}

Anforderungen

Anforderung Wert
Unterstützte Mindestversion (Client) Erfordert WDK für Windows 8. Zielt auf Windows Vista und höhere Versionen des Windows-Betriebssystems ab.
Zielplattform Desktop
Kopfzeile usbdlib.h (include Usbdlib.h)
Bibliothek Usbdex.lib
IRQL PASSIVE_LEVEL

Weitere Informationen

Programmierreferenz für USB-Gerätetreiber