注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

LINUX驱动学习——USB驱动(七)之USB鼠标(7)  

2011-01-20 11:10:53|  分类: USB系列 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
 

今天争取把鼠标这部分结束,其实今天也没有什么难的东西了,不过很复杂,这个东西就是报告描述符,USB HID设备是通过报告来传送数据的,关于HID的设备可以到USB的官网上下载,这个挺重要。

报告就要有输入和输出两种啦,输出报告是主机发送给USB设备的,例如键盘上的数字键盘锁定灯和大写字母锁定灯。

输入报告就是USB设备发送给主机的,例如,USB鼠标将鼠标移动和鼠标点击等信息返回给计算机,或者键盘将按键数据返回给计算机。

报告里包含的是所要传输的数据,数量为整数字节,被划分为一个个的域。通常,输入报告是通过中断输入端点返回的,而输出报告有点区别,当没有中断输出端点时,可以通过控制输出端点0发送,当有中断输出端点时,通过中断输出端点发出。当然,不管是否有中断输出端点(中断输入端点是必须的),主机都可以通过获取报告和设置报告的请求从端点0来来获取或者发送报告。

报告描述符和普通描述符一样都是通过控制输入端点0来返回,主机使用获取报告描述符请求来获取报告描述符,注意这个请求是发送到接口的,而不是设备。一个报告描述符可以描述多个报告,不同的报告通过报告ID来识别,报告ID放在报告的最前面,即第一个字节,当报告描述符中没有规定报告ID时,报告中就没有ID字段,开始就是数据。

报告描述符与前面的描述符有所不同,没有描述符长度和描述符类型等信息,而是由一个个条目(item)组成的,通常,在写报告描述符时,一个条目占据一行,这样看起来清晰一些,在HID的协议中元宝了两种条目:短条目和长条目,长条目很少使用,这里不介绍,只介绍短条目的结构。

短条目由1字节的前缀后面跟上可选 的数据字节组成,可选的数据字节可以是0字节,1字节和2或者4字节,实际使用的条目,大部分是只有1字节可选数据的,少数会使用0或者2字节数据,条目的前缀结构如下:

7

6

5

4

3

2

1

`0

          bTag

     bType

     bSize

 

 

D0 ~ D1:代表bSize用来说明后面所跟数据的字节数。这里需要注意的3表示的是4字节。

D2~D3:代表bType,表示条目的类型。

0为主(main)条目,1为全局(global)条目,2为局部(local)条目,3为保留值。

D4~D7:该条目的功能,具体参看HID协议以及HID的用途表。

 

主条目有5个,分别为input(输入),output(输出),feature(特性),collection(集合) endcollection(关集合)。

主条目用来定义或者分组报告的数据域,例如可以使用输入主条目将输入报告划分为不同的数据域,以及指定该域的属性。以于input,output,feature三个主条目,后面跟的第一个字节数据每个位的数据表示一种属性,例如位0表示该数据域是变量还是常量,位1表示是数组还是单一变量,位2表示是相对值还是绝对值。

全局条目主要用来选择用途页,定义数据域的长度、数量和报告ID等。全局条目在出现后对接下来的所有主条目都有效,除非遇到另外一个全局条目来改变它。常用的有Usage Page,Logical Minimum,Logical Maximum,Physical Minimum,Physical Maximum,Report Size,Report Count,Report ID等等。具体的看协议和书了。

局部条目用来定义控制的特性,例如,该数据域的用途,用途的最小值,用途的最大值等。局部条目只在局部有效,遇到一个主条目后,它后效用就结束了,常用的局部条目有:Usage,Usage Minimum,Usage Maximum.

条目的功能值不再说了,这个说得我都头晕了,虽然是抄别人的,但还是受不了,大家可以按照协议来设计报告描述符,也可以使用USB官网上提供的HID描述符工具来生成,还可以使用现成的报告描述符进行修改,例如,在HID协议以及用途表文档中,就有很多现成的例子。

再抄个例子给大家。

code uint8 ReportDescriptor[]=

{

 //每行开始的第一字节为该条目的前缀,前缀的格式为:

 //D7~D4:bTag。D3~D2:bType;D1~D0:bSize。以下分别对每个条目注释。

 

 //这是一个全局(bType为1)条目,选择用途页为普通桌面Generic Desktop Page(0x01)

 //后面跟一字节数据(bSize为1),后面的字节数就不注释了,

 //自己根据bSize来判断。

 0x05, 0x01, // USAGE_PAGE (Generic Desktop)

 

 //这是一个局部(bType为2)条目,说明接下来的应用集合用途用于鼠标

 0x09, 0x02, // USAGE (Mouse)

 

 //这是一个主条目(bType为0)条目,开集合,后面跟的数据0x01表示

 //该集合是一个应用集合。它的性质在前面由用途页和用途定义为

 //普通桌面用的鼠标。

 0xa1, 0x01, // COLLECTION (Application)

 

 //这是一个局部条目。说明用途为指针集合

 0x09, 0x01, //   USAGE (Pointer)

 

 //这是一个主条目,开集合,后面跟的数据0x00表示该集合是一个

 //物理集合,用途由前面的局部条目定义为指针集合。

 0xa1, 0x00, //   COLLECTION (Physical)

 

 //这是一个全局条目,选择用途页为按键(Button Page(0x09))

 0x05, 0x09, //     USAGE_PAGE (Button)

 

 //这是一个局部条目,说明用途的最小值为1。实际上是鼠标左键。

 0x19, 0x01, //     USAGE_MINIMUM (Button 1)

 

 //这是一个局部条目,说明用途的最大值为3。实际上是鼠标中键。

 0x29, 0x03, //     USAGE_MAXIMUM (Button 3)

 

 //这是一个全局条目,说明返回的数据的逻辑值(就是我们返回的数据域的值啦)

 //最小为0。因为我们这里用Bit来表示一个数据域,因此最小为0,最大为1。

 0x15, 0x00, //     LOGICAL_MINIMUM (0)

 

 //这是一个全局条目,说明逻辑值最大为1。

 0x25, 0x01, //     LOGICAL_MAXIMUM (1)

 

 //这是一个全局条目,说明数据域的数量为三个。

 0x95, 0x03, //     REPORT_COUNT (3)

 

 //这是一个全局条目,说明每个数据域的长度为1个bit。

 0x75, 0x01, //     REPORT_SIZE (1)

 

 //这是一个主条目,说明有3个长度为1bit的数据域(数量和长度

 //由前面的两个全局条目所定义)用来做为输入,

 //属性为:Data,Var,Abs。Data表示这些数据可以变动,Var表示

 //这些数据域是独立的,每个域表示一个意思。Abs表示绝对值。

 //这样定义的结果就是,第一个数据域bit0表示按键1(左键)是否按下,

 //第二个数据域bit1表示按键2(右键)是否按下,第三个数据域bit2表示

 //按键3(中键)是否按下。

 0x81, 0x02, //     INPUT (Data,Var,Abs)

 

 //这是一个全局条目,说明数据域数量为1个

 0x95, 0x01, //     REPORT_COUNT (1)

 

 //这是一个全局条目,说明每个数据域的长度为5bit。

 0x75, 0x05, //     REPORT_SIZE (5)

 

 //这是一个主条目,输入用,由前面两个全局条目可知,长度为5bit,

 //数量为1个。它的属性为常量(即返回的数据一直是0)。

 //这个只是为了凑齐一个字节(前面用了3个bit)而填充的一些数据

 //而已,所以它是没有实际用途的。

 0x81, 0x03, //     INPUT (Cnst,Var,Abs)

 

 //这是一个全局条目,选择用途页为普通桌面Generic Desktop Page(0x01)

 0x05, 0x01, //     USAGE_PAGE (Generic Desktop)

 

 //这是一个局部条目,说明用途为X轴

 0x09, 0x30, //     USAGE (X)

 

 //这是一个局部条目,说明用途为Y轴

 0x09, 0x31, //     USAGE (Y)

 

 //这是一个局部条目,说明用途为滚轮

 0x09, 0x38, //     USAGE (Wheel)

 

 //下面两个为全局条目,说明返回的逻辑最小和最大值。

 //因为鼠标指针移动时,通常是用相对值来表示的,

 //相对值的意思就是,当指针移动时,只发送移动量。

 //往右移动时,X值为正;往下移动时,Y值为正。

 //对于滚轮,当滚轮往上滚时,值为正。

 0x15, 0x81, //     LOGICAL_MINIMUM (-127)

 0x25, 0x7f, //     LOGICAL_MAXIMUM (127)

 

 //这是一个全局条目,说明数据域的长度为8bit。

 0x75, 0x08, //     REPORT_SIZE (8)

 

 //这是一个全局条目,说明数据域的个数为3个。

 0x95, 0x03, //     REPORT_COUNT (3)

 

 //这是一个主条目。它说明这三个8bit的数据域是输入用的,

 //属性为:Data,Var,Rel。Data说明数据是可以变的,Var说明

 //这些数据域是独立的,即第一个8bit表示X轴,第二个8bit表示

 //Y轴,第三个8bit表示滚轮。Rel表示这些值是相对值。

 0x81, 0x06, //     INPUT (Data,Var,Rel)

 

 //下面这两个主条目用来关闭前面的集合用。

 //我们开了两个集合,所以要关两次。bSize为0,所以后面没数据。

 0xc0,       //   END_COLLECTION

 0xc0        // END_COLLECTION

};

感谢OO写得很清楚,我就不再多说了,很唐僧了,非常的,真的。

现在主要是bTag,这里有一个表如下:

表1、报告描述符的标签

 

主项目

全域项目

区域项目

标签

代码

标签

代码

标签

代码

Input

X08?

Usage Page

0x0?

Usage

0x0?

Output

0x9?

Logical Minimum

0x1?

Usage Minimum

0x1?

Feature

0x0b?

Logical Maximum

0x2?

Usage Maximum

0x2?

 

 

Physical Minimum

0x3?

Designator Minimum

0x3?

Collection

0xa1

Physical Maximum

0x4?

Designator Minimum

0x4?

End Collection

0xc0

Unit Exponent

0x5?

Designator Maximum

0x5?

 

 

Unit

0x6?

String

0x7?

 

 

Report Size

0x7?

Sreing Minimum

0x8?

 

 

Report ID

0x8?

String Maximum

0x9?

 

 

Report Coumt

0x9?

Delimiter

0xa?

 

 

Push

0xA?

 

 

 

 

Pop

0xb?

 

 

这个真得让我头大,自己对吧,因为只有前D7~D4才表示bTag,所以,后面的为问号,真得很累啊。

活儿终于完成了,顺利的按计划,虽然有很多很多的困难克服了,但前面仍然还有很多很多的困难,一起来吧!!!

  评论这张
 
阅读(1117)| 评论(2)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017