Compartilhar via


Suspensão seletiva em drivers UMDF USB

Este tópico descreve como os drivers de função UMDF dão suporte à suspensão seletiva usb.

APIs importantes

Os drivers de função UMDF podem dar suporte à suspensão seletiva de USB de duas maneiras:

  • Ao reivindicar a propriedade da política de energia e lidar com a ociosidade do dispositivo, desligue e retome.
  • Ao contar com o driver de WinUSB.sys, fornecido pela Microsoft, para lidar com a suspensão seletiva. WinUSB.sys é instalado como parte da pilha de dispositivos no modo kernel durante a instalação do driver USB UMDF. WinUSB.sys implementa os mecanismos subjacentes para suspender e retomar a operação do dispositivo USB.

Ambas as abordagens exigem apenas pequenas quantidades de código. O exemplo IdleWake fornecido no WDK mostra como dar suporte à suspensão seletiva em um driver USB UMDF. Você pode encontrar este exemplo em %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\ UMDF\Fx2_Driver\IdleWake. A pasta contém versões PPO e não PPO do exemplo.

Os drivers UMDF que dão suporte à suspensão seletiva devem seguir estas diretrizes:

  • O driver UMDF pode reivindicar a propriedade da política de energia para sua pilha de dispositivos, mas não é necessário fazê-lo. Por padrão, o driver de WinUSB.sys subjacente possui a política de energia.
  • Um driver UMDF que dá suporte à suspensão seletiva e é o PPO pode usar filas gerenciadas por energia ou filas que não são gerenciadas por energia. Um driver UMDF que dá suporte à suspensão seletiva, mas não é o PPO, não deve usar filas gerenciadas por energia.

Propriedade da política de energia em drivers USB UMDF

Por padrão, WinUSB.sys é o PPO para uma pilha de dispositivos que contém um driver USB UMDF. A partir do WDF 1.9, os drivers USB baseados em UMDF podem reivindicar a propriedade da política de energia. Como apenas um driver em cada pilha de dispositivos pode ser o PPO, um driver USB UMDF que é o PPO deve desabilitar explicitamente a propriedade da política de energia em WinUSB.sys.

Para reivindicar a propriedade da política de energia em um driver USB UMDF

  1. Chame IWDFDeviceInitialize::SetPowerPolicyOwnership e passe TRUE, normalmente do método IDriverEntry::OnDeviceAdd no objeto de retorno de chamada do driver. Por exemplo:

    FxDeviceInit->SetPowerPolicyOwnership(TRUE);
    
  2. Desabilite a propriedade da política de energia no WinUSB. No arquivo INF do driver, inclua uma diretiva AddReg que define o valor WinUsbPowerPolicyOwnershipDisabled no Registro como um valor diferente de zero. A diretiva AddReg deve aparecer em uma seção DDInstall.HW. Por exemplo:

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

Os drivers USB UMDF que dão suporte à suspensão seletiva e são criados com versões do WDF anteriores à 1.9 não devem reivindicar a propriedade da política de energia. Com essas versões anteriores do WDF, a suspensão seletiva por USB só funcionará corretamente se WinUSB.sys for o PPO.

Filas de E/S em drivers USB UMDF

Para um driver UMDF que dá suporte à suspensão seletiva, se o driver UMDF possui a política de energia para seu dispositivo determina o tipo de filas de E/S que ele pode usar. Os drivers UMDF que dão suporte à suspensão seletiva e são PPOs podem usar filas gerenciadas por energia ou não gerenciadas por energia. Drivers USB UMDF que dão suporte à suspensão seletiva, mas não são o PPO, não devem usar filas de E/S gerenciadas por energia.

Se uma solicitação de E/S chegar para uma fila gerenciada por energia enquanto o dispositivo estiver suspenso, a estrutura não apresentará a solicitação, a menos que o driver seja PPO, conforme mostrado na imagem na suspensão seletiva em drivers USB. Se o driver UMDF não for o PPO do dispositivo, a estrutura não poderá ligar o dispositivo em seu nome. Como resultado, a solicitação permanece presa na fila gerenciada por energia. A solicitação nunca atinge o WinUSB, portanto, o WinUSB não pode ligar o dispositivo. Consequentemente, a pilha de dispositivos pode parar.

Se a fila não for gerenciada por energia, a estrutura apresentará solicitações de E/S para o driver UMDF mesmo quando o dispositivo estiver desligado. O driver UMDF formata a solicitação e a encaminha para baixo na pilha do dispositivo para o destino de E/S padrão da maneira usual. Código especial não é necessário. Quando a solicitação atinge o PPO (WinUSB.sys), WinUSB.sys habilita o dispositivo e executa a operação de E/S necessária.

O driver de exemplo em %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\umdf\Fx2_Driver\IdleWake define a constante _NOT_POWER_POLICY_OWNER_ quando você cria a versão não PPO do driver. Quando o driver cria uma fila para solicitações de leitura e gravação, ele determina se deve criar uma fila gerenciada por energia verificando a constante.

Para criar a fila, o driver chama o método CMyQueue::Initialize definido pelo driver, que usa os três parâmetros a seguir:

  • DispatchType, um valor de enumeração WDF_IO_QUEUE_DISPATCH_TYPE que indica como a fila envia solicitações.
  • Padrão, um Boolean que indica se a fila é uma fila padrão.
  • PowerManaged, um booliano que indica se a fila é gerenciada por energia.

O snippet de código a seguir mostra a chamada do driver para o método CMyQueue::Initialize como parte da criação da fila de leitura/gravação:

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

CMyQueue::Initialize chama IWDFDevice::CreateIoQueue para criar a fila da seguinte maneira:

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

Essa sequência de código resulta em uma fila padrão que envia solicitações em paralelo. Se o driver for o PPO, a fila será gerenciada por energia e, se o driver não for o PPO, a fila não será gerenciada por energia.

Suporte à suspensão seletiva de USB em um PPO UMDF

Para dar suporte à suspensão seletiva, um driver USB UMDF que é o PPO para sua pilha de dispositivos deve fazer o seguinte:

  1. Requisite a propriedade da política de energia para a pilha de dispositivos, normalmente no método IDriverEntry::OnDeviceAdd em seu objeto de retorno de chamada de driver, conforme descrito anteriormente.
  2. Habilite a suspensão seletiva chamando o método IWDFDevice2::AssignS0IdleSettings no objeto do dispositivo de estrutura.

Para habilitar a suspensão seletiva de USB de um PPO

  • Chame IWDFDevice2::AssignS0IdleSettings, normalmente do método OnPrepareHardware no objeto de retorno de chamada do dispositivo. Defina os parâmetros como AssignS0IdleSettings da seguinte maneira:
    • IdleCaps para IdleUsbSelectiveSuspend.
    • DxState para o estado de suspensão do dispositivo para o qual a estrutura faz a transição do dispositivo ocioso. Para suspensão seletiva de USB, especifique PowerDeviceMaximum, que indica que a estrutura deve usar o valor especificado pelo driver de barramento.
    • IdleTimeout para o número de milissegundos que o dispositivo deve estar ocioso antes que a estrutura o faça a transição para DxState.
    • UserControlOfIdleSettings para IdleAllowUserControl se o driver permitir que os usuários gerenciem as configurações ociosas ou, caso contrário, para IdleDoNotAllowUserControl.
    • Habilitado para WdfUseDefault para habilitar a suspensão seletiva por padrão, mas para permitir que a configuração do usuário substitua o padrão.

O exemplo a seguir mostra como o driver de IdleWake_PPO chama esse método em seu método CMyDevice::SetPowerManagement interno:

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

Se o hardware do dispositivo puder gerar um sinal de ativação, o driver UMDF também poderá dar suporte à ativação do sistema de S1, S2 ou S3. Para obter detalhes, confira Ativação do sistema em um driver UMDF.

Suporte à suspensão seletiva de USB em um driver UMDF não PPO

Um driver de função UMDF que não é o PPO pode dar suporte à suspensão seletiva usando os recursos do driver de WinUSB.sys subjacente. O driver UMDF deve notificar o WinUSB de que o dispositivo e o driver dão suporte à suspensão seletiva e devem habilitar a suspensão seletiva no arquivo INF ou definindo a política de energia no objeto de dispositivo de destino USB.

Se um driver de função UMDF habilitar a suspensão seletiva, o driver de WinUSB.sys subjacente determinará quando o dispositivo está ocioso. O WinUSB inicia um contador de tempo limite ocioso quando nenhuma transferência está pendente ou quando as únicas transferências pendentes são transferências IN em um ponto de extremidade de interrupção ou em massa. Por padrão, o tempo limite ocioso é de 5 segundos, mas o driver UMDF pode alterar esse padrão.

Quando WinUSB.sys determina que o dispositivo está ocioso, ele envia uma solicitação para suspender o dispositivo na pilha de dispositivos no modo kernel. O motorista do ônibus altera o estado do hardware conforme apropriado. Se todas as funções de dispositivo na porta tiverem sido suspensas, a porta entrará no estado de suspensão seletiva usb.

Se uma solicitação de E/S chegar a WinUSB.sys enquanto o dispositivo estiver suspenso, WinUSB.sys retomará a operação do dispositivo se o dispositivo precisar ser ligado para atender à solicitação. O driver UMDF não exige nenhum código para retomar o dispositivo enquanto o sistema permanece em S0. Se o hardware do dispositivo puder gerar um sinal de ativação, o driver UMDF também poderá dar suporte à ativação do sistema de S1, S2 ou S3. Para obter detalhes, confira Ativação do sistema em um driver UMDF.

Um driver UMDF que não é o PPO pode dar suporte à suspensão seletiva seguindo as duas etapas a seguir:

  1. Notificar WinUSB.sys que o dispositivo e o driver dão suporte à suspensão seletiva.
  2. Habilitando a suspensão seletiva de USB.

Além disso, o driver pode opcionalmente:

  • Defina um valor de tempo limite para o dispositivo.
  • Permitir que o usuário habilite ou desabilite a suspensão seletiva.

Para obter um exemplo de como implementar a suspensão seletiva de USB em um driver de função USB UMDF que não é o PPO, consulte o exemplo de Fx2_Driver no WDK. Este exemplo está localizado em %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\Umdf\Fx2_Driver\ IdleWake_Non-PPO.

Para notificar o WinUSB sobre o suporte de suspensão seletiva

Para notificar WinUSB.sys que o dispositivo pode dar suporte à suspensão seletiva por USB, o INF do dispositivo deve adicionar o valor DeviceIdleEnabled à chave de hardware do dispositivo e definir o valor como 1. O exemplo a seguir mostra como o exemplo de Fx2_Driver adiciona e define esse valor no arquivo WUDFOsrUsbFx2_IdleWakeNon-PPO.Inx:

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

Para habilitar a suspensão seletiva de USB

Um driver USB UMDF pode habilitar a suspensão seletiva de USB em runtime ou durante a instalação no INF.

  • Para habilitar o suporte em runtime, o driver de função chama IWDFUsbTargetDevice::SetPowerPolicy e define o parâmetro PolicyType como AUTO_SUSPEND e o parâmetro Value como TRUE ou 1. O exemplo a seguir mostra como o exemplo de Fx2_Driver habilita a suspensão seletiva no arquivo DeviceNonPpo.cpp:

    BOOL AutoSuspend = TRUE;
    hr = m_pIUsbTargetDevice->SetPowerPolicy( AUTO_SUSPEND,
                                              sizeof(BOOL),
                                             (PVOID) &AutoSuspend );
    
  • Para habilitar o suporte durante a instalação, o INF inclui uma diretiva AddReg que adiciona o valor DefaultIdleState à chave de hardware do dispositivo e define o valor como 1. Por exemplo:

    HKR,,"DefaultIdleState",0x00010001,1
    

Para definir um valor de tempo limite ocioso

Por padrão, o WinUSB suspende o dispositivo após 5 segundos se nenhuma transferência estiver pendente ou se as únicas transferências pendentes forem transferências IN em um ponto de extremidade em massa ou interrupção. Um driver UMDF pode alterar esse valor de tempo limite ocioso na instalação no INF ou em runtime.

  • Para definir um tempo limite ocioso na instalação, o INF inclui uma diretiva AddReg que adiciona o valor DefaultIdleTimeout à chave de hardware do dispositivo e define o valor como o intervalo de tempo limite em milissegundos. O exemplo a seguir define o tempo limite como 7 segundos:

    HKR,,"DefaultIdleTimeout",0x00010001,7000
    
  • Para definir um tempo limite ocioso em runtime, o driver chama IWDFUsbTargetDevice::SetPowerPolicy com PolicyType definido como SUSPEND_DELAY e Value para o valor de tempo limite ocioso, em milissegundos. No exemplo a seguir do arquivo Device.cpp, o exemplo Fx2_Driver define o tempo limite como 10 segundos:

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

Para fornecer ao usuário o controle de suspensão seletiva usb**

Os drivers USB UMDF que usam o suporte de suspensão seletiva do WinUSB podem, opcionalmente, permitir que o usuário habilite ou desabilite a suspensão seletiva. Para fazer isso, inclua uma diretiva AddReg no INF que adiciona o valor UserSetDeviceIdleEnabled à chave de hardware do dispositivo e define o valor como 1. O seguinte mostra a cadeia de caracteres a ser usada para a diretiva AddReg:

HKR,,"UserSetDeviceIdleEnabled",0x00010001,1

Se UserSetDeviceIdleEnabled estiver definido, a caixa de diálogo Propriedades do dispositivo incluirá uma guia Gerenciamento de Energia que permite ao usuário habilitar ou desabilitar a suspensão seletiva de USB.

Ativação do sistema em um driver UMDF

Em um driver UMDF, o suporte para ativação do sistema é independente do suporte para suspensão seletiva. Um driver USB UMDF pode dar suporte à ativação do sistema e à suspensão seletiva, nem à ativação do sistema nem à suspensão seletiva ou à ativação do sistema ou à suspensão seletiva. Um dispositivo que dá suporte à ativação do sistema pode ativar o sistema de um estado de suspensão (S1, S2 ou S3).

Um driver PPO USB UMDF pode dar suporte à ativação do sistema fornecendo informações de ativação para o objeto de driver da estrutura. Quando um evento externo dispara a ativação do sistema, a estrutura retorna o dispositivo para o estado de trabalho.

Um driver não PPO USB pode usar o suporte de ativação do sistema que o driver de WinUSB.sys implementa.

Para dar suporte à ativação do sistema em um driver USB UMDF que é o PPO**

Chame o método IWDFDevice2::AssignSxWakeSettings no objeto de dispositivo da estrutura com os seguintes parâmetros:

  • DxState para o estado de energia para o qual o dispositivo faz a transição quando o sistema entra em um estado Sx de ativação. Para dispositivos USB, especifique PowerDeviceMaximum para usar o valor especificado pelo driver de barramento.
  • UserControlOfWakeSettings para WakeAllowUserControl se o driver permitir que os usuários gerenciem as configurações de ativação ou, caso contrário, para WakeDoNotAllowUserControl.
  • Habilitado para WdfUseDefault para habilitar a ativação por padrão, mas para permitir que a configuração do usuário substitua o padrão.

O exemplo a seguir mostra como o driver de IdleWake_PPO chama esse método em seu método CMyDevice::SetPowerManagement interno:

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

Para habilitar a ativação do sistema por meio do WinUSB em um driver não PPO**

Para habilitar a ativação do sistema por meio do WinUSB, o INF do driver adiciona o valor do registro SystemWakeEnabled à chave de hardware do dispositivo e o define como 1. O exemplo IdleWake_Non-PPO permite a ativação do sistema da seguinte maneira:

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

Ao definir esse valor, o driver habilita a ativação do sistema e permite que o usuário controle a capacidade do dispositivo de ativar o sistema. Em Gerenciador de Dispositivos, a página de propriedades de configurações de gerenciamento de energia do dispositivo inclui uma caixa de marcar com a qual o usuário pode habilitar ou desabilitar a ativação do sistema.