Partilhar via


Suspensão seletiva em controladores UMDF USB

Este tópico descreve como os drivers de função UMDF suportam suspensão seletiva USB.

APIs importantes

Os controladores de função UMDF podem suportar suspensão seletiva USB de duas maneiras:

  • Ao assumir o controlo da política de energia e gerir o dispositivo em modo de inatividade para desligar e retomar.
  • Confiando no driver WinUSB.sys, fornecido pela Microsoft, para gerenciar a suspensão seletiva. WinUSB.sys é instalado como parte da pilha de dispositivos do 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 requerem apenas pequenas quantidades de código. O exemplo IdleWake fornecido no WDK mostra como oferecer 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 controladores UMDF que suportam suspensão seletiva devem seguir estas diretrizes:

  • O driver UMDF pode reivindicar o controlo da política de potência para a pilha de dispositivos, mas não é necessário que o faça. Por padrão, o driver subjacente WinUSB.sys controla a política de energia.
  • Um driver UMDF que suporta suspensão seletiva e atua como o PPO pode usar filas geridas por energia ou filas que não são geridas por energia. Um driver UMDF que ofereça suporte à suspensão seletiva, mas não seja o PPO, não deve usar filas gerenciadas por energia.

Política de propriedade de energia em drivers UMDF USB

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 no WinUSB.sys.

Para assumir a propriedade da política de energia num driver USB UMDF

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

    FxDeviceInit->SetPowerPolicyOwnership(TRUE);
    
  2. Desative a propriedade da política de energia no WinUSB. No arquivo INF do driver, inclua uma diretiva AddReg que defina 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 suportam suspensão seletiva e são criados com versões WDF anteriores à 1.9 não devem assumir a propriedade da política de energia. Com essas versões anteriores do WDF, a suspensão seletiva USB funciona corretamente somente se WinUSB.sys for o PPO.

Filas de E/S em drivers USB UMDF

Para um driver UMDF que oferece suporte à suspensão seletiva, se o driver UMDF possui política de energia para seu dispositivo determina o tipo de filas de E/S que ele pode usar. Os drivers UMDF que suportam suspensão seletiva e são PPOs podem usar filas que são gerenciadas por energia ou não gerenciadas por energia. Os drivers USB UMDF que suportam 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 de gerenciamento de energia. A solicitação nunca chega ao WinUSB, portanto, o WinUSB não pode ligar o dispositivo. Consequentemente, a pilha de dispositivos pode parar.

Se a fila não for gerenciada pela energia, a estrutura apresentará solicitações de E/S ao driver UMDF mesmo quando o dispositivo estiver desligado. O driver UMDF formata a solicitação e a encaminha pela pilha de dispositivos para o destino de E/S padrão da maneira usual. Código especial não é necessário. Quando a solicitação chega ao PPO (WinUSB.sys), WinUSB.sys liga 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_ ao compilar 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 despacha solicitações.
  • Padrão, um booleano que indica se a fila é uma fila padrão.
  • PowerManaged, um booleano que indica se a fila é gerenciada por energia.

O trecho 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 despacha solicitações em paralelo. Se o driver for o PPO, a fila será gerenciada pela energia e, se o driver não for o PPO, a fila não será gerenciada pela energia.

Suporte à suspensão seletiva USB em um PPO UMDF

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

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

Para ativar a suspensão seletiva USB a partir de um PPO

  • Chame IWDFDevice2::AssignS0IdleSettings, normalmente do método OnPrepareHardware no objeto de retorno de chamada do dispositivo. Defina os parâmetros para AssignS0IdleSettings da seguinte forma:
    • IdleCaps para IdleUsbSelectiveSuspend.
    • DxState para o estado de suspensão ao qual a estrutura transfere o dispositivo quando este está ocioso. Para suspensão seletiva USB, especifique PowerDeviceMaximum, que indica que o framework 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 transfira para DxState.
    • UserControlOfIdleSettings para IdleAllowUserControl se o driver permitir que os utilizadores gerenciem as definições de inatividade, 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 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 pode gerar um sinal de ativação, o driver UMDF pode também suportar a ativação do sistema a partir dos estados S1, S2 ou S3. Para obter detalhes, consulte System Wake in a UMDF Driver.

Suporte para suspensão seletiva USB em um driver UMDF não-PPO

Um driver de função UMDF que não é o PPO pode suportar 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 suportam 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 ativar a suspensão seletiva, o driver subjacente WinUSB.sys determina 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 de inatividade é 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 do modo kernel. O motorista do autocarro altera o estado do hardware conforme apropriado. Se todas as funções do dispositivo na porta tiverem sido suspensas, a porta entra no estado de suspensão seletiva USB.

Se uma solicitação de E/S chegar ao 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 requer nenhum código para retomar o dispositivo enquanto o sistema permanece em S0. Se o hardware do dispositivo consegue gerar um sinal de despertar, o driver UMDF também pode suportar ativar o sistema a partir dos estados S1, S2 ou S3. Para obter detalhes, consulte System Wake in a UMDF Driver.

Um driver UMDF que não é o PPO pode suportar suspensão seletiva executando as seguintes duas etapas:

  1. Notificando WinUSB.sys que o dispositivo e o driver suportam suspensão seletiva.
  2. Ativando a suspensão seletiva USB.

Além disso, o condutor 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 USB num driver UMDF de função USB que não é o PPO, consulte o exemplo 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 notificáWinUSB.sys de que o dispositivo pode suportar suspensão seletiva 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 ativar a suspensão seletiva USB

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

  • Para habilitar o suporte em tempo de execução, 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 numa endpoint de interrupção ou em massa. Um driver UMDF pode alterar esse valor de tempo limite ocioso na instalação no INF ou no tempo de execução.

  • 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 para o intervalo de tempo limite em milissegundos. O exemplo a seguir define o tempo limite para 7 segundos:

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

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

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

Os drivers USB UMDF que usam o suporte de suspensão seletiva 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. A seguir mostra a cadeia de caracteres a ser usada para a diretiva AddReg:

HKR,,"UserSetDeviceIdleEnabled",0x00010001,1

Se UserSetDeviceIdleEnabled estiver definida, 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 USB.

Despertar do sistema em um driver UMDF

Em um driver UMDF, o suporte para despertar do sistema é independente do suporte para suspensão seletiva. Um driver USB UMDF pode suportar tanto o acordar do sistema quanto a suspensão seletiva, nem o acordar do sistema nem a suspensão seletiva, ou apenas o acordar do sistema ou a suspensão seletiva. Um dispositivo que suporta a ativação do sistema pode despertar o sistema de um estado de suspensão (S1, S2 ou S3).

Um driver UMDF USB PPO pode suportar a ativação do sistema fornecendo informações de ativação para o objeto de driver da estrutura. Quando um evento externo aciona a ativação do sistema, o framework retorna o dispositivo para o estado operacional.

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

Para suportar a ativação do sistema num driver UMDF USB 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 transita quando o sistema entra num estado Sx despertável. Para dispositivos USB, especifique PowerDeviceMaximum para utilizar o valor que o driver de barramento especificou.
  • UserControlOfWakeSettings para WakeAllowUserControl se o driver permitir que os utilizadores gerenciem as configurações de despertar ou caso contrário, para WakeDoNotAllowUserControl.
  • Definido como WdfUseDefault para ativar a funcionalidade de despertar por padrão, permitindo que a configuração do utilizador prevaleça sobre o padrão.

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

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

Para ativar o despertar do sistema com o WinUSB em um driver não-PPO**

Para habilitar a ativação do sistema através do WinUSB, o INF do driver adiciona o valor do registo "SystemWakeEnabled" à chave de hardware do dispositivo e defini-lo como 1. A amostra IdleWake_Non-PPO permite o despertar do sistema da seguinte maneira:

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

Ao definir esse valor, o driver permite o despertar do sistema e permite que o usuário controle a capacidade do dispositivo de despertar o sistema. No Gestor de Dispositivos, a página de propriedades das definições de gestão de energia para o dispositivo inclui uma caixa de seleção com a qual o utilizador pode ativar ou desativar o acordar do sistema.