USB论坛-百合电子工作室USB专题站

 找回密码
 我要注册
搜索
热搜: USB学习板
查看: 5984|回复: 7

一直没搞清楚报告输入每字节各位与报告描述符之间的关系

[复制链接]

4

主题

0

好友

42

积分

产品用户

Rank: 4

发表于 2015-8-29 19:46:50 |显示全部楼层
搞USB快一个月了,主要是想搞键盘方面的东西。看了HID协议和HID使用表,就是一直搞不懂输入报告/输出报告8个字节每个位与报告描述符所描述的键值之间的关系;另外如果是102键,一个8字节的输入数据报告怎么可能对应到102键(假如每一位对应一个键的ON/OFF,也只能对应64个键啊)。
回复

使用道具 举报

6

主题

0

好友

1063

积分

管理员

Rank: 9Rank: 9Rank: 9

发表于 2015-8-30 12:48:28 |显示全部楼层
报告描述符确实非常复杂,要看懂协议真得比较难(因为只有英文的),我见到的国内教材也没有对这部分写得很详细的,有的也只是部分内容的翻译而已。

一般建议用示例报告描述符修改一下就可以了,《Hid Usage Table》里给出了一些常见应用的报告描述符。对于键盘类应用,通常用已有的示例已经够用了。

针对楼主说的那句:“如果是102键,一个8字节的输入数据报告怎么可能对应到102键(假如每一位对应一个键的ON/OFF,也只能对应64个键啊”,应该是你对键盘输入机制不理解造成的,包括传统PS2接口键盘是同样的机制。当键盘一个键按下到弹起过程,其实会发两个数据,一是按下时,会发送对应键按下的数据包,弹起时又会发一次此键没有按下的状态数据包。对于USB键盘里,如果定义的是8字节输入报告,应该是你看说的本站里USB学习板示例,本站的USB开源项目《Easy USB 51 Programer Plus》里的键盘示例,输入也是八个字节,其中第一个字节里的八个位表示八个特殊键的状态八个特殊键如图所示(《Hid Usage Table》里有哟):


为什么第一个字节对应这几个键呢,可以看报告描述符,第一个字节的用途定义(USAGE_MINIMUM)是:
[code=cpp]//用途最小值,这里为左ctrl键      
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)      
    //用途最大值,这里为右GUI键,即window键      
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)  [/code]
查查《Hid Usage Table》,是不是正好对应八个特殊功能键?

那为什么说用位来代表八个键呢,而不是一个字节代表呢,同样看报告描述符,由逻辑最小值(LOGICAL_MINIMUM)、逻辑最大值(LOGICAL_MAXIMUM)、报告大小(REPORT_SIZE0)、报告个数(REPORT_COUNT)决定的:
[code=cpp]//逻辑最小值为0      
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)      
    //逻辑最大值为1      
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)      
    //报告大小(即这个字段的宽度)为1bit,所以前面的逻辑最小值为0,逻辑最大值为1      
    0x75, 0x01,                    //   REPORT_SIZE (1)      
    //报告的个数为8,即总共有8个bits      
    0x95, 0x08,                    //   REPORT_COUNT (8)   [/code]

因为逻辑最大值是1,最小值是0,而且报告大小是1个bit,而且报告数为8个,所以正好是一个字节,注意这里不能用八个字节来表示。如果报告大小REPORT_SIZE是8,即8位,报告数REPORT_COUNT为1,那就是一个字节,如果报告数REPORT_COUNT也是8,那就是八个字节。看一看报告里的对那一个字节的输出报告定义可以加强认识。

学习报告描述符应先理解报告描述符的结构组成。下面是提取出来的关于输入报告的定义,第一个字节:
[code=cpp]//表示用途页为按键      
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)      
     
    //用途最小值,这里为左ctrl键      
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)      
    //用途最大值,这里为右GUI键,即window键      
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)      
    //逻辑最小值为0      
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)      
    //逻辑最大值为1      
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)      
    //报告大小(即这个字段的宽度)为1bit,所以前面的逻辑最小值为0,逻辑最大值为1      
    0x75, 0x01,                    //   REPORT_SIZE (1)      
    //报告的个数为8,即总共有8个bits      
    0x95, 0x08,                    //   REPORT_COUNT (8)      
    //输入用,变量,值,绝对值。像键盘这类一般报告绝对值,      
    //而鼠标移动这样的则报告相对值,表示鼠标移动多少      
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)      
    //上面这这几项描述了一个输入用的字段,总共为8个bits,每个bit表示一个按键      
    //分别从左ctrl键到右GUI键。这8个bits刚好构成一个字节,它位于报告的第一个字节。      
    //它的最低位,即bit-0对应着左ctrl键,如果返回的数据该位为1,则表示左ctrl键被按下,      
    //否则,左ctrl键没有按下。最高位,即bit-7表示右GUI键的按下情况。中间的几个位,      
    //需要根据HID协议中规定的用途页表(HID Usage Tables)来确定。这里通常用来表示      
    //特殊键,例如ctrl,shift,del键等[/code]
注意,对于输入或输出都要规定用途页(USAGE_PAGE),上面规定的用途页是键盘。第二个字节:
[code=cpp]//这样的数据段个数为1      
    0x95, 0x01,                    //   REPORT_COUNT (1)      
    //每个段长度为8bits      
    0x75, 0x08,                    //   REPORT_SIZE (8)      
    //输入用,常量,值,绝对值      
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)  [/code]
由于报告有继承性,所以第二个字节的用途页、用途最大最小值、逻辑最大最小值是和第一个字节一样的,但最后那句,定义了第二个字节是个常量,所以它应该是不变的,所以这里没有实际意义。
后面6个字节:
[code=cpp]//报告个数为6      
    0x95, 0x06,                    //   REPORT_COUNT (6)      
    //每个段大小为8bits      
    0x75, 0x08,                    //   REPORT_SIZE (8)      
    //逻辑最小值0      
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)      
    //逻辑最大值255      
    0x25, 0xFF,                    //   LOGICAL_MAXIMUM (255)      
    //用途页为按键      
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)      
    //使用最小值为0      
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))      
    //使用最大值为0x65      
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)      
    //输入用,变量,数组,绝对值      
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)      
    //以上定义了6个8bit宽的数组,每个8bit(即一个字节)用来表示一个按键,所以可以同时      
    //有6个按键按下。没有按键按下时,全部返回0。如果按下的键太多,导致键盘扫描系统      
    //无法区分按键时,则全部返回0x01,即6个0x01。如果有一个键按下,则这6个字节中的第一      
    //个字节为相应的键值(具体的值参看HID Usage Tables),如果两个键按下,则第1、2两个      
    //字节分别为相应的键值,以次类推[/code]
后面六个字节为什么是一个字节代表一个键呢,同样是由逻辑最小值(LOGICAL_MINIMUM)、逻辑最大值(LOGICAL_MAXIMUM)、报告大小(REPORT_SIZE0)、报告个数(REPORT_COUNT)决定的,用途最小值0和最大值对应hid usage table里的定义,参考表Table 12: Keyboard/Keypad Page。其实逻辑最大值和最小值之差为255,其实一个字节就可以表示255个键了。只不过一个字节不能同时表示所有键按下。

那么上面定义的报告描述符能用一个数据包表示多少个键按同时下呢,答案是8+6=14个,8个特殊功能键,用第一个字节的八个位表示,最后面的6个字节只能表示6个键同时按下。现在举几个例子来验证一下你对输入报告定义的8个字节的理解。
1、只按下左Shift时发送的八个字节:
按下时发送一次:0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
弹起时发送一次:0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
2、只按下A键时:
按下时发送一次:0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00
弹起时发送一次:0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?我要注册

回复

使用道具 举报

6

主题

0

好友

1063

积分

管理员

Rank: 9Rank: 9Rank: 9

发表于 2015-8-30 13:32:30 |显示全部楼层
3、同时按下A键和左Shift键时:
按下时发送一次:0x02 0x00 0x04 0x00 0x00 0x00 0x00 0x00
弹起时发送一次:0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

4、同时按下左Ctrl左Alt和A键时:
按下时发送一次:0x05 0x00 0x04 0x00 0x00 0x00 0x00 0x00
弹起时发送一次:0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

5、同时按下A键和B键时:
按下时发送一次:0x00 0x00 0x04 0x05 0x00 0x00 0x00 0x00
弹起时发送一次:0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
回复

使用道具 举报

4

主题

0

好友

42

积分

产品用户

Rank: 4

发表于 2015-9-3 17:42:19 |显示全部楼层
baiheee 发表于 2015-8-30 13:32
3、同时按下A键和左Shift键时:
按下时发送一次:0x02 0x00 0x04 0x00 0x00 0x00 0x00 0x00
弹起时发送一 ...

那请问如果我想实现101键,就是普通的PC键盘,通过一个8字节大小的中断输入端点1来实现,报告描述符是怎么样的,端点1中断输入的8个字节各个位的数据与键值又是怎么个对应关系?
谢谢。
回复

使用道具 举报

6

主题

0

好友

1063

积分

管理员

Rank: 9Rank: 9Rank: 9

发表于 2015-9-4 09:41:48 |显示全部楼层
就用我给出的报告描述符就可以啊,可实现的按键已经不止101键了,各个字节及位怎么表示按键已经说得很清楚了
回复

使用道具 举报

4

主题

0

好友

42

积分

产品用户

Rank: 4

发表于 2015-9-8 15:51:37 |显示全部楼层
baiheee 发表于 2015-8-30 12:48
报告描述符确实非常复杂,要看懂协议真得比较难(因为只有英文的),我见到的国内教材也没有对这部分写得很 ...

有个怪现象:我发一次0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00,电脑里一直出来aaaaaa......;如果我发一次0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00,跟着发一次0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00,电脑里面就只出来一个a了。
这是怎么回事呢
回复

使用道具 举报

4

主题

0

好友

42

积分

产品用户

Rank: 4

发表于 2015-9-8 15:52:40 |显示全部楼层
有个怪现象:我发一次0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00,电脑里一直出来aaaaaa......;如果我发一次0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00,跟着发一次0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00,电脑里面就只出来一个a了。
这是怎么回事呢
回复

使用道具 举报

6

主题

0

好友

1063

积分

管理员

Rank: 9Rank: 9Rank: 9

发表于 2015-9-8 20:11:43 |显示全部楼层
Andrewyancn 发表于 2015-9-8 15:52
有个怪现象:我发一次0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00,电脑里一直出来aaaaaa......;如果我发一次 ...

你还没明白键盘输入的机制,如果键盘发一个键值给系统,系统认为此键按下,如果没有发弹起的消息,就认为此键一直按下
回复

使用道具 举报

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

USB开发网 (渝ICP备09006681号-4)

GMT+8, 2022-8-14 02:07 , Processed in 0.054372 second(s), 20 queries .

百合电子工作室版权所有
回顶部