WIN10+VS2017环境下对USB HID设备进行枚举的程序(含源码)

前段时间在WIN10系统+VS2017环境下安装了USB开发的驱动环境(详见我的博客【如何在win10+VS2017环境下安装USB驱动开发套件WDK】),今天介绍一下如何建立一个简单的HID设备枚举工程。文中的工程使用VS2017社区版建立和编译,文中对整个工程的建立、配置、编码过程进行了详细的介绍,大家可以参照自己执行。如果觉得麻烦,也可以点击此处【CSDN下载压缩包】直接下载我编辑好的整个工程,或者直接去我的码云克隆,地址是【https://gitee.com/leon1741/MyFirstHIDTest】。不过建议大家去码云里克隆,因为这里的代码我会随时保持更新,而CSDN上的压缩包则是最早的版本。

步骤1、新建工程

新建一个空白项目即可。工程名称我输入的是MyFirstHIDTest,大家可以自定义修改。
WIN10+VS2017环境下对USB HID设备进行枚举的程序(含源码)_第1张图片
工程建好之后,新建一个cpp源码文件:
WIN10+VS2017环境下对USB HID设备进行枚举的程序(含源码)_第2张图片
源码文件名我输入的也是MyFirstHIDTest.cpp,大家可以自定义修改。
WIN10+VS2017环境下对USB HID设备进行枚举的程序(含源码)_第3张图片

步骤2:工程设置

工程建好之后,要对工程进行一些设置:

1、设置工程的字符集为多字节字符集,以免后面编译代码时出现问题。
WIN10+VS2017环境下对USB HID设备进行枚举的程序(含源码)_第4张图片
2、添加必要的依赖库(hid.lib;setupapi.lib):
WIN10+VS2017环境下对USB HID设备进行枚举的程序(含源码)_第5张图片
WIN10+VS2017环境下对USB HID设备进行枚举的程序(含源码)_第6张图片

步骤3、编写代码

输入以下代码:

#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 

/*********************************************************************************************************************/
//                           模块宏定义
/*********************************************************************************************************************/
#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设备进行读写,敬请期待…

你可能感兴趣的:(玩转windows)