建设个人商城网站,系统开发的特点有,天天作文网,中卫网红大型蹦床设备libusb 当前版本#xff08;1.0.26#xff09;libusb.h 头文件提供的接口似乎没有办法获取 Windows 平台相关的设备实例路径#xff0c;其形如#xff1a;
\\?\usb#vid_04capid_7070#520d34a7606#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
只是提供了…libusb 当前版本1.0.26libusb.h 头文件提供的接口似乎没有办法获取 Windows 平台相关的设备实例路径其形如
\\?\usb#vid_04capid_7070#520d34a7606#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
只是提供了 libusb_get_port_numbers 之类的接口来获取拓扑结构。
我们可以通过 libusb 源码中平台相关的接口来获取DevicePath但是使用非公有接口意味着替换版本的时候要注意源码相关的修改。目前找了两种方式
1.通过 winusb_device_priv 结构体中的 path 获取
通过 libusbi.h 头文件中的 usbi_get_device_priv 函数获取 libusb_device 对应的平台相关的数据结构对应到 windows 平台就是 winusb_device_priv其包含的 path 字段就是存放DevicePath。
#include libusb.h
#include libusbi.hvoid enum_device()
{libusb_init(NULL);libusb_device **device_list;int count libusb_get_device_list(NULL, device_list);for(int i 0 ; i count; i){libusb_device_descriptor desc;int ret libusb_get_device_descriptor(device_list[i], desc);if (ret ! LIBUSB_SUCCESS) {continue;}winusb_device_priv *priv (winusb_device_priv*)usbi_get_device_priv(device_list[i]);if (priv) {fprintf(stderr, Device %d path: %s.\n, i, priv-path);}}libusb_free_device_list(device_list, 1);libusb_exit(NULL);
}
从 usbi_get_device_priv 函数推测公有结构和平台相关结构在内存上是紧挨着的
#define PTR_ALIGN(v) (((v) (sizeof(void *) - 1)) ~(sizeof(void *) - 1))static inline void *usbi_get_device_priv(struct libusb_device *dev)
{return (unsigned char *)dev PTR_ALIGN(sizeof(*dev));
}
获取 DevicePath 的过程在 windows_winusb.c 的 winusb_get_device_list 和 get_interface_details 函数使用的 SetupAPI 系列的接口来获取的。有一点需要注意获取到的 path 内部转换成了大写见 normalize_path 函数实现。
不修改库源码而是直接使用私有接口需要用到的源码文件 其中 config.h 文件来自于源码的 msvc 文件夹。
可能会遇到类型转换报错自己做下显式转换即可。 2.通过 libusb_device 结构体中的 session_data 和 Windows 的 DevInst 比较
session_data 在 windows 平台上目前就是存储的 SP_DEVINFO_DATA 结构的 DevInst 值。相较于第一种方式我们需要再次用 SetupAPI 的接口枚举一遍设备信息然后判断 session_data 和 DevInst 是否相等相等时就可以用 Win32 接口获取 DevicePath 了。
libusb_device 结构体定义在 libusbi.h 头文件。
#include stdio.h
#include Windows.h
#include SetupAPI.h
#pragma comment(lib, SetupAPI.lib)
#include devguid.h
// 具体的设备 GUID 需要 initguid, 如 usbiodef
#include initguid.h
// USB 设备
// GUID_DEVINTERFACE_USB_DEVICE
#include usbiodef.hvoid enum_device()
{// HDEVINFO 标识设备信息集HDEVINFO info_set;// SetupDiGetClassDevs 返回包含本地计算机请求的设备信息元素的设备信息集的句柄// 接口文档https://learn.microsoft.com/zh-cn/windows/win32/api/setupapi/nf-setupapi-setupdigetclassdevsa// 若要返回支持任何类的设备接口的设备设置 DIGCF_DEVICEINTERFACE 和 DIGCF_ALLCLASSES 标志然后将 ClassGuid 设置为 NULL//info_set SetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);// 若要仅返回支持指定类的设备接口的设备设置 DIGCF_DEVICEINTERFACE 标志并使用 ClassGuid 参数提供设备接口类的类 GUID// 实际使用对应设备的 GUIDGUID device_guid{GUID_DEVINTERFACE_USB_DEVICE};info_set SetupDiGetClassDevsA(device_guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);// 如果操作失败返回 INVALID_HANDLE_VALUEif (info_set INVALID_HANDLE_VALUE) {fprintf(stderr, SetupDiGetClassDevs: [err code] %d.\n, GetLastError());return;}// SP_DEVINFO_DATA 标识设备信息集中的设备SP_DEVINFO_DATA info_data { 0 };info_data.cbSize sizeof(info_data);// SetupDiEnumDeviceInfo 枚举设备信息for (int index 0; SetupDiEnumDeviceInfo(info_set, index, info_data); index){fprintf(stderr, Device %d %d:\n, index, info_data.DevInst);// 获取设备实例路径// SP_DEVICE_INTERFACE_DATA 设备信息集中的设备接口SP_DEVICE_INTERFACE_DATA interface_data { 0 };interface_data.cbSize sizeof(interface_data);// SetupDiEnumDeviceInterfaces 枚举包含在设备信息集中的设备接口BOOL ret SetupDiEnumDeviceInterfaces(info_set, NULL, (LPGUID)device_guid, index, interface_data);if (!ret) continue;ULONG required_len 0;// SetupDiGetDeviceInterfaceDetail 返回有关设备接口的详细信息// 第一次调用是获取长度这里是返回falseSetupDiGetDeviceInterfaceDetailA(info_set, interface_data, NULL, 0, required_len, NULL);if (required_len 0) continue;ULONG predicted_len required_len;// SP_INTERFACE_DEVICE_DETAIL_DATA 包含设备接口的路径SP_INTERFACE_DEVICE_DETAIL_DATA_A detail_data { 0 };detail_data.cbSize sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA_A);// 检索即插即用设备信息if (SetupDiGetDeviceInterfaceDetailA(info_set,interface_data,detail_data,predicted_len,required_len,info_data)) {fprintf(stderr, Device Instance Path: %s.\n, detail_data.DevicePath);}}// SetupDiDestroyDeviceInfoList 删除设备信息集并释放所有关联的内存SetupDiDestroyDeviceInfoList(info_set);
}