文章目录
1.简介
前面我们介绍了USB的枚举,还没真正与产品挂钩,生活中常用的USB设备大家都很熟悉,键盘、鼠标、U盘,USB设备分为5大类:显示器、通信设备、音频设备、人机输入、海量存储。今天我们来看下U盘的使用,即海量存储设备,在4种传输方式中使用批量传输方式。
2.U盘(mass storage device)
2.1 描述符
在USB协议中规定了大容量存储设备,大容量设备有很多种,U盘就是其中一种,bInterfaceClass字段为0x08,bInterfaceSubClass有好几种,但大部分U盘都使用0x06,即SCSI命令集,bInterfaceProtocol字段有3种:0x00、0x01、0x50,前两种需要使用中断传输,最后一种使用批量传输,一般使用批量传输。用描述符软件查看U盘如下所示,关键字段用了红色方框:
2.2 类特殊请求
U盘枚举的时候除了有前面说到的标准设备请求外,在Bulk-Only协议中定义了两个类特殊请求:Bulk-Only Mass Storage Reset和Get Max LUN。前者是复位到命令状态的请求,后者是获取最大逻辑单元请求。
2.2.1 Bulk Only Mass Storage Reset
2.2.2 Get Max LUN
2.2.3 伪代码
接上一节的控制传输流程添加代码:
//控制传输流程
void usb_control_transmit()
{
usb_ctl_req req;
static int state;
if(state == 建立过程){
//读8个字节长度请求
usb_read_ep0(&req, 8);
switch(req.bmRequestType & 0x1f){
case DEVICE:
SET_ADDRESS:
结束流程,没有数据过程;
break;
GET_DESCRIPTOR:
设备、配置、接口描述符;
state = 数据过程;
break;
case INTERFACE:
switch(req.bmRequestType & 0x60){
case Standard:
break;
case Class:
switch (req.bRequest){
case Bulk Only Mass Storage Reset:
初始化端口状态,准备接收命令。
break;
case Get Max LUN:
返回最大逻辑单元。
break;
default:
break;
}
break;
default:
break;
}
break;
case ENDPOINT:
break;
default:
break;
}
}else if(数据过程){
发送数据/接收数据;
数据发送完成/接收完成结束;
}
}
2.3 Bulk-Only
在接口协议类型中指定了协议使用批量传输Bulk-Only,Bulk-Only协议也有像控制传输的三个过程:命令阶段、数据阶段、状态阶段(相当于封装了3个批量传输),在命令阶段使用命令块封包CBW(Command Block Wrapper),在状态阶段使用CSW(Command Status Wrapper)来回复,它们的格式如下所示:
2.4 SCSI
我们知道了传输协议Bulk-Only,但还需要知道传输协议的格式scsi是如何的(虽然在接口子类定义的是SCSI,但实际上是使用UFI命令集),U盘中常用的只有几个:INQUIRY、READ CAPACITY、READ、WRITE等。
2.4.1 INQUIRY
命令请求目标设备的一些基本信息。
2.4.2 READ FORMAT CAPACITIES
表示设备智齿最大的格式化容量,容量=块数*每块字节数,通常每块字节数为512。
2.4.3 READ CAPACITY
读容量命令可以让主机读取到当前存储媒介的容量。
2.4.4 READ(10)
读出取存储设备数据。
2.4.5 WRITE(10)
写入存储设备数据。
2.4.6 REQUEST SENSE
用来探测上一个命令执行失败的原因,主机可以在每个命令之后使用该命令来读取命令执行情况。
2.4.7 TEST UNIT READ
TEST UNIT READY命令用来测试设备的某个逻辑单元是否准备好,如果准备好则在状态阶段返回执行成功,如果没准备好则返回执行失败,当主机使用REQUEST SENSE命令来探测错误原因的时候,设置Sense Key为NOT READY。
2.4.8 伪代码
void mssstorage_device(){
//1.获取cbw,31字节
cbw = get_cbw();
//2.判断操作码
switch(cbw.optcode){
case INQUIRY:
break;
case READ FORMAT CAPACITIES:
break;
case READ CAPACITY:
break;
case READ10:
break;
case WRITE10:
break;
case REQUEST SENSE:
break;
case TEST UNIT READ:
break;
default:
break;
}
//3.发送csb
send_csb(csb);
}
3.参考文档
USB官网:https://www.usb.org/
usbmass-ufi10.pdf
usbmassbulk_10.pdf