UEFI开发探索83- YIE002USB开发板(06 制作HID设备)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

我们所要开发用来通信的USB设备,是HID类设备。HID(Human Interface Devices)为人机接口设备,是USB规范中最早提出并支持的一种设备类。我们日常使用的键盘、鼠标等,都属于HID设备,这是一种使用非常广泛的USB设备。

USB规范中,HID类设备的规范为Device Definiton for Human Interface Devices,每个HID设备都必须符合该规范中对描述符、传输类型等的定义。另外,USB-IF还提供了HID的用例规范,名为HID Usage Tables,定义了HID设备和USB主机之间通信的HID数据。所有的 HID 传输都是使用默认控制管道或是一个中断管道, HID 设备必须有一个中断输入端点来传送数据到主机,中断输出端点则不是必需的。

HID设备的标准描述符同样遵循上一篇所介绍的内容,也即拥有各种标准描述符。对于HID设备,其设备描述符的类代码、子类代码和协议代码都需要设置为0;接口描述符的类代码设为0x03,子类代码为0或者0x01,协议码为0、0x01或0x02。

当然,作为类设备,HID也有自己的描述符,也即人机接口类描述符,本篇介绍这些内容。

HID设备支持3种类描述符:HID描述符、报告描述符和物理描述符。一个USB设备只能包含一个HID描述符,可以支持多个报告描述符,而物理描述符是可选的。在本章的示例中,只用到了HID描述符和报告描述符,没有使用物理描述符,一般的HID设备也不使用该描述符,就不再进行介绍了。

1 HID描述符

HID描述符主要用来识别HID设备通信时所使用的额外信息(如HID版本号、报告描述符长度等),如表1所示,给出了HID描述符的定义结构。

表1 HID描述符的结构

偏移大小描述
0bLength1数字描述符的长度
1bDescriptorType1常量描述符的类型,0x21
2bcdHID2BCD码HID规范版本号(BCD码)
4bCountryCode1数字国家代码
5bNumDescriptor1数字支持的其他类描述符的数量
6bDescriptorType1常量类别描述符的类型
7wDescriptorLength2数字报表描述符的总长度
9bDescriptorType1常量识别描述符类型的常数,多个描述符时使用
10wDescriptorLength2数字描述符总长度,多个描述符时使用

其中,bCountryCode表示的是国家代码,一般将其设置为0就可以了。0表示的是HID设备不是本土化的,其他的值可以查看HID规范。bDescriptorType识别HID描述符附属的描述符的类型,报表描述符的类型为0x22,物理描述符的类型为0x23。每一个 HID设备都必须至少支持一个报表描述符。一个接口可以支持多个报表描述符,以及一个或多个实体描述符。HID描述符的偏移量为9和10的bDescriptorType和wDescriptorLength可以重复存在多个。

在USB主机发送标准命令Get_ Configuration,获取配置描述符的时候,将按照配置描述符、接口描述符、HID描述符、端点描述符的顺序,返回数据。也即主机此时可用获取到HID描述符,可以据其信息再去获取相关的描述符(如报告描述符)。

2 报告描述符

HID设备的报告描述符是一种数据报表,主要用来定义HID设备和USB主机之间的数据交换格式。与标准描述符不同,它没有固定的长度,根据设备不同的用途,需要准备不同的结构和数据描述。

报告描述符由多个不同的项目(item)组成,它有两种编码:短项目(short item)和长项目(long item)。长项目保留给未来使用,本节不对它进行介绍。HID短项目的字节格式如图1所示。

图1 HID短项目

最低位的bSize用来指出项目所需要的数据字节(即data部分的字节长度),其值可为0(bSize=0)、1(bSize=1)、2(bSize=2)和4(bSize=3)。注意没有3个字节长的数据,大部分项目只需要1个字节数据。

bType表示项目的类型,用来表示是主(Main)项目、全局(Global)还是局部(Local)项目。主项目用来定义报告中数据的种类和格式;局部项目表示所定义只能适用于其下的第一个主项目,不能扩展到其他主项目;全局项目则适用于其下方所有主项目,除非被另一个相同标签的全局项目替代。bType=0时,表示项目为主项目;bType=1时,项目为全局项目;bType=2时,项目为局部项目。

bTag为标签,用来标记各项目的作用。图2给出了HID项目的标签定义。

图2 HID项目的标签描述

HID短项目的data部分,是可选的,其长度由bSize决定。比如集合结束(End Collection)项目,其值一般为0xC0,后面不带有任何数据。

表2中给出的各种HID项目,每种项目的含义都不相同。下面只对常用的几种项目进行解释,更详细的内容可以参考HID类规范文档,以及专门解释Usage Page和Usage项目的文档(即《HID Usage Tables for USB》)。

主项目中的Input、Output和Feature用来定义报告中的数据通讯字段,每个项目标签之后是用来描述特性的32位数,其中前9位有不同的含义,后23位被保留。当然,HID项目中的data部分,不一定是32位数,其长度仍旧由bSize值决定。这三个项目的特性描述,如表2所示。

表2 Input、Output和Feature的特性描述

偏移 描述
00=数据,表示项目内容可改;1=常数,项目内容不可改
10=数组,表示项目描述每个控制的状态;1=变量,项目只报告作用中的控制
20=绝对,表示数值以固定值为基准;1=相对,当前数值以上一数值为基准
30=没有折行,数据不作折返处理;1=有折行,遇到最大最小界限时折返
40=线性,测量与报告数据为线性关系;1=非线性,测量与报告数据非线性关系
50=优选状态,无交互时,回到特定状态;1=非优选状态
60=没有空位置;1=空状态
70=非挥发;1=挥发,设备可以自己改变数值。此位对Input无效
80=位字段,表示每一位或每一字节内的群组位可代表一份数据;1=缓冲字节,表示信息包含一个或者多个字节,缓冲字节的报告大小必须为8
9~23 保留

表2中的Usage Page和Usage是最复杂的项目,为此USB-IF专门为它们准备了参考文档。Usage Page是全局项目,用来定义数据的用法或功能;Usage是局部项目,用来描述项目或集合的用途。

Usage Page一般和Usage,或者和Usage Minimum、Usage Maximum共同决定设备的用途。如示例1所示,这是一个常见的Usage Page和Usage的定义项目。

【示例1】Usage Page和Usage的示例。

unsigned char MyHidReportDescriptor[]={
    0x05, 0x01       //Usage Page (Generic Desktop)
    0x09, 0x02       //Usage (Mouse)
    ……            //其他数据
}

示例1中的例子,Usage Page项目的数据部分为0x01,也即Generic Desktop(通用桌面项)。而Usage项目的数据部分为0x02,可以在参考文档《HID Usage Tables for USB》介绍通用桌面项的部分,它定义了各种标识,0x02所对应的为Mouse(鼠标)。

另外需要注意的是,HID设备通过Usage Page:Usage ID的形式来确定设备的类型的。当Usage项目的bSize部分为1或2时,可以认为Usage项目就是Usage ID。如果Usage项目的bSize部分为3,也即Usage项目的数据部分有4个字节,此时高2字节将被解释为Usage Page,低2字节解释为Usage ID。也即Usage项目的数据部分,重新决定了设备用途。

后一种情况较少,常见的还是形如示例1中的情况。上述解释,同样适用于Usage Minimum项目和Usage Maximum项目。

关于HID的类描述符和报告描述符,不需要去强行记忆。大致了解了每个字段的内容,根据参考文档,结合各种实例进行修改,是基本的编程方法。

下一篇开始介绍USB标准命令和USB HID的类命令,结合上一篇和本篇的描述符内容,可从软件层面了解USB的识别和通信过程。

1,047 total views, 2 views today

发表评论

电子邮件地址不会被公开。