⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msddstatemachine.c

📁 Include startup files and peripherial devices Code for Atmel ARM7 development
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support 
 * ----------------------------------------------------------------------------
 * Copyright (c) 2008, Atmel Corporation
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ----------------------------------------------------------------------------
 */

//-----------------------------------------------------------------------------
//      Includes
//-----------------------------------------------------------------------------

#include "SBCMethods.h"
#include "MSDDStateMachine.h"

//-----------------------------------------------------------------------------
//      Internal functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Returns the expected transfer length and direction (IN, OUT or don't care)
/// from the host point-of-view.
/// \param  cbw     Pointer to the CBW to examinate
/// \param  pLength Expected length of command
/// \param  pType   Expected direction of command
//-----------------------------------------------------------------------------
static void MSDD_GetCommandInformation(MSCbw *cbw,
                                       unsigned int  *length,
                                       unsigned char *type)
{
    // Expected host transfer direction and length
    (*length) = cbw->dCBWDataTransferLength;

    if (*length == 0) {

        (*type) = MSDD_NO_TRANSFER;
    }
    else if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) != 0) {

        (*type) = MSDD_DEVICE_TO_HOST;
    }
    else {

        (*type) = MSDD_HOST_TO_DEVICE;
    }
}

//-----------------------------------------------------------------------------
/// 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;
    unsigned int        deviceLength;
    unsigned char       hostType;
    unsigned char       deviceType;
    unsigned char       isCommandSupported;
    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
    MSDD_GetCommandInformation(cbw, &hostLength, &hostType);

    // Device-side
    isCommandSupported = SBC_GetCommandInformation(cbw->pCommand,
                                                   &deviceLength,
                                                   &deviceType,
                                                   lun);

    // Initialize data residue and result status
    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;
}

//-----------------------------------------------------------------------------
/// Post-processes a command given the case identified during the
/// pre-processing step.
/// Depending on the case, one of the following actions can be done:
///           - Bulk IN endpoint is stalled
///           - Bulk OUT endpoint is stalled
///           - CSW status set to phase error
/// \param  pMsdDriver Pointer to a MSDDriver instance
//-----------------------------------------------------------------------------
static void MSDD_PostProcessCommand(MSDDriver *pMsdDriver)
{
    MSDCommandState *commandState = &(pMsdDriver->commandState);
    MSCsw           *csw = &(commandState->csw);

    // STALL Bulk IN endpoint ?
    if ((commandState->postprocess & MSDD_CASE_STALL_IN) != 0) {

        TRACE_INFO_WP("StallIn ");
        MSDD_Halt(MSDD_CASE_STALL_IN);
    }

    // STALL Bulk OUT endpoint ?
    if ((commandState->postprocess & MSDD_CASE_STALL_OUT) != 0) {

        TRACE_INFO_WP("StallOut ");
        MSDD_Halt(MSDD_CASE_STALL_OUT);
    }

    // Set CSW status code to phase error ?
    if ((commandState->postprocess & MSDD_CASE_PHASE_ERROR) != 0) {

        TRACE_INFO_WP("PhaseErr ");
        csw->bCSWStatus = MSD_CSW_PHASE_ERROR;
    }
}

//-----------------------------------------------------------------------------
/// Processes the latest command received by the %device.
/// \param  pMsdDriver Pointer to a MSDDriver instance
/// \return 1 if the command has been completed, false otherwise.
//-----------------------------------------------------------------------------
static unsigned char MSDD_ProcessCommand(MSDDriver * pMsdDriver)
{
    unsigned char   status;
    MSDCommandState *commandState = &(pMsdDriver->commandState);
    MSCbw           *cbw = &(commandState->cbw);
    MSCsw           *csw = &(commandState->csw);
    MSDLun          *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
    unsigned char   isCommandComplete = 0;

    // Check if LUN is valid
    if (cbw->bCBWLUN > pMsdDriver->maxLun) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -