다음을 통해 공유


USB KMDF 함수 드라이버의 선택적 일시 중단

이 문서에서는 KMDF 함수 드라이버가 USB 선택적 일시 중단을 지원하는 방법을 설명합니다.

USB 드라이버에 사용자 모드에서 사용할 수 없는 기능 또는 리소스가 필요한 경우 KMDF 함수 드라이버를 제공해야 합니다. KMDF 드라이버는 KMDF 초기화 구조에서 관련 값을 설정한 다음 적절한 콜백 함수를 제공하여 선택적 일시 중단을 구현합니다. KMDF는 디바이스를 일시 중단 및 다시 시작하기 위해 낮은 드라이버와 통신하는 세부 정보를 처리합니다.

KMDF 드라이버의 선택적 일시 중단에 대한 지침

선택적 일시 중단을 지원하는 KMDF 드라이버는 다음 지침을 따라야 합니다.

  • KMDF 함수 드라이버는 디바이스 스택의 PPO여야 합니다. 기본적으로 KMDF 함수 드라이버는 PPO입니다.
  • 선택적 일시 중단을 지원하는 KMDF 함수 드라이버는 전원 관리 큐 또는 전원 관리되지 않는 큐를 사용할 수 있습니다. 기본적으로 PPO용 큐 개체는 전원 관리됩니다.

전원 정책 소유권 및 KMDF USB 드라이버

기본적으로 USB 디바이스의 KMDF 함수 드라이버는 디바이스 스택의 PPO입니다. KMDF는 이 드라이버를 대신하여 선택적 일시 중단 및 다시 시작을 관리합니다.

KMDF 드라이버의 I/O 큐 구성

선택적 일시 중단을 지원하는 KMDF 함수 드라이버는 전원 관리 큐 또는 전원 관리되지 않는 큐를 사용할 수 있습니다. 일반적으로 드라이버는 들어오는 디바이스 I/O 제어 요청을 수신하도록 전원 관리되지 않는 큐를 구성하고 읽기, 쓰기 및 기타 전원 종속 요청을 수신하도록 하나 이상의 전원 관리형 큐를 구성합니다. 요청이 전원 관리 큐에 도착하면 KMDF는 드라이버에 요청을 표시하기 전에 디바이스가 D0에 있는지 확인합니다.

디바이스 스택의 PPO 위에 계층화된 KMDF 필터 드라이버를 작성하는 경우 전원 관리형 큐를 사용하면 안 됩니다. 그 이유는 UMDF 드라이버의 경우와 동일합니다. 프레임워크는 디바이스가 일시 중단된 동안 전원 관리 큐의 요청을 표시하지 않으므로 이러한 큐를 사용하면 디바이스 스택이 중단될 수 있습니다.

KMDF 함수 드라이버에 대한 선택적 일시 중단 메커니즘

KMDF는 USB 선택적 일시 중단을 지원하는 데 필요한 대부분의 작업을 처리합니다. I/O 작업을 추적하고, 유휴 타이머를 관리하고, 부모 드라이버(Usbhub.sys 또는 Usbccgp.sys)가 디바이스를 일시 중단하고 다시 시작하도록 하는 디바이스 I/O 제어 요청을 보냅니다.

KMDF 함수 드라이버가 선택적 일시 중단을 지원하는 경우 KMDF는 각 디바이스 개체가 소유한 모든 전원 관리 큐에서 I/O 작업을 추적합니다. 프레임워크는 I/O 수가 0에 도달할 때마다 유휴 타이머를 시작합니다. 기본 제한 시간 값은 5초입니다.

I/O 요청이 유휴 시간 제한 기간이 만료되기 전에 디바이스 개체에 속한 전원 관리형 큐에 도착하면 프레임워크는 유휴 타이머를 취소하고 디바이스를 일시 중단하지 않습니다.

유휴 타이머가 만료되면 KMDF는 USB 디바이스를 일시 중단 상태로 만드는 데 필요한 요청을 발급합니다. 함수 드라이버가 USB 엔드포인트에서 연속 판독기를 사용하는 경우 판독기에서 반복되는 폴링은 KMDF 유휴 타이머에 대한 활동으로 계산되지 않습니다. 그러나 EvtDeviceD0Exit 콜백 함수에서 USB 드라이버는 장치가 작동 상태가 아닌 동안 드라이버가 I/O 요청을 보내지 않도록 전원이 공급되지 않는 큐에서 공급되는 연속 판독기 및 기타 I/O 대상을 수동으로 중지해야 합니다. 대상을 중지하기 위해 드라이버는 WdfIoTargetStop을 호출하고 WdfIoTargetWaitForSentIoToComplete 를 대상 작업으로 지정합니다. 이에 대한 응답으로 프레임워크는 대상의 I/O 큐에 있는 모든 I/O 요청이 완료되고 연결된 I/O 완료 콜백이 실행된 후에만 I/O 대상을 중지합니다.

기본적으로 KMDF는 디바이스를 D0 외부로 전환하고 드라이버가 유휴 설정에 지정한 디바이스 전원 상태로 전환합니다. 전환의 일환으로 KMDF는 드라이버의 전원 콜백 함수를 다른 전원 다운 시퀀스에서와 동일한 방식으로 호출합니다.

디바이스가 일시 중단된 후 프레임워크는 다음 이벤트가 발생할 때 자동으로 디바이스를 다시 시작합니다.

  • 드라이버의 전원 관리 큐에 대한 I/O 요청이 도착합니다.
  • 사용자는 장치 관리자 사용하여 USB 선택적 일시 중단을 사용하지 않도록 설정합니다.
  • 드라이버는 USB 디바이스 일시 중단 방지에 설명된 대로 WdfDeviceStopIdle을 호출합니다.

디바이스를 다시 시작하기 위해 KMDF는 디바이스 스택 아래로 전원 켜기 요청을 보낸 다음 다른 전원 켜기 시퀀스와 동일한 방식으로 드라이버의 콜백 함수를 호출합니다.

전원 다운 및 전원 강화 시퀀스와 관련된 콜백에 대한 자세한 내용은 WDF 드라이버 백서의 플러그 앤 플레이 및 전원 관리를 참조하세요.

KMDF 함수 드라이버에서 USB 선택적 일시 중단 지원

KMDF 함수 드라이버에서 USB 선택적 일시 중단을 구현하려면 다음을 수행합니다.

  • 유휴 시간 제한 등 유휴 상태와 관련된 전원 정책 설정을 초기화합니다.
  • 선택적으로 드라이버가 열려 있는 핸들 또는 디바이스의 I/O 큐와 관련이 없는 기타 이유로 인해 디바이스를 일시 중단해서는 안 된다고 판단할 때 일시 중단 또는 다시 시작 작업을 일시적으로 방지하는 논리를 포함합니다.
  • HID(휴먼 인터페이스 디바이스)용 USB 드라이버에서 INF에서 선택적 일시 중단을 지원함을 나타냅니다.

KMDF 함수 드라이버에서 전원 정책 설정 초기화

USB 선택적 일시 중단에 대한 지원을 구성하기 위해 KMDF 드라이버는 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS 구조를 사용합니다. 드라이버는 먼저 구조를 초기화한 다음 드라이버 및 해당 디바이스의 기능에 대한 세부 정보를 제공하는 필드를 설정할 수 있습니다. 일반적으로 드라이버는 EvtDriverDeviceAdd 또는 EvtDevicePrepareHardware 함수에서 이 구조를 채웁니다.

WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS 구조를 초기화하려면

드라이버가 디바이스 개체를 만든 후 드라이버는 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT 함수를 사용하여 구조를 초기화합니다. 이 함수는 다음 두 개의 인수를 사용합니다.

  • 초기화할 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS 구조체에 대한 포인터입니다.
  • 선택적 일시 중단에 대한 지원을 나타내는 열거형 값입니다. 드라이버는 IdleUsbSelectiveSuspend를 지정해야 합니다.

드라이버가 IdleUsbSelectiveSuspend를 지정하는 경우 함수는 다음과 같이 구조체의 멤버를 초기화합니다.

  • IdleTimeoutIdleTimeoutDefaultValue (현재 5000밀리초 또는 5초)로 설정됩니다.
  • UserControlOfIdleSettingsIdleAllowUserControl 로 설정됩니다.
  • EnabledWdfUseDefault로 설정됩니다. 이는 선택적 일시 중단이 사용하도록 설정되어 있지만 UserControlOfIdleSettings 멤버가 허용하는 경우 사용자가 사용하지 않도록 설정할 수 있음을 나타냅니다.
  • DxState 는 디바이스에 대해 보고된 전원 기능을 사용하여 유휴 디바이스를 전환할 상태를 결정하는 PowerDeviceMaximum으로 설정됩니다.

USB 선택적 일시 중단을 구성하려면

드라이버가 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS 구조를 초기화한 후 드라이버는 구조체의 다른 필드를 설정한 다음 WdfDeviceAssignS0IdleSettings 를 호출하여 이러한 설정을 프레임워크에 전달할 수 있습니다. 다음 필드는 USB 함수 드라이버에 적용됩니다.

  • IdleTimeout - 프레임워크에서 디바이스 유휴를 고려하기 전에 I/O 요청을 받지 않고 경과해야 하는 간격(밀리초)입니다. 드라이버는 ULONG 값을 지정하거나 기본값을 적용할 수 있습니다.

  • UserControlOfIdleSettings - 사용자가 디바이스의 유휴 설정을 수정할 수 있는지 여부입니다. 가능한 값은 IdleDoNotAllowUserControl 및 IdleAllowUserControl입니다.

  • DxState - 프레임워크가 디바이스를 일시 중단하는 디바이스 전원 상태입니다. 가능한 값은 PowerDeviceD1, PowerDeviceD2 및 PowerDeviceD3입니다.

    USB 드라이버는 이 값의 초기 설정을 변경하지 않아야 합니다. WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT 함수는 이 값을 PowerDeviceMaximum으로 설정하여 프레임워크가 디바이스 기능에 따라 올바른 값을 선택하도록 합니다.

다음 코드 조각은 Osrusbfx2 샘플 드라이버의 Device.c 파일에서 가져옵니다.

WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
NTSTATUS    status = STATUS_SUCCESS;
//
// Initialize the idle policy structure.
//
WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, 
     IdleUsbSelectiveSuspend);
idleSettings.IdleTimeout = 10000; // 10 sec

status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings);
if ( !NT_SUCCESS(status)) {
     TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", 
                 status);
    return status;
}

이 예제에서 드라이버는 idleUsbSelectiveSuspend를 지정하여 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT 호출합니다. 드라이버는 IdleTimeout 을 10,000밀리초(10초)로 설정하고 DxStateUserControlOfIdleSettings에 대한 프레임워크 기본값을 허용합니다. 따라서 프레임워크는 유휴 상태일 때 디바이스를 D3 상태로 전환하고 관리자 권한이 있는 사용자가 디바이스 유휴 지원을 사용하거나 사용하지 않도록 설정할 수 있는 장치 관리자 속성 페이지를 만듭니다. 그런 다음 드라이버는 WdfDeviceAssignS0IdleSettings를 호출하여 유휴 지원을 사용하도록 설정하고 이러한 설정을 프레임워크에 등록합니다.

드라이버는 디바이스 개체를 만든 후 언제든지 WdfDeviceAssignS0IdleSettings 를 호출할 수 있습니다. 대부분의 드라이버는 처음에 EvtDriverDeviceAdd 콜백에서 이 메서드를 호출하지만 항상 가능하거나 바람직하지는 않을 수 있습니다. 드라이버가 여러 디바이스 또는 디바이스 버전을 지원하는 경우 드라이버는 하드웨어를 쿼리할 때까지 모든 디바이스 기능을 알지 못할 수 있습니다. 이러한 드라이버는 EvtDevicePrepareHardware 콜백까지 WdfDeviceAssignS0IdleSettings 호출을 연기할 수 있습니다.

WdfDeviceAssignS0IdleSettings에 대한 초기 호출 후 언제든지 드라이버는 유휴 시간 제한 값과 디바이스가 유휴 상태인 디바이스 상태를 변경할 수 있습니다. 하나 이상의 설정을 변경하기 위해 드라이버는 앞에서 설명한 대로 다른 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS 구조를 초기화하고 WdfDeviceAssignS0IdleSettings를 다시 호출합니다.

USB 디바이스 일시 중단 방지

경우에 따라 제한 시간 내에 I/O 요청이 없더라도 USB 디바이스의 전원이 꺼지지 않아야 합니다(일반적으로 핸들이 디바이스에 열려 있거나 디바이스가 충전 중인 경우). USB 드라이버는 WdfDeviceStopIdle 을 호출하고 디바이스가 일시 중단될 수 있는 경우 WdfDeviceResumeIdle 을 호출하여 이러한 상황에서 프레임워크가 유휴 디바이스를 일시 중단하는 것을 방지할 수 있습니다.

WdfDeviceStopIdle 은 유휴 타이머를 중지합니다. IdleTimeout 기간이 만료되지 않았고 디바이스가 아직 일시 중단되지 않은 경우 프레임워크는 유휴 타이머를 취소하고 디바이스를 일시 중단하지 않습니다. 디바이스가 이미 일시 중단된 경우 프레임워크는 디바이스를 작업 상태로 반환합니다. WdfDeviceStopIdle은 시스템이 Sx 절전 상태로 변경되면 프레임워크가 디바이스를 일시 중단하는 것을 방지하지 않습니다. 유일한 효과는 시스템이 S0 작동 상태에 있는 동안 디바이스 일시 중단을 방지하는 것입니다. WdfDeviceResumeIdle 은 유휴 타이머를 다시 시작합니다. 이러한 두 메서드는 디바이스에서 참조 횟수를 관리하므로 드라이버가 WdfDeviceStopIdle 을 여러 번 호출하는 경우 드라이버가 WdfDeviceResumeIdle 을 동일한 횟수만큼 호출할 때까지 프레임워크는 디바이스를 일시 중단하지 않습니다. 드라이버는 먼저 WdfDeviceStopIdle을호출하지 않고 WdfDeviceResumeIdle을 호출해서는 안 됩니다.

레지스트리 키 포함(HID 드라이버만 해당)

USB HID 디바이스용 KMDF 상위 필터 드라이버는 MICROSOFT에서 제공하는 HIDClass.sys 포트 드라이버가 HID 스택에 대해 선택적 일시 중단을 사용하도록 설정할 수 있도록 선택적 일시 중단을 지원한다는 것을 INF에 표시해야 합니다. INF에는 다음 문자열과 같이 SelectiveSuspendEnabled 키를 추가하고 해당 값을 1로 설정하는 AddReg 지시문이 포함되어야 합니다.

HKR,,"SelectiveSuspendEnabled",0x00000001,0x1

예를 들어 WDK의 Hidusbfx2.inx at %WinDDK%\BuildNumber\Src\Hid\ Hidusbfx2\sys를 참조하세요.

KMDF 드라이버에 대한 원격 절 해제 지원

선택적 일시 중단과 마찬가지로 KMDF는 절전 모드 해제 지원을 통합하여 디바이스가 유휴 상태이고 시스템이 S0(작동 상태) 또는 절전 상태(S1-S4)에 있는 동안 USB 디바이스가 절전 모드 해제 신호를 트리거할 수 있도록 합니다. KMDF 용어에서 이러한 두 기능을 각각 "S0에서 절전 모드 해제"와 "Sx에서 절전 모드 해제"라고 합니다.

USB 디바이스의 경우 절전 모드 해제는 디바이스 자체가 저전력 상태에서 작업 상태로의 전환을 시작할 수 있음을 나타냅니다. 따라서 USB 측면에서 S0에서 절전 모드 해제 및 Sx에서 절전 모드 해제는 동일하며 "원격 절전 모드 해제"라고 합니다.

KMDF USB 함수 드라이버는 선택적 일시 중단 메커니즘의 일부로 이 기능을 제공하기 때문에 S0에서 절전 모드 해제를 지원하는 코드가 필요하지 않습니다. 그러나 시스템이 Sx에 있을 때 원격 절전 모드 해제를 지원하려면 함수 드라이버가 다음을 수행해야 합니다.

KMDF 드라이버는 일반적으로 EvtDriverDeviceAdd 또는 EvtDevicePrepareHardware 함수에서 USB 선택적 일시 중단에 대한 지원을 구성하는 동시에 절전 모드 해제 지원을 구성합니다.

디바이스 기능 확인

KMDF USB 함수 드라이버가 유휴 및 절전 모드 해제에 대한 전원 정책 설정을 초기화하기 전에 디바이스가 원격 절전 모드 해제를 지원하는지 확인해야 합니다. 디바이스 하드웨어 기능에 대한 정보를 얻기 위해 드라이버는 WDF_USB_DEVICE_INFORMATION 구조를 초기화하고 일반적으로 EvtDriverDeviceAdd 또는 EvtDevicePrepareHardware 콜백에서 WdfUsbTargetDeviceRetrieveInformation을 호출합니다.

WdfUsbTargetDeviceRetrieveInformation 호출에서 드라이버는 디바이스 개체에 대한 핸들과 초기화된 WDF_USB_DEVICE_INFORMATION 구조체에 대한 포인터를 전달합니다. 함수에서 성공적으로 반환되면 구조체의 특성 필드에는 디바이스가 자체 구동되는지 여부를 나타내는 플래그가 포함되어 있으며 고속으로 작동할 수 있으며 원격 절전 모드 해제를 지원합니다.

Osrusbfx2 KMDF 샘플의 다음 예제에서는 이 메서드를 호출하여 디바이스가 원격 절전 모드 해제를 지원하는지 여부를 확인하는 방법을 보여 줍니다. 이러한 코드 줄이 실행된 후 디바이스가 원격 절전 모드 해제를 지원하는 경우 waitWakeEnable 변수에 TRUE가 포함되고, 그렇지 않으면 FALSE가 포함됩니다.

    WDF_USB_DEVICE_INFORMATION          deviceInfo;
// Retrieve USBD version information, port driver capabilities and device
// capabilities such as speed, power, etc.
//

WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo);

status = WdfUsbTargetDeviceRetrieveInformation(
                            pDeviceContext->UsbDevice,
                            &deviceInfo);
waitWakeEnable = deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;

원격 절전 모드 해제 사용

USB 용어에서 USB 디바이스는 DEVICE_REMOTE_WAKEUP 기능이 설정된 경우 원격 절전 모드 해제를 사용하도록 설정됩니다. USB 사양에 따라 호스트 소프트웨어는 디바이스를 절전 모드로 설정하기 위해 디바이스의 원격 절전 모드 해제 기능을 "바로 이전"으로 설정해야 합니다. KMDF 함수 드라이버는 절전 모드 해제 설정을 초기화하는 데만 필요합니다. KMDF 및 Microsoft 제공 USB 버스 드라이버는 I/O 요청을 실행하고 원격 절전 모드 해제를 사용하도록 설정하는 데 필요한 하드웨어 조작을 처리합니다.

절전 모드 해제 설정을 초기화하려면

  1. WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT 호출하여 WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS 구조를 초기화합니다. 이 함수는 구조체의 Enabled 멤버를 WdfUseDefault로 설정하고 , DxState 멤버를 PowerDeviceMaximum으로 설정하고, UserControlOfWakeSettings 멤버를WakeAllowUserControl로 설정합니다.
  2. 초기화된 구조체를 사용하여 WdfDeviceAssignSxWakeSettings 를 호출합니다. 결과적으로 디바이스가 D3 상태에서 절전 모드 해제되도록 설정되고 사용자는 장치 관리자 디바이스 속성 페이지에서 절전 모드 해제 신호를 사용하거나 사용하지 않도록 설정할 수 있습니다.

Osrusbfx2 샘플의 다음 코드 조각은 절전 모드 해제 설정을 기본값으로 초기화하는 방법을 보여 줍니다.

WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;

WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);
status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);
if (!NT_SUCCESS(status)) {
    return status;
}

선택적 일시 중단을 지원하는 USB 디바이스의 경우 기본 버스 드라이버는 디바이스 하드웨어가 절전 모드 해제되도록 준비합니다. 따라서 USB 함수 드라이버에는 EvtDeviceArmWakeFromS0 콜백이 거의 필요하지 않습니다. 프레임워크는 유휴 시간 초과가 만료되면 USB 버스 드라이버에 선택적 일시 중단 요청을 보냅니다.

같은 이유로 USB 함수 드라이버에는 EvtDeviceWakeFromS0Triggered 또는 EvtDeviceWakeFromSxTriggered 콜백이 거의 필요하지 않습니다. 대신 프레임워크 및 기본 버스 드라이버는 디바이스를 작업 상태로 반환하기 위한 모든 요구 사항을 처리합니다.