Menulis aplikasi desktop Windows berdasarkan templat WinUSB

Cara termampu untuk menulis aplikasi desktop Windows yang berkomunikasi dengan perangkat USB, adalah dengan menggunakan templat C/C++ WinUSB. Untuk templat ini, Anda memerlukan lingkungan terintegrasi dengan Windows Driver Kit (WDK) (dengan Alat Debugging untuk Windows) dan Microsoft Visual Studio (Professional atau Ultimate). Anda dapat menggunakan templat sebagai titik awal.

Sebelum memulai

  • Untuk menyiapkan lingkungan pengembangan terintegrasi, pertama-tama instal Microsoft Visual Studio Ultimate 2019 atau Microsoft Visual Studio Professional 2019 lalu instal WDK. Anda dapat menemukan informasi tentang cara menyiapkan Visual Studio dan WDK di halaman unduhan WDK.
  • Alat Penelusuran Kesalahan untuk Windows disertakan saat Anda menginstal WDK. Untuk informasi selengkapnya, lihat Mengunduh dan Menginstal Alat Penelusuran Kesalahan untuk Windows.

Membuat aplikasi WinUSB

Untuk membuat aplikasi dari templat:

  1. Dalam kotak dialog Proyek Baru , di kotak pencarian di bagian atas, ketik USB.

  2. Di panel tengah, pilih Aplikasi WinUSB (Universal).

  3. Pilih Selanjutnya.

  4. Masukkan nama proyek, pilih lokasi penyimpanan, dan pilih Buat.

    Cuplikan layar berikut ini memperlihatkan kotak dialog Proyek Baru untuk templat Aplikasi WinUSB (Universal).

    winusb template layar pertama pembuatan proyek baru.

    winusb template proyek baru pembuatan layar kedua.

    Topik ini mengasumsikan bahwa nama proyek Visual Studio adalah USB Application1.

    Visual Studio membuat satu proyek dan solusi. Anda dapat melihat solusi, proyek, dan file milik proyek di jendela Penjelajah Solusi, seperti yang ditunjukkan pada cuplikan layar berikut. (Jika jendela Penjelajah Solusi tidak terlihat, pilih Penjelajah Solusi dari menu Tampilan.) Solusinya berisi proyek aplikasi C++ bernama USB Application1.

    penjelajah solusi templat winusb 1.

    Proyek USB Application1 memiliki file sumber untuk aplikasi. Jika Anda ingin melihat kode sumber aplikasi, Anda dapat membuka salah satu file yang muncul di bawah File Sumber.

  5. Tambahkan proyek paket driver ke solusi. Pilih dan tahan (atau klik kanan) solusi (Solusi 'USB Application1'), lalu pilih Tambahkan>Proyek Baru seperti yang ditunjukkan pada cuplikan layar berikut.

    penambahan proyek kedua pembuatan templat winusb.

  6. Dalam kotak dialog Proyek Baru , di kotak pencarian di bagian atas, sekali lagi ketik USB.

  7. Di panel tengah, pilih Paket Driver WINUSB INF.

  8. Pilih Selanjutnya.

  9. Masukkan nama proyek, lalu pilih Buat.

    Cuplikan layar berikut ini memperlihatkan kotak dialog Proyek Baru untuk templat Paket Driver INF WinUSB .

    templat winusb layar pertama pembuatan proyek kedua.

    winusb template kedua proyek pembuatan layar kedua.

    Topik ini mengasumsikan bahwa nama proyek Visual Studio adalah Paket USB Application1.

    Proyek Paket Usb Application1 berisi file INF yang digunakan untuk menginstal driver Winusb.sys yang disediakan Microsoft sebagai driver perangkat.

    Penjelajah Solusi Anda sekarang harus berisi kedua proyek, seperti yang ditunjukkan pada cuplikan layar berikut.

    penjelajah solusi templat winusb 2.

  10. Dalam file INF, USBApplication1.inf, temukan kode ini: %DeviceName% =USB_Install, USB\VID_vvvv&PID_pppp

  11. Ganti VID_vvvv&PID_pppp dengan ID perangkat keras untuk perangkat Anda. Dapatkan ID perangkat keras dari Manajer Perangkat. Di Manajer Perangkat, lihat properti perangkat. Pada tab Detail , lihat nilai properti Id Perangkat Keras .

  12. Di jendela Penjelajah Solusi, pilih dan tahan (atau klik kanan) Solusi 'USB Application1' (2 dari 2 proyek), dan pilih Configuration Manager. Pilih konfigurasi dan platform untuk proyek aplikasi dan proyek paket. Dalam latihan ini, kami memilih Debug dan x64, seperti yang ditunjukkan pada cuplikan layar berikut.

Cuplikan layar yang memperlihatkan jendela

Membangun, menyebarkan, dan men-debug proyek

Sejauh ini dalam latihan ini, Anda telah menggunakan Visual Studio untuk membuat proyek Anda. Selanjutnya Anda perlu mengonfigurasi perangkat yang tersambung dengan perangkat. Templat mengharuskan driver Winusb diinstal sebagai driver untuk perangkat Anda.

Lingkungan pengujian dan penelusuran kesalahan Anda dapat memiliki:

  • Dua pengaturan komputer: komputer host dan komputer target. Anda mengembangkan dan membangun proyek di Visual Studio di komputer host. Debugger berjalan di komputer host dan tersedia di antarmuka pengguna Visual Studio. Ketika Anda menguji dan men-debug aplikasi, driver berjalan pada komputer target.

  • Penyiapan komputer tunggal: Target dan host Anda berjalan di satu komputer. Anda mengembangkan dan membangun proyek di Visual Studio, dan menjalankan debugger dan aplikasi.

Anda dapat menyebarkan, menginstal, memuat, dan men-debug aplikasi dan driver Anda dengan mengikuti langkah-langkah berikut:

  • Dua penyetelan komputer

    1. Provisikan komputer target Anda dengan mengikuti instruksi di Menyediakan komputer untuk penyebaran dan pengujian driver. Catatan: Provisi membuat pengguna pada komputer target bernama, WDKRemoteUser. Setelah provisi selesai, Anda akan melihat pengguna beralih ke WDKRemoteUser.
    2. Di komputer host, buka solusi Anda di Visual Studio.
    3. Di main.cpp tambahkan baris ini sebelum panggilan OpenDevice.
    system ("pause")
    

    Baris ini menyebabkan aplikasi dijeda saat diluncurkan. Ini berguna dalam penelusuran kesalahan jarak jauh.

    1. Di pch.h, sertakan baris ini:
    #include <cstdlib>
    

    Ini termasuk pernyataan yang diperlukan untuk system() panggilan di langkah sebelumnya.

    1. Di jendela Penjelajah Solusi, pilih dan tahan (atau klik kanan) Paket Usb Application1, dan pilih Properti.

    2. Di jendela Halaman Properti Paket Usb Application1 , di panel kiri, navigasikan ke Properti > Konfigurasi Penyebaran Penginstalan > Driver, seperti yang ditunjukkan pada cuplikan layar berikut.

    3. Centang Hapus versi driver sebelumnya sebelum penyebaran.

    4. Untuk Nama Komputer Jarak Jauh, pilih nama komputer yang Anda konfigurasi untuk pengujian dan penelusuran kesalahan. Dalam latihan ini, kita menggunakan komputer bernama dbg-target.

    5. Pilih Instal/Instal Ulang dan Verifikasi. Pilih Terapkan.

      penyebaran templat winusb.

    6. Di halaman properti, navigasikan ke Penelusuran Kesalahan Properti > Konfigurasi, dan pilih Alat Penelusuran Kesalahan untuk Windows – Debugger Jarak Jauh, seperti yang ditunjukkan pada cuplikan layar berikut.

      debugger jarak jauh templat winusb.

    7. Pilih Bangun Solusi dari menu Build. Visual Studio menampilkan kemajuan build di jendela Output . (Jika jendela Output tidak terlihat, pilih Output dari menu Tampilan.) Dalam latihan ini, kami telah membangun proyek untuk sistem x64 yang berjalan Windows 10.

    8. Pilih Sebarkan Solusi dari menu Build .

Pada komputer target, Anda akan melihat skrip penginstalan driver berjalan. File driver disalin ke folder %Systemdrive%\drivertest\drivers pada komputer target. Verifikasi bahwa file .inf, .cat, test cert, dan .sys, dan file lain yang diperlukan, ada folder %systemdrive%\drivertest\drivers. Perangkat harus muncul di Manajer Perangkat tanpa kesalahan.

Pada komputer host, Anda akan melihat pesan ini di jendela Output .

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

Untuk men-debug aplikasi

  1. Di komputer host, navigasikan ke x64 > Win8.1Debug di folder solusi.

  2. Salin aplikasi yang dapat dieksekusi, UsbApplication1.exe ke komputer target.

  3. Pada komputer target, luncurkan aplikasi.

  4. Di komputer host, dari menu Debug , pilih Lampirkan ke proses.

  5. Di jendela, pilih Debugger Mode Pengguna Windows (Alat Debugging untuk Windows) sebagai transportasi dan nama komputer target, dalam hal ini dbg-target, sebagai kualifikasi seperti yang ditunjukkan pada gambar ini.

    pengaturan debug templat winusb.

  6. Pilih aplikasi dari daftar Proses yang Tersedia dan pilih Lampirkan. Anda sekarang dapat men-debug menggunakan Jendela Langsung atau dengan menggunakan opsi di menu Debug .

Instruksi sebelumnya men-debug aplikasi dengan menggunakan Alat Debugging untuk Windows – Debugger Jarak Jauh. Jika Anda ingin menggunakan Debugger Windows Jarak Jauh (debugger yang disertakan dengan Visual Studio), ikuti instruksi berikut:

  1. Di komputer target, tambahkan msvsmon.exe ke daftar aplikasi yang diizinkan melalui Firewall.
  2. Luncurkan Monitor Penelusuran Kesalahan Jarak Jauh Visual Studio yang terletak di C:\DriverTest\msvsmon\msvsmon.exe.
  3. Buat folder yang berfungsi, seperti, C:\remotetemp.
  4. Salin aplikasi yang dapat dieksekusi, UsbApplication1.exe ke folder kerja pada komputer target.
  5. Di komputer host, di Visual Studio, klik kanan proyek Paket Usb Application1 , dan pilih Bongkar Proyek.
  6. Pilih dan tahan (atau klik kanan) proyek USB Application1 , di properti proyek perluas simpul Properti Konfigurasi dan pilih Debugging.
  7. Ubah Debugger untuk diluncurkan ke Debugger Windows Jarak Jauh.
  8. Ubah pengaturan proyek untuk menjalankan yang dapat dieksekusi di komputer jarak jauh dengan mengikuti instruksi yang diberikan dalam Penelusuran Kesalahan Jarak Jauh proyek yang Dibangun Secara Lokal. Pastikan bahwa properti Direktori Kerja dan Perintah Jarak Jauh mencerminkan folder pada komputer target.
  9. Untuk men-debug aplikasi, di menu Build , pilih Mulai Debugging, atau tekan F5.
  • Penyiapan komputer tunggal:

    1. Untuk membangun aplikasi anda dan paket penginstalan driver, pilih Build Solution dari menu Build . Visual Studio menampilkan kemajuan build di jendela Output . (Jika jendela Output tidak terlihat, pilih Output dari menu Tampilan.) Dalam latihan ini, kami telah membangun proyek untuk sistem x64 yang berjalan Windows 10.

    2. Untuk melihat paket driver bawaan, navigasikan di Windows Explorer ke folder USB Application1 Anda, lalu navigasikan ke Paket x64 > Debug > USB Application1. Paket driver berisi beberapa file: MyDriver.inf adalah file informasi yang digunakan Windows saat Anda menginstal driver, mydriver.cat adalah file katalog yang digunakan alat penginstal untuk memverifikasi tanda tangan pengujian untuk paket driver. File-file ini ditampilkan dalam cuplikan layar berikut.

      templat aplikasi winusb.

      Tidak ada file driver yang disertakan dalam paket. Itu karena file INF mereferensikan driver dalam kotak, Winusb.sys, ditemukan di folder Windows\System32.

    3. Instal driver secara manual. Di Manajer Perangkat, perbarui driver dengan menentukan INF dalam paket. Arahkan ke paket driver yang terletak di folder solusi, yang ditunjukkan di bagian sebelumnya. Jika Anda melihat kesalahan DriverVer set to a date in the future, atur pengaturan > proyek Paket INF Inf2Cat > Penggunaan Umum > Waktu > Lokal Ya.

    4. Pilih dan tahan (atau klik kanan) proyek USB Application1 , di properti proyek perluas simpul Properti Konfigurasi dan pilih Debugging.

    5. Ubah Debugger untuk diluncurkan ke Windows Debugger Lokal.

    6. Pilih dan tahan (atau klik kanan) proyek Paket USB Application1, dan pilih Bongkar Proyek.

    7. Untuk men-debug aplikasi, di menu Build , pilih Mulai Debugging, atau tekan F5.

Diskusi kode templat

Templat adalah titik awal untuk aplikasi desktop Anda. Proyek USB Application1 memiliki file sumber device.cpp dan main.cpp.

File main.cpp berisi titik entri aplikasi, _tmain. device.cpp berisi semua fungsi pembantu yang membuka dan menutup handel ke perangkat.

Templat juga memiliki file header bernama device.h. File ini berisi definisi untuk GUID antarmuka perangkat (dibahas nanti) dan struktur DEVICE_DATA yang menyimpan informasi yang diperoleh oleh aplikasi. Misalnya, ia menyimpan handel antarmuka WinUSB yang diperoleh oleh OpenDevice dan digunakan dalam operasi berikutnya.

typedef struct _DEVICE_DATA {

    BOOL                    HandlesOpen;
    WINUSB_INTERFACE_HANDLE WinusbHandle;
    HANDLE                  DeviceHandle;
    TCHAR                   DevicePath[MAX_PATH];

} DEVICE_DATA, *PDEVICE_DATA;

Mendapatkan jalur instans untuk perangkat - lihat RetrieveDevicePath di device.cpp

Untuk mengakses perangkat USB, aplikasi membuat handel file yang valid untuk perangkat dengan memanggil CreateFile. Untuk panggilan itu, aplikasi harus mendapatkan instans jalur perangkat. Untuk mendapatkan jalur perangkat, aplikasi menggunakan rutinitas SetupAPI dan menentukan GUID antarmuka perangkat dalam file INF yang digunakan untuk menginstal Winusb.sys. Device.h mendeklarasikan konstanta GUID bernama GUID_DEVINTERFACE_USBApplication1. Dengan menggunakan rutinitas tersebut, aplikasi menghitung semua perangkat di kelas antarmuka perangkat yang ditentukan dan mengambil jalur perangkat perangkat.

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;
}

Dalam fungsi sebelumnya, aplikasi mendapatkan jalur perangkat dengan memanggil rutinitas ini:

  1. SetupDiGetClassDevs untuk mendapatkan handel ke kumpulan informasi perangkat, array yang berisi informasi tentang semua perangkat yang diinstal yang cocok dengan kelas antarmuka perangkat yang ditentukan, GUID_DEVINTERFACE_USBApplication1. Setiap elemen dalam array yang disebut antarmuka perangkat sesuai dengan perangkat yang diinstal dan terdaftar dengan sistem. Kelas antarmuka perangkat diidentifikasi dengan meneruskan GUID antarmuka perangkat yang Anda tentukan dalam file INF. Fungsi mengembalikan handel HDEVINFO ke kumpulan informasi perangkat.

  2. SetupDiEnumDeviceInterfaces untuk menghitung antarmuka perangkat dalam set informasi perangkat dan mendapatkan informasi tentang antarmuka perangkat Anda.

    Panggilan ini memerlukan item berikut:

    • Struktur SP_DEVICE_INTERFACE_DATA yang dialokasikan penelepon yang diinisialisasi yang memiliki anggota cbSize diatur ke ukuran struktur.

    • Handel HDEVINFO dari langkah 1.

    • GUID antarmuka perangkat yang Anda tentukan dalam file INF.

      SetupDiEnumDeviceInterfaces mencari array kumpulan informasi perangkat untuk indeks antarmuka perangkat yang ditentukan dan mengisi struktur SP_DEVICE_INTERFACE_DATA yang diinisialisasi dengan data dasar tentang antarmuka.

    Untuk menghitung semua antarmuka perangkat dalam kumpulan informasi perangkat, panggil SetupDiEnumDeviceInterfaces dalam perulangan hingga fungsi mengembalikan FALSE dan kode kesalahan untuk kegagalan ERROR_NO_MORE_ITEMS. Kode kesalahan ERROR_NO_MORE_ITEMS dapat diambil dengan memanggil GetLastError. Dengan setiap perulangan, tingkatkan indeks anggota.

    Secara bergantian, Anda dapat memanggil SetupDiEnumDeviceInfo yang menghitung kumpulan informasi perangkat dan mengembalikan informasi tentang elemen antarmuka perangkat, yang ditentukan oleh indeks, dalam struktur SP_DEVINFO_DATA yang dialokasikan pemanggil. Anda kemudian dapat meneruskan referensi ke struktur ini di parameter DeviceInfoData dari fungsi SetupDiEnumDeviceInterfaces .

  3. SetupDiGetDeviceInterfaceDetail untuk mendapatkan data terperinci untuk antarmuka perangkat. Informasi dikembalikan dalam struktur SP_DEVICE_INTERFACE_DETAIL_DATA . Karena ukuran struktur SP_DEVICE_INTERFACE_DETAIL_DATA bervariasi, SetupDiGetDeviceInterfaceDetail dipanggil dua kali. Panggilan pertama mendapatkan ukuran buffer untuk dialokasikan untuk struktur SP_DEVICE_INTERFACE_DETAIL_DATA . Panggilan kedua mengisi buffer yang dialokasikan dengan informasi terperinci tentang antarmuka.

    1. Memanggil SetupDiGetDeviceInterfaceDetail dengan parameter DeviceInterfaceDetailData diatur ke NULL. Fungsi mengembalikan ukuran buffer yang benar dalam parameter requiredlength . Panggilan ini gagal dengan kode kesalahan ERROR_INSUFFICIENT_BUFFER. Kode galat ini diharapkan.
    2. Mengalokasikan memori untuk struktur SP_DEVICE_INTERFACE_DETAIL_DATA berdasarkan ukuran buffer yang benar yang diambil dalam parameter requiredlength .
    3. Memanggil SetupDiGetDeviceInterfaceDetail lagi dan meneruskannya referensi ke struktur yang diinisialisasi dalam parameter DeviceInterfaceDetailData . Ketika fungsi kembali, struktur diisi dengan informasi terperinci tentang antarmuka. Jalur perangkat berada di anggota DevicePath struktur SP_DEVICE_INTERFACE_DETAIL_DATA.

Membuat handel file untuk perangkat

Lihat OpenDevice di device.cpp.

Untuk berinteraksi dengan perangkat, diperlukan handel antarmuka WinUSB ke antarmuka pertama (default) pada perangkat. Kode templat mendapatkan handel file dan handel antarmuka WinUSB dan menyimpannya dalam struktur 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. Aplikasi memanggil CreateFile untuk membuat handel file untuk perangkat dengan menentukan jalur perangkat yang diambil sebelumnya. Ini menggunakan bendera FILE_FLAG_OVERLAPPED karena WinUSB tergantung pada pengaturan ini.
  2. Dengan menggunakan handel file untuk perangkat, aplikasi membuat handel antarmuka WinUSB. Fungsi WinUSB menggunakan handel ini untuk mengidentifikasi perangkat target alih-alih handel file. Untuk mendapatkan handel antarmuka WinUSB, aplikasi memanggil WinUsb_Initialize dengan melewati handel file. Gunakan handel yang diterima dalam panggilan berikutnya untuk mendapatkan informasi dari perangkat, dan untuk mengirim permintaan I/O ke perangkat.

Merilis handel perangkat - lihat CloseDevice di device.cpp

Kode templat mengimplementasikan kode untuk merilis handel file dan handel antarmuka WinUSB untuk perangkat.

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;
}

Langkah berikutnya

Selanjutnya, baca topik ini untuk mengirim dapatkan informasi perangkat dan kirim transfer data ke perangkat: