Windows下枚举系统中所有HID设备
2020-10-29
3726
3
Windows下对任何设备,文件的打开都是通过CreateFile来实现的,不过要打开一个设备得首先知道设备或文件名。
由上节可知道,对于HID设备,都会注册一个接口类型为{2ACCFE60-C130-11D2-B082-00A0C91EFB8B}的GUID。我们可以通过Setup系列函数枚举出系统中所有的HID设备,然后再根据其属信息判断(如PID,VID,报告描述符长度等)来进行过滤。
枚举系统中所有HID设备信息代码示例
#include<windows.h>
#include <winioctl.h>
#include <setupapi.h>
#include <initguid.h>
#include <stdio.h>
#include<hidsdi.h>
#include<tchar.h>
#pragma comment(lib,"Setupapi.lib ")
#pragma comment(lib,"hid.lib ")
BOOL USBEnumDevice(OUT PTCHAR pDeviceName, IN LPGUID pGuid,IN int instance)
{
HDEVINFO info = SetupDiGetClassDevs((GUID*)pGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
if (info == INVALID_HANDLE_VALUE)
{
printf("No HDEVINFO available for this GUID\n");
return FALSE;
}
// Get interface data for the requested instance
SP_INTERFACE_DEVICE_DATA ifdata;
ifdata.cbSize = sizeof(ifdata);
if (!SetupDiEnumDeviceInterfaces(info, NULL, (GUID*)pGuid, instance, &ifdata))
{
_tprintf(TEXT("No SP_INTERFACE_DEVICE_DATA available for this GUID instance\n"));
SetupDiDestroyDeviceInfoList(info);
return FALSE;
}
// Get size of symbolic link name
DWORD ReqLen;
SetupDiGetDeviceInterfaceDetail(info, &ifdata, NULL, 0, &ReqLen, NULL);
PSP_INTERFACE_DEVICE_DETAIL_DATA ifDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)(new TCHAR[ReqLen]);
if (ifDetail == NULL)
{
SetupDiDestroyDeviceInfoList(info);
return FALSE;
}
// Get symbolic link name
ifDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(info, &ifdata, ifDetail, ReqLen, NULL, NULL))
{
SetupDiDestroyDeviceInfoList(info);
delete ifDetail;
return FALSE;
}
//printf("Symbolic link is %s\n", ifDetail->DevicePath);
memcpy(pDeviceName, ifDetail->DevicePath, _tcslen(ifDetail->DevicePath) * sizeof(TCHAR));
pDeviceName[_tcslen(ifDetail->DevicePath)] = TEXT('\0');
delete [] ifDetail;
SetupDiDestroyDeviceInfoList(info);
return TRUE;
}
int main()
{
GUID hidGuid;
::HidD_GetHidGuid((LPGUID)&hidGuid); // 取HID设备GUID
for (int i = 0;; i++)
{
TCHAR strDevicePath[512] = { 0 };
if (!USBEnumDevice(strDevicePath, &hidGuid, i))
{
break;
}
HANDLE tmp_DeviceHandle = CreateFile(strDevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (tmp_DeviceHandle == INVALID_HANDLE_VALUE)
{
CloseHandle(tmp_DeviceHandle);
continue;
}
//=============== Get Attribute ===============
HIDD_ATTRIBUTES Attributes;
ZeroMemory(&Attributes, sizeof(Attributes));
Attributes.Size = sizeof(HIDD_ATTRIBUTES);
if (!HidD_GetAttributes(tmp_DeviceHandle, &Attributes))
{
CloseHandle(tmp_DeviceHandle);
continue;
}
_tprintf(TEXT("%d %s\n"), i, strDevicePath);
_tprintf(TEXT("Vendor ID: %04x, Product ID:%04x\n"), Attributes.VendorID, Attributes.ProductID);
/////////////////////////////////
ULONG bufferLength = 126;
TCHAR ProductString[126] = { 0 };;
if (!HidD_GetProductString(tmp_DeviceHandle, ProductString, bufferLength))
{
CloseHandle(tmp_DeviceHandle);
continue;
}
//=============== Get Capabilities ===============
PHIDP_PREPARSED_DATA PreparsedData;
if (!HidD_GetPreparsedData(tmp_DeviceHandle, &PreparsedData))
{
CloseHandle(tmp_DeviceHandle);
printf("Cannot get the Preparsed Data...\n");
continue;
}
HIDP_CAPS ReturnCapabilities;
if (!HidP_GetCaps(PreparsedData, &ReturnCapabilities))
{
CloseHandle(tmp_DeviceHandle);
printf("Cannot get the Cap Data...\n");
continue;
}
// Normal USB Device
if ((ReturnCapabilities.OutputReportByteLength == 0x40) &&
(ReturnCapabilities.InputReportByteLength == 0x40) &&
(ReturnCapabilities.Usage == 0x0001) &&
(ReturnCapabilities.UsagePage == 0xFF00))
{
}
}
}
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936