USB UMDF ドライバーにおけるセレクティブ サスペンド

このトピックでは、KMDF ファンクション ドライバーが USB セレクティブ サスペンドをサポートする方法について説明します。

重要な API

UMDF ファンクション ドライバーは、次の 2 つの方法のいずれかで USB セレクティブ サスペンドをサポートできます。

  • 電源ポリシーの所有権を要求し、デバイスのアイドル電源オフと再開を処理する。
  • マイクロソフトにより提供される WinUSB.sys ドライバーを使用してセレクティブ サスペンドを処理します。 WinUSB.sys は、UMDF USB ドライバーのインストール時にカーネル モード デバイス スタックの一部としてインストールされます。 WinUSB.sys は、USB デバイスの操作を一時停止および再開するための基になるメカニズムを実装します。

どちらのアプローチでも、少量のコードのみ必要です。 WDK で提供される IdleWake サンプルは、UMDF USB ドライバーでセレクティブ サスペンドをサポートする方法を示しています。 このサンプルは、%WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\ UMDF\Fx2_Driver\IdleWake にあります。 このフォルダーには、サンプルの PPO バージョンと PPO 以外のバージョンの両方が含まれています。

セレクティブ サスペンドをサポートする UMDF ドライバーは、以下のガイドラインに従う必要があります。

  • UMDF ドライバーは、デバイス スタックの電源ポリシーの所有権を要求できますが、これを行う必要はありません。 既定では、基になる WinUSB.sys ドライバーは電源ポリシーを所有します。
  • セレクティブ サスペンドをサポートし、PPO である UMDF ドライバーは、電源管理キューまたは電源管理されていないキューを使用できます。 セレクティブ サスペンドをサポートするが、PPO ではない UMDF ドライバーでは、電源管理キューを使用しないでください。

UMDF USB ドライバーにおける電源ポリシーの所有権

既定では、WinUSB.sys は UMDF USB ドライバーを含むデバイス スタックの PPO です。 WDF 1.9 以降、UMDF ベースの USB ドライバーは電源ポリシーの所有権を要求できます。 各デバイス スタック内の 1 つのドライバーのみ PPO にできるため、PPO である UMDF USB ドライバーは、WinUSB.sys で電源ポリシーの所有権を明示的に無効にする必要があります。

UMDF USB ドライバーで電源ポリシーの所有権を要求するには

  1. IWDFDeviceInitialize::SetPowerPolicyOwnership を呼び出し、通常はドライバー コールバック オブジェクトの IDriverEntry::OnDeviceAdd メソッドから TRUE を渡します。 次に例を示します。

    FxDeviceInit->SetPowerPolicyOwnership(TRUE);
    
  2. WinUSB で電源ポリシーの所有権を無効にします。 ドライバーの INF ファイルに、レジストリの WinUsbPowerPolicyOwnershipDisabled 値を 0 以外の値に設定する AddReg ディレクティブを含めます。 AddReg ディレクティブは、DDInstall.HW セクションに含まれている必要があります。 次に例を示します。

    [MyDriver_Install.NT.hw]
    AddReg=MyDriver_AddReg
    
    [MyDriver_AddReg]
    HKR,,"WinUsbPowerPolicyOwnershipDisabled",0x00010001,1
    

セレクティブ サスペンドをサポートし、1.9 より前のバージョンの WDF でビルドされている UMDF USB ドライバーは、電源ポリシーの所有権を要求してはなりません。 これらの以前のバージョンの WDF では、USB セレクティブ サスペンドは、WinUSB.sys が PPO の場合のみ適切に動作します。

UMDF USB ドライバーにおける I/O キュー

セレクティブ サスペンドをサポートする UMDF ドライバーの場合、UMDF ドライバーがデバイスの電源ポリシーを所有しているかどうかによって、使用できる I/O キューの種類が決まります。 セレクティブ サスペンドをサポートし、GPIO である UMDF ドライバーは、電源管理されているキューまたは電源管理されていないキューを使用できます。 セレクティブ サスペンドをサポートするが、PPO ではない UMDF USB ドライバーは、電源管理 I/O キューを使用しないでください。

デバイスの一時停止中に電源管理キューに対して I/O 要求が到着した場合、「USB ドライバーのセレクティブ サスペンド」の図に示すように、ドライバーが PPO でない限り、フレームワークは要求を提示しません。 UMDF ドライバーがデバイスの PPO でない場合、フレームワークはデバイスの代わりに電源をオンにできません。 その結果、要求は電源管理キューにスタックしたままになります。 要求は WinUSB に到達しないため、WinUSB はデバイスの電源をオンにしません。 その結果、デバイス スタックがストールする可能性があります。

キューが電源管理されていない場合、デバイスの電源がオフの場合でも、フレームワークは UMDF ドライバーに I/O 要求を提示します。 UMDF ドライバーは要求をフォーマットし、デバイス スタックを通常の方法で既定の I/O ターゲットに転送します。 特殊なコードは必要ありません。 要求が PPO (WinUSB.sys) に達すると、WinUSB.sys によりデバイスの電源がオンになり、必要な I/O 操作が実行されます。

%WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\umdf\Fx2_Driver\IdleWake にあるサンプル ドライバーは、PPO 以外のバージョンのドライバーをビルドするときに定数 _NOT_POWER_POLICY_OWNER_ を定義します。 ドライバーは、読み取りおよび書き込み要求のキューを作成するとき、定数をチェックして電源管理キューを作成するかどうかを決定します。

キューを作成するため、ドライバーはドライバー定義の CMyQueue::Initialize メソッドを呼び出します。このメソッドは、次の 3 つのパラメーターを受け取ります。

  • DispatchType は、キューが要求をディスパッチする方法を示す WDF_IO_QUEUE_DISPATCH_TYPE 列挙値です。
  • 既定値。キューが既定のキューかどうかを示すブール値です。
  • PowerManaged。キューが電源管理されているかどうかを示すブール値です。

次のコード スニペットは、読み取り/書き込みキューの作成の 一部として CMyQueue::Initialize メソッドに対するドライバーの呼び出しを示しています。

#if defined(_NOT_POWER_POLICY_OWNER_)
    powerManaged = false;
#else
    powerManaged = true;
#endif  
hr = __super::Initialize(WdfIoQueueDispatchParallel,
                         true,
                         powerManaged,
                         );

その後、CMyQueue::Initialize は、次のように IWDFDevice::CreateIoQueue を呼び出してキューを作成します。

hr = m_FxDevice->CreateIoQueue(
                               callback,
                               Default,
                               DispatchType,
                               PowerManaged,
                               FALSE,
                               &fxQueue
                               );

このコード シーケンスは、要求を並列にディスパッチする既定のキューになります。 ドライバーが PPO の場合、キューは電源管理され、ドライバーが PPO でない場合、キューは電源管理されません。

UMDF PPO における USB セレクティブ サスペンドのサポート

セレクティブ サスペンドをサポートするには、デバイス スタックの PPO である UMDF USB ドライバーで、次の操作を行う必要があります。

  1. デバイス スタックの電源ポリシーの所有権を要求します。前述のように、通常はドライバー コールバック オブジェクトの IDriverEntry::OnDeviceAdd メソッドで要求します。
  2. フレームワーク デバイス オブジェクトで IWDFDevice2::AssignS0IdleSettings メソッドを呼び出して、セレクティブ サスペンドを有効にします。

PPO から USB セレクティブ サスペンドを有効にするには

  • IWDFDevice2::AssignS0IdleSettings を呼び出します。通常は、デバイス コールバック オブジェクトの OnPrepareHardware メソッドから呼び出します。 次のように、パラメーターを AssignS0IdleSettings に設定します。
    • IdleCaps から IdleUsbSelectiveSuspend
    • DxState から、フレームワークがアイドル状態のデバイスを移行するデバイス スリープ状態。 USB セレクティブ サスペンドの場合、PowerDeviceMaximum を指定します。これは、フレームワークでバス ドライバーが指定した値を使用する必要があることを示しています。
    • IdleTimeout は、フレームワークが DxState に移行する前にデバイスがアイドル状態でなければならないミリ秒数です。
    • ユーザーによるアイドル設定の管理がドライバーにより許可されている場合は UserControlOfIdleSettingsIdleAllowUserControl。それ以外の場合は IdleDoNotAllowUserControl
    • 既定ではセレクティブ サスペンドを有効にするが、ユーザーの設定で既定値をオーバーライドできるようにするには、Enabled から WdfUseDefault

次の例は、IdleWake_PPO ドライバーが内部 CMyDevice::SetPowerManagement メソッドでこのメソッドを呼び出す方法を示しています。

hr = m_FxDevice->AssignS0IdleSettings( IdleUsbSelectiveSuspend,
                                PowerDeviceMaximum,
                                IDLE_TIMEOUT_IN_MSEC,
                                IdleAllowUserControl,
                                WdfUseDefault);                                                                                                   

デバイス ハードウェアがウェイク信号を生成できる場合、UMDF ドライバーは、S1、S2、または S3 からのシステム ウェイクもサポートできます。 詳しくは、「UMDF ドライバーにおけるシステム ウェイク」をご覧ください。

PPO 以外の UMDF ドライバーでの USB セレクティブ サスペンドのサポート

PPO ではない UMDF ファンクション ドライバーは、基になる WinUSB.sys ドライバーの機能を使用してセレクティブ サスペンドをサポートできます。 UMDF ドライバーは、デバイスとドライバーがセレクティブ サスペンドをサポートし、INF ファイルで、または USB ターゲット デバイス オブジェクトで電源ポリシーを設定することによってセレクティブ サスペンドを有効にする必要があることを WinUSB に通知する必要があります。

UMDF ファンクション ドライバーがセレクティブ サスペンドを有効にした場合、基になる WinUSB.sys ドライバーは、デバイスがアイドル状態のタイミングを判断します。 WinUSB は、転送が保留中でない場合、または保留中の転送のみが割り込みまたは一括エンドポイントにおける IN 転送である場合、アイドル タイムアウト カウンターを開始します。 既定では、アイドル タイムアウトは 5 秒ですが、UMDF ドライバーはこの既定値を変更できます。

WinUSB.sys は、デバイスがアイドル状態であると判断すると、カーネル モード デバイス スタックでデバイスを一時停止する要求を送信します。 バス ドライバーは、必要に応じてハードウェアの状態を変更します。 ポート上のすべてのデバイス機能が一時停止されている場合、ポートは USB セレクティブ サスペンド状態になります。

デバイスが一時停止されている間に I/O 要求が WinUSB.sys に到着した場合、WinUSB.sys は、要求を処理するためにデバイスの電源を入れる必要が生じると、デバイスの操作を再開します。 UMDF ドライバーは、システムが S0 のままの間デバイスを再開するコードを必要としません。 デバイス ハードウェアがウェイク信号を生成できる場合、UMDF ドライバーは、S1、S2、または S3 からのシステム ウェイクもサポートできます。 詳しくは、「UMDF ドライバーにおけるシステム ウェイク」をご覧ください。

PPO ではない UMDF ドライバーは、次の 2 つの手順を実行することによりセレクティブ サスペンドをサポートできます。

  1. デバイスとドライバーがセレクティブ サスペンドをサポートしていることを WinUSB.sys に通知します。
  2. USB セレクティブ サスペンドを有効にします。

さらに、ドライバーは必要に応じて、次の処理を実行できます。

  • デバイスのタイムアウト値を設定します。
  • ユーザーがセレクティブ サスペンドを有効または無効にすることを許可します。

PPO ではない UMDF USB ファンクション ドライバーで USB セレクティブ サスペンドを実装する方法の例については、WDK の Fx2_Driver サンプルをご覧ください。 このサンプルは、%WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\Umdf\Fx2_Driver\IdleWake_Non-PPO にあります。

セレクティブ サスペンドのサポートについて WinUSB に通知するには

デバイスが USB セレクティブ サスペンドをサポートできることを WinUSB.sys に通知するには、デバイス INF はデバイスのハードウェア キーに DeviceIdleEnabled 値を追加し、値を 1 に設定する必要があります。 次の例は、Fx2_Driver サンプルが WUDFOsrUsbFx2_IdleWakeNon-PPO.Inx ファイルにこの値を追加して設定する方法を示しています。

[OsrUsb_Device_AddReg]
...
HKR,,"DeviceIdleEnabled",0x00010001,1

USB セレクティブ サスペンドを有効にするには

UMDF USB ドライバーは、実行時または INF へのインストール時に USB セレクティブ サスペンドを有効にすることができます。

  • 実行時にサポートを有効にするため、ファンクション ドライバーは IWDFUsbTargetDevice::SetPowerPolicy を呼び出して、PolicyType パラメーターを AUTO_SUSPEND に設定し、Value パラメーターを TRUE または 1 に設定します。 次の例は、DeviceNonPpo.cpp ファイルで Fx2_Driver サンプルによりセレクティブ サスペンドを有効にする方法を示しています。

    BOOL AutoSuspend = TRUE;
    hr = m_pIUsbTargetDevice->SetPowerPolicy( AUTO_SUSPEND,
                                              sizeof(BOOL),
                                             (PVOID) &AutoSuspend );
    
  • インストール中にサポートを有効にするため、INF には、デバイスのハードウェア キーに DefaultIdleState 値を追加し、値を 1 に設定する AddReg ディレクティブが含まれています。 次に例を示します。

    HKR,,"DefaultIdleState",0x00010001,1
    

アイドル タイムアウト値を設定するには

既定では、転送が保留中でない場合、または保留中の転送が割り込みまたは一括エンドポイントにおける IN 転送のみである場合、WinUSB は 5 秒後にデバイスを一時停止します。 UMDF ドライバーは、INF のインストール時または実行時、このアイドル タイムアウト値を変更できます。

  • インストール時にアイドル タイムアウトを設定するため、INF には、DefaultIdleTimeout 値をデバイスのハードウェア キーに追加して、タイムアウト間隔 (ミリ秒単位) に設定する AddReg ディレクティブが含まれています。 次の例では、タイムアウトを 7 秒に設定します。

    HKR,,"DefaultIdleTimeout",0x00010001,7000
    
  • 実行時にアイドル タイムアウトを設定するため、ドライバーは IWDFUsbTargetDevice::SetPowerPolicy を呼び出して、PolicyType を SUSPEND_DELAY に設定し、値をアイドル タイムアウト値 (ミリ秒単位) に設定します。 Device.cpp ファイルの次の例では、Fx2_Driver サンプルがタイムアウトを 10 秒に設定しています。

    HRESULT hr;
    ULONG value;
    value = 10 * 1000;
    hr = m_pIUsbTargetDevice->SetPowerPolicy( SUSPEND_DELAY,
                                              sizeof(ULONG),
                                             (PVOID) &value );
    

USB セレクティブ サスペンドのユーザー制御を提供するには**

WinUSB セレクティブ サスペンドのサポートを使用する UMDF USB ドライバーは、ユーザーがセレクティブ サスペンドを有効または無効にすることを必要に応じて許可できます。 そのためには、デバイスのハードウェア キーに UserSetDeviceIdleEnabled 値を追加し、値を 1 に設定する AddReg ディレクティブを INF に含めます。 AddReg ディレクティブに使用する文字列を次に示します。

HKR,,"UserSetDeviceIdleEnabled",0x00010001,1

UserSetDeviceIdleEnabled が設定されている場合、デバイスの [プロパティ] ダイアログ ボックスには、ユーザーが USB セレクティブ サスペンドを有効または無効にできる [電源管理] タブが含まれています。

UMDF ドライバーでのシステム ウェイク

UMDF ドライバーでは、システム ウェイクのサポートは、セレクティブ サスペンドのサポートとは無関係です。 UMDF USB ドライバーは、システム ウェイクとセレクティブ サスペンドの両方をサポートする、システム ウェイクもセレクティブ サスペンドもサポートしない、またはシステム ウェイクまたはセレクティブ サスペンドのいずれかをサポートできます。 システム ウェイクをサポートするデバイスは、スリープ状態 (S1、S2、または S3) からシステムをウェイクアップできます。

UMDF USB PPO ドライバーは、フレームワークのドライバー オブジェクトのウェイクアップ情報を提供することにより、システム のウェイクをサポートできます。 外部イベントによってシステムのウェイクアップがトリガーされると、フレームワークはデバイスを動作状態に戻します。

USB の PPO 以外のドライバーは、WinUSB.sys ドライバーが実装するシステム ウェイク サポートを使用できます。

PPO である UMDF USB ドライバーでシステム ウェイクをサポートするには**

次のパラメーターを使用して、フレームワークのデバイス オブジェクトで IWDFDevice2::AssignSxWakeSettings メソッドを呼び出します。

  • DxState は、システムがウェイクアップ可能な Sx 状態になったときにデバイスが遷移する電源状態です。 USB デバイスの場合、PowerDeviceMaximum を指定して、バス ドライバーが指定した値を使用します。
  • ユーザーによるアイドル設定の管理がドライバーにより許可されている場合は UserControlOfWakeSettingsWakeAllowUserControl。それ以外の場合は WakeDoNotAllowUserControl
  • 既定ではウェイクアップを有効にするが、ユーザーの設定で既定値をオーバーライドできるようにするには、Enabled から WdfUseDefault

次の例は、IdleWake_PPO ドライバーが内部 CMyDevice::SetPowerManagement メソッドでこのメソッドを呼び出す方法を示しています。

hr = m_FxDevice->AssignSxWakeSettings( PowerDeviceMaximum,
                                       WakeAllowUserControl,
                                       WdfUseDefault);

PPO 以外のドライバーで WinUSB 経由でシステム ウェイクを有効にするには**

WinUSB によるシステム ウェイクを有効にするには、ドライバーの INF は、デバイスのハードウェア キーにレジストリ値 SystemWakeEnabled を追加し、1 に設定します。 IdleWake_Non-PPO サンプルでは、次のようにシステムのウェイクアップが有効になります。

[OsrUsb_Device_AddReg]
...
HKR,,"SystemWakeEnabled",0x00010001,1

この値を設定することにより、ドライバーはどちらもシステムのウェイクアップを有効にし、ユーザーがシステムをウェイクアップするデバイスの機能を制御できるようにします。 デバイス マネージャーでは、デバイスの電源管理設定プロパティ ページに、ユーザーがシステム ウェイクを有効または無効にできるチェック ボックスが含まれています。