Compartir a través de


Suspensión selectiva en controladores UMDF USB

En este tema se describe cómo los controladores de función UMDF admiten la suspensión selectiva USB.

API importantes

Los controladores de función UMDF pueden admitir la suspensión selectiva usb de dos maneras:

  • Al reclamar la propiedad de la directiva de energía y controlar el apagado y reanudación del dispositivo inactivo.
  • Al confiar en el controlador de WinUSB.sys, que Proporciona Microsoft, para controlar la suspensión selectiva. WinUSB.sys se instala como parte de la pila de dispositivos en modo kernel durante la instalación del controlador USB UMDF. WinUSB.sys implementa los mecanismos subyacentes para suspender y reanudar la operación del dispositivo USB.

Ambos enfoques solo requieren pequeñas cantidades de código. El ejemplo IdleWake que se proporciona en el WDK muestra cómo admitir la suspensión selectiva en un controlador USB UMDF. Puede encontrar este ejemplo en %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\ UMDF\Fx2_Driver\IdleWake. La carpeta contiene las versiones PPO y no PPO del ejemplo.

Los controladores umdf que admiten la suspensión selectiva deben seguir estas directrices:

  • El controlador UMDF puede reclamar la propiedad de la directiva de energía para su pila de dispositivos, pero no es necesario hacerlo. De forma predeterminada, el controlador de WinUSB.sys subyacente posee la directiva de energía.
  • Un controlador UMDF que admite la suspensión selectiva y es el PPO puede usar colas administradas por energía o colas que no están administradas por energía. Un controlador UMDF que admita la suspensión selectiva, pero no es el PPO, no debe usar colas administradas por energía.

Propiedad de la directiva de alimentación en controladores USB de UMDF

De forma predeterminada, WinUSB.sys es el PPO para una pila de dispositivos que contiene un controlador USB UMDF. A partir de WDF 1.9, los controladores USB basados en UMDF pueden reclamar la propiedad de la directiva de energía. Dado que solo un controlador de cada pila de dispositivos puede ser el PPO, un controlador USB UMDF que sea el PPO debe deshabilitar explícitamente la propiedad de la directiva de energía en WinUSB.sys.

Para reclamar la propiedad de la directiva de energía en un controlador USB UMDF

  1. Llame a IWDFDeviceInitialize::SetPowerPolicyOwnership y pase TRUE, normalmente desde el método IDriverEntry::OnDeviceAdd en el objeto de devolución de llamada del controlador. Por ejemplo:

    FxDeviceInit->SetPowerPolicyOwnership(TRUE);
    
  2. Deshabilite la propiedad de la directiva de energía en WinUSB. En el archivo INF del controlador, incluya una directiva AddReg que establezca el valor WinUsbPowerPolicyOwnershipDisabled en el Registro en un valor distinto de cero. La directiva AddReg debe aparecer en una sección DDInstall.HW. Por ejemplo:

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

Los controladores USB UMDF que admiten la suspensión selectiva y se compilan con versiones de WDF anteriores a la 1.9 no deben reclamar la propiedad de la directiva de energía. Con estas versiones anteriores de WDF, la suspensión selectiva usb funciona correctamente solo si WinUSB.sys es la PPO.

Colas de E/S en controladores USB de UMDF

En el caso de un controlador UMDF que admita la suspensión selectiva, si el controlador UMDF posee la directiva de energía para su dispositivo determina el tipo de colas de E/S que puede usar. Los controladores UMDF que admiten la suspensión selectiva y son PPO pueden usar colas administradas por energía o no administradas por energía. Los controladores USB UMDF que admiten la suspensión selectiva, pero no son la PPO, no deben usar ninguna cola de E/S administrada por energía.

Si llega una solicitud de E/S para una cola administrada por energía mientras el dispositivo está suspendido, el marco no presenta la solicitud a menos que el controlador sea PPO, como se muestra en la imagen en la suspensión selectiva en controladores USB. Si el controlador UMDF no es el PPO para el dispositivo, el marco no puede encender el dispositivo en su nombre. Como resultado, la solicitud permanece bloqueada en la cola administrada por energía. La solicitud nunca llega a WinUSB, por lo que WinUSB no puede encender el dispositivo. Por lo tanto, la pila del dispositivo puede detenerse.

Si la cola no está administrada por energía, el marco presenta solicitudes de E/S al controlador UMDF incluso cuando el dispositivo está apagado. El controlador UMDF da formato a la solicitud y lo reenvía a la pila de dispositivos al destino de E/S predeterminado de la manera habitual. No se requiere código especial. Cuando la solicitud llega al PPO (WinUSB.sys), WinUSB.sys activa el dispositivo y realiza la operación de E/S necesaria.

El controlador de ejemplo de %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\umdf\Fx2_Driver\IdleWake define la constante _NOT_POWER_POLICY_OWNER_ al compilar la versión que no es PPO del controlador. Cuando el controlador crea una cola para las solicitudes de lectura y escritura, determina si se debe crear una cola administrada por energía comprobando la constante.

Para crear la cola, el controlador llama al método CMyQueue::Initialize definido por el controlador, que toma los tres parámetros siguientes:

  • DispatchType, un valor de enumeración WDF_IO_QUEUE_DISPATCH_TYPE que indica cómo envía la cola las solicitudes.
  • Valor predeterminado, un valor booleano que indica si la cola es una cola predeterminada.
  • PowerManaged, un valor booleano que indica si la cola está administrada por energía.

En el fragmento de código siguiente se muestra la llamada del controlador al método CMyQueue::Initialize como parte de la creación de la cola de lectura y escritura:

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

CMyQueue::Initialize llama a IWDFDevice::CreateIoQueue para crear la cola de la siguiente manera:

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

Esta secuencia de código da como resultado una cola predeterminada que envía solicitudes en paralelo. Si el controlador es el PPO, se administra la energía de la cola y, si el controlador no es el PPO, la cola no se administra con energía.

Compatibilidad con la suspensión selectiva usb en un PPO de UMDF

Para admitir la suspensión selectiva, un controlador USB UMDF que sea el PPO para su pila de dispositivos debe hacer lo siguiente:

  1. Reclamar la propiedad de la directiva de energía para la pila de dispositivos, normalmente en el método IDriverEntry::OnDeviceAdd en su objeto de devolución de llamada del controlador, como se ha descrito anteriormente.
  2. Habilite la suspensión selectiva llamando al método IWDFDevice2::AssignS0IdleSettings en el objeto de dispositivo de marco.

Para habilitar la suspensión selectiva usb de un PPO

  • Llame a IWDFDevice2::AssignS0IdleSettings, normalmente desde el método OnPrepareHardware en el objeto de devolución de llamada del dispositivo. Establezca los parámetros en AssignS0IdleSettings de la siguiente manera:
    • IdleCaps a IdleUsbSelectiveSuspend.
    • DxState al estado de suspensión del dispositivo al que el marco realiza la transición del dispositivo inactivo. Para la suspensión selectiva usb, especifique PowerDeviceMaximum, que indica que el marco debe usar el valor especificado por el controlador de bus.
    • IdleTimeout en el número de milisegundos que el dispositivo debe estar inactivo antes de que el marco lo pase a DxState.
    • UserControlOfIdleSettings a IdleAllowUserControl si el controlador permite a los usuarios administrar la configuración inactiva o, de lo contrario, a IdleDoNotAllowUserControl.
    • Se habilitóen WdfUseDefault para habilitar la suspensión selectiva de forma predeterminada, pero para permitir que la configuración del usuario invalide el valor predeterminado.

En el ejemplo siguiente se muestra cómo el controlador de IdleWake_PPO llama a este método en su método CMyDevice::SetPowerManagement interno:

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

Si el hardware del dispositivo puede generar una señal de reactivación, el controlador UMDF también puede admitir la reactivación del sistema desde S1, S2 o S3. Para obtener más información, consulte Reactivación del sistema en un controlador UMDF.

Compatibilidad con la suspensión selectiva USB en un controlador UMDF no PPO

Un controlador de funciones UMDF que no sea el PPO puede admitir la suspensión selectiva mediante las características del controlador de WinUSB.sys subyacente. El controlador UMDF debe notificar a WinUSB que el dispositivo y el controlador admiten la suspensión selectiva y deben habilitar la suspensión selectiva en el archivo INF o estableciendo la directiva de alimentación en el objeto de dispositivo de destino USB.

Si un controlador de función UMDF habilita la suspensión selectiva, el controlador de WinUSB.sys subyacente determina cuándo el dispositivo está inactivo. WinUSB inicia un contador de tiempo de espera de inactividad cuando no hay transferencias pendientes o cuando las únicas transferencias pendientes son transferencias IN en un punto de conexión de interrupción o masivo. De forma predeterminada, el tiempo de espera de inactividad es de 5 segundos, pero el controlador UMDF puede cambiar este valor predeterminado.

Cuando WinUSB.sys determina que el dispositivo está inactivo, envía una solicitud para suspender el dispositivo en la pila de dispositivos en modo kernel. El controlador de bus cambia el estado del hardware según corresponda. Si se han suspendido todas las funciones del dispositivo en el puerto, el puerto entra en el estado de suspensión selectiva USB.

Si una solicitud de E/S llega a WinUSB.sys mientras se suspende el dispositivo, WinUSB.sys reanuda la operación del dispositivo si el dispositivo debe estar encendido para atender la solicitud. El controlador UMDF no requiere ningún código para reanudar el dispositivo mientras el sistema permanece en S0. Si el hardware del dispositivo puede generar una señal de reactivación, el controlador UMDF también puede admitir la reactivación del sistema desde S1, S2 o S3. Para obtener más información, consulte Reactivación del sistema en un controlador UMDF.

Un controlador UMDF que no sea el PPO puede admitir la suspensión selectiva siguiendo estos dos pasos:

  1. Notificar a WinUSB.sys que el dispositivo y el controlador admiten la suspensión selectiva.
  2. Habilitación de la suspensión selectiva usb.

Además, el controlador puede:

  • Establezca un valor de tiempo de espera para el dispositivo.
  • Permitir que el usuario habilite o deshabilite la suspensión selectiva.

Para obtener un ejemplo de cómo implementar la suspensión selectiva USB usb en un controlador de función USB UMDF que no es el PPO, consulte el ejemplo de Fx2_Driver en el WDK. Este ejemplo se encuentra en %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\Umdf\Fx2_Driver\ IdleWake_Non-PPO.

Para notificar a WinUSB el soporte técnico de suspensión selectiva

Para notificar a WinUSB.sys que el dispositivo puede admitir la suspensión selectiva usb, el inf del dispositivo debe agregar el valor DeviceIdleEnabled a la clave de hardware del dispositivo y establecer el valor en 1. En el ejemplo siguiente se muestra cómo agrega el ejemplo de Fx2_Driver y establece este valor en el archivo WUDFOsrUsbFx2_IdleWakeNon-PPO.Inx:

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

Para habilitar la suspensión selectiva de USB

Un controlador USB UMDF puede habilitar la suspensión selectiva usb en tiempo de ejecución o durante la instalación en INF.

  • Para habilitar la compatibilidad en tiempo de ejecución, el controlador de función llama a IWDFUsbTargetDevice::SetPowerPolicy y establece el parámetro PolicyType en AUTO_SUSPEND y el parámetro Value en TRUE o 1. En el ejemplo siguiente se muestra cómo el ejemplo de Fx2_Driver habilita la suspensión selectiva en el archivo DeviceNonPpo.cpp:

    BOOL AutoSuspend = TRUE;
    hr = m_pIUsbTargetDevice->SetPowerPolicy( AUTO_SUSPEND,
                                              sizeof(BOOL),
                                             (PVOID) &AutoSuspend );
    
  • Para habilitar la compatibilidad durante la instalación, INF incluye una directiva AddReg que agrega el valor DefaultIdleState a la clave de hardware del dispositivo y establece el valor en 1. Por ejemplo:

    HKR,,"DefaultIdleState",0x00010001,1
    

Para establecer un valor de tiempo de espera de inactividad

De forma predeterminada, WinUSB suspende el dispositivo después de 5 segundos si no hay transferencias pendientes o si las únicas transferencias pendientes son transferencias IN en un punto de conexión de interrupción o masivo. Un controlador UMDF puede cambiar este valor de tiempo de espera de inactividad en la instalación en INF o en tiempo de ejecución.

  • Para establecer un tiempo de espera de inactividad en la instalación, INF incluye una directiva AddReg que agrega el valor DefaultIdleTimeout a la clave de hardware del dispositivo y establece el valor en el intervalo de tiempo de espera en milisegundos. En el ejemplo siguiente se establece el tiempo de espera en 7 segundos:

    HKR,,"DefaultIdleTimeout",0x00010001,7000
    
  • Para establecer un tiempo de espera de inactividad en tiempo de ejecución, el controlador llama a IWDFUsbTargetDevice::SetPowerPolicy con PolicyType establecido en SUSPEND_DELAY y Value al valor de tiempo de espera de inactividad, en milisegundos. En el ejemplo siguiente del archivo Device.cpp, el ejemplo de Fx2_Driver establece el tiempo de espera en 10 segundos:

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

Para proporcionar el control de usuario de la suspensión selectiva usb**

Opcionalmente, los controladores USB UMDF que usan compatibilidad con suspensión selectiva de WinUSB pueden permitir que el usuario habilite o deshabilite la suspensión selectiva. Para ello, incluya una directiva AddReg en el INF que agregue el valor UserSetDeviceIdleEnabled a la clave de hardware del dispositivo y establezca el valor en 1. A continuación se muestra la cadena que se va a usar para la directiva AddReg:

HKR,,"UserSetDeviceIdleEnabled",0x00010001,1

Si se establece UserSetDeviceIdleEnabled, el cuadro de diálogo Propiedades del dispositivo incluye una pestaña Administración de energía que permite al usuario habilitar o deshabilitar la suspensión selectiva de USB.

Reactivación del sistema en un controlador UMDF

En un controlador UMDF, la compatibilidad con la reactivación del sistema es independiente de la compatibilidad con la suspensión selectiva. Un controlador USB UMDF puede admitir la reactivación del sistema y la suspensión selectiva, ni la reactivación del sistema ni la suspensión selectiva, ni la reactivación del sistema o la suspensión selectiva. Un dispositivo compatible con la reactivación del sistema puede reactivar el sistema desde un estado de suspensión (S1, S2 o S3).

Un controlador PPO USB UMDF puede admitir la reactivación del sistema proporcionando información de reactivación para el objeto de controlador del marco. Cuando un evento externo desencadena la reactivación del sistema, el marco devuelve el dispositivo al estado de trabajo.

Un controlador USB que no es PPO puede usar la compatibilidad de reactivación del sistema que implementa el controlador WinUSB.sys.

Para admitir la reactivación del sistema en un controlador USB UMDF que es el PPO**

Llame al método IWDFDevice2::AssignSxWakeSettings en el objeto de dispositivo del marco con los parámetros siguientes:

  • DxState al estado de alimentación al que pasa el dispositivo cuando el sistema entra en un estado Sx reactivable. En el caso de los dispositivos USB, especifique PowerDeviceMaximum para usar el valor especificado por el controlador de bus.
  • UserControlOfWakeSettings a WakeAllowUserControl si el controlador permite a los usuarios administrar la configuración de reactivación o, de lo contrario, a WakeDoNotAllowUserControl.
  • Habilitado para WdfUseDefault para habilitar la reactivación de forma predeterminada, pero para permitir que la configuración del usuario invalide el valor predeterminado.

En el ejemplo siguiente se muestra cómo el controlador de IdleWake_PPO llama a este método en su método interno CMyDevice::SetPowerManagement :

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

Para habilitar la reactivación del sistema a través de WinUSB en un controlador que no sea PPO**

Para habilitar la reactivación del sistema a través de WinUSB, el INF del controlador agrega el valor del Registro SystemWakeEnabled a la clave de hardware del dispositivo y lo establece en 1. El ejemplo IdleWake_Non-PPO habilita la reactivación del sistema de la siguiente manera:

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

Al establecer este valor, el controlador habilita la reactivación del sistema y permite al usuario controlar la capacidad del dispositivo de reactivar el sistema. En Administrador de dispositivos, la página de propiedades de configuración de administración de energía del dispositivo incluye una casilla con la que el usuario puede habilitar o deshabilitar la reactivación del sistema.