HID报表描述符原理解释
一个报表描述符主要是为了描述报表的结构以及用途。
报表的结构主要由报表的字段的长度(size)、数量(count)、属性(输入、输出等)决定,而报表的用途则由 HID 用途表文档规定。
下面我们还是从 Kinetis KL25 USB 例程指南—进阶篇中的 USB 鼠标的报表描述符入手,分析报表描述符中各项的含义,并介绍 HID用途表中的要点。
;=========================================
;HID Reports Descriptor 报表描述符
;=========================================
DB 0x05, 1 ; Usage Page (1: Generic Desktop)
DB 0x09, 2 ; Usage (2: Mouse) 表示报表定义的是HID鼠标
DB 0xA1, 1 ; Collection (1: Application) ===============集合开始
DB 0x09, 1 ; Usage (1: Pointer)
DB 0Xa1, 0 ; Collection (0: Physical)
DB 0x05, 9 ; USAGE_PAGE (Button)
DB 0x19, 1 ; Usage Minimum (1)
DB 0x29, 3 ; Usage Maximum (3)
DB 0x15, 0 ; Logical Minimum (0)
DB 0x25, 1 ; Logical Maximum (1)
DB 0x95, 3 ; Report Count (3)
DB 0x75, 1 ; Report Size (1)
DB 0x81, 2 ; Input (Data, Variable, Absolute)
;
DB 0x95, 1 ; Report Count (1)
DB 0x75, 5 ; Report Size (5),
DB 0x81, 1 ; Input (Constant)
;
DB 0x05, 1 ; USAGE_PAGE (Generic Desktop)
DB 0x09, 30 ; USAGE (X)
DB 0x09, 31 ; USAGE (Y)
DB 0x09, 38 ; USAGE (Wheel)
DB 0x15, 81 ; LOGICAL_MINIMUM (-127)
DB 0x25, 7f ; LOGICAL_MAXIMUM (127)
DB 0x75, 8 ; REPORT_SIZE (8)
DB 0x95, 3 ; REPORT_COUNT (3)
DB 0x81, 6 ; INPUT (Data, Variable, Relative)
DB 0xC0
DB 0xC0 ; End_Collection ====================== 集合结束
用途 ID(Usage ID)和用途页 ID(Usage Page ID)
上文的报表描述符为例,需要一个用途为 Mouse 的最外层应用集合。通过查看 HID 用途表,知道在 Generic Desktop Page(0x01)中有一个用途类型为 CA 的 Mouse(0x02)用途,因此在 USB 鼠标报表描述符中,开头就先指定了使用用途页 Generic Desktop Page(0x01),然后又指定了该用途页下的 Mouse(0x02)用途,接着使用开集合的主条目打开一个应用集合,如下所示。
DB 0x05, 1 ; Usage Page (1: Generic Desktop)
DB 0x09, 2 ; Usage (2: Mouse) 表示报表定义的是HID鼠标
DB 0xA1, 1 ; Collection (1: Application) ===============集合开始
读到这里,我想大家会对前段加粗所标示出的名词具体所.
用途页 ID(Usage Page ID)用途 ID(Usage ID)就像论文的大标题和小标题一样,大标题着眼于研究领域的划分,而小标题则着眼于该领域中具体分支的介绍,让读者一看题目,就能大致了解论文描述的内容。
而在描述符中,要指定 Input、Output 或 Feature 项目定义的数据域功能时,就需要指定对应的用途页以及用途。指定用途有两种方法:可以一个个的用 Usage 去指定(如 USB 鼠标中对 X、Y 以及滚轮的用途指定),也可以指定用途最小值和用途的最大值(如 USB 鼠标中对按键的用途指定)。这样,每个数据域就会分配到对应的用途。但是这里有一个例外,那就是用途类型(Usage Type)为 Sel(Selectors)的用途 ID,它的数据域属性为 NAry(数组)。一个 Nary 可以有一个或者多个元素,每个元素都具有相同的用途。当对一个属性为 Nary 的数据域指定用用途最小值和用途最大值时,并不是将这些数据域分别分配为这些用途,而是这些数据域的每个数组元素的返回值可以在这些用途中选择。键盘中的普通键就是这种情况,HID 用途表中规定了这些普通键的 Usage ID 类型 Sel 的。
注意:HID 用途表文档列出了各式的用途页,并在每个用途页下都规定了很多的用途,切记用途页和用途不可随意使用。
HID 用途表文档还规定了用途的类型,总共 3 种,分为:集合(Collections)、控制(Controls)、数据(Data),上段中提到的 Sel是数据中一种,而 CA 则为集合的一种,具体分类请参考 HID 用途表文档。集合与控制、数据的用法区别,已经在 HID 用途表中标示出来啊(如图 1)。至于控制和数据的差异,个人意见是两者着眼于 Input、Output 或 Feature 项目定义的数据域的不同位域,一个用于说明数据域的属性,另一个则用于说明数据域的类型(如表 1),感觉没什么可比
性,所以只好乖乖的遵守 HID 用途表文档中的分类了。
注:
①:该位不能应用到数组。
②:只应用于 Output 和 Feature 项目,对于 Input 项目该位保留。
完成集合内的各用途 ID(Usage ID)及对应数据域指定
DB 0x09, 1 ; Usage (1: Pointer)
DB 0Xa1, 0 ; Collection (0: Physical)
DB 0x05, 9 ; USAGE_PAGE (Button)
DB 0x19, 1 ; Usage Minimum (1)
DB 0x29, 3 ; Usage Maximum (3)
DB 0x15, 0 ; Logical Minimum (0)
DB 0x25, 1 ; Logical Maximum (1)
DB 0x95, 3 ; Report Count (3)
DB 0x75, 1 ; Report Size (1)
DB 0x81, 2 ; Input (Data, Variable, Absolute)
;
DB 0x95, 1 ; Report Count (1)
DB 0x75, 5 ; Report Size (5),
DB 0x81, 1 ; Input (Constant)
;
DB 0x05, 1 ; USAGE_PAGE (Generic Desktop)
DB 0x09, 30 ; USAGE (X)
DB 0x09, 31 ; USAGE (Y)
DB 0x09, 38 ; USAGE (Wheel)
DB 0x15, 81 ; LOGICAL_MINIMUM (-127)
DB 0x25, 7f ; LOGICAL_MAXIMUM (127)
DB 0x75, 8 ; REPORT_SIZE (8)
DB 0x95, 3 ; REPORT_COUNT (3)
DB 0x81, 6 ; INPUT (Data, Variable, Relative)
在指定了 Mouse(0x02)用途,并打开了一个应用集合后,这样系统软件在分析此报表描述符时,就知道最外层的一个应用集合是用作鼠标的,操作系统就会增加一个 HID 鼠标设备。接着在该应用集合中,增加一个用途为 Point 的物理集合。Point 也是 Generic DesktopPage 中的一个开物理集合的用途,是指针设备集合。由于鼠标上有三个按键,因此需要用到按键(Button)的功能。在 HID 用途表中,专门一个按键页:Button Page(0x09),选择了按键用途 1~3,分别为左键、
右键、中键。另外,鼠标还有 X 轴、Y 轴以及滚轮,这些用途在Generic Desktop 页中定义的,所以接着又切换到了 Generic Desktop 页,将三个宽度为 8 位的数据段分别定义为 X 轴、Y 轴、滚轮。
关闭集合
最后,使用关闭集合的主条目将两个集合关闭。这样,一个 USB鼠标的 HID 报表符就构造好了