Écrire une application de bureau Windows basée sur le modèle WinUSB
Le moyen le plus simple d’écrire une application de bureau Windows qui communique avec un périphérique USB consiste à utiliser le modèle WinUSB C/C++. Pour ce modèle, vous avez besoin d’un environnement intégré avec le Kit de pilotes Windows (WDK) (avec outils de débogage pour Windows) et Microsoft Visual Studio (Professionnel ou Ultimate). Vous pouvez utiliser le modèle comme point de départ.
Avant de commencer
- Pour configurer l’environnement de développement intégré, installez d’abord Microsoft Visual Studio Ultimate 2019 ou Microsoft Visual Studio Professional 2019, puis installez le WDK. Vous trouverez des informations sur la configuration de Visual Studio et de WDK sur la page de téléchargement WDK.
- Les outils de débogage pour Windows sont inclus lorsque vous installez wdK. Pour plus d’informations, consultez Télécharger et installer les outils de débogage pour Windows.
Création d’une application WinUSB
Pour créer une application à partir du modèle :
Dans la boîte de dialogue Nouveau projet , dans la zone de recherche située en haut, tapez USB.
Dans le volet central, sélectionnez Application WinUSB (universelle).
Sélectionnez Suivant.
Entrez un nom de projet, choisissez un emplacement d’enregistrement, puis sélectionnez Créer.
Les captures d’écran suivantes montrent la boîte de dialogue Nouveau projet pour le modèle Application WinUSB (universelle).
Cette rubrique suppose que le nom du projet Visual Studio est USB Application1.
Visual Studio crée un projet et une solution. Vous pouvez voir la solution, le projet et les fichiers qui appartiennent au projet dans la fenêtre Explorateur de solutions, comme illustré dans la capture d’écran suivante. (Si la fenêtre Explorateur de solutions n’est pas visible, choisissez Explorateur de solutions dans le menu Affichage.) La solution contient un projet d’application C++ nommé USB Application1.
Le projet USB Application1 contient des fichiers sources pour l’application. Si vous souhaitez examiner le code source de l’application, vous pouvez ouvrir l’un des fichiers qui apparaissent sous Fichiers sources.
Ajoutez un projet de package de pilote à la solution. Sélectionnez et maintenez enfoncée (ou cliquez avec le bouton droit) sur la solution (solution « APPLICATION USB1 »), puis sélectionnez Ajouter un>nouveau projet , comme illustré dans la capture d’écran suivante.
Dans la boîte de dialogue Nouveau projet , dans la zone de recherche située en haut, tapez à nouveau USB.
Dans le volet central, sélectionnez Package de pilotes WINUSB INF.
Sélectionnez Suivant.
Entrez un nom de projet, puis sélectionnez Créer.
Les captures d’écran suivantes montrent la boîte de dialogue Nouveau projet pour le modèle Package de pilotes INF WinUSB .
Cette rubrique suppose que le nom du projet Visual Studio est Package USB Application1.
Le projet package USB Application1 contient un fichier INF qui est utilisé pour installer le pilote de Winusb.sys fourni par Microsoft en tant que pilote de périphérique.
Votre Explorateur de solutions doit maintenant contenir les deux projets, comme illustré dans la capture d’écran suivante.
Dans le fichier INF, USBApplication1.inf, recherchez ce code :
%DeviceName% =USB_Install, USB\VID_vvvv&PID_pppp
Remplacez VID_vvvv&PID_pppp par l’ID matériel de votre appareil. Obtenez l’ID matériel à partir de Gestionnaire de périphériques. Dans Gestionnaire de périphériques, affichez les propriétés de l’appareil. Sous l’onglet Détails , affichez la valeur de la propriété Id de matériel .
Dans la fenêtre Explorateur de solutions, sélectionnez et maintenez la touche (ou cliquez avec le bouton droit) Solution « Application USB1 » (2 projets sur 2) et choisissez Configuration Manager. Choisissez une configuration et une plateforme pour le projet d’application et le projet de package. Dans cet exercice, nous choisissons Déboguer et x64, comme illustré dans la capture d’écran suivante.
Génération, déploiement et débogage du projet
Jusqu’à présent, dans cet exercice, vous avez utilisé Visual Studio pour créer vos projets. Ensuite, vous devez configurer l’appareil auquel l’appareil est connecté. Le modèle nécessite que le pilote Winusb soit installé en tant que pilote pour votre appareil.
Votre environnement de test et de débogage peut avoir :
Configuration de deux ordinateurs : l’ordinateur hôte et l’ordinateur cible. Vous développez et générez votre projet dans Visual Studio sur l’ordinateur hôte. Le débogueur s’exécute sur l’ordinateur hôte et est disponible dans l’interface utilisateur de Visual Studio. Lorsque vous testez et déboguez l’application, le pilote s’exécute sur l’ordinateur cible.
Installation d’un seul ordinateur : votre cible et votre hôte s’exécutent sur un ordinateur. Vous développez et générez votre projet dans Visual Studio, puis exécutez le débogueur et l’application.
Vous pouvez déployer, installer, charger et déboguer votre application et le pilote en procédant comme suit :
Configuration de deux ordinateurs
- Configurez votre ordinateur cible en suivant les instructions fournies dans Provisionner un ordinateur pour le déploiement et le test de pilotes. Note: L’approvisionnement crée un utilisateur sur l’ordinateur cible nommé WDKRemoteUser. Une fois l’approvisionnement terminé, vous voyez l’utilisateur basculer vers WDKRemoteUser.
- Sur l’ordinateur hôte, ouvrez votre solution dans Visual Studio.
- Dans main.cpp, ajoutez cette ligne avant l’appel OpenDevice.
system ("pause")
La ligne entraîne la suspension de l’application lors du lancement. Cela est utile dans le débogage à distance.
- Dans pch.h, incluez cette ligne :
#include <cstdlib>
Cette instruction include est requise pour l’appel
system()
à l’étape précédente.Dans la fenêtre Explorateur de solutions, sélectionnez package d’application USB1 de façon enfoncée (ou cliquez avec le bouton droit), puis choisissez Propriétés.
Dans la fenêtre Pages de propriétés du package APPLICATION1 USB , dans le volet gauche, accédez à Configuration Properties > Driver Install > Deployment, comme illustré dans la capture d’écran suivante.
Cochez Supprimer les versions précédentes du pilote avant le déploiement.
Pour Nom de l’ordinateur distant, sélectionnez le nom de l’ordinateur que vous avez configuré pour le test et le débogage. Dans cet exercice, nous utilisons un ordinateur nommé dbg-target.
Sélectionnez Installer/Réinstaller et Vérifier. Sélectionnez Appliquer.
Dans la page de propriétés, accédez à Propriétés > de configuration Débogage, puis sélectionnez Outils de débogage pour Windows – Débogueur distant, comme illustré dans la capture d’écran suivante.
Sélectionnez Générer la solution dans le menu Générer. Visual Studio affiche la progression de la build dans la fenêtre Sortie . (Si la fenêtre Sortie n’est pas visible, choisissez Sortie dans le menu Affichage.) Dans cet exercice, nous avons créé le projet pour un système x64 exécutant Windows 10.
Sélectionnez Déployer la solution dans le menu Générer .
Sur l’ordinateur cible, vous verrez des scripts d’installation de pilote en cours d’exécution. Les fichiers de pilote sont copiés dans le dossier %Systemdrive%\drivertest\drivers sur l’ordinateur cible. Vérifiez que les fichiers .inf, .cat, test cert et .sys, ainsi que tous les autres fichiers nécessaires, sont présents dans le dossier %systemdrive%\drivertest\drivers. L’appareil doit apparaître dans Gestionnaire de périphériques sans erreur.
Sur l’ordinateur hôte, ce message s’affiche dans la fenêtre Sortie .
Deploying driver files for project
"<path>\visual studio 14\Projects\USB Application1\USB Application1 Package\USB Application1 Package.vcxproj".
Deployment may take a few minutes...
========== Build: 1 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
Pour déboguer l’application
Sur l’ordinateur hôte, accédez à x64 > Win8.1Débug dans le dossier solution.
Copiez l’exécutable de l’application, UsbApplication1.exe sur l’ordinateur cible.
Sur l’ordinateur cible, lancez l’application.
Sur l’ordinateur hôte, dans le menu Déboguer , sélectionnez Attacher à traiter.
Dans la fenêtre, sélectionnez Débogueur en mode utilisateur Windows (Outils de débogage pour Windows) comme transport et le nom de l’ordinateur cible, en l’occurrence dbg-target, comme qualificateur comme indiqué dans cette image.
Sélectionnez l’application dans la liste des processus disponibles , puis sélectionnez Attacher. Vous pouvez maintenant déboguer à l’aide de la fenêtre Exécution ou des options du menu Déboguer .
Les instructions précédentes déboguent l’application à l’aide des outils de débogage pour Windows – Débogueur distant. Si vous souhaitez utiliser le débogueur Windows distant (le débogueur fourni avec Visual Studio), suivez ces instructions :
- Sur l’ordinateur cible, ajoutez msvsmon.exe à la liste des applications autorisées via le pare-feu.
- Lancez le Moniteur de débogage à distance Visual Studio situé dans C:\DriverTest\msvsmon\msvsmon.exe.
- Créez un dossier de travail, tel que C :\remotetemp.
- Copiez l’exécutable de l’application, UsbApplication1.exe dans le dossier de travail sur l’ordinateur cible.
- Sur l’ordinateur hôte, dans Visual Studio, cliquez avec le bouton droit sur le projet package USB Application1 , puis sélectionnez Décharger le projet.
- Sélectionnez le projet Application USB1 et maintenez-la enfoncée (ou cliquez avec le bouton droit). Dans les propriétés du projet, développez le nœud Propriétés de configuration, puis sélectionnez Débogage.
- Modifiez débogueur pour lancer enDébogueur Windows distant.
- Modifiez les paramètres du projet pour exécuter l’exécutable sur un ordinateur distant en suivant les instructions fournies dans Débogage à distance d’un projet construit localement. Assurez-vous que les propriétés Répertoire de travail et Commande à distance reflètent le dossier sur l’ordinateur cible.
- Pour déboguer l’application, dans le menu Générer , sélectionnez Démarrer le débogage ou appuyez sur F5.
Configuration d’un seul ordinateur :
Pour générer votre application et le package d’installation de pilote, choisissez Générer une solution dans le menu Générer . Visual Studio affiche la progression de la génération dans la fenêtre Sortie . (Si la fenêtre Sortie n’est pas visible, choisissez Sortie dans le menu Affichage.) Dans cet exercice, nous avons créé le projet pour un système x64 exécutant Windows 10.
Pour afficher le package de pilotes généré, accédez à Windows Explorer à votre dossier Application1 USB, puis accédez à Package d’application USB de débogage > x64>. Le package de pilotes contient plusieurs fichiers : MyDriver.inf est un fichier d’informations que Windows utilise lorsque vous installez le pilote, mydriver.cat est un fichier catalogue que le programme d’installation utilise pour vérifier la signature de test pour le package de pilotes. Ces fichiers sont affichés dans la capture d’écran suivante.
Aucun fichier de pilote n’est inclus dans le package. En effet, le fichier INF fait référence au pilote intégré, Winusb.sys, qui se trouve dans le dossier Windows\System32.
Installez manuellement le pilote. Dans Gestionnaire de périphériques, mettez à jour le pilote en spécifiant le fichier INF dans le package. Pointez sur le package de pilote situé dans le dossier solution, indiqué dans la section précédente. Si vous voyez l’erreur
DriverVer set to a date in the future
, définissez les paramètres > de projet du package INF Inf2Cat > Général > Utiliser l’heure > locale Oui.Sélectionnez le projet Application USB1 et maintenez-la enfoncée (ou cliquez avec le bouton droit). Dans les propriétés du projet, développez le nœud Propriétés de configuration, puis sélectionnez Débogage.
Remplacez Débogueur pour qu’il soit lancé en Débogueur Windows local.
Sélectionnez et maintenez enfoncée (ou cliquez avec le bouton droit) sur le projet package d’application USB1, puis sélectionnez Décharger le projet.
Pour déboguer l’application, dans le menu Générer , sélectionnez Démarrer le débogage ou appuyez sur F5.
Discussion sur le code de modèle
Le modèle est un point de départ pour votre application de bureau. Le projet d’application USB1 contient les fichiers sources device.cpp et main.cpp.
Le fichier main.cpp contient le point d’entrée de l’application, _tmain. Le fichier device.cpp contient toutes les fonctions d’assistance qui ouvrent et ferment la poignée de l’appareil.
Le modèle a également un fichier d’en-tête nommé device.h. Ce fichier contient des définitions pour le GUID d’interface d’appareil (abordé plus loin) et une structure DEVICE_DATA qui stocke les informations obtenues par l’application. Par exemple, il stocke le handle d’interface WinUSB obtenu par OpenDevice et utilisé dans les opérations suivantes.
typedef struct _DEVICE_DATA {
BOOL HandlesOpen;
WINUSB_INTERFACE_HANDLE WinusbHandle;
HANDLE DeviceHandle;
TCHAR DevicePath[MAX_PATH];
} DEVICE_DATA, *PDEVICE_DATA;
Obtention du chemin d’accès instance pour l’appareil - consultez RetrieveDevicePath dans device.cpp
Pour accéder à un périphérique USB, l’application crée un handle de fichier valide pour l’appareil en appelant CreateFile. Pour cet appel, l’application doit obtenir le chemin d’accès de l’appareil instance. Pour obtenir le chemin d’accès de l’appareil, l’application utilise des routines SetupAPI et spécifie le GUID d’interface de l’appareil dans le fichier INF utilisé pour installer Winusb.sys. Device.h déclare une constante GUID nommée GUID_DEVINTERFACE_USBApplication1. En utilisant ces routines, l’application énumère tous les appareils de la classe d’interface d’appareil spécifiée et récupère le chemin d’accès de l’appareil de l’appareil.
HRESULT
RetrieveDevicePath(
_Out_bytecap_(BufLen) LPTSTR DevicePath,
_In_ ULONG BufLen,
_Out_opt_ PBOOL FailureDeviceNotFound
)
/*++
Routine description:
Retrieve the device path that can be used to open the WinUSB-based device.
If multiple devices have the same device interface GUID, there is no
guarantee of which one will be returned.
Arguments:
DevicePath - On successful return, the path of the device (use with CreateFile).
BufLen - The size of DevicePath's buffer, in bytes
FailureDeviceNotFound - TRUE when failure is returned due to no devices
found with the correct device interface (device not connected, driver
not installed, or device is disabled in Device Manager); FALSE
otherwise.
Return value:
HRESULT
--*/
{
BOOL bResult = FALSE;
HDEVINFO deviceInfo;
SP_DEVICE_INTERFACE_DATA interfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;
ULONG length;
ULONG requiredLength=0;
HRESULT hr;
if (NULL != FailureDeviceNotFound) {
*FailureDeviceNotFound = FALSE;
}
//
// Enumerate all devices exposing the interface
//
deviceInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBApplication1,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (deviceInfo == INVALID_HANDLE_VALUE) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
//
// Get the first interface (index 0) in the result set
//
bResult = SetupDiEnumDeviceInterfaces(deviceInfo,
NULL,
&GUID_DEVINTERFACE_USBApplication1,
0,
&interfaceData);
if (FALSE == bResult) {
//
// We would see this error if no devices were found
//
if (ERROR_NO_MORE_ITEMS == GetLastError() &&
NULL != FailureDeviceNotFound) {
*FailureDeviceNotFound = TRUE;
}
hr = HRESULT_FROM_WIN32(GetLastError());
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
//
// Get the size of the path string
// We expect to get a failure with insufficient buffer
//
bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo,
&interfaceData,
NULL,
0,
&requiredLength,
NULL);
if (FALSE == bResult && ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
hr = HRESULT_FROM_WIN32(GetLastError());
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
//
// Allocate temporary space for SetupDi structure
//
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
LocalAlloc(LMEM_FIXED, requiredLength);
if (NULL == detailData)
{
hr = E_OUTOFMEMORY;
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
length = requiredLength;
//
// Get the interface's path string
//
bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo,
&interfaceData,
detailData,
length,
&requiredLength,
NULL);
if(FALSE == bResult)
{
hr = HRESULT_FROM_WIN32(GetLastError());
LocalFree(detailData);
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
//
// Give path to the caller. SetupDiGetDeviceInterfaceDetail ensured
// DevicePath is NULL-terminated.
//
hr = StringCbCopy(DevicePath,
BufLen,
detailData->DevicePath);
LocalFree(detailData);
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
Dans la fonction précédente, l’application obtient le chemin d’accès de l’appareil en appelant ces routines :
ConfigurezDiGetClassDevs pour obtenir un handle pour l’ensemble d’informations sur l’appareil, un tableau qui contient des informations sur tous les appareils installés correspondant à la classe d’interface d’appareil spécifiée, GUID_DEVINTERFACE_USBApplication1. Chaque élément du tableau appelé interface d’appareil correspond à un appareil installé et inscrit auprès du système. La classe d’interface d’appareil est identifiée en transmettant le GUID d’interface d’appareil que vous avez défini dans le fichier INF. La fonction retourne un handle HDEVINFO au jeu d’informations de l’appareil.
ConfigurezDiEnumDeviceInterfaces pour énumérer les interfaces d’appareil dans l’ensemble d’informations de l’appareil et obtenir des informations sur votre interface d’appareil.
Cet appel nécessite les éléments suivants :
Une structure de SP_DEVICE_INTERFACE_DATA d’appel initialisée dont le membre cbSize est défini sur la taille de la structure.
Le handle HDEVINFO de l’étape 1.
GUID d’interface d’appareil que vous avez défini dans le fichier INF.
SetupDiEnumDeviceInterfaces recherche le tableau d’informations sur l’appareil pour l’index spécifié de l’interface de l’appareil et remplit la structure SP_DEVICE_INTERFACE_DATA initialisée avec des données de base sur l’interface.
Pour énumérer toutes les interfaces d’appareil dans l’ensemble d’informations de l’appareil, appelez SetupDiEnumDeviceInterfaces dans une boucle jusqu’à ce que la fonction retourne FALSE et que le code d’erreur de l’échec soit ERROR_NO_MORE_ITEMS. Le code d’erreur ERROR_NO_MORE_ITEMS peut être récupéré en appelant GetLastError. À chaque itération, incrémentez l’index membre.
Vous pouvez également appeler SetupDiEnumDeviceInfo qui énumère le jeu d’informations sur l’appareil et retourne des informations sur les éléments d’interface de l’appareil, spécifiés par l’index, dans une structure de SP_DEVINFO_DATA allouée à l’appelant . Vous pouvez ensuite passer une référence à cette structure dans le paramètre DeviceInfoData de la fonction SetupDiEnumDeviceInterfaces .
SetupDiGetDeviceInterfaceDetail pour obtenir des données détaillées pour l’interface de l’appareil. Les informations sont retournées dans une structure SP_DEVICE_INTERFACE_DETAIL_DATA . Étant donné que la taille de la structure SP_DEVICE_INTERFACE_DETAIL_DATA varie, SetupDiGetDeviceInterfaceDetail est appelé deux fois. Le premier appel obtient la taille de mémoire tampon à allouer pour la structure SP_DEVICE_INTERFACE_DETAIL_DATA . Le deuxième appel remplit la mémoire tampon allouée avec des informations détaillées sur l’interface.
- Appelle SetupDiGetDeviceInterfaceDetail avec le paramètre DeviceInterfaceDetailData défini surNULL. La fonction retourne la taille de mémoire tampon correcte dans le paramètre requiredlength . Cet appel échoue avec le code d’erreur ERROR_INSUFFICIENT_BUFFER. Ce code d’erreur est attendu.
- Alloue de la mémoire pour une structure SP_DEVICE_INTERFACE_DETAIL_DATA en fonction de la taille de mémoire tampon correcte récupérée dans le paramètre requiredlength .
- Appelle à nouveau SetupDiGetDeviceInterfaceDetail et lui transmet une référence à la structure initialisée dans le paramètre DeviceInterfaceDetailData . Lorsque la fonction retourne, la structure est remplie d’informations détaillées sur l’interface. Le chemin d’accès de l’appareil se trouve dans le membre DevicePath de la structure SP_DEVICE_INTERFACE_DETAIL_DATA.
Création d’un handle de fichier pour l’appareil
Consultez OpenDevice dans device.cpp.
Pour interagir avec l’appareil, le a besoin d’un handle d’interface WinUSB sur la première interface (par défaut) de l’appareil. Le code de modèle obtient le handle de fichier et le handle d’interface WinUSB et les stocke dans la structure DEVICE_DATA.
HRESULT
OpenDevice(
_Out_ PDEVICE_DATA DeviceData,
_Out_opt_ PBOOL FailureDeviceNotFound
)
/*++
Routine description:
Open all needed handles to interact with the device.
If the device has multiple USB interfaces, this function grants access to
only the first interface.
If multiple devices have the same device interface GUID, there is no
guarantee of which one will be returned.
Arguments:
DeviceData - Struct filled in by this function. The caller should use the
WinusbHandle to interact with the device, and must pass the struct to
CloseDevice when finished.
FailureDeviceNotFound - TRUE when failure is returned due to no devices
found with the correct device interface (device not connected, driver
not installed, or device is disabled in Device Manager); FALSE
otherwise.
Return value:
HRESULT
--*/
{
HRESULT hr = S_OK;
BOOL bResult;
DeviceData->HandlesOpen = FALSE;
hr = RetrieveDevicePath(DeviceData->DevicePath,
sizeof(DeviceData->DevicePath),
FailureDeviceNotFound);
if (FAILED(hr)) {
return hr;
}
DeviceData->DeviceHandle = CreateFile(DeviceData->DevicePath,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (INVALID_HANDLE_VALUE == DeviceData->DeviceHandle) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
bResult = WinUsb_Initialize(DeviceData->DeviceHandle,
&DeviceData->WinusbHandle);
if (FALSE == bResult) {
hr = HRESULT_FROM_WIN32(GetLastError());
CloseHandle(DeviceData->DeviceHandle);
return hr;
}
DeviceData->HandlesOpen = TRUE;
return hr;
}
- L’application appelle CreateFile pour créer un handle de fichier pour l’appareil en spécifiant le chemin d’accès de l’appareil récupéré précédemment. Il utilise l’indicateur FILE_FLAG_OVERLAPPED, car WinUSB dépend de ce paramètre.
- En utilisant le handle de fichier pour l’appareil, l’application crée un handle d’interface WinUSB. Les fonctions WinUSB utilisent ce handle pour identifier l’appareil cible au lieu du handle de fichier. Pour obtenir un handle d’interface WinUSB, l’application appelle WinUsb_Initialize en passant le handle de fichier. Utilisez le handle reçu dans les appels suivants pour obtenir des informations à partir de l’appareil et pour envoyer des demandes d’E/S à l’appareil.
Relâchez les poignées d’appareil - consultez CloseDevice dans device.cpp
Le code du modèle implémente le code pour libérer le handle de fichier et le handle d’interface WinUSB pour l’appareil.
- CloseHandle pour libérer le handle créé par CreateFile, comme décrit dans la section Créer un handle de fichier pour l’appareil de cette procédure pas à pas.
- WinUsb_Free libérer le handle d’interface WinUSB pour l’appareil, qui est retourné par WinUsb_Initialize .
VOID
CloseDevice(
_Inout_ PDEVICE_DATA DeviceData
)
/*++
Routine description:
Perform required cleanup when the device is no longer needed.
If OpenDevice failed, do nothing.
Arguments:
DeviceData - Struct filled in by OpenDevice
Return value:
None
--*/
{
if (FALSE == DeviceData->HandlesOpen) {
//
// Called on an uninitialized DeviceData
//
return;
}
WinUsb_Free(DeviceData->WinusbHandle);
CloseHandle(DeviceData->DeviceHandle);
DeviceData->HandlesOpen = FALSE;
return;
}
Étapes suivantes
Ensuite, lisez ces rubriques pour envoyer des informations sur l’appareil et envoyer des transferts de données à l’appareil :
Accéder à un périphérique USB à l’aide des fonctions WinUSB
Découvrez comment interroger l’appareil pour obtenir des informations spécifiques à l’USB, telles que la vitesse de l’appareil, les descripteurs d’interface, les points de terminaison associés et leurs canaux.
Envoyer des transferts isochronieux USB à partir d’une application de bureau WinUSB
Transférez des données vers et depuis des points de terminaison isochronieux d’un périphérique USB.