Comment écrire votre premier pilote client USB (UMDF)
Dans cet article, vous utiliserez le modèle Pilote en mode utilisateur, USB (UMDF V2) fourni avec Microsoft Visual Studio 2022 pour écrire un pilote client basé sur le framework de pilotes en mode utilisateur (UMDF). Après avoir compilé et installé le pilote client, vous visualiserez le pilote client dans le Gestionnaire de périphériques et afficherez la sortie du pilote dans un débogueur.
L’UMDF (appelé dans cet article le framework) est basé sur le modèle d’objet composant (COM). Chaque objet du framework doit implémenter IUnknown et ses méthodes, QueryInterface, AddRef, et Release, par défaut. Les méthodes AddRef et Release gèrent la durée de vie de l’objet, de sorte que le pilote client n’a pas besoin de maintenir le compteur de référence. La méthode QueryInterface permet au pilote client d’obtenir des pointeurs d’interface vers d’autres objets du framework dans le modèle d’objet Windows Driver Frameworks (WDF). Les objets du framework exécutent des tâches complexes de pilote et interagissent avec Windows. Certains objets du framework exposent des interfaces qui permettent à un pilote client d’interagir avec le framework.
Un pilote client basé sur l’UMDF est implémenté en tant que serveur COM en processus (DLL), et le C++ est le langage préféré pour écrire un pilote client pour un périphérique USB. En général, le pilote client implémente plusieurs interfaces exposées par le framework. Cet article fait référence à une classe définie par le pilote client qui implémente les interfaces du framework en tant que classe de rappel. Une fois ces classes instanciées, les objets de rappel résultants sont associés à des objets spécifiques du framework. Cette association donne au pilote client l’opportunité de répondre à des événements liés à l’appareil ou au système signalés par le framework. Chaque fois que Windows informe le framework de certains événements, le framework invoque le rappel du pilote client, s’il en existe un. Sinon, le framework poursuit le traitement par défaut de l’événement. Le code modèle définit des classes de rappel pour le pilote, le périphérique et la file d’attente.
Pour une explication du code source généré par le modèle, veuillez consulter la section Comprendre le code modèle UMDF pour le pilote client USB.
Avant de commencer
Pour développer, déboguer et installer un pilote en mode utilisateur, vous avez besoin de deux ordinateurs :
- Un ordinateur hôte exécutant Windows 10 ou une version ultérieure du système d’exploitation Windows. L’ordinateur hôte est votre environnement de développement, où vous écrivez et déboguez votre pilote.
- Un ordinateur cible exécutant la version du système d’exploitation que vous souhaitez tester pour votre pilote, par exemple, Windows 11, version 22H2. L’ordinateur cible possède le pilote en mode utilisateur que vous souhaitez déboguer ainsi qu’un des débogueurs.
Dans certains cas, où les ordinateurs hôte et cible exécutent la même version de Windows, vous pouvez n’avoir qu’un seul ordinateur exécutant Windows 10 ou une version ultérieure de Windows. Cet article part du principe que vous utilisez deux ordinateurs pour développer, déboguer et installer votre pilote en mode utilisateur.
Avant de commencer, assurez-vous de respecter les prérequis suivants :
Configuration logicielle requise
Votre ordinateur hôte dispose de Visual Studio 2022.
Votre ordinateur hôte dispose du dernier Kit de pilotes Windows (WDK) pour Windows 11, version 22H2.
Le kit comprend des en-têtes, des bibliothèques, des outils, de la documentation et les outils de débogage nécessaires pour développer, construire et déboguer un pilote client USB. Vous pouvez obtenir la dernière version du WDK à partir de Comment obtenir le WDK.
Votre ordinateur hôte dispose de la dernière version des outils de débogage pour Windows. Vous pouvez obtenir la dernière version via le WDK ou en consultant la section Télécharger et installer les outils de débogage pour Windows.
Si vous utilisez deux ordinateurs, vous devez configurer les ordinateurs hôte et cible pour le débogage en mode utilisateur. Pour plus d’informations, veuillez consulter la section Configuration du débogage en mode utilisateur dans Visual Studio.
Configuration matérielle requise
Procurez-vous un périphérique USB pour lequel vous allez écrire le pilote client. Dans la plupart des cas, vous recevez un périphérique USB et ses spécifications matérielles. La spécification décrit les capacités du périphérique et les commandes du fabricant prises en charge. Utilisez la spécification pour déterminer les fonctionnalités du pilote USB et les décisions de conception associées.
Si vous êtes novice dans le développement de pilotes USB, utilisez le kit d’apprentissage OSR USB FX2 pour étudier les exemples de pilotes USB inclus dans le WDK. Il contient le périphérique USB FX2 et toutes les spécifications matérielles requises pour implémenter un pilote client.
Lectures recommandées
- Concepts pour tous les développeurs de pilotes
- Nœuds de périphériques et piles de périphériques
- Premiers pas avec les pilotes sur Windows
- Framework de pilotes en mode utilisateur
- Developing Drivers with Windows Driver Foundation, écrit par Penny Orwick et Guy Smith. Pour plus d’informations, consultez Développer des pilotes avec WDF.
Étape 1 : Générer le code du pilote
Pour plus de détails sur l’écriture du code du pilote UMDF, veuillez consulter la section Écrire un pilote UMDF basé sur un modèle.
Pour le code spécifique à l’USB, sélectionnez les options suivantes dans Visual Studio 2022
- Dans la boîte de dialogue Nouveau projet, dans la zone de recherche en haut, tapez USB.
- Dans le volet central, sélectionnez Pilote en mode utilisateur, USB (UMDF V2).
- Cliquez sur Suivant.
- Entrez un nom de projet, choisissez un emplacement d’enregistrement et sélectionnez Créer.
Les captures d’écran suivantes montrent la boîte de dialogue Nouveau projet pour le modèle Pilote USB en mode utilisateur.
Cet article part du principe que le nom du projet est MyUSBDriver_UMDF_. Il contient les fichiers suivants :
Fichiers | Description |
---|---|
Driver.h; Driver.c | Contient l’implémentation du point d’entrée du module du pilote. DriverEntry et la fonctionnalité liée à WDFDRIVER et aux rappels. |
Device.h; Device.c | Fonctionnalité liée à WDFDEVICE et WDFUSBDEVICE et rappels. |
Queue.h; Queue.c | Fonctionnalité liée à WDFQUEUE et rappels. |
Trace.h | Définit le GUID de l’interface du périphérique. Il déclare également des fonctions de traçage et des macros. |
<Nom du projet>.inf | Fichier INF nécessaire pour installer le pilote client sur l’ordinateur cible. |
Étape 2 : Ajouter des informations sur votre appareil
Avant de construire le pilote, vous devez ajouter des informations sur votre appareil, en particulier l’ID matériel. Pour fournir l’ID matériel :
- Dans la fenêtre Explorateur de solutions, faites un clic droit sur MyUSBDriver_UMDF_, et choisissez Propriétés.
- Dans la fenêtre Pages des propriétés de MyUSBDriver_UMDF_, accédez à Propriétés de configuration > Installation du pilote > Déploiement, comme montré ici.
- Cochez Supprimer les versions précédentes du pilote avant le déploiement.
- Pour Nom de l’appareil cible, sélectionnez le nom de l’ordinateur que vous avez configuré pour les tests et le débogage.
- Sélectionnez Mise à jour du pilote via l’ID matériel, et entrez l’ID matériel pour votre pilote. Dans cet exercice, l’ID matériel est Root\MyUSBDriver_UMDF_. Cliquez sur OK.
Remarque
Dans cet exercice, l’ID matériel n’identifie pas un matériel réel. Il identifie un appareil imaginaire qui sera placé dans l’arborescence des appareils en tant qu’enfant du nœud racine. Pour un matériel réel, ne sélectionnez pas Mise à jour du pilote via l’ID matériel. Au lieu de cela, sélectionnez Installer et vérifier. Vous pouvez voir l’ID matériel dans le fichier d’informations (INF) de votre pilote. Dans la fenêtre Explorateur de solutions, accédez à MyUSBDriver_UMDF_ > Fichiers de pilote, et double-cliquez sur MyUSBDriver_UMDF_.inf. L’ID matériel se trouve sous [Standard.NT$ARCH$].
Tous les pilotes clients USB basés sur l’UMDF nécessitent deux pilotes fournis par Microsoft, le réflecteur et WinUSB.
Réflecteur : Si votre pilote se charge correctement, le réflecteur est chargé en tant que pilote le plus haut dans la pile en mode noyau. Le réflecteur doit être le pilote le plus haut dans la pile en mode noyau. Pour répondre à cette exigence, le fichier INF du modèle spécifie le réflecteur comme un service et WinUSB comme un pilote de filtre inférieur dans l’INF :
[MyDevice_Install.NT.Services] AddService=WUDFRd,0x000001fa,WUDFRD_ServiceInstall ; flag 0x2 sets this as the service for the device AddService=WinUsb,0x000001f8,WinUsb_ServiceInstall ; this service is installed because its a filter.
WinUSB : Le package d’installation doit contenir des co-installateurs pour Winusb.sys car, pour le pilote client, WinUSB est la passerelle vers la pile de pilotes USB en mode noyau. Un autre composant chargé est une DLL en mode utilisateur, nommée WinUsb.dll, dans le processus hôte du pilote client (Wudfhost.exe). Winusb.dll expose des Fonctions WinUSB qui simplifient le processus de communication entre le pilote client et WinUSB.
Étape 3 : Compiler le code du pilote client USB
Pour compiler votre pilote :
- Ouvrez le projet ou la solution du pilote dans Visual Studio 2022.
- Faites un clic droit sur la solution dans Explorateur de solutions et sélectionnez Gestionnaire de configuration.
- Depuis le Gestionnaire de configuration, sélectionnez votre Configuration active de la solution (par exemple, Débogage ou Release) et votre Plateforme active de la solution (par exemple, x64) qui correspondent au type de build qui vous intéresse.
- Vérifiez que votre GUID d’interface de périphérique est correct dans tout le projet.
- Le GUID d’interface de périphérique est défini dans Trace.h et est référencé dans
MyUSBDriverUMDFCreateDevice
dans Device.c. Lorsque vous créez votre projet sous le nom MyUSBDriver_UMDF_, Visual Studio 2022 définit le GUID d’interface de périphérique sous le nomGUID_DEVINTERFACE_MyUSBDriver_UMDF_
mais appelleWdfDeviceCreateDeviceInterface
avec le paramètre incorrect&GUID_DEVINTERFACE_MyUSBDriverUMDF
. Remplacez le paramètre incorrect par le nom défini dans Trace.h pour vous assurer que le pilote se construit correctement.
- Le GUID d’interface de périphérique est défini dans Trace.h et est référencé dans
- Dans le menu Générer, sélectionnez Générer la solution.
Pour plus d’informations, veuillez consulter la section Compilation d’un pilote.
Étape 4 : Configurer un ordinateur pour les tests et le débogage
Pour tester et déboguer un pilote, vous exécutez le débogueur sur l’ordinateur hôte et le pilote sur l’ordinateur cible. Jusqu’à présent, vous avez utilisé Visual Studio sur l’ordinateur hôte pour compiler un pilote. Ensuite, vous devez configurer un ordinateur cible. Pour configurer un ordinateur cible, suivez les instructions de la section Approvisionnement d’un ordinateur pour le déploiement et le test de pilotes.
Étape 5 : Activer le traçage pour le débogage en mode noyau
Le code du modèle contient plusieurs messages de traçage (TraceEvents) qui peuvent vous aider à suivre les appels de fonction. Toutes les fonctions du code source contiennent des messages de traçage qui marquent l’entrée et la sortie d’une routine. En cas d’erreurs, le message de traçage contient le code d’erreur et une chaîne significative. Étant donné que le traçage WPP est activé pour votre projet de pilote, le fichier symbole PDB créé pendant le processus de compilation contient des instructions de formatage des messages de traçage. Si vous configurez les ordinateurs hôte et cible pour le traçage WPP, votre pilote peut envoyer des messages de traçage vers un fichier ou le débogueur.
Pour configurer votre ordinateur hôte pour le traçage WPP
Créez des fichiers de format de message de traçage (TMF) en extrayant les instructions de formatage des messages de traçage à partir du fichier symbole PDB.
Vous pouvez utiliser Tracepdb.exe pour créer des fichiers TMF. L’outil est situé dans le <dossier d’installation>Windows Kits\10\bin\<architecture> du WDK. La commande suivante crée des fichiers TMF pour le projet de pilote.
tracepdb -f <PDBFiles> -p <TMFDirectory>
L’option -f spécifie l’emplacement et le nom du fichier symbole PDB. L’option -p spécifie l’emplacement des fichiers TMF créés par Tracepdb. Pour plus d’informations, veuillez consulter la section Commandes Tracepdb.
Il y a trois fichiers à l’emplacement spécifié, un par fichier de code C dans le projet. Ils ont des noms de fichiers GUID.
Dans le débogueur, tapez les commandes suivantes :
.load Wmitrace .chain !wmitrace.searchpath + <TMF file location>
Ces commandes :
- Chargez l’extension Wmitrace.dll.
- Vérifie que l’extension du débogueur est chargée.
- Ajoute l’emplacement des fichiers TMF au chemin de recherche de l’extension du débogueur.
La sortie ressemble à ceci :
Trace Format search path is: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;c:\drivers\tmf
Pour configurer votre ordinateur cible pour le traçage WPP
Assurez-vous que vous disposez de l’outil Tracelog sur votre ordinateur cible. L’outil est situé dans le <dossier d’installation>Windows Kits\10\Tools\<arch> du WDK. Pour plus d’informations, veuillez consulter la section Syntaxe des commandes Tracelog.
Ouvrez une Fenêtre de commande et exécutez en tant qu’administrateur.
Tapez la commande suivante :
tracelog -start MyTrace -guid \#c918ee71-68c7-4140-8f7d-c907abbcb05d -flag 0xFFFF -level 7-rt -kd
La commande démarre une session de traçage nommée MyTrace.
L’argument guid spécifie le GUID du fournisseur de traçage, qui est le pilote client. Vous pouvez obtenir le GUID à partir de Trace.h dans le projet Visual Studio 2022. Comme autre option, vous pouvez taper la commande suivante et spécifier le GUID dans un fichier .guid. Le fichier contient le GUID au format avec tirets :
tracelog -start MyTrace -guid c:\\drivers\\Provider.guid -flag 0xFFFF -level 7-rt -kd
Vous pouvez arrêter la session de traçage en tapant la commande suivante :
tracelog -stop MyTrace
Étape 6 : Déployer le pilote sur l’ordinateur cible
- Dans la fenêtre Explorateur de solutions, faites un clic droit sur le nom du projet (MyUSBDriver_UMDF_), et choisissez Propriétés.
- Dans le volet de gauche, accédez à Propriétés de la configuration > Installation du pilote > Déploiement.
- Pour Nom de l’appareil cible, spécifiez le nom de l’ordinateur cible.
- Sélectionnez Installer/Réinstaller et vérifier.
- Sélectionnez OK.
- Dans le menu Déboguer, choisissez Démarrer le débogage, ou appuyez sur F5 sur le clavier.
Remarque
Ne spécifiez pas l’identifiant matériel de votre périphérique sous Mise à jour du pilote par ID matériel. L’identifiant matériel doit être spécifié uniquement dans les informations (fichier INF) de votre pilote.
Étape 7 : Visualiser le pilote dans le Gestionnaire de périphériques
Entrez la commande suivante pour ouvrir le Gestionnaire de périphériques.
devmgmt
Vérifiez que le Gestionnaire de périphériques affiche le nœud suivant.
Appareil USB
MyUSBDriver_UMDF_Device
Étape 8 : Visualiser la sortie dans le débogueur
Vérifiez que les messages de traçage apparaissent dans la Fenêtre immédiate du débogueur sur l’ordinateur hôte.
La sortie doit ressembler à ce qui suit :
[0]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::OnPrepareHardware Entry
[0]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::OnPrepareHardware Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::CreateInstanceAndInitialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Initialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Initialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::CreateInstanceAndInitialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Configure Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::CreateInstanceAndInitialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::Initialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::Initialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::CreateInstanceAndInitialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Configure Exit
Notes
Jetons un coup d’œil à la manière dont le framework et le pilote client fonctionnent ensemble pour interagir avec Windows et traiter les requêtes envoyées au périphérique USB. Cette illustration montre les modules chargés dans le système pour un pilote client USB basé sur l’UMDF.
Le rôle de chaque module est décrit ici :
- Application : un processus en mode utilisateur qui émet des requêtes d’E/S pour communiquer avec le périphérique USB.
- Gestionnaire d’E/S : un composant de Windows qui crée des paquets de requêtes d’E/S (IRP) pour représenter les requêtes d’application reçues, et les transmet au sommet de la pile de périphériques en mode noyau pour le périphérique cible.
- Réflecteur : un pilote en mode noyau fourni par Microsoft installé au sommet de la pile de périphériques en mode noyau (WUDFRd.sys). Le réflecteur redirige les IRP reçus du gestionnaire d’E/S vers le processus hôte du pilote client. Lors de la réception de la requête, le framework et le pilote client traitent la requête.
- Processus hôte : le processus dans lequel le pilote en mode utilisateur s’exécute (Wudfhost.exe). Il héberge également le framework et le répartiteur d’E/S.
- Pilote client : le pilote fonctionnel en mode utilisateur pour le périphérique USB.
- UMDF : le module framework qui gère la plupart des interactions avec Windows pour le compte du pilote client. Il expose les interfaces de pilotes de périphériques en mode utilisateur (DDI) que le pilote client peut utiliser pour effectuer des tâches courantes de pilote.
- Répartiteur : mécanisme qui s’exécute dans le processus hôte ; détermine comment transmettre une requête au mode noyau après qu’elle a été traitée par les pilotes en mode utilisateur et a atteint le bas de la pile en mode utilisateur. Dans l’illustration, le répartiteur transmet la requête à la DLL en mode utilisateur, Winusb.dll.
- Winusb.dll : une DLL en mode utilisateur fournie par Microsoft qui expose des Fonctions WinUSB qui simplifient le processus de communication entre le pilote client et WinUSB (Winusb.sys, chargé en mode noyau).
- Winusb.sys : un pilote fourni par Microsoft qui est requis par tous les pilotes clients UMDF pour les périphériques USB. Le pilote doit être installé sous le réflecteur et agit comme la passerelle vers la pile de pilotes USB en mode noyau. Pour plus d’informations, consultez Présentation de WinUSB pour les développeurs.
- Pile de pilotes USB : un ensemble de pilotes, fournis par Microsoft, qui gèrent la communication au niveau des protocoles avec le périphérique USB. Pour plus d’informations, veuillez consulter la section Pilotes côté hôte USB dans Windows.
Chaque fois qu’une application fait une requête pour la pile de pilotes USB, le gestionnaire d’E/S de Windows envoie la requête au réflecteur, qui la redirige vers le pilote client en mode utilisateur. Le pilote client traite la requête en appelant des méthodes spécifiques de l’UMDF, qui appellent en interne des Fonctions WinUSB pour envoyer la requête à WinUSB. Lors de la réception de la requête, WinUSB traite la requête ou la transmet à la pile de pilotes USB.