USB定义以及硬件原理这里不做过多描述,可以直接网络搜索到很多专业的介绍和描述,本文直接进行其他主要知识点的整理和记录。
USB 采用轮询的广播机制传输数据,所有的传输都由主机发起,任何时刻整个 USB 体系内仅允许一个数据包的传输,即不同物理传输线上看到的数据包都是同一被广播的数据 包。
USB 采用“令牌包”-“数据包”-“握手包”的传输机制,在令牌包中指定数据包去向或者来源的设备地址和端点(Endpoint),从而保证了只有一个设备对被广播的数据包/令牌包作出响应,“握手包”表示了传输的成功与否。
USB 设备连接到 HOST 时,HOST 必须通过默认的控制管道对其进行枚举,完成获得其设备描述、进行地址分配、获得其配置描述、进行配置等操作方可正常使用。USB 设备的即插即用特性即依赖于此。
端点(Endpoint) 是 USB 设备中的可以进行数据收发的最小单元,支持单向或者双向的数据传输。设备支持端点的数量是有限制的,除默认端点外低速设备最多支持 2 组端点(2 输入,2 输出),高速和全速设备最多支持 15 组端点。
管道(Pipe) 是主机和设备端点之间数据传输的模型,共有两种类型的管道:无格式的流管道(Stream Pipe)和有格式的信息管道(Message Pipe)。任何 USB 设备一旦上电就存在一个信息管道,即默认的控制管道,USB 主机通过该管道来获取设备的描述、配置、状态,并对设备进行配置。
USB 设备连接到 HOST 时,HOST 必须通过默认的控制管道对其进行枚举,完成获得其设备描述、进行地址分配、获得其配置描述、进行配置等操作方可正常使用。USB 设备的即插即用特性即依赖于此。后续章节对枚举有更加详细介绍。
USB 设备通过管道和 HOST 通信,在默认控制管道上接受并处理以下三种类型的请求:
USB HUB 提供了一种低成本、低复杂度的 USB 接口扩展方法。HUB 的上行 PORT 面 HOST,下行 PORT 面向设备(HUB 或功能设备)。在下行 PORT 上,HUB 提供了设备连接检测和设备移除检测的能力,并给各下行 PORT 供电。HUB 可以单独使能各下行PORT,不同 PORT 可以工作在不同的速度等级(高速/全速/低速)。
HUB 由 HUB 重发器(HUB Repeater)、转发器(Transaction Translator)以及 HUB 控制器(HUB Controller)三部分组成。HUB Repeater 是上行 PORT 和下行 PORT 之间的一个协议控制的开关,它负责高速数据包的重生与分发。HUB 控制器负责和 HOST 的通信,HOST 通过 HUB 类请求和 HUB 控制器通讯,获得关于 HUB 本身和下行 PORT 的 HUB 描述符,进行 HUB 和下行 PORT 的监控和管理。转发器提供了从高速和全速/低速通讯的转换能力,通过 HUB 可以在高速 HOST 和全速/低速设备之间进行匹配。HUB 在硬件上支持Reset、Resume、Suspend。
USB HOST 在 USB 体系中负责设备连接/移除的检测、HOST 和设备之间控制流和数据流的管理、传输状态的收集、总线电源的供给。
USB规定了几种具有共同行为和协议的设备类,这样使编写通用设备的驱动程序更加容易。
在USB的设备类信息在USB的设备描述符,接口描述符,甚至接口关联描述符中都有所描述,这些描述符的字段一般包括bDeviceClass、bDeviceSubClass、bDeviceProtocol。
USB定义了类代码信息,用于识别设备的功能并基于该功能加载设备驱动程序。信息包含在三个字节中,分别是基类(BaseClass)、子类(SubClass)和协议(Protocol)。
在一个设备有两处描述符可以显示设备类代码信息。一个位置在设备描述符中,另一个在接口描述符中。
一些设备类型的类代码只允许在设备描述符中使用,一些设备类代码可以在设备和接口描述符中使用,而另一些类代码只能在接口描述符中使用。
一般的USB设备类型如下:
类代码 | 用法 | 描述 |
---|---|---|
00h | 设备描述符 | Use class information in the interface Descriptors |
01h | 接口描述符 | 音频 |
02h | 设备描述符、接口描述符 | 通讯设备,如电话,moden等等 |
03h | 接口描述符 | HID设备 |
05h | 接口描述符 | Physical |
06h | 接口描述符 | Image |
07h | 接口描述符 | 打印机 |
08h | 接口描述符 | 大容量存储 |
09h | 设备描述符 | Hub USB集线器 |
0Ah | 接口描述符 | CDC-Data |
0Bh | 接口描述符 | Smart Card |
0Bh | 接口描述符 | Content Security |
0Dh | 接口描述符 | Content Security |
0Eh | 接口描述符 | UVC视频/CAMERA |
0Fh | 接口描述符 | Personal Healthcare |
10h | 接口描述符 | 音视频设备 |
11h | 设备描述符 | Billboard Device Class |
12h | 接口描述符 | USB Type-C Bridge Class |
DCh | 设备描述符、接口描述符 | Diagnostic Device |
E0h | 接口描述符 | 无线控制器 |
EFh | 设备描述符、接口描述符 | Miscellaneous |
FEh | 接口描述符 | Application Specific |
FFh | 设备描述符、接口描述符 | 厂商用自定义 |
更加详细的可以参考USBIF官方的设备类型,以及内核代码./include/uapi/linux/usb/ch9.h
/*
* Device and/or Interface Class codes
* as found in bDeviceClass or bInterfaceClass
* and defined by www.usb.org documents
*/
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
#define USB_CLASS_AUDIO 1
#define USB_CLASS_COMM 2
#define USB_CLASS_HID 3
#define USB_CLASS_PHYSICAL 5
#define USB_CLASS_STILL_IMAGE 6
#define USB_CLASS_PRINTER 7
#define USB_CLASS_MASS_STORAGE 8
#define USB_CLASS_HUB 9
#define USB_CLASS_CDC_DATA 0x0a
#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
#define USB_CLASS_VIDEO 0x0e
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
#define USB_CLASS_MISC 0xef
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
#define USB_SUBCLASS_VENDOR_SPEC 0xff
USB 体系采用分层的星型拓扑来连接所有 USB 设备,塔顶为USB主控制器和根集线器(Root Hub),下面接USB集线器(Hub),集线器将一个USB口扩展为多个USB口,USB2.0规定集线器的层数最多为6层,理论上一个USB主控制器最多可接127个设备,因为协议规定USB设备具有一个7 bit的地址(取值范围为0~127,而地址0是保留给未初始化的设备使用的)。
ROOT HUB 是一个特殊的 USB HUB,它集成在主机控制器里,不占用地址。ROOT HUB 不但实现了普通 USB HUB 的功能,还包括其他一些功能,具体在增强型主机控制器的规范中有详细的介绍。
“复合设备(Compound Device)”可以占用多个地址。所谓复合设备其实就是把多个功能设备
通过内置的 USB HUB 组合而成的设备,比如带录音话筒的 USB 摄像头等。
USB采用差分信号传输,使用的是如上图所示的NRZI编码方式:数据为0时,电平翻转;数据为1时,电平不翻转。如果出现6个连续的数据1,则插入一个数据0,强制电平翻转,以便时钟同步。上面的一条线表示的是原始数据序列,下面的一条线表示的是经过NRZI编码后的数据序列。
USB总线上的传输数据是以包为基本单位的,包格式如上图所示。根据PID的不同,USB协议中规定的包类型有令牌包、数据包、握手包和特殊包等。
数据包:USB 总线上数据传输的最小单位,包括 SYNC、数据及 EOP 三个部分。其中数据的格式针对不同的包有不同的格式。但都以 8 位的 PID 开始。PID 指定了数据包的类型(共 16 种)。
令牌包 即指 PID 为 IN/OUT/SETUP 的包。
USB芯片(硬件)会完成CRC校验、位填充、PID识别、数据包切换、握手等协议处理。
USB为所有的USB外设提供了单一的、易于使用的标准的连接类型,这样一来就简化了USB外设的设。同时也简化了用户在判断哪个插头对应哪个插槽时的任务,实现了单一的数据通用接口。
整个的USB的系统只有一个端口和一个中断 节省了系统资源。
USB支持热插拔(hot plug)和 PNP(Plug-and-Play), 也就是说在不关闭PC的情况下可以安全的插上和断开USB设备。 计算机系统动态地检测外设的插拔,并且动态地加载驱动程序,其他普通的外围连接标准如SCSI设备等必须在关掉主机的情况下才能插拔外围设备。
USB在设备供电方面提供了灵活性。 USB直接连接到Hub或者是连接到Host的设备可以通过USB电缆供电,也可以通过电池或者其它的电力设备来供电或使用两种供电方式的组合.并且支持节约能源的挂机和唤醒模式。
USB提供全速12Mbps的速率和低速 1.5Mbps的速率来适应各种不同类型的外设USB2.0 还支持480Mbps的高速传输速率(USB3.0超高带也实现了对USB2.0及以下版本的兼容支持)。
为了适应各种不同类型外围设备的要求,USB提供了四种不同的数据传输类型。控制传输、批量传输、中断传输和同步传输。 同步数据传输可为音频和视频等实时设备的实时数据传输提供固定带宽。
USB的端口具有很灵活的扩展性, 一个 USB端口串接上一个USBHub就可以扩展为多个USB端口。
携带方便。USB设备大多以“小、轻、薄”见长,对用户来说,随身携带大量数据时,很方便。当然USB硬盘是首要之选了。
标准统一。大家常见的是IDE接口的硬盘,串口的鼠标键盘,并口的打印机扫描仪,可是有了USB之后,这些应用外设统统可以用同样的标准与个人电脑连接,这时就有了USB硬盘、USB鼠标、USB打印机等等。
可以连接多个设备。USB在个人电脑上往往具有多个接口,可以同时连接几个设备,如果接上一个有四个端口的USB HUB时,就可以再连上;四个USB设备,以此类推,尽可以连下去,将你家的设备都同时连在一台个人电脑上而不会有任何问题(注:最高可连接至127个设备)。
USB协议定义了设备的6种状态,仅在枚举过程种,设备就经历了4个状态的迁移:上电状态(Powered),默认状态(Default),地址状态(Address)和配置状态(Configured)(其他两种是连接状态和挂起状态(Suspend))
一旦有设备连接到主机,主机就会发送一系列Requests(请求)到设备所挂载的hub上面,hub收到请求之后,就会建立起一条连接Host(主机)和Device(设备)的通信通道,然后Host再以Controll Transfer(控制传输)的方式,通过端点0(Ep0)对设备发送各种请求,设备根据主机的请求回复对应的信息(这个过程称为枚举操作),因此,所有的USB设备都必须支持StandardRequests,ControlTransfer和Ep0,才能完成设备的枚举操作,即USB设备枚举一般会经过插入、供电、初始化、分配地址,配置,获取设备描述符、获取配置描述符、获取字符串描述符和配置设备这么几个过程,完成获得其设备描述、进行地址分配、获得其配置描述、进行配置等操作方可正常使用。USB 设备的即插即用特性即依赖于此。
枚举是 USB 体系中一个很重要的活动,由一系列标准请求组成(若设备属于某个子类,还包含该
子类定义的特殊请求)。通过枚举 HOST 可以获得设备的基本描述信息,如支持的 USB 版本、PID、VID、设备分类(Class)、供电方式、最大消耗电流、配置数量、各种类型端点的数量及传输能力(最大包长度)。HOST 根据 PID 和 VID 加载设备驱动程序,并对设备进行合适的配置。只有经过枚举的设备才能正常使用。对于总线供电设备,在枚举完成前最多可从总线获取 100mA 的电流。
USB主机检测到USB设备插入后,就要对设备进行枚举了。
枚举的作用就是从设备是那个读取一些信息,知道设备是什么样的设备,然后通信,这样主机就可以根据这些信息安装合适的驱动程序。
USB设备的枚举过程如下:
主机集线器检测到新设备
USB设备插入USB接口后,主机检测D+/D-线上的电压,确认有设备连接,USB集线器通过中断IN通道,向主机报告有USB设备连接,即连接了设备的 HUB 在 HOST 查询其状态改变端点时返回对应的 bitmap,告知HOST 某个PORT 状态发生了改变。
主机发送Get_Port_Status
请求
主机发送Get_Port_Status
(读端口状态)请求,以获取更多的信息。返回的消息告诉主机一个设备是什么时候连接的。
主机发送Set_Port_Feature
(写端口状态)请求,集线器重启端口
当主机知道有一个新的设备时,主机等待100ms等待设备稳定,然后发送集线器设备类请求Set_Port_Feature
(写端口状态),对USB设备进行复位并使能该PORT,主机发送另一个Get_Port_Status
请求,确定设备是否已经从复位状态退出。HUB 执行 PORT 复位操作后USB设备的地址为00h
,这样主机就可以使用地址00h
与USB设备进行通信,复位后的设备可以从USB总线上获取小于100mA的电流,用于使用默认地址对管道0控制事务响应。
集线器在设备和主机之间建立一个信号通路
主机向地址为0(即刚插入的USB设备)的设备端点0(默认端点)发送获取设备描述符( get_device_descriptor
)的标准请求来验证设备是否激起重启状态。返回的数据有一位表示设备仍然处于重启状态。当集线器释放了重启状态,设备就处于默认状态了,设备已经准备好通过Endpoint 0 的默认流程响应控制传输,即设备现在使用默认地址0x0与主机通信。
集线器检测设备速度
集线器通过测定哪根信号线(D+或D-)在空闲时有更高的电压来检测设备是低速设备还是全速设备。(全速和高速设备D+有上拉电阻,低速设备D-有上拉电阻),主机使用Chirp K信号来了解全速设备是否支持高速运行。
获取最大数据包长度
主机 向address 0发送USB协议规定的 get_device_descriptor
命令获取设备描述符,以取得缺省控制管道所支持的最大数据包长度,并在有限的时间内等待USB设备的响应。该长度包含在设备描述符的bMaxPacketSize0字段中,其地址偏移量为7,所以这时主机只需读取该描述符的前8个字节。USB设备收到请求后,将其预设的设备描述符返回给主机。主机收到设备描述符后,返回一个0长度的数据确认包。注意,主机一次只能枚举一个USB设备,所以同一时刻只能有一个USB设备使用缺省地址0。
主机分配一个新的地址给设备
机对地址为0的设备端点0发送一个设置地址(set_address
)请求(新的设备地址在数据包中)来分配一个唯一的地址给设备。设备读取这个请求,返回一个确认(0长度的状态数据包),并保存新的地址。主机收到状态数据包后,发送应答包ACK给设备,设备收到ACK后,启用新的设备地址。
主机重新发送 get_device_descriptor
命令读取完整设备描述符
主机再次使新的地址获取设备描述符( get_device_descriptor
),设备返回地址描述符,此次读取其设备描述符的全部字段,以了解该设备的总体信息,如VID,PID。主机获取第一次配置描述符有前18个字节,设备返回配置描述符的前18个字节,其数据包中含有配置描述符的总长度。
主机发送 get_device_descriptor
命令,获取完整配置信息
主机根据配置描述符的总长度向设备循环发送 get_device_descriptor
命令,要求USB设备回答,以读取全部配置信息,设备返回全总的配置描述符。
主机发送 get_device_descriptor
命令,获得字符描述符(unicode)
描述字符集包括了产商、产品描述、型号。
主机展示新设备信息
此时主机将会弹出窗口,展示发现新设备的信息,产商、产品描述、型号
主机判断能否提供该类USB的驱动
根据设备描述符和配置描述符应答,主机判断是否能够提供USB的Driver
主机发送set_configuration(X)
命令,请求为设备选择一个配置
加载了USB设备驱动以后,主机发送set_configuration(X)
命令请求为该设备选择一个合适的配置(x代表非0的配置值),设备此时处于配置状态。如果配置成功,USB设备进入“配置”状态,并可以和客户软件进行数据传输。如果是复合设备,主机为复合设备接口分配驱动程序。
过流状态检测
如果集线器检测到有过流现象,或者主机要求集线器关闭电源,则USB总线切断设备供电电源。在这种情况下,设备与主机无法通信,但设备处于连接状态。
挂起状态
如果在3毫秒内设备在总线上未见任何动作,则它将进入挂起状态,在挂起状态设备消耗的总线电能最少。
这时设备方可正常使用。
这是因为有些USB设备的端点0的最大包长度为8字节(USB规定端点0的最大包长至少有8字节长),而设备描述符有18个字节,所以第一次获取设备描述时如果要想获取全部的描述符需要多次获取,而实际上系统只是取前8字节的设备描述符,后续的数据是不再获取的,这样有可能获取的描述符是不完全的,而复位后是要获取设备描述符的全部18字节。
为什么USB规定端点0的最大包长至少有8字节长?
这是因为端点0最大包包长度刚好在设备描述符的第8字节处。
USB 设备的常用操作包括:设备连接、设备移除、设备配置、地址分配、数据传输、设备挂起、设备唤醒等。
USB 的请求包括标准请求、类请求以及厂商请求三类。所有的请求都通过默认管道发送,按照控制传输的三个阶段进行。首先HOST 通过一次控制事务传输向Device 发送一个8 字节的 Setup 包,这个包说明了请求的具体信息,如请求类型、数据传输方向、接收目标( Device/Interface/Endpoint 等)。具体定义参考USB2.0 Spec p248。USB 标准请求共包括 11 个请求,如清除特性(Clear_Feature )、 得到配置( Get_Configuration)、得到描述(Get_Descriptor)、设置地址(Set_Address)等。具体参考 USB 2.0 Spec p250
PC主机一般有一个根集线器,在主机启动时由根集线器所在的总线负责进行枚举根集线器。在我们的PC中,USB根控制器通常是一个PCI/E设备,所以由PCI/E总线枚举并发现的,并将USB根控制器的地址空间永久地映射在内存中(可通过设备管理器看到)。
USB根控制器一般包括根集线器功能和根控制器功能。
PC主机通过与USB根集线器对话,然后由根集线器报告连接在其集线器上的其它USB设备或集线器,其它集线器负责报告连接到其它集线器上的集线器和USB设备,直到发现所有的USB设备。
一个根集线器在windows中就是一个单独的USB总线,如果系统中有多个根集线器,就会有多个USB总线。
我们的pc中一般有2-3个根集线器,通常包括1个USB3.0根集线器和多个USB2.0根集线器。
USB设备从USB总线断开时,包括以下几个步骤:
如果断开的是一个USB集线器,USB主机会对该集线器和其所连接的所有设备进行断开操作。
枚举的过程用到总线的“控制传输(Control Transfer)”的传输方式。用于配置/命令/状态等情形,其中的设置操作setup和状态操作status过程的数据包具有USB协议定义的数据结构,控制传输只能通过消息管道进行。
机setup包(发往地址0端点0),主机数据包(请求设备描述符),设备握手包ack设备产生端点0 数据输出中断,固件程序要根据数据包中的主机要求做好准备,这里是在端点0输入缓冲区准备好设备描述符数据过程:主机发一个in令牌包,设备发一个数据包(这个数据已准备好,sie收到in令牌后直接到达总线),主机发送ack包。此时sie产生端点0数据输入中断,表明主机已取走设备所准备的数据,用户也可以在该中断处理程序中做自己的处理主机直接受一次数据,最少8字节,如果用户数据没发完,又在控制输入缓冲区准备了数据,主机也不理会状态过程:主机发out包(通知设备要输出),主机发0字节状态数据包(0字节表示自己没收到设备描述符),设备发握手包ack包此时设备不会产生端点0数据输出中断,此时没有数据
主机setup包(发送地址0端点0),主机数据包(请求设置地址),设备握手包ack包。Setup包后跟一个主机setup包的目的数据包(get/set)。
设备产生端点0数据输出中断,固件程序要根据数据包中主机的要求做好准备,根据主机发来的地址写入自己的地址控制寄存器
数据过程:本次传输无数据
状态过程:主机发in包(通知设备要返回数据),设备发0字节状态数据(表明地址设置已成功),主机发握手ack包(地址设置已生效)
此时设备不会产生端点0数据输入中断,此时无数据
主机setup包(发往新地址端点0),主机数据包(请求设备描述符),设备握手ack包设备产生端点0数据输出中断,固件程序要根据数据包中主机要求做好准备,在端点0输入缓冲区准备好描述符数据过程:主机发一个in令牌包,设备发一个数据包(这个数据已经准备好,sie收到in令牌后,直接送到总线上),主机发ack包此时sie产生端点0数据输入中断,表明主机已取走设备所准备的数据用户可以在中断处理程序中做如下处理(如果一次没有把描述送完,要再次将剩下的内容填充端点0输入缓冲区区)
主机接着再发个in令牌包,设备发一个数据包,主机发ack包
此时sie再次产生端点0数据输入中断,如果数据已发完,不需处理
状态过程:主机发送out包(通知设备要输出),主机发0字节状态数据包(表明已收到设备描述符),设备发握手ack包
USB设备枚举是USB主机检测设备是否存在,并执行一系列的操作以确保将设备端点添加到主机服务端点列表的过程。
新的全速、高速或低速设备的存在可通过 D- 或 D+ 信号的变化来识别。低速设备将 5 V 置于 D- 上,高速和全速设备将 5 V 置于 D+ 上。连接信号由集线器检测并报告给主机。一旦检测到设备,主机就会向设备发出RESET 命令。
当接收到 RESET 控制信号序列时,设备将根据规范管理其负载以进行枚举。如果连接的设备是高速设备,将返回“chirp”,完成高速检测过程。一旦速度确定,主机读取设备描述符并分配地址。
设置地址后,主机读取设备的所有剩余描述符表。如果主机确定它可以为设备的接口端点提供服务并提供足够的电力,则主机会发出一个命令,通知设备要激活其哪些配置。
在收到主机关于激活哪个配置的通知后,设备就可以使用活动配置运行了。
针对不同的数据传输场景,USB分为四种数据传输模式,这四种传输模式分别由不同的包(packet)组成,并且有不同的数据处理策略。
控制传输是一种特殊的传输方式。当USB设备初次连接主机时,用控制传输传送控制命令等对设备进行配置。同时设备接入主机时,需要通过控制传输去获取USB设备的描述符以及对设备进行识别,在设备的枚举过程中都是使用控制传输进行数据交换 ,也可以理解为:主要用于在设备连接时对设备进行枚举以及其他因设备而已的特定操作。
一次控制传输分为三(或两)个阶段:
建立阶段是由建立传输事务(Setup Transaction)实现的,状态阶段和数据阶段是由数据输出(Data Out Transaction)或输入事务(Data IN Transaction)实现的(如果数据太多,将会采用多次数据输入或输出事务)。
下图为整个控制传输的示意图:
(SETUP(0)由三个包组成:SETUP Packet 、DATA0 Packet、ACK Packet;
OUT(1)由三个包组成:OUT Packet 、DATA1 Packet、ACK Packet;
IN(1)由三个包组成:IN Packet 、DATA0 Packet、ACK Packet 。这里的 SETUP 、DATA0 、ACK 、OUT 、IN是PID)
注意:设备不能返回NAK或STALL,即设备必须接收建立事务的数据。建立过程是建立事务,建立事务是通过SETUP令牌包,其次是DATA0数据包,最后是握手包,设备只能使用ACK来应答(或者由于出错不应答),而不能使用NAK或者STALL来应答,即设备必须接收建立事务的数据。
下图为建立阶段的事务传输流程图。可以看出: 与批量传输相比,在流程上并没有多大区别,区别只在于该事务传输发生的端点不一样、支持的最大包长度不一样、优先级不一样等这样一些对用户来说透明的东西。
建立阶段过后,可能会有数据阶段,这个阶段将会通过一次或多次控制传输事务,完成数据的传输。一个数据过程可以不包括或包含多个数据事务,但所有数据事务必须是同一方向的,即在控制读传输中,数据过程中的数据事务都必须是输入的,在控制写传输过程中,数据过程中的事务都必须是输出。若数据方向发生了改变,则认为进入状态过程。数据过程的第一个数据包必须为DATA1,然后每次正确传输一个数据包后就在DATA0和DATA1之间交替。
最后是状态阶段,,通过一次方向与前一次相反的控制事务传输来表明传输的成功与否。如果成功会返回一个长度为 0 的数据包,否则返回 NAK 或STALL。状态过程只使用DATA1包,并且传输方向与数据过程相反,即控制写输出在状态过程中使用一个批量输入事务,控制读输入在状态过程中使用一个批量输出事务。
状态过程是要返回数据传输的成功与否,具体也需要看控制传输的类型。需要注意的是,状态信息的数据传输方向与数据阶段方向相反。其实我们来思考下,主机给设备把一推数据发送完毕了(OUT事务),主机肯定要请求一个IN事务,让设备把自己的接收情况发给主机,你设备要给我说你在本轮接收数据有没有问题,同样的,设备把数据发送给主机(IN事务),主机肯定要发起一个OUT事务请求,告诉设备主机的接收情况,告诉设备本轮接收数据有没有问题。
一个事务又是由各种包组成的。包又分为四大类包:Token(令牌)Packet、Data(数据) Packet、 Handshake(握手)Packet、特殊 Packet。每类包中又分为各种具体的包(由PID(Packet ID)确定该包属于哪一种包)。需要注意的是 包是 USB 传输最小的传输单位、所有数据都必须进行打包才可以进行传输,包格式如下。
注意:返回NAK并不代表数据出错,只是说明设备暂时没有数据传输或暂时没有能力接收数据.当主机或设备检测到数据出错时(如CRC校验出错,PID校验出错,位填充出错等 )将什么也不返回。这时等待握手包的一方就会因为收不到握手包而等待超时。
在控制读传输时,该阶段则为OUT事务,其中的数据包固定为DATA1数据包。返回数据成功与否以有以下情况:
在控制写传输时,该阶段则为IN事务,其中的数据包固定为DATA1数据包。返回数据成功与否以有以下情况:
批量传输一般用于批量的和非实时的数据传输,通俗的来说就是用于数据量大但对时间要求又不高的场合的一种传输方式,类似用于USB打印机,U盘和USB扫描仪等等。
批量传输使用批量传输事务,一次批量传输事务分为三个阶段:令牌包阶段、数据包阶段、握手包阶段。
批量传输分为批量读和批量写,批量读使用批量输入事务,批量写使用批量输出事务。注意:不论输入还是输出都是以主机为参考的。
对于批量传输,如果启动批量传输,如果USB总线中有多余的总线带宽,批量传输会立即执行,但当带宽比较紧张时,批量传输会把带宽让给其它传输类型。所以批量传输的优先级相对其它传输优先级比较低。
高速的批量端点必须支持 PING 操作,向主机报告端点的状态,NYET 表示否 定应答,没有准备好接收下一个数据包,ACK 表示肯定应答,已经准备好接收下一个数据包。
图中一个方框表示一个 Packet,灰色的包表示主机发出的包,白色的包表示 Device 发出的包。批量传输是可靠的传输,需要握手包来表明传输的结果。若数据量比较大,将采用多次批量事务传输来完成全部数据的传输,传输过程中数据包的 PID 按照 DATA0-DATA1-DATA0-…的方式翻转,以保证发送端和接收端的同步。
USB 允许连续 3 次以下的传输错误,会重试该传输,若成功则将错误次数计数器清零,否则累加该计数器。超过三次后,HOST 认为该端点功能错误(STALL),放弃该端点的传输任务。一次批量传输(Transfer)由 1 次到多次批量事务传输(Transaction)组成。
翻转同步:发送端按照 DATA0-DATA1-DATA0-…的顺序发送数据包,只有成功的事务传输才会导致 PID 翻转,也就是说发送段只有在接收到 ACK 后才会翻转 PID,发送下一个数据包,否则会重试本次事务传输。同样,若在接收端发现接收到到的数据包不是按照此顺序 翻转的,比如连续收到两个DATA0,那么接收端认为第二个 DATA0 是前一个 DATA0 的重传。
批量功能端点必须传输数据字段小于或等于 1024 字节的数据负载。如果批量传输有比之更多的数据,在突发事务交易的所有数据的有效载荷必须为 1024 字节长度,除了突发的最后一个数据有效载荷,它可能包含剩余数据。
如果传输的数据量大于端点所支持的最大数据包长度,USB主控制器会把该数据按最大数据包长度分为多个批量数据包进行传输,最后一个批量传输长度可以小于或等于最大包长度。
批量传输数据流传输包括IN传输和OUT传输,分别对应于数据的读和写,其也分为3个阶段,分别为:
中断传输在流程上除不支持 PING 之外,其他的跟批量传输是一样的。他们之间的区别也仅在于事务传输发生的端点不一样、支持的最大包长度不一样、优先级 不一样等这样一些对用户来说透明的东西。
主机在排定中断传输任务时,会根据对应中断端点描述符中指定的查询间隔发起中断传输。中断传输有较高的优先级,仅次于同步传输。同样中断传输也采用 PID 翻转的机制来保证收发端数据同步。
中断传输的延迟有保证,也就是说,可以在有限的延迟中完成传输,并且支持错误重传(在下一个周期进行重传),所以它是可靠的。因为可能产生错误重传,所以中断传输也会采用 PID 翻转的机制保证收发端数据的同步。
中断传输一般用于对延迟要求比较严格,同时数据量较小和非连续的数据传输,通俗的来说就是用于数据量小的数据不连续的但实时性高的场合的一种传输方式,主要应用于人机交互设备(HID)中的USB鼠标和USB键盘等。
USB中断传输和我们传统意义上的中断不一样。它不是由设备主动地发起一个中断请求,主机响应再操作,而是由主机保证在不大于某个时间间隔内按排的一次传输,所以USB的中断实际意义是实时查询操作,即USB的中断传输是主机在一定的时间不断地主动轮询设备检查其是否有数据需要传输,若有则传输数据,否则 NAK ,主机对此有3个重要参数需要在端点描述符中进行配置:
中断端点需指定一个范围在1-255毫秒内的询查周期。主机保留足够的带宽以确保在指定频率上直接向中断端点发出IN或OUT事务。Microsoft的主控制器驱动程序把中断端点描述符中指定的循检周期简化为不大于32的2的幂。例如,一个指定循检周期为31毫秒的端点实际上是以16毫秒进行循检。指定周期在32-255毫秒之间的循检实际上是以32毫秒为循检周期。
对于中断传输,如果传输的数据长度大于端点支持的最大包长度,这时一个中断传输内会有多个事务。在传输数据时,如果最后一个事务的数据长度小于端点支持的最大包长度,则认为数据传输完成。
USB中断数据流传输包括IN传输和OUT传输,分别对应于数据的读和写,其也分为3个阶段,分别为:
中断传输和批量传输的结构基本一致,只是中断传输没有ping和nyet两种包。
下图为中断传输 的流程图。
这种传输是四大传输中唯一 不可靠的传输方式,但是好处就是可以保证带宽,并且没有延迟,而且因为是不可靠的传输,所以没有握手包,也不支持 PID 翻转,主机在安排这些传输事务时,同步传输拥有最高的优先级。
在现实中,这种传输用于摄像头、USB音响等,因为它们对实时性要求比较高,但是可以容忍错误(摄像头偶尔出现了一帧有错误的画面,没多大关系,因为下一帧画面马上就会传过来)。
USB总线上的情形是怎样的?包是 USB 总线是数据传输的最小单位,不能被打断或干扰,否则会引发错误。若干个数据包组成一次事务传输,一次事务传输也不能打断,属于一次事务传输的几个包必须连续,不能跨帧完成。一次传输由一次到多次事务传输构成,可以跨帧完成。
同步事务没有握手包。当一个同步传输中有多个事务时,最后一个事务之前的事务的数据长度必须是端点所支持的最大包长度。如果最后个事务的数据长度小于端点支持的最大包长度,则认为数据传输完成。对于全速模式的同步传输,USB设备或主机应可能接收DATA0和DATA1包,但只能发送DATA0包。
超高速等时传输的端点指定所需的最大数据包有效负载大小为1024字节(对于支持大于1的突发大小,可以是0到1024之间的任何大小,以实现同步突发大小等于1的终结点。等时传输突发大小应在 1 至 16 范围。但是,在相同的时间间隔内一个等时端点最多可以请求3个突发事务。参见超高速端点伴随描述符的bmAttributes和bMaxBurst字段。
Maximum number of packets = (bMaxBurst +1) x (Mult + 1) //Mult=bmAttributes:1.0
同步传输事务需要保证固定的时间段有固定的数据传输量,所以它允许有一定的误码率。
由于同步传输只关心数据的实时性,不关心的数据的正确性,故没有握手阶段,所以只有两个阶段:
USB 枚举/断开过程
USB 之枚举过程概述
带你遨游USB世界
USB 控制传输方式
USB设备的枚举过程分析
USB 之传输事务
Linux USB基础之虚拟串口枚举流程(三)
USB2.0官方协议规格书
USB2.0协议入门中文版