USBD_QueryUsbCapability 함수(usbdlib.h)

WDM 클라이언트 드라이버에서 USBD_QueryUsbCapability 루틴을 호출하여 기본 USB 드라이버 스택과 호스트 컨트롤러 하드웨어가 특정 기능을 지원하는지 여부를 확인합니다. WDF(Windows 드라이버 프레임워크) 드라이버에 대한 참고 사항: 클라이언트 드라이버가 WDF 기반 드라이버인 경우 USBD_QueryUsbCapability 대신 WdfUsbTargetDeviceQueryUsbCapability 메서드를 호출해야 합니다.

구문

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

OutputBuffer가 가리키는 버퍼의 실제 바이트 수를 수신하는 ULONG 변수에 대한 포인터입니다. 호출자는 ResultLength에서 NULL을 전달할 수 있습니다. ResultLength가 NULL이 아니면 받은 값이 OutputBufferLength 값보다 작거나 같습니다.

반환 값

USBD_QueryUsbCapability 루틴은 NT 상태 코드를 반환합니다.

가능한 값은 다음 표에 나열된 상태 코드를 포함하지만 이에 국한되지 않습니다.

반환 코드 설명
STATUS_SUCCESS
요청이 성공했으며 지정된 기능이 지원됩니다.
STATUS_INVALID_PARAMETER
호출자가 잘못된 매개 변수 값을 전달했습니다.
  • USBDHandle 또는 CapabilityType 은 NULL입니다.
  • OutputBuffer 는 NULL이지만 OutputBufferLength 는 0이 아닌 값을 나타냅니다. 반대로 호출자는 출력 버퍼를 제공했지만 버퍼 길이는 0입니다.
STATUS_NOT_IMPLEMENTED
지정된 기능은 기본 USB 드라이버 스택에서 지원되지 않습니다.
STATUS_NOT_SUPPORTED
지정된 기능은 호스트 컨트롤러 하드웨어 또는 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개의 스트림을 지원합니다.

정적 스트림이 지원되는 경우 클라이언트 드라이버는 select-configuration 요청을 통해 가져온 파이프 핸들을 사용하여 첫 번째 스트림( 기본 스트림이라고도 함)에 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

추가 정보

USB 디바이스 드라이버 프로그래밍 참조