USBD_QueryUsbCapability function (usbdlib.h)
The USBD_QueryUsbCapability routine is called by a WDM client driver to determine whether the underlying USB driver stack and the host controller hardware support a specific capability. Note for Windows Driver Framework (WDF) Drivers: If your client driver is a WDF-based driver, then you must call the WdfUsbTargetDeviceQueryUsbCapability method instead of USBD_QueryUsbCapability.
Syntax
NTSTATUS USBD_QueryUsbCapability(
[in] USBD_HANDLE USBDHandle,
[in] const GUID *CapabilityType,
[in] ULONG OutputBufferLength,
[in, out] PUCHAR OutputBuffer,
[out, optional] PULONG ResultLength
);
Parameters
[in] USBDHandle
USBD handle that is retrieved by the client driver in a previous call to the USBD_CreateHandle routine.
[in] CapabilityType
Pointer to a GUID that represents the capability for which the client driver wants to retrieve information. The possible PGUID values are as follows:
- 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
Length, in bytes, of the buffer pointed to by OutputBuffer.
[in, out] OutputBuffer
Pointer to a caller-allocated buffer. Certain capability requests return additional information in an output buffer. For those requests, you must allocate the buffer and provide a pointer to the buffer in the OutputBuffer parameter. Currently, only the static-streams capability request requires an output buffer of the type USHORT. The buffer is filled by USBD_QueryUsbCapability with the maximum number of streams supported per endpoint.
Other capability requests do not require an output buffer. For those requests, you must set OutputBuffer to NULL and OutputBufferLength to 0.
[out, optional] ResultLength
Pointer to a ULONG variable that receives the actual number of bytes in the buffer pointed to by OutputBuffer. The caller can pass NULL in ResultLength. If ResultLength is not NULL, the received value is less than or equal to the OutputBufferLength value.
Return value
The USBD_QueryUsbCapability routine returns an NT status code.
Possible values include, but are not limited to, the status codes listed in the following table.
Return code | Description |
---|---|
|
The request was successful and the specified capability is supported. |
|
The caller passed an invalid parameter value.
|
|
The specified capability is not supported by the underlying USB driver stack. |
|
The specified capability is not supported either by the host controller hardware or the USB driver stack. |
Remarks
Windows 8 includes a new USB driver stack to support USB 3.0 devices. The new USB driver stack provides several new capabilities defined such as, stream support and chained MDLs that can be used by a client driver.
A client driver can determine the version of the underlying USB driver stack by calling the IsInterfaceVersionSupported routine.
The client driver can use the new capabilities only if the underlying USB driver stack and hardware support them. For example, in order to send I/O requests to a particular stream associated with a bulk endpoint, the underlying USB driver stack, the endpoint, and the host controller hardware must support the static streams capability. The client driver must not call IsInterfaceVersionSupported and assume the capabilities of the driver stack. Instead, the client driver must always call USBD_QueryUsbCapability to determine whether the USB driver stack and hardware support a particular capability.
The following table describes the USB-specific capabilities that a client driver can query through a USBD_QueryUsbCapability call.
Capability GUID | Description |
---|---|
GUID_USB_CAPABILITY_CHAINED_MDLS | If the USB driver stack supports chained MDLs, the client driver can provide the transfer data as a chain of MDLs that reference segmented buffers in physical memory. For more information, see MDL. Chained MDLs preclude the need for allocating and copying memory to create virtually contiguous buffers and therefore make I/O transfers more efficient. For more information, see How to Send Chained MDLs. |
GUID_USB_CAPABILITY_STATIC_STREAMS |
If supported, the client driver can send I/O requests to streams in a bulk endpoint.
For the static streams query request, the client driver is required to provide an output buffer (USHORT). After the call completes and if the static streams capability is supported, the output buffer receives the maximum number of supported streams by the host controller. The output buffer value does not indicate the maximum number of streams supported by the bulk endpoint in the device. To determine that number, the client driver must inspect the endpoint companion descriptor. The USB driver stack in Windows 8 supports up to 255 streams. If static streams are supported, the client driver can send I/O requests to the first stream (also called the default stream) by using the pipe handle obtained through a select-configuration request. For other streams in the endpoint, the client driver must open those streams and obtain pipe handles for them in order to send I/O requests. For more information about opening streams, see How to Open and Close Static Streams in a USB Bulk Endpoint. |
GUID_USB_CAPABILITY_FUNCTION_SUSPEND |
This capability determines whether the underlying USB driver stack supports USB Function Suspend and Remote Wake-Up features. If supported, the driver stack can process a resume signal (for remote wake-up) from an individual function in a USB 3.0 composite device. Based on that signal, an individual function driver can exit the low-power state of its function.
The capability is intended to be used by a composite driver: the driver that is loaded as the function device object (FDO) in the device stack for the composite device. By default, the Microsoft-provided USB Generic Parent Driver (Usbccgp.sys) is loaded as the FDO. If your driver replaces Usbccgp.sys, the driver must be able to request remote wake-up and propagate the resume signal from the USB driver stack. Before implementing that logic, the driver must determine the USB driver stack's support for the function suspend capability by calling USBD_QueryUsbCapability. Usbccgp.sys in Windows 8 implements function suspend. For a code example and more information about function suspend, see How to Implement Function Suspend in a Composite Driver. |
GUID_USB_CAPABILITY_SELECTIVE_SUSPEND |
Determines whether the underlying USB driver stack supports selective suspend.
For information about selective suspend, see USB Selective Suspend. |
GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE | Determines whether the bus is operating at high-speed or higher. |
GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE | Determines whether the bus is operating at SuperSpeed or higher. |
GUID_USB_CAPABILITY_TIME_SYNC | Determines whether the frame number and QPC association feature is supported on the controller. |
Examples
The code snippet shows how to call USBD_QueryUsbCapability to determine the capabilities of the underlying USB driver stack.
/*++
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;
}
Requirements
Requirement | Value |
---|---|
Minimum supported client | Requires WDK for Windows 8. Targets Windows Vista and later versions of the Windows operating system. |
Target Platform | Desktop |
Header | usbdlib.h (include Usbdlib.h) |
Library | Usbdex.lib |
IRQL | PASSIVE_LEVEL |