USB bulk设备中的CBW和CSW

时间:2024-05-23 18:42:12

网上关于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),必须要实现下面这些功能:

  1. 检测和响应通用的USB Request和USB总线上的事件。
  2. 检测和响应来自USB设备的关于信息或者动作的USB Mass Storage Request。
  3. 检测和响应,从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 bulk设备中的CBW和CSW

        USB协议能够在启动或是当设备插入系统时对设备进行配置,这就是USB设备为什么可以执插拨的原因。USB协议能够在启动或是当设备插入系统时对设备进行配置,这就是USB设备为什么可以执插拨的原因。

        按照上面的描述,对于PC端烧写工具而言,板子上的存储设备就相当于只是一个SCSI设备。它只负责按照USB协议封装USB传输所需要的数据。

        
      在windows编程的时候,只需要按照要求发送SCSI命令操作就能够通过驱动完成对目标机上存储介质的操作。而这个过程是如何进行操作的呢?
      了解USB之后,会知道USB的描述符机制,在每个设备的描述符中,都存在如下几个域:
           bInterfaceClass
           bInterfaceSubClass
           bInterfaceProtocol
       分别对应着USB的Class,Subclass.protocol。

   bInterfaceClass=0x08=Mass Storage

          Class就是USB Mass Storage Class

  bInterfaceSubClass=0x06=SCSI Transparent

        Subclass,所支持的列表如下

   SubClass Codes Mapped to Command Block Specifications

USB bulk设备中的CBW和CSW

bInterfaceProtocol=0x50=Bulk Only Transport

Protocol,所支持的列表如下:Mass Storage Transport Protocol



USB bulk设备中的CBW和CSW

           从上面的描述中,就能够更清晰直观的感受到,设备的两种协议在工作方式上的协作与独立性。


下面这幅图片就是CBW包的各个字段信息。他是一个31B的包,这个是在USB仿真器抓包之后进行分析的依据。

USB bulk设备中的CBW和CSW

  • 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指令的状态返回,它指示了上一条指令执行是否成功,具体定义如下:

USB bulk设备中的CBW和CSW

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