对报告描述符里主项目input和output的理解(原)

 1 code char MouseReportDescriptor[29] = {    
 2     0x06,0x00,0xFF,             //USAGE_PAGE (Vendor Defined Page 1)     
 3     0x09,0x01,              //USAGE (Vendor Usage 1)     
 4     0xA1,0x01,              //COLLECTION (Application)     
 5    
 6     0x19,0x01,              //(Vendor Usage 1)     
 7     0x29,0x08,              //(Vendor Usage 1)     
 8     0x15,0x00,              //LOGICAL_MINIMUM (0)     
 9     0x26,0xFF,0x00,             //LOGICAL_MAXIMUM (255)     
10     0x75,0x08,              //REPORT_SIZE (8)     
11     0x95,0x40,              //REPORT_COUNT (64)     
12     0x81,0x02,              //INPUT (Data,Var,Abs)     
13    
14     0x19,0x01,              //(Vendor Usage 1)     
15     0x29,0x08,              //(Vendor Usage 1)     
16     0x91,0x02,              //OUTPUT (Data,Var,Abs)     
17    
18     0xC0                    // END_COLLECTION    
19 };   

此报告描述符描述的是厂商自定义设备,定义了64个字节的输入输出数据。

首先是input(Data,Var,Abs),然后是output(Data,Var,Abs)。之前一直很困惑,这里定义了输入输出报告,那到底什么时候发送数据呢?白皮书上也没有解释,我就自己理解为这段报告描述符是告诉系统如果收到input报告的数据,就立即向设备output数据。这一点还在键盘的报告描述符里得到验证。

 
 1 code char MouseReportDescriptor[63] = {    
 2     //表示用途页为通用桌面设备    
 3     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)    
 4    
 5     //表示用途为键盘    
 6     0x09, 0x06,                    // USAGE (Keyboard)    
 7         
 8     //表示应用集合,必须要以END_COLLECTION来结束它,见最后的END_COLLECTION    
 9     0xa1, 0x01,                    // COLLECTION (Application)    
10         
11     //表示用途页为按键    
12     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)    
13    
14     //用途最小值,这里为左ctrl键    
15     0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)    
16     //用途最大值,这里为右GUI键,即window键    
17     0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)    
18     //逻辑最小值为0    
19     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)    
20     //逻辑最大值为1    
21     0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)    
22     //报告大小(即这个字段的宽度)为1bit,所以前面的逻辑最小值为0,逻辑最大值为1    
23     0x75, 0x01,                    //   REPORT_SIZE (1)    
24     //报告的个数为8,即总共有8个bits    
25     0x95, 0x08,                    //   REPORT_COUNT (8)    
26     //输入用,变量,值,绝对值。像键盘这类一般报告绝对值,    
27     //而鼠标移动这样的则报告相对值,表示鼠标移动多少    
28     0x81, 0x02,                    //   INPUT (Data,Var,Abs)    
29     //上面这这几项描述了一个输入用的字段,总共为8个bits,每个bit表示一个按键    
30     //分别从左ctrl键到右GUI键。这8个bits刚好构成一个字节,它位于报告的第一个字节。    
31     //它的最低位,即bit-0对应着左ctrl键,如果返回的数据该位为1,则表示左ctrl键被按下,    
32     //否则,左ctrl键没有按下。最高位,即bit-7表示右GUI键的按下情况。中间的几个位,    
33     //需要根据HID协议中规定的用途页表(HID Usage Tables)来确定。这里通常用来表示    
34     //特殊键,例如ctrl,shift,del键等    
35      
36    
37     //这样的数据段个数为1    
38     0x95, 0x01,                    //   REPORT_COUNT (1)    
39     //每个段长度为8bits    
40     0x75, 0x08,                    //   REPORT_SIZE (8)    
41     //输入用,常量,值,绝对值    
42     0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)    
43         
44     //上面这8个bit是常量,设备必须返回0    
45    
46    
47     //这样的数据段个数为5    
48     0x95, 0x05,                    //   REPORT_COUNT (5)    
49     //每个段大小为1bit    
50     0x75, 0x01,                    //   REPORT_SIZE (1)    
51     //用途是LED,即用来控制键盘上的LED用的,因此下面会说明它是输出用    
52     0x05, 0x08,                    //   USAGE_PAGE (LEDs)    
53     //用途最小值是Num Lock,即数字键锁定灯    
54     0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)    
55     //用途最大值是Kana,这个是什么灯我也不清楚^_^    
56     0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)    
57     //如前面所说,这个字段是输出用的,用来控制LED。变量,值,绝对值。    
58     //1表示灯亮,0表示灯灭    
59     0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)    
60    
61     //这样的数据段个数为1    
62     0x95, 0x01,                    //   REPORT_COUNT (1)    
63     //每个段大小为3bits    
64     0x75, 0x03,                    //   REPORT_SIZE (3)    
65     //输出用,常量,值,绝对    
66     0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)        
67     //由于要按字节对齐,而前面控制LED的只用了5个bit,    
68     //所以后面需要附加3个不用bit,设置为常量。     
69    
70     //报告个数为6    
71     0x95, 0x06,                    //   REPORT_COUNT (6)    
72     //每个段大小为8bits    
73     0x75, 0x08,                    //   REPORT_SIZE (8)    
74     //逻辑最小值0    
75     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)    
76     //逻辑最大值255    
77     0x25, 0xFF,                    //   LOGICAL_MAXIMUM (255)    
78     //用途页为按键    
79     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)    
80     //使用最小值为0    
81     0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))    
82     //使用最大值为0x65    
83     0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)    
84     //输入用,变量,数组,绝对值    
85     0x81, 0x00,                    //   INPUT (Data,Ary,Abs)    
86     //以上定义了6个8bit宽的数组,每个8bit(即一个字节)用来表示一个按键,所以可以同时    
87     //有6个按键按下。没有按键按下时,全部返回0。如果按下的键太多,导致键盘扫描系统    
88     //无法区分按键时,则全部返回0x01,即6个0x01。如果有一个键按下,则这6个字节中的第一    
89     //个字节为相应的键值(具体的值参看HID Usage Tables),如果两个键按下,则第1、2两个    
90     //字节分别为相应的键值,以次类推。    
91    
92     //关集合,跟上面的对应    
93     0xc0                           // END_COLLECTION    
94 };   

 当按下Num Lock键时,PC会发送输出报告,从报告描述符中我们知道,Num Lock的LED对应着输出报告的最低位,
当数字小键盘打开时,输出xxxxxxx1(二进制,打x的由其它的LED状态决定);
当数字小键盘关闭时,输出xxxxxxx0(同前)。取出最低位就可以控制数字键锁定LED了。

用Bus Hound软件可捕捉到输入输出数据。

后来才发现自己的理解是错的。报告描述符里只规定了报告的格式,即每个字节,每个位是表示什么意思,没有说明输入输出的时间,这中间不存在顺序关系。键盘的报告描述符里,output报告规定了哪一个位对应哪一个LED灯的状态,并没有说设备产生一个Input报告后,系统一定会有一个Output报告出来。Output报告的产生是要看按键有没有改变LED灯的状态了,如果改变了,则有output报告输出,如果按键不影响LED灯的状态,系统也没有必要输出output报告。

当然了,这只是我的理解,有不同意见,欢迎交流。

posted on 2012-11-23 17:02  nubia101  阅读(1801)  评论(0编辑  收藏  举报

导航