복합 드라이버에서 기능 절전을 구현하는 방법

이 항목에서는 USB(범용 직렬 버스) 3.0 다기능 장치(복합 장치)에 대한 기능 절전 및 기능 원격 절전 모드 해제와 관련한 특징을 대략적으로 설명합니다. 이 항목에서는 복합 장치를 제어하는 드라이버에서 해당 기능을 구현하는 방법에 대해 알아봅니다. 이 항목은 Usbccgp.sys를 대체하는 복합 드라이버에 적용됩니다.

USB(범용 직렬 버스) 3.0 사양은 기능 절전이라는 새 기능을 정의합니다. 이 기능은 복합 장치의 개별 기능이 다른 기능과는 별도로 전원 부족 상태를 시작할 수 있도록 합니다. 키보드의 기능 및 마우스의 다른 기능을 정의하는 복합 장치를 고려해보세요. 사용자는 키보드 기능을 작동 상태로 유지하지만 일정 기간 동안 마우스를 움직이지 않습니다. 마우스의 클라이언트 드라이버는 키보드 기능이 작동 상태를 유지하는 동안 마우스 기능이 유휴 상태임을 감지하고 해당 기능을 절전 상태로 보낼 수 있습니다.

모든 개별 기능이 절전 상태일 때 전체 복합 장치는 절전 상태로 전환됩니다. 그러나 전체 장치는 장치 내 기능의 전원 상태에 관계없이 절전 상태로 전환될 수 있습니다. 특정 기능 및 전체 장치가 절전 상태가 되면 장치가 절전 상태인 동안, 그리고 장치의 절전 시작 및 종료 프로세스 전체에서 해당 기능의 절전 상태가 유지됩니다.

USB 2.0 장치의 원격 절전 모드 해제 기능(USB 장치의 Remote Wakeup 참조)과 마찬가지로 USB 3.0 복합 장치의 개별 기능은 다른 기능의 전원 상태에 영향을 주지 않으면서 전력 부족 상태에서 깨어날 수 있습니다. 이를 기능 원격 절전 모드 해제라고 합니다. 이 기능은 장치 펌웨어에서 원격 절전 모드 해제 비트를 설정하는 프로토콜 요청을 전송하여 호스트에 의해 명시적으로 활성화됩니다. 이 프로세스를 원격 절전 모드 해제에 대한 기능 활성화라고 합니다. Remote Wake 관련 비트에 대한 자세한 내용은 공식적인 USB 사양에서 그림 9-6을 참조하세요.

원격 절전 모드 해제에 대한 기능이 준비되면 절전 상태일 때 실제 장치에 대해 사용자 이벤트가 발생할 경우 절전 해제 신호를 생성할 만큼 충분한 전력을 보유하게 됩니다. 재개 신호가 발생하면 클라이언트 드라이버는 연결된 기능의 절전 상태를 종료할 수 있습니다. 복합 장치의 마우스 기능에 대한 예제에서 사용자가 유휴 상태인 마우스를 움직이면 마우스 기능이 호스트로 재개 신호를 보냅니다. 호스트에서 USB 드라이버 스택은 깨어난 기능을 감지하고 해당 기능의 클라이언트 드라이버로 알림을 전파합니다. 그러면 클라이언트 드라이버는 기능을 절전 해제하고 작동 상태를 시작할 수 있습니다.

클라이언트 드라이버의 경우 기능을 절전 상태로 보내고 기능을 절전 해제하는 단계는 단일 기능 장치 드라이버가 전체 장치를 절전 상태로 보내는 것과 비슷합니다. 다음 절차는 이러한 단계를 요약합니다.

  1. 연결된 기능이 유휴 상태인 경우를 감지합니다.
  2. 유휴 IRP(I/O 요청 패킷)를 보냅니다.
  3. Wait-Wake IRP(I/O 요청 패킷)를 보내 기능의 원격 절전 모드 해제를 활성화하기 위한 요청을 전송합니다.
  4. Dx 전원 IRP(D2 또는 D3)를 보내 기능을 절전 모드로 전환합니다.
앞의 단계에 대한 자세한 내용은 USB 선택적 절전 모드 섹션의 USB 유휴 요청 IRP 전송을 참조하세요.

복합 드라이버는 복합 장치의 각 기능에 대해 PDO(실제 장치 개체)를 만들고 클라이언트 드라이버가 보낸 전력 요청을 처리합니다(기능 장치 스택의 FDO). 클라이언트 드라이버가 기능에 대한 절전 상태를 성공적으로 시작 및 종료하려면 복합 드라이버는 기능 절전 및 원격 절전 모드 해제 기능을 지원하고 수신된 전력 요청을 처리해야 합니다.

Windows 8에서는 USB 3.0 장치용 USB 드라이버 스택이 이러한 기능을 지원합니다. 또한 기능 절전 및 기능 원격 절전 모드 해제 구현은 Windows 기본 복합 드라이버인 Microsoft 제공 USB Generic Parent Driver(Usbccgp.sys)에 추가되었습니다. 사용자 지정 복합 드라이버를 작성하는 경우 드라이버는 다음 절차에 따라 기능 절전 및 원격 절전 모드 해제 요청과 관련된 요청을 처리해야 합니다.

지침

단계 1: USB 드라이버 스택이 기능 절전을 지원하는지 확인

복합 드라이버의 start-device 루틴(IRP_MN_START_DEVICE)에서 다음 단계를 수행합니다.

  1. USBD_QueryUsbCapability 루틴을 호출하여 기본 USB 드라이버 스택이 기능 절전 기능을 지원하는지 여부를 확인합니다. 이 호출을 위해서는 이전 USBD_CreateHandle 루틴 호출에서 획득한 유효한 USBD 핸들이 필요합니다.

    USBD_QueryUsbCapability를 성공적으로 호출하면 기본 USB 드라이버 스택이 기능 절전을 지원하는지 여부가 확인됩니다. 이러한 호출의 결과로 USB 드라이버 스택이 기능 절전을 지원하지 않거나 연결된 장치가 USB 3.0 다기능 장치가 아님을 나타내는 오류 코드가 반환될 수 있습니다.

  2. USBD_QueryUsbCapability 호출 결과로 기능 절전이 지원됨을 알 수 있는 경우 복합 장치를 기본 USB 드라이버 스택에 등록합니다. 복합 장치를 등록하려면 IOCTL_INTERNAL_USB_REGISTER_COMPOSITE_DEVICE I/O 제어 요청을 전송해야 합니다. 이 요청에 대한 자세한 내용은 복합 장치를 등록하는 방법을 참조하세요.

    등록 요청은 REGISTER_COMPOSITE_DEVICE 구조를 사용하여 복합 드라이버에 대한 해당 정보를 지정합니다. 복합 드라이버가 기능 절전을 지원함을 나타내려면 CapabilityFunctionSuspend를 1로 설정해야 합니다.

USB 드라이버 스택이 기능 절전을 지원하는지 여부를 확인하는 방법을 보여 주는 코드 예제를 보려면 USBD_QueryUsbCapability를 참조하세요.

단계 2: 유휴 IRP 처리

클라이언트 드라이버는 유휴 IRP(IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION 참조)를 보낼 수 있습니다. 클라이언트 드라이버가 기능에 대한 유휴 상태를 감지한 후에 이 요청이 전송됩니다. IRP에는 클라이언트 드라이버가 구현한 콜백 완료 루틴(유휴 콜백)에 대한 포인터가 들어 있습니다. 유휴 콜백 내에서 클라이언트는 기능을 절전 상태로 보내기 직전에 보류 중인 I/O 전송 취소와 같은 작업을 수행합니다.

참고  유휴 IRP 메커니즘은 USB 3.0 장치의 클라이언트 드라이버에 대해 선택적입니다. 그러나 대부분의 클라이언트 드라이버는 USB 2.0 장치와 USB 3.0 장치를 모두 지원하도록 작성되었습니다. 복합 드라이버는 각 기능의 전원 상태를 추적하기 위해 해당 IRP에 의존하므로 USB 2.0 장치를 지원하기 위해 드라이버는 유휴 IRP를 보내야 합니다. 모든 기능이 유휴 상태인 경우 복합 드라이버는 전체 장치를 절전 상태로 보냅니다.

복합 드라이버는 클라이언트 드라이버에서 유휴 IRP를 수신하면 유휴 콜백을 즉시 호출하여 클라이언트 드라이버에 기능을 절전 상태로 보낼 수 있음을 알려야 합니다.

단계 3: 원격 절전 모드 해제 알림 요청 보내기

클라이언트 드라이버는 주 기능 코드 집합이 IRP_MN_WAIT_WAKE(Wait-Wake IRP)로 설정된 IRP_MJ_POWER IRP를 전송하여 원격 절전 모드 해제를 위해 기능을 활성화하기 위한 요청을 전송할 수 있습니다. 클라이언트 드라이버는 드라이버가 사용자 이벤트의 결과로 작동 상태를 시작하려고 하는 경우에만 이 요청을 전송합니다.

Wait-Wake IRP를 수신하면 복합 드라이버는 USB 드라이버 스택에 IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION I/O 제어 요청을 보내야 합니다. 이 요청이 수행되면 USB 드라이버 스택은 재개 신호에 대한 알림을 받을 때 복합 드라이버에 알릴 수 있습니다. IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATIONREQUEST_REMOTE_WAKE_NOTIFICATION 구조를 사용하여 요청 매개 변수를 지정합니다. 복합 드라이버가 지정해야 하는 값 중 하나는 원격 절전 모드 해제를 위해 활성화된 기능에 대한 함수 핸들입니다. 복합 드라이버는 USB 드라이버 스택에 복합 장치를 등록하라는 이전 요청에서 이 핸들을 획득했습니다. 복합 드라이버 등록 요청에 대한 자세한 내용은 복합 장치를 등록하는 방법을 참조하세요.

요청에 대한 IRP에서 복합 드라이버는 구현하는 (원격 절전 모드 해제) 완료 루틴에 대한 포인터를 제공합니다.

다음 예제 코드에서는 원격 절전 모드 해제 요청을 전송하는 방법을 보여 줍니다.


/*++

Description: 
    This routine sends a IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION request
    to the USB driver stack. The IOCTL is completed by the USB driver stack 
    when the function wakes up from sleep.

    Parameters:
    parentFdoExt: The device context associated with the FDO for the
    composite driver.

    functionPdoExt: The device context associated with the PDO (created by 
    the composite driver) for the client driver.
--*/

VOID
SendRequestForRemoteWakeNotification(
    __inout PPARENT_FDO_EXT parentFdoExt,
    __inout PFUNCTION_PDO_EXT functionPdoExt
)

{
    PIRP                                irp;
    REQUEST_REMOTE_WAKE_NOTIFICATION    remoteWake;
    PIO_STACK_LOCATION                  nextStack;
    NTSTATUS                            status;

    // Allocate an IRP
    irp =  IoAllocateIrp(parentFdoExt->topDevObj->StackSize, FALSE); 

    if (irp)
    {
 
        //Initialize the USBDEVICE_REMOTE_WAKE_NOTIFICATION structure
        remoteWake.Version = 0;
        remoteWake.Size = sizeof(REQUEST_REMOTE_WAKE_NOTIFICATION);
        remoteWake.UsbdFunctionHandle = functionPdoExt->functionHandle;
        remoteWake.Interface = functionPdoExt->baseInterfaceNumber;

        nextStack = IoGetNextIrpStackLocation(irp);

        nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;   
        nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION;

        nextStack->Parameters.Others.Argument1 = &remoteWake;
        
        // Caller's completion routine will free the IRP when it completes.
 
        SetCompletionRoutine(functionPdoExt->debugLog,
                             parentFdoExt->fdo,
                             irp, 
                             CompletionRemoteWakeNotication, 
                             (PVOID)functionPdoExt, 
                             TRUE, TRUE, TRUE);

        // Pass the IRP
        IoCallDriver(parentFdoExt->topDevObj, irp);

    }

    return;
}


IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION 요청은 재개 신호에 대한 알림을 수신할 때 절전 모드 해제 프로세스 중에 USB 드라이버 스택에 의해 완료됩니다. 또한 이 시간 동안 USB 드라이버 스택은 원격 절전 모드 해제 완료 루틴을 호출합니다.

복합 드라이버는 Wait-Wake IRP를 보류 상태로 유지하고 나중에 처리하기 위해 대기해야 합니다. 복합 드라이버는 드라이버의 원격 절전 모드 해제 완료 루틴이 USB 드라이버 스택에 의해 호출될 때 해당 IRP를 완료해야 합니다.

단계 4: 원격 절전 모드 해제에 대한 기능을 활성화하기 위한 요청 보내기

기능을 저전력 상태로 보내기 위해 클라이언트 드라이버는 WDM(Windows Driver Model) 장치 전력 상태를 D2 또는 D3으로 변경하기 위한 요청과 함께 IRP_MN_SET_POWER IRP를 전송합니다. 일반적으로 클라이언트 드라이버는 이전에 Wait-Wake IRP를 보내 원격 절전 모드 해제를 요청한 경우 D2 IRP를 보냅니다. 그렇지 않은 경우 클라이언트 드라이버는 D3 IRP를 보냅니다.

D2 IRP를 수신하면 복합 드라이버는 먼저 클라이언트 드라이버가 보낸 이전 요청에서 Wait-Wake IRP가 보류 중인지 여부를 확인해야 합니다. 해당 IRP가 보류 중이면 복합 드라이버는 원격 절전 모드 해제를 위해 기능을 활성화해야 합니다. 이렇게 하기 위해 복합 드라이버는 기능의 첫 번째 인터페이스에 SET_FEATURE 제어 요청을 전송하여 장치가 절전 모드 해제 신호를 보낼 수 있도록 해야 합니다. 제어 요청을 보내려면 USBD_UrbAllocate 루틴을 호출하여 URB 구조를 할당하고 UsbBuildFeatureRequest 매크로를 호출하여 SET_FEATURE 요청에 맞게 URB 형식을 지정합니다. 이 호출에서 URB_FUNCTION_SET_FEATURE_TO_INTERFACE를 작업 코드로 지정하고 USB_FEATURE_FUNCTION_SUSPEND를 기능 선택기로 지정합니다. Index 매개 변수에서 최상위 바이트의 Bit 1을 설정합니다. 이 값은 전송의 설정 패킷에 있는 wIndex 필드로 복사됩니다.

다음 예제에서는 SET_FEATURE 제어 요청을 전송하는 방법을 보여 줍니다.



/*++

Routine Description:

Sends a SET_FEATURE for REMOTE_WAKEUP to the device using a standard control request.

Parameters:
parentFdoExt: The device context associated with the FDO for the
composite driver.

functionPdoExt: The device context associated with the PDO (created by 
the composite driver) for the client driver.

Returns:

NTSTATUS code.

--*/
VOID
    NTSTATUS SendSetFeatureControlRequestToSuspend(
    __inout PPARENT_FDO_EXT parentFdoExt,
    __inout PFUNCTION_PDO_EXT functionPdoExt,
    )

{
    PURB                            urb
    PIRP                            irp;
    PIO_STACK_LOCATION              nextStack;
    NTSTATUS                        status;

    status = USBD_UrbAllocate(parentFdoExt->usbdHandle, &urb);

    if (!NT_SUCCESS(status))
    {    
        //USBD_UrbAllocate failed.
        goto Exit;
    }

    //Format the URB structure.
    UsbBuildFeatureRequest (
        urb,
        URB_FUNCTION_SET_FEATURE_TO_INTERFACE, // Operation code
        USB_FEATURE_FUNCTION_SUSPEND,          // feature selector
        functionPdoExt->firstInterface,           // first interface of the function
        NULL);

    irp =  IoAllocateIrp(parentFdoExt->topDevObj->StackSize, FALSE); 

    if (!irp)
    {
        // IoAllocateIrp failed.
        status = STATUS_INSUFFICIENT_RESOURCES;

        goto Exit;
    }

    nextStack = IoGetNextIrpStackLocation(irp);

    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;  

    nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;  

    //  Attach the URB to the IRP.
    USBD_AssignUrbToIoStackLocation(nextStack, (PURB)urb);

    // Caller's completion routine will free the IRP when it completes.
    SetCompletionRoutine(functionPdoExt->debugLog,
        parentFdoExt->fdo,
        irp, 
        CompletionForSuspendControlRequest, 
        (PVOID)functionPdoExt, 
        TRUE, TRUE, TRUE);


    // Pass the IRP
    IoCallDriver(parentFdoExt->topDevObj, irp);


Exit:
    if (urb)
    {
        USBD_UrbFree( parentFdoExt->usbdHandle, urb); 
    }

    return status;

}


그런 후 복합 드라이버는 D2 IRP를 USB 드라이버 스택으로 보냅니다. 다른 모든 기능이 절전 상태이면 USB 드라이버 스택은 컨트롤러의 특정 포트 등록을 처리하여 포트를 절전 모드로 전환합니다.

설명

마우스 기능 예제에서는 원격 절전 모드 해제 기능이 사용되도록 설정되어 있으므로(4단계 참조) 사용자가 마우스를 움직일 때 마우스 기능은 호스트 컨트롤러를 향해 업스트림 방향으로 유선 절전 해제 신호를 생성합니다. 그런 후 컨트롤러는 깨워진 기능에 대한 정보가 들어 있는 알림 패킷을 전송하여 USB 드라이버 스택에 알립니다. 기능 절전 해제 알림에 대한 자세한 내용은 USB 3.0 사양에서 그림 8-17을 참조하세요.

알림 패킷을 수신할 때 USB 드라이버 스택은 보류 중인 IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION 요청(3단계 참조)을 완료하고 요청에 지정되고 복합 드라이버가 구현한 (원격 절전 모드 해제) 완료 콜백 루틴을 호출합니다. 알림이 복합 드라이버에 도달하면 클라이언트 드라이버가 앞서 전송한 Wait-Wake IRP를 완료하여 기능이 작동 상태가 되었음을 해당 클라이언트 드라이버에 알립니다.

(원격 절전 모드 해제) 완료 루틴에서 복합 드라이버는 보류 중인 Wait-Wake IRP를 완료하기 위해 작업 항목을 대기해야 합니다. USB 3.0 장치의 경우 복합 드라이버는 다시 시작 신호를 전송하는 기능만 절전 해제하고 다른 기능은 절전 상태로 둡니다. 작업 항목을 대기하면 USB 2.0 장치의 기존 기능 드라이버 구현에 대한 호환성이 유지됩니다. 작업 항목 대기에 대한 자세한 내용은 IoQueueWorkItem을 참조하세요.

작업자 스레드는 Wait-Wake IRP를 완료하고 클라이언트 드라이버의 완료 루틴을 호출합니다. 그러면 완료 루틴은 D0 IRP를 전송하여 기능이 작동 상태가 되도록 합니다. 복합 드라이버는 Wait-Wake IRP를 완료하기 전에 PoSetSystemWake룰 호출하여 Wait-Wake IRP를 시스템의 절전 상태를 해제하도록 지원한 IRP로 표시해야 합니다. 전원 관리자는 시스템을 깨운 장치에 대한 정보를 포함하는 ETW(Windows용 이벤트 추적) 이벤트(전역 시스템 채널에서 확인 가능)를 로깅합니다.

관련 항목

USB 전원 관리
USB 선택적 절전 모드

 

 

표시:
© 2015 Microsoft