【问题标题】:Use Windows SetupAPI to get USB Device Descriptor使用 Windows SetupAPI 获取 USB 设备描述符
【发布时间】:2017-09-08 10:15:30
【问题描述】:

我想知道是否可以使用 SetupAPI 函数(如 SetupDiGetDeviceRegistryProperty)获取 USB 设备描述符? 谢谢!

编辑

目前我只能收到windows 友好的名称:

SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC,
            &dwPropertyRegDataType, (BYTE*)szDesc, sizeof(szDesc), &dwSize)

【问题讨论】:

  • 你有什么输入?
  • @RbMm 我收到的是驱动程序中的名称,而不是使用上述代码的 USB 设备描述符。
  • 我问 - 你一开始有什么数据。
  • 你能详细说明你的意思是什么数据吗?我有hDevInfo,我从hDevInfo = SetupDiGetClassDevs((LPGUID)&oGUID, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));得到的

标签: windows setupapi


【解决方案1】:

我们需要有/得到代表设备的Device Instance ID 的字符串。有了这个,我们首先通过CM_Locate_DevNode获取设备节点的设备实例句柄,然后用DEVPKEY_NAME调用CM_Get_DevNode_Property:

检索到的属性值与 DEVPKEY_Device_FriendlyName 设备属性,如果 DEVPKEY_Device_FriendlyName 已设置。否则,值 DEVPKEY_NAME 与 DEVPKEY_Device_DeviceDesc 的值相同 设备属性。

static volatile UCHAR guz;

CONFIGRET PrintFriendlyNameByDeviceID(PWSTR DeviceID)
{
    DEVINST dnDevInst;

    CONFIGRET status = CM_Locate_DevNodeW(&dnDevInst, DeviceID, CM_LOCATE_DEVNODE_NORMAL);

    if (status == CR_SUCCESS)
    {
        ULONG cb = 0, rcb = 16;

        PVOID stack = alloca(guz);

        DEVPROPTYPE PropertyType;

        union {
            PVOID pv;
            PWSTR sz;
            PBYTE pb;
        };

        do 
        {
            if (cb < rcb)
            {
                rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
            }

            status = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_NAME, &PropertyType, pb, &rcb, 0);

            if (status == CR_SUCCESS)
            {
                if (PropertyType == DEVPROP_TYPE_STRING)
                {
                    DbgPrint("NAME = %S\n", sz);
                }
                else
                {
                    status = CR_WRONG_TYPE;
                }
            }

        } while (status == CR_BUFFER_SMALL);
    }

    return status;
}

如果我们有标识设备接口实例的字符串 - 我们可以通过调用CM_Get_Device_Interface_Property 和DEVPKEY_Device_InstanceId 键从中获取设备实例标识符,然后调用PrintFriendlyNameByDeviceID

CONFIGRET PrintFriendlyNameByInterface(PCWSTR pszDeviceInterface)
{
    ULONG cb = 0, rcb = 64;

    PVOID stack = alloca(guz);
    DEVPROPTYPE PropertyType;

    CONFIGRET status;

    union {
        PVOID pv;
        PWSTR DeviceID;
        PBYTE pb;
    };

    do 
    {
        if (cb < rcb)
        {
            rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
        }

        status = CM_Get_Device_Interface_PropertyW(pszDeviceInterface, &DEVPKEY_Device_InstanceId, &PropertyType, pb, &rcb, 0);

        if (status == CR_SUCCESS)
        {
            if (PropertyType == DEVPROP_TYPE_STRING)
            {
                DbgPrint("DeviceID = %S\n", DeviceID);

                status = PrintFriendlyNameByDeviceID(DeviceID);
            }
            else
            {
                status = CR_WRONG_TYPE;
            }

            break;
        }

    } while (status == CR_BUFFER_SMALL);

    return status;
}

一开始我们有 2 个选择:通过调用 CM_Get_Device_ID_List 和 CM_GETIDLIST_FILTER_CLASS|CM_GETIDLIST_FILTER_PRESENT 检索设备实例 ID 列表,并使用 "{36fc9e60-c465-11cf-8056-444553540000}" 作为过滤器 - 这是在 @ 中定义的众所周知的 GUID_DEVCLASS_USB 的字符串表示987654342@:

void PrintFriendlyNames(PCWSTR pszFilter)
{
    CONFIGRET status;
    ULONG len = 0, cb = 0, rcb;
    PVOID stack = alloca(guz);
    PWSTR buf = 0;

    do 
    {
        if (status = CM_Get_Device_ID_List_SizeW(&len, pszFilter, CM_GETIDLIST_FILTER_CLASS|CM_GETIDLIST_FILTER_PRESENT))
        {
            break;
        }

        if (cb < (rcb = len * sizeof(WCHAR)))
        {
            len = (cb = RtlPointerToOffset(buf = (PWSTR)alloca(rcb - cb), stack)) / sizeof(WCHAR);
        }

        status = CM_Get_Device_ID_ListW(pszFilter, buf, len, CM_GETIDLIST_FILTER_CLASS|CM_GETIDLIST_FILTER_PRESENT);

        if (status == CR_SUCCESS)
        {
            while (*buf)
            {
                DbgPrint("DeviceID = %S\n", buf);

                PrintFriendlyNameByDeviceID(buf);

                buf += 1 + wcslen(buf);
            }
        }

    } while (status == CR_BUFFER_SMALL);
}
PrintFriendlyNames(L"{36fc9e60-c465-11cf-8056-444553540000}");

或通过CM_Get_Device_Interface_List 枚举设备接口并为每个设备接口调用PrintFriendlyNameByInterface。

void PrintFriendlyNames(PGUID InterfaceClassGuid)
{
    CONFIGRET status;
    ULONG len = 0, cb = 0, rcb;
    PVOID stack = alloca(guz);
    PWSTR buf = 0;

    do 
    {
        if (status = CM_Get_Device_Interface_List_SizeW(&len, InterfaceClassGuid, 0, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
        {
            break;
        }

        if (cb < (rcb = len * sizeof(WCHAR)))
        {
            len = (cb = RtlPointerToOffset(buf = (PWSTR)alloca(rcb - cb), stack)) / sizeof(WCHAR);
        }

        status = CM_Get_Device_Interface_ListW(InterfaceClassGuid, 0, buf, len, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);

        if (status == CR_SUCCESS)
        {
            while (*buf)
            {
                DbgPrint("Interface = %S\n", buf);

                PrintFriendlyNameByInterface(buf);

                buf += 1 + wcslen(buf);
            }
        }

    } while (status == CR_BUFFER_SMALL);
}

你可以说GUID_DEVINTERFACE_USB_DEVICE

PrintFriendlyNames(const_cast<PGUID>(&GUID_DEVINTERFACE_USB_DEVICE));

列出的方法(哪些设备/接口)的结果可能不同。通过GUID_DEVINTERFACE_USB_DEVICE 枚举时说 om my comp:

Interface = \\?\USB#VID_046D&PID_C52E#5&18d671f8&0&4#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
DeviceID = USB\VID_046D&PID_C52E\5&18d671f8&0&4
NAME = USB Composite Device
Interface = \\?\USB#VID_051D&PID_0002#5B1120T12418__#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
DeviceID = USB\VID_051D&PID_0002\5B1120T12418__
NAME = American Power Conversion USB UPS
Interface = \\?\USB#VID_045E&PID_077B#5&18d671f8&0&3#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
DeviceID = USB\VID_045E&PID_077B\5&18d671f8&0&3
NAME = USB Input Device

当通过GUID_DEVCLASS_USB 字符串过滤器枚举时:

DeviceID = USB\VID_1F75&PID_0916\120709860570000024
NAME = USB Mass Storage Device
DeviceID = USB\ROOT_HUB30\4&33ed72c&0&0
NAME = USB Root Hub (xHCI)
DeviceID = USB\VID_0951&PID_168F\001A92053B6A0CA101340008
NAME = USB Mass Storage Device
DeviceID = PCI\VEN_8086&DEV_A2AF&SUBSYS_7A741462&REV_00\3&11583659&0&A0
NAME = Intel(R) USB 3.0 eXtensible Host Controller - 1.0 (Microsoft)
DeviceID = USB\VID_046D&PID_C52E\5&18d671f8&0&4
NAME = USB Composite Device

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 2014-12-19
    • 2018-10-12
    相关资源
    最近更新 更多