USBD_QueryUsbCapability函式 (usbdlib.h)
WDM 用戶端驅動程式會呼叫USBD_QueryUsbCapability例程,以判斷基礎 USB 驅動程式堆疊和主機控制器硬體是否支援特定功能。 Windows Driver Framework (WDF) 驅動程式注意事項: 如果您的用戶端驅動程式是以 WDF 為基礎的驅動程式,則必須呼叫 WdfUsbTargetDeviceQueryUsbCapability 方法,而不是 USBD_QueryUsbCapability。
語法
NTSTATUS USBD_QueryUsbCapability(
[in] USBD_HANDLE USBDHandle,
[in] const GUID *CapabilityType,
[in] ULONG OutputBufferLength,
[in, out] PUCHAR OutputBuffer,
[out, optional] PULONG ResultLength
);
參數
[in] USBDHandle
用戶端驅動程式在先前呼叫 USBD_CreateHandle 例程時擷取的USBD句柄。
[in] CapabilityType
GUID 的指標,表示用戶端驅動程式想要擷取資訊的功能。 可能的 PGUID 值如下所示:
- 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
OutputBuffer 所指向之緩衝區的長度,以位元組為單位。
[in, out] OutputBuffer
呼叫端配置的緩衝區指標。 某些功能要求會傳回輸出緩衝區中的其他資訊。 對於這些要求,您必須配置緩衝區,並提供 OutputBuffer 參數中緩衝區的指標。 目前,只有靜態數據流功能要求需要 USHORT 類型的輸出緩衝區。 緩衝區會填入 USBD_QueryUsbCapability 每個端點支持的數據流數目上限。
其他功能要求不需要輸出緩衝區。 針對這些要求,您必須將 OutputBuffer 設定為 NULL, 並將 OutputBufferLength 設定為 0。
[out, optional] ResultLength
ULONG 變數的指標,該變數會接收 OutputBuffer 所指向之緩衝區中實際位元組數目。 呼叫端可以在 ResultLength 中傳遞 NULL。 如果 ResultLength 不是 NULL,則收到的值小於或等於 OutputBufferLength 值。
傳回值
USBD_QueryUsbCapability例程會傳回NT狀態代碼。
可能的值包括,但不限於下表所列的狀態代碼。
傳回碼 | Description |
---|---|
|
要求成功且支援指定的功能。 |
|
呼叫端傳遞了無效的參數值。
|
|
基礎 USB 驅動程式堆疊不支援指定的功能。 |
|
主機控制器硬體或 USB 驅動程式堆疊不支援指定的功能。 |
備註
Windows 8 包含支援 USB 3.0 裝置的新 USB 驅動程式堆疊。 新的 USB 驅動程式堆疊提供數個定義新功能,例如數據流支援和用戶端驅動程式可使用的鏈結 MDL。
用戶端驅動程式可以呼叫 IsInterfaceVersionSupported 例程來判斷基礎 USB 驅動程式堆疊的版本。
只有在基礎 USB 驅動程式堆疊和硬體支援這些功能時,用戶端驅動程式才能使用新功能。 例如,為了將 I/O 要求傳送至與大量端點相關聯的特定數據流,基礎 USB 驅動程式堆疊、端點和主機控制器硬體必須支援靜態數據流功能。 用戶端驅動程式 不得 呼叫 IsInterfaceVersionSupported ,並假設驅動程式堆疊的功能。 相反地,用戶端驅動程序 必須 一律呼叫 USBD_QueryUsbCapability ,以判斷USB驅動程式堆疊和硬體是否支援特定功能。
下表描述客戶端驅動程式可透過 USBD_QueryUsbCapability 呼叫查詢的USB特定功能。
功能 GUID | Description |
---|---|
GUID_USB_CAPABILITY_CHAINED_MDLS | 如果 USB 驅動程式堆疊支援鏈結的 MDL,則用戶端驅動程式可以將傳輸數據當做參考實體記憶體中分段緩衝區的 MDL 鏈結。 如需詳細資訊,請參閱 MDL。 鏈結的 MDL 會排除配置和複製記憶體的需求,以建立幾乎連續的緩衝區,因此讓 I/O 傳輸更有效率。 如需詳細資訊,請參閱 如何傳送鏈結的 MDL。 |
GUID_USB_CAPABILITY_STATIC_STREAMS |
如果支援,客戶端驅動程式可以將I/O要求傳送至大量端點中的數據流。
對於靜態數據流查詢要求,用戶端驅動程序必須提供輸出緩衝區 (USHORT) 。 呼叫完成後,如果支援靜態數據流功能,輸出緩衝區就會接收主控制器所支持數據流的最大數目。 輸出緩衝區值不會指出裝置中大量端點所支持的數據流數目上限。 若要判斷該數位,用戶端驅動程式必須檢查端點隨附描述元。 Windows 8 中的 USB 驅動程式堆疊最多可支援 255 個數據流。 如果支援靜態數據流,用戶端驅動程式可以使用透過選取組態要求取得的管道句柄,將 I/O 要求傳送至第一個數據流 (也稱為 預設數據流) 。 對於端點中的其他數據流,用戶端驅動程式必須開啟這些數據流,併為其取得管道句柄,才能傳送 I/O 要求。 如需開啟數據流的詳細資訊,請參閱 如何在USB大量端點中開啟和關閉靜態數據流。 |
GUID_USB_CAPABILITY_FUNCTION_SUSPEND |
這項功能可決定基礎 USB 驅動程式堆疊是否支援 USB 函式暫止和遠端 Wake-Up 功能。 如果支援,驅動程式堆疊可以從USB 3.0複合裝置中的個別函式處理遠端喚醒 (的繼續訊號) 。 根據該訊號,個別函式驅動程式可以結束其函式的低電量狀態。
此功能旨在供複合驅動程式使用:載入為複合裝置裝置裝置堆疊中函式裝置對象的驅動程式, (FDO) 。 根據預設,Microsoft 提供的 USB 一般父驅動程式 (Usbccgp.sys) 會載入為 FDO。 如果您的驅動程式取代 Usbccgp.sys,驅動程式必須能夠要求遠端喚醒,並從USB驅動程式堆疊傳播繼續訊號。 在實作該邏輯之前,驅動程式必須呼叫 USBD_QueryUsbCapability來判斷USB驅動程式堆疊對函式暫停功能的支援。 Windows 8 中的 Usbccgp.sys 會實作函式暫止。 如需函式暫止的程式碼範例和詳細資訊,請參閱 如何在複合驅動程式中實作函式暫停。 |
GUID_USB_CAPABILITY_SELECTIVE_SUSPEND |
判斷基礎 USB 驅動程式堆疊是否支援選擇性暫停。
如需選擇性暫停的相關信息,請參閱 USB 選擇性暫停。 |
GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE | 判斷總線是以高速或更高速度運作。 |
GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE | 判斷總線是否在 SuperSpeed 或更新版本上運作。 |
GUID_USB_CAPABILITY_TIME_SYNC | 判斷控制器上是否支援框架編號和 QPC 關聯功能。 |
範例
代碼段示範如何呼叫 USBD_QueryUsbCapability ,以判斷基礎 USB 驅動程式堆疊的功能。
/*++
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;
}
規格需求
需求 | 值 |
---|---|
最低支援的用戶端 | Windows 8 需要 WDK。 以 Windows Vista 和更新版本的 Windows 作業系統為目標。 |
目標平台 | 桌面 |
標頭 | usbdlib.h (包含 Usbdlib.h) |
程式庫 | Usbdex.lib |
IRQL | PASSIVE_LEVEL |