USB HID报告描述符详解
HID类键盘的报告描述符的理解
USB学习小记-HID类键盘的报告描述符的理解前言断断续续的学习了将近三个月,才把USB的HID类搞明白,速度真是够慢的。
利用晚上+周末的时间学习自己的东西确实是必要的,不过效率是有点低,以后要更专注一些才行,希望自己能做到吧。
在学习过程中,刚开始主要参考了周立功编写的一本《PDIUSBD12 USB 固件编程与驱动开发》,后面的学习主要参考电脑圈圈的资料包,包括里面的HID类的英文协议文档,还有一位台湾前辈几年前写的几篇文章,还有网络下有下得到的一些例程。
在此感谢各位大虾前辈的分享。
一、学习流程1,先大致看下USB1.1中文版的协议(就是网上能找到的翻译版),先了解一下USB1.1的工作流程(可能此时的你会对其中很多内容都很含糊,不过没关系,请坚持!);2,选择一款最常用的USB芯片,比如我选择的NXP的PDIUSBD12.有很多使用该芯片的源码可以在上网搜索得到,而且周立功公司为其写了一本书,前面的章节对USB的工作流程作了一个简单而又清晰的讲解,而不致让人陷入协议的海洋里;3,有了对USB1.1协议的大致了解,选好了开发的平台(我刚好手上有一块周立功公司的EASEARM2200的开发板,上面有D12)之后,先跑一下附带的例程(此开发板配套的例程是基于UCOS2系统的,刚开始用它来参考肯定晕)。
没有能跑的例程,那就上网找一下经验证的例程,比如电脑圈圈在EDNCHINA建立的USB学习小组里有很好的几个例程,而且都是基于51+D12的,所以极具参考价值。
我是参考周立功公司出的那本书来学习的,电脑圈圈的例程与此书的例子书写风格较相似,所以可以互相参考。
如果也没有开发板,那可购买一套电脑圈圈他们搞活动的套件或者直接用51+D12自己搭一下,这样就可以直接用电脑圈圈写的例程了,可以避免走很多弯路。
4,有了例程的直观印象后,此时可以上BUS HOUND5.0了。
此软件可以观察到USB设备与主机(PC)之间的通讯数据,特别那11个标准请求的理解,通过此软件的观察,可以更好理解其相互之间是如何完成这个握手枚举过程的。
USBHID协议详情
USB HID类设备属于人机交互操作的设备,是一个比较大的类,用于控制计算机操作的某些方面,如USB鼠标、USB键盘、USB游戏操作杆、USB触摸板、USB轨迹球、电话拨号设备、VCR遥控等等设备。
另外,使用HID设备的一个好处就是操作系统自带了HID类的驱动程序,用户无需开发很麻烦的驱动程序,只有直接使用API调用即可完成通信,所有很多简单的USB设备喜欢枚举成HID设备,这样就可以不用安装驱动而直接使用。
1、HID设备描述符当插入USB设备后,主机会向设备请求各种描述符来识别设备。
为了把一个设备识别为HID类,设备在定义描述符的时候必须遵守HID规范。
HID设备的描述符除了5个USB的标准描述符(设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符)外,还包括3个HID设备类特定描述符:HID描述符、报告描述符、物理描述符。
HID描述符是关联于接口(而不是端点)的,所以设备不需要为每个端点都提供一个HID描述符。
设备和主机的通信是通过报告的形式来实现的。
而物理描述符不是必需的。
5个标准描述符中与HID设备有关的部分有:设备描述符中bDeviceClass、bDeviceSubClass和bDeviceProtocol三个字段的值必须为0。
接口描述符中bInterfaceClass的值必须为0x03,bInterfaceSubClass的值为0或1,为1表示HID设备是一个启动设备(BootDevice,一般对PC机而言才有意义,意思是BIOS启动时能识别并使用您的HID设备,且只有标准鼠标或键盘类设备才能成为Boot Device。
如果为0则只有在操作系统启动后才能识别并使用您的HID设备)。
HID接口描述符中bInterfaceProtocol的含义bInterfaceProtocol的取值含0 NO1 键2 鼠3~255 保1.1 HID描述符HID描述符关联于接口描述符,因而如果一个设备只有一个接口描述符,则无论它有几个端点描述符,HID设备只有一个HID描述符。
USB HID报告及报告描述符简介
在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等。
USB报告描述符(Report Descriptor)是HID设备中的一个描述符,它是比较复杂的一个描述符。
USB HID设备是通过报告来给传送数据的,报告有输入报告和输出报告。
输入报告是USB设备发送给主机的,例如USB鼠标将鼠标移动和鼠标点击等信息返回给电脑,键盘将按键数据数据返回给电脑等;输出报告是主机发送给USB设备的,例如键盘上的数字键盘锁定灯和大写字母锁定灯等。
报告是一个数据包,里面包含的是所要传送的数据。
输入报告是通过中断输入端点输入的,而输出报告有点区别,当没有中断输出端点时,可以通过控制输出端点0发送,当有中断输出端点时,通过中断输出端点发出。
而报告描述符,是描述一个报告以及报告里面的数据是用来干什么用的。
通过它,USB HOST可以分析出报告里面的数据所表示的意思。
它通过控制输入端点0返回,主机使用获取报告描述符命令来获取报告描述符,注意这个请求是发送到接口的,而不是到设备。
一个报告描述符可以描述多个报告,不同的报告通过报告ID来识别,报告ID在报告最前面,即第一个字节。
当报告描述符中没有规定报告ID时,报告中就没有ID字段,开始就是数据。
更详细的说明请参看USB HID协议,该协议可从下载。
USB报告描述符可以通过使用HID Descriptor tool来生成,这个工具可以到下载,为了方便大家,我顺便上传了一份。
/Upload/Blog/2007/4/2/af7c3443-ad61-4465-ADC7-a74d28bbc322.zip下面通过由HID Descriptor tool生成的USB鼠标和USB键盘来说明一下报告描述符和报告。
code char KeyBoardReportDescriptor[63] = {//表示用途页为通用桌面设备0x05, 0x01, // USAGE_PAGE (Generic Desktop)//表示用途为键盘0x09, 0x06, // USAGE (Keyboard)//表示应用集合,必须要以END_COLLECTION来结束它,见最后的END_COLLECTION 0xa1, 0x01, // COLLECTION (Application)//表示用途页为按键0x05, 0x07, // USAGE_PAGE (Keyboard)//用途最小值,这里为左ctrl键0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)//用途最大值,这里为右GUI键,即window键0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)//逻辑最小值为00x15, 0x00, // LOGICAL_MINIMUM (0)//逻辑最大值为10x25, 0x01, // LOGICAL_MAXIMUM (1)//报告大小(即这个字段的宽度)为1bit,所以前面的逻辑最小值为0,逻辑最大值为10x75, 0x01, // REPORT_SIZE (1)//报告的个数为8,即总共有8个bits0x95, 0x08, // REPORT_COUNT (8)//输入用,变量,值,绝对值。
USBHID键盘报告范文描述符
USBHID键盘报告范文描述符HIDScript脚本语言的理解:Globalitem--全局项Mainitem--主项localitem--局部项对于Main项,parer解释器,将顺序解释集合中的数据,并且,解释器解释完的数据,将按Main项出现的先后顺序,主要是Input和Output项,顺序拼接生成对应的数据bit位,解释器将以关键字Collection开始解释并拼接bit位信息,关键字EndCollection将结束paer解释器的工作,我把关键字Collection和关键字EndCollection叫做\集合\,关键字Collection和关键字EndCollection都是Mainitem主项,对应的控制字分别为:101000nn和110000nn,如果Collection后边有1个参数数据,那么即为:10100001=0某A1,如Collection(Application)翻译成控制码后为:0某A1,0某01;0某A1的1表示有1个参数数据,0某01表示Application在HID协议中规定的索引值为0某01,pc的HID驱动程序在parer解释器中会通过0某01得知,是对Application进行数据流位生成,就是说HID报告描述符(ReportDecriptor)所描述的数据流是为了Application使用的,Application在中包含两种设备:moue和keyboard,至于Collection(Application)里边描述的是moue还是keyboard,将具体的由Uage进一步限定,如:Uage(KeyBoard),也就是说明确告诉pc的HID驱动程序的paer解释器,接下来的这段信息最后生成出来的bit位数据信息,将交由pc的HID驱动程序中KeyBoard对应的API函数处理,当然这只是HID硬件设备开发者给pc的HID驱动程序的paer解释器提供的一个建议值,比如我们做DDK下的HID驱动二次开发,那么我们可以很随意,但是HID硬件设备开发者,建议使用的HID驱动程序API接口,最好遵守,因为HID硬件设备开发者比DDK开发人员更清楚送上来的bit数据流的真正物理意义.Input和Output是用来真正生成bit位流数据域的关键字,他们描述的东西是最后通过ub总线实实在在发送到pc或者从pc接收的数据位,当然这些bit数据流数据域所代表的意义以及某段bit位们所代表的意思以及这些bit将交由pc上HID驱动程序的哪一个API接口来做进一步解析(是moue还是keyboard),需要其他描述符来描述,比如前边的Uage就是其中的1个描述符,如果一个HID设备同时提供2种不同的功能,那么就会分别生成2个bit位流数据域,每个bit位流数据,将交由不同的驱动解析,比如,一个keyboard可能还集成了一个附属的鼠标功能,那么键盘数据信息将由HIDcript脚本描述的keyboard对应bit数据位流传送,moue数据将由HIDcript脚本描述的moue对应bit数据位流传送,但同一个Input 管道怎么能传送两个独立的数据流呢,答案很简单:不能,所以又引入了一个ReportID的概念,ID 用来标识多条独立的bit数据流,pc的HID驱动程序根据ID,将这些独立的bit数据流们路由到相应的API处理函数上去,进而不同的bit数据流数据最终都能够被自己对应的API驱动函数正确接收并解析处理.对于2字节、4字节等多字节数据的传输,是按小端模式little-endian进行的.这些多字节数据的最小值由LogicalMinimum定义,最大值由LogicalMa 某imum定义,如果两个值均为非负值,那么bit位流数据就是无符号数,如果没有明确指定,那么作为有符号数处理,另外HID1.1协议不允许传输浮点数据.硬件开发者应该时刻清除自己写的HIDcript脚本所描述的数据流将来应该由PC上的HID驱动程序怎么使用,另外对于硬件开发者来说,对于不允许PC驱动修改的bit 位数据,HID1.1协议制定者强烈建议采用NULL数值,最好不要随便填其他值.----------------------------------------------Mainitem--主项当前一共5个:1)Input2)Output3)Feature4)Collection5)EndCollection----------------------------------------------Globalitem--全局项当前一共13个:1)UagePage2)LogicalMinimum---var变量或array数组的逻辑最小值3)LogicalMa某imum4)PhyicalMinimum5)PhyicalMa某imum6)UnitE某ponent---单位的指数值,是10的指数7)Unit---单位索引号:可以是时间单位、电流单位、电压单位和距离单位等等.8)ReportSize9)ReportID---数据流的ID值设置10)ReportCount11)Puh12)Pop13)Reeved---保留----------------------------------------------localitem--局部项当前一共11个:1)Uage---定义UagePage下面某个功能item的起始索引值,比如Keyboard功能,LED功能等,这也告诉pc的HID解释器,Input或Output变量或数组的相应生成数据位用来描述Uage引用到的那个功能,如:用来描述Keyboard功能或LED功能等.2)UageMinimum---定义与array或bitmap关联的uage定义的某个功能下的起始值Uage作为UagePage的一个子功能索引号,同时Uage自己也有很多子功能,或者说有很多个子值,这里就是定义这些子值的范围值,之后和用Input或Output生成bit位数据流,进行相应关联.(可以用多维数组来说明,可能会更明确一点)前一个基础上Uage(6),当然在HIDDecriptorTool里边6有它的字符串名,即:Uage(Keyboard),然后80就是Keyboard里边的一个索引取值,查找之后是:KeyBoardLeftArrow,所以Uage_Minimum(80)就等于Uage_Minimum(KeyBoardLeftArrow)Uage的顺序先后和ReportCount定义的bit位组的先后顺序依次一一对应,UageMinimum和UageMa某imum之间的Uage的索引值也将依次与ReportCount定义的bit位组的先后顺序依次一一对应上。
STM32 USB HID详解
STM32 USB HID详解1、USB简介2、USB描述符USB只是一个总线,只提供一个数据通路而已。
USB总线驱动程序并不知道一个设备具体如何操作,有哪些行为。
具体的一个设备实现什么功能,要由设备自己来决定。
那么,USB主机是如何知道一个设备的功能以及行为呢?这就要通过描述符来实现了。
描述符中记录了设备的类型、厂商ID和产品ID(通常依靠它们来加载对应的驱动程序)、端点情况、版本号等众多信息。
标准的USB设备有5种USB描述符:设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符。
下面详解:2.1、设备描述符一个USB设备只有一个设备描述符。
设备描述符主要记录的信息有:设备所使用的USB协议版本号、设备类型、端点0的最大包大小、厂商ID(VID)和产品ID(PID)、设备版本号、厂商字符串索引、产品字符串索引、设备序列号索引、可能的配置数等。
设备描述符里决定了该设备有多少种配置,每种配置都有一个配置描述符。
配置描述符主要记录的信息有:配置所包含的接口数、配置的编号、供电方式、是否支持远程唤醒、电流需求量等。
2.3、接口描述符在每个配置描述符中又定义了该配置有多少个接口,每个接口都有一个接口描述符。
接口描述符主要记录的信息有:接口的编号、接口的端点数、接口所使用的类、子类、协议等。
2.4、[类描述符]该描述符不是必须的,如果配置的USB类型有类特殊描述符(如HID类),它跟在相应的接口描述符之后。
在接口描述符里又定义了该接口有多少个端点,每个端点都有一个端点描述符。
端点描述符主要记录的信息有:端点号及方向、端点的传输类型、最大包长度、查询时间间隔等。
2.6、[字符串描述符]字符串描述符主要是提供一些方便人们阅读的信息,它不是必需的。
3、USB HID为了把一个设备识别为HID类别,设备在定义描述符的时候必须遵守HID规范。
除了USB标准定义的一些描述符外,HID设备还必须定义HID描述符。
hid协议报告描述总结
HID报告描述符主要内容整理●刚刚接触USB(HID)时对【报告描述符】感到难于理解, 因此就更无从下手。
下面根据2个主要的协议文本整理出一些常用信息, 不完整, 备忘。
⏹主要参考文本:⏹【协议文本1】: 《Device Class Definition for Human Interface Devices (HID)》Ver1.11【协议文本2】: 《Universal Serial Bus HID Usage Tables》Ver1.12每个协议文本后面的附录都有很多例子可供参考借鉴。
0、主要术语与概念(1)报告(Report): HID设备与主机交换信息的单位(报告字节数似乎没有限制);(2)报告描述符(Report Description): 用许多【项目】说明报告的格式与【用途】;(3)用途(Usage): 用于指出报告中某个数据域的意义或目的, 32bit。
高16bit用途页(Usage Page)指出用途的大类, 低16bit用途ID(Usage ID)指出用途大类下的子用途;(4)项目(Item):报告描述符用于说明数据域的某种属性的数据, 有短项目和长项目之分, 短项目1~5B, 长项目3~255B;(5)共有3种类型的项目: 主项目、全局项目(Global)、局部项目(Local);(6)主项目(Main Item)共有5个, 其中的Input、Output和Feature会产生实际的数据域并附带说明其操作特性(见2.1);其余2个Collection和End Collection是一对括号, 其间的内容构成一个【集合】, 用于限定集合中信息的整体特性;(7)全局项目(Global Item): 说明其后主项目产生的数据域的某方面特性, 一旦说明一直有效, 除非遇到一个新的全局项目说明改变其值;(8)局部项目(Local Item): 说明其后主项目产生的数据域的某方面特性, 但只对其后的一个主项目有效;(9)可以认为所有用【全局项目】说明的各种数据域特性构成一个【全局状态表】, 随着新的【全局项目】出现, 该表在不断变化。
USBHID设备报告描述符详解
USBHID设备报告描述符详解
USBHID设备报告描述符是一种描述USBHID设备报告的结构,用于定义设备报告的输入输出特性,允许设备与控制器的主机通信。
通常,报告描述符是一段二进制数据,其中包含由设备提供的输入和输出报告,以及描述报告的数据结构要求信息。
它是一种混合结构,由多个子块组成,每个子块又由一个或多个报告描述符中的域组成。
报告描述符的结构如下:
报告描述符
-
-bLengt
-bDescriptorTyp
-wDescriptorLengt
-数据
-输入报
-输出/特殊报
-特殊报
头部:报告描述符的头部包括三个字段:报告描述符的字节长度(bLength),报告描述符类型(bDescriptorType)和报告描述符的总长度(wDescriptorLength)。
bLength:报告描述符的字节长度,是报告描述符数据的字节数。
bDescriptorType:报告描述符类型,用于指示报告描述符的类型,必须为0x22
wDescriptorLength:报告描述符的总长度,用于指示报告描述符的总字节数。
数据段:数据段包括输入报告、输出/特殊报告和特殊报告。
输入报告:输入报告用于获取主机发送到设备的数据,一般由设备按定义的格式读取。
输出报告:输出报告用于将设备发送到主机的数据。
HID设备报告描述符详解_划出重点
USB/HID设备报告描述符详解概述:报告在这里意思是数据传输(data transfer),而报告描述符是对这些传输的数据作用途(usage)上的说明。
USB通讯协议的规范是以1ms产生一个USB帧(frame),USB设备可以每一个帧中发送和接收一个交换(transaction)。
交换是由几个封包(packet)组成,而传输是由一个或几个交换来完成传送一口中有效的数据。
在这里,传输和报告的意思相类似。
传输方式有四种,初始学一般只要了解控制型传输(control trans fer)和中断型传输(interrupt transfer)即可。
控制型传输是当需要时才执行传输要求,是最一般的传输方式,组态、命令和状态的通讯都可以使用控制型传输;控制型传输主要用于消息型数据(message-type data)。
中断型传输目的在做重复的数据更新(recurring data)传输,精确一点而言,即是在每个有限有周期内(b ounded period)作至少一次的小量数据发送或接收;所以适用于流动型数据(str eam-type data),注意这里所谓的周期时间就是在端点描述符中的轮询间隔时间。
报告有三种:input,output,和Feature.后面将作进一步介绍。
中断型输入管线(inter rupt in pipe)仅可以传送input报告;中断型输出管线(interrupt out pipe)仅可以传送output报告;但是控制型管线(control pipe)可以传送input,output和feature报告。
端点描述符有声明所使用的端点为何种管线。
数据本身没有任何意义,要赋于用途才能明确其为控制什么(control);例如设备上的按钮指示灯和X与Y轴的位移等都通称控制,数据则为按钮和指示灯的开关状态或X与Y轴的位移量。
为了这个目的应运而生报告描述符,其将数据的操控与它的用途作一对一的对应,所以解读报告后就可以知道每个数据作何种操作。
STM32 USB HID详解
STM32 USB HID详解1、USB简介2、USB描述符USB只是一个总线,只提供一个数据通路而已。
USB总线驱动程序并不知道一个设备具体如何操作,有哪些行为。
具体的一个设备实现什么功能,要由设备自己来决定。
那么,USB主机是如何知道一个设备的功能以及行为呢?这就要通过描述符来实现了。
描述符中记录了设备的类型、厂商ID和产品ID(通常依靠它们来加载对应的驱动程序)、端点情况、版本号等众多信息。
标准的USB设备有5种USB描述符:设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符。
下面详解:2.1、设备描述符一个USB设备只有一个设备描述符。
设备描述符主要记录的信息有:设备所使用的USB协议版本号、设备类型、端点0的最大包大小、厂商ID(VID)和产品ID(PID)、设备版本号、厂商字符串索引、产品字符串索引、设备序列号索引、可能的配置数等。
设备描述符里决定了该设备有多少种配置,每种配置都有一个配置描述符。
配置描述符主要记录的信息有:配置所包含的接口数、配置的编号、供电方式、是否支持远程唤醒、电流需求量等。
2.3、接口描述符在每个配置描述符中又定义了该配置有多少个接口,每个接口都有一个接口描述符。
接口描述符主要记录的信息有:接口的编号、接口的端点数、接口所使用的类、子类、协议等。
2.4、[类描述符]该描述符不是必须的,如果配置的USB类型有类特殊描述符(如HID类),它跟在相应的接口描述符之后。
在接口描述符里又定义了该接口有多少个端点,每个端点都有一个端点描述符。
端点描述符主要记录的信息有:端点号及方向、端点的传输类型、最大包长度、查询时间间隔等。
2.6、[字符串描述符]字符串描述符主要是提供一些方便人们阅读的信息,它不是必需的。
3、USB HID为了把一个设备识别为HID类别,设备在定义描述符的时候必须遵守HID规范。
除了USB标准定义的一些描述符外,HID设备还必须定义HID描述符。
关于USBHID协议以及鼠标键盘描述符的解释【转】
关于USBHID协议以及⿏标键盘描述符的解释【转】转⾃:⼀.HID设备识别前⾯有提到关于SCSI协议的USB设备实现。
现在来谈谈USBHID设备。
HID全称Human Interface Device。
HID协议⾥增加了HID描述符和报告描述符,以及特定的关于HID的类请求。
HID设备的通信是通过报表来进⾏的。
据说,报告描述符是USB设备中最难的描述符了。
关于HID描述符可以参考HID协议。
接下来我们谈谈报告描述符。
⼆.报告描述符每⼀个HID设备都有⾃⼰的报告描述符。
报告描述符有三种类项⽬:Main类项⽬,Global类项⽬,Local类项⽬。
具体看下表Global作⽤域是遇到下⼀个同名Global,Local作⽤域是遇到下⼀个Main(Input,Output,Feature)。
Usage Min-Max表⽰有⼏种功能,Logical Min-Max表⽰有⼏种状态。
每个报告描述符都有报告ID,报告ID是⽤来区别复合设备的。
在报告描述符⾥没有写报告ID,默认报告ID是0。
USB的控制端点可以进⾏Input,Output,Feature项⽬的传输,中断端点可以进⾏Input,Output传输。
三.⿏标和键盘的报告描述符(1)键盘的报告描述符1. 0x05,0x01,// Global Generic Desktop2. 0x09,0x06,// Local KeyBoard3. 0xA1,0x01,// Main app collection4. 0x05,0x07,// Global KeyBoard5. //////////////////////////////////第1字节6. 0x19,0xe0,// Local Usage Min (KeyBoard LeftControl)7. 0x29,0xe7,// Local Usage Max (KeyBoard Right GUI)8. 0x15,0x00,// Global Logical Min9. 0x25,0x01,// Global Logical Max10. 0x95,0x08,// Global ReportCount11. 0x75,0x01,// Global ReportSize12. 0x81,0x02,// Main Input(Data,Var,Abs)13. //////////////////////////////////第2字节14. 0x95,0x01,// Global ReportCount15. 0x75,0x08,// Global ReportSize16. 0x81,0x03,// Main Input(Cnst,Var,Abs)17. //////////////////////////////////第3-8字节18. 0x95,0x06,// Global ReportCount19. 0x75,0x08,// Global ReportSize20. 0x15,0x00,// Global Logical Min21. 0x26,0xff,0x00,//Global Logical Max22. 0x19,0x00,// Local Usage Min23. 0x29,0x65,// Local Usage Max24. 0x81,0x00,// Main Output(Data,Ary,Abs)25. ////////////////////////////////1字节输出报告26. 0x15,0x00,// Global Logical Min27. 0x25,0x01,// Global Logical Max28. 0x95,0x05,// Global ReportCount29. 0x75,0x01,// Global ReportSize30. 0x05,0x08,// Global LED31. 0x19,0x01,// Local Usage Min32. 0x29,0x05,// Local Usage Max33. 0x91,0x02,// Main Output(Data,Var,Abs)34. ////////////////////////////////补⾜上⾯变成1个字节35. 0x95,0x01,// Global ReportCount36. 0x75,0x03,// Global ReportSize37. 0x91,0x03,// Main Output(Cnst,Var,Abs)38. 0xc0 // Main End collection键盘的描述符共有8字节的输⼊报告和1字节的输出报告。
HID设备描述符介绍
HID设备描述符介绍最近在做一个投票系统的上位机。
虽然是上位机,但还是要弄清楚下位机与自己的接口――HID。
因为windows下已经有一个usb监听程序――USB HOUND。
所以,我选择先写好下位机的程序,成功发送数据后,再进行上位机程序的编写。
下位机程序,重点在于HID设备的描述符配置。
什么是描述符?HID设备通过设备描述符来标识自己的设备信息,如设备ID、厂商名称、版本、配置数量等;通过配置描述符集合来标识自己的配置信息,包括:配置描述符(总述)、接口描述符(接口类型,鼠标,键盘,自定义设备等)、端点描述符(端点读写类型,支持的数据包属性等)和HID描述符(HID版本、下级描述符信息等)。
通过字符串描述符来定义自己的一些字符串,如厂商名称等;通过报告描述符来标识数据流的格式,如数据用途(鼠标、键盘、自定义等)、长度、大小等。
网上的很多示例和介绍都使用c语言,但是,我遇到的源码,却是汇编编写的,所以我以我的项目为例,用汇编来介绍各个描述符结构,也算是个不一样的体验吧。
具体的描述介绍如下:设备描述符deviceDesc: ; Device descriptorDB deviceDescEnd - deviceDesc ; bLength 该描述符长度DB DESC_TYPE_DEVICE ; bDescriptorType 类型DW 0200H ; bcdUSB (USB 2.0) USB 版本DB 00H ; bDeviceClass (given by interface) 类代码DB 00H ; bDeviceSubClass 子类代码DB 00H ; bDeviceProtocol 设备协议DB EP0_PACKET_SIZE ; 端点0最大包长DW 0451H ; idV endor (Texas Instruments) 厂商ID (VID)#if (chip==2531)DW 16A9H ; idProduct (CC2531 HID) 产品ID (PID)#elif (chip==2511)DW 16A5H ; idProduct (CC2511 HID)#elseDW 16A7H ; idProduct (CC1111 HID)#endifDW 0100H ; bcdDevice (v1.0) 设备版本号DB 01H ; iManufacturer 描述厂商的字符串索引DB 02H ; iProduct 描述产品的字符串索引DB 00H ; iSerialNumber 产品序列号字符串的索引DB 01H ; bNumConfigurations 可能的配置数deviceDescEnd:在里面,最重要的是VID和PID,它一般用来标识你的USB设备。
USBHID报告描述符详解
USBHID报告描述符详解
1、HID报告描述符介绍
USB人机界面设备,简称HID,是计算机系统中最常见的一种通信接口,它使用设备描述符(Device Descriptors)来描述设备特性,同时使用报告描述符(Report Descriptors)来描述设备支持的数据报文格式,操作系统或软件驱动可以根据报告描述符中设置的信息来识别HID设备所具有的功能,从而支持和控制HID设备。
HID报告描述符描述了与设备相关的数据信息,它是HID设备进行自然交互的基础。
2、HID报告描述符的作用
输入报告(Input Reports)可以被认为是从HID设备发送到操作系统的数据,它可以描述HID设备特性的状态,可以用来报告控制命令、操作状态、三轴分量数据等信息;输出报告(Output Reports)则相反,它表示从操作系统发送给HID设备的数据。
HID 报告描述符终极解析
USB HID Report终极解析 HID的报告描述符巨难懂,关键是数据格式与每一位代表的意思。
经过三天的研究,终于将HID Report的每一个数据位的含义弄清楚了,现将数据解析如下,最后附上了一个HID 通信的Report例子。
以一个键盘的HID Report为例:键盘的HID报告描述符:code char KeyBoardReportDescriptor[63] = {0x05, 0x01, // USAGE_PAGE (Generic Desktop)0x09, 0x06, // USAGE (Keyboard)0xa1, 0x01, // COLLECTION (Application)0x05, 0x07, // USAGE_PAGE (Keyboard)0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)0x15, 0x00, // LOGICAL_MINIMUM (0)0x25, 0x01, // LOGICAL_MAXIMUM (1)0x75, 0x01, // REPORT_SIZE (1)0x95, 0x08, // REPORT_COUNT (8)0x81, 0x02, // INPUT (Data,V ar,Abs)0x95, 0x01, // REPORT_COUNT (1)0x75, 0x08, // REPORT_SIZE (8)0x81, 0x03, // INPUT (Cnst,V ar,Abs)0x95, 0x05, // REPORT_COUNT (5)0x75, 0x01, // REPORT_SIZE (1)0x05, 0x08, // USAGE_PAGE (LEDs)0x19, 0x01, // USAGE_MINIMUM (Num Lock)0x29, 0x05, // USAGE_MAXIMUM (Kana)0x91, 0x02, // OUTPUT (Data,V ar,Abs)0x95, 0x01, // REPORT_COUNT (1)0x75, 0x03, // REPORT_SIZE (3)0x91, 0x03, // OUTPUT (Cnst,V ar,Abs)0x95, 0x06, // REPORT_COUNT (6)0x75, 0x08, // REPORT_SIZE (8)0x15, 0x00, // LOGICAL_MINIMUM (0)0x25, 0xFF, // LOGICAL_MAXIMUM (255)0x05, 0x07, // USAGE_PAGE (Keyboard)0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)0x81, 0x00, // INPUT (Data,Ary,Abs)0xc0 // END_COLLECTION};具体分析如下:code char KeyBoardReportDescriptor[63] = {0x05, 0x01, // USAGE_PAGE (Generic Desktop)// 分析根据HID短项目数据格式短项目的编码形式如下:0x05 = 0000 01010000:Usage Page01:bType,全局(bType = 0:主项目;bType = 1:全局项目;bType = 2:区域项目;)01:bSize,1字节(BSize 用来指出项目的数据所需字节的数目,该数目仅可以为0(当bSize=0),1(当bSize=1),2(当bSize=2),和4(当bSize=3)﹔注意不可以为3个字节。
usbHid
一、应用场合USB HID类是比较大的一个类,HID类设备属于人机交互操作的设备。
用于控制计算机操作的一些方面,如USB鼠标,USB键盘,USB游戏操纵杆,USB触摸板,USB轨迹球、电话拨号设备、VCR遥控等等设备。
另外,使用HID设备的一个好处就是,操作系统自带了HID类的驱动程序,而用户无需去开发很麻烦的驱动程序,只要直接使用API调用即可完成通信。
所以很多简单的USB设备,喜欢枚举成HID设备,这样就可以不用安装驱动而直接使用。
二、USB HID类可采用的通信管道所有的HID设备通过USB的控制管道(默认管道,即端点0)和中断管道与主机通信。
控制管道主要用于以下3个方面:接收/响应USB主机的控制请示及相关的类数据在USB主机查询时传输数据(如响应Get_Report请求等)接收USB主机的数据中断管道主要用于以下两个方面:USB主机接收USB设备的异步传输数据USB主机发送有实时性要求的数据给USB设备从USB主机到USB设备的中断输出数据传输是可选的,当不支持中断输出数据传输时,USB主机通过控制管道将数据传输给USB设备。
三、与USB HID设备有关的描述符HID设备的描述符除了5个USB的标准描述符(设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符,另一篇文章:USB开发基础--USB命令(请求)和USB描述符)外,还包括3个HID设备类特定描述符:HID描述符、报告描述符、实体描述符。
除了HID的三个特定描述符组成对HID设备的解释外,5个标准描述符中与HID设备有关的部分有:设备描述符中bDeviceClass、bDeviceSubClass和bDeviceProtocol三个字段的值必须为零。
接口描述符中bInterfaceClass的值必须为0x03,bInterfaceSubClass的值为0或1,为1表示HID设备符是一个启动设备(Boot Device,一般对PC机而言才有意义,意思是BIOS 启动时能识别并使用您的HID设备,且只有标准鼠标或键盘类设备才能成为Boot Device。
USB设备描述符完全解析
USB设备描述符完全解析//===================================== ======================================= // 文件名: USBDESC.C// 用途: USB描述符// 作者: shenfei5// 时间: 2007.2.3// 版本: V1.10//===================================== =======================================#include <RTL.h>#include "usb.h" // USB模块#include "hid.h" // HID设备#include "usbcfg.h" // 配置USB#include "usbdesc.h" // USB描述符//// HID报文描述符//const U8 HID_ReportDescriptor[] = {HID_UsagePageVendor(0x00), // 报告页版本: 0X06 0X00 0XFF HID_Usage(0x01), // 用途页: 0X05 0X01// 如果是MOUSE,KEY,在这里应该有用法索引HID_Collection(HID_Application), // 用法集合开始: 0XA1 0X01HID_UsagePage(HID_USAGE_PAGE_BUTTON), // BUTTON用法页HID_UsageMin(1), // 用法最小值HID_UsageMax(3), // 用法最小值HID_LogicalMin(0), // 逻辑最小值HID_LogicalMax(1), // 逻辑最大值HID_ReportCount(3), // 报告计数(3)HID_ReportSize(1), // 报告页大小 (1)HID_Input(HID_Data | HID_Variable | HID_Absolute), // 输入(2)HID_ReportCount(1), // 报告计数值HID_ReportSize(5), // 报告大小HID_Input(HID_Constant), // 输入 1HID_UsagePage(HID_USAGE_PAGE_LED), // LED用法页HID_Usage(HID_USAGE_LED_GENERIC_INDICATOR), // 用法页HID_LogicalMin(0), // 用法最小值HID_LogicalMax(1), // 用法最大值HID_ReportCount(8), // 报告计数值HID_ReportSize(1), // 报告大小 (1)HID_Output(HID_Data | HID_Variable | HID_Absolute), // 输出(2)HID_EndCollection, // 报告结束};// HID报告描述符大小const U16 HID_ReportDescSize = sizeof(HID_ReportDescriptor);//// USB 设备描述符//const U8 USB_DeviceDescriptor[] = {USB_DEVICE_DESC_SIZE, // bLength 描述符长度 = 12HUSB_DEVICE_DESCRIPTOR_TYPE, // bDescriptorType 描述符类型 = 1HWBVAL(0x0110), // 1.10 // bcdUSB 设备版本号 = 你发行的版本的号0x00, // bDeviceClass 类型代码 = 由USB指定0x00, // bDeviceSubClass 子类型代码 = 由USB分配0x00, // bDeviceProtocol 协议代码 = 由USB分配USB_MAX_PACKET0, // bMaxPacketSize0 端点0的容量= 64(只能是 8,16,32,64)WBVAL(0x1977), // idVendor 供应商ID(同USB协会分配,我就自己分配一份)WBVAL(0X1006), // idProduct 产品ID(由厂商分配)WBVAL(0x0100), // 1.00 // bcdDevice ( 设备出厂编号 )0x04, // iManufacturer ( 厂商描述字符串索引, 用来在字符串索引中查找字符串)0x20, // iProduct ( 产品描述字符串索引, 用来在字符串索引中查找字符串)0x42, // iSerialNumber ( 设备序列号描述字符串索引, 用来在字符串索引中查找字符串)0x01 // bNumConfigurations (配置字符串的个数)};//// USB 描述符集// 所有描述符 (配置描述符, 接口描述符, 端点描述符, USB类描述符, 设备描述符//const U8 USB_ConfigDescriptor[] = {// 配置描述符USB_CONFIGUARTION_DESC_SIZE, // bLength 描述符长度 = 9HUSB_CONFIGURATION_DESCRIPTOR_TYPE, // bDescriptorType 描述符类型 = 2HWBVAL( // wTotalLengthUSB_CONFIGUARTION_DESC_SIZE + // 返回描述符串集的长度, 配置描述字符长度USB_INTERFACE_DESC_SIZE + // 接口描述字符长度HID_DESC_SIZE + // HID描述字符长度USB_ENDPOINT_DESC_SIZE // 端点描述字符长度),0x01, // bNumInterfaces// 支持接口数0x01, // bConfigurationValue// 配置值0x00, // iConfiguration// 配置字符串描述索相// 0: 不使用// 如果使用,必须在字符串描述符中添加相应的字符串.USB_CONFIG_BUS_POWERED | // bmAttributes 设置的供电特性USB_CONFIG_REMOTE_WAKEUP, // 总线供电// 有唤醒功能USB_CONFIG_POWER_MA(100), // bMaxPower 设备从供电总线吸取的电流值//// 当前配置为 100MA// 接口类描述符// 接口 0 ,位置 0 , HID类// Interface 0, Alternate Setting 0, HID ClassUSB_INTERFACE_DESC_SIZE, // bLength 描述符长度 = 9HUSB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType 描述符类型 = 4H0x00, // bInterfaceNumber ( 接口编号 )0x00, // bAlternateSetting ( 可代替位置 )0x01, // bNumEndpoints 使用端点(不含端点0)USB_DEVICE_CLASS_HUMAN_INTERFACE, // bInterfaceClass // USB 类// USB_DEVICE_CLASS_HUMAN_INTERFACE == 3// HID类HID_SUBCLASS_NONE, // bInterfaceSubClass// 子类,没有.HID_PROTOCOL_NONE, // bInterfaceProtocol// 协议代码0x5C, // iInterface// 字符串描述符索引,要使用该字符串必须在字符串描述符里添加相应的字符串// HID类描述符// HID_DESC_OFFSET = 0x0012// HID类描述符的偏移量HID_DESC_SIZE, // bLength 描述符长度 =HID_HID_DESCRIPTOR_TYPE, // bDescriptorType HID描述符类型 = 21HWBVAL(0x0100), // 1.00 // bcdHID HID版本号0x00, // bCountryCode 国家代码0x01, // bNumDescriptors 支持其它类描述符个数HID_REPORT_DESCRIPTOR_TYPE, // bDescriptorType 从属类描述类型 = 报告描述符22HWBVAL(HID_REPORT_DESC_SIZE), // wDescriptorLength 从属类描述的长度// Endpoint, HID Interrupt In// HID 端点描述描,端点1输入USB_ENDPOINT_DESC_SIZE, // bLength 端点描述符长度USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType 端点描述符类型 = 5HUSB_ENDPOINT_IN(1), // bEndpointAddress 逻辑端点号 BIT.7 = DIR// BIT.0..3 端点号// 这个值是用来把逻辑端点号换成物理端点号USB_ENDPOINT_TYPE_INTERRUPT, // bmAttributes 端点属性= 中断WBVAL(0x0004), // wMaxPacketSize 端点容量10, // 10ms // bInterval// 传输间隔时间.只对中断端点有效// Terminator0 // bLength// 结果码.};//// USB 字符串描述符 (可选)// 字符描述符结构:// {// 字符串描述符 1 大小// 描述符类型 = 字符串描述符(0X03)// 描述符内容.// ... ...// 字符串描述符n 1 大小// 描述符类型n = 字符串描述符(0X03)// 描述符内容n.// }//const U8 USB_StringDescriptor[] = {// 字符串索引: 0x00:// 字符串用途: 语言代码0x04, // 描述符长度 bLengthUSB_STRING_DESCRIPTOR_TYPE, // bDescriptorType,描述符类型:3(字符串描述符)//WBVAL(0x0409), // 使用English 语言// 描述符内容wLANGIDWBVAL(0x0804), // 试一下中文的行不行,改了之后,在硬件属性里看不到,在客户端可以看到,不明原因.// 字符串索引: 0x04:// 字符串用途: 生产产商字符描述符0x1C, // 描述符长度 bLengthUSB_STRING_DESCRIPTOR_TYPE, // bDescriptorType,描述符类型:3(字符串描述符)0xc1,0,0xd6,0,0xca,0,0xa4,0,0xb7,0,0xe1,0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,// 字符串索引: 0x20// 字符串用途: 产品名称0x22, // 描述符长度 bLengthUSB_STRING_DESCRIPTOR_TYPE, // bDescriptorType,描述符类型:3(字符串描述符)0xc1,0,0xd6,0,0xca,0,0xa4,0,0xb7,0,0xe1,0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,'H',0,'I',0,'D',0,// 字符串索引: 0x42// 字符串用途: 产品系列号0x1A, // 描述符长度 bLengthUSB_STRING_DESCRIPTOR_TYPE, // bDescriptorType,描述符类型:3(字符串描述符)'T',0,'E',0,'S',0,'T',0,'0',0,'0',0,'0',0,'0',0,'0',0,'0',0,'0',0,'0',0,// 字符串索引号 0x5C// 接口 Interface 0, 位置 Alternate Setting 00x08, // 描述符长度 bLengthUSB_STRING_DESCRIPTOR_TYPE, // bDescriptorType,描述符类型:3(字符串描述符)'H',0,'I',0,'D',0,};。
HID报告描述详解
在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等。
USB报告描述符(Report Descriptor)是HID设备中的一个描述符,它是比较复杂的一个描述符。
USB HID设备是通过报告来给传送数据的,报告有输入报告和输出报告。
输入报告是USB 设备发送给主机的,例如USB鼠标将鼠标移动和鼠标点击等信息返回给电脑,键盘将按键数据数据返回给电脑等;输出报告是主机发送给USB设备的,例如键盘上的数字键盘锁定灯和大写字母锁定灯等。
报告是一个数据包,里面包含的是所要传送的数据。
输入报告是通过中断输入端点输入的,而输出报告有点区别,当没有中断输出端点时,可以通过控制输出端点0发送,当有中断输出端点时,通过中断输出端点发出。
而报告描述符,是描述一个报告以及报告里面的数据是用来干什么用的。
通过它,USB HOST可以分析出报告里面的数据所表示的意思。
它通过控制输入端点0返回,主机使用获取报告描述符命令来获取报告描述符,注意这个请求发送到接口的,而不是到设备。
一个报告描述符可以描述多个报告,不同的报告通过报告ID 来识别,报告ID在报告最前面,即第一个字节。
当报告描述符中没有规定报告ID时,报告中就没有ID字段,开始就是数据。
更详细的说明请参看USB HID协议,该协议可从下载。
下面通过由HID Descriptor tool生成的USB鼠标和USB键盘来说明一下报告描述符和报告。
code char KeyBoardReportDescriptor[63] = {//表示用途页为通用桌面设备0x05, 0x01, // USAGE_PAGE (Generic Desktop)//表示用途为键盘0x09, 0x06, // USAGE (Keyboard)//表示应用集合,必须要以END_COLLECTION来结束它,见最后的END_COLLECTION 0xa1, 0x01, // COLLECTION (Application)//表示用途页为按键0x05, 0x07, // USAGE_PAGE (Keyboard)//用途最小值,这里为左ctrl键0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)//用途最大值,这里为右GUI键,即window键0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)//逻辑最小值为00x15, 0x00, // LOGICAL_MINIMUM (0)//逻辑最大值为10x25, 0x01, // LOGICAL_MAXIMUM (1)//报告大小(即这个字段的宽度)为1bit,所以前面的逻辑最小值为0,逻辑最大值为10x75, 0x01, // REPORT_SIZE (1)//报告的个数为8,即总共有8个bits0x95, 0x08, // REPORT_COUNT (8)//输入用,变量,值,绝对值。
USB HID介绍 - Leo_Wonty的专栏 - 博客频道 - CSDN
Descriptor即描述符,是一个完整的数据结构,可以通过C语言等编程实现,并存储在USB设备中,用于描述一个USB设备的所有 属性,USB主机是通过一系列命令来要求设备发送这些信息的。
描述符的作用就是通过命令操作作来给主机传递信息,从而让主机知道设备具有什么功能、属于哪一类设备、要占用多少带宽、 使用哪类传输方式及数据量的大小,只有主机确定了这些信息之后,设备才能真正开始工作。
端点描述符 struct _ENDPOIN_DEscriptOR_STRUCT { BYTE bLength; //端点描述符的字节数大小 BYTE bDescriptorType; //描述符类型编号,为0x05 BYTE bEndpointAddress; //端点地址及输入输出属性 BYTE bmAttribute; //端点的传输类型属性 WORD wMaxPacketSize; //端点收、发的最大包的大小 BYTE bInterval; //主机查询端点的时间间隔 }
一个报告描述符可能包含多个main item,为了准确描述来自一个控制管道的数据,一个报告描述符必须包括以下内容:
input(output,feature) usage usage page Logical Minimum Logical Maximum Report Size Report Count
长item,其bType位值为3,bTag值为F
}
字符描述符 struct _STRING_DEscriptOR_STRUCT
{
BYTE bLength; //字符串描述符的字节数大小 BYTE bDescriptorType; //描述符类型编号,为0x03 BYTE SomeDescriptor[36]; //UNICODE编码的字符串
USB HID设备报告描述符详解
USB HID设备报告描述符详解概述:报告在这里意思是数据传输(data transfer),而报告描述符是对这些传输的数据作用途(usage)上的说明。
USB通讯协议的规范是以1ms产生一个USB帧(frame),USB设备可以每一个帧中发送和接收一个交换(transaction)。
交换是由几个封包(packet)组成,而传输是由一个或几个交换来完成传送一口中有效的数据。
在这里,传输和报告的意思相类似。
传输方式有四种,初始学一般只要了解控制型传输(control transfer)和中断型传输(interrupt transfer)即可。
控制型传输是当需要时才执行传输要求,是最一般的传输方式,组态、命令和状态的通讯都可以使用控制型传输;控制型传输主要用于消息型数据(message-type data)。
中断型传输目的在做重复的数据更新(recurring data)传输,精确一点而言,即是在每个有限有周期内(bounded period)作至少一次的小量数据发送或接收;所以适用于流动型数据(stream-type data),注意这里所谓的周期时间就是在端点描述符中的轮询间隔时间。
报告有三种:input,output,和Feature.后面将作进一步介绍。
中断型输入管线(interrupt in pipe)仅可以传送input报告;中断型输出管线(interrupt out pipe)仅可以传送output报告;但是控制型管线(control pipe)可以传送input,out put和feature报告。
端点描述符有声明所使用的端点为何种管线。
数据本身没有任何意义,要赋于用途才能明确其为控制什么(control);例如设备上的按钮指示灯和X与Y轴的位移等都通称控制,数据则为按钮和指示灯的开关状态或X与Y轴的位移量。
为了这个目的应运而生报告描述符,其将数据的操控与它的用途作一对一的对应,所以解读报告后就可以知道每个数据作何种操作。
USBHID鼠标信息解析
USBHID鼠标信息解析
鼠标发送给PC的数据每次4个字节
BYTE1 BYTE2 BYTE3 BYTE4
定义分别是:
BYTE1 --
|--bit7: 1 表示 Y 坐标的变化量超出-256 ~ 255的范围,0表示没有溢出
|--bit6: 1 表示 X 坐标的变化量超出-256 ~ 255的范围,0表示没有溢出
|--bit5: Y 坐标变化的符号位,1表示负数,即鼠标向下移动
|--bit4: X 坐标变化的符号位,1表示负数,即鼠标向左移动
|--bit3: 恒为1
|--bit2: 1表示中键按下
|--bit1: 1表示右键按下 0表示右键抬起
|--bit0: 1表示左键按下 0表示左键抬起
BYTE2 -- X坐标变化量,与byte的bit4组成9位符号数,负数表示向左移,正数表右移。
用补码表示变化量
BYTE3 -- Y坐标变化量,与byte的bit5组成9位符号数,负数表示向下移,正数表上移。
用补码表示变化量
BYTE4 -- 滚轮变化。
0x01表示滚轮向前滚动一格;0xFF表示滚轮向后滚动一格;0x80是个中间值,不滚动。
试验数据:
BYTE2 X坐标变化量,当BYTE1的bit4为0的时候,0x01~0x7F 为向左移动,0x81~0xFF为向右移动,0x00,0x80为不移动。
BYTE1的bit4为1的时候,依旧。
试验数据是跟BYTE1的bit4没什么关系。
BYTE3的变化跟BYTE2的一样。
因此BYTE2/BYTE3/BYTE4的变化趋势都是一样的,中间是分界
点,山峰结构。
从低到高,再从高到低。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
USB 之人性化接口装置的报告描述元(1)作者: 林锡宽e-mail: sklin@.tw(原文刊于e 科技杂志vol. 30,2003 年6 月号)关于USB 的标准描述元已经在 e 科技杂志的第24 和25 期中作了完整的介绍。
有些读者来函希望能早日刊出报告描述元的介绍。
人性化接口装置HID 的类别特定描述元有三种,其中HID 描述元因为需要连接在接口描述元(标准描述元之一)之后,所以也已经在前文介绍了。
其他二个HID 类别特定描述元为报告描述元和实体描述元。
实体描述元几乎很少使用到,所以不拟介绍,虽然它不会很复杂。
本文仅专注介绍报告描述元。
相对来说,报告描述元最复杂,也不容易理解,可是却最重要,因为HID 装置与主机间的经常性数据传输都由报告描述元来规范。
因为报告描述元的复杂和难理解,使得此文的编撰花了不少时间,因此无法在上次刊完USB 标准描述元后,接着刊出。
由于内容篇幅颇长,所以仅能分为三篇陆续刊出。
本期的第一篇中仅介绍到区域性项目,下期的第二篇再继续介绍全局性项目和主项目。
这三类项目构成一个报告描述元。
最后仍需要以一个实际的范例来解说使用方法,所以第三篇文章将提供一个实际的范例:整合鼠标的键盘装置。
此外,也会将该范例的韧体程序代码提供给有兴趣的读者。
这个韧体程序代码不只是该范例的报告描述元,也含括了它的标准描述元。
概述报告(report)在这里意指数据传输(data transfer),而报告描述元则是对这些传输的数据作用途(usage)的说明。
USB 通讯协议的规范是以1 毫秒产生一个USB 讯框(frame),USB 装置可以在每一个讯框中传送和接收一个交易(transaction)。
交易是由数个封包(packet)组成,而传输是由一或数个交易来完成传递一串有意义的数据。
在这里,传输和报告的意义大同小异。
传输方式有四种,初学者只要了解控制型传输(control transfer)和中断型传输(interrupt transfer)即可。
控制型传输是当需要时才执行传输要求,是最一般的传输,组态、命令和状态的通讯都可以使用,主要用于讯息型数据(message-type data)。
中断型传输目的在做重复的数据更新(recurring data)传输,精确一点而言,即是在每个有限的周期内(bounded period)作至少一次的小量数据传送或接收﹔所以适用于流动型数据(stream-type data),注意这里所谓的周期时间就是在端点描述元中的轮询间隔时间。
报告有三种:Input,Output,和Feature。
后文会做进一步介绍。
中断型输入管线(interrupt in pipe)仅可以传送Input 报告,中断型输出管线(interrupt out pipe)仅可以传送Output 报告,但是控制型管线(control pipe)可传送Input,Output,和Feature 报告。
端点描述元有宣告所使用的端点为何种管线。
数据本身无意义,要赋于用途才知其为何种操控(control)﹔例如装置上的按钮、指示灯和x 与y 轴的位移等都通称操控,数据则为按钮和指示灯的开关状态或x 与y 轴的位移量。
为了这个目的应运而生报告描述元,其将数据的操控与它的用途作一对一的对应,所以解读报告后就可以知道每个数据作何种操控。
所以『传输的数据』和『操控』可谓一体的两面。
用途是以一个32 位的卷标(称作Usage tag)来表示,较高的16 位称作UsagePage(用途类页),较低的16 位称为Usage ID(用途识别名):Usage = (Usage Page: Usage ID)举例而言,二个字节分别为x 和y 轴的位移数据,因此第一个字节的Usage=(Generic Desktop: X),而第二个字节的Usage =(Generic Desktop: Y),其中Generic Desktop 为用途的大类别(称作用途类页)之一,x 和y 轴的操控用途属于此用途类页。
文件Universal Serial Bus HID Usage Tables完整列出所有的Usage Pages(用途类页)和Usage ID’s(用途识别名),使用者必须遵照该文件的规范来宣告操控的用途。
该文件的附录 A 有十多个报告描述元的范例,值得读者进一步参考。
标签用途卷标只是报告描述元诸多标签之一。
表 1 列出所有的卷标,利用这些卷标即可以清楚完整的描述操控的用途。
报告描述元的语法不同于USB 标准描述元者,它是以项目(items)方式排列而成,无一定的长度﹔项目有一个前称(prefix),然后跟着一个括号,内为该项目的数据(data):item = prefix (data)。
项目又分三种型别:主项目,全局项目,区域项目。
主项目中的Input,Output,Feature 三个卷标用来表示报告中数据的种类,这些是报告描述元中最主要的项目,其他项目都是用来修饰这三种项目。
主项目中其他二个卷标容后再介绍,在此略过。
Input项:表示由装置操控输入到主机的数据格式。
这个数据格式就形成一个输入报告,虽然输入报告可以用控制型管线以Get_Report(Input)来传输,但是通常用中断型输入管线来传输,以确保在每一固定周期内都能将更新的输入报告传给主机。
Output项:表示由主机输出到装置操控的数据格式。
这个数据格式就形成一个输出报告。
输出报告通常不适用轮询方式来传给装置,而是由应用软件依实际需求以指令方式要求送出输出报告,所以大多是用控制型管线以Set_Report(Output)指令来将报告送到装置。
当然也可以选择用中断型输出管线来传送,只是通常不建议。
Feature项:表示由主机送到装置的组态所需数据的数据格式。
这个个数据格式就形成一个特征报告。
特征报告只能用控制型管线以Get_Report(Feature)和Set_Report(Feature)指令分别来取得和设定装置的特征值。
范例:考虑一个2×16 字的显示设备,它的列数、行数、字宽、和字高为固定值属于Feature 报告﹔显示状态例如『就绪』和『输入字错误』则属于Input 报告﹔光标位置和显示的字需可读可写,所以属于另一个Feature 报告﹔更新显示的字则为Output 报告。
为了区别二个Features,要用到全局项目中的Report ID,每个Feature 报告有一个不同的Report ID,因而主机的请求指令要加上Report ID 的值:Get_Report(Feature, Report ID)和Set_Report(Feature,Report ID)。
主项目用来定义报告中数据的种类和格式,而说明主项目之意义与用途为全局性项目和区域性项目。
顾名思义,区域性项目只能适用于列于其下面的第一个主项目,不能扩及其他主项目,若一个主项目之上方有数个不同卷标的区域性项目,则这些区域性项目皆适用于描述该主项目。
相反的,全局性项目适用于其下方所列的所有主项目,除非另一个相同卷标的全局性项目出现在其下方来取代它。
为求清楚说明报告描述元,将使用『项目状态表』(item state table)用来表示在某位址处适用的全局性项目的组合。
图 1 显示全局性项目和区域性项目与所描述的主项目之对应关系。
图1报告描述元之架构图区域项目卷标简单的说,区域项目(见表1)只是说明用途而已。
Designator 是要搭配实体描述元使用的,本文不拟介绍实体描述元,所以忽略这些Designator 标签。
标签Usage 实际上应该称作Usage ID,它搭配全局项目的Usage Page 卷标才形成前文所定义的用途{usage}﹔但是报告描述元允许在区域项目的Usage 卷标直接用32位的方式来指定用途,这种方式称作扩充式用途指定法(extended usage)以示区别。
例如:Usage(Generic Desktop:Mouse),Usage Minimum(Keyboard:0),和UsageMaximum(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 来描述该操控的报告数据,这个字符串在字符串描述元中,String Index (data)项目中的data 是这个字符串在字符串描述元中的位置索引。
如果需要用到数个字符串,则可以使用String Minimum 来指向字符串描述元中被用到字符串的最先位置索引,和String Maximum 来指向最后位置索引。
标签Delimiter 很少用到,请读者参考Universal Serial Bus HID Usage Tables文件中Appendix B 的范例详细说明。
小结在下二期的e 科技杂志中将会陆续刊出下二篇文章,其中第二篇将介绍全局性项目和主项目。
而第三篇为讲解报告描述元的使用方法,将提供一个实际的范例:整合鼠标的键盘装置。
USB 之人性化接口装置的报告描述元(2)作者: 林锡宽e-mail: sklin@.tw(原文刊于e 科技杂志vol. 31,2003 年7 月号)上期的第一篇文章提到报告描述元的语法是以项目方式排列而成,无一定的长度﹔项目有一个前称,然后跟着一个括号,内为该项目的数据,即item = prefix (data)。
项目又分三种型别:主项目,全局项目,区域项目。
第一篇已经介绍了区域项目,本篇将继续介绍主项目和全局项目。
下期的第三篇文章将以一个实际例子来介绍使用方法。
阅读本篇时,请随时参考第一篇的表1。