网上关于USB的讲解很多,讲的好的大家可以参见《Linux那些事儿之我是USB》,非常具有趣味性。此处恕我才疏学浅只能记录一些皮毛。因为在做烧写工具,所以涉及到这部分的知识。在之前的经验教训中明白了一个道理:对待工作要严谨认真,对待知识不能浅尝辄止。
在学习一个新知识的时候,最难的就是有人能用最简单的文字描述它。而通常的概述也会因为太晦涩而难懂。当然也不可能有哪项技术能够用简单的几句话来描述清楚。因此要有耐心,在理论看到一定程度之后一定要转入实践,最后再回归到理论。
在做烧写工具的时候,最简单的模型就是window PC通过数据线将数据传输到存储介质上。其中用到了USB Mass Storage协议,完成命令和数据的传输。而SCSI是存储介质遵循的协议。亦即:
⑴Host和Device间数据通讯协议是Bulk-only Transport。也称为BBB协议,这是与CBI对应的一种说法。因为CBI是指Commond、Bulk和Interrupt。而对于Bulk-only所有的传输都是通过BULK EP完成。
⑵USB Device内部和数据存储介质之间通信协议为SCSI(Small Computer System Interface)。
USB 设备中的固件(firmware)或者硬件(hardware),必须要实现下面这些功能:
- 检测和响应通用的USB Request和USB总线上的事件。
- 检测和响应来自USB设备的关于信息或者动作的USB Mass Storage Request。
- 检测和响应,从USB Transfer中获得的SCSI Command。这些业界标准的命令,是用来获得状态信息,控制设备操作,向存储介质块中读取(read block)和写入(write block)数据的。
另外,设备如果想要向存储介质中,创建/读取/写入,文件/文件夹的话,那么就涉及到文件系统,还要实现对应的文件系统。嵌入式系统中常见的文件系统有FAT16或FAT32。
在平板电脑设备的烧写过程中,平板电脑的ROM中存在USB的驱动程序,并且在USB的驱动中注册了SCSI设备的初始化函数。当SCSI命令通过USB协议传送到目标板上之后,会通过对USB数据包的解析完成对存储介质的读写擦除等的操作。
Microsoft Windows 中提供对Mass Storage 协议的支持,因此USB 移动设备只需要遵循 Mass Storage 协议来组织数据和处理命令,即可实现与PC 机交换数据。而Flash 的存储单元组织形式采用FAT16 文件系统,这样,就可以直接在Windows的浏览器中通过可移动磁盘来交换数据了,Windows 负责对FAT16 文件系统的管理,USB 设备不需要干预FAT16 文件系统操作的具体细节。
USB(Host)唯一通过描述符了解设备的有关信息,根据这些信息,建立起通信,在这 些描述符中,规定了设备所使用的协议、端点情况等。因此,正确地提供描述符,是USB 设备正常工作的先决条件。
按照上面的描述,在存储设备工作的过程中,USB的协议就成了关注的焦点。而在USB通信的过程中最重要的两个概念就是CBW和CSW。
设备插入到USB后,USB即对设备进行搜索,并要求设备提供相应的描述符。在USB Host得到上述描述符后,即完成了设备的配置,识别出为Bulk-Only的Mass Storage设备,然后即进入Bulk-Only传输方式。在此方式下,USB与设备间的所有数据均通过Bulk-In和Bulk-Out来进行传输,不再通过控制端点传输任何数据。
在这种传输方式下,有三种类型的数据在USB和设备之间传送,CBW、CSW和普通数据。CBW(Command Block Wrapper,即命令块包)是从USB Host发送到设备的命令,命令格式遵从接口中的bInterfaceSubClass所指定的命令块,这里为SCSI传输命令集。USB设备需要将SCSI命令从CBW中提取出来,执行相应的命令,完成以后,向Host发出反映当前命令执行状态的CSW(Command Status Wrapper),Host根据CSW来决定是否继续发送下一个CBW或是数据。Host要求USB设备执行的命令可能为发送数据,则此时需要将特定数据传送出去,完毕后发出CSW,以使Host进行下一步的操作。USB设备所执行的操作可用下图描述:
USB协议能够在启动或是当设备插入系统时对设备进行配置,这就是USB设备为什么可以执插拨的原因。USB协议能够在启动或是当设备插入系统时对设备进行配置,这就是USB设备为什么可以执插拨的原因。
按照上面的描述,对于PC端烧写工具而言,板子上的存储设备就相当于只是一个SCSI设备。它只负责按照USB协议封装USB传输所需要的数据。
Class就是USB Mass Storage Class
bInterfaceSubClass=0x06=SCSI Transparent
Subclass,所支持的列表如下
SubClass Codes Mapped to Command Block Specifications
从上面的描述中,就能够更清晰直观的感受到,设备的两种协议在工作方式上的协作与独立性。
下面这幅图片就是CBW包的各个字段信息。他是一个31B的包,这个是在USB仿真器抓包之后进行分析的依据。
-
dCBWSignature:
CBW的标识,固定值:43425355h (little endian)。 -
dCBWTag:
主机发送的一个命令块标识,设备需要原样作为dCSWTag(CSW中的一部分)再发送给Host;主要用于关联CSW到对应的CBW。 -
dCBWDataTransferLength:
本次CBW命令要求在命令与回应之间传输的字节数。如果为0,则不传输数据。 -
bmCBWFlags:
反映数据传输的方向,0x00 表示来自Host,0x80 表示发至Host; -
bCBWLUN:
对于有多个LUN逻辑单元的设备,用来选择具体目标。如果没有多个LUN,则写0。 -
bCBWCBLength:
命令的长度,范围在0~16. -
CBWCB:
传输的具体命令,符合bInterfaceSubClass.中定义的命令规范,此处是SCSI指令集
CSW(Command Status Wrapper)状态格式
CSW的长度为13个字节,是对应CBW指令的状态返回,它指示了上一条指令执行是否成功,具体定义如下:
-
dCSWSignature:
CSW的标识,固定值:53425355h (little endian) -
dCSWTag:
设置这个标识和CBW中的dCBWTag一致,参照上面关于dCBWTag的解释 -
dCSWDataResidue:
还需要传送的数据,此数据根据dCBWDataTransferLength-本次已经传送的数据得到 -
bCSWStatus:
指示命令的执行状态。如果命令正确执行,bCSWStatus 返回0 ,不正确返回1,phase错返回2(当HOST收到此错误时需要对Device复位) -