<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
现在在我手上,有三本书:《USB2.0硬件设计》、《圈圈教你玩USB》和《基于MKD的STM32处理器应用开发》。我都翻到了与 报告描述符相关的部分,边看、边理解、边记录。
一、HID类与报告描述符
1、设备类和接口类的含义
为了使USB设备的开发标准化,USB定义了许多标准设备类、设备子类,好处是如果你遵循这些设备类的控制要求,有时候可以不用开发上位机上的驱动程序,因为windows已经自带了驱动。即使没有相应的驱动,也会使驱动开发更为简单。
特别是有些标准系统设备,连应用程序都可以不用开发,真正的“即插即用”,比如USB鼠标、USB键盘和U盘。
通过“JoyStickMouse”例程的学习,我发现在描述符中有两处讲到了设备类。
一是设备描述符第4、5、6字节,分别表示设备类、子类和协议。
二是接口描述符第5、6、7字节,分别表示接口类、子列和协议。
它们之间有什么关联呢?书上都没有详细的说明,求助于网络。搜到了下面一片文章,讲得比较详细。我就留下链接,把表复制过来。有兴趣的可以去源地址查看全文。
Base Class | Descriptor Usage | Description |
00h | Device | |
01h | Interface | |
02h | Both | |
03h | Interface | |
05h | Interface | |
06h | Interface | |
07h | Interface | |
08h | Interface | |
09h | Device | |
0Ah | Interface | |
0Bh | Interface | |
0Dh | Interface | |
0Eh | Interface | |
0Fh | Interface | |
DCh | Both | |
E0h | Interface | |
EFh | Both | |
FEh | Interface | |
FFh | Both |
上面这个表指明了只有类“02”、“DC”、“EF”和“FF”可以将类代码写在设备描述符中,“09”HUB类必须将设备类代码写在设备描述负重。其它的设备类、协议都必须放在接口描述符中。
HID设备设备类代码03,子类表示是否支持启动,协议与是否支持启动有关。对于普通应用没有意义,都写成0也可以。
那么对于HID设备,到底加载什么类型的驱动呢?实际上这取决于“报告描述符”中对“用途页、用途”的指定。
如果要使用自定义设备,则需要自己开发驱动,设备类代码设定为“FF”。
2、鼠标的报告描述符分析
《圈圈教你玩USB》的“4.8 再谈USB HID的报告描述符”对其结构、特性做了详细的分析,我从中学到了不少。
(1) 报告描述符主要是为了描述报告的结构、用途。
(2) 指定位域作用时,同时指明用途页、用途。
(3) 指明用途可以一个个指定、可以指明最大值和最小值。
(4) Sel 和 Ary:这个在实例中阐明。
(5) 基本用途类型:集合、控制、数据。
(6) 鼠标、游戏杆、键盘都属于集合类用途。
(7) 音量控制、键盘LED开关控制、鼠标按键控制属于控制类用途。
(8) 选择器、动态标志、动态值属于数据类用途。
后面这几个,还理解得不是很好。
const u8 Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =
{
0x05, 0x01, /*Usage Page(Generic Desktop)*/
0x09, 0x02, /*Usage(Mouse)*/ 用途鼠标属于集合类,可以开集合,以下所以数据都在这四个字节的控制范围内。主机读到以上信息后,就会将该设备视为标准系统设备“鼠标”。
0xA1, 0x01, /*Collection(Logical)*/ //这个应用集合一直作用到报告最后。
0x09, 0x01, /*Usage(Pointer)*/ //这里又开了一个子集合,用途为指针,集合为物理集合。0x05, 0x01的作用域到了这儿,所以这个集合仍然属于Generic Desktop
0xA1, 0x00, /*Collection(Linked)*/
0x05, 0x09, /*Usage Page(Buttons)*/
0x19, 0x01, /*Usage Minimum(1)*/
0x29, 0x03, /*Usage Maximum(3)*/
以上六个字节说明了这是按键用途页,下面的01到03说明是控制类用途,可以确定,这个主条目有三个数据域。
0x15, 0x00, /*Logical Minimum(0)*/ 每个数据域是1位。
0x25, 0x01, /*Logical Maximum(1)*/
0x95, 0x03, /*Report Count(3)*/ 3个数据域
0x75, 0x01, /*Report Size(1)*/ 每个大小为1位。
0x81, 0x02, /*Input(Variable)*/
//一个数据集合到此结束。81是一个输入主条目,02表示数据的性质为“数据、变量、绝对值。但是这个数据域只占了一个字节的3位,所以下面需要一个数据集合填满高5位。
0x95, 0x01, /*Report Count(1)*/
0x75, 0x05, /*Report Size(5)*/
0x81, 0x03, / 主条目结束,填充5位常数,构成一个字节。
// 0x01, 原来数据为0x01,这里改为03后,每位表示独立的常量
0x05, 0x01, /*Usage Page(Generic Desktop)*/
0x09, 0x30, /*Usage(X axis)*/
0x09, 0x31, /*Usage(Y axis)*/
0x09, 0x38, /*Usage(Wheel)*/这里单独指明了三个用途。与前面的Usage Minimum——Usage Maximum有异曲同工之妙,也是指明三个数据域。
0x15, 0x81, /*Logical Minimum(-127)*/
0x25, 0x<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />7F, /*Logical Maximum(127)*/这里指明了数据的范围,从-127到127,每个数据域至少8位。
0x75, 0x08, /*Report Size(8)*/
0x95, 0x03, /*Report Count(3)*/
0x81, 0x06, /*Input(Variable, Relative)*/
//这里数据的性质是相对值,针对鼠标X、Y方向和滚轮。
0xC0, /*End Collection*/ //关掉了指针物理集合,鼠标应用集合还没有关
0x09, 0x3c, //这是一个局部条目,表示运动唤醒。全局条目性质仍然是:0x05, 0x01 (Generic Desktop)
0x05, 0xff, //这是一个全局条目用途页,由用户自己定义
0x09, 0x01, //局部条目用途,由用户自己定义,这里的意思没有弄明白,在程序中好像也没有用到。
0x15, 0x00, //全局条目,逻辑最小值
0x25, 0x01, //全局条目,逻辑最大值 说明数据域为1位。
0x75, 0x01, //全局条目 ,数据长度1位
0x95, 0x02, //全局条目,数据的数量2个。
0xb1, 0x22, //主条目,Feature,变量,数组,非优选状态
0x75, 0x06, //全局条目 ,数据长度6位
0x95, 0x01, //全局条目 ,数量为1个。填充6个凑满一个字节。
0xb1, 0x01, //主条目,Feature,常数
0xc0 //关鼠标应用集合。
}
二、改造成键盘报告描述符
1、改造的目的
我的开发板上可以实现7个键,除了PB3按钮用于退出,还有六个键可以用于键盘。分配如下:
OK键用于“左GUI键”,就是那个一按就显示开始菜单的按键;
PB2用于“左Ctrl”。
上右下左分别表示“abcd”。
通过这样分析,报告描述符输入部分需要2个字节(除了ctrl、shift外,不支持多键同时按下)。
输出部分用一个字节,其中用第1位表示大小写是否打开,并且用于控制开发板上“唯一的可控Led”。
这个报告描述符将用于实现USB键盘。
2、键盘报告描述符
以下报告描述符结合上面的鼠标报告描述符,并且借鉴了圈圈书中的报告描述符代码。
const u8 Keyboard_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =
{
0x05, 0x01, /*Usage Page(Generic Desktop)*/
( 0x09, 0x02, /*Usage(Mouse)*/ 用途鼠标属于集合类,可以开集合,以下所以数据都在这四个字节的控制范围内。主机读到以上信息后,就会将该设备视为标准系统设备“鼠标”。)
0x09, 0x06 //06表示键盘用途。
0xA1, 0x01, /*Collection(Logical)*/ //这个应用集合一直作用到报告最后。
(0x09, 0x01, /*Usage(Pointer)*/ //这里又开了一个子集合,用途为指针,集合为物理集合。0x05, 0x01的作用域到了这儿,所以这个集合仍然属于Generic Desktop
0xA1, 0x00, /*Collection(Linked)*/ )
现在不需要物理集合了,应用集合将包含所有的数据。
(0x05, 0x09, /*Usage Page(Buttons)*/)
0x05, 0x07, //把用途页改变为按键
0x19, 0xe0, /*Usage Minimum(1)*/
0x29, 0xe7, /*Usage Maximum(3)*/
0x15, 0x00, /*Logical Minimum(0)*/ 每个数据域是1位。
0x25, 0x01, /*Logical Maximum(1)*/
0x95, 0x08, /*Report Count(3)*/ 3个数据域
0x75, 0x01, /*Report Size(1)*/ 每个大小为1位。
0x81, 0x02, /*Input(Variable)*/
//一个数据集合到此结束。81是一个输入主条目,02表示数据的性质为“数据、变量、绝对值。但是这个数据域只占了一个字节的3位,所以下面需要一个数据集合填满高5位。
0x05, 0x07, /*键盘控制用途页*/
0x19, 0x00, /*Usage 最小值0*/
0x29, 0x65, /*Usage 最大值101*/
0x15, 0x00, /*Logical Minimum(0)*/
0x25, 0xFF, /*Logical Maximum(255)*/这里指明了数据的范围,从0到255,每个数据域至少8位。
0x75, 0x08, /*Report Size(8)*/
0x95, 0x01, /*Report Count(1)*/
0x81, 0x00, /*Input(Variable, Array)*/
//这里数据的性质是数据、数组、绝对值。
//又一个数据集合结束。一个字节。输入共两个字节。
0x05, 0x07, /*LED用途页*/
0x19, 0x00, /*Usage 最小值0*/
0x29, 0x03, /*Usage 最大值3*/ 表示有3个数据域
0x15, 0x00, /*Logical Minimum(0)*/
0x25, 0x01, /*Logical Maximum(1)*/这里指明了数据的范围,从0到1,每个数据域为1位。
0x75, 0x01, /*Report Size(1)*/
0x95, 0x03, /*Report Count(3)*/
0x91, 0x02, /*Output(Variable, Abs)*/
//输出3个位。
0x75, 0x01, /*Report Size(1)*/
0x95, 0x05, /*Report Count(5)*/
0x91, 0x03, /*Output(Constant, Abs)*/
//输出5个位。常数。
//加上上面的3位,构成输出一个字节。
0xc0 //关键盘应用集合。
}
文章评论(0条评论)
登录后参与讨论