Freigeben über


Selektives Anhalten in USB-UMDF-Treibern

In diesem Thema wird beschrieben, wie UMDF-Funktionstreiber die selektive Suspendierung von USB unterstützen.

Wichtige APIs

UMDF-Funktionstreiber können das selektive Anhalten von USB auf zwei Arten unterstützen:

  • Indem die Energieverwaltung übernommen wird und das Geräte-Leerlaufsystem gesteuert und das Wiederaufnehmen der Geräteleistung verwaltet wird.
  • Durch die Nutzung des WinUSB.sys-Treibers, den Microsoft bereitstellt, um das selektive Anhalten zu steuern. WinUSB.sys wird während der Installation des UMDF-USB-Treibers als Teil des Kernelmodusgerätestapels installiert. WinUSB.sys implementiert die zugrunde liegenden Mechanismen zum Anhalten und Fortsetzen des USB-Gerätebetriebs.

Beide Ansätze erfordern nur kleine Codemengen. Das IdleWake-Beispiel, das im WDK bereitgestellt wird, zeigt, wie selektives Anhalten in einem UMDF-USB-Treiber unterstützt wird. Dieses Beispiel finden Sie in %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\ UMDF\Fx2_Driver\IdleWake. Der Ordner enthält sowohl PPO- als auch Nicht-PPO-Versionen des Beispiels.

UMDF-Treiber, die das selektive Anhalten unterstützen, müssen folgenden Richtlinien befolgen:

  • Der UMDF-Treiber kann den Besitz der Energierichtlinie für seinen Gerätestapel beanspruchen, muss dies jedoch nicht tun. Standardmäßig verwaltet der zugrunde liegende WinUSB.sys-Treiber die Energieverwaltungspolitik.
  • Ein UMDF-Treiber, der das selektive Anhalten unterstützt und das PPO ist, kann entweder stromverwaltete oder nicht stromverwaltete Warteschlangen verwenden. Ein UMDF-Treiber, der selektives Anhalten unterstützt, aber nicht das PPO ist, darf keine stromverwalteten Warteschlangen verwenden.

Der Besitz der Energiepolitik in UMDF-USB-Treibern

Standardmäßig ist WinUSB.sys das PPO für einen Gerätestapel, der einen UMDF-USB-Treiber enthält. Ab WDF 1.9 können UMDF-basierte USB-Treiber die Kontrolle über die Energierichtlinien übernehmen. Da nur ein Treiber in jedem Gerätestapel das PPO sein kann, muss ein UMDF-USB-Treiber, der das PPO ist, den Besitz von Energierichtlinien in WinUSB.sysexplizit deaktivieren.

Fordern Sie die Besitzrechte an der Energieverwaltungspolitik in einem UMDF-USB-Treiber an.

  1. Rufen Sie IWDFDeviceInitialize::SetPowerPolicyOwnership auf, und übergeben Sie TRUE, in der Regel aus der IDriverEntry::OnDeviceAdd-Methode für das Treiberrückrufobjekt. Beispiel:

    FxDeviceInit->SetPowerPolicyOwnership(TRUE);
    
  2. Deaktivieren Sie die Energieverwaltungs-Zuständigkeit in WinUSB. Fügen Sie in der INF-Datei des Treibers eine AddReg-Direktive hinzu, die den WinUsbPowerPolicyOwnershipDisabled-Wert in der Registrierung auf einen Wert ungleich Null festlegt. Die AddReg-Direktive muss in einem Abschnitt "DDInstall.HW" angezeigt werden. Beispiel:

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

UMDF-USB-Treiber, die selektives Anhalten unterstützen und mit WDF-Versionen vor 1.9 erstellt wurden, dürfen die Verwaltung der Energierichtlinien nicht übernehmen. Bei diesen früheren Versionen von WDF funktioniert das selektive Anhalten von USB nur ordnungsgemäß, wenn WinUSB.sys als PPO eingestellt ist.

E/A-Warteschlangen in UMDF-USB-Treibern

Bei einem UMDF-Treiber, der das selektive Anhalten unterstützt, bestimmt, ob er die Energierichtlinie für sein Gerät verwaltet, den Typ der E/A-Warteschlangen, die er verwenden kann. UMDF-Treiber, die selektives Aussetzen unterstützen und PPOs sind, können Warteschlangen verwenden, die entweder energieverwaltet oder nicht energieverwaltet sind. UMDF-USB-Treiber, die selektives Anhalten unterstützen, aber nicht das PPO, sollten keine energieverwalteten E/A-Warteschlangen verwenden.

Wenn eine E/A-Anforderung für eine stromverwaltete Warteschlange eingeht, während sich das Gerät im Ruhezustand befindet, bearbeitet das Framework die Anforderung nicht, es sei denn, der Treiber ist PPO, wie in der Abbildung zu Selektivem Anhalten bei USB-Treibern gezeigt. Wenn der UMDF-Treiber nicht das PPO für das Gerät ist, kann das Framework das Gerät nicht in seinem Auftrag einschalten. Daher bleibt die Anforderung in der energieverwalteten Warteschlange hängen. Die Anforderung erreicht nie WinUSB, sodass WinUSB das Gerät nicht einschalten kann. Folglich kann der Gerätestapel angehalten werden.

Wenn die Warteschlange nicht mit Strom verwaltet wird, stellt das Framework E/A-Anforderungen an den UMDF-Treiber vor, auch wenn das Gerät heruntergefahren wird. Der UMDF-Treiber formatiert die Anforderung und leitet sie in der üblichen Weise im Gerätestapel an das Standard-E/A-Ziel weiter. Spezieller Code ist nicht erforderlich. Wenn die Anforderung das PPO (WinUSB.sys) erreicht, wird das Gerät durch WinUSB.sys unterstützt und der erforderliche E/A-Vorgang ausgeführt.

Der Beispieltreiber in %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\umdf\Fx2_Driver\IdleWake definiert die Konstante '_NOT_POWER_POLICY_OWNER_', wenn Sie die Nicht-PPO-Version des Treibers erstellen. Wenn der Treiber eine Warteschlange für Lese- und Schreibanforderungen erstellt, bestimmt er, ob eine stromverwaltete Warteschlange erstellt werden soll, indem nach der Konstante gesucht wird.

Zum Erstellen der Warteschlange ruft der Treiber die treiberdefinierte CMyQueue::Initialize-Methode auf, die die folgenden drei Parameter verwendet:

  • DispatchType, ein WDF_IO_QUEUE_DISPATCH_TYPE Enumerationswert, der angibt, wie die Warteschlange Anforderungen verteilt.
  • Standard, ein boolescher Wert, der angibt, ob es sich bei der Warteschlange um eine Standardwarteschlange handelt.
  • PowerManaged, ein Boolescher Wert, der angibt, ob die Warteschlange energieverwaltet ist.

Der folgende Codeausschnitt zeigt den Aufruf des Treibers an die CMyQueue::Initialize-Methode als Teil der Erstellung von Lese-/Schreibwarteschlangen:

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

CMyQueue::Initialize ruft dann IWDFDevice::CreateIoQueue auf, um die Warteschlange wie folgt zu erstellen:

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

Diese Codesequenz führt zu einer Standardwarteschlange, die Anforderungen parallel verteilt. Wenn der Treiber das PPO ist, wird die Warteschlange energieverwaltet, und wenn der Treiber nicht das PPO ist, wird die Warteschlange nicht energieverwaltet.

Unterstützung des selektiven Anhaltens von USB in einem UMDF-PPO

Um das selektive Anhalten zu unterstützen, muss ein UMDF-USB-Treiber, der das PPO für seinen Gerätestapel ist, folgende Schritte ausführen:

  1. Beanspruchen Sie das Eigentum an der Stromrichtlinie für den Gerätestapel, normalerweise in der Methode IDriverEntry::OnDeviceAdd auf seinem Treiberrückrufobjekt, wie zuvor beschrieben.
  2. Aktivieren Sie das selektive Anhalten, indem Sie die IWDFDevice2::AssignS0IdleSettings-Methode für das Framework-Geräteobjekt aufrufen.

So aktivieren Sie das selektive Anhalten von USB von einem PPO

  • Rufen Sie IWDFDevice2::AssignS0IdleSettings auf, in der Regel aus der OnPrepareHardware-Methode für das Geräterückrufobjekt. Legen Sie die Parameter wie folgt auf AssignS0IdleSettings fest:
    • IdleCaps zu IdleUsbSelectiveSuspend.
    • DxState in den Standbyzustand des Geräts, zu dem das Framework das Leerlaufgerät übergibt. Geben Sie für das selektive Anhalten von USB PowerDeviceMaximum an, was darauf hinweist, dass das Framework den Wert verwenden soll, den der Bustreiber angegeben hat.
    • IdleTimeout auf die Anzahl von Millisekunden, die das Gerät im Leerlauf sein muss, bevor das Framework es zu DxState übergibt.
    • UserControlOfIdleSettings zu IdleAllowUserControl , wenn Ihr Treiber Benutzern erlaubt, die Leerlaufeinstellungen zu verwalten, oder andernfalls zu IdleDoNotAllowUserControl.
    • Aktiviert für WdfUseDefault , um das selektive Anhalten standardmäßig zu aktivieren, aber um die Einstellung des Benutzers zuzulassen, die Standardeinstellung außer Kraft zu setzen.

Das folgende Beispiel zeigt, wie der IdleWake_PPO-Treiber diese Methode in der internen CMyDevice::SetPowerManagement-Methode aufruft:

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

Wenn die Gerätehardware ein Wake-Signal generieren kann, kann der UMDF-Treiber auch das Systemaufwecken von S1, S2 oder S3 unterstützen. Ausführliche Informationen finden Sie unter System Wake in einem UMDF-Treiber.

Unterstützung der USB-Selektivsuspendierung in einem nicht-PPO UMDF-Treiber

Ein UMDF-Funktionstreiber, der nicht das PPO ist, kann das selektive Anhalten mithilfe der Funktionen des zugrunde liegenden WinUSB.sys-Treibers unterstützen. Der UMDF-Treiber muss WinUSB benachrichtigen, dass das Gerät und der Treiber das selektive Anhalten unterstützen. Selektives Anhalten muss entweder in der INF-Datei aktiviert werden oder durch Festlegen der Energierichtlinie für das USB-Zielgerätobjekt.

Wenn ein UMDF-Funktionstreiber das selektive Anhalten ermöglicht, bestimmt der zugrunde liegende WinUSB.sys Treiber, wann sich das Gerät im Leerlauf befindet. WinUSB startet einen Leerlauftimeoutzähler, wenn keine Übertragungen ausstehen oder wenn die einzigen ausstehenden Übertragungen IN-Übertragungen auf einem Unterbrechungs- oder Massenendpunkt sind. Standardmäßig beträgt das Leerlauftimeout 5 Sekunden, aber der UMDF-Treiber kann diese Standardeinstellung ändern.

Wenn WinUSB.sys bestimmt, dass das Gerät im Leerlauf ist, sendet es eine Anforderung, das Gerät entlang des Kernelmodus-Gerätestapels anzuhalten. Der Bustreiber ändert den Zustand der Hardware entsprechend. Wenn alle Gerätefunktionen am Anschluss angehalten wurden, wechselt der Port in den selektiven USB-Ruhezustand.

Wenn eine E/A-Anforderung bei WinUSB.sys eingeht, während das Gerät angehalten ist, setzt WinUSB.sys den Gerätevorgang fort, wenn das Gerät eingeschaltet werden muss, um die Anforderung zu warten. Der UMDF-Treiber erfordert keinen Code, um das Gerät fortzusetzen, während das System in S0 verbleibt. Wenn die Gerätehardware ein Wake-Signal generieren kann, kann der UMDF-Treiber auch das Systemaufwecken aus S1, S2 oder S3 unterstützen. Ausführliche Informationen finden Sie unter System Wake in einem UMDF-Treiber.

Ein UMDF-Treiber, der nicht das PPO ist, kann selektives Anhalten unterstützen, indem er die folgenden zwei Schritte ausführt:

  1. Benachrichtigen WinUSB.sys, dass das Gerät und der Treiber das selektive Anhalten unterstützen.
  2. Aktivieren des selektiven Anhaltens von USB.

Darüber hinaus kann der Treiber optional:

  • Legen Sie einen Timeoutwert für das Gerät fest.
  • Zulassen, dass der Benutzer das selektive Anhalten aktivieren oder deaktivieren kann.

Ein Beispiel, wie der selektive Suspend-Modus von USB in einem UMDF-USB-Funktionstreiber implementiert wird, der nicht das PPO ist, finden Sie im Fx2_Driver-Beispiel im WDK. Dieses Beispiel befindet sich unter %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\Umdf\Fx2_Driver\ IdleWake_Non-PPO.

So benachrichtigen Sie WinUSB über die Unterstützung für Selective Suspend.

Um WinUSB.sys zu benachrichtigen, dass das Gerät das selektive Anhalten von USB unterstützen kann, muss das Gerät INF dem Hardwareschlüssel des Geräts den Wert "DeviceIdleEnabled" hinzufügen und den Wert auf 1 festlegen. Das folgende Beispiel zeigt, wie das Fx2_Driver Beispiel diesen Wert in der Datei WUDFOsrUsbFx2_IdleWakeNon-PPO.Inx hinzufügt und festlegt:

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

So aktivieren Sie das selektive Anhalten von USB

Ein UMDF-USB-Treiber kann das selektive Anhalten von USB zur Laufzeit oder während der Installation im INF aktivieren.

  • Um die Unterstützung zur Laufzeit zu aktivieren, ruft der Funktionstreiber IWDFUsbTargetDevice::SetPowerPolicy auf und legt den PolicyType-Parameter auf AUTO_SUSPEND und den Value-Parameter auf TRUE oder 1 fest. Das folgende Beispiel zeigt, wie das Fx2_Driver Beispiel das selektive Anhalten in der DeviceNonPpo.cpp Datei ermöglicht:

    BOOL AutoSuspend = TRUE;
    hr = m_pIUsbTargetDevice->SetPowerPolicy( AUTO_SUSPEND,
                                              sizeof(BOOL),
                                             (PVOID) &AutoSuspend );
    
  • Um die Unterstützung während der Installation zu aktivieren, enthält die INF eine AddReg-Direktive, die den DefaultIdleState-Wert zum Hardwareschlüssel des Geräts hinzufügt und den Wert auf 1 festlegt. Beispiel:

    HKR,,"DefaultIdleState",0x00010001,1
    

So legen Sie einen Leerlauf-Zeitüberschreitungswert fest

WinUSB hält das Gerät standardmäßig nach 5 Sekunden an, wenn keine Übertragungen ausstehen oder die einzigen ausstehenden Übertragungen IN-Übertragungen auf einem Unterbrechungs- oder Massenendpunkt sind. Ein UMDF-Treiber kann diesen Leerlaufzeitüberschreitungswert entweder bei der Installation im INF oder zur Laufzeit ändern.

  • Zum Festlegen eines Leerlauftimeouts bei der Installation enthält die INF eine AddReg-Direktive, die den DefaultIdleTimeout-Wert zum Hardwareschlüssel des Geräts hinzufügt und den Wert auf das Timeoutintervall in Millisekunden festlegt. Im folgenden Beispiel wird das Timeout auf 7 Sekunden festgelegt:

    HKR,,"DefaultIdleTimeout",0x00010001,7000
    
  • Um einen Leerlauftimeout zur Laufzeit festzulegen, ruft der Treiber IWDFUsbTargetDevice::SetPowerPolicy mit dem PolicyType auf SUSPEND_DELAY und dem Wert, der dem Leerlauftimeout in Millisekunden entspricht, auf. Im folgenden Beispiel aus der datei Device.cpp legt das Fx2_Driver Beispiel das Timeout auf 10 Sekunden fest:

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

So stellen Sie die Benutzersteuerung des selektiven Anhaltens von USB bereit**

UMDF-USB-Treiber, die WinUSB selektive Suspendierungsunterstützung verwenden, können es dem Benutzer optional ermöglichen, die selektive Suspendierung zu aktivieren oder zu deaktivieren. Fügen Sie dazu eine AddReg-Direktive in die INF ein, die den UserSetDeviceIdleEnabled-Wert zum Hardwareschlüssel des Geräts hinzufügt und den Wert auf 1 festlegt. Im Folgenden wird die für die AddReg-Direktive zu verwendende Zeichenfolge gezeigt:

HKR,,"UserSetDeviceIdleEnabled",0x00010001,1

Wenn UserSetDeviceIdleEnabled festgelegt ist, enthält das Dialogfeld "Eigenschaften" des Geräts eine Registerkarte "Energieverwaltung", mit der der Benutzer den USB-Selektivem Standby aktivieren oder deaktivieren kann.

Systemaufwecken in einem UMDF-Treiber

In einem UMDF-Treiber ist die Unterstützung für die Systemaufweckung unabhängig von der Unterstützung für das selektive Anhalten. Ein UMDF-USB-Treiber kann sowohl die Systemreaktivierung als auch das selektive Suspend unterstützen, weder die Systemreaktivierung noch das selektive Suspend, oder entweder die Systemreaktivierung oder das selektive Suspend. Ein Gerät, das die Systemaktivierung unterstützt, kann das System aus einem Ruhezustand (S1, S2 oder S3) reaktivieren.

Ein UMDF-USB-PPO-Treiber kann das Aufwecken des Systems unterstützen, indem er Aufwachinformationen für das Treiberobjekt des Frameworks bereitstellt. Wenn ein externes Ereignis das Aufwecken des Systems auslöst, bringt das Framework das Gerät in den Betriebszustand zurück.

Ein NICHT-PPO-USB-Treiber kann die Systemreaktivierungsunterstützung verwenden, die der WinUSB.sys Treiber implementiert.

So unterstützen Sie das Systemerwachen in einem UMDF-USB-Treiber, der das PPO** ist

Rufen Sie die IWDFDevice2::AssignSxWakeSettings-Methode für das Geräteobjekt des Frameworks mit den folgenden Parametern auf:

  • DxState in den Energiezustand, zu dem das Gerät wechselt, wenn das System in einen aufweckbaren Sx-Zustand wechselt. Geben Sie für USB-Geräte powerDeviceMaximum an, um den vom Bustreiber angegebenen Wert zu verwenden.
  • UserControlOfWakeSettings auf WakeAllowUserControl, wenn Ihr Treiber es zulässt, dass Benutzer die Wake-Einstellungen verwalten, andernfalls auf WakeDoNotAllowUserControl.
  • Aktiviert für WdfUseDefault , um die Aktivierung standardmäßig zu aktivieren, aber um zuzulassen, dass die Einstellung des Benutzers die Standardeinstellung außer Kraft setzt.

Das folgende Beispiel zeigt, wie der IdleWake_PPO-Treiber diese Methode in der internen CMyDevice::SetPowerManagement-Methode aufruft:

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

Um die Systemaufweckung über WinUSB in einem Nicht-PPO-Treiber zu ermöglichen**

Um die Systemreaktivierung über WinUSB zu aktivieren, fügt der INF des Treibers den Registrierungswert SystemWakeEnabled zum Hardwareschlüssel des Geräts hinzu und legt ihn auf 1 fest. Das IdleWake_Non-PPO-Muster ermöglicht die Systemaktivierung wie folgt:

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

Durch das Festlegen dieses Werts aktiviert der Treiber die Systemaufweckfunktion und gestattet dem Benutzer, die Möglichkeit des Geräts zu steuern, das System zu reaktivieren. Im Geräte-Manager enthält die Eigenschaftenseite mit den Einstellungen für die Energieverwaltung für das Gerät ein Kontrollkästchen, mit dem der Benutzer die Systemaktivierung aktivieren oder deaktivieren kann.