Linux下USBMASSSTORAGE驱动的分析笔记1.USBMASSSTORAGE协议分析SubClass协议名说明0x01ReducedBlockCommands(RBC)通常为FlashRom介质的存储设备使用0x028020i,MMC-2(ATAPI)通常为CD/DVD设备使用0x03QIC-157常用于磁带机设备0x04UFI常用于软磁盘设备(FDD)0x058070i常用于软磁盘设备或者其他设备0x06SCSI协议0x07-0xFF保留SubClass可以在usb设备连入系统后获取。不同的通讯协议决定了usb驱动要用不同的命令和数据包格式和u盘通讯。接口协议号协议名0x00Control/Bulk/Interrupt协议(CBI)带有commandcompletion中断0x01Control/Bulk/Interrupt协议(CBI)不带有commandcompletion中断0x50Bulk-Only协议0x02-0x4F保留0x51-0xFF保留接口协议号即InterfaceProtocol字段,在usb设备插入后可以从总线上获取。在实际usbmassstorage设备工作时,设备驱动首先要做的是获得该u盘的通讯协议和通讯方式,然后按照需要产生与目标设备兼容的控制命令,并将该控制命令打包通过设备的通讯传输方式发送至设备,完成一次对设备的读写操作。对于上述6中数据通讯协议,均有很详细的说明文档,经过分析,他们的命令有很大的相似之处,这也是通讯usb驱动能够实现的原因之一。2.自带驱动usb-storage的简要原理分析linux内核中自带的usbmassstorage驱动位于内核源代码目录kernel/drivers/usb/storage/下,下表为该目录下各文件的功能说明:文件功能说明usb.c/.hUsb-storage的核心文件,是整个驱动的框架代码transport.c/.h实现了对于不同通讯方式的支持函数scsiglue.c/.hScsi设备的模拟函数protocol.c/.h实现了对于几种通讯协议的SCSI命令翻译函数initializers.c/.h对于某些设备的专用初始化函数unusual_devs.h对于非常规设备ProductID和VendorID的支持shuttle_usbat.c/.h支持SCMMicrosystems设备的驱动sddr55.c/.hSanDiskSDDR-55SmartMediareader的驱动sddr09.c/.hanDiskSDDR-09SmartMediareader的驱动onetouch.c/.hMaxtorOneTouchUSBharddrive驱动支持libusual.c对于常规设备的ProductID和VendorID的支持karma.c/.hRioKarma设备驱动jumpshot.c/.hLexarJumpshotCompactFlashreader驱动isd200.c/.hISD200专属通讯协议支持freecom.c/.hFreecomUSB/IDE转化器支持dpcm.c/.hDPCM-USBCompactFlash/SmartMediareader设备支持debug.c/.h用于调试的工具函数datafab.c/.hDatafabUSBCompactFlashreader驱动支持alauda.c/.hAlauda-basedcardreaders驱动支持通过上述文件作用分析后,可以看出,对于常规的usb设备,大部分代码文件都是多余的,核心文件为上表的前4项。这就为进一步分析驱动已经对其进行简化和仿制提供了可能。通过对核心代码的分析,本驱动的工作机理是将自身模拟为标准的SCSI设备,并向scsi管理器注册,这样对于上层系统而言,只需操作标准的SCSI设备即可。这样可以简化具体的文件读写功能。同时驱动接受到的SCSI命令转化为对应u盘设备的通讯协议,并用对应设备的通讯方式进行发送,并将结果回馈到SCSI管理器。下图展示了整个驱动的工作布局:图中Transferlayer和protocollayer分别对应了transfer.c和protocol.c文件,CommandTransferThread是usb.c在探测到有新设备接入后加载的线程,他将不断轮询SCSI发来的消息命令,并负责将这些命令通过protocollayer提供的函数翻译并发送到u盘上,完成对u盘的读写操作。DelayedDeviceScan是为了防止用户在设备插入后马上拔除,造成驱动在后续通讯中造成混乱。实现方式是创建一个专门线程。同时,usb.c在设备插入时会通过scsiglue.c提供的SCSI接口函数向SCSI管理器注册自身。3.usb-storage的传输协议MassStorage类支持两种传输协议:1、Bulk-Only传输(BOT)2、Control/Bulk/Interrupt传输(CBI)MassStorage类规范定义了两个类规定的请求。Get_Max_Lun和MassStroageReset,所有的MassStorage设备都必须支持这两个请求。MassStorageReset(bmRequestType=00100001bandbRequest=11111111b)用来复位MassStorage设备及相关接口。Get_Max_Lun(bmRequestType=00100001bandbRequest=11111110b)用来确认设备支持的逻辑单元数。MaxLun的值必须是0—15。注意Lun必须是从0开始的。主机不能向不存在的Lun发送CBW。支持BOT传输的MassStorage设备接口描述符要求如下:接口类代码bInterfaceClass=08h,表示为MassStorage设备。接口类子代码bInterfaceProtocol有3种:0x00,0x01,0x50,前两种使用中断传输,最后一种使用批量传输(BOT)。支持BOT的设备必须支持最少3个endpoint:Control,Bulk-in,Bulk-out。USB2.0的规范定义了控制端点0。Bulk-in端点用来从设备向主机传送数据,Bulk-out端点用来从主机向设备传送数据。Bulk-Only传输(BOT)像控制传输一样,Bot也是由command阶段,可选的数据阶段和状态阶段组成。所有的Command命令都有可能没有Data阶段。下图说明了BOT的Command传输,Data-in,Data-out传输及Status传输。Bulk-only传输示意图CBW是由31个字节组成的短包。CWB和后续的数据以及CSW都是从新封装包开始的。要注意的是所有的CBW传输都是little-endian模式。在CBW中,dCBWsignature必须是“43425355h”,表示是CBW封装包。dCBWTag是CB标签,会通过对应的CSW反馈回来。在CSW中,dCSWSignature必须是“53425355h”,表示是CSW封装包。