原创 HID报告描述符(Report Descriptor)脚本语言研读笔记

2009-3-6 16:08 4081 9 9 分类: 通信
HID报告描述符(Report Descriptor)脚本语言研读笔记1

文章来源:http://gliethttp.cublog.cn[转载请声明出处]

  HID的Report Descriptor报告描述符已经不是简简单单的描述某个值对应某个固定意义了,
它已经能够组合出很多种情况,并且需要pc上的HID驱动程序提供parser解释器来对
描述的设备情形进行重新解释,进而组合生成出本HID硬件设备独特的数据流格式,
所以我觉得可以把它理解为--报告描述符脚本语言--HID script,虽然它确实简单了点,但是
我觉得这么称呼报告描述符的这种行为能力,比较爽一些,而且似乎也算是贴切(gliethttp).

  作为HID脚本语言,它有它的独特的语言关键字定义:
Global item--全局项
Main item --主项
local item --局部项
Push --state table中的所有局部项值入栈
Pop --所有入栈的局部项值出栈到state table
...还有很多,可以参见<HID协议.pdf>

  用户通过HID script专有脚本描述语言定义的Report Descriptor报告描述符,由usb设备端提供,
之后由pc上的HID专有parser解释器对usb提供的报告描述符进行处理,之后
pc对usb设备将要上传的数据成分会一清二楚.

  最后由用户通过Report Descriptor的script专有脚本描述语言,个性定制出来的
将要被usb一次性发送的数据流,会交由pc操作系统指定的HID驱动程序中相应的API函数
(鼠标数据处理函数或者键盘数据处理函数)对数据串中的相应bits们进行解释,
最后影响到pc操作系统(鼠标单击、移动或者键盘数据)

  对于HID设备的定义,需要注意:
HID的类码,是定义在接口描述符中的,至于接口描述符中的,子类码,其值不是用来区分mouse
或者keyboard的,因为HID设备形形色色,五花八门,HID协议制订者们,不希望,使用简单的子类码来
区分各种HID设备,而是采用一种更加灵活的方式---"报告描述符",原因很简单:多么好的规定,
随着产品应用中的不断创新和花样翻新,都会最后限定住用户对协议更丰富、更个性、更灵活的需求,
所以使用"报告描述符"专用脚本语言,让用户来自己定义他们的HID设备都有什么数据、以及这些
数据各个bit都有什么意义,之后位于pc上的HID驱动程序将通过parser解释器,
用户使用HID专用脚本语言描述的数据情形--"报告描述符",进行数据拼接,
最后pc的HID驱动程序将明确的知道,usb设备上传过来的数据的各个bit位的意义,
进而将相应意义下的bits位们,送到pc上HID驱动程序对应的API接口上进行bits数据处理,
这些API可能是用于mouse的X、Y坐标管理的,也可能是用于keyboard的-LED指示灯管理的.

  因为HID"报告描述符"脚本语言的parser解释器代码比较大,所以对于BIOS来说不太现实,
因此需要把HID设备的接口描述符中的子类码值设置为1,
进而能够在BIOS启动时识别并使用你的HID硬件设备,当然前提是,你用HID脚本语言描述的
mouse或者keyboard的数据流格式必须和BIOS固定的格式相符才行,
如果设置为0,HID硬件就不提供BIOS支持,
所以我们的HID硬件设备只有当进入pc操作系统,并且pc操作系统的HID驱动加载完成之后,
才能被识别和使用,不过对于嵌入式系统,尤其我[gliethttp]的at91rm9200板子来说,没有多少意义,
因为这里说的BIOS是PC的BIOS,at91rm9200不提供那么复杂的BIOS,仅仅提供传递信息参数的uboot之类,
所以完全没必要设置成1.

  HID设备的接口描述符中的接口协议部分用来宏观定义设备类型,
1--keyboard设备
2--mouse设备
因为HID有了"报告描述符"脚本语言,所以设备的所有具体信息都可以用脚本来描述,
所以从这个角度来说,接口描述符中的接口协议部分也没有存在的意义,
至于需不需要定义,那就看你做的HID设备是否支持BIOS了,
只有当BIOS启动标志位置位1时,接口描述符中的接口协议部分才有意义,因为BIOS中的代码
将使用这个位值,来判断接入到pc主板上的是mouse设备,还是keyboard设备,
进而BIOS将决定,由HID设备送上来的被BIOS限定好格式的数据流,
该交由mouse数据处理程序做,还是交由keyboard数据处理程序做.

  HID设备必须具备控制管道--:端点0,
和至少一个IN管道--用来传递HID设备数据,
至于host主机输出到HID设备中的OUT型数据,可以通过OUT管道专门传送,
也可以间接通过控制管道的OUT通道传输,
所以当我们定义了OUT管道后,枚举之后,pc的HID驱动就会通过该OUT管道
传递,如果我们没有定义OUT管道,那么控制管道的OUT通道就将作为传递
OUT型数据的间接管道.

以上是我[gliethttp]近3天的零散的研读心得,其他的继续研读中,说实话,english文档确实比较难啃,
就那些语句的逻辑关系就搞的人头大,tnnd,不过还好,兴趣还算足,还能勉强的出现津津有味的情况...
对HID Script脚本语言的理解:
Global item--全局项
Main item --主项
local item --局部项
  对于Main项,parser解释器,将顺序解释集合中的数据,并且,解释器解释完的数据,
将按Main项出现的先后顺序,主要是Input和Output项,顺序拼接生成对应的数据bit位,
解释器将以关键字Collection开始解释并拼接bit位信息,关键字End Collection将
结束paser解释器的工作,我把关键字Collection和关键字End Collection叫做"集合",
这样给他取个名字,以后说明起来也方便些,"集合"里边描述的就是最后生成的
由HID硬件设备1次性上发给pc的HID驱动程序的数据流了.<HID协议.pdf>,(gliethttp)
关键字Collection和关键字End Collection都是Main item主项,对应的控制字分别为:
1010 00 nn和1100 00 nn,如果Collection后边有1个参数数据,那么即为:
1010 00 01=0xA1,如Collection(Application)
翻译成控制码后为:0xA1,0x01;0xA1的1表示有1个参数数据,0x01表示Application在HID
协议中规定的索引值为0x01,pc的HID驱动程序在parser解释器中会通过0x01得知,
是对Application进行数据流位生成,就是说HID报告描述符(Report Descriptor)
所描述的数据流是为了Application使用的,Application在<HID协议.pdf>中包含
两种设备:mouse和keyboard,至于Collection(Application)里边描述的是mouse
还是keyboard,将具体的由Usage进一步限定,:Usage(KeyBoard),也就是说明确
告诉pc的HID驱动程序的paser解释器,接下来的这段信息最后生成出来的bits位数据信息,
将交由pc的HID驱动程序中KeyBoard对应的API函数处理,当然这只是HID硬件设备开发者
给pc的HID驱动程序的paser解释器提供的一个建议值,比如我们做DDK下的HID驱动二次开发,
那么我们可以很随意,但是HID硬件设备开发者,建议使用的HID驱动程序API接口,最好遵守,
因为HID硬件设备开发者比DDK开发人员更清楚送上来的bit数据流的真正物理意义.
  Input和Output是用来真正生成bits位流数据域的关键字,他们描述的东西是最后通过
usb总线实实在在发送到pc或者从pc接收的数据位,当然这些bits数据流数据域所代表的意义
以及某段bits位们所代表的意思以及这些bits将交由pc上HID驱动程序的哪一个API接口
来做进一步解析(是mouse还是keyboard),需要其他描述符来描述,比如前边的Usage就是其中的1个描述符,
  如果一个HID设备同时提供2种不同的功能,那么就会分别生成2个bits位流数据域,
每个bits位流数据,将交由不同的驱动解析,比如,一个keyboard可能还集成了一个附属的鼠标功能,
那么键盘数据信息将由HID script脚本描述的keyboard对应bits数据位流传送,mouse数据将由
HID script脚本描述的mouse对应bits数据位流传送,但同一个Input管道怎么能传送两个独立的
数据流呢,答案很简单:不能,所以又引入了一个Report ID的概念,ID用来标识多条独立的bits数据流,
pc的HID驱动程序根据ID,将这些独立的bits数据流们路由到相应的API处理函数上去,
进而不同的bits数据流数据最终都能够被自己对应的API驱动函数正确接收并解析处理.
  对于2字节、4字节等多字节数据的传输,是按小端模式little-endian进行的.
些多字节数据的最小值由Logical Minimum定义,最大值由Logical Maximum定义,如果两个值均为非负
,那么bits位流数据就是无符号数,如果没有明确指定,那么作为有符号数处理,另外HID1.1协议
不允许传输浮点数据.
  硬件开发者应该时刻清除自己写的HID script脚本所描述的数据流将来应该由PC上的HID驱动程序
怎么使用,另外对于硬件开发者来说,对于不允许PC驱动修改的bit位数据,HID1.1协议制定者强烈建议
采用NULL数值,最好不要随便填其他值.
----------------------------------------------
Main item --主项当前一共5个:
1)Input
2)Output
3)Feature
4)Collection
5)End Collection
----------------------------------------------
Global item--全局项当前一共13个:
1)Usage Page
2)Logical Minimum ---var变量或array数组的逻辑最小值
3)Logical Maximum
4)Physical Minimum
5)Physical Maximum
6)Unit Exponent ---单位的指数值,是10的指数
7)Unit ---单位索引号:可以是时间单位、电流单位、电压单位和距离单位等等.
8)Report Size
9)Report ID ---数据流的ID值设置
10)Report Count
11)Push
12)Pop
13)Reseved ---保留
----------------------------------------------
local item --局部项当前一共11个:
1)Usage ---定义Uage Page下面某个功能item的起始索引值,比如Keyboard功能,LEDs功能等,
                       这也告诉pc的HID解释器,Input或Output变量或数组的相应生成数据位用来描述
                       Usage引用到的那个功能,:用来描述Keyboard功能或LEDs功能等.
2)Usage Minimum ---定义与array或bitmap关联的usage定义的某个功能下的起始值
                       Usage作为Uage Page的一个子功能索引号,同时Usage自己也有很多子功能,或者
                       说有很多个子值,这里就是定义这些子值的范围值,之后和用Input或Output生成
                       bits位数据流,进行相应关联.(可以用多维数组来说明,可能会更明确一点)
                       如:Gliethttp[5][6][80],Gliethttp为最上层,5就是Usage Page(5),6就是在
                       前一个基础上Usage(6),当然在HID Descriptor Tool里边6有它的字符串名,:
                       Usage(Keyboard),然后80就是Keyboard里边的一个索引取值,查找之后是:
            KeyBoard LeftArrow,所以Usage_Minimum(80)就等于Usage_Minimum(KeyBoard LeftArrow)
                       Usage的顺序先后和Report Count定义的bits位组的先后顺序依次一一对应,Usage Minimum和

                          Usage Maximum之间的Usage的索引值也将依次与Report Count定义的bits位组的先后顺序


                          依次一一对应上。
3)Usage Maximum ---定义与array或bitmap关联的usage的结束值
4)Designator Index
5)Designator Minimum
6)Designator Maximum
7)String Index
8)String Minimum
9)String Maximum
10)Delimiter
11)Reserved
local的作用范围不会延续到下一个Main item,下一个Main item开始的local值会
自动恢复到local的默认值;如果local item定义开始到下一个Main item之间的
Report Count=0,那么local item的属性值将作用在下一个Main item上(通常是Collection)
  以上部分内容来自<HID协议.pdf>,部分内容是自己的揣测式理解,可能有不正确之处,要是能够拿到
HID Descriptor Tool工具的源码就能够清除pc的HID驱动程序下的parser解释器到底是
怎么处理以上关键字的了,linux里边可能有,如果大家打算再深入一些的话,我想你可以到linux
的源程序里边去看看,那里有parser解释器的全部源程序,不过对于我来说,以上的这些知识基本上
就够用了,再往往深入走,对我已经没有什么用了,所以就到这里;这2篇研读笔记是我在english文档中辛苦的总结,
希望能够对刚刚开始做HID这方面工作的同行们有一点点积极的作用(gliethttp).


文章评论0条评论)

登录后参与讨论
我要评论
0
9
关闭 站长推荐上一条 /2 下一条