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

📄 bot_driver.c

📁 This software package contains the USB framework core developped by ATMEL, as well as a Mass stora
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
        // Case 3  (Hn < Do)
        else if ((bHostType == BOT_NO_TRANSFER)
                 && (bDeviceType == BOT_HOST_TO_DEVICE)) {

            TRACE_WARNING("W: BOT_PreProcessCommand: Case 3\n\r");
            pCommandState->bCase = BOT_CASE_PHASE_ERROR;
            pCommandState->dLength = 0;
        }
        // Case 4  (Hi > Dn)
        else if ((bHostType == BOT_DEVICE_TO_HOST)
                 && (bDeviceType == BOT_NO_TRANSFER)) {

            TRACE_WARNING("W: BOT_PreProcessCommand: Case 4\n\r");
            pCommandState->bCase = BOT_CASE_STALL_IN;
            pCommandState->dLength = 0;
            pCsw->dCSWDataResidue = dHostLength;
        }
        // Case 5  (Hi > Di)
        else if ((bHostType == BOT_DEVICE_TO_HOST)
                 && (bDeviceType == BOT_DEVICE_TO_HOST)
                 && (dHostLength > dDeviceLength)) {

            TRACE_WARNING("W: BOT_PreProcessCommand: Case 5\n\r");
            pCommandState->bCase = BOT_CASE_STALL_IN;
            pCommandState->dLength = dDeviceLength;
            pCsw->dCSWDataResidue = dHostLength - dDeviceLength;
        }
        // Case 6  (Hi = Di)
        if ((bHostType == BOT_DEVICE_TO_HOST)
            && (bDeviceType == BOT_DEVICE_TO_HOST)
            && (dHostLength == dDeviceLength)) {

            pCommandState->bCase = 0;
            pCommandState->dLength = dDeviceLength;
        }
        // Case 7  (Hi < Di)
        else if ((bHostType == BOT_DEVICE_TO_HOST)
                 && (bDeviceType == BOT_DEVICE_TO_HOST)
                 && (dHostLength < dDeviceLength)) {

            TRACE_WARNING("W: BOT_PreProcessCommand: Case 7\n\r");
            pCommandState->bCase = BOT_CASE_PHASE_ERROR;
            pCommandState->dLength = dHostLength;
        }
        // Case 8  (Hi <> Do)
        else if ((bHostType == BOT_DEVICE_TO_HOST)
                 && (bDeviceType == BOT_HOST_TO_DEVICE)) {

            TRACE_WARNING("W: BOT_PreProcessCommand: Case 8\n\r");
            pCommandState->bCase = BOT_CASE_STALL_IN | BOT_CASE_PHASE_ERROR;
            pCommandState->dLength = 0;
        }
        // Case 9  (Ho > Dn)
        else if ((bHostType == BOT_HOST_TO_DEVICE)
                 && (bDeviceType == BOT_NO_TRANSFER)) {

            TRACE_WARNING("W: BOT_PreProcessCommand: Case 9\n\r");
            pCommandState->bCase = BOT_CASE_STALL_OUT;
            pCommandState->dLength = 0;
            pCsw->dCSWDataResidue = dHostLength;
        }
        // Case 10 (Ho <> Di)
        else if ((bHostType == BOT_HOST_TO_DEVICE)
                 && (bDeviceType == BOT_DEVICE_TO_HOST)) {

            TRACE_WARNING("W: BOT_PreProcessCommand: Case 10\n\r");
            pCommandState->bCase = BOT_CASE_STALL_OUT | BOT_CASE_PHASE_ERROR;
            pCommandState->dLength = 0;
        }
        // Case 11 (Ho > Do)
        else if ((bHostType == BOT_HOST_TO_DEVICE)
                 && (bDeviceType == BOT_HOST_TO_DEVICE)
                 && (dHostLength > dDeviceLength)) {

            TRACE_WARNING("W: BOT_PreProcessCommand: Case 11\n\r");
            pCommandState->bCase = BOT_CASE_STALL_OUT;
            pCommandState->dLength = dDeviceLength;
            pCsw->dCSWDataResidue = dHostLength - dDeviceLength;
        }
        // Case 12 (Ho = Do)
        else if ((bHostType == BOT_HOST_TO_DEVICE)
                 && (bDeviceType == BOT_HOST_TO_DEVICE)
                 && (dHostLength == dDeviceLength)) {

            pCommandState->bCase = 0;
            pCommandState->dLength = dDeviceLength;
        }
        // Case 13 (Ho < Do)
        else if ((bHostType == BOT_HOST_TO_DEVICE)
                 && (bDeviceType == BOT_HOST_TO_DEVICE)
                 && (dHostLength < dDeviceLength)) {

            TRACE_WARNING("W: BOT_PreProcessCommand: Case 13\n\r");
            pCommandState->bCase = BOT_CASE_PHASE_ERROR;
            pCommandState->dLength = dHostLength;
        }
    }

    return isCommandSupported;
}

//------------------------------------------------------------------------------
//! \brief  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  pBot Pointer to a S_bot instance
//------------------------------------------------------------------------------
static void BOT_PostProcessCommand(S_bot *pBot)
{
    S_bot_command_state *pCommandState = &(pBot->sCommandState);
    S_msd_csw           *pCsw = &(pCommandState->sCsw);
    const S_usb         *pUsb = pBot->sClass.pUsb;

    // STALL Bulk IN endpoint ?
    if (ISSET(pCommandState->bCase, BOT_CASE_STALL_IN)) {

        TRACE_DEBUG_M("StallIn ");
        USB_Halt(pUsb, BOT_EPT_BULK_IN, USB_SET_FEATURE);
    }

    // STALL Bulk OUT endpoint ?
    if (ISSET(pCommandState->bCase, BOT_CASE_STALL_OUT)) {

        TRACE_DEBUG_M("StallOut ");
        USB_Halt(pUsb, BOT_EPT_BULK_OUT, USB_SET_FEATURE);
    }

    // Set CSW status code to phase error ?
    if (ISSET(pCommandState->bCase, BOT_CASE_PHASE_ERROR)) {

        TRACE_DEBUG_M("PhaseErr ");
        pCsw->bCSWStatus = MSD_CSW_PHASE_ERROR;
    }
}

//------------------------------------------------------------------------------
//! \brief  Processes the latest command received by the device.
//! \param  pBot Pointer to a S_bot instance
//! \return true if the command has been completed, false otherwise.
//------------------------------------------------------------------------------
static bool BOT_ProcessCommand(S_bot *pBot)
{
    unsigned char       bStatus;
    const S_usb         *pUsb = pBot->sClass.pUsb;
    S_bot_command_state *pCommandState = &(pBot->sCommandState);
    S_msd_cbw           *pCbw = &(pCommandState->sCbw);
    S_msd_csw           *pCsw = &(pCommandState->sCsw);
    S_lun               *pLun = &(pBot->pLun[(unsigned char) pCbw->bCBWLUN]);
    bool                isCommandComplete = false;

    // Check if LUN is valid
    if (pCbw->bCBWLUN > pBot->bMaxLun) {

        TRACE_WARNING("W: BOT_ProcessCommand: Requested LUN does not exist\n\r");
        bStatus = BOT_STATUS_ERROR;
    }
    else {

        // Process command
        if (pBot->bMaxLun > 0) {

            TRACE_DEBUG_M("LUN%d ", pCbw->bCBWLUN);
        }

        bStatus = SBC_ProcessCommand(pUsb, pLun, pCommandState);
    }

    // Check command result code
    if (bStatus == BOT_STATUS_PARAMETER) {

        TRACE_WARNING("W: BOT_ProcessCommand: Unknown command 0x%02X\n\r",
                      pCbw->pCommand[0]);

        // Update sense data
        SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                            SBC_SENSE_KEY_ILLEGAL_REQUEST,
                            SBC_ASC_INVALID_FIELD_IN_CDB,
                            0);

        // Result codes
        pCsw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
        isCommandComplete = true;

        // stall the request, IN or OUT
        if (!ISSET(pCbw->bmCBWFlags, MSD_CBW_DEVICE_TO_HOST)
            && (pCbw->dCBWDataTransferLength > 0)) {

            // Stall the OUT endpoint : host to device
            USB_Halt(pUsb, BOT_EPT_BULK_OUT, USB_SET_FEATURE);
            TRACE_DEBUG_M("StaOUT ");
        }
        else {

            // Stall the IN endpoint : device to host
            USB_Halt(pUsb, BOT_EPT_BULK_IN, USB_SET_FEATURE);
            TRACE_DEBUG_M("StaIN ");
        }
    }
    else if (bStatus == BOT_STATUS_ERROR) {

        TRACE_WARNING("W: MSD_ProcessCommand: Command failed\n\r");

        // Update sense data
// TODO (jjoannic#1#): Change code
        SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                            SBC_SENSE_KEY_MEDIUM_ERROR,
                            SBC_ASC_INVALID_FIELD_IN_CDB,
                            0);

        // Result codes
        pCsw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
        isCommandComplete = true;
    }
    else {

        // Update sense data
        SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                            SBC_SENSE_KEY_NO_SENSE,
                            0,
                            0);

        // Is command complete ?
        if (bStatus == BOT_STATUS_SUCCESS) {

            isCommandComplete = true;
        }
    }

    // Check if command has been completed
    if (isCommandComplete) {

        TRACE_DEBUG_M("Cplt ");

        // Adjust data residue
        if (pCommandState->dLength != 0) {

            pCsw->dCSWDataResidue += pCommandState->dLength;

            // STALL the endpoint waiting for data
            if (!ISSET(pCbw->bmCBWFlags, MSD_CBW_DEVICE_TO_HOST)) {

                // Stall the OUT endpoint : host to device
                USB_Halt(pUsb, BOT_EPT_BULK_OUT, USB_SET_FEATURE);
                TRACE_DEBUG_M("StaOUT ");
            }
            else {

                // Stall the IN endpoint : device to host
                USB_Halt(pUsb, BOT_EPT_BULK_IN, USB_SET_FEATURE);
                TRACE_DEBUG_M("StaIN ");
            }
        }

        // Reset command state
        pCommandState->bState = 0;
    }

    return isCommandComplete;
}

//------------------------------------------------------------------------------
//      Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief  Resets the state of the BOT driver
//! \param  pBot Pointer to a S_bot instance
//! \see    S_bot
//------------------------------------------------------------------------------
void BOT_Reset(S_bot *pBot)
{
    TRACE_DEBUG_M("MSDReset ");

#if !defined(TR_DEBUG_L)
    TRACE_DEBUG_M("\n\r");
#endif

    pBot->bState = BOT_STATE_READ_CBW;
    pBot->isWaitResetRecovery = false;
    pBot->sCommandState.bState = 0;
}

//------------------------------------------------------------------------------
//! \brief  Initializes a BOT driver and the associated USB driver.
//! \param  pBot    Pointer to a S_bot instance
//! \param  pUsb    USB driver to use
//! \param  pLun    Pointer to a list of LUNs
//! \param  bNumLun Number of LUN in list
//! \see    S_bot
//! \see    S_usb
//------------------------------------------------------------------------------
void BOT_Init(S_bot *pBot,
              const S_usb *pUsb,
              S_lun *pLun,
              unsigned char bNumLun)
{
    TRACE_INFO("I: MSD init\n\r");

    // BOT driver initialization
    pBot->sClass.pUsb = pUsb;
    pBot->sClass.pDescriptors = &sDescriptors;

    // Command state initialization

⌨️ 快捷键说明

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