原创 【转】USB/HID设备报告描述符详解2

2011-1-10 20:38 3238 19 19 分类: MCU/ 嵌入式

区域性项目卷标:
简单地说,区域性项目(见表1)只是说明用途而已。Designator是要搭配实体描述符使用的,这里不对实体描述符进行介绍,所以略过这些designator标签。
标签Usage 实际上应该称作Usage ID,它搭配全域项目的Usage Page 卷标才形成前文所定义的用途{usage}﹔但是报告描述符允许在区域项目的Usage 卷标直接用32位的方式来指定用途,这种方式称作扩充式用途指定法(extended usage)以示区别。例如:Usage(Generic Desktop:Mouse),Usage Minimum(Keyboard:0),和Usage Maximum(Keyboard:101)。很明显的,扩充式用途指定法会取代『项目状态表』中的Usage Page。还有,使用扩充式用途指定法时,数据的高16 个位为用途类页Usage Page,低16 个位则为用途识别名Usage ID。往往一个报告数据会对应到几个操作,因而会有几个用途,例如101 按键的键盘利用不同代码代表不同的键,每一个键是一个操作,有自己的用途,要将所有Usage ID 列出不太现实,所以就需要Usage Minimum 和Usage Maximum 二个标签。以键盘为例,主项目之上只要二个区域项目:Usage Minimum (0), Usage Maximum (101)。如此一来,则无键按下(Usage ID 为0)和101 键中任一键被按下(Usage ID 为1 至101)的用途都被赋于到一个报告数据上,后面会有一个范例进一步解说。
卷标String Index 类似卷标Usage,而卷标String Minimum 和String Maximum 则类似标签Usage Minimum 和Usage Maximum。如果希望某个操作对应到一个字串,则用String Index 来描述该操控的报告数据,这个字符串在字符串描述符中,StringIndex (data)项目中的data 是这个字符串在字符串描述符中的位置索引。如果需要用到几个字符串,则可以使用String Minimum 来指向字符串描述符中被用到字符串的最先位置索引,和String Maximum 来指向最后位置索引。
标签Delimiter 很少用到,请参考Universal Serial Bus HID Usage Tables 文件中Appendix B 的范例详细说明。

全局项目卷标
全局项目的卷标事实上只要Usage Page,Logical Minimum,Logical Maximum,
Report Size,Report ID,Report Count 就足够了。表2 列了二个音量操作的例子(音量增减键和音量旋钮)将用来辅助说明这些卷标,不过主项目括号内的数据会在后文中再做说明。
表2、音量操作举例
音量减键 音量旋钮
Usage Page(consumer) Usage Page(Consumer)
Usage(Volume) Usage(Volume)
Logical Minimum(-1) Logical Minimum(0)
Logical Maximum(1) Logical Maximum(100)
Report Size(2) Report Size(7)
Report Count(1) Report Count(1)
Input(Data,Variable,Relative) Input(Data,Variable,Absolute,No Wrap,Linear,No Relative)


 
查阅Universal Serial Bus HID Usage Tables 文档,这两个例子的用途需要令为(Consumer: Volume)。Usage Page 前面已经介绍过了。Report Size 用来设定主项目(Input,Output,Feature)的报告字段大小,它的单位是位。主项目会对每个操作产生一个报告字段,字段大小则由Report Size 决定。而Report Count 用来设定主项目之报告字段的数目,其等于操作的数目。音量增减键的例子中ReportCount (1)表示主项目Input 只产生一个字段,所以可知只有一个音量增减键﹔而Report Size (2)表示这个字段为2 位。另一个音量旋钮例子也是只有一个旋钮,所以用Report Count (1)﹔但是因为Report Size (7),所以该旋钮的数据字段为7位,可以表示0到127之数值。再举一例,如果是鼠标的三个按键,每个按键占用一个一位的字段,则Report Size (1), Report Count (3)﹔那么这个报告长度为三个位,可以同时呈现出三个按键的状态(原状或被按下)。
Logical Minimum 和Logical Maximum 在说明每个报告字段的数值范围,这是纯数值所以称为逻辑数值(logical value)。音量增减键的例子中Logical Minimum (-1),Logical Maximum (1)表示只会出现-1, 0, 1 三种数值,所以用到二位(即ReportSize(2)),0b11 代表-1,0b00 代表0,0b01 代表1。在音量旋钮例子中,虽然用7 位作一字段,但是旋钮仅会产生0 到100 的数值,因为Logical Minimum (0)和Logical Maximum (100)。假如实体程序错误产生超出逻辑数值的范围,则主机将会忽略该数值,这种数值称作null value。
当要将同一种报告分成数个部分,则每一个部分要给予一个识别值,这时就需用到卷标Report ID,其数据值必须从1起算,不可使用0。没有赋予Report ID 标签的报告,主机有可能会将其Report ID 视为0,所以Report ID (0)被要求不能使用。这个标签对控制型管线才有意义,因为它可以在请求报告时指定Report ID的值。对于中断型管线,其为周期性传输报告,所以每次都会将所属报告传完,没有仅传输部分之必要,所以Report ID 标签就无意义。
其它的全局项目卷标可分为辅助工具(Push 和Pop)和物理量说明(Physical Minimum,Physical Maximum,Unit Exponent,和Unit)。Push 卷标将『项目状态表』存放到缓存器(stack),而Pop 卷标反过来将缓存器最顶层的『项目状态表』取回来取代目前之状态表。这二个标签对很长的报告描述符才有用处,因为其可以节省多列一些全局项目。读者当要使用到时,参考Universal Serial Bus HIDUsage Tables 文件的Appendix A.7 节中范例则可获得正确使用方式。
不同厂家的鼠标有不同的分辨率,若要让主机知道鼠标的分辨率,就必须用到物理量的标签。不使用也不会影响到鼠标的功能,只是使用者无法由主机的驱动程式得知分辨率而已。但是量测装置(例如温度计)的应用程序必须知道物理量,则这些标签就必备了。分辨率r 的算法如下
     r = ((lM-lm)/(PM-Pm))X10iUnit
其中lm = Logical Minimum,lM = Logical Maximum, pm = Physical Minimum,pM = Physical Maximum, i = Unit Exponent。以400-dpi 的鼠标为例如表3。
表3:解析度的范例
Logical Minimum(-127) R = ((127-(-127))/(3175-(-3175))X10-4
= 400counts per inch
Logical Minimum(127)
Physical Minimum(-3175)
Physical Minimum(3175) 给定Logical值,计算出physical值:
((PM-Pm)/2)/10i=((127-(-127))/400)/2=0.3173
à|PM|=|Pm|=3175,i=4
Unit Exponent(-4)
Unit(inch)


注意,若是Unit Exponent 未定义,则视为i = 0﹔若是Physical Minimum和Physical Maximum有一个以上未定义,则视为PM=lM和pm=lm。所以标签Physical Minimum和Physical Maximum 一定要同时定义,否则无意义。这些卷标的括号内数字为有符号的整数,可以是一个字节或二至四个字节,字节数目会在卷标代码的最低二位定义,详情后文会叙述。卷标Unit 的括号内数据比较复杂,总共用了7 个四位(nibbles)来描述,各个四位之意义如表4,其中第8 个四位
未被使用到。
表4:标签Unit的信息格式
Nibbe 7 6 5 4 3 2 1 0
  0 Luminous Intensity Current Temperature Time Mass Length System


HID 共享了四种单位系统,最低的四位就是决定使用的单位系统(System),不同的系统中当然物理量的单位也不一样。单位和系统间的对应关系如表5。
表5:物理量的单位之编码法
  None SI Linear SI Rotation English Linear English Rotation
System 0x0 0x1 0x2 0x3 0x4
Length None 公分 径度 英寸 角度
Mass None 公克 公克 Slug Slug
Time None 秒 秒 秒 秒
Temperature None 凯氏(绝对温度) 凯氏(绝对温度) 华氏 华氏
Current None 安培 安培 安培 安培
Luminous intensity None Candela Candela Candela Candela


除了最低四位的值用来选择单位系统外,其余每个四位皆表示该单位的幂次方,每个四位(nibble)都是有符号的整数,可表示的范围为-8 至+7:
-8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
08h 09h 0ah 0bh 0ch 0dh 0eh 0fh 00h 01h 02h 03h 04h 05h 06h 07h


因此长度的单位若为公分则Unit (data)中data 的码为0x11,若为英吋则为0x13,这二者中Length 的四位值皆为1 表示幕次方为1,即cm1 或in1 。质量单位为公克之码为0x0101,加速度单位为公分除以平方秒之码为0xE011,其中E 代表-2。所以力量单位为质量(公克)乘于加速度(公分/平方秒)的码为0xE111。能量单位焦尔为力量乘于长度之码为0xE121,其等义于s?2g cm2 和单位系统为SI Linear。
主项目
主项目中产生报告数据格式的三个卷标(Input,Output,和Feature)具有共通的数据定义,这些数据和其代码列于表6中。目前用到9个位来表示这些数据。如果第九位(bit 8)为0,则仅需用一个字节来表示该数据,即忽略第九位。如果第九位为1,就需用到二个字节来表示该数据。
表6:主项目的信息代码
Bit 8 7 6 5 4 3 2 1 0
0 Bit Field Non Volatile No Null Position Preferred State Linear No Wrap Absolute Array Data
1 Buffered Bytes Volatile Null State No Preferred Non Linear Wrap Relative Variable Constant


Data/Constant:主项目之数据为可变值(设为Data),或为固定不可变值(设为Constant)。Constant 都用于Feature 的报告,或是用于填充位(padding),使报告长度以字节为单位。
Array/Variable:主项目之数据的每个字段可以表示几个不同的操作的其中一个被触发(设为Array),或是每个字段仅表示一个操作(设为Variable)。如果是Variable,则Report Count 的数据值等于报告数据的字段数。若是Array,则Report Count 的数据值表示可以同时被触发的最多操作数目。后文中键盘之例会解说Array 的用法。
Absolute/Relative:主项目的数据是以相对于固定的基准点方式提供绝对数值(设为Absolute),或是提供相对于前次报告的相对值(设为Relative)。
【范例说明】前文中的音量操控范例,因为都是Data 和Variable,二者的操作值皆为变化值,且一个字段仅表示一个操作。但是音量增减键的例子为Relative,所以若报告值由0 变成+1,则音量增大一个刻度,反之由0 变作-1 则音量减小一个刻度,因而音量大小因输入值而作相对的变化。然而音量旋钮的例子为Absolute,当输入值为最小值0 时,为静音,而输入值为最大值100 时,为最大音量,其余值作百分比的音量调整,输入值和音量成绝对关系。
No Wrap/Wrap:主项目的数据值达到极值后会转为极低值,反之亦同,称作卷绕(设为Wrap)。例如一个转钮可以做360°旋转,输出值从0 至10,若设定为Wrap,则值达10 后,在同方向旋转则值变为0,反之若达到0,再转就得到10。
Linear/Nonlinear:主项目的数据与操作刻度为线性关系(设为Linear),或为非线性(设为Nonlinear)。
Preferred State/No Preferred:主项目对应的操作再不被触发时会自动恢复到初始状态(设为Preferred State),或是不会恢复原状(设为No Preferred)。例如键盘的按键和会自动置中(self-centering)的游戏杆,皆为Preferred State。
【范例说明】再以音量操作为例,音量增减键的例子都没标注No Wrap,Linear,Preferred State,但是没有标注即认定其属于默认值,所以等同于是这些设定,只是这些设定对此例的操作无意义,所以不标出。音量旋钮的例子明确指出其为No Wrap, Linear, No Preferred,可见旋钮不是循环旋转,输出值与旋转角呈线性关系,旋钮释放开时会停留在释放前位置(因为No Preferred)。
No Null Position/Null State:主项目对应的操和有一个状态,其不会送出有意义的数据,即数据将不在Logical Minimum 和Logical Maximum 之间,这种操控要标注Null State,否则为No Null Position。例如几个按键,而无键被按下的用途没有声明在Usage 之列,则可以在主项目的数据中设Null State,将无键被按下的状态排除在Logical Minimum 和Logical Maximum区间之外,进一步请参看Universal Serial Bus HID Usage Tables 文件的Appendix A.3 节中范例。
Non Volatile/Volatile:主项目Feature 的数据不允许被主机改变(设为Non Volatile),或是允许被主机改变(设为Volatile)。注意主项目Input 和Output,此标注设定无意义,所以bit 7 的代码必须为0。

本文来自: (www.91linux.com) 详细出处参考:http://www.91linux.com/html/article/program/cpp/20090417/16506_2.html

文章评论0条评论)

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