USB Mass Storage 6.7 The Thirteen Cases章节的理解

 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;
}


 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值