现在的位置: 首页 > 综合 > 正文

USB枚举和HID枚举实例

2013年02月16日 ⁄ 综合 ⁄ 共 3466字 ⁄ 字号 评论关闭

在说枚举过程之前,先把一些必须了解的说明白

一.USB包结构和分类

     包的共同特点是,都是以同步域开始,接着是PID,最后以EOP结束,而设备端则靠SEI(串行接口引擎,硬件上实现)来进行这些底层的处理,包括CRC的校验之类的东东。

    8位的PIDPID0~PID3,用于表示包,高四位进行取反,进行校验

    各种包的如下:

    令牌类:OUT,IN ,SOF,SETUP

    数据类:DATA0,DATA1,DATA2,MDATA

    握手类:ACK,NCK,STALL,NYET

    特殊类:PRE,ERR,SPLIT,PING

    令牌包用于启动一次USB传输,这些IN,OUT都以主设备而言的

    SETUP建立控制传输过程

    令牌包的结构为,

    同步域+PID+7位地址+4位端点号+5CRC校验+EOP

    数据包的结构为,

    同步域+PID+字节0~字节N+CRC+EOP

    在数据包中,我们看到有DATA0DATA1,这实际上形成了一种数据纠错机制。

    在数据发送成功或者接收时,数据包类型切换,如果检测到包类型没有切换,说明刚刚的数据传输没有发送成功。否则表示成功接收到数据了,虽然也有握手包来说明问题。

   握手包

   同步域+包标识+EOP

 

.事务

   不能简单的通过包来进行数据传输,所以由不同的包组织而成事务,就是所谓的transcation

一个事务通常由三个不同类型的包组成,令牌包,数据包,握手包

令牌包启动事务,握手包返回信息,数据包传输数据,方向由令牌包决定

我们知道USB中有4中传输类型,批量传输,等时传输,中断传输和控制传输,控制传输一般用于总线的枚举过程。

控制传输事务有三个过程,包括建立过程,数据过程,状态过程

其余三种传输对应一个事务

我们挑控制传输说明问题,其余就简单了

   这里有个有趣的东西,setup只能使用DATA0,在数据传输过程中,一旦数据传输方向发生变化,就会认为进入了状态过程,数据传输的第一个过程必须是DATA1包,每次传输正确之后是在DATA0DATA1中切换,而状态事务只能使用DATA1包。

USB设备的检测机制,在前面已经说过了,说个有意思的二次枚举的应用(因为重新上电之后就会有BUS的枚举设备过程)当设备插入之后,它先被识别成一个设备,该设备负责从主机上下载固件到设备的RAM内,然后设备将上拉电阻断开(模拟拔下,设备未断电,可以对口线进行操作就可以了),接着重新连接上拉电阻,当重新检测到设备时,使用的是已经下载的固件了,这就是不用烧录器的好处,只要改固件程序。

 

三.USB设备枚举过程

下面是USB设备枚举的过程

1. 主机发起第一个控制传输(获取设备描述):

1)主机SETUP包(发往地址0端点0)、主机数据包(请求设备描述符)、设备握手包ACK

设备产生端点0数据输出中断,固件程序要根据数据包中的主机要求做好准备,这里是在端点0输入缓冲区准备好设备描述符。

2)数据过程,主机先发一个IN令牌包、设备发一个数据包(这个数据已经准备好,SIE收到IN令牌后,直接送到总线上,用户此时不干预)、主机发ACK包。

此时SIE产生端点0数据输入中断,表明主机已经取走了设备所准备的数据,用户也可以在该中断处理程序中作自己的处理。(如清理操作等)

此时,主机只接受一次数据,最少8个字节。如果用户数据没有发完,又在控制端点输入缓冲区,准备了数据,主机也不理会。

3)状态过程:主机发OUT包(通知设备要输出)、主机发0字节状态数据包(这个是0字节,表明自己收到设备描述符)、设备发握手ACK包。

此时设备不会产生端点0数据输出中断,此时没有数据。

 

2、枚举过程中,第二个来回:设置地址。

第一个来回成功以后,主机再次复位总线。进入地址设置控制传输阶段。

1)主机SETUP包(发往地址0端点0)、主机数据包(请求设置地址)、设备握手包ACK。所以SETUP包后面都会跟一个表明主机SETUP目的的数据包,要么GET,要么SET

设备产生端点0数据输出中断,固件程序要根据数据包中的主机要求做好准备,这里是在根据主机发来的地址写入自己的地址控制寄存器。

2)数据过程,本次传输没有数据。

3)状态过程:主机发IN包(通知设备要返回数据)、设备发0字节状态数据包(表明地址设置已经成功)、主机发握手ACK包(地址设置已经生效)。

此时设备不会产生端点0数据输入中断,此时没有数据。

 

3、枚举过程中,第三个来回:主机使用新地址获取完整的设备描述符。

主机采用新地址发起第一个控制传输:

1)主机SETUP包(发往新的地址端点0)、主机数据包(请求设备描述符)、设备握手包ACK

设备产生端点0数据输出中断,固件程序要根据数据包中的主机要求做好准备,这里是在端点0输入缓冲区准备好设备描述符。

2)数据过程,主机先发一个IN令牌包、设备发一个数据包(这个数据已经准备好,SIE收到IN令牌后,直接送到总线上,用户此时不干预)、主机发ACK包。

此时SIE产生端点0数据输入中断,表明主机已经取走了设备所准备的数据,用户可以该中断处理程序中要做如下处理:如果一次没有将描述符送完,要再次将剩下的内容填充端点0输入缓冲区。

第二次数据传输:主机再发一个IN令牌包、设备发一个数据包、主机发ACK包。

此时SIE再次产生端点0数据输入中断,如果数据已经发完了。这里就不处理了。进入状态过程。

3)状态过程:主机发OUT包(通知设备要输出)、主机发0字节状态数据包(表明自己收到设备描述符)、设备发握手ACK包。

接下来获取配置描述符、配置集合、字符串描述符、报告描述符的过程差不多,这里就不再叙述了。

具体可以看下图:

 

 

上面说的前两个过程在BUS bound中是看不到的,上图来自网络

具体的上面已经说得很清楚了

其中红线的部分就是设置的地址,

 

set_address请求的结构为

bmrequestType 0x00

SET_ADDRESS 0x05

wValue 设备地址(上面提到的0x0002,设备地址一般从地址0开始分配

wIndex 0x0000

wLength 0x0000

具体可以看文档

 

四.USB HID设备(鼠标)的枚举过程

 

以上的截图是通过BUS BOUND得到的,不过没有set_address前的枚举过程而已。

(1)   取得设备描述符    get device descriptor

80 06 00 01 00 00 12 00

80         标准请求 数据传输方向 设备到主机

06         取得描述符请求Get Descriptor

0100     01表示的设备描述符 00描述符的索引

0000     读取描述符时 字符串的语言ID

0012     18字节 需要返回取得的字节数

(2)   设备描述符

12 01 10 01 00 00 00 08 3a 09 10 25 00 01 01 02 00 01

12         18字节 设备描述符长度

01         设备描述符

0110     USB设备的USB协议为1.1

00          设备使用的类代码 一般这里定义为0 协议在接口描述符中定义

00         子类代码

00         设备使用的协议

08         端点0的最大包长

093a      厂商的ID

2510            产品ID              这两个值可以在设备属性中看到

0100      版本号1.0

01          描述厂商的字符串的索引值    

02          产品的字符串索引值

00          设备的序列号字符串索引值   0表示没有序列号字符串

01          设备有多少种配置      

(3)   取得配置描述符 Get Descriptor

80 06 00 02 00 00 09 00

这里取得描述符(1)类似

02 表示 取得配置描述符

00 09 希望取得的配置描述符长度

(4)   配置描述符

09 02 22 00 01 01 04 a0 32

09         length

02         configuration descriptor

0022     配置描述符总长度34字节

01         该配置所支持的接口数01 鼠标是一个接口,一个接口代表一个功能

01                配置值为01      set config时,如果找到与配置值匹配的,则设置为此配置

04          配置字符串的索引值

a0                 a0对应的二进制位10100000 D71是必须的,D61表示为设备自供电,为

抱歉!评论已关闭.