自定义HID应用程序开发(Windows)
+ -

Windows下枚举系统中所有HID设备

2020-10-29 3726 3

Windows下对任何设备,文件的打开都是通过CreateFile来实现的,不过要打开一个设备得首先知道设备或文件名。
由上节可知道,对于HID设备,都会注册一个接口类型为{2ACCFE60-C130-11D2-B082-00A0C91EFB8B}的GUID。我们可以通过Setup系列函数枚举出系统中所有的HID设备,然后再根据其属信息判断(如PID,VID,报告描述符长度等)来进行过滤。

枚举系统中所有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;
        }

        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;
        }

        _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))
        {


        }

    }
}
HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

Windows下枚举系统中所有HID设备
Windows下对任何设备,文件的打开都是通过CreateFile来实现的,不过要打开一个设备得首先知道设备或文件名。由上节可知道,对于HID设备,都会注册一个接口类型为{2ACCFE60-C130-11D2-B082-00A0C91EFB8B}的GUID。我们可以通过Setup系列函数枚举出系统中......
USB复合HID设备报告描述符的区分
在USB规范中,设备的功能是通过接口来承载的,在USB规格书中就是接口描述符。对于一般的设备,一般一个接口就是一个功能,这个功能可以是鼠标,键盘或其它设备类型。当然这个只是对USB简易设备而言的,对于一些USB复杂设备如UVC摄像头,UAC音频等是多接口相互配合来实现其功能的,为了整合这么多接口使......
USB通用父驱动usbccgp.sys的过滤UVC摄像头、UAC麦克风和HID设备硬件ID
激动的心情,无溢言表。。虽然只是一个很简单的东西。。但相于折腾了这么久,还是很开心的了。最近有个需求,功能是这样的:有一个USB复合设备,连接到windows系统中它在windows下的设备树如下:USB Composite Device(usbccgp.sys)UVC CameraUAC ......
HID设备固件升级失败
USB设备现在比较多,像UVC摄像头,UAC音频或TOUCH设备,这些设备在设备管理器中无不都会带一个自定义的HID设备。这个自定义的HID主要的功能一般是通过应用层与固件进行数据通讯,比如对固件参数的配置,甚至固件的升级。在Windows下,两2套与HID设备的通讯的接口,一组是WriteFil......
USB复合设备-UVC摄像头HID设备共存的设计实现
通常做USB设备的开发,我们做的都是单一的功能设备。这种单一的功能设备只实现某种特定的功能,如只实现一个HID鼠标或键盘,只实现一个USB存储功能,或再复杂一点只实现一个UVC音频麦克风和扬声器功能或一个UVC摄像头功能。但我们在一般的市场上看到的设备通常不只实现一种功能,如UVC摄像头功能还提供......
HID设备的实现原理-HID描述符
USB设备的信息存储在USB设备的固件中,当USB设备接入PC机启动后,主机会通过USB的标准请求对存储在USB设备的固件信息进行读取分析。这些存储的信息主要包括各种USB描述符信息,如设备描述符,配置描述符,接口描述符、端点描述符和字符串描述符等。USB设备的功能按接口来进行分类的,一个接口就代......
HID设备描述符的级级关系
和大多数的USB设备一样,HID设备也有USB设备的一些标准描述符,如设备描述符、配置描述符、接口描述符、端点找述符。但HID设备也有一些特的描述述,如HID描述符和报告描述符(也叫描表描述符)。HID设备的设备类型不是在设备类型中定义,而是在接口描述符中定义。设备描述符中的bDeviceCla......
HID设备的bInterfaceClass、bInterfaceSubClass和bInterfaceProtocol
HID设备是USB规范定义的设备类型之一,其分类号为0x03.关于USB设备类型定义,可参见本站:http://www.usbzh.com/article/detail-221.htmlHID设备除了用于专门的输入输出设备外,有时也与其它的设备类型组合成一个复杂的设备。如对于UVC摄像头设备,可以......
Windows下自定义HID设备通讯调试工具HidTool
功能枚举系统中可用的自定义HID设备,并进行数据通讯.在软件界面中显示该HID设备的,VID,PID,产品名称,输入报告长度,输出报告长度,特性报告长度和该输入报告所使用的USAGE_PAGE和USAGE。另外,对于一些用户,也可以指定Windows系统关于HID读取输入报告的缓冲区大小,系统默......
HID设备虚拟触摸屏上报的多点数据系统不响应
前一般时间在Windows10下使用USB驱动虚拟了一个触摸屏设备,上层软件按照HID报告述符的格式下发触摸屏数据给驱动,再由驱动将数据上交给系统,实现虚拟触摸屏的功能。今天,突发奇想,上次的报告描述符仅支持的是一个点触摸效果,今天保不实现了一下多点触摸效果,所以我通过在一个支持多点触摸屏的设备......
Windows下虚拟USB设备数据的读写请求调试笔记
到现在为止,本人已经在Windows下确切来说是Windows10 x64下开发了以下USB虚拟USB设备:USB虚拟UVC摄像头设备USB虚拟UAC麦克风设备USB虚拟HID键盘设备USB虚拟HID鼠标设备USB虚拟HID键盘鼠标复合设备USB虚拟HID单点触摸屏设备USB虚拟HID多点触摸屏......
Windows自定义HID设备通讯开发概述
HID设备是USB规范中最早提出并支持的一类通讯设备,常见的键盘、鼠标、游戏手柄都属于HID设备HID设备一般用于数据量小但实时性要求较高的环境,所以HID设备采用的是USB四种通讯类弄的中中断传传输类型。除了上述描述符的标准的HID设备,HID也提供一种自定义通讯,并由Windows提供驱动,而......
HID设备SET_IDLE时遇到c0000004
下午,USB中文网技术交流群里的一个同学,说他的HID设备时好时不好的,有时会花很长的时间才能枚举成功。没有抓包,没的截图…我是一顿乱扯,从硬件电路到各种抓包方法….晚上11点,这位同学发来了BUSHOUND抓的包,打开一看:Device Length Phase Data ......
UAC复合设备(麦克风,扬声器,HID设备)的示例
UAC符合设备(麦克风,扬声器,HID设备)在设备管理器中如下图所示:在BUSHOUND下如下图所示:UAC音频设备UAC音频设备包括扬声器和麦克风。其中USB Pnp Audio Device使用了接口0,1,2,分别用于控制接口,扬声器和麦克风。HID音量控制设备USB输入设备用于音频的......
USB鼠标HID设备示例
本示例的鼠标是一个最简单的USB鼠标,不包括任何其它附加设备。该设备在设备管理器中如下图所示:该USB鼠标的枚举过程如示:Device Length Phase Data Descriptio......
关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!