Chinaunix首页 | 论坛 | 博客
  • 博客访问: 38872
  • 博文数量: 34
  • 博客积分: 1773
  • 博客等级: 上尉
  • 技术积分: 360
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-10 16:40
文章分类
文章存档

2011年(5)

2010年(19)

2009年(10)

我的朋友

分类: 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:

......
 
更多内容请点击查看原文:
阅读(287) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~