Case(1), case(6), case(12)状态下是正常的数据传输,被称为“The thin diagonal”。其它的状态是协议外的内容,是一些判断。

6.7.1 主机期望发起一次无数据传输的命令

CBW包中的dCBWDataTransferLength字段=0,Direction位不考虑。

主机做的工作:

(1)       发送一个CBW

(2)       偿试接收CSW

(3)       如果在STALL状态下接收到CSW:先清空BULK—IN端口数据,再接收CSW

(4)       判断CSW,如果“bCSWStatus = 00h or 01h, and the dCSWDataResidue is 0.”,它是CASE(1),其它是一个相位错误,需要主机发送一个复位来清除错误。

设备做的工作:

(1)       等待接收一个CBW

(2)       CBW有效,则执行命令

(3)       分析包,如果是CASE(1),说明无数据传输,设置bCSWStatus to 00h or 01h.,bCSWStatus to 00h or 01h.。如果是CASE(2)或CASE(3),设置bCSWStatus to 02h.

(4)       发送CSW。

6.7.2 主机期望从设备接收数据

这种情况下CBW中的dCBWDataTransferLength为非0并且Direction为1(Data-In)。

主机做的工作:

(1)       发送CBW

(2)       偿试接收数据

(3)       如果在STALL状态下接收到数据:1)主将接收数据2)主机将清空BULK_IN端口

(4)       偿试接收CSW

(5)       如果在STALL状态下接收到CSW:1)主机将清空bulk_in端口2)主机将偿试再次接收CSW。

(6)       分析CSW,如果是CASE(4),CASE(5),CASE(6), bCSWStatus = 00h or 01h, 接收数据的大小应等于dCBWDataTransferLength – dCSWDataResidue。如果是CASE(7),CASE(8),且bCSWStatus = 02h,主机需要发送复位来清除错误。

设备做的工作:

(1)       等待并接收CBW

(2)       CBW有效则执行命令。如果是CASE(6),发送dCBWDataTransferLength字节数据给主机,设置bCSWStatus to 00h or 01h,dCSWDataResidue to zero。

CASE(4),CASE(5):说明设备发送的数据长度比主机要求的数据长度小。有两种处理方法:1)发送实际数据后再发送填充数据使用总长度等于dCBWDataTransferLength,设置dCSWDataResidue=dCBWDataTransferLength;2)发送实际数据长度,设置dCSWDataResidue=dCBWDataTransferLength-发送数据的长度。

CASE(7),CASE(8):说明设备要发送的数据超出主机要求的数据长度。两种处理:1)发送主机要求的数据长度,(下一句不知怎么翻译)2)发送设备的数据长度(超出主机要求的数据长度)。这两种处理后均设置bulk_in端口为STALL状态,并设置CSW包相位错误(bCSWStatus to 02h)。

(3)       发送CSW。

6.7.3 主机期望发送数据到设备

这种情况下CBW中的dCBWDataTransferLength为非0并且Direction为0(Data-In)。

主机做的工作:

(1)       发送CBW

(2)       发送数据到设备,在数据传输结尾,主机将发送一个短包。

(3)       在STALL状态下发送数据,主机将清空bulk_out端口

(4)       偿试接收CSW

(5)       在STALL状态下接收CSW,主机清空bulk_in端口,再偿试接收CSW

(6)       CSW有效,如果是CASE(9),CASE(11),CASE(12),设备实际接收的数据等于dCBWDataTransferLength – dCSWDataResidue。如果是CASE(9),(13),主机需要发送复位来清除错误。

设备做的工作

(1)       接收CBW

(2)       CBW有效:

如果是CASE(9),CASE(11),CASE(12),有可能设备需要的数据小于主机发送的长度:

1)       设备接收它需要的数据长度,并设置dCSWDataResidue = dCBWDataTransferLength – 实际接收数据的长度。之后设置bulk_out端口为STALL状态。

2)       设备接收主机发送的所有数据。

3)       发送CSW。

//-----------------------------------------------------------------------------
/// Pre-processes a command by checking the differences between the host and
/// device expectations in term of transfer type and length.
/// Once one of the thirteen cases is identified, the actions to do during the
/// post-processing phase are stored in the dCase variable of the command
/// state.
/// \param  pMsdDriver Pointer to a MSDDriver instance
/// \return 1 if the command is supported, false otherwise
//-----------------------------------------------------------------------------
static unsigned char MSDD_PreProcessCommand(MSDDriver *pMsdDriver)
{
unsigned int        hostLength = 0; //记录cbw包中的数据传输大小
unsigned int        deviceLength = 0; //分析cbw包中的SCSI命令中的数据传输大小
unsigned char       hostType;   //记录cbw包中的数据传输方向
unsigned char       deviceType; //分析cbw包中的SCSI命令中的数据传输方向
unsigned char       isCommandSupported; //分析cbw包中的SCSI命令是否支持
MSDCommandState *commandState = &(pMsdDriver->commandState);
MSCsw           *csw = &(commandState->csw);
MSCbw           *cbw = &(commandState->cbw);
MSDLun          *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
// Get information about the command
// Host-side
//获取cbw包中标明的数据传输方向和数据传输大小
MSDD_GetCommandInformation(cbw, &hostLength, &hostType);
// Device-side
//分析cbw包中scsi命令,取得scsi命令中标明的数据传输方向和大小
isCommandSupported = SBC_GetCommandInformation(cbw->pCommand,
&deviceLength,
&deviceType,
lun);
// Initialize data residue and result status
// dCSWDataResidue记录传输数据大小,
csw->dCSWDataResidue = 0;
csw->bCSWStatus = MSD_CSW_COMMAND_PASSED;
// Check if the command is supported
if (isCommandSupported) {
// Identify the command case
if(hostType == MSDD_NO_TRANSFER) {
// Case 1  (Hn = Dn)
if(deviceType == MSDD_NO_TRANSFER) {
//TRACE_WARNING("Case 1\n\r");
commandState->postprocess = 0;
commandState->length = 0;
}
else if(deviceType == MSDD_DEVICE_TO_HOST) {
// Case 2  (Hn < Di)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 2\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
else { //if(deviceType == MSDD_HOST_TO_DEVICE) {
// Case 3  (Hn < Do)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 3\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
}
// Case 4  (Hi > Dn)
else if(hostType == MSDD_DEVICE_TO_HOST) {
if(deviceType == MSDD_NO_TRANSFER) {
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 4\n\r");
commandState->postprocess = MSDD_CASE_STALL_IN;
commandState->length = 0;
csw->dCSWDataResidue = hostLength;
}
else if(deviceType == MSDD_DEVICE_TO_HOST) {
if(hostLength > deviceLength) {
// Case 5  (Hi > Di)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 5\n\r");
commandState->postprocess = MSDD_CASE_STALL_IN;
commandState->length = deviceLength;
csw->dCSWDataResidue = hostLength - deviceLength;
}
else if(hostLength == deviceLength) {
// Case 6  (Hi = Di)
commandState->postprocess = 0;
commandState->length = deviceLength;
}
else { //if(hostLength < deviceLength) {
// Case 7  (Hi < Di)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 7\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = hostLength;
}
}
else { //if(deviceType == MSDD_HOST_TO_DEVICE) {
// Case 8  (Hi <> Do)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 8\n\r");
commandState->postprocess =
MSDD_CASE_STALL_IN | MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
}
else if(hostType == MSDD_HOST_TO_DEVICE) {
if(deviceType == MSDD_NO_TRANSFER) {
// Case 9  (Ho > Dn)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 9\n\r");
commandState->postprocess = MSDD_CASE_STALL_OUT;
commandState->length = 0;
csw->dCSWDataResidue = hostLength;
}
else if(deviceType == MSDD_DEVICE_TO_HOST) {
// Case 10 (Ho <> Di)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 10\n\r");
commandState->postprocess =
MSDD_CASE_STALL_OUT | MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
else { //if(deviceType == MSDD_HOST_TO_DEVICE) {
if(hostLength > deviceLength) {
// Case 11 (Ho > Do)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 11\n\r");
commandState->postprocess = MSDD_CASE_STALL_OUT;
commandState->length = deviceLength;
csw->dCSWDataResidue = hostLength - deviceLength;
}
else if(hostLength == deviceLength) {
// Case 12 (Ho = Do)
//TRACE_WARNING(
//    "MSDD_PreProcessCommand: Case 12\n\r");
commandState->postprocess = 0;
commandState->length = deviceLength;
}
else { //if(hostLength < deviceLength) {
// Case 13 (Ho < Do)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 13\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = hostLength;
}
}
}
}
return isCommandSupported;
}

USB Mass Storage 6.7 The Thirteen Cases章节的理解相关推荐

  1. USB Mass Storage大容量存储 The Thirteen Class章节的理解

    http://blog.csdn.net/xgbing/article/details/7002558 USB Mass Storage 6.7 The Thirteen Class章节的理解 Cas ...

  2. 如何实现Linux下的U盘(USB Mass Storage)驱动

    如何实现Linux下的U盘(USB Mass Storage)驱动 版本:v0.7 How to Write LinuxUSB MSC (Mass Storage Class) Driver Crif ...

  3. ZYNQ裸机实现 USB MASS STORAGE (usb+sd卡 实现U盘功能)

    ZYNQ裸机实现 USB MASS STORAGE (usb+sd卡 实现U盘功能) 之所以写裸机,也就是没有操作系统的实现方法是因为linux系统下的实现方法网上已经有很多了,之前使用的STM32实 ...

  4. 基于OHCI的USB主机 —— UFI命令 USB Mass Storage Class Bulk-Only Transport协议介绍

    USB Mass Storage Class Bulk-Only Transport Microsoft公司至Windows98后,USB主机 都支持Bulk-Only标准,所以现在的大容量存储类设备 ...

  5. Linux下大容量存储,第 2 章 USB Mass Storage大容量存储的基本知识

    第 2 章 USB Mass Storage大容量存储的基本知识 摘要 USB Mass Storage所对应的层次和要实现哪些东西: 图 2.1. USB Mass Storage Framewor ...

  6. USB Mass Storage协议

    简介 USB Mass storage Device协议即海量存储设备协议适用于硬盘,U盘等大容量存储设备.协议使用的接口端点有BulkIn.BulkOut和Interrupt端点.该设备类又包含6个 ...

  7. usb mass storage设备枚举过程

    8月份从PC开发岗位换到底层嵌入式驱动开发来了.接到的第二个活,是在高通8650平台上实现驻留支持SCSI指令.8650平台是高通推出的EVDO RevB的双核平台,和之前6085相比性能更强,软件结 ...

  8. USB Mass Storage

    参见:USB Mass StorageClass Bulk-Only Transport 1 规范概述和范围 前提条件:熟悉USB协议规范和USB海量存储类规范概述. 本规范只描述块传输,也就是仅通过 ...

  9. USB Mass Storage Class

    编辑博客时,回车的意思是切换段落,shift+回车才是换行. SCSI Interface Controller: AMD am5380 1 U盘量产工具 - 主控芯片私有的SCSI命令 ChipEa ...

最新文章

  1. 小米air耳机重新配对_小米发布 399 元真无线蓝牙耳机,除了小爱同学还支持其他手机语音助手...
  2. python中集合变量_详解python的变量缓存机制
  3. SSRF(服务端请求伪造)原理/防御
  4. 3.企业应用架构模式 --- 映射到关系数据库
  5. (首个填坑)联想拯救者Y7000(自带win10 home) 安装Ubuntu16.04.6 + NVIDIA GTX1650驱动
  6. 怎么远程传输大文件?
  7. Python3.6之py文件转exe文件
  8. 基于51单片机的数字频率计
  9. 小白入门级的视频剪辑软件
  10. 「干活」基因组组装 学习笔记 - 入门知识点和Genome Survey
  11. 深度学习中 GPU 和显存分析
  12. python安装以后怎么打开_安装python后如何打开
  13. Android关机充电打开log,Android关机log
  14. PYNQ-关于PYNQ的UART的使用(RPI接口)
  15. Vim - 官方网站
  16. 阻止checkbox选中态
  17. lytro 光场相机 重聚焦
  18. Mac 电脑wify 没有ip地址
  19. oracle将excel导入,Win7系统把Excel数据导入oracle的方法(图文)
  20. 华企会“资源整合赢天下”――龙岩分会发动大会

热门文章

  1. 【转】CMNET和CMWAP区别
  2. python 新式类_【Python】Python 新式类介绍
  3. eai java,EAI与SOA
  4. 考研数学第三章复习:微分中值定理以及导数的应用(1)
  5. 多层标高平面图中的CAD标高设置
  6. ECMAScript6语法
  7. uefi装完系统后无法引导_uefi安装win10无法启动?uefi安装win10无法启动原因分析及解决方法...
  8. 【Oracle】高级查询练习题详解
  9. 盘点几款好用的开源商城系统
  10. 财税SaaS行业格局再变,慧算账为何能受资本“偏爱”?