分类: LINUX
2010-01-04 15:20:41
这一节主要把在实现“linux模拟U盘功能”过程中的一些调试过程记录下来,并加以解析。
一、背景知识
1、USB Mass Storage类规范概述
USB 组织在universal Serial Bus Mass Storage Class Spaceification 1.1版本中定义了海量存储设备类(Mass Storage Class)的规范,这个类规范包括四个
独立的子类规范,即:
1. USB Mass Storage Class Control/Bulk/Interrupt (CBI) Transport
2.USB Mass Storage Class Bulk-Only Transport
3.USB Mass Storage Class ATA Command Block
4.USB Mass Storage Class UFI Command Specification
前两个子规范定义了数据/命令/状态在USB 上的传输方法。Bulk- Only 传输规范仅仅使用Bulk 端点传送数据/命令/状态,CBI 传输规范则使用Control/Bulk/Interrupt 三种类型的端点进行数据/命令/状态传送。后两个子规范则定义了存储介质的操作命令。ATA 命令规范用于硬盘,UFI 命令规范是针对USB 移动存储。
Microsoft Windows 中提供对Mass Storage 协议的支持,因此USB 移动设备只需要遵循 Mass Storage 协议来组织数据和处理命令,即可实现与PC 机交换数据。而Flash 的存储单元组织形式采用FAT16 文件系统,这样,就可以直接在Windows的浏览器中通过可移动磁盘来交换数据了,Windows 负责对FAT16 文件系统的管理,USB 设备不需要干预FAT16 文件系统操作的具体细节。
USB(Host)唯一通过描述符了解设备的有关信息,根据这些信息,建立起通信,在这 些描述符中,规定了设备所使用的协议、端点情况等。因此,正确地提供描述符,是USB 设备正常工作的先决条件。
Linux-2.6.26内核中在利用USB gadget驱动实现模拟U盘时主要涉及到file_storage.c、s3c2410_udc.c等驱动文件(这些文件的具体结构,将在下一篇文章中描述)。此时我们想先从这些代码中找到USB描述描述符,从中确定使用的存储类规范,从而确定协议。确定通讯协议是我们调试的基础。
存储类规范是由接口描述符决定的。接口描述符各项的定义义如下:
其中,bInterfaceClass、bInterfaceSubClass、bInterfaceProtocol可以判断出设备是否是存储类,以及属于哪种存储子类和存储介质的操作命令。
在file_storage.c文件中,
/* USB protocol value = the transport method */
#define USB_PR_CBI 0x00 // Control/Bulk/Interrupt
#define USB_PR_CB 0x01 // Control/Bulk w/o interrupt
#define USB_PR_BULK 0x50 // Bulk-only
/* USB subclass value = the protocol encapsulation */
#define USB_SC_RBC 0x01 // Reduced Block Commands (flash)
#define USB_SC_8020 0x02 // SFF-8020i, MMC-2, ATAPI (CD-ROM)
#define USB_SC_QIC 0x03 // QIC-157 (tape)
#define USB_SC_UFI 0x04 // UFI (floppy)
#define USB_SC_8070 0x05 // SFF-8070i (removable)
#define USB_SC_SCSI 0x06 // Transparent SCSI
默认的情况是:
mod_data = { // Default values
.transport_parm = "BBB",
.protocol_parm = "SCSI",
……
默认的赋值如下:
bInterfaceClass=08 表示:存储类
bInterfaceSubClass=0x06 表示:透明的SCSI指令
bInterfaceProtocol=0x50 表示:bulk-only 传输
2、Bulk-Only 传输协议
下面看看Bulk-Only 传输协议:(详细的规范请阅读《Universal Serial BusMass Storage ClassBulk-Only Transport》)
设备插入到USB 后,USB 即对设备进行搜索,并要求设备提供相应的描述符。在USBHost 得到上述描述符后,即完成了设备的配置,识别出为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 设备所执行的操
作可用下图描述:
CBW的格式如下:
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命令格式如下:
dCSWSignature:
CSW的标识,固定值:53425355h (little endian)
dCSWTag:
设置这个标识和CBW中的dCBWTag一致,参照上面关于dCBWTag的解释
dCSWDataResidue:
还需要传送的数据,此数据根据dCBWDataTransferLength-本次已经传送的数据得到
bCSWStatus:
指示命令的执行状态。如果命令正确执行,bCSWStatus 返回0 即可。
3、SCSI指令集
Bulk-Only 的CBW 中的CBWCB 中的内容即为如下格式的命令块描述符(Command Block Descriptor)。SCSI-2 有三种字长的命令,6 字节、10字节和12字节,Microsoft Windows 环境下支持12 字节长的命令。
Operation Code:
操作代码,表示特定的命令。高3 位为Group Code,共有8 种组合,
即8 个组,低5 五位为Command Code,可以有32 种命令。
Logicol unit Number: