欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-12 09:34:35
...

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

步骤1、新建工程

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

步骤2:工程设置

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

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

步骤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设备进行读写,敬请期待…