USB UMDF 驅動程式中的選擇性暫停
本主題描述 UMDF 函式驅動程式如何支援 USB 選擇性暫停。
重要 API
- IWDFUsbTargetDevice::SetPowerPolicy
- IWDFDevice2::AssignSxWakeSettings
- IWDFDevice2::AssignS0IdleSettings
UMDF 函式驅動程式可以使用下列兩種方式之一支援 USB 選擇性暫停:
- 藉由宣告電源原則擁有權,並處理裝置閑置電源關閉和繼續。
- 藉由依賴 Microsoft 提供的 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 驅動程式擁有電源原則。
- 支援選擇性暫停的 UMDF 驅動程式,而且 PPO 可以使用非電源管理的佇列或佇列。 支援選擇性暫停但不是 PPO 的 UMDF 驅動程式不得使用受電源管理的佇列。
UMDF USB 驅動程式中的電源原則擁有權
根據預設,WinUSB.sys 是包含UMDF USB驅動程式之裝置堆疊的PPO。 從WDF 1.9開始,UMDF型USB驅動程式可以宣告電源原則擁有權。 因為每個裝置堆疊中只有一個驅動程式可以是 PPO,所以 PPO 的 UMDF USB 驅動程式必須在 WinUSB.sys 中明確停用電源原則擁有權。
在 UMDF USB 驅動程式中宣告電源原則擁有權
呼叫 IWDFDeviceInitialize::SetPowerPolicyOwnership 並傳遞 TRUE,通常是從驅動程式回呼物件的 IDriverEntry::OnDeviceAdd 方法傳遞。 例如:
FxDeviceInit->SetPowerPolicyOwnership(TRUE);
停用 WinUSB 中的電源原則擁有權。 在驅動程式的 INF 檔案中,包含 AddReg 指示詞,將登錄中的 WinUsbPowerPolicyOwnershipDisabled 值設定為非零值。 AddReg 指示詞必須出現在 DDInstall.HW 區段中。 例如:
[MyDriver_Install.NT.hw] AddReg=MyDriver_AddReg [MyDriver_AddReg] HKR,,"WinUsbPowerPolicyOwnershipDisabled",0x00010001,1
支援選擇性暫停且使用 1.9 之前的 WDF 版本所建置的 UMDF USB 驅動程式不得宣告電源原則擁有權。 使用這些舊版 WDF 時,只有在 WinUSB.sys 是 PPO 時,USB 選擇性暫停才能正常運作。
UMDF USB 驅動程式中的 I/O 佇列
對於支援選擇性暫停的 UMDF 驅動程式,UMDF 驅動程式是否擁有其裝置的電源原則,是否決定其可以使用的 I/O 佇列類型。 支援選擇性暫停且為 PPO 的 UMDF 驅動程式可以使用受電源管理或未受電源管理的佇列。 支援選擇性暫停但不是 PPO 的 UMDF USB 驅動程式不應使用任何受電源管理的 I/O 佇列。
如果在裝置暫停時,I/O 要求抵達受電源管理的佇列,除非驅動程式是 PPO,否則架構不會顯示要求,如 USB 驅動程式中選擇性暫停中的影像所示。 如果 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 方法,其採用下列三個參數:
- 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 驅動程式必須執行下列動作:
- 裝置堆疊的宣告電源原則擁有權,通常是在其驅動程式回呼物件的 IDriverEntry::OnDeviceAdd 方法中,如先前所述。
- 在架構裝置物件上呼叫 IWDFDevice2::AssignS0IdleSettings 方法,以啟用選擇性暫停。
若要從 PPO 啟用 USB 選擇性暫停
- 呼叫 IWDFDevice2::AssignS0IdleSettings,通常是從裝置回呼物件的 OnPrepareHardware 方法。 將參數設定為 AssignS0IdleSettings,如下所示:
- IdleCaps 至 IdleUsbSelectiveSuspend。
- DxState 到架構轉換閒置裝置的裝置睡眠狀態。 針對 USB 選擇性暫停,指定 PowerDeviceMaximum,這表示架構應該使用總線驅動程式指定的值。
- IdleTimeout 到裝置必須在架構轉換為 DxState 之前閒置的毫秒數。
- 如果您的驅動程式允許使用者管理閑置設定,則 UserControlOfIdleSettings 為 IdleAllowUserControl,否則為 IdleDoNotAllowUserControl。
- 啟用 至 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 驅動程式必須通知 WinUSB 裝置和驅動程式支援選擇性暫停,而且必須在 INF 檔案中啟用選擇性暫停,或在 USB 目標裝置物件上設定電源原則。
如果 UMDF 函式驅動程式啟用選擇性暫停,基礎 WinUSB.sys 驅動程式會決定裝置閑置的時機。 當沒有任何傳輸擱置時,或只有擱置的傳輸是在中斷或大量端點上的 IN 傳輸時,WinUSB 就會啟動閑置逾時計數器。 根據預設,閑置逾時為5秒,但UMDF驅動程式可以變更此預設值。
當 WinUSB.sys 判斷裝置處於閑置狀態時,它會傳送要求以將裝置暫止於內核模式裝置堆疊。 總線驅動程序會視需要變更硬體的狀態。 如果埠上的所有裝置功能都已暫停,埠會進入USB選擇性暫停狀態。
如果 I/O 要求在裝置暫停時抵達 WinUSB.sys,WinUSB.sys 如果裝置必須提供電源才能服務要求,WinUSB.sys 繼續裝置作業。 UMDF 驅動程式不需要在系統保留在 S0 中時繼續裝置的任何程式代碼。 如果裝置硬體可以產生喚醒訊號,UMDF 驅動程式也可以支援 S1、S2 或 S3 的系統喚醒。 如需詳細資訊,請參閱 UMDF 驅動程式中的系統喚醒。
不是 PPO 的 UMDF 驅動程式可以採取下列兩個步驟來支援選擇性暫停:
- 通知 WinUSB.sys 裝置和驅動程式支援選擇性暫停。
- 啟用USB選擇性暫停。
此外,驅動程式也可以選擇性地:
- 設定裝置的逾時值。
- 允許使用者啟用或停用選擇性暫停。
如需如何在不是 PPO 的 UMDF USB 函式驅動程式中實作 USB 選擇性暫停的範例,請參閱 WDK 中的Fx2_Driver範例。 此範例位於 %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\Umdf\Fx2_Driver\ IdleWake_Non-PPO。
通知 WinUSB 選擇性暫停支援
若要通知 WinUSB.sys 裝置可以支援 USB 選擇性暫停,裝置 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。 下列範例顯示Fx2_Driver範例如何在 DeviceNonPpo.cpp 檔案中啟用選擇性暫停:
BOOL AutoSuspend = TRUE; hr = m_pIUsbTargetDevice->SetPowerPolicy( AUTO_SUSPEND, sizeof(BOOL), (PVOID) &AutoSuspend );
若要在安裝期間啟用支援,INF 包含 AddReg 指示詞,可將 DefaultIdleState 值新增至裝置的硬體密鑰,並將值設定為 1。 例如:
HKR,,"DefaultIdleState",0x00010001,1
設定閑置逾時值
根據預設,WinUSB 會在 5 秒後暫停裝置,如果沒有暫止傳輸,或只有擱置的傳輸是在中斷或大量端點上的 IN 傳輸。 UMDF 驅動程式可以在 INF 或執行時間安裝時變更此閒置逾時值。
若要在安裝時設定閑置逾時,INF 包含 AddReg 指示詞,可將 DefaultIdleTimeout 值新增至裝置的硬體密鑰,並將值設定為以毫秒為單位的逾時間隔。 下列範例會將逾時設定為 7 秒:
HKR,,"DefaultIdleTimeout",0x00010001,7000
若要在運行時間設定閑置逾時,驅動程式會呼叫 IWDFUsbTargetDevice::SetPowerPolicy ,並將 PolicyType 設為 SUSPEND_DELAY,而 Value 會以毫秒為單位呼叫閑置逾時值。 在 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 驅動程式可以選擇性地允許使用者啟用或停用選擇性暫停。 若要這樣做,請在 INF 中包含 AddReg 指示詞,將 UserSetDeviceIdleEnabled 值新增至裝置的硬體密鑰,並將值設定為 1。 下列顯示要用於 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 方法:
- 當系統進入可喚醒的 Sx 狀態時,裝置轉換到電源狀態的 DxState。 針對USB裝置,指定 PowerDeviceMaximum 以使用總線驅動程式指定的值。
- 如果您的驅動程式允許使用者管理喚醒設定,或是將喚醒設定設為 WakeDoNotAllowUserControl,則 UserControlOfWakeSettings 為 WakeAllowUserControl。
- 啟用至 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
藉由設定此值,驅動程式都會啟用系統喚醒,並允許使用者控制裝置喚醒系統的能力。 在 裝置管理員 中,裝置的電源管理設定屬性頁包含一個複選框,用戶可以啟用或停用系統喚醒。