问题描述
概述...
我已经阅读了 How to get device interface GUID for a device? 和 How to open a handle to a device using its Device Instance ID?,但我仍然对如何(或者我是否应该)使用 SetupDiEnumDeviceInterfaces 和 SetupDiGetDeviceInterfaceDetail 配对感到困惑获取一个 DevicePath,当不知道 device interface class GUID 时,可以使用 CreateFile 打开它以访问设备。我的问题基于依赖这些函数的 MSDN 文章 here 和 here。
更多详情...
我的问题最严重的是我有一个音频 USB 设备,我需要发送控制传输命令。为此,我想使用 WinUSB 的 API,并且要做到这一点,我需要通过 CreateFile 获取设备句柄。不幸的是,没有与设备关联的 .inf 文件,因此没有已知的设备接口类 GUID。如果插入设备,Windows 会将其关联为 usbaudio.sys 作为驱动程序。为了开始讨论 WinUSB,我使用 libwdi 安装 WinUSB 作为设备驱动程序,以便我可以通过 WinUSB API 与它通信。为了完成 WinUSB 的安装,libwdi 动态创建了一个自签名的 .cat 和 .inf 文件对,遗憾的是没有定义设备接口类。其实INF文件里面有以下内容:
[NoDeviceInterfaceGUID]
; Avoids adding a DeviceInterfaceGUID for generic driver
因此,尽管我现在已将 usbaudio.sys 换成 winusb.sys,但我无法与设备通信。
起初我想也许我应该尝试使用 GUID_DEVINTERFACE_USB_DEVICE,理由是这是 WinUSB,因此被视为通用 USB 设备。但是,如果我调用
SetupDiEnumDeviceInterfaces(_deviceList,&devInfo,&GUID_DEVINTERFACE_USB_DEVICE,&usbInterface)
失败并且 GetLastError 立即返回 259 或 ERROR_NO_MORE_ITEMS。我假设这意味着它没有实现接口?
那么,一般来说,当不知道接口类 guid 时,我是否能够以任何形式使用上述函数来获取完整的设备路径? 提前感谢您抽出宝贵时间。
解决方法
是的,首先您需要为通过 SetupDiGetClassDevs
实现接口的设备获取一个设备信息集,然后选择其中一个设备并读取其设备接口数据,并使用它获取包含设备路径的设备接口详细信息。
示例:
#include <windows.h>
#include <setupapi.h>
#include <initguid.h>
#include <usbioctl.h>
#include <stdio.h>
BOOL DevicePath(_In_ LPCGUID interfaceGuid,DWORD instance)
{
BOOL result = FALSE;
PSP_DEVICE_INTERFACE_DETAIL_DATA_W devInterfaceDetailData = NULL;
HDEVINFO hDevInfo = SetupDiGetClassDevsW(interfaceGuid,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(hDevInfo == INVALID_HANDLE_VALUE)
goto cleanup;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
if(!SetupDiEnumDeviceInterfaces(hDevInfo,interfaceGuid,instance,&devInterfaceData))
goto cleanup;
// Call this with an empty buffer to the required size of the structure.
ULONG requiredSize;
SetupDiGetDeviceInterfaceDetailW(hDevInfo,&devInterfaceData,&requiredSize,NULL);
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto cleanup;
devInterfaceDetailData = malloc(requiredSize);
if(!devInterfaceDetailData)
goto cleanup;
devInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if(!SetupDiGetDeviceInterfaceDetailW(hDevInfo,devInterfaceDetailData,requiredSize,NULL))
goto cleanup;
wprintf(L"%s\n",devInterfaceDetailData->DevicePath);
result = TRUE;
cleanup:
if(hDevInfo != INVALID_HANDLE_VALUE)
SetupDiDestroyDeviceInfoList(hDevInfo);
free(devInterfaceDetailData);
return result;
}
int main()
{
for(DWORD i = 0; DevicePath(&GUID_DEVINTERFACE_USB_DEVICE,i); ++i)
;
}