USB Mass Storage

UMS_001

Bulk-only是USB设备端,此处的U盘和USB Host端,即普通PC,之间信息交换的协议。
Bulk Only Transport,也被简称为BOT。

 

USB MSC的CBI,是Control/Bulk/Interrupt的简写,但是其具体含义是:
1. Control
Control端点用于,除了传送标准的USB请求之外,还用于通过Class-specific的请求,
将命令块(command block)传给设备;即Control端点传送命令块
2. Bulk
Bulk In和Bulk Out端点用于在主机(Host)和设备(Device)之间数据的传输。
即Bulk用于传送数据
3. Interrupt
Interrupt端点用于(设备向主机)通知命令完成。即Interrupt用于传送状态信息
因此,上面的USB MSC的Control/Bulk/Interrupt,才被简称为CBI。
和CBI中的用三种不同的端点来传送三种类型的信息,而不同的是,
Bulk-only传送这些全部的信息,都之用Bulk端点。
即用Bulk端点来传送命令块,数据,状态,因此,
才类似于Control/Bulk/Interrupt被简称为CBI一样,而Bulk/Bulk/Bulk被简称为BBB。

 

USB MSC传输协议分CBI和BOT,而BOT又称为BBB。

 

UFI,即Universal Floppy Interface,是基于SCSI-2 和SFF-8070i命令集合的

 

如果你想要实现让操作系统从你的这个MSC设备启动,
那么你就要实现对应的CDB(Command Descriptor Block,命令描述符块)或者Data数据。

 

“Lockable Storage Devices Feature Specification”,简称为 LSD FS。

 

USB MSC USB Attached SCSI Protocol (UASP),为了克服旧的BOT协议的总线利用率不高的缺点,所以定义了新的UAS协议,即UASP,来提升USB的传输效率,提升USB速度。

UMS_002

①USB Mass Storage Class Control/Bulk/Interrupt (CBI) Transport
②USB Mass Storage Class Bulk-Only (BBB) Transport
③USB Mass Storage Class Universal Floppy Interface (UFI) Command Specification
④USB Mass Storage Class Bootability Specification
⑤USB Mass Storage Class Compliance Test Specification
⑥USB Lockable Storage Devices Feature Specification (LSD FS)
⑦USB Mass Storage Class USB Attached SCSI Protocol (UASP)

 

bInterfaceClass=0x08=Mass Storage
bInterfaceSubClass=0x06=SCSI Transparent
bInterfaceProtocol=0x50=Bulk Only Transport

UMS_003

UMS_004

UMS_005

Mass Storage设备所使用的SCSI命令集
0x00    TestUnitReady
0x03    RequestSense
0x12    Inquiry
0x1A    ModeSense6
0x1B    StartStop
0x1E    MediumRemoval
0x23    ReadFormatCapacity
0x25    ReadCapacity
0x28    Read(10)
0x2A    Write(10)
0x2F    Verify
0x5A    ModeSense10

 

– 主机首先发出Inquiry命令,响应了Inquiry之后就可以看到盘符.

 

– Inquiry之后会发出ReadFormatCapacity命令,这个命令在SCSI规范中是“厂家自定义命令”,
可以参考UFI命令集文档(实际上,U盘所使用的所有SCSI命令集都可以参考UFI文档,它比SCSI标准文档更简洁明了)。
注意这个命令在BusHound里是没有描述的,必须在“Device”选项页里勾选上
这个U盘所对应的USB Mass Storage Device这个节点,才能看到这个命令的数据流。
– ReadFormatCapacity之后会发出ReadCapacity命令。
ReadCapacity完成后就会发送Read(10)读取U盘的第一个扇区。

 

– U盘读数据(读扇区)时会发送Read(10)。
– U盘写数据时(写扇区)会发送Write(10)。

 

– TestUnitReady会在无其他数据传输时会定时发送,如果设备没有回应成功的CSW给主机,
则主机认为设备已不存在。此时如果再双击磁盘图标,Windows会提示“请插入磁盘”。

 

– Verify在写数据时有用,表示核实数据,一般直接返回成功的CSW就可以了。
一般来说,数据校验的工作在接收和向介质写数据时就已经顺带做了,
如果发现错误,则直接告诉主机那次的数据传输有误,不会等到主机Verify时。
当然,这不是一个必然的方案。

 

– RequestSense:如果CSW指示此次传输不成功,那么主机会发出此请求。

 

– StartStop暂时未发现大用处,一般直接返回成功的CSW。

 

– MediumRemoval在U盘被Eject的时候有用,处理不正确会Windows会弹出错误信息。

 

– ModeSense6/ModeSense10 这两个命令可以不支持
(不支持不代表不反应,任何一个命令你都要做出反应,对于不支持的命令,可以通过STALL握手来向主机表明),
暂时也未遇到过什么异常情况,而且我查看过一些U盘,有相当一部分就是随便回了几个数据给主机。
这两个命令只会在U盘插入后发送一次,此后不再发送。

 

第一,主机首先会发出一系列标准请求。
第二,在标准请求完成之后,会发出两个类请求:
Bulk-Only Mass Storage Reset请求和
Get Max LUN请求。

 

Bulk-Only Mass Storage Reset没有数据阶段,
只在状态阶段告诉主机设备的Reset过程完成与否。
如果在状态阶段返回ACK,那么主机就认为设备已经Reset完毕并准备好接收CBW了。

 

Get Max LUN要求设备返回一个字节的数据给主机,以表明此USB设备有多少个逻辑设备。
返回的这个数据就是最大的设备逻辑号(Logic Unit Number),
范围是0到15。例如,如果返回2,那么代表有0、1、2三个逻辑设备。

 

USB Mass Storage设备的Bulk数据交换流程

 

通过bulk端点进行的数据传输,都遵循这样一个过程,即三个阶段:

 

CBW->DATA->CSW

 

CBW是一个数据块,携带主机发给设备的SCSI命令。
接收了CBW后,设备就可以从中知道在接下来的DATA阶段中该干什么。

 

DATA阶段有三种情况:
无数据需要传输,
IN传输(设备到主机)或
OUT传输(主机到设备)。

 

CSW阶段反馈这次传输的结果给主机。

 

– CBW[12](CBW数据块的第13个字节)指明了传输方向,CBW[8-11]指明了传输的数据长度。
– CSW[12](CSW数据块的第13个字节)这个字节很重要,它为0则表示此次传输成功,非0就是不成功。

 

Bulk-Only 传输协议 (详细的规范请阅读《Universal Serial BusMass Storage ClassBulk-Only Transport》)

 

USB 设备所执行的操作可用下图描述:

UMS_006

CBW的格式如下:

UMS_007

dCBWSignature: CBW的标识,固定值:43425355h (little endian)。
dCBWTag: 主机发送的一个命令块标识,设备需要原样作为dCSWTag(CSW中的一部分)
再发送给Host;主要用于关联CSW到对应的CBW。
dCBWDataTransferLength: 本次CBW命令要求在命令与回应之间传输的字节数。如果为0,则不传输数据。
bmCBWFlags: 反映数据传输的方向,0 表示来自Host,1 表示发至Host;
bCBWLUN: 对于有多个LUN逻辑单元的设备,用来选择具体目标。如果没有多个LUN,则写0。
bCBWCBLength: 命令的长度,范围在0~16.
CBWCB: 传输的具体命令,符合bInterfaceSubClass.中定义的命令规范,此处是SCSI
CSW命令格式如下:

UMS_008

dCSWSignature: CSW的标识,固定值:53425355h (little endian)
dCSWTag: 设置这个标识和CBW中的dCBWTag一致,参照上面关于dCBWTag的解释
dCSWDataResidue: 还需要传送的数据,此数据根据dCBWDataTransferLength-本次已经传送的数据得到
bCSWStatus: 指示命令的执行状态。如果命令正确执行,bCSWStatus 返回0 即可。

 

发表评论