USB-HID一些笔记
HID(Human Interface Deviece)协议是USB协议中的一个子协议。指的是直接与人进行交互的设备。
一、简述一些概念
1.0 USB设备描述符
USB是个通用的总线,硬件端口是统一的,而USB设备却有很种,为了区分这些不同的设备,就得要用到不同设备各自的描述符。
1.1USB标准描述符
USB设备的信息存储在USB设备的固件中,当USB设备接入PC机启动后,主机会通过USB的标准请求,对存储在USB设备的固件信息进行读取分析。
USB有5种标准设备描述符,分别是:设备描述符、配置描述符、字符串描述符、接口描述符、端点描述符。
另外还有:HID描述符、报告描述符等各个类特有的描述符。
更详细的内容请查找USB协议的相关资料。
1.2HID描述符
由于USB HID设备的接口中标识了设备类型,但同一种设备类型因为厂商或实现机制的原因,数据格式不统一,所以虽然是同一种设备,但固件上报的数据格式甚至长度可能五花八门,那么通过什么方式来实现使USB主机端识别并解析这些数据呢?答案就是报告描述符。
USB HID描述符包括两种报表描述符,分别为物理描述符集合和报告描术符,也叫报表描述符。
- 物理描述符集合是可选的描述符,提供用于激活设备控件的人体一个或多个部分的信息。
- 报告描述符用于描述符USB HID设备上报的数据信息格式。
二、HID报告描述符/报表描述符
报表描述符用于描述USB_HID设备与主机之间数据交互的格式。根据数据的传输方向,分为输入报告和输出报告。
USB HID设备与主机传输的是数据,这些原始的数据就像内存里的数据一样,如果没有人告诉我们这些字节干什么的,也许我们永远也不知道的。USB报表描述符的功能就是用于描述这些报告数据格式。当主机或设备收到报告数据后,会根据报告描述符的内容解析并理解这些数据的含义
2.0输出报告
输出报告主要是由主机给HID设备发送数据,例如键盘上的LED灯的开关命令。在我的开发里面,输出报告使用的比较少,这里不加以描述。
2.1输入报告
输入报告主要是由HID设备发送给主机数据的报告,大部分HID设备主要实现的也是输入报告。例如鼠标的点击,移动,滚轮等操作。都是发送的输入报告。
2.2报表描述符的格式
在进行报表传输之前,主机必须先请求设备的报表描述符,只有得到了报表描述符才可正确解析报表的数据。
HID的报表描述符并不像USB设备描述符一样,包含描述符的长度和描述符类型的信息。HID描述符是由一个个项目(item)组成。每一个项目具有其项目的信息。
HID定义了两种项目,一种是长项目,另一种是短项目。报告描述符里面的长项目一般不使用,一般短项目使用较多。这里就只介绍短项目。
2.2.0长项目(long item)
长项目可以携带更多的数据,当第一个字节为上图中的特定值时表明该项目是一个长项目。
2.2.1短项目(short item)
- bSize为0、1、2、3时Data部分的字节数分别为0、1、2、4个字节。
0 = 0 bytes
1 = 1 bytes
2 = 2 bytes
3 = 4 bytes - bType为0、1、2时分别为Main、Global和Local类型。
0 = Main
1 = Global
2 = Local
3 = Reserved - bTag:表示该项目的功能。
2.2.2三个项目类型(Main Item、Global Item、Local Item)
一些常用的项目类型,功能用法
主项目(Main Item)
主项目其有5个,分别为Input,Output,Feature,Collection和End Collection.
Input、Outpot和Feature项目
Input项目可以应用到任何控制、计数器读数或其他设备传给主机的信息。一个输入报表包含一个或多个Input项目,主机使用中断输入传输来请求输入报表。
Ouput项目用来定义主机传送给设备的信息。一个输出报表包含一个或多个Outpot项目。输出报表包含控制状态的数据。如果有中断输出管道,HID1.1兼容主机使用中断输出传输来传送输出报表,否则使用Set_Report控制请求。
Feature项目应用到主机传送给设备的信息,或是主机从设备读取Feature项目。一个特征报表包含一个或多个Feature项目,Feature项目通常是包合影响设备与其组件整体行为的配置。特征报表通常是控制可以使用实际的控制面板调整的设置,例如主机可以使用虚拟控制面板来让用户选择控制特征。主机使用 Set_Report与Get_Report请求来传送与接收特征报表。
在每一个Input、Output和Feature项目的前缀字之后是32位描述数据,目前最多定义了9个位,余的位则是保留。位0~8的定义中只有位7不能应用于Input项目,除此之外其他的位定义都适应于Input、Output和Feature项目。
Input、Outpot和Feature项目,这3个项目用来定义报表中的数据字段。
Collection和End Collection项目
Collection共有四种,分别为Physical,Application,Logical和Vendoer Defined.
所有的报表类型都可以使用Collection与 End Collection项目来将相关的Main类型项目组成群组。这两个项目分别用于打开和关闭集合。所有在Collection与End Collection项目之间的Main类型项目都是 Collection的一部分。
Collection有3种类型:Application、Physical与Logical,其项目的数据项的值分别为1、0和2。厂商也可以自己定义Collection类型,数据项的值为80h~FFh保留给厂商定义。End Collection项目无数据项。
Application Collection包含有共同用途的项目或执行单一功能的项目。例如键盘的开机描述符将键盘的按键与LED指示灯数据集合成一个Application Collection。所有的报表必须在一个Application Collection内。
Physical Collection包含在一个单一几何点上的数据项目,可以将每个位置的数据集合成一个 Physical Collection。在设备报告多个传感器的位置的时候,使用Physical Collection指明不同的数据来自不同的传感器。
Logical Collection形成一个数据结构,包含由 Collection所连结的不同类型的项目。例如数据缓冲区的内容以及缓冲区内字节数目的计数。
全局项目(Global Item)
全局项目主要用来选择用途页(Usage Page),定义数据域的长度(Report Count)、数量(Report Size)、报告ID(ReportId)等。
全局项目描述对后续的所有项目有效,除非遇到有新的全局项目。
常见的全局项目有:
- Usage Page(用途页)
- Logical Minimum(逻辑最小值)
- Logical Maxinum(逻辑最大值)
- Physical Minimum(物理最小值)
- Physical Maximum(物理最大值)
- Report Size:数据域大小,表示每个数据域有多少位
- Report Count:数据域有多少个数据域。
- ReportId:报告ID
局部项目(local Item)
局部项目用于定义数据的控制特性,如该数据域的用途,用途的最大值,用途的最小值等。
局部项目只在局部有效,遇到一个主项目后,它的失效。
常见的局部数据项目有:
- Usage :用途
- Usage Minmum:用途的最小值
- Usage Maxmum:用途的最大值。
三、下面是鼠标的HID设备描述符举例
0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 全局项目
0x09, 0x02, // Usage (Mouse) 局部项目
0xA1, 0x01, // Collection (Application)主项目
0x85, 0x04, // Report ID (4)
0x09, 0x01, // Usage (Pointer) 局部项目
0xA1, 0x00, // Collection (Physical) 主项目
0x95, 0x03, // Report Count (3) 全局项目 ->>>数量
0x75, 0x01, // Report Size (1) 全局项目 ->>>位数 1位(bit)
0x05, 0x09, // Usage Page (Button) 全局项目->>>定义用法(按键)
0x19, 0x01, // Usage Minimum (0x01) 局部项目->>>使用最大值
0x29, 0x03, // Usage Maximum (0x03) 局部项目->>>使用最小值
0x15, 0x00, // Logical Minimum (0) 全局项目->>>逻辑最小值
0x25, 0x01, // Logical Maximum (1) 全局项目->>>逻辑最大值
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)主项目->>>设置位输入项目
0x95, 0x01, // Report Count (1) 全局项目->>>数量
0x75, 0x05, // Report Size (5) 全局项目->>>位数
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)主项目->>>设置位输入项目 (Const常量不变量)填充上面Report Size 补足一个字节
0x95, 0x03, // Report Count (3) 全局项目->>>数量
0x75, 0x08, // Report Size (8) 全局项目->>>位数8位(bit)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)全局项目
0x09, 0x30, // Usage (X)局部项目
0x09, 0x31, // Usage (Y)局部项目
0x09, 0x38, // Usage (Wheel)局部项目
0x15, 0x81, // Logical Minimum (-127) 全局项目
0x25, 0x7F, // Logical Maximum (127) 全局项目
0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)主项目
0xC0, // End Collection 主项目
发送的数据
一些比较好的网上资料,和一些比较好的学习网站
[USB中文网]( USB中文网 - USB技术开发交流 这个里面的的资料是比较全的,不止有USB_HID的协议,还有很多USB的其他资料。
USB_HID协议基础,这是一个博客,是一个比较厉害的博主写的对USB_HID的一个介绍,可以了解一下。