Share via


Selektives Anhalten in USB-UMDF-Treibern

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

Wichtige APIs

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

  • Durch Den Anspruch auf den Besitz der Energierichtlinie und die Behandlung von Gerät im Leerlauf wird heruntergefahren und fortgesetzt.
  • Indem Sie sich auf den WinUSB.sys Treiber verlassen, den Microsoft bereitstellt, um das selektive Anhalten zu verarbeiten. WinUSB.sys wird während der Installation des UMDF-USB-Treibers als Teil des Kernelmodus-Gerä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 das selektive Anhalten in einem UMDF-USB-Treiber unterstützt wird. Dieses Beispiel finden Sie unter %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 selektives Anhalten unterstützen, müssen die folgenden Richtlinien befolgen:

  • Der UMDF-Treiber kann den Besitz von Energierichtlinien für seinen Gerätestapel beanspruchen, ist jedoch nicht erforderlich. Standardmäßig besitzt der zugrunde liegende WinUSB.sys Treiber die Energierichtlinie.
  • Ein UMDF-Treiber, der das selektive Anhalten unterstützt und als PPO verwendet wird, kann powerverwaltete Warteschlangen oder Warteschlangen verwenden, die nicht energieverwaltet sind. Ein UMDF-Treiber, der das selektive Anhalten unterstützt, aber nicht das PPO ist, darf keine stromverwalteten Warteschlangen verwenden.

Besitz von Energierichtlinien 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 den Besitz von Energierichtlinien beanspruchen. Da nur ein Treiber in jedem Gerätestapel der PPO sein kann, muss ein UMDF-USB-Treiber, der das PPO ist, den Besitz von Energierichtlinien in WinUSB.sys explizit deaktivieren.

So beanspruchen Sie den Besitz von Energierichtlinien in einem UMDF-USB-Treiber

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

    FxDeviceInit->SetPowerPolicyOwnership(TRUE);
    
  2. Deaktivieren Sie den Besitz von Energierichtlinien in WinUSB. Fügen Sie in die INF-Datei des Treibers eine AddReg-Direktive ein, die den WinUsbPowerPolicyOwnershipDisabled-Wert in der Registrierung auf einen Wert ungleich null festlegt. Die AddReg-Direktive muss in einem DDInstall.HW-Abschnitt 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 früheren WDF-Versionen als 1.9 erstellt werden, dürfen keinen Besitz von Energierichtlinien beanspruchen. Mit diesen früheren Versionen von WDF funktioniert das selektive Anhalten von USB nur ordnungsgemäß, wenn WinUSB.sys das PPO ist.

E/A-Warteschlangen in UMDF-USB-Treibern

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

Wenn eine E/A-Anforderung für eine energieverwaltete Warteschlange eingeht, während das Gerät angehalten wird, stellt das Framework die Anforderung nur dann bereit, wenn der Treiber PPO ist, wie in der Abbildung unter Selektives Anhalten in USB-Treibern gezeigt. Wenn der UMDF-Treiber nicht der PPO für das Gerät ist, kann das Framework das Gerät nicht in seinem Namen 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 Energie verwaltet wird, stellt das Framework E/A-Anforderungen an den UMDF-Treiber bereit, auch wenn das Gerät ausgeschaltet ist. Der UMDF-Treiber formatiert die Anforderung und leitet sie auf die übliche Weise an das Standard-E/A-Ziel weiter. Spezieller Code ist nicht erforderlich. Wenn die Anforderung den PPO (WinUSB.sys) erreicht, WinUSB.sys das Gerät ein und führt den erforderlichen E/A-Vorgang aus.

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 energieverwaltete Warteschlange erstellt werden soll, indem er nach der Konstanten sucht.

Um die Warteschlange zu erstellen, ruft der Treiber die vom Treiber definierte 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.
  • Standardwert: Ein boolescher Wert, der angibt, ob die Warteschlange eine Standardwarteschlange ist.
  • PowerManaged, ein boolescher Wert, der angibt, ob die Warteschlange energieverwaltet ist.

Der folgende Codeausschnitt zeigt den Aufruf des Treibers an die CMyQueue::Initialize-Methode im Rahmen der Lese-/Schreibwarteschlangenerstellung:

#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 der 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 Aktionen ausführen:

  1. Fordern Sie den Besitz der Energierichtlinie für den Gerätestapel an, in der Regel in der IDriverEntry::OnDeviceAdd-Methode für ihr 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 die selektive USB-Aussetzung 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, in den das Framework das Gerät im Leerlauf übergibt. Geben Sie für die selektive USB-Aussetzung PowerDeviceMaximum an, was angibt, dass das Framework den Wert verwenden soll, den der Bustreiber angegeben hat.
    • IdleTimeout auf die Anzahl von Millisekunden, die das Gerät im Leerlauf befinden muss, bevor das Framework es zu DxState übergibt.
    • UserControlOfIdleSettings auf IdleAllowUserControl , wenn Ihr Treiber Benutzern erlaubt, die Einstellungen im Leerlauf zu verwalten, oder auf andere Weise idleDoNotAllowUserControl.
    • Für WdfUseDefault aktiviert, um das selektive Anhalten standardmäßig zu aktivieren, aber damit die Einstellung des Benutzers die Standardeinstellung überschreiben kann.

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

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

Wenn die Gerätehardware ein Aktivierungssignal generieren kann, kann der UMDF-Treiber auch die Systemreaktivierung von S1, S2 oder S3 unterstützen. Weitere Informationen finden Sie unter Systemreaktivierung in einem UMDF-Treiber.

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

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

Wenn ein UMDF-Funktionstreiber das selektive Anhalten aktiviert, 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 Interrupt- oder Massenendpunkt sind. Standardmäßig beträgt das Leerlauftimeout 5 Sekunden, aber der UMDF-Treiber kann diese Standardeinstellung ändern.

Wenn WinUSB.sys feststellt, dass sich das Gerät im Leerlauf befindet, sendet es eine Anforderung, das Gerät im Kernelmodus im Gerätestapel anzusetzen. Der Bustreiber ändert den Zustand der Hardware nach Bedarf. Wenn alle Gerätefunktionen am Port angehalten wurden, wechselt der Port in den usb-selektiven Anhaltezustand.

Wenn eine E/A-Anforderung bei WinUSB.sys eingeht, während das Gerät angehalten wird, setzt WinUSB.sys den Gerätebetrieb fort, wenn das Gerät eingeschaltet werden muss, um die Anforderung zu verarbeiten. Der UMDF-Treiber erfordert keinen Code, um das Gerät fortzusetzen, während das System in S0 verbleibt. Wenn die Gerätehardware ein Aktivierungssignal generieren kann, kann der UMDF-Treiber auch die Systemreaktivierung von S1, S2 oder S3 unterstützen. Weitere Informationen finden Sie unter Systemreaktivierung in einem UMDF-Treiber.

Ein UMDF-Treiber, der nicht der PPO ist, kann das selektive Anhalten unterstützen, indem die folgenden zwei Schritte ausgeführt werden:

  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 für die Implementierung der selektiven USB-Aussetzung in einem UMDF-USB-Funktionstreiber, der nicht der PPO ist, finden Sie im Beispiel Fx2_Driver 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 das selektive Anhalten

Um WinUSB.sys darüber zu informieren, dass das Gerät das selektive Anhalten von USB unterstützen kann, muss das Geräte-INF dem Hardwareschlüssel des Geräts den Wert DeviceIdleEnabled hinzufügen und den Wert auf 1 festlegen. Im folgenden Beispiel wird gezeigt, wie im beispiel für Fx2_Driver in der Datei WUDFOsrUsbFx2_IdleWakeNon-PPO.Inx dieser Wert hinzugefügt und festgelegt wird:

[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 entweder 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 Parameter PolicyType 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 Datei DeviceNonPpo.cpp aktiviert:

    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 dem Hardwareschlüssel des Geräts den DefaultIdleState-Wert hinzufügt und den Wert auf 1 festlegt. Beispiel:

    HKR,,"DefaultIdleState",0x00010001,1
    

So legen Sie einen Leerlauftimeoutwert fest

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

  • Um ein Leerlauftimeout bei der Installation festzulegen, enthält die INF eine AddReg-Direktive, die dem Hardwareschlüssel des Geräts den DefaultIdleTimeout-Wert 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 ein Leerlauftimeout zur Laufzeit festzulegen, ruft der Treiber IWDFUsbTargetDevice::SetPowerPolicy auf, wobei PolicyType auf SUSPEND_DELAY und Wert auf den Leerlauftimeoutwert in Millisekunden festgelegt ist. 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 ermöglichen Sie die Benutzersteuerung der selektiven USB-Aussetzung**

UMDF-USB-Treiber, die die Unterstützung für selektives Anhalten von WinUSB verwenden, können dem Benutzer optional das Aktivieren oder Deaktivieren des selektiven Anhaltens ermöglichen. Fügen Sie hierzu eine AddReg-Direktive in das INF ein, die dem Hardwareschlüssel des Geräts den Wert UserSetDeviceIdleEnabled hinzufügt und den Wert auf 1 festlegt. Im Folgenden wird die für die AddReg-Direktive zu verwendende Zeichenfolge veranschaulicht:

HKR,,"UserSetDeviceIdleEnabled",0x00010001,1

Wenn UserSetDeviceIdleEnabled festgelegt ist, enthält das Dialogfeld Eigenschaften des Geräts eine Registerkarte Energieverwaltung, auf der der Benutzer die selektive USB-Aussetzung aktivieren oder deaktivieren kann.

Systemreaktivierung in einem UMDF-Treiber

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

Ein UMDF USB PPO-Treiber kann die Systemreaktivierung unterstützen, indem er Aktivierungsinformationen für das Treiberobjekt des Frameworks bereitstellt. Wenn ein externes Ereignis die Systemreaktivierung auslöst, kehrt das Framework das Gerät in den Arbeitszustand zurück.

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

Zur Unterstützung der Systemreaktivierung in einem UMDF-USB-Treiber, der der PPO ist**

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

  • DxState in den Energiezustand, in den das Gerät übergeht, wenn das System in einen reaktivierbaren 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 Benutzern die Verwaltung der Aktivierungseinstellungen oder anderweitig wakeDoNotAllowUserControl zulässt.
  • FürWdfUseDefault aktiviert, um die Aktivierung standardmäßig zu aktivieren, aber damit die Einstellung des Benutzers die Standardeinstellung überschreiben kann.

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

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

So aktivieren Sie die Systemreaktivierung über WinUSB in einem Nicht-PPO-Treiber**

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

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

Durch Festlegen dieses Werts aktiviert der Treiber sowohl die Systemreaktivierung als auch den Benutzer, die Fähigkeit des Geräts zu steuern, das System zu reaktivieren. In Geräte-Manager enthält die Eigenschaftenseite der Energieverwaltungseinstellungen für das Gerät ein Kontrollkästchen, mit dem der Benutzer die Systemreaktivierung aktivieren oder deaktivieren kann.