É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 :

  1. Dans la boîte de dialogue Nouveau projet , dans la zone de recherche située en haut, tapez USB.

  2. Dans le volet central, sélectionnez Application WinUSB (universelle).

  3. Sélectionnez Suivant.

  4. 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).

    Premier écran de création de projet du modèle winusb.

    Deuxième écran de création de projet du modèle winusb.

    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.

    Explorateur de solutions de modèle winusb 1.

    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.

  5. 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.

    Ajout du deuxième projet de création de modèle winusb.

  6. Dans la boîte de dialogue Nouveau projet , dans la zone de recherche située en haut, tapez à nouveau USB.

  7. Dans le volet central, sélectionnez Package de pilotes WINUSB INF.

  8. Sélectionnez Suivant.

  9. 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 .

    Premier écran de création du deuxième projet de modèle winusb.

    Deuxième écran de création de projet de modèle 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.

    Explorateur de solutions de modèle winusb 2.

  10. Dans le fichier INF, USBApplication1.inf, recherchez ce code : %DeviceName% =USB_Install, USB\VID_vvvv&PID_pppp

  11. 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 .

  12. 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.

Capture d’écran montrant la fenêtre « Configuration Manager » avec « Debug » et « x64 » sélectionnés.

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

    1. 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.
    2. Sur l’ordinateur hôte, ouvrez votre solution dans Visual Studio.
    3. 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.

    1. Dans pch.h, incluez cette ligne :
    #include <cstdlib>
    

    Cette instruction include est requise pour l’appel system() à l’étape précédente.

    1. 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.

    2. 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.

    3. Cochez Supprimer les versions précédentes du pilote avant le déploiement.

    4. 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.

    5. Sélectionnez Installer/Réinstaller et Vérifier. Sélectionnez Appliquer.

      Déploiement de modèle winusb.

    6. 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.

      Débogueur distant de modèle winusb.

    7. 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.

    8. 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

  1. Sur l’ordinateur hôte, accédez à x64 > Win8.1Débug dans le dossier solution.

  2. Copiez l’exécutable de l’application, UsbApplication1.exe sur l’ordinateur cible.

  3. Sur l’ordinateur cible, lancez l’application.

  4. Sur l’ordinateur hôte, dans le menu Déboguer , sélectionnez Attacher à traiter.

  5. 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.

    Paramètre de débogage du modèle winusb.

  6. 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 :

  1. Sur l’ordinateur cible, ajoutez msvsmon.exe à la liste des applications autorisées via le pare-feu.
  2. Lancez le Moniteur de débogage à distance Visual Studio situé dans C:\DriverTest\msvsmon\msvsmon.exe.
  3. Créez un dossier de travail, tel que C :\remotetemp.
  4. Copiez l’exécutable de l’application, UsbApplication1.exe dans le dossier de travail sur l’ordinateur cible.
  5. 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.
  6. 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.
  7. Modifiez débogueur pour lancer enDébogueur Windows distant.
  8. 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.
  9. 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 :

    1. 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.

    2. 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.

      modèle d’application winusb.

      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.

    3. 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.

    4. 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.

    5. Remplacez Débogueur pour qu’il soit lancé en Débogueur Windows local.

    6. 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.

    7. 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 :

  1. 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.

  2. 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 .

  3. 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.

    1. 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.
    2. 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 .
    3. 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;
}
  1. 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.
  2. 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.

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 :