Windows下怎么用VS打开自定义HID设备?
无论是HID设备还是其它USB或PCIE设备,在windows下都是通过CreateFile来打开的。
使用CreateFile打开设备,一个重要的参数就是设备的名称,这个是可以通过SetupApi函数来获取的。
下面的一个示例是枚举系统中所有的HID设备,并偿试打开,然后获取设备的一些属性信息如PID,VID,报表描述符的数据的长度等。
注意:
这里为什么说是要偿试打开了?这是因为并不是所有的HID设备都可以打开的,像一些独占设备如键盘,鼠标,是无法打开的。但是可以打开自定义通讯的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;
}
_tprintf(TEXT("%d %s\n"), i, strDevicePath);
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;
}
if (Attributes.VendorID != 0x1234)
{
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))
{
}
}
}
在我的电脑中运行的结果如下:
0 \\?\hid#intc816&col06#3&dc5eada&0&0005#{4d1e55b2-f16f-11cf-88cb-001111000030}
1 \\?\hid#vid_12d1&pid_3a07&mi_03#7&288cea76&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
2 \\?\hid#intc816&col0b#3&dc5eada&0&000a#{4d1e55b2-f16f-11cf-88cb-001111000030}
3 \\?\hid#intc816&col12#3&dc5eada&0&0011#{4d1e55b2-f16f-11cf-88cb-001111000030}
4 \\?\hid#intc816&col07#3&dc5eada&0&0006#{4d1e55b2-f16f-11cf-88cb-001111000030}
5 \\?\hid#intc816&col0c#3&dc5eada&0&000b#{4d1e55b2-f16f-11cf-88cb-001111000030}
6 \\?\hid#intc816&col02#3&dc5eada&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}
7 \\?\hid#intc816&col08#3&dc5eada&0&0007#{4d1e55b2-f16f-11cf-88cb-001111000030}
8 \\?\hid#intc816&col0d#3&dc5eada&0&000c#{4d1e55b2-f16f-11cf-88cb-001111000030}
9 \\?\hid#intc816&col03#3&dc5eada&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}
10 \\?\hid#intc816&col0a#3&dc5eada&0&0009#{4d1e55b2-f16f-11cf-88cb-001111000030}
11 \\?\hid#intc816&col09#3&dc5eada&0&0008#{4d1e55b2-f16f-11cf-88cb-001111000030}
12 \\?\hid#intc816&col01#3&dc5eada&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}\kbd
13 \\?\hid#intc816&col0e#3&dc5eada&0&000d#{4d1e55b2-f16f-11cf-88cb-001111000030}
14 \\?\hid#dell097b&col03#5&38169fd1&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}
15 \\?\hid#dell097b&col04#5&38169fd1&0&0003#{4d1e55b2-f16f-11cf-88cb-001111000030}
16 \\?\hid#intc816&col04#3&dc5eada&0&0003#{4d1e55b2-f16f-11cf-88cb-001111000030}
17 \\?\hid#converteddevice&col02#5&4a30443&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}
18 \\?\hid#intc816&col0f#3&dc5eada&0&000e#{4d1e55b2-f16f-11cf-88cb-001111000030}
19 \\?\hid#converteddevice&col01#5&4a30443&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}\kbd
20 \\?\hid#intc816&col05#3&dc5eada&0&0004#{4d1e55b2-f16f-11cf-88cb-001111000030}
21 \\?\hid#vid_093a&pid_2510#6&26d999e3&2&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
22 \\?\hid#intc816&col10#3&dc5eada&0&000f#{4d1e55b2-f16f-11cf-88cb-001111000030}
23 \\?\hid#converteddevice&col03#5&4a30443&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}
24 \\?\hid#intc816&col11#3&dc5eada&0&0010#{4d1e55b2-f16f-11cf-88cb-001111000030}
No SP_INTERFACE_DEVICE_DATA available for this GUID instance