Sospensione selettiva nei driver UMDF USB

Questo argomento descrive come i driver di funzione UMDF supportano la sospensione selettiva USB.

API importanti

I driver di funzione UMDF possono supportare la sospensione selettiva USB in uno dei due modi seguenti:

  • Rivendicando la proprietà dei criteri di risparmio energia e gestendo l'accensione e la ripresa dell'inattività del dispositivo.
  • Basandosi sul driver WinUSB.sys, fornito da Microsoft, per gestire la sospensione selettiva. WinUSB.sys viene installato come parte dello stack di dispositivi in modalità kernel durante l'installazione del driver USB UMDF. WinUSB.sys implementa i meccanismi sottostanti per la sospensione e la ripresa dell'operazione del dispositivo USB.

Entrambi gli approcci richiedono solo piccole quantità di codice. L'esempio IdleWake fornito in WDK illustra come supportare la sospensione selettiva in un driver USB UMDF. Questo esempio è disponibile in %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\ UMDF\Fx2_Driver\IdleWake. La cartella contiene sia versioni PPO che non PPO dell'esempio.

I driver UMDF che supportano la sospensione selettiva devono seguire queste linee guida:

  • Il driver UMDF può richiedere la proprietà dei criteri di alimentazione per lo stack di dispositivi, ma non è necessario farlo. Per impostazione predefinita, il driver di WinUSB.sys sottostante è proprietario dei criteri di alimentazione.
  • Un driver UMDF che supporta la sospensione selettiva ed è PPO può usare code o code gestite dall'alimentazione che non sono gestite dall'alimentazione. Un driver UMDF che supporta la sospensione selettiva, ma non è PPO, non deve usare code gestite dall'alimentazione.

Proprietà dei criteri di alimentazione nei driver USB UMDF

Per impostazione predefinita, WinUSB.sys è PPO per uno stack di dispositivi che contiene un driver USB UMDF. A partire da WDF 1.9, i driver USB basati su UMDF possono richiedere la proprietà dei criteri di alimentazione. Poiché un solo driver in ogni stack di dispositivi può essere PPO, un driver USB UMDF che è l'PPO deve disabilitare in modo esplicito la proprietà dei criteri di alimentazione in WinUSB.sys.

Per richiedere la proprietà dei criteri di alimentazione in un driver USB UMDF

  1. Chiamare IWDFDeviceInitialize::SetPowerPolicyOwnership e passare TRUE, in genere dal metodo IDriverEntry::OnDeviceAdd nell'oggetto callback del driver. Ad esempio:

    FxDeviceInit->SetPowerPolicyOwnership(TRUE);
    
  2. Disabilitare la proprietà dei criteri di alimentazione in WinUSB. Nel file INF del driver includere una direttiva AddReg che imposta il valore WinUsbPowerPolicyOwnershipDisabled nel Registro di sistema su un valore diverso da zero. La direttiva AddReg deve essere visualizzata in una sezione DDInstall.HW. Ad esempio:

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

I driver USB UMDF che supportano la sospensione selettiva e vengono compilati con versioni WDF precedenti alla 1.9 non devono richiedere la proprietà dei criteri di alimentazione. Con queste versioni precedenti di WDF, la sospensione selettiva USB funziona correttamente solo se WinUSB.sys è PPO.

Code di I/O nei driver USB UMDF

Per un driver UMDF che supporta la sospensione selettiva, se il driver UMDF possiede i criteri di alimentazione per il dispositivo determina il tipo di code di I/O che può usare. I driver UMDF che supportano la sospensione selettiva e sono ppO possono usare code gestite o non gestite dall'alimentazione. I driver USB UMDF che supportano la sospensione selettiva, ma non lo sono, non devono usare code di I/O gestite dall'alimentazione.

Se arriva una richiesta di I/O per una coda gestita dall'alimentazione mentre il dispositivo è sospeso, il framework non presenta la richiesta a meno che il driver non sia PPO, come illustrato nell'immagine nella sospensione selettiva nei driver USB. Se il driver UMDF non è PPO per il dispositivo, il framework non può accendere il dispositivo per suo conto. Di conseguenza, la richiesta rimane bloccata nella coda gestita dall'alimentazione. La richiesta non raggiunge mai WinUSB, quindi WinUSB non può accendere il dispositivo. Di conseguenza, lo stack di dispositivi può bloccarsi.

Se la coda non è gestita dall'alimentazione, il framework presenta richieste di I/O al driver UMDF anche quando il dispositivo è spento. Il driver UMDF formatta la richiesta e la inoltra allo stack di dispositivi alla destinazione di I/O predefinita nel modo consueto. Il codice speciale non è obbligatorio. Quando la richiesta raggiunge il protocollo PPO (WinUSB.sys), WinUSB.sys accende il dispositivo ed esegue l'operazione di I/O richiesta.

Il driver di esempio in %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\umdf\Fx2_Driver\IdleWake definisce la costante _NOT_POWER_POLICY_OWNER_ quando si compila la versione non PPO del driver. Quando il driver crea una coda per le richieste di lettura e scrittura, determina se creare una coda gestita dall'alimentazione controllando la costante.

Per creare la coda, il driver chiama il metodo CMyQueue::Initialize definito dal driver, che accetta i tre parametri seguenti:

  • DispatchType, valore di enumerazione WDF_IO_QUEUE_DISPATCH_TYPE che indica come la coda invia le richieste.
  • Valore predefinito, valore booleano che indica se la coda è una coda predefinita.
  • PowerManaged, valore booleano che indica se la coda è gestita dall'alimentazione.

Il frammento di codice seguente mostra la chiamata del driver al metodo CMyQueue::Initialize come parte della creazione della coda di lettura/scrittura:

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

CMyQueue::Initialize chiama quindi IWDFDevice::CreateIoQueue per creare la coda come segue:

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

Questa sequenza di codice genera una coda predefinita che invia le richieste in parallelo. Se il driver è il PPO la coda è gestita dall'alimentazione e se il driver non è il PPO, la coda non viene gestita dall'alimentazione.

Supporto della sospensione selettiva USB in un UMDF PPO

Per supportare la sospensione selettiva, un driver USB UMDF che rappresenta l'PPO per lo stack di dispositivi deve eseguire le operazioni seguenti:

  1. Richiedere la proprietà dei criteri di risparmio energia per lo stack di dispositivi, in genere nel metodo IDriverEntry::OnDeviceAdd nell'oggetto di callback del driver, come descritto in precedenza.
  2. Abilitare la sospensione selettiva chiamando il metodo IWDFDevice2::AssignS0IdleSettings nell'oggetto dispositivo framework.

Per abilitare la sospensione selettiva USB da un PPO

  • Chiamare IWDFDevice2::AssignS0IdleSettings, in genere dal metodo OnPrepareHardware nell'oggetto callback del dispositivo. Impostare i parametri su AssignS0IdleSettings come indicato di seguito:
    • Da IdleCaps a IdleUsbSelectiveSuspend.
    • DxState allo stato di sospensione del dispositivo a cui il framework esegue la transizione del dispositivo inattivo. Per la sospensione selettiva USB, specificare PowerDeviceMaximum, che indica che il framework deve usare il valore specificato dal driver del bus.
    • IdleTimeout al numero di millisecondi in cui il dispositivo deve essere inattiva prima che il framework lo passi a DxState.
    • UserControlOfIdleSettings su IdleAllowUserControl se il driver consente agli utenti di gestire le impostazioni di inattività o in caso contrario a IdleDoNotAllowUserControl.
    • Abilitato per WdfUseDefault per abilitare la sospensione selettiva per impostazione predefinita, ma per consentire all'impostazione dell'utente di eseguire l'override dell'impostazione predefinita.

L'esempio seguente illustra come il driver IdleWake_PPO chiama questo metodo nel metodo CMyDevice::SetPowerManagement interno:

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

Se l'hardware del dispositivo può generare un segnale di riattivazione, il driver UMDF può supportare anche la riattivazione del sistema da S1, S2 o S3. Per informazioni dettagliate, vedere Riattivazione del sistema in un driver UMDF.

Supporto della sospensione selettiva USB in un driver UMDF non PPO

Un driver di funzione UMDF che non è PPO può supportare la sospensione selettiva usando le funzionalità del driver WinUSB.sys sottostante. Il driver UMDF deve notificare a WinUSB che il dispositivo e il driver supportano la sospensione selettiva e devono abilitare la sospensione selettiva nel file INF o impostando i criteri di alimentazione sull'oggetto dispositivo di destinazione USB.

Se un driver di funzione UMDF abilita la sospensione selettiva, il driver di WinUSB.sys sottostante determina quando il dispositivo è inattiva. WinUSB avvia un contatore di timeout di inattività quando non sono in sospeso trasferimenti o quando gli unici trasferimenti in sospeso sono trasferimenti IN su un endpoint di interruzione o bulk. Per impostazione predefinita, il timeout di inattività è di 5 secondi, ma il driver UMDF può modificare questo valore predefinito.

Quando WinUSB.sys determina che il dispositivo è inattivo, invia una richiesta per sospendere il dispositivo nello stack di dispositivi in modalità kernel. Il driver del bus modifica lo stato dell'hardware in base alle esigenze. Se tutte le funzioni del dispositivo sulla porta sono state sospese, la porta entra nello stato di sospensione selettiva USB.

Se una richiesta di I/O arriva a WinUSB.sys mentre il dispositivo è sospeso, WinUSB.sys riprende l'operazione del dispositivo se il dispositivo deve essere acceso per gestire la richiesta. Il driver UMDF non richiede codice per riprendere il dispositivo mentre il sistema rimane in S0. Se l'hardware del dispositivo può generare un segnale di riattivazione, il driver UMDF può supportare anche la riattivazione del sistema da S1, S2 o S3. Per informazioni dettagliate, vedere Riattivazione del sistema in un driver UMDF.

Un driver UMDF che non è PPO può supportare la sospensione selettiva eseguendo i due passaggi seguenti:

  1. Notifica WinUSB.sys che il dispositivo e il driver supportano la sospensione selettiva.
  2. Abilitazione della sospensione selettiva USB.

Inoltre, il driver può facoltativamente:

  • Impostare un valore di timeout per il dispositivo.
  • Consentire all'utente di abilitare o disabilitare la sospensione selettiva.

Per un esempio di come implementare la sospensione selettiva USB in un driver di funzione USB UMDF che non è PPO, vedere l'esempio di Fx2_Driver in WDK. Questo esempio si trova in %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\Umdf\Fx2_Driver\ IdleWake_Non-PPO.

Per notificare a WinUSB il supporto per la sospensione selettiva

Per notificare WinUSB.sys che il dispositivo può supportare la sospensione selettiva USB, il dispositivo INF deve aggiungere il valore DeviceIdleEnabled alla chiave hardware del dispositivo e impostare il valore su 1. Nell'esempio seguente viene illustrato come l'esempio di Fx2_Driver aggiunge e imposta questo valore nel file WUDFOsrUsbFx2_IdleWakeNon-PPO.Inx:

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

Per abilitare la sospensione selettiva USB

Un driver USB UMDF può abilitare la sospensione selettiva USB in fase di esecuzione o durante l'installazione in INF.

  • Per abilitare il supporto in fase di esecuzione, il driver di funzione chiama IWDFUsbTargetDevice::SetPowerPolicy e imposta il parametro PolicyType su AUTO_SUSPEND e il parametro Value su TRUE o 1. Nell'esempio seguente viene illustrato come l'esempio di Fx2_Driver abilita la sospensione selettiva nel file DeviceNonPpo.cpp:

    BOOL AutoSuspend = TRUE;
    hr = m_pIUsbTargetDevice->SetPowerPolicy( AUTO_SUSPEND,
                                              sizeof(BOOL),
                                             (PVOID) &AutoSuspend );
    
  • Per abilitare il supporto durante l'installazione, INF include una direttiva AddReg che aggiunge il valore DefaultIdleState alla chiave hardware del dispositivo e imposta il valore su 1. Ad esempio:

    HKR,,"DefaultIdleState",0x00010001,1
    

Per impostare un valore di timeout inattiva

Per impostazione predefinita, WinUSB sospende il dispositivo dopo 5 secondi se non sono in sospeso i trasferimenti o se l'unico trasferimento in sospeso è IN trasferimenti in un endpoint di interruzione o bulk. Un driver UMDF può modificare questo valore di timeout inattiva in fase di installazione in INF o in fase di esecuzione.

  • Per impostare un timeout inattiva all'installazione, INF include una direttiva AddReg che aggiunge il valore DefaultIdleTimeout alla chiave hardware del dispositivo e imposta il valore sull'intervallo di timeout in millisecondi. L'esempio seguente imposta il timeout su 7 secondi:

    HKR,,"DefaultIdleTimeout",0x00010001,7000
    
  • Per impostare un timeout inattivo in fase di esecuzione, il driver chiama IWDFUsbTargetDevice::SetPowerPolicy con PolicyType impostato su SUSPEND_DELAY e Valore sul valore di timeout inattivo, in millisecondi. Nell'esempio seguente dal file Device.cpp, l'esempio di Fx2_Driver imposta il timeout su 10 secondi:

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

Per fornire il controllo utente della sospensione selettiva USB**

I driver USB UMDF che usano il supporto di sospensione selettiva WinUSB possono facoltativamente consentire all'utente di abilitare o disabilitare la sospensione selettiva. A tale scopo, includere una direttiva AddReg in INF che aggiunge il valore UserSetDeviceIdleEnabled alla chiave hardware del dispositivo e imposta il valore su 1. Di seguito viene illustrata la stringa da usare per la direttiva AddReg:

HKR,,"UserSetDeviceIdleEnabled",0x00010001,1

Se UserSetDeviceIdleEnabled è impostato, la finestra di dialogo Proprietà del dispositivo include una scheda Power Management che consente all'utente di abilitare o disabilitare la sospensione selettiva USB.

Riattivazione del sistema in un driver UMDF

In un driver UMDF il supporto per la riattivazione del sistema è indipendente dal supporto per la sospensione selettiva. Un driver USB UMDF può supportare sia la riattivazione del sistema che la sospensione selettiva, né la riattivazione selettiva del sistema o la sospensione selettiva. Un dispositivo che supporta la riattivazione del sistema può riattivare il sistema da uno stato di sospensione (S1, S2 o S3).

Un driver USB PPO UMDF può supportare la riattivazione del sistema fornendo informazioni di riattivazione per l'oggetto driver del framework. Quando un evento esterno attiva la riattivazione del sistema, il framework restituisce il dispositivo allo stato funzionante.

Un driver USB non PPO può usare il supporto di riattivazione del sistema che il driver WinUSB.sys implementa.

Per supportare la riattivazione del sistema in un driver USB UMDF che è il PPO**

Chiamare il metodo IWDFDevice2::AssignSxWakeSettings nell'oggetto dispositivo del framework con i parametri seguenti:

  • DxState allo stato di alimentazione a cui passa il dispositivo quando il sistema entra in uno stato Sx riattivabile. Per i dispositivi USB, specificare PowerDeviceMaximum per usare il valore specificato dal driver del bus.
  • UserControlOfWakeSettings a WakeAllowUserControl se il driver consente agli utenti di gestire le impostazioni di riattivazione o in caso contrario di WakeDoNotAllowUserControl.
  • Abilitato per WdfUseDefault per abilitare la riattivazione per impostazione predefinita, ma per consentire all'impostazione dell'utente di eseguire l'override del valore predefinito.

Nell'esempio seguente viene illustrato come il driver IdleWake_PPO chiama questo metodo nel relativo metodo CMyDevice interno::SetPowerManagement :

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

Per abilitare la riattivazione del sistema tramite WinUSB in un driver non PPO**

Per abilitare la riattivazione del sistema tramite WinUSB, l'INF del driver aggiunge il valore del Registro di sistema SystemWakeEnabled alla chiave hardware del dispositivo e lo imposta su 1. L'esempio IdleWake_Non-PPO abilita la riattivazione del sistema come indicato di seguito:

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

Impostando questo valore, il driver abilita la riattivazione del sistema e consente all'utente di controllare la capacità del dispositivo di riattivare il sistema. In Gestione dispositivi, la pagina delle proprietà delle impostazioni di risparmio energia per il dispositivo include una casella di controllo con cui l'utente può abilitare o disabilitare la riattivazione del sistema.