找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 174|回复: 1

hid协议是什么?

[复制链接]
  • 打卡等级:热心大叔
  • 打卡总天数:245
  • 打卡月天数:2
  • 打卡总奖励:7719
  • 最近打卡:2025-12-05 20:56:49

350

主题

557

回帖

1万

积分

管理员

积分
10407
发表于 2024-2-13 22:00:40 | 显示全部楼层 |阅读模式

HID设备是什么?
HID是英文“Human Interface Devices”的缩写,翻译为“人机界面设备”。这是指任何一种用来与计算机或其他电子设备交互的输入或输出设备。常见的HID设备包括鼠标、键盘、游戏手柄、数字笔、扫描仪等。
HID设备与计算机或其他电子设备的交互依赖于驱动程序,这些驱动程序为HID设备提供指令和信息。HID设备通常采用标准接口协议来与计算机或其他电子设备进行通信,这使得开发人员能够方便地编写驱动程序来支持不同的设备。
在远程控制的协议中,如果我们需要在控制端,使用键鼠、手柄、触摸板(手写笔)等外设控制云端电脑的话,必须使用HID的虚拟驱动,来实现:
1、识别操作端的外设输入设备信息
2、通过协议传输给受控端
3、受控端设备拦截识别输入设备信息,进行系统层面的操作
本文我们来探讨上述HID设备虚拟化的基本实现原理(关于HID设备的虚拟化,需要了解HID描述符相关基础知识,可以参见另外一篇文章:关于HID描述符)。
1. HID架构
在Windows下面HID的基本架构如下:

在应用层的一个完整的HID应用(HID Clients)包括有驱动、服务以及应用程序,他们需要与HIDClass.sys进行通信;通常来说每一次通信的对象都是一个指定的设备(例如键盘,鼠标等)。通常系统是通过hardware ID或者HID Collection来标识一个设备,设备之间的通信遵循如下规则:
  • 用户模式驱动或者应用程序通过HIDClass提供的HidD_xxx来获取HID Collection
  • 内核驱动或者用户驱动以及应用程序通过HID分析支持程序HidP_xxx,内核驱动程序使用HID 类驱动的IOCTL来处理HID报表。
ModeDriversApplications
User ModeHidD_XxxHidP_Xxx
Kernel ModeHidD_XxxIOCTL_HID_xxxN/A
HID Transport是具体的硬件设备,我们HID Transport向上提供硬件相关信息,HID Client从来不主动和HID Transport直接通信,都是通过HIDClass.sys来进行中转的,这样给我们HID Client和HID Transport的开发都带来了非常大的便利;这也是Windows MiniPort驱动实现的基本框架。
对于HID的设备的虚拟,我们主要是需要实现HID Transport
2. HID接口函数
Windows提供了如下的HID函数接口来或者和操作HID设备:
1、Device Discovery and Setup。
2、Data Movement。
3、Report Creation and Interpretation。
2.1 查找和设置设备(Device Discovery and Setup)
API描述
HidD_GetAttributes请求获得HID设备的厂商ID、产品ID和版本号
HidD_GetHidGuid请求获得HID设备的GUID
HidD_GetIndexString请求获得由索引识别的字符串
HidD_GetManufactureString请求获得设备制造商字符串
HidD_GetPhysicalDescriptor请求获得设备实体字符串
HidD_GetPreparsedData请求获得与设备能力信息相关的缓冲区的代号
HidD_GetProductString请求获得产品字符串
HidD_GetSerialNumberString请求获得产品序列号字符串
HidD_GetNumInputBuffer获得驱动程序用于存储输入报表的环形缓冲区的大小,默认值是8
HidD_SetNumInputBuffer设置驱动程序用于存储输入报表的环形缓冲区的大小
2.2 数据传输转移(Data Movement)
API描述
HidD_GetInputReport从设备读取一个特征报表
HidD_SetFeature向设备传送一个特征报表
HidD_SetOutputReport向设备传送输出报表
WriteFile向设备传送输出报表
ReadFile从设备读取输入报表
2.3 反馈信息创建及说明(Report Creation and Interpretation)
API描述
HidP_GetButtonCaps请求获得HID报表中所有按钮的能力
HidP_GetButtons从设备读取包含每个按下的按钮的用法(Usage)的缓冲区的指针,该请求可以设定一个Usage Page
HidP_GetButtonEx从设备读取包含每个按下的按钮的Usage和Usage Page的缓冲区的指针
HidP_GetCaps请求获得用于描述设备能力的结构的指针
HidP_GetLinkCollectionNotes请求获得描述在顶层集合中的连接集合(Link Collection)关系的结构的数组
HidP_GetSpecificButtonCaps请求获得报表中按钮的能力,该请求可以设定一个Usage Page、Usage或是Link Collection
HidP_GetSpecificValueCaps请求获得报表中数值的能力,该请求可以设定一个Usage Page、Usage或是Link Collection
HidP_GetValueCaps请求获得 HID 报表中所有数值的能力
HidP_MaxUsageListLength请求获得 HID 报表中可以回传的按钮的最大数目,该请求可以设定一个Usage Page
HidP_UsageListDifference比较两个按钮列表,并且求出在一个列表中设定而在另一个列表中没有设定的按钮
HidP_GetScaledUsageValue从设备读取一个已经经过比例因子调整的有符号数值
HidP_GetUsageValue从设备读取一个指向数值的指针
HidP_GetUsageValueArray从设备读取包含多个数据项的Usage的数据
HidP_SetButtons向设备传送设置按钮的数据
HidP_SetScaledUsageValue将一个实际数值转换成设备使用的逻辑数值,并将其插入到报表中
HidP_SetUsageValue向设备传送数据
HidP_SetUsageValueArray向设备传送包含多个数据项的Usage的数据
3. 创建虚拟设备
由于windows提供这些接口函数,所以我们可以据此创建虚拟驱动,在系统内识别和创建安装对应的HID设备,这样我们通过远程输入设备,就可以正常操控受控电脑了。
以下是创建虚拟设备的主要函数:
3.1 HidRegisterMinidriver
对于一个HID的Miniport硬件驱动来说,都是通过HidRegisterMinidriver函数来完成注册的,这个函数是HIDClass.sys提供,也就是说HIDClass.sys提供了框架,给我们MiniPort驱动的开发。
对于 HidRegisterMinidriver 工作大致可以总结为如下:
1、IoAllocateDriverObjectExtension创建驱动的上下文HIDCLASS_DRIVER_EXTENSION
2、保存MiniPort驱动的相关信息到HIDCLASS_DRIVER_EXTENSION结构中,如下:
  1. RtlCopyMemory(hidDriverExtension->MajorFunction,
  2.     minidriverObject->MajorFunction,sizeof( PDRIVER_DISPATCH ) * (IRP_MJ_MAXIMUM_FUNCTION + 1) );

  3. minidriverObject->DriverUnload = HidpDriverUnload;

  4. hidDriverExtension->AddDevice = driverExtension->AddDevice;
复制代码




3.2 IRP_MJ_INTERNAL_DEVICE_CONTROL
对于HID的虚拟硬件设备,对上层实现的接口都是通过IRP_MJ_INTERNAL_DEVICE_CONTROL来提供的,HID需要实现的相关IOCTL如下:
  1. //
  2. // Internal IOCTLs for the class/mini driver interface.
  3. //

  4. #define IOCTL_HID_GET_DEVICE_DESCRIPTOR             HID_CTL_CODE(0)
  5. #define IOCTL_HID_GET_REPORT_DESCRIPTOR             HID_CTL_CODE(1)
  6. #define IOCTL_HID_READ_REPORT                       HID_CTL_CODE(2)
  7. #define IOCTL_HID_WRITE_REPORT                      HID_CTL_CODE(3)
  8. #define IOCTL_HID_GET_STRING                        HID_CTL_CODE(4)
  9. #define IOCTL_HID_ACTIVATE_DEVICE                   HID_CTL_CODE(7)
  10. #define IOCTL_HID_DEACTIVATE_DEVICE                 HID_CTL_CODE(8)
  11. #define IOCTL_HID_GET_DEVICE_ATTRIBUTES             HID_CTL_CODE(9)
  12. #define IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST    HID_CTL_CODE(10)
复制代码



我们知道HID最重要的两个描述符是:
1、HID设备描述符。HID设备描述符通过IOCTL_HID_GET_DEVICE_DESCRIPTOR向上层提供。
2、HID报表描述符。HID报表描述符通过IOCTL_HID_GET_REPORT_DESCRIPTOR向上层提供。
其他操作包括IOCTL_HID_READ_REPORT实现用来读取报表描述符,IOCTL_HID_WRITE_REPORT用来写入报表描述符。
这里我们需要定义两个描述符,例如可以定义如下:
  1. HID_REPORT_DESCRIPTOR           DefaultReportDescriptor[] = {
  2.     0x06,0x00, 0xFF,                // USAGE_PAGE (Vender Defined Usage Page)     
  3.     0x09,0x01,                          // USAGE (Vendor Usage 0x01)      
  4.     0xA1,0x01,                           // COLLECTION (Application)        
  5.     0x85,CONTROL_FEATURE_REPORT_ID,           // REPORT_ID (1)                     
  6.     0x09,0x01,                          // USAGE (Vendor Usage 0x01)              
  7.     0x15,0x00,                          // LOGICAL_MINIMUM(0)                  
  8.     0x26,0xff, 0x00,                // LOGICAL_MAXIMUM(255)               
  9.     0x75,0x08,                          // REPORT_SIZE (0x08)                     
  10.     0x95,0x01,                          // REPORT_COUNT (0x01)                    
  11.     0xB1,0x00,                          // FEATURE (Data,Ary,Abs)
  12.     0x09,0x01,                          // USAGE (Vendor Usage 0x01)              
  13.     0x75,0x08,                          // REPORT_SIZE (0x08)                     
  14.     0x95,INPUT_REPORT_BYTES,           // REPORT_COUNT (0x01)                    
  15.     0x81,0x00,                      // INPUT (Data,Ary,Abs)
  16.     0xC0                                // END_COLLECTION                       

  17. };

  18. HID_DESCRIPTOR              DefaultHidDescriptor = {
  19.     0x09,   // length of HID descriptor
  20.     0x21,   // descriptor type == HID  0x21
  21.     0x0100, // hid spec release
  22.     0x00,   // country code == Not Specified
  23.     0x01,   // number of HID class descriptors
  24.     { 0x22,   // report descriptor type 0x22
  25.     sizeof(DefaultReportDescriptor) }  // total length of report descriptor
  26. };
复制代码


3.3 效果展示
通过实现相关的HID硬件特性之后,我们可以虚拟化如下HID设备:
1、虚拟游戏手柄
2、虚拟键盘
3、虚拟鼠标
4、虚拟显示器
5、虚拟触摸屏
6、虚拟触摸板
7、虚拟手写笔

并且我们可以直接操作虚拟化的驱动来模拟各种HID设备信息,如下我们利用虚拟HID键盘向系统开始菜单输入一个Hello:

这张图即是通过虚拟HID进行输入Hello字符4、更多HID驱动
Nanos目前已经实现了成熟的商业化产品中,多种HID设备的驱动程序,可以提供完整的驱动解决方案。
现在随着云桌面、嵌入式设备等串流技术发展,HID相关驱动技术也越来越丰富,欢迎大家一起进行交流



论坛免责声明
版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。
  • 打卡等级:热心大叔
  • 打卡总天数:245
  • 打卡月天数:2
  • 打卡总奖励:7719
  • 最近打卡:2025-12-05 20:56:49

350

主题

557

回帖

1万

积分

管理员

积分
10407
 楼主| 发表于 2024-2-13 22:02:37 | 显示全部楼层
1. 基本概念 HID协议是一种基于USB的通讯协议,用于在计算机和输入设备之间进行数据传输。HID协议定义了标准的数据格式、命令结构以及传输方式,使得不同厂商生产的输入设备可以被操作系统识别和兼容。
  • HID协议的实现基于USB(Universal Serial Bus)接口,因此HID设备通常都是通过USB接口与计算机相连的。在HID协议中,设备会向计算机发送一系列的报告,描述设备的状态和用户的操作。计算机则可以根据这些报告来识别设备,并对用户的操作做出相应的响应。
  • HID协议支持的设备种类非常广泛,包括但不限于键盘、鼠标、游戏手柄、摄像头、扫描仪等等。这些设备都可以通过HID协议与计算机进行通信,从而实现与用户的交互。

特点 HID协议的优点包括以下几个方面:
  • 简单易用:HID协议定义的指令和数据格式都很简单,易于理解并进行开发。对于绝大多数的输入设备,我们只需要遵循HID协议来实现输入输出即可。
  • 高效性能:HID协议使用了一种类似于中断传输的方式,在需要时及时传输数据,降低了延迟,并保证了数据的实时性。这使得HID协议更适合用于实时性要求比较高的应用。
  • 可靠性:HID协议的实现通常基于硬件设计,配合驱动程序和操作系统支持,使得输入设备能够与计算机无缝连接和互通。也因此HID协议具有高可靠性、稳定性等特点,提高了产品的品质。

此外,HID协议还支持多种输入设备类型(如键盘、鼠标、摇杆等),并且支持对输入设备进行配置和控制,如设置灯光、自定义按键功能等。
总的来说,HID协议是一种很好的通讯协议,使得输入设备的设计和使用更加简单、高效、可靠,同时也提高了用户的使用体验。

1.简述
USB HID类是USB设备的一个标准设备类,包括的设备非常多。HID类设备定义它属于人机交互操作的设备,用于控制计算机操作的一些方面,如USB鼠标、USB键盘、USB游戏操纵杆等。但HID设备类不一定要有人机接口,只要符合HID类别规范的设备都是HID设备。
   USB HID设备的一个好处就是操作系统自带了HID类的驱动程序,而用户无需去开发驱动程序,只要使用API系统调用即可完成通信。
  
2. HID 协议
2.1 USB HID设备类的通信管道
所有的HID设备通过USB的控制管道(默认管道,即端点0)和中断管道(端点1或端点2)与主机进行通信。
管道        要求      说明
控制(端点0)    必须      传输USB描述符、类请求代码以及供查询的消息数据
中断输入      必须      传输从设备到主机的输入数据
中断输出      可选      传输从主机到设备的输出数据
注:USB主机为PC,USB设备如鼠标等。中断端点的描述中,指定了主机轮询的时间 Interval。即,主机会隔一段时间来“要”数据。
控制管道主要用于下面3个方面
  • 接收/响应USB主机的控制请求以及相关的类数据
  • 在USB主机查询时传输数据(如响应Get_Report请求等)
  • 接收USB主机的数据
中断管道主要用于下面两个方面
  • USB主机接收USB设备的异步传输数据
  • USB主机发送有实时性要求的数据给USB设备
从USB主机到USB设备的中断输出数据传输是可选的,当不支持中断输出数据时,USB主机通过控制管道将数据传输给USB设备。
2.2 与 USB HID 设备有关的描述符
HID设备的描述符除了5个USB的标准描述符(设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符)外,还包括三个HID设备类特定的描述符:HID描述符、报告描述符(Report)、实体描述符(Physical)。


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Discuz! X

GMT+8, 2025-12-7 08:46 , Processed in 0.025000 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表