• 生活就是这样,需要去灌溉!
    • 谢谢您的关注,欢迎您的注册与写作!
    • 循环往复,生生不息,或许这就是生命的意义吧!生命是插曲的产品吧!
    • 古今多少事,都付笑言中!
    • 风住尘香花已尽,日晚倦梳头。物是人非事事休,欲语泪先流。
    • 闻说双溪春尚好,也拟泛轻舟,只恐双溪舴艋舟,载不动许多愁。

USB协议基本知识

Resources 柳叶扉鸿 来源:CSDN:wrty 4年前 (2020-04-27) 421次浏览 已收录 扫描二维码
内容纲要

USB 基本知识 
USB 的重要关键概念:
1、 端点:位于 USB 设备或主机上的一个数据缓冲区,用来存放和发送 USB 的各种数据,每一个端点都有惟一的确定地址,有不同的传输特性(如输入端点、输出端点、配置端点、批量传输端点)
2、 帧:时间概念,在 USB 中,一帧就是 1MS,它是一个独立的单元,包含了一系列总线动作,USB 将 1 帧分为好几份,每一份中是一个 USB 的传输动作。
3、upstream、downstream(上行、下行)设备到主机为上行,主机到设备为下行

下面以一问一答的形式开始学习吧:

问题一:USB 的传输线结构是如何的呢?

答案一:一条 USB 的传输线分别由地线、电源线、D+、D-四条线构成,D+和 D-是差分输入线,它使用的是 3.3V 的电压(注意哦,与 CMOS 的 5V 电平不同),而电源线和地线可向设备提供 5V 电压,最大电流为 500MA

问题二:数据是如何在 USB 传输线里面传送的

答案二:数据在 USB 线里传送是由低位到高位发送的。

问题三:USB 的编码方案?

答案三:USB 采用不归零取反来传输数据,当传输线上的差分数据输入 0 时就取反,输入 1 时就保持原值,为了确保信号发送的准确性,当在 USB 总线上发送一个包时,传输设备就要进行位插入***作(即在数据流中每连续 6 个 1 后就插入一个 0),从而强迫 NRZI 码发生变化。这个了解就行了,这些是由专门硬件处理的。

问题四:USB 的数据格式是怎么样的呢?

答案四:和其他的一样,USB 数据是由二进制数字串构成的,首先数字串构成域(有七种),域再构成包,包再构成事务(IN、OUT、SETUP),事务最后构成传输(中断传输、并行传输、批量传输和控制传输)。下面简单介绍一下域、包、事务、传输,请注意他们之间的关系。

(一)域:是 USB 数据最小的单位,由若干位组成(至于是多少位由具体的域决定),域可分为七个类型:

1、同步域(SYNC),八位,值固定为 0000 0001,用于本地时钟与输入同步

2、标识域(PID),由四位标识符+四位标识符反码构成,表明包的类型和格式,这是一个很重要的部分,这里可以计算出,USB 的标识码有 16 种,具体分类请看问题五。

3、地址域(ADDR):七位地址,代表了设备在主机上的地址,地址 000 0000 被命名为零地址,是任何一个设备第一次连接到主机时,在被主机配置、枚举前的默认地址,由此可以知道为什么一个 USB 主机只能接 127 个设备的原因。

4、端点域(ENDP),四位,由此可知一个 USB 设备有的端点数量最大为 16 个。

5、帧号域(FRAM),11 位,每一个帧都有一个特定的帧号,帧号域最大容量 0x800,对于同步传输有重要意义(同步传输为四种传输类型之一,请看下面)。

6、数据域(DATA):长度为 0~1023 字节,在不同的传输类型中,数据域的长度各不相同,但必须为整数个字节的长度

7、校验域(CRC):对令牌包和数据包(对于包的分类请看下面)中非 PID 域进行校验的一种方法,CRC 校验在通讯中应用很泛,是一种很好的校验方法,至于具体的校验方法这里就不多说,请查阅相关资料,只须注意 CRC 码的除法是模 2 运算,不同于 10 进制中的除法。

(二)包:由域构成的包有四种类型,分别是令牌包、数据包、握手包和特殊包,前面三种是重要的包,不同的包的域结构不同,介绍如下

1、令牌包:可分为输入包、输出包、设置包和帧起始包(注意这里的输入包是用于设置输入命令的,输出包是用来设置输出命令的,而不是放据数的)

其中输入包、输出包和设置包的格式都是一样的:

SYNC+PID+ADDR+ENDP+CRC5(五位的校验码)

帧起始包的格式:

SYNC+PID+11 位 FRAM+CRC5(五位的校验码)

2、数据包:分为 DATA0 包和 DATA1 包,当 USB 发送数据的时候,当一次发送的数据长度大于相应端点的容量时,就需要把数据包分为好几个包,分批发送,DATA0 包和 DATA1 包交替发送,即如果第一个数据包是 DATA0,那第二个数据包就是 DATA1。但也有例外情况,在同步传输中(四类传输类型中之一),所有的数据包都是为 DATA0,格式如下:

SYNC+PID+0~1023 字节+CRC16

3、握手包:结构最为简单的包,格式如下

SYNC+PID

USB 的四种传输类型:

1.  控制传输:

      控制传输是一种可靠的双向传输,一次控制传输可分为三个阶段。第一阶段为从 HOST 到 Device 的SETUP 事务传输,这个阶段指定了此次控制传输的请求类型;

      第二阶段为数据阶段,也有些请求没有数据阶段;第三阶段为状态阶段,通过一次 IN/OUT 传输表明请求是否成功完成。

      控制传输通过控制管道在应用软件和 Device 的控制端点之间进行,控制传输过程中传输的数据是有格式定义的,USB 设备或主机可根据格式定义解析获得的数据含义。

      其他三种传输类型都没有格式定义。

      控制传输对于最大包长度有固定的要求。对于高速设备该值为 64Byte;对于低速设备该值为 8;全速设备可以是 8 或 16 或 32 或 64。

      最大包长度 表征了一个端点单次接收/发送数据的能力,实际上反应的是该端点对应的 Buffer 的大小。Buffer 越大,单次可接收/发送的数据包越大,反之亦反。

      当通过一个端点进行数据传输时,  若数据的大小超过该端点的最大包长度时,需要将数据分成若干个数据包传输,并且要求除最后一个包外,所有的包长度均等于该最大包长度。

      这也就是说如果一个端点收到/发送了一个长度小于最大包长度的包,即意味着数据传输结束。

      控制传输在访问总线时也受到一些限制,如:

        a. 高速端点的控制传输不能占用超过 20%的微帧,全速和低速的则不能超过 10%。 
b. 在一帧内如果有多余的未用时间,并且没有同步和中断传输,可以用来进行控制传输。

2.  中断传输:

      中断传输是一种轮询的传输方式,是一种单向的传输,HOST 通过固定的间隔对中断端点进行查询,若有数据传输或可以接收数据则返回数据或发送数据,否则返回 NAK,表示尚未准备好。

      中断传输的延迟有保证,但并非实时传输,它是一种延迟有限的可靠传输,支持错误重传。
对于高速/全速/低速端点,最大包长度分别可以达到 1024/64/8 Bytes。

      高速中断传输不得占用超过 80%的微帧时间,全速和低速不得超过 90%。

      中断端点的轮询间隔由在端点描述符中定义,全速端点的轮询间隔可以是 1~255mS,低速端点为 10~255mS,高速端点为(2interval-1)*125uS,其中 interval 取 1 到 16 之间的值。

      除高速高带宽中断端点外,一个微帧内仅允许一次中断事务传输,高速高带宽端点最多可以在一个微帧内进行三次中断事务传输,传输高达 3072 字节的数据。

      所谓单向传输,并不是说该传输只支持一个方向的传输,而是指在某个端点上该传输仅支持一个方向,或输出,或输入。如果需要在两个方向上进行某种单向传输,需要占用两个端点,

      分别配置成不同的方向,可以拥有相同的端点编号。

3.  批量传输:

      批量传输是一种可靠的单向传输,但延迟没有保证,它尽量利用可以利用的带宽来完成传输,适合数据量比较大的传输。

      低速 USB 设备不支持批量传输,高速批量端点的最大包长度为 512,全速批量端点的最大包长度可以为 8、16、32、64。

      批量传输在访问 USB 总线时,相对其他传输类型具有最低的优先级,USB HOST 总是优先安排其他类型的传输,当总线带宽有富余时才安排批量传输。

      高速的批量端点必须支持 PING 操作,向主机报告端点的状态,NYET 表示否定应答,没有准备好接收下一个数据包,ACK 表示肯定应答,已经准备好接收下一个数据包。

4.  同步传输:

      同步传输是一种实时的、不可靠的传输,不支持错误重发机制。只有高速和全速端点支持同步传输,高速同步端点的最大包长度为 1024,低速的为 1023。

      除高速高带宽同步端点外,一个微帧内仅允许一次同步事务传输,高速高带宽端点最多可以在一个微帧内进行三次同步事务传输,传输高达 3072 字节的数据。

      全速同步传输不得占用超过 80%的帧时间,高速同步传输不得占用超过 90%的微帧时间。 同步端点的访问也和中断端点一样,有固定的时间间隔限制。

      在主机控制器和 USB  HUB 之间还有另外一种传输——分离传输(Split  Transaction),它仅在主机控制器和 HUB 之间执行,通过分离传输,可以允许全速/低速设备连接到高速主机。

      分离传输对于 USB 设备来说是透明的、不可见的。

      分离传输:顾名思义就是把一次完整的事务传输分成两个事务传输来完成。其出发点是高速传输和全速/低速传输的速度不相等,如果使用一次完整的事务来传输,势必会造成比较长的等待时间,

      从而降低了高速 USB 总线的利用率。通过将一次传输分成两此,将令牌(和数据)的传输与响应数据(和握手)的传输分开,这样就可以在中间插入其他高速传输,从而提高总线的利用率。

总结:USB 的最小单元是“域”,由“域”构成了“包”,在由“包”构成了“事务”,最后由“事务”构成了“传输”,在应用层面,我们看到的只是传输,所以 USB 协议栈就需要完成传输以下的所有事情。这对标准的 USB 协议栈提出了最基本的要求。

————————————————————————————————————————————-

一、USB 硬件介绍
1.1、概述

一条 USB 传输线分别由地线、电源线、D+和 D-四条线构成,D+和 D-是差分输入线,它使用的是 3.3V 的电压(与 CMOS 的 5V 电平不同),而电源线和地线可向设备提供 5V 电压,最大电流为 500mA(可以在编程中设置)。
USB 设备可以直接和 HOST 通信,或者通过 Hub 和 Host 通信。一个 USB 系统中仅有一个 USB 主机,设备包括 USB 功能设备和 USB HUB,最多支持 127 个设备。物理连接指的是 USB 传输线。在 USB 2.0 系统中要求使用屏蔽双绞线。
1.2、USB HUB
USB HUB 提供了一种低成本、低复杂度的 USB 接口扩展方法。HUB 的上行 PORT 面向 HOST,下行 PORT 面向设备(HUB 或功能设备)。在下行 PORT 上,HUB 提供了设备连接检测和设备移除检测的能力,并给各下行 PORT 供电。HUB 可以单独使能各下行 PORT。不同 PORT 可以工作在不同的速度等级(高速/全速/低速)。
如果 USB 设备通过集线器和 Host 通信,主机集线器监视着每个端口的信号电压,当有新设备接入时便可觉察。集线器端口的两根信号线的每一根都有 15kΩ的下拉电阻,而每一个设备在 D+都有一个 1.5kΩ的上拉电阻。当用 USB 线将 PC 和设备接通后,设备的上拉电阻使信号线的电位升高,因此被主机集线器检测到。

二、USB 数据格式

USB 的重要关键字:

端点(Endpoint):位于 USB 设备或主机上的一个数据缓冲区,是 USB 设备中可以进行数据收发的最小单元,支持单向或者双向的数据传输,用来存放和发送 USB 的各种数据,每一个端点都有惟一的确定地址,有不同的传输特性(如输入端点、输出端点、配置端点、批量传输端点)。设备支持端点的数量是有限制的,除默认端点外低速设备最多支持 2 组端点(2 个输入,2 个输出),高速和全速设备最多支持 15 组端点。

帧:时间概念,在 USB 中,一帧就是 1MS,它是一个独立的单元,包含了一系列总线动作,USB 将 1 帧分为好几份,每一份是一个 USB 的传输动作。

上行、下行:设备到主机为上行,主机到设备为下行。

2.1、USB 数据传输方法

数据在 USB 线里传送是由低位到高位发送的。

USB 采用不归零取反来传输数据,当传输线上的差分数据输入 0 时就取反,输入 1 时就保持原值,为了确保信号发送的准确性,当在 USB 总线上发送一个包时,传输设备就要进行位插入操作(即在数据流中每连续 6 个 1 后就插入一个 0),从而强迫 NRZI 码发生变化。这些是由专门硬件处理的。

2.2、数据格式

USB 数据是由二进制数字串构成的,首先数字串构成域(有七种),域再构成包,包再构成事务(IN、OUT、SETUP),事务最后构成传输(中断传输、并行传输、批量传输和控制传输)。下面介绍一下域、包和事务。

2.2.1、域
域是 USB 数据最小的单位,由若干位组成(多少位由具体的域决定),域可分为七个类型:

1、同步域(SYNC)
所有的 USB 包都由 SYNC 开始,高速包的 SYNC 宽度为 32bit,全速/低速包的 SYNC 段度为 8bit。实际接收到的 SYNC 长度由于 USB HUB 的关系,可能会小于该值。八位的值固定为 0000 0001,用于本地时钟与输入同步。

2、标识域(PID)
由四位标识符 + 四位标识符反码构成,表明包的类型和格式,这是一个很重要的部分,这里可以计算出,USB 的标识码有 16 种。USB2.0 使用了十六种标识码,标识码的作用是用来说明包的属性的,标识码是和包联系在一起的,标识码分别有以下十六种:

令牌包 :

0x01:输出(OUT)启动一个方向为主机到设备的传输,并包含了设备地址和标号。

0x09:输入(IN) 启动一个方向为设备到主机的传输,并包含了设备地址和标号。

0x05:帧起始(SOF)表示一个帧的开始,并且包含了相应的帧号。

0x0d:设置(SETUP)启动一个控制传输,用于主机对设备的初始化。

数据包 :

0x03:偶数据包(DATA0)。

0x0b:奇数据包(DATA1)。

握手包:

0x02:确认接收到无误的数据包(ACK)。

0x0a:无效,接收(发送)端正在忙而无法接收(发送)信息。

0x0e:错误,端点被禁止或不支持控制管道请求。

特殊包 0x0C 前导,用于启动下行端口的低速设备的数据传输。

3、地址域(ADDR):七位地址,代表了设备在主机上的地址,地址 000 0000 被命名为零地址,是任何设备第一次连接到主机时,在被主机配置、枚举前的默认地址,由此可以知道为什么一个 USB 主机只能接 127 个设备的原因。

4、端点域(ENDP),四位,由此可知一个 USB 设备端点数量最大为 16 个。

5、帧号域(FRAM),11 位,每一个帧都有一个特定的帧号,帧号域最大容量 0x800,对于同步传输有重要意义。

6、数据域(DATA):长度为 0~1023 字节,在不同的传输类型中,数据域的长度各不相同,但必须为整数个字节的长度。

7、校验域(CRC):对令牌包和数据包中非 PID 域进行校验的一种方法,CRC 校验在通讯中应用很泛,是一种很好的校验方法,CRC 码的除法是模 2 运算,不同于 10 进制中的除法。

2.2.2、包
USB 数据包的格式如下:
USB协议基本知识

由域构成的包有四种类型,分别是令牌包、数据包、握手包和特殊包,前面三种是重要的包,不同包的域结构不同,介绍如下:

1、令牌包

分为输入包、输出包、设置包和帧起始包(注意这里的输入包是用于设置输入命令的,输出包是用来设置输出命令的,而不是放数据的)其中输入包、输出包和设置包的格式都是一样的:

SYNC + PID + ADDR + ENDP + CRC5(五位的校验码)

帧起始包的格式:

SYNC + PID + 11 位 FRAM + CRC5(五位的校验码)

2、数据包

分为 DATA0 包和 DATA1 包,当 USB 发送数据的时候,如果一次发送的数据长度大于相应端点的容量时,就需要把数据包分为好几个包,分批发送,DATA0 包和 DATA1 包交替发送,即如果第一个数据包是 DATA0,那第二个数据包就是 DATA1。但也有例外情况,在同步传输中(四类传输类型中之一),所有的数据包都是为 DATA0,格式如下:

SYNC + PID + 0~1023 字节 + CRC16

3、握手包
结构最为简单的包,格式如下:

SYNC + PID
握手包包括 ACK、NAK、STALL 以及 NYET 四种,其中 ACK 表示肯定的应答,成功的数据传输。NAK 表示否定的应答,失败的数据传输,要求重新传输。STALL 表示功能错误或端点被设置了 STALL 属性。NYET 表示尚未准备好,要求等待。

2.2.3、事务

分别有 IN、OUT 和 SETUP 三大事务,每一种事务都由令牌包、数据包、握手包三个阶段构成,这里用阶段的意思是因为这些包的发送是有一定的时间先后顺序的,事务的三个阶段如下:

1、令牌包阶段:启动一个输入、输出或设置的事务。

2、数据包阶段:按输入、输出发送相应的数据。

3、握手包阶段:返回数据接收情况,在同步传输的 IN 和 OUT 事务中没有这个阶段,这是比较特殊的。

事务的三种类型如下(以下按三个阶段来说明一个事务):

1、 IN 事务:

令牌包阶段——主机发送一个 PID 为 IN 的输入包给设备,通知设备要往主机发送数据;

数据包阶段——设备根据情况会作出三种反应(要注意:数据包阶段也不总是传送数据的,根据传输情况还会提前进入握手包阶段)。

1) 设备端点正常:设备往主机里面发出数据包(DATA0 与 DATA1 交替);

2) 设备正在忙:无法往主机发出数据包就发送 NAK 无效包,IN 事务提前结束,到了下一个 IN 事务才继续;

3) 相应设备端点被禁止:发送错误包 STALL 包,事务也就提前结束了,总线进入空闲状态。

握手包阶段——主机正确接收到数据之后就会向设备发送 ACK 包。

2、 OUT 事务:

令牌包阶段——主机发送一个 PID 为 OUT 的输出包给设备,通知设备要接收数据;

数据包阶段——比较简单,就是主机会往设备送数据,DATA0 与 DATA1 交替

握手包阶段——设备根据情况会作出三种反应

1) 设备端点接收正确,设备给主机返回 ACK,通知主机可以发送新的数据,如果数据包发生了 CRC 校验错误,将不返回任何握手信息;

2) 设备正在忙,无法给主机返回 ACK,就发送 NAK 无效包,通知主机再次发送数据;

3) 相应设备端点被禁止,发送错误包 STALL 包,事务提前结束,总线直接进入空闲状态。

3、SETUT 事务:

令牌包阶段——主机发送一个 PID 为 SETUP 的输出包给设备,通知设备要接收数据;

数据包阶段——比较简单,就是主机往设备送数据,注意,这里只有一个固定为 8 个字节的 DATA0 包,这 8 个字节的内容就是标准的 USB 设备请求命令,详见 2.4。

握手包阶段——设备接收到主机的命令信息后,返回 ACK,此后总线进入空闲状态,并准备下一个传输(在 SETUP 事务后通常是一个 IN 或 OUT 事务构成的传输)。

2.3、标准的 USB 设备请求命令

标准的 USB 设备请求命令是用在控制传输中的“初始设置步骤”里的数据包阶段(即 DATA0,由八个字节构成)。命令共有 11 个,大小都是 8 个字节,具有相同的结构,由 5 个字段构成(字段是标准请求命令的数据部分),结构如下(括号中的数字表示字节数,首字母 bm,b,w 分别表示位图、字节,双字节):

bmRequestType(1) + bRequest(1) + wvalue(2) + wIndex(2) + wLength(2)

各字段的意义如下:

1、bmRequestType:D7D6D5D4D3D2D1D0

D7=0 主机到设备

=1 设备到主机;

D6D5=00 标准请求命令

=01 类请求命令

=10 用户定义的命令

=11 保留值

D4D3D2D1D0=00000 接收者为设备

=00001 接收者为接口

=00010 接收者为端点

=00011 接收者为其他接收者

=其他  其他值保留

2、bRequest:请求命令代码,在标准的 USB 命令中,每一个命令都定义了编号,编号的值就为字段的值,编号与命令名称如下(要注意这里的命令代码要与其他字段结合使用,可以说命令代码是标准请求命令代码的核心,正是因为这些命令代码而决定了 11 个 USB 标准请求命令):

0  GET_STATUS:用来返回特定接收者的状态;

1  CLEAR_FEATURE:用来清除或禁止接收者的某些特性;

2) 3  SET_FEATURE:用来启用或激活命令接收者的某些特性;

5  SET_ADDRESS:用来给设备分配地址;

6  GET_DEscriptOR:用于主机获取设备的特定描述符;

7  SET_DEscriptOR:修改设备中有关的描述符,或者增加新的描述符;

8  GET_CONFIGURATION:用于主机获取设备当前设备的配置值(注同上面的不同);

9  SET_CONFIGURATION:用于主机指示设备采用的要求的配置;

10  GET_INTERFACE:用于获取当前某个接口描述符编号;

11  SET_INTERFACE:用于主机要求设备用某个描述符来描述接口;

12 SYNCH_FRAME:用于设备设置和报告一个端点的同步帧;

控制传输是 USB 的重心,而这 11 个命令是控制传输的重心,所以这 11 个命令是重中之重。
2.4、描述符(Descriptor)

Descriptor 是一个完整的数据结构,可以通过 C 语言等编程实现,并存储在 USB 设备中,用于描述一个 USB 设备的所有属性,USB 主机是通过一系列命令来要求设备发送这些信息的。它的作用就是给主机传递信息,从而让主机知道设备具有什么功能、属于哪一类设备、要占用多少带宽、使用哪类传输方式及数据量的大小,只有主机确定了这些信息之后,设备才能真正开始工作,所以描述符也是十分重要的部分,标准的描述符有 5 种,USB 为这些描述符定义了编号:

        1——设备描述符

        2——配置描述符

        3——字符描述符

        4——接口描述符

        5——端点描述符

上面的描述符之间有一定的关系,一个设备只有一个设备描述符,而一个设备描述符可以包含多个配置描述符,而一个配置描述符可以包含多个接口描述符,一个接口使用了几个端点,就有几个端点描述符。这些描述符是用一定的字段构成的,分别如下说明:

1、设备描述符

struct _DEVICE_DEscriptOR_STRUCT

{

BYTE bLength;          //设备描述符的字节数大小,为 0x12

BYTE bDescriptorType;  //描述符类型编号,为 0x01

WORD bcdUSB;           //USB 版本号

BYTE bDeviceClass;  //USB 分配的设备类代码,0x01~0xfe 为标准设备类,0xff 为厂商自定义类型

//0x00 不是在设备描述符中定义的,如 HID

BYTE bDeviceSubClass;   //usb 分配的子类代码,同上,值由 USB 规定和分配的

BYTE bDeviceProtocl;    //USB 分配的设备协议代码,同上

BYTE bMaxPacketSize0;   //端点 0 的最大包的大小

WORD idVendor;          //厂商编号

WORD idProduct;         //产品编号

WORD bcdDevice;         //设备出厂编号

BYTE iManufacturer;     //描述厂商字符串的索引

BYTE iProduct;          //描述产品字符串的索引

BYTE iSerialNumber;     //描述设备序列号字符串的索引

BYTE bNumConfiguration; //可能的配置数量

}

2、配置描述符

struct _CONFIGURATION_DEscriptOR_STRUCT

{

BYTE bLength;          //设备描述符的字节数大小,为 0x12

BYTE bDescriptorType;  //描述符类型编号,为 0x01

WORD wTotalLength;     //配置所返回的所有数量的大小

BYTE bNumInterface;    //此配置所支持的接口数量

BYTE bConfigurationVale;   //Set_Configuration 命令需要的参数值

BYTE iConfiguration;       //描述该配置的字符串的索引值

BYTE bmAttribute;          //供电模式的选择

BYTE MaxPower;             //设备从总线提取的最大电流

}

3、字符描述符

struct _STRING_DEscriptOR_STRUCT

{

BYTE bLength;          //设备描述符的字节数大小,为 0x12

BYTE bDescriptorType;  //描述符类型编号,为 0x01

BYTE SomeDescriptor[36];          //UNICODE 编码的字符串

}

4、接口描述符

struct _INTERFACE_DEscriptOR_STRUCT

{

BYTE bLength;          //设备描述符的字节数大小,为 0x12

BYTE bDescriptorType;  //描述符类型编号,为 0x01

BYTE bInterfaceNunber; //接口的编号

BYTE bAlternateSetting;//备用的接口描述符编号

BYTE bNumEndpoints;    //该接口使用端点数,不包括端点 0

BYTE bInterfaceClass;  //接口类型

BYTE bInterfaceSubClass;//接口子类型

BYTE bInterfaceProtocol;//接口所遵循的协议

BYTE iInterface;        //描述该接口的字符串索引值

}

5、端点描述符

struct _ENDPOIN_DEscriptOR_STRUCT

{

BYTE bLength;          //设备描述符的字节数大小,为 0x12

BYTE bDescriptorType;  //描述符类型编号,为 0x01

BYTE bEndpointAddress; //端点地址及输入输出属性

BYTE bmAttribute;      //端点的传输类型属性

WORD wMaxPacketSize;   //端点收、发最大包的大小

BYTE bInterval;        //主机查询端点的时间间隔

}

三、传输
USB 系统中的数据传输,宏观看是在 HOST 和 USB 功能设备之间进行。微观看是在应用软件的 Buffer 和 USB 功能设备的端点之间进行。一般来说端点都有 Buffer,可以认为 USB 通讯就是应用软件 Buffer 和设备端点 Buffer 之间的数据交换,交换的通道称为管道。应用软件通过和设备之间的数据交换来完成设备控制和数据传输。通常需要多个管道来完成数据交换,因为同一管道只支持一种类型的数据传输。用在一起来对设备进行控制的若干管道称为设备的接口,这就是端点、管道和接口的关系。
USB 采用“令牌包”-“数据包”-“握手包”的传输机制,在令牌包中指定数据包去向或者来源的设备地址和端点(Endpoint),从而保证了只有一个设备对被广播的数据包/令牌包作出响应。握手包表示了传输的成功与否。
USB 采用轮询的广播机制传输数据,所有的传输都由主机发起,任何时刻整个 USB 体系内仅允许一个数据包的传输,即不同物理传输线上看到的数据包都是同一被广播的数据包。

传输由 OUT、IN 和 SETUP 事务构成,传输有四种类型,中断传输、批量传输、同步传输、控制传输,其中中断传输和批量传输的结构一样,同步传输有最简单的结构,而控制传输是最重要的也是最复杂的传输。

3.1、控制传输
控制传输是一种可靠的双向传输,是最重要也是最复杂的,一次控制传输可分为构成(初始设置阶段、可选数据阶段、状态信息步骤),每一个阶段可以看成一个传输,也就是说控制传输其实是由三个传输构成的,在 USB 设备初次接到主机后,主机通过控制传输来交换信息、设备地址和读取设备的描述符,使得主机识别设备,并安装相应的驱动程序,这是每一个 USB 开发者都要关心的问题。
第一阶段:从 HOST 到 Device 的 SETUP 事务传输,这个阶段指定了此次控制传输的请求类型。
第二阶段:数据阶段,也有些请求没有数据阶段。
第三阶段:状态阶段,通过一次 IN/OUT 传输表明请求是否成功完成。
控制传输通过控制管道在应用软件和 Device 的控制端点之间进行,控制传输过程中传输的数据是有格式定义的,USB 设备或主机可根据格式定义解析获得的数据含义。其他三种传输类型都没有格式定义。控制传输对于最大包长度有固定的要求。对于高速设备该值为 64Byte,对于低速设备该值为 8,全速设备可以是 8 或 16 或 32 或 64。
最大包长度表征了一个端点单次接收/发送数据的能力,实际上反应的是该端点对应 Buffer 的大小。Buffer 越大,单次可接收/发送的数据包越大,反之亦反。当通过一个端点进行数据传输时,若数据的大小超过该端点的最大包长度时,需要将数据分成若干个数据包传输。并保证除最后一个包外,所有的包长度均等于该最大包长度。这也就是说如果一个端点收到/发送了一个长度小于最大包长度的包,即意味着数据传输结束。
控制传输在访问总线时也受到一些限制,如高速端点的控制传输不能占用超过 20%的微帧,全速和低速的则不能超过 10%。在一帧内如果有多余的未用时间,并且没有同步和中断传输,可以用来进行控制传输。
USB协议基本知识

控制传输(Transaction) 一次控制传输分为三(或两个)个阶段:建立(Setup)、数据(DATA)(可能没有)以及状态(Status)。每个阶段都由一次或多次(数据阶段)事务传输组成(Transaction)。
上图为建立阶段的事务传输流程图。可以看出:
与批量传输相比,在流程上并没有多大区别,区别只在于该事务传输发生的端点不一样、支持的最大包长度不一样、优先级不一样等这样一些对用户来说透明的东西。
建立阶段过后,可能会有数据阶段,这个阶段将会通过一次或多次控制传输事务,完成数据的传输。同样也会采用 PID 翻转的机制。
建立阶段,Device 只能返回 ACK 包,或者不返回任何包。
最后是状态阶段,通过一次方向与前一次相反的控制事务传输来表明传输的成功与否。如果成功会返回一个长度为 0 的数据包,否则返回 NAK 或 STALL。下图为整个控制传输的示意图:
USB协议基本知识
3.2、中断传输
中断传输是一种轮询的传输方式,是一种单向的传输。HOST 通过固定的间隔对中断端点进行查询,若有数据传输或可以接收数据则返回数据或发送数据。否则返回 NAK,表示尚未准备好。中断传输的延迟有保证,但并非实时传输,它是一种延迟有限的可靠传输,支持错误重传。对于高速/全速/低速端点,最大包长度分别可以达到 1024/64/8 Bytes。 高速中断传输不得占用超过 80%的微帧时间,全速和低速不得超过 90%。 中断端点的轮询间隔由在端点描述符中定义,全速端点的轮询间隔可以是 1~255mS。低速端点为 10~255mS,高速端点为(2interval-1)*125uS,其中 interval 取 1 到 16 之间的值。
除高速高带宽中断端点外,一个微帧内仅允许一次中断事务传输。高速高带宽端点最多可以在一个微帧内进行三次中断事务传输,传输高达 3072 字节的数据。
所谓单向传输,并不是说该传输只支持一个方向的传输。而是指在某个端点上该传输仅支持一个方向,或输出、或输入。如果需要在两个方向上进行某种单向传输,需要占用两个端点,分别配置成不同的方向。可以拥有相同的端点编号。
中断传输由 OUT 事务和 IN 事务构成,用于键盘、鼠标等 HID 设备的数据传输。
中断传输在流程上除不支持 PING 之外,其他的跟批量传输是一样的。他们之间的区别也仅在于事务传输发生的端点不一样、支持的最大包长度不一样、优先级不一样等这样一些对用户来说透明的东西。
主机在排定中断传输任务时,会根据对应中断端点描述符中指定的查询间隔发起中断传输。中断传输有较高的优先级,仅次于同步传输。同样中断传输也采用 PID 翻转的机制来保证收发端数据同步。
下图为中断传输的流程图。
USB协议基本知识

3.3、批量传输
批量传输由 OUT 事务和 IN 事务构成,是一种可靠的单向传输,但延迟没有保证,它尽量利用可以利用的带宽来完成传输,适合数据量比较大的传输。低速 USB 设备不支持批量传输,高速批量端点的最大包长度为 512,全速批量端点的最大包长度可以为 8、16、32、64。
批量传输在访问 USB 总线时,相对其他传输类型具有最低的优先级,USB HOST 总是优先安排其他类型的传输,当总线带宽有富余时才安排批量传输。高速的批量端点必须支持 PING 操作,向主机报告端点的状态。NYET 表示否定应答,没有准备好接收下一个数据包,ACK 表示肯定应答,已经准备好接收下一个数据包。
USB协议基本知识
图中一个方框表示一个 Packet,灰色的包表示主机发出的包,白色的包表示 Device 发出的包。批量传输是可靠的传输,需要握手包来表明传输的结果。若数据量比较大,将采用多次批量事务传输来完成全部数据的传输,传输过程中数据包的 PID 按照 DATA0-DATA1-DATA0-…的方式翻转,以保证发送端和接收端的同步。若成功则将错误次数计数器清 0,否则累加该计数器。USB 允许连续 3 次以下的传输错误,会重试该传输。超过三次后,HOST 认为该端点功能错误(STALL),放弃该端点的传输任务。
一次批量传输(Transfer)由 1 次到多次批量事务传输(Transaction)组成。
翻转同步:发送端按照 DATA0-DATA1-DATA0-…的顺序发送数据包,只有成功的事务传输才会导致 PID 翻转,也就是说发送段只有在接收到 ACK 后才会翻转 PID,发送下一个数据包,否则会重试本次事务传输。同样,若在接收端发现接收到的数据包不是按照此顺序翻转的,比如连续收到两个 DATA0,那么接收端认为第二个 DATA0 是前一个 DATA0 的重传。

3.4、同步传输

同步传输是一种实时的、不可靠的传输,不支持错误重发机制。只有高速和全速端点支持同步传输,高速同步端点的最大包长度为 1024,低速的为 1023。由 OUT 事务和 IN 事务构成。有两个特殊地方,第一,在同步传输的 IN 和 OUT 事务中是没有返回包阶段的;第二,在数据包阶段所有的数据包都为 DATA0。
除高速高带宽同步端点外,一个微帧内仅允许一次同步事务传输,高速高带宽端点最多可以在一个微帧内进行三次同步事务传输,传输高达 3072 字节的数据。全速同步传输不得占用超过 80%的帧时间,高速同步传输不得占用超过 90%的微帧时间。同步端点的访问也和中断端点一样,有固定的时间间隔限制。
USB协议基本知识
同步传输是不可靠的传输,所以它没有握手包,也不支持 PID 翻转。主机在排定事务传输时,同步传输有最高的优先级。

3.5、分离传输(Split Transaction)
分离传输是在主机控制器和 USB HUB 之间的传输,它仅在主机控制器和 HUB 之间执行,通过分离传输,可以允许全速/低速设备连接到高速主机。分离传输对于 USB 设备来说是透明的、不可见的。
分离传输,顾名思义就是把一次完整的事务传输分成两个事务传输来完成。其出发点是高速传输和全速/低速传输的速度不相等,如果使用一次完整的事务来传输,势必会造成比较长的等待时间,从而降低了高速 USB 总线的利用率。通过将一次传输分成两次,将令牌(和数据)的传输与响应数据(和握手)的传输分开,这样就可以在中间插入其他高速传输,从而提高总线的利用率。
3.6、总结
USB协议基本知识
包是 USB 总线数据传输的最小单位,不能被打断或干扰,否则会引发错误。若干个数据包组成一次事务传输,一次事务传输也不能打断,属于一次事务传输的几个包必须连续,不能跨帧完成。一次传输由一次到多次事务传输构成,可以跨帧完成。
四、枚举

USB 设备连接到 HOST 时,HOST 必须通过默认的控制管道对其进行枚举,完成获得其设备描述、进行地址分配、获得其配置描述、进行配置等操作后方可正常使用。USB 设备的即插即用特性即依赖于此。

4.1、枚举时 USB 的状态

当 USB 设备插上主机时,主机就通过一系列的动作来对设备进行枚举配置(配置是属于枚举的一个态,态表示暂时的状态),这些态如下:

1、接入态(Attached):设备接入主机后,主机通过检测信号线上的电平变化来发现设备的接入;

2、供电态(Powered):就是给设备供电,分为设备接入时的默认供电值,配置阶段后的供电值(按数据中要求的最大值,可通过编程设置);

3、缺省态(Default):USB 在被配置之前,通过缺省地址 0 与主机进行通信;

4、地址态(Address):经过了配置,USB 设备被复位后,就可以按主机分配给它的唯一地址来与主机通信,这种状态就是地址态;

5、配置态(Configured):通过各种标准的 USB 请求命令来获取设备的各种信息,并对设备的某些信息进行改变或设置。

6、挂起态(Suspended):总线供电设备在 3ms 内没有总线操作,即 USB 总线处于空闲状态的话,该设备就要自动进入挂起状态,在进入挂起状态后,总的电流功耗不超过 280uA。
状态转移图如下所示:
USB协议基本知识

4.2、枚举过程

1、用户将一个 USB 设备插入 USB 端口,主机为端口供电,设备此时处于上电状态。主机检测设备。集线器使用中断通道将事件报告给主机。

2、主机发送 Get_Port_Status(读端口状态)请求,以获取更多的设备信息。返回的消息告诉主机该设备是什么时候连接的。集线器检测设备是低速运行还是高速运行,并将此信息送给主机,这是对 Get_Port_Status 请求的响应。

3、主机发送 Set_Port_Feature(写端口状态)请求给集线器,要求它复位端口,请求集线器来重新设置端口。集线器使设备的 USB 数据线处于重启(RESET)状态至少 10ms。

4、主机使用 Chirp K 信号来了解全速设备是否支持高速运行。

5、主机发送另一个 Get_Port_Status 请求,确定设备是否已经从复位状态退出。返回的数据有一位表示设备仍然处于重启状态。当集线器释放了重启状态,设备此时处于缺省状态,且已准备好在零端点通过缺省通道响应主机控制传输。缺省地址为 00h,设备能从总线获取高达 100mA 的电流。
6、集线器检测设备速度

集线器通过测定哪根信号线(D+或 D-)在空闲时有更高的电压来检测设备是低速设备还是全速设备。全速和高速设备 D+有上拉电阻,低速设备 D-有上拉电阻。

7、获取最大数据包长度
主机向 address 0 发送 Get_Device_Deor(读设备描述符)报文,以取得缺省控制管道所支持的最大数据包长度。并在有限的时间内等待 USB 设备的响应。该长度包含在设备描述符的 bMaxPacketSize0 字段中,其地址偏移量为 7,所以这时主机只需读取该描述符的前 8 个字节。注意,主机一次只能枚举一个 USB 设备,所以同一时刻只能有一个 USB 设备使用缺省地址 0。
例:主机向设备发送一个八字节请求:80 06 00 01 00 00 40 00,设备接收到请求后产生一个中断,我们可以通过读中断寄存器知道中断源,并且可以加读最后状态寄存器来确定第一个接到的包是否为一个 Setup 包。当控制器处理程序判断出它是一个 Get_descriptor 请求时,把设备描述符的前 16 个字节发送到端点 0 缓冲区中。剩下的 2 个字节描述符第一次请求时不再发送。

8、主机分配一个新的地址给设备

主机通过发送一个 Set_Address 请求来分配一个唯一的地址给设备。设备读取这个请求,返回一个确认,并保存新的地址。从此开始所有通信都使用这个新地址。

例:当主机收到正确的前 16 字节描述符后,会给设备分配一个地址,我的 PC 分配的地址为:0x03(这个要看你的机子当时的 USB 接口设备数目而定) Set_Address 请求所发送的数据为:00 05 03 00 00 00 00 00,其中的 03 就表示主机为设备分配的地址为 0x03,在以后的通信里设备就只对 0x03 地址作出应答。当设备产生一个接收中断后,根据所分配的地址设置设备的地址寄存器相应位。

9、主机向新地址重新发送 Get_Device_Deor 命令,此次读取其设备描述符的全部字段,以了解该设备的总体信息,如 VID,PID。
例:主机发送设备描述符标准请求 Get_descriptor:80 06 00 01 00 00 12 00,此次将要求把 18 个字节全部发送完。所以主机要分两次来读取。第一次读取 16 个字节,第二次读取两个字节,最后主机发送 0 表示发送完毕的应答。

10、主机向设备循环发送 Get_Device_Configuration 命令,要求 USB 设备回答,以读取全部配置信息。

11、主机发送 Get_Device_String 命令,获得字符集描述(unicode),比如产商、产品描述、型号等等。此时主机将会弹出窗口,展示发现新设备的信息,产商、产品描述、型号等。

根据 Device_Deor 和 Device_Configuration 应答,PC 判断是否能够提供 USB 的 Driver,一般 win2k 能提供几大类的设备,如游戏操作杆、存储、打印机、扫描仪等,操作就在后台运行。但是 Win98 却不可以,所以在此时将会弹出对话框,索要 USB 的 Driver。

12、主机分配并加载设备驱动程序,这时就可能作应用中的数据传输了。

13、主机发送 Set_Configuration(x)(写配置)命令请求为该设备选择一个合适的配置(x 代表非 0 的配置值)。如果配置成功,USB 设备进入“配置”状态,并可以和客户软件进行数据传输。此时,常规的 USB 完成了其必须进行的配置和连接工作,至此设备应当可以开始使用。不过,USB 协议还提供了一些用户可选的协议,设备如果不应答,也不会出错,但是会影响到系统的功能。

14、主机为复合设备接口分配驱动程序。如果集线器检测到有过流现象,或者主机要求集线器关闭电源,则 USB 总线切断设备供电电源。在这种情况下,设备与主机无法通信,但设备处于连接状态。

使用 USB View 采集到的数据:

Device Descriptor:
bcdUSB:             0x0100
bDeviceClass:         0xDC
bDeviceSubClass:      0x00
bDeviceProtocol:      0x00
bMaxPacketSize0:      0x10 (16)
idVendor:           0x0471
idProduct:          0x0666
bcdDevice:          0x0100
iManufacturer:        0x00
iProduct:             0x00
iSerialNumber:        0x00
bNumConfigurations:   0x01

ConnectionStatus: DeviceConnected
Current Config Value: 0x01
Device Bus Speed:     Full
Device Address:       0x02
Open Pipes:              4

Endpoint Descriptor:
bEndpointAddress:     0x81
Transfer Type:   Interrupt
wMaxPacketSize:     0x0010 (16)
bInterval:            0x0A

Endpoint Descriptor:
bEndpointAddress:     0x01
Transfer Type:   Interrupt
wMaxPacketSize:     0x0010 (16)
bInterval:            0x0A

Endpoint Descriptor:
bEndpointAddress:     0x82
Transfer Type:        Bulk
wMaxPacketSize:     0x0040 (64)
bInterval:            0x0A

Endpoint Descriptor:
bEndpointAddress:     0x02
Transfer Type:        Bulk
wMaxPacketSize:     0x0040 (64)
bInterval:            0x0A

4.3、USB 枚举实例

对 2440 的 USB HOST 进行初始化完毕(主要包括对符合 OHCI 规范的寄存器的初始化—总线复位、中断使能、清除中断标志、电源管理、内存指针寄存器的初始化,各种数据结构的初始化等),等待 USB 设备的插入,当 2440 检测到有设备插入,就要对设备进行枚举了。起始枚举就相当于主机和设备建立连接的过程(接头),Host 向 Device 询问一些东西,Device 将自身的设备类型,如何进行通信报告给 Host,这样 Host 就知道怎么对 Device 进行操作了。

枚举的过程实际上用到而且只用到了总线的“控制传输(Control Transfer)”。这种传输方式通常用于配置/命令/状态等情形,其中的设置操作 setup 和状态操作 status 过程的数据包具有 USB 协议定义的数据结构,因此,控制传输只能通过消息管道进行。

一个完整的控制传输包括三个过程:

1、建立连接。
2、数据过程(可选) 。
3、状态过程。

建立连接的过程都是由 Host 发起,它开始于一个 Setup 令牌包,后面紧跟一个 DATA0 包。如果是控制输入传输,数据过程则为输入数据,若是控制输出传输,则数据过程是输出数据。

数据过程的可选型是指设置过程需要指定数据长度,如果指定为 0,则没有数据过程。状态过程跟在数据过程之后,状态过程恰好和数据过程的数据传输方向相反,因为此阶段主要是用来确认之前两阶段的所有数据都已经正确传输了。

好了,下面就结合我的这个实例来看看枚举的详细过程:

1、控制 2440 向 U 盘发送第一个 Setup 包,内容是 80 06 00 01 00 00 08 00,其中最后的 00 08 表示得到 DEVICE_DCESCRIPTOR 的前 8 个字节,因为这个包的主要目的是要获得 USB Device 中端点 0 的最大包的大小(第 8 个字节),所以只需要 8 个字节就可以了。USB Device 返回的设备标识符为 12 01 10 01 00 00 00 40,下面我们需要把 0x40 记录下来,将其放到 Endpoint Descriptor 数据结构的 DWORD0 的 MPS(bit16~bit32)块中去。
2、接下来 2440 发送第二个 Setup 包,内容是 00 05 01 00 00 00 00 00,这一次的作用是为 USB 设备分配地址。如果 USB Device 接收并接受了此地址设置包,会返回一个长度为 0 的数据包。主机接收到长度为 0 的状态包之后就会返回一个 ACK 给 Device,Device 再接收到这个 ACK 之后,就可以启用新地址了。这样 Device 就得到了一个唯一的设备地址,作为主机通信的唯一表示。

3、发送第三个 Setup 包,内容是 80 06 00 02 00 00 09 00,这次是为了获取配置描述符集合的大小,此位位于读回数据的第三个字节。U 盘返回的数据为 09 02 20 00 01 01 00 80 32,即描述符集合总大小为 0x20。

4、发送第四个 Setup 包,内容是 80 06 00 02 00 00 09 00,和上次不同的仅仅是,这次要读回来的数据是整个配置描述符区域。U 盘返回来的数据是 09 02 20 00 01 01 00 80 32 09 04 00 00 02 08 06 50 00 07 05 82 02 40 00 00 07 05 02 02 40 00 00。这时候我们就可以知道该设备是什么类型的设备,支持什么样的操作了。

上述这两个过程也有的程序就是直接读取 0xff 个字符大小,当然同样可以达到读回设备描述符集合的目的。

至此,我们已经得到了所需要的设备信息,之后就可以对设备进行配置了。

5、向设备发送第五个 Setup 包,数据为 00 09 01 00 00 00 00 00,USB Device 返回一个长度为 0 的数据包,表明数据正确接收。至此,USB 枚举过程就完成了。初始设置步骤:就是一个由 SET 事务构成的传输

可选数据步骤:就是一个由 IN 或 OUT 事务构成的传输,这个步骤是可选的,要看初始设置步骤有没有要求读/写数据(由 SET 事务的数据包阶段发送的标准请求命令决定)。

状态信息步骤:这个步骤就是要获取状态信息,由 IN 或 OUT 事务构成的传输,但是要注意这里的 IN 和 OUT 事务和之前的 INT 和 OUT 事务有两点不同:

1) 传输方向相反,通常 IN 表示设备往主机送数据,OUT 表示主机往设备送数据;在这里,IN 表示主机往设备送数据,而 OUT 表示设备往主机送数据,这是为了和可选数据步骤相结合;

2) 在这个步骤里,数据包阶段的数据包都是 0 长度的,即 SYNC+PID+CRC16。

原文始发于:USB 协议基本知识


柳叶扉鸿 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明USB协议基本知识
相关文章 相关文章 相关文章
喜欢 (0)