前段时间在WIN10系统+VS2017环境下安装了USB开发的驱动环境(详见我的博客【如何在win10+VS2017环境下安装USB驱动开发套件WDK】),今天介绍一下如何建立一个简单的HID设备枚举工程。文中的工程使用VS2017社区版建立和编译,文中对整个工程的建立、配置、编码过程进行了详细的介绍,大家可以参照自己执行。如果觉得麻烦,也可以点击此处【CSDN下载压缩包】直接下载我编辑好的整个工程,或者直接去我的码云克隆,地址是【https://gitee.com/leon1741/MyFirstHIDTest】。不过建议大家去码云里克隆,因为这里的代码我会随时保持更新,而CSDN上的压缩包则是最早的版本。
步骤1、新建工程
新建一个空白项目即可。工程名称我输入的是MyFirstHIDTest,大家可以自定义修改。
工程建好之后,新建一个cpp源码文件:
源码文件名我输入的也是MyFirstHIDTest.cpp,大家可以自定义修改。
步骤2:工程设置
工程建好之后,要对工程进行一些设置:
1、设置工程的字符集为多字节字符集,以免后面编译代码时出现问题。
2、添加必要的依赖库(hid.lib;setupapi.lib):
步骤3、编写代码
输入以下代码:
#include <windows.h>
#include <stdio.h>
#include <winnt.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <hidsdi.h>
#include <setupapi.h>
/*********************************************************************************************************************/
// 模块宏定义
/*********************************************************************************************************************/
#define OVERLAP_MODE 0 /* 是否要启用重叠异步模式打开HID设备文件 */
/*********************************************************************************************************************/
// 函数功能:主函数 - 用来列举出系统中所有可用的HID设备信息,并尝试打开他们获取其属性(有可能会打开失败)
// 输入参数:
// 输出参数:
// 返回参数:
/*********************************************************************************************************************/
int main(int argc, char** argv)
{
int deviceNo;
bool result;
HANDLE hidHandle;
GUID hidGuid;
ULONG requiredLength;
SP_DEVICE_INTERFACE_DATA devInfoData;
deviceNo = 0;
hidHandle = NULL;
devInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
printf("Begin to list all HID device...\r\n\r\n");
/* HidD_GetHidGuid routine returns the device interfaceGUID for HIDClass devices - from MS */
HidD_GetHidGuid(&hidGuid);
printf("Get HID Guid: Data1[0x%X]. Data2[0x%X]. Data3[0x%X]. Data4[0x%X%X%X%X%X%X%X%X]\r\n", hidGuid.Data1, hidGuid.Data2, hidGuid.Data3,
hidGuid.Data4[0], hidGuid.Data4[1], hidGuid.Data4[2], hidGuid.Data4[3], hidGuid.Data4[4], hidGuid.Data4[5], hidGuid.Data4[6], hidGuid.Data4[7]);
/* SetupDiGetClassDevs返回一个包含本机上所有被请求的设备信息的设备信息集句柄 */
/* SetupDiGetClassDevs function returns a handle to a device information set that contains requested device information elements for a local computer - from MS */
HDEVINFO hDevInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
if (hDevInfo == INVALID_HANDLE_VALUE) {
printf("Fatal Error: SetupDiGetClassDevs Fail!!!\r\n");
return 1;
}
SetLastError(NO_ERROR); /* 首先清空错误代码,以便于后面的使用 */
while (1) {
printf("\r\ntry deviceNo %d.\r\n", deviceNo);
/* The SetupDiEnumDeviceInterfaces function enumerates the device interfaces that are contained in a device information set - from MS */
result = SetupDiEnumInterfaceDevice(hDevInfo, 0, &hidGuid, deviceNo, &devInfoData);
if ((result == false) || (GetLastError() == ERROR_NO_MORE_ITEMS)) { /* 出现ERROR_NO_MORE_ITEMS错误表示已经找完了所有的设备 */
printf("No More Item Left!!!\r\n\r\n");
break;
} else {
printf("----Get devInfoData: cbSize[%d]. Flags[0x%.2X]. InterfaceClassGuid([0x%X] [0x%X] [0x%X] [0x%X%X%X%X%X%X%X%X])\r\n",
devInfoData.cbSize, devInfoData.Flags, devInfoData.InterfaceClassGuid.Data1, devInfoData.InterfaceClassGuid.Data2, devInfoData.InterfaceClassGuid.Data3,
devInfoData.InterfaceClassGuid.Data4[0], devInfoData.InterfaceClassGuid.Data4[1], devInfoData.InterfaceClassGuid.Data4[2], devInfoData.InterfaceClassGuid.Data4[3],
devInfoData.InterfaceClassGuid.Data4[4], devInfoData.InterfaceClassGuid.Data4[5], devInfoData.InterfaceClassGuid.Data4[6], devInfoData.InterfaceClassGuid.Data4[7]);
}
/* The SetupDiGetDeviceInterfaceDetail function returns details about a device interface - From MS */
requiredLength = 0; /* 先将变量置零,以便于下一步进行获取 */
SetupDiGetInterfaceDeviceDetail(hDevInfo, &devInfoData, NULL, 0, &requiredLength, NULL); /* 第一次调用,为了获取requiredLength */
PSP_INTERFACE_DEVICE_DETAIL_DATA devDetail = (SP_INTERFACE_DEVICE_DETAIL_DATA *)malloc(requiredLength); /* 根据获取到的长度申请动态内存 */
devDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); /* 先对变量进行部分初始化 */
result = SetupDiGetInterfaceDeviceDetail(hDevInfo, &devInfoData, devDetail, requiredLength, NULL, NULL); /* 第二次调用,为了获取devDetail */
if (result == false) {
printf("Fatal Error: SetupDiGetInterfaceDeviceDetail fail!!!\r\n");
free(devDetail);
SetupDiDestroyDeviceInfoList(hDevInfo);
return 1;
} else {
printf("----Get devDetail: cbSize[%d] DevicePath[%s]\r\n", devDetail->cbSize, devDetail->DevicePath);
}
if (OVERLAP_MODE == 1) {
hidHandle = CreateFile(devDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
} else {
hidHandle = CreateFile(devDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
}
free(devDetail);
if (hidHandle == INVALID_HANDLE_VALUE) { /* 系统会将部分HID设备设置成独占模式 */
printf("CreateFile fail!!! dev maybe in_use. continue to try next one...\r\n");
++deviceNo;
continue;
}
_HIDD_ATTRIBUTES hidAttributes;
result = HidD_GetAttributes(hidHandle, &hidAttributes); /* 获取HID设备的属性 */
if (result == false) {
printf("Fatal Error: HidD_GetAttributes fail!!!\r\n");
CloseHandle(hidHandle);
SetupDiDestroyDeviceInfoList(hDevInfo);
return 1;
} else {
printf("----Get hidAttributes: Size[%d]. VersionNumber[%d]. ProductID[0x%X]. VendorID[0x%X]\r\n",
hidAttributes.Size, hidAttributes.VersionNumber, hidAttributes.ProductID, hidAttributes.VendorID);
}
CloseHandle(hidHandle);
++deviceNo;
}
/* The SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory - From MS */
SetupDiDestroyDeviceInfoList(hDevInfo);
printf("Search is Over!!! find %d HID_Dev altogether in your computer...\r\n\r\n", deviceNo);
printf("任务完成,按任意键退出...\r\n");
getchar();
getchar();
return 0;
}
编译,运行,得到以下结果:
Begin to list all HID device...
Get HID Guid: Data1[0x4D1E55B2]. Data2[0xF16F]. Data3[0x11CF]. Data4[0x88CB011110030]
try deviceNo 0.
----Get devInfoData: cbSize[28]. Flags[0x01]. InterfaceClassGuid([0x4D1E55B2] [0xF16F] [0x11CF] [0x88CB011110030])
----Get devDetail: cbSize[5] DevicePath[\\?\hid#vid_413c&pid_2113&mi_01&col01#8&d329eae&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}]
----Get hidAttributes: Size[12]. VersionNumber[264]. ProductID[0x2113]. VendorID[0x413C]
try deviceNo 1.
----Get devInfoData: cbSize[28]. Flags[0x01]. InterfaceClassGuid([0x4D1E55B2] [0xF16F] [0x11CF] [0x88CB011110030])
----Get devDetail: cbSize[5] DevicePath[\\?\hid#vid_09da&pid_054f&mi_00&col01#7&20cf2917&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}]
CreateFile fail!!! dev maybe in_use. continue to try next one...
try deviceNo 2.
----Get devInfoData: cbSize[28]. Flags[0x01]. InterfaceClassGuid([0x4D1E55B2] [0xF16F] [0x11CF] [0x88CB011110030])
----Get devDetail: cbSize[5] DevicePath[\\?\hid#vid_09da&pid_054f&mi_00&col02#7&20cf2917&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}]
----Get hidAttributes: Size[12]. VersionNumber[628]. ProductID[0x54F]. VendorID[0x9DA]
try deviceNo 3.
----Get devInfoData: cbSize[28]. Flags[0x01]. InterfaceClassGuid([0x4D1E55B2] [0xF16F] [0x11CF] [0x88CB011110030])
----Get devDetail: cbSize[5] DevicePath[\\?\hid#vid_09da&pid_054f&mi_00&col03#7&20cf2917&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}]
----Get hidAttributes: Size[12]. VersionNumber[628]. ProductID[0x54F]. VendorID[0x9DA]
try deviceNo 4.
----Get devInfoData: cbSize[28]. Flags[0x01]. InterfaceClassGuid([0x4D1E55B2] [0xF16F] [0x11CF] [0x88CB011110030])
----Get devDetail: cbSize[5] DevicePath[\\?\hid#vid_09da&pid_054f&mi_00&col04#7&20cf2917&0&0003#{4d1e55b2-f16f-11cf-88cb-001111000030}]
----Get hidAttributes: Size[12]. VersionNumber[628]. ProductID[0x54F]. VendorID[0x9DA]
try deviceNo 5.
----Get devInfoData: cbSize[28]. Flags[0x01]. InterfaceClassGuid([0x4D1E55B2] [0xF16F] [0x11CF] [0x88CB011110030])
----Get devDetail: cbSize[5] DevicePath[\\?\hid#vid_413c&pid_2113&mi_01&col02#8&d329eae&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}]
----Get hidAttributes: Size[12]. VersionNumber[264]. ProductID[0x2113]. VendorID[0x413C]
try deviceNo 6.
----Get devInfoData: cbSize[28]. Flags[0x01]. InterfaceClassGuid([0x4D1E55B2] [0xF16F] [0x11CF] [0x88CB011110030])
----Get devDetail: cbSize[5] DevicePath[\\?\hid#vid_09da&pid_054f&mi_01#7&30814ab&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}]
CreateFile fail!!! dev maybe in_use. continue to try next one...
try deviceNo 7.
----Get devInfoData: cbSize[28]. Flags[0x01]. InterfaceClassGuid([0x4D1E55B2] [0xF16F] [0x11CF] [0x88CB011110030])
----Get devDetail: cbSize[5] DevicePath[\\?\hid#vid_413c&pid_301a#7&5745a0d&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}]
CreateFile fail!!! dev maybe in_use. continue to try next one...
try deviceNo 8.
----Get devInfoData: cbSize[28]. Flags[0x01]. InterfaceClassGuid([0x4D1E55B2] [0xF16F] [0x11CF] [0x88CB011110030])
----Get devDetail: cbSize[5] DevicePath[\\?\hid#vid_413c&pid_2113&mi_00#8&359d4c77&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}]
CreateFile fail!!! dev maybe in_use. continue to try next one...
try deviceNo 9.
No More Item Left!!!
Search is Over!!! find 9 HID_Dev altogether in your computer...
任务完成,按任意键退出...
结束语
一个最简单的HID设备枚举工程就是这样了,接下去还会继续研究对其中的某个HID设备进行读写,敬请期待…