Partager via


Suspension sélective dans les pilotes USB UMDF

Cette rubrique décrit comment les pilotes de fonction UMDF prennent en charge la suspension sélective USB.

API importantes

Les pilotes de fonction UMDF peuvent prendre en charge la suspension sélective USB de deux façons :

  • En revendiquant la propriété de la stratégie d’alimentation et en gérant l’arrêt et la reprise des appareils inactifs.
  • En s’appuyant sur le pilote WinUSB.sys, que Microsoft fournit, pour gérer la suspension sélective. WinUSB.sys est installé dans le cadre de la pile de périphériques en mode noyau pendant l’installation du pilote USB UMDF. WinUSB.sys implémente les mécanismes sous-jacents pour suspendre et reprendre le fonctionnement du périphérique USB.

Les deux approches ne nécessitent que de petites quantités de code. L’exemple IdleWake fourni dans le WDK montre comment prendre en charge la suspension sélective dans un pilote USB UMDF. Vous trouverez cet exemple dans %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\ UMDF\Fx2_Driver\IdleWake. Le dossier contient à la fois les versions PPO et non PPO de l’exemple.

Les pilotes UMDF qui prennent en charge la suspension sélective doivent suivre ces instructions :

  • Le pilote UMDF peut revendiquer la propriété de la stratégie d’alimentation pour sa pile de périphériques, mais il n’est pas nécessaire de le faire. Par défaut, le pilote WinUSB.sys sous-jacent possède la stratégie d’alimentation.
  • Un pilote UMDF qui prend en charge la suspension sélective et qui est l’objet PPO peut utiliser des files d’attente gérées par l’alimentation ou des files d’attente qui ne sont pas gérées par l’alimentation. Un pilote UMDF qui prend en charge la suspension sélective mais qui n’est pas l’objet PPO ne doit pas utiliser de files d’attente gérées par l’alimentation.

Propriété de la stratégie d’alimentation dans les pilotes USB UMDF

Par défaut, WinUSB.sys est le PPO d’une pile de périphériques qui contient un pilote USB UMDF. À compter de WDF 1.9, les pilotes USB basés sur UMDF peuvent revendiquer la propriété de la stratégie d’alimentation. Étant donné qu’un seul pilote dans chaque pile de périphériques peut être le PPO, un pilote USB UMDF qui est le PPO doit désactiver explicitement la propriété de la stratégie d’alimentation dans WinUSB.sys.

Pour revendiquer la propriété de la stratégie d’alimentation dans un pilote USB UMDF

  1. Appelez IWDFDeviceInitialize ::SetPowerPolicyOwnership et passez TRUE, généralement à partir de la méthode IDriverEntry ::OnDeviceAdd sur l’objet de rappel du pilote. Par exemple :

    FxDeviceInit->SetPowerPolicyOwnership(TRUE);
    
  2. Désactivez la propriété de la stratégie d’alimentation dans WinUSB. Dans le fichier INF du pilote, incluez une directive AddReg qui définit la valeur WinUsbPowerPolicyOwnershipDisabled dans le Registre sur une valeur différente de zéro. La directive AddReg doit apparaître dans une section DDInstall.HW. Par exemple :

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

Les pilotes USB UMDF qui prennent en charge la suspension sélective et qui sont générés avec des versions WDF antérieures à la version 1.9 ne doivent pas revendiquer la propriété de la stratégie d’alimentation. Avec ces versions antérieures de WDF, la suspension sélective USB fonctionne correctement uniquement si WinUSB.sys est le PPO.

Files d’attente d’E/S dans les pilotes USB UMDF

Pour un pilote UMDF qui prend en charge la suspension sélective, si le pilote UMDF possède la stratégie d’alimentation pour son appareil, détermine le type de files d’attente d’E/S qu’il peut utiliser. Les pilotes UMDF qui prennent en charge la suspension sélective et qui sont des PO peuvent utiliser des files d’attente gérées par l’alimentation ou non gérées par l’alimentation. Les pilotes USB UMDF qui prennent en charge la suspension sélective, mais qui ne sont pas le PPO, ne doivent pas utiliser de files d’E/S gérées par l’alimentation.

Si une demande d’E/S arrive pour une file d’attente gérée par l’alimentation pendant la suspension de l’appareil, l’infrastructure ne présente pas la demande, sauf si le pilote est PPO, comme illustré dans l’image de la suspension sélective dans les pilotes USB. Si le pilote UMDF n’est pas le PPO de l’appareil, l’infrastructure ne peut pas mettre le périphérique sous tension en son nom. Par conséquent, la requête reste bloquée dans la file d’attente gérée par l’alimentation. La requête n’atteint jamais WinUSB, de sorte que WinUSB ne peut pas mettre l’appareil sous tension. Par conséquent, la pile de l’appareil peut se bloquer.

Si la file d’attente n’est pas gérée par l’alimentation, le framework présente les demandes d’E/S au pilote UMDF, même lorsque l’appareil est hors tension. Le pilote UMDF met en forme la demande et la transfère à la cible d’E/S par défaut de la manière habituelle. Un code spécial n’est pas requis. Lorsque la demande atteint le PPO (WinUSB.sys), WinUSB.sys allume l’appareil et effectue l’opération d’E/S requise.

L’exemple de pilote dans %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\umdf\Fx2_Driver\IdleWake définit la constante _NOT_POWER_POLICY_OWNER_ lorsque vous générez la version non PPO du pilote. Lorsque le pilote crée une file d’attente pour les demandes de lecture et d’écriture, il détermine s’il faut créer une file d’attente gérée par l’alimentation en vérifiant la constante.

Pour créer la file d’attente, le pilote appelle la méthode CMyQueue ::Initialize définie par le pilote, qui prend les trois paramètres suivants :

  • DispatchType, une valeur d’énumération WDF_IO_QUEUE_DISPATCH_TYPE qui indique comment la file d’attente distribue les demandes.
  • Valeur par défaut , booléen qui indique si la file d’attente est une file d’attente par défaut.
  • PowerManaged, booléen qui indique si la file d’attente est gérée par l’alimentation.

L’extrait de code suivant montre l’appel du pilote à la méthode CMyQueue ::Initialize dans le cadre de la création de la file d’attente en lecture-écriture :

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

CMyQueue ::Initialize appelle ensuite IWDFDevice ::CreateIoQueue pour créer la file d’attente comme suit :

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

Cette séquence de code génère une file d’attente par défaut qui distribue les demandes en parallèle. Si le pilote est le PPO, la file d’attente est gérée par l’alimentation, et si le pilote n’est pas le PPO, la file d’attente n’est pas gérée par l’alimentation.

Prise en charge de la suspension sélective USB dans un PPO UMDF

Pour prendre en charge la suspension sélective, un pilote USB UMDF qui est le PPO pour sa pile de périphériques doit effectuer les opérations suivantes :

  1. Revendication de la propriété de la stratégie d’alimentation pour la pile des appareils, généralement dans la méthode IDriverEntry ::OnDeviceAdd sur son objet de rappel de pilote, comme décrit précédemment.
  2. Activez la suspension sélective en appelant la méthode IWDFDevice2 ::AssignS0IdleSettings sur l’objet d’appareil du framework.

Pour activer la suspension sélective USB à partir d’un PPO

  • Appelez IWDFDevice2 ::AssignS0IdleSettings, généralement à partir de la méthode OnPrepareHardware sur l’objet de rappel d’appareil. Définissez les paramètres sur AssignS0IdleSettings comme suit :
    • IdleCaps àIdleUsbSelectiveSuspend.
    • DxState vers l’état de veille de l’appareil vers lequel le framework effectue la transition de l’appareil inactif. Pour la suspension sélective USB, spécifiez PowerDeviceMaximum, ce qui indique que l’infrastructure doit utiliser la valeur spécifiée par le pilote de bus.
    • IdleTimeout au nombre de millisecondes pendant lesquelles l’appareil doit être inactif avant que le framework le transfère vers DxState.
    • UserControlOfIdleSettings à IdleAllowUserControl si votre pilote permet aux utilisateurs de gérer les paramètres d’inactivité, ou bien à IdleDoNotAllowUserControl.
    • Activé sur WdfUseDefault pour activer la suspension sélective par défaut, mais pour autoriser le paramètre de l’utilisateur à remplacer la valeur par défaut.

L’exemple suivant montre comment le pilote IdleWake_PPO appelle cette méthode dans sa méthode CMyDevice ::SetPowerManagement interne :

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

Si le matériel de l’appareil peut générer un signal de sortie de veille, le pilote UMDF peut également prendre en charge la mise en éveil du système à partir de S1, S2 ou S3. Pour plus d’informations, consultez Éveil du système dans un pilote UMDF.

Prise en charge de la suspension sélective USB dans un pilote UMDF non PPO

Un pilote de fonction UMDF qui n’est pas l’objet PPO peut prendre en charge la suspension sélective à l’aide des fonctionnalités du pilote de WinUSB.sys sous-jacent. Le pilote UMDF doit informer WinUSB que le périphérique et le pilote prennent en charge la suspension sélective et doit activer la suspension sélective dans le fichier INF ou en définissant la stratégie d’alimentation sur l’objet périphérique cible USB.

Si un pilote de fonction UMDF active la suspension sélective, le pilote de WinUSB.sys sous-jacent détermine quand le périphérique est inactif. WinUSB démarre un compteur de délai d’attente inactif quand aucun transfert n’est en attente ou lorsque les seuls transferts en attente sont des transferts IN sur un point de terminaison d’interruption ou en bloc. Par défaut, le délai d’inactivité est de 5 secondes, mais le pilote UMDF peut modifier cette valeur par défaut.

Lorsque WinUSB.sys détermine que l’appareil est inactif, il envoie une demande de suspension de l’appareil dans la pile d’appareils en mode noyau. Le pilote de bus modifie l’état du matériel en fonction des besoins. Si toutes les fonctions de l’appareil sur le port ont été suspendues, le port passe à l’état de suspension sélective USB.

Si une demande d’E/S arrive à WinUSB.sys alors que l’appareil est suspendu, WinUSB.sys reprend le fonctionnement de l’appareil si l’appareil doit être mis sous tension pour traiter la demande. Le pilote UMDF ne nécessite aucun code pour reprendre l’appareil tant que le système reste dans S0. Si le matériel de l’appareil peut générer un signal de sortie de veille, le pilote UMDF peut également prendre en charge la mise en éveil du système à partir de S1, S2 ou S3. Pour plus d’informations, consultez Éveil du système dans un pilote UMDF.

Un pilote UMDF qui n’est pas le PPO peut prendre en charge la suspension sélective en effectuant les deux étapes suivantes :

  1. Notification WinUSB.sys que le périphérique et le pilote prennent en charge la suspension sélective.
  2. Activation de la suspension sélective USB.

En outre, le pilote peut éventuellement :

  • Définissez une valeur de délai d’attente pour l’appareil.
  • Autoriser l’utilisateur à activer ou désactiver la suspension sélective.

Pour obtenir un exemple d’implémentation de la suspension sélective USB dans un pilote de fonction USB UMDF qui n’est pas le PPO, consultez l’exemple Fx2_Driver dans le WDK. Cet exemple se trouve dans %WinDDK%\BuildNumber\Src\Usb\OsrUsbFx2\Umdf\Fx2_Driver\ IdleWake_Non-PPO.

Pour informer WinUSB de la prise en charge de la suspension sélective

Pour informer WinUSB.sys que l’appareil peut prendre en charge la suspension sélective USB, l’INF de l’appareil doit ajouter la valeur DeviceIdleEnabled à la clé matérielle de l’appareil et définir la valeur sur 1. L’exemple suivant montre comment l’exemple Fx2_Driver ajoute et définit cette valeur dans le fichier WUDFOsrUsbFx2_IdleWakeNon-PPO.Inx :

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

Pour activer la suspension sélective USB

Un pilote USB UMDF peut activer la suspension sélective USB au moment de l’exécution ou pendant l’installation dans l’INF.

  • Pour activer la prise en charge au moment de l’exécution, le pilote de fonction appelle IWDFUsbTargetDevice ::SetPowerPolicy et définit le paramètre PolicyType sur AUTO_SUSPEND et le paramètre Value sur TRUE ou 1. L’exemple suivant montre comment l’exemple Fx2_Driver active la suspension sélective dans le fichier DeviceNonPpo.cpp :

    BOOL AutoSuspend = TRUE;
    hr = m_pIUsbTargetDevice->SetPowerPolicy( AUTO_SUSPEND,
                                              sizeof(BOOL),
                                             (PVOID) &AutoSuspend );
    
  • Pour activer la prise en charge pendant l’installation, inf inclut une directive AddReg qui ajoute la valeur DefaultIdleState à la clé matérielle de l’appareil et définit la valeur sur 1. Par exemple :

    HKR,,"DefaultIdleState",0x00010001,1
    

Pour définir une valeur de délai d’inactivité

Par défaut, WinUSB suspend l’appareil après 5 secondes si aucun transfert n’est en attente ou si les seuls transferts en attente sont des transferts IN sur un point de terminaison d’interruption ou de bloc. Un pilote UMDF peut modifier cette valeur de délai d’inactivité au moment de l’installation dans le fichier INF ou au moment de l’exécution.

  • Pour définir un délai d’inactivité lors de l’installation, l’inf inclut une directive AddReg qui ajoute la valeur DefaultIdleTimeout à la clé matérielle de l’appareil et définit la valeur sur l’intervalle de délai d’attente en millisecondes. L’exemple suivant définit le délai d’attente sur 7 secondes :

    HKR,,"DefaultIdleTimeout",0x00010001,7000
    
  • Pour définir un délai d’inactivité au moment de l’exécution, le pilote appelle IWDFUsbTargetDevice ::SetPowerPolicy avec PolicyType défini sur SUSPEND_DELAY et Value sur la valeur de délai d’inactivité, en millisecondes. Dans l’exemple suivant du fichier Device.cpp, l’exemple Fx2_Driver définit le délai d’attente sur 10 secondes :

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

Pour fournir à l’utilisateur le contrôle de la suspension sélective USB**

Les pilotes USB UMDF qui utilisent la prise en charge de la suspension sélective WinUSB peuvent éventuellement permettre à l’utilisateur d’activer ou de désactiver la suspension sélective. Pour ce faire, incluez une directive AddReg dans l’INF qui ajoute la valeur UserSetDeviceIdleEnabled à la clé matérielle de l’appareil et définit la valeur sur 1. Voici la chaîne à utiliser pour la directive AddReg :

HKR,,"UserSetDeviceIdleEnabled",0x00010001,1

Si UserSetDeviceIdleEnabled est défini, la boîte de dialogue Propriétés de l’appareil inclut un onglet Gestion de l’alimentation qui permet à l’utilisateur d’activer ou de désactiver la suspension sélective USB.

Veille du système dans un pilote UMDF

Dans un pilote UMDF, la prise en charge de l’éveil du système est indépendante de la prise en charge de la suspension sélective. Un pilote USB UMDF peut prendre en charge à la fois l’éveil du système et la suspension sélective, ni l’éveil du système ni la suspension sélective, ni l’éveil du système ou la suspension sélective. Un appareil qui prend en charge la veille du système peut sortir le système d’un état de veille (S1, S2 ou S3).

Un pilote PPO USB UMDF peut prendre en charge l’éveil du système en fournissant des informations de mise en éveil pour l’objet pilote de l’infrastructure. Lorsqu’un événement externe déclenche la mise en éveil du système, l’infrastructure retourne l’appareil à l’état de fonctionnement.

Un pilote USB non-PPO peut utiliser la prise en charge de l’éveil du système que le pilote WinUSB.sys implémente.

Pour prendre en charge le réveil du système dans un pilote USB UMDF qui est le PPO**

Appelez la méthode IWDFDevice2 ::AssignSxWakeSettings sur l’objet d’appareil de l’infrastructure avec les paramètres suivants :

  • DxState à l’état d’alimentation vers lequel l’appareil passe lorsque le système entre dans un état Sx réactivable. Pour les périphériques USB, spécifiez PowerDeviceMaximum pour utiliser la valeur spécifiée par le pilote de bus.
  • UserControlOfWakeSettings vers WakeAllowUserControl si votre pilote permet aux utilisateurs de gérer les paramètres de veille ou de WakeDoNotAllowUserControl.
  • Activé sur WdfUseDefault pour activer la veille par défaut, mais pour permettre au paramètre de l’utilisateur de remplacer la valeur par défaut.

L’exemple suivant montre comment le pilote IdleWake_PPO appelle cette méthode dans sa méthode interne CMyDevice ::SetPowerManagement :

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

Pour activer la mise en éveil du système via WinUSB dans un pilote non PPO**

Pour activer la mise en éveil du système via WinUSB, le inf du pilote ajoute la valeur de Registre SystemWakeEnabled à la clé matérielle de l’appareil et la définit sur 1. L’exemple IdleWake_Non-PPO active la veille du système comme suit :

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

En définissant cette valeur, le pilote active l’éveil du système et permet à l’utilisateur de contrôler la capacité de l’appareil à réveiller le système. Dans Gestionnaire de périphériques, la page de propriétés des paramètres de gestion de l’alimentation de l’appareil inclut une zone de case activée avec laquelle l’utilisateur peut activer ou désactiver la veille du système.