WinUSB
+ -

WinUSB枚举和打开设备

2022-05-11 2026 0

打开设备之前,得先枚举到设备,获取到设备的链接名,然后才能通过CreateFile打开设备,与之通讯。

设备接口GUID

枚举设备是通过winsub驱动的inf文件中的DeviceInterfaceGUIDs来实现的。在WinUSB驱动设备时,会使用该GUID来注册设备接口,所以我们也需要此接口来枚举设备。

DeviceInterfaceGUIDs由用户定义,在该设备的inf文件中,如:

[ADB.HW.AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{5E9DCF7E-5A2A-49C9-A992-704D47B92CF2}"

枚举设备

枚举设备可以通过SetupAPI函数来实现,也可以使用CM系列函数实现。
SetupAPI函数我们比较熟悉,其代码可以参考:http://www.usbzh.com/article/detail-111.html

CM函数是比较新的一套API,最新的WDK10生成应用层示例代码时,自动生成:


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

--*/
{
    CONFIGRET cr = CR_SUCCESS;
    HRESULT   hr = S_OK;
    PTSTR     DeviceInterfaceList = NULL;
    ULONG     DeviceInterfaceListLength = 0;

    if (NULL != FailureDeviceNotFound) {

        *FailureDeviceNotFound = FALSE;
    }

    //
    // Enumerate all devices exposing the interface. Do this in a loop
    // in case a new interface is discovered while this code is executing,
    // causing CM_Get_Device_Interface_List to return CR_BUFFER_SMALL.
    //
    do {
        cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListLength,
                                               (LPGUID)&GUID_DEVINTERFACE_WINUSB,
                                               NULL,
                                               CM_GET_DEVICE_INTERFACE_LIST_PRESENT);

        if (cr != CR_SUCCESS) {
            hr = HRESULT_FROM_WIN32(CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA));
            break;
        }

        DeviceInterfaceList = (PTSTR)HeapAlloc(GetProcessHeap(),
                                               HEAP_ZERO_MEMORY,
                                               DeviceInterfaceListLength * sizeof(TCHAR));

        if (DeviceInterfaceList == NULL) {
            hr = E_OUTOFMEMORY;
            break;
        }

        cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_WINUSB,
                                          NULL,
                                          DeviceInterfaceList,
                                          DeviceInterfaceListLength,
                                          CM_GET_DEVICE_INTERFACE_LIST_PRESENT);

        if (cr != CR_SUCCESS) {
            HeapFree(GetProcessHeap(), 0, DeviceInterfaceList);

            if (cr != CR_BUFFER_SMALL) {
                hr = HRESULT_FROM_WIN32(CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA));
            }
        }
    } while (cr == CR_BUFFER_SMALL);

    if (FAILED(hr)) {
        return hr;
    }

    //
    // If the interface list is empty, no devices were found.
    //
    if (*DeviceInterfaceList == TEXT('\0')) {
        if (NULL != FailureDeviceNotFound) {
            *FailureDeviceNotFound = TRUE;
        }

        hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceList);
        return hr;
    }

    //
    // Give path of the first found device interface instance to the caller. CM_Get_Device_Interface_List ensured
    // the instance is NULL-terminated.
    //
    hr = StringCbCopy(DevicePath,
                      BufLen,
                      DeviceInterfaceList);

    HeapFree(GetProcessHeap(), 0, DeviceInterfaceList);

    return hr;
}

这里的GUID_DEVINTERFACE_WINUSB就是DeviceInterfaceGUIDs。

打开设备

打开设备比较简单,就是CreateFile。

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;
}
HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

使用SetupApi函数通过GUID枚举系统中所有关联设备
Windows的设备在驱动中大部分都会IoSetRegisterInterface,这其中一个重要的参数是GUID,这样系统会根据这个GUID给设备创建一个symbolicname,这个名字在应用层可以通过CreateFile打开。这里分享一个在应用层通过SetuApi枚举该类型GUID下的所有设备......
使用WinUSB读写USB设备
Windows为WinUSB设备提供了API,主要通过以下几个步骤访问设备。通过扩展描述符中的GUID查看接口的路径用接口的路径作为参数,调用CreateFile打开接口使用WinUsb_Initialize得到WinUSB句柄通过WinUsb_WritePipe和WinUsb_ReadPipe对......
windows通过GUID枚举系统中所有USB设备并且显示该设备的所有属性信息
微信群里有同学问怎么获取USB设备的位置信息,这个学名叫做SPDRP_LOCATION_PATHS,刚好自己以前写过这个代码,就分享了一下。代码如下:#include#include #include
打开设备之前,得先枚举到设备,获取到设备的链接名,然后才能通过CreateFile打开设备,与之通讯。设备接口GUID枚举设备是通过winsub驱动的inf文件中的DeviceInterfaceGUIDs来实现的。在WinUSB驱动设备时,会使用该GUID来注册设备接口,所以我们也需要此接口来枚举......
主要还是SetupAPI函数的封装#include <SetupAPI.h>//获取设备的实例路径HRESULTRetrieveDevicePath( _Out_bytecap_(BufLen) LPTSTR DevicePath, _In_ ......
话不多说,直接使用可以正常运行的。#include #include #include #include #include #inclu......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!