Windows下怎么用VS打开自定义HID设备?

USB中文网 2021-07-07 23:32:53 编辑

无论是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
sampei 2021-05-28 16:36:26 编辑

这些都是上层的,希望有些底层的

USB中文网 2021-05-28 17:11:30 编辑

你想了解那些底层的了?HID底层的可以操作系统驱动层,固件层,硬件层?