一、USB协议介绍
1.1 USB拓扑结构
主从结构:所有的数据传输都由主机主动发起的,而设备只是被动地负责应答。
1.2 USB的包结构:
1.2.1 Packet、Transaction、Transfer的基本关系
USB总线上数据传输的基本单位是包(Packet),在USB上数据信息的一次接收或发送的处理过程称为事务处理(Transaction),在USB上数据信息完成一次传输的过程叫Transfer.
一个Transfer由一个或若干个Transaction组成,取决于此次传输的数据量。
一个Transanction由3个Packet组成(令牌包、数据包、握手包),唯一的例外是同步传输的过程中没有握手包。
每次传输的数据负载是在Transaction的数据包中
1.2.2 Packet包(USB总线上数据传输的基本单位)
Packet由SOP(包起始),SYNC(同步信号),Packet Content(包内容),EOP(包终止)组成
-
Token Packet: 包内容 PID + 地址 + CRC组成
其中ADDR和ENDP分别是设备地址和端点地址,示例如下:
- Data Packet: 包内容 PID + 数据 + CRC,示例如下:
- Handshake Packet: 包内容 只有PID
1.2.3 Transaction(USB总线上数据信息一次接收或发送的过程):
分类:
- Setup transaction: 主机用来向设备发送控制命令
- Data In transaction: 主机用来从设备读取数据
- Data Out transaction: 主机用来向设备发送数据
packet组成:
- Token packet: 总是由主机发出
- Data packet: 包含此次transaction的数据负载
- 可选的Handshake packet
1.2.4 Tansfers(USB上数据信息一次完整的传输过程):
传输类型:
- 控制传输 Control Transfer: (非周期性,突发)
- 用于命令和状态的传输
- 大容量数据传输 Bulk Transfers: (非周期性,突发)
- 大容量数据的通信,数据可以占用任意带宽
- 同步传输 Isochronous Transfers:
- 中断传输 Interrupt Transfers:
- 允许有限延迟的通信
- 允许有限延迟的通信
这是一个USB控制传输数据的示例,包括了3个transaction: 控制、输入、输出。
1.2 USB上电枚举过程
1.2.1 USB的枚举
USB设备上电后的初始化过程
1.2.2 USB的描述符
定义了USB设备类型、协议版本号、厂商ID、最大电流等信息
Device Descriptors(设备描述符):
Configuration Descriptors(配置描述符)
Interface Descriptors(接口描述符)
1.2.3 Bus Bound工具抓包分析
Phase中有CTL,IN,OUT,对应的是三种不同类型的Transaction
Data中显示的是Transaction的数据包的Data字段的内容
1.3 USB协议分类
协议缩写 | 协议全称 | 说明 |
---|---|---|
HID | Human Interface Device | USB接口的鼠标、键盘 |
MSC | Mass Storage Device | 大容量存储设备 |
CDC | Communications Device Class | 网络设备 |
Audio | Aduio | USB接口音频设备 |
DFU | Device Firmware Upgrade | 主要用于单片机下载程序 |
1.4 USB Mass Storage framework
1.5 BOT(Bulk-only Transport)协议
上文提到的Transfer类型共有四种,但对于MSC(mass storage class)类,传输的数据量比较大,只能用Buck传输,所以诞生了BOT(Bulk-only Transport),来传输数据、状态和控制信息。
1.5.1 BOT协议的基本架构:
主要由两个包组成: 命令状态包(CSW)和命令块包(CBD)组成
1.5.2 Command Status Wrapper(CSW):
- bCSWStatus: 指示传输是否成功
1.5.3 Command Block Wrapper(CBW)
- CBWCB: 储存了scsi指令
1.6 参考资料
[1]ST发布的USB设备库 http://mcu.eetrend.com/files/2020-01/wen_zhang_/100046858-87890-dm00108129zhv1.pdf
[2]ST发布的USB2.0培训文档https://www.stmcu.com.cn/Designresource/design_resource_detail/file/5557/lang/ZH/token/6d3999f8af41afc3ed2c5c4ec861c452
[3]Bulk Only Transport官方文档 https://www.usb.org/sites/default/files/usbmassbulk_10.pdf
二、光盘介绍
2.1 光盘与光驱
2.1.1 外形
https://th.bing.com/th/id/OIP.ey2Ei_VHPdmwkJxkcvJeUwHaHa?w=217&h=217&c=7&o=5&dpr=1.25&pid=1.7
https://th.bing.com/th/id/OIP.IfKqBwk1u5gsA4zwY9g5mQHaFR?w=290&h=206&c=7&o=5&dpr=1.25&pid=1.7
2.1.2 光盘
- CD(Compact Disc),DVD(Digital Video Disc), BD(Blu-ray Disc)基本类似,主要是工艺和容量不同
- DVD-ROM: 采用模具压缩印制,"只读";DVD-R/DVD+R: 可以多次刻录,但不能擦除,每次刻录是永久的;DVD±RW: 可以多次刻录和擦除
- DVD-R和DVD-RW的差异是由光盘材料决定的
2.2 光盘的文件系统
2.2.1 CDFS
也叫iso9660,只读文件系统,用于CD/DVD-ROM上,一旦生成,不可改写数据。
2.2.2 UDF
允许在CD-R或CD-RW光盘上任意追加数据,类似于U盘,可以读写和擦除。(当然在CD-R上不能真正地擦除,只是擦除文件目录,不能擦除磁盘内容)。
2.3 参考资料
[1]https://en.wikipedia.org/wiki/DVD_recordable#DVD-R_and_DVD-RW_(DVD_"dash")
[2]https://en.wikipedia.org/wiki/DVD
[3]https://blog.csdn.net/lisenyang/article/details/39227641
[4]http://target0.be/madchat/coding/filesystems/introduction_to_iso9660.pdf
三、U盘->DVD设备
我们基于stm32cube生成的U盘代码修改,使其能够被识别为DVD-ROM和DVD-RW.
3.1 识别为DVD-ROM
3.1.1 描述符(不需要修改)
描述符中与设备有关的只有Interface Descriptors的以下三个字段
stm32: (usbd_msc.c)
0x08, /* bInterfaceClass: MASS STORAGE Class */
0x06, /* bInterfaceSubClass : SCSI transparent command set */
0x50, /* USB Mass Storage Class Bulk-Only (BBB)Transport */
不管是U盘还是光盘,都是MSC的设备,使用scsi指令以及bulk-only传输协议,所以不需要修改描述符。
3.1.2 scsi指令
stm32在usbd_msc_scsi.c中定义了scsi指令,但是U盘版本缺少了几条scsi指令,需要补充上去,具体指令如下所示:
- READ TOC/PMA
读取TOC(Table of Contents), PMA(Program Memory Area)的信息,包括第一个轨道序号、第二个轨道序号,Q子轨道编码方式等等。
输入的指令:
返回的指令:
0x00,0x12,0x01,0x01,0x00,0x14,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x14,0xaa,0x00,0x00,0xff,0x3b,0x4a
注: 这里仅仅针对了format = 0000;
- GET EVENT/STATUS 返回Events或Statuses事件
- GET CONFIGURATION 返回配置信息(有多个分支,可以简单处理)
- READ DISC INFORMATION 读取磁盘信息
- READ TRACK INFORMATION 读取轨道信息
- GET PERFORMANCE 读取磁盘性能
蓝色表示与DVD设备类型有关,需要特别注意。
3.1.3 文件系统
添加了以上scsi指令之后,PC还是不能识别到光盘,因为代码内部创建的是FAT的文件系统,而光盘不适配FAT文件系统,它的文件系统只有UDF或者CDFS。所以我们打算在PC上用Write指令写入一个.iso文件,从而生成CDFS的文件系统。
参考代码: https://github.com/GenieKits/USB-CDROM-Emulation-on-STM32F103C8
3.1.4 结果
写入.iso文件后,可以识别到DVD-ROM并读取数据(.iso文件解压出来的数据),但是不能添加和删除数据。
3.2 识别为DVD-RW
3.2.1 scsi指令
修改usbd_msc_scsi.c中的scsi指令,具体如下:
- READ TOC/PMA; 获取TOC/PMA的信息(两个分支)
- GET EVENT/STATUS; 获取EVENT/STATUS信息
- GET CONFIGURATION; 获取配置信息(很多个分支)
- READ DISC INFORMATION; 读取磁盘信息
- READ TRACK INFORMATION; 读取轨道信息
- GET PERFORMANCE; 读取磁盘性能
- REPORT KEY; 请求认证
- READ DVD STRUCT; 读取DVD结构
- READ FORMAT CAPS; 读取DVD容量
- FORMAT UNIT; 格式化
- SYSN CACHE ; 同步,有处理即可
蓝色表示与DVD设备类型有关,需要特别注意。
3.2.2 文件系统:
我们修改了FAT文件系统初始化代码,在初始化过程中将SDRAM清零,让windows误以为它没有文件系统,将它格式化,同时写入UDF的文件系统。
3.2.3 结果:
设备上电格式化之后,可以识别到DVD-RW,并且可以像U盘一样拖动和删除文件。
3.3 参考资料:
[1]scsi标准指令集https://www.seagate.com/files/staticfiles/support/docs/manual/Interface manuals/100293068j.pdf
[2]scsi多媒体设备指令集
https://ia802808.us.archive.org/33/items/mmc3r10g/mmc3r10g.pdf