HID设备连接到USB主机后,主机通过发送Get_Descriptor请求读取HID设备的描述符,了解描述符对了解USB设备是至关重要的。 2.1 HID设备的描述符 HID设备除了支持USB设备的5种标准描述符之外,还支持HID设备特有的3种描述符。这些描述符是:
从描述符的关联关系看,HID描述符是关联于接口。所以如果一个HID设备有2个端点,设备不需要每个端点有一个HID描述符。
图2-2 HID描述符的关联关系
从前面的USB描述符可以看出一个规律,描述符的第一、二字节分别是描述符的长度和类型,描述符的类型字段(bDescriptorType)表明描述符的种类,下表列出了不同描述符的类型字段数值。
表2-2 HID的描述符
对于一个HID设备,设备描述符与配置描述符没有HID特定的信息。其设备描述符的bDeviceClass和bDeviceSubClass字段的值为0,接口描述符的bInterfaceClass字段值为03,表示设备的该接口是HID类别。在接口描述符中其他包含HID特定信息的字段还有子类别码(blnterfaceSubClass)与协议码(blnterfaceProtocol字段)。 在接口描述符中子类别码字段等于1表示此设备支持启动接口(Boot Interface)。如果设备有启动接口,即便主机的HID没有加载驱动程序,设备也可以使用。这种情形可能发生在计算机是由DOS直接启动,在启动时观看系统设置画面或使用Wndows的安全模式时。 含有启动接口的键盘或鼠标可以使用BIOS或许多主机支持的默认简单协议。HID规范定义了键盘与鼠标的启动接口协议。如果设备没有启动接口,并且接口描述符中协议码字段是1,表示设备支持键盘接口,协议码字段是2,表示支持鼠标接口。接口描述符中协议码字段是0,表示设备不支持启动协议。 在 HID Usage Tables规范中定义了键盘与鼠标的启动描述符(Boot Descriptor)。BIOS不需要从设备中读取描述符,因为它知道启动协议,并且假设设备支持启动协议。所以要启动的设备不需要在固件内包含启动接口描述符,它只要在主机尚未要求在报表描述符中的定义协议时支持启动协议即可。在操作系统加载HlD驱动程序后会使用Set_Protocol请求,将设备由启动协议转换成报表协议。 2.2 HID描述符 HID描述符的主要作用是用来识别HID通信所使用的额外描述符。下表是HID描述符结构。 表2-3 HID描述符结构
bcdHID:设备与其描述符所遵循的HID规范的版本号码,此数值是4个16进位的BCD格式字符。例如版本1.1的bcdHID是0110h。 bCountryCode:硬件目的国家的识别码。如果不说明,该字段为0。 bDescriptorType:HID描述符附属的描述符的类型(报表或实体)。每一个 HID都必须至少支持一个报表描述符。一个接口可以支持多个报表描述符,以及一个或多个实体描述符。 HID描述符的偏移量为9和10的bDescriptorType和wDescriptorLength可以重复存在多个。 1. 报表描述符 报表描述符定义了执行设备功能的数据格式和使用方法。 报表描述符和USB的其他描述符是不一样的,它不是一个简单的表格,报表描述符是USB所有描述符中最复杂的。报表描述符非常复杂而有弹性,因为它需要处理各种用途的设备。报表的数据必须以简洁的格式来储存,这样才不会浪费设备内的储存空间以及数据传输时的总线时间。 实际上可以这样理解,报表内容的简洁,是通过报表描述符全面的、复杂的数据描述实现的。 报表描述符必须先描述数据的大小与内容。报表描述符的内容与大小因设备的不同而不同,在进行报表传输之前,主机必须先请求设备的报表描述符,只有得到了报表描述符才可正确解析报表的数据。 报表描述符是报表描述项目(Item)的集合,每一个描述项目都有相对统一的数据结构,项目很多,通过编码实现。 (1)项目 报表描述符由描述HID设备的数据项目(Item)组成,项目的第一个字节(项目前缀)由三部分构成,即项目类型(item type)、项目标志(item tag)和项目长度(item size)。其中项目类型说明项目的数据类型,项目标签说明项目的功能,项目长度说明项目的数据部分的长度。 HID的项目有短项目和长项目两种,其中短项目的格式如下图。 图2-3 HID报表短项目格式 短项目的数据字节数由bSize的值定义,bSize为0、1、2、3时Data部分的字节数分别为0、1、2、4个字节。短项目的项目类型由bType定义,bType为0、1、2时分别为Main、Global和Local类型。 长项目可以携带较多的数据,其格式如下图。
图2-4 HID报表长项目格式
项目中的第一个字节为上图中的特定值时表明该项目是一个长项目。长项目中的bDataSize说明Data部分的字节数,bLongItemTag在HID规范中没有定义。 下面是通过汇编实现的一个简单的报表描述符,描述符的每一行是一个项目,该描述符描述了一个从设备接收2个字节的输入报表和发送2个字节到设备的输出报表。
(2)项目的分类 Main类项目用于定义报表描述符中的数据项。也可以组合其中的若干数据项成为一个集合。Main项目可以分为带数据的Main项目和不带数据的Main项目。带数据项的Main用于生成报表中的数据项,包括Input、Output和Feature项目。不带数据的Main项目不生成报表中的数据项,包括Collection和End Collection项目。 Global类项目实现对数据的描述,用来识别报表并且描述报表内的数据,包括数据的功能、最大与最小允许值以及数据项的大小与数目等。改变由Main类项目生成的项目状态表。Global类项目描述对后续的所有项目有效,除非遇到有新的Global类项目。 Local类项目定义控制的特征,这一类项目的作用域不超过下一个Main项目,所以在每一Main项目之前可能有多个Local项目。Local项目用于描述后面的Input、Output和Feature项目。 下表列出的是全部的项目的前缀字和简要功能说明。 表2-4 HID项目列表
在这些项目中,Usage Page用来指定设备的功能,而Usage项目用来指定个别报表的功能。Usage Page项目相当于是HID的子集合,Usage相当于是Usage Page的子集合。 2. 报表描述符的项目 (1)Input、Outpot和Feature项目 这3个项目用来定义报表中的数据字段。 Input项目可以应用到任何控制、计数器读数或其他设备传给主机的信息。一个输入报表包含一个或多个Input项目,主机使用中断输入传输来请求输入报表。 Ouput项目用来定义主机传送给设备的信息。一个输出报表包含一个或多个Outpot项目。输出报表包含控制状态的数据。如果有中断输出管道,HID1.1兼容主机使用中断输出传输来传送输出报表,否则使用Set_Report控制请求。 Feature项目应用到主机传送给设备的信息,或是主机从设备读取Feature项目。一个特征报表包含一个或多个Feature项目,Feature项目通常是包合影响设备与其组件整体行为的配置。特征报表通常是控制可以使用实际的控制面板调整的设置,例如主机可以使用虚拟控制面板来让用户选择控制特征。主机使用 Set_Report与Get_Report请求来传送与接收特征报表。 在每一个Input、Output和Feature项目的前缀字之后是32位描述数据,目前最多定义了9个位,余的位则是保留。位0~8的定义中只有位7不能应用于Input项目,除此之外其他的位定义都适应于Input、Output和Feature项目。 表2-5 Input、Output和Feature项目的数据项说明
注: ①:该位不能应用到数组。 ②:只应用于Output和Feature项目,对于Input项目该位保留。 (2)Collection和End Collection项目 所有的报表类型都可以使用Collection与 End Collection项目来将相关的Main类型项目组成群组。这两个项目分别用于打开和关闭集合。所有在Collection与End Collection项目之间的Main类型项目都是 Collection的一部分。 Collection有3种类型:Application、Physical与Logical,其项目的数据项的值分别为1、0和2。厂商也可以自己定义Collection类型,数据项的值为80h~FFh保留给厂商定义。End Collection项目无数据项。 Application Collection包含有共同用途的项目或执行单一功能的项目。例如键盘的开机描述符将键盘的按键与LED指示灯数据集合成一个Application Collection。所有的报表必须在一个Application Collection内。 Physical Collection包含在一个单一几何点上的数据项目,可以将每个位置的数据集合成一个 Physical Collection。在设备报告多个传感器的位置的时候,使用Physical Collection指明不同的数据来自不同的传感器。 Logical Collection形成一个数据结构,包含由 Collection所连结的不同类型的项目。例如数据缓冲区的内容以及缓冲区内字节数目的计数。 (3)Usage Page和Usage项目 Usage page项目的数据部分为1~2个字节,目前的定义全部都是一个字节。Usage Page定义了常用的设备功能,关于Usage Page(以及其他项目)的具体定义内容,可以查阅HID Usage tables,下表是来自HID Usage tables的Usage Page定义。 表2-6 Usage Page定义
关于Usage Page的每一个有效定义项,都有一个相应的下一级定义,如Usage Page的数据项数值为1,则设备定义为Generic Desktop Controls,关于该类设备的具体功能可以在HID Usage Tables中查到具体的定义。下表是HID Usage Tables中对Generic Desktop Controls设备的功能定义。
表2-7 Generic Desktop Controls 用法定义
用法(Usage)定义了各种各样设备特性,对于Usage Page的每一项都定义了常用的各种用法。 用法说明了3种信息,即控制、集合和数据。控制说明设备的状态,如on/off、Enable/Disable等。集合说明控制和数据的组合关系。 上表中的用法类型(Usage Type)描述了应用程序如何处理由Main类型项目生成的数据,具体的定义和详细说明请参阅HID Usage Tables。 (4)Report ID项目 Report ID放在信息包中报表数据之前,设备可以支持多个相同类型的报表,每一个报表包含不同的数据与其特有的ID。 在报表描述符中,Report ID项目作用于其后续所有的项目,直到遇到下一个Report ID为止。如果报表描述符中没有Report ID项目,默认的ID值是0,描述符不能定义一个为0的Report ID,输入报表、输出报表与特征报表可以分享同一个Report ID。 在Set_Report和Get_Report请求传输中,主机在设置事务的 wValue字段的低字节中指定一个Report ID。在中断传输中如果接口支持一个以上的 Report ID,Report ID必须是传送报表中的第一个字节。如果接口只支持数值为0的默认Report ID,此Report ID不应该在中断传输中随着报表一起传送。 (5)Logical Minimum和Logical Maximum项目 Logical Minimum与 Logical Maximum项目定义报表的变量(Variable)或阵列(Array)数据的限制范围,此限制范围以逻辑单位来表示。例如设备报表的一个电流值读数是500mA,而一个单位是2mA,则 Logical Maximum值等于250。 负数值以2的补码来表示。如果Logical Minimum与Logical Maximum都是正数,就不需要有正负号位。不管 Logical Minimum与Logical Maximum是以有正负号或是无正负号的数值来表示,设备都可以正确地传输数据。数据的接收者必须知道数据是否可以是负值。 (7)Physical Minimum和Physical Maximum项目 Physical Minimum和Physical Maximum项目定义数值的限制范围,该限制范围使用Unit项目定义的单位来表示。上例中设备报表的一个电流值读数是500mA,单位是2mA, Logical Maximum值等于250,而Physical Maximum值是500。 Logical Minimum与 Logical Maximum值说明了设备返回数值的边界,可以根据Physical Minimum和Physical Maximum值对数据进行偏移和比例变换。 (8)Unit Exponent项目 Unit Exponent项目定义了在使用逻辑范围和实际范围将设备的返回数值转换成实际数值时,使用10的多少次方对数值进行定标。Unit Exponent的值的编码为4位补码,代表10的指数范围是-8~+7。
表2-8 Unit Exponent 数值表
根据以上5个项目的值可以换算出报表传送数据(逻辑数据)与物理数据的转换关系。 物理数据值 = 逻辑数据值÷分辨率 分辨率 = (LogicalMaximum - LogicalMinimum)÷ ((PhysicalMaximum - PhysicalMinimum)×10UnitExponent) (7)Unit项目 从半字节0~6由下表给出了具体的定义,其中半字节0表示测量系统,半字节7保留。例如在半字节0数值为1(表示采用线性公制测量系统)的条件下,半字节1表示长度(单位为厘米),如果其数值为1表示厘米,数值为2表示(厘米)2,成为面积单位。半字节3表示时间(单位为秒),如果其数值为-2,表示(秒)-2。 表2-9 Unit 单位的定义
虽然表中只是定义了有限的基本单位,但可以通过这些基本单位的组合派生出大多数其它的常用单位。 例如报表使用一个字节传送一个从-20到110华氏度温度值,可以定义以下报表描述项目: Logical Minimum = -128 Unit的半字节0=3选择英制线性测量系统,半字节4=3选择华氏温度单位。 130(110+20)华氏度的数值范围线性分布到了256和有效数值区域,每一位相当于0.51华氏度,这样就提高了分辨率。 (8)Report Size和Report Count项目 Report Size项目指定Input、Output与Feature项目字段的大小,以位为单位。 Report Count项目指定Input、Output与Feature项目包含的字段数目。 例如两个8位的字段,Report Size等于8,而Report Count等于2。8个1位的字段,Report Size等于1,而 Report Count等于8。 Input、Output与Feature项目报表可以有多个项目,每一个项目可以有自己的Report Size和Report Count项目。 (9)Push和Pop项目 Push项目将一个Global项目状态表格的副本压入CPU的堆栈内。GIobal项目状态表格包含所有之前定义的Gobal项目的目前设置。 Pop项目恢复之前压入堆栈的Global项目状态的储存状态。 (10)Usage、Usage Minimum和Usage Maximum项目 这3个项目输入Local类型项目。 Usage项目和Global类型的Usage Page项目协同描述项目或集合的功能。 一个报表可以指定一个Usage给许多个控制,或是指定不同的Usage给每一个控制。如果一个报表项目之前有一个Usage,此Usage应用到该项目的所有控制。如果一个报表项目之前有一个以上的Usage,每一个Usage应用到一个控制,Usage与控制是按顺序结合的。 例如下面报表描述符的一个局部,报表含有2个输入字节,第一个字节的用法是x,第2个字节是y。
如果一个报表项目之前有一个以上的Usage,而且控制的数目多于Usage的数目,每一个Usage与一个控制对应,最后一个Usage则应用到所有剩余的控制。 例如在下面报表包含16个字节输入数据,第一个字节对应用法x,第2个字节对应用法y,剩余的14个字节对应厂商定义的用法。
例如在一个键盘描述符中定义的标准键盘的左、右修饰键的输入项目中,使用一个字节的8位分别输入键盘的左、右Ctrl键、Shift键、Alt键和GUI键,从HID Usage tables文档中的第10节可以查到关于键盘用法的定义,其中上述8个修饰键的用法定义值为224到231。以下是报表描述符的修饰键部分描述。
|