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

📄 sbc_methods.c

📁 This software package contains the USB framework core developped by ATMEL, as well as a Mass stora
💻 C
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------------
static unsigned char SBC_ModeSense6(const S_usb         *pUsb,
                                    S_lun               *pLun,
                                    S_bot_command_state *pCommandState)
{
    unsigned char      bResult = BOT_STATUS_INCOMPLETE;
    unsigned char      bStatus;
    S_bot_transfer     *pTransfer = &(pCommandState->sTransfer);

    // Initialize command state if needed
    if (pCommandState->bState == 0) {

        pCommandState->bState = SBC_STATE_WRITE;
    }

    // Check current command state
    switch (pCommandState->bState) {
    //-------------------
    case SBC_STATE_WRITE:
    //-------------------
        // Start transfer
        bStatus = USB_Write(pUsb,
                            BOT_EPT_BULK_IN,
                            (void *) &sModeParameterHeader6,
                            pCommandState->dLength,
                            (Callback_f) BOT_Callback,
                            (void *) pTransfer);

        // Check operation result code
        if (bStatus != USB_STATUS_SUCCESS) {

            TRACE_WARNING("W: SPC_ModeSense6: Cannot start data transfer\n\r");
            bResult = BOT_STATUS_ERROR;
        }
        else {

            // Proceed to next state
            pCommandState->bState = SBC_STATE_WAIT_WRITE;
        }
        break;

    //------------------------
    case SBC_STATE_WAIT_WRITE:
    //------------------------
        TRACE_DEBUG_M("Wait ");

        // Check semaphore value
        if (pTransfer->bSemaphore > 0) {

            // Take semaphore and terminate command
            pTransfer->bSemaphore--;

            if (pTransfer->bStatus != USB_STATUS_SUCCESS) {

                TRACE_WARNING("W: SPC_ModeSense6: Data transfer failed\n\r");
                bResult = BOT_STATUS_ERROR;
            }
            else {

                bResult = BOT_STATUS_SUCCESS;
            }

            // Update dLength field
            pCommandState->dLength -= pTransfer->dBytesTransferred;

        }
        break;
    }

    return bResult;
}

//------------------------------------------------------------------------------
//! \brief  Performs a TEST UNIT READY COMMAND command.
//! \param  pLun          Pointer to the LUN affected by the command
//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
//! \see    S_lun
//------------------------------------------------------------------------------
static unsigned char SBC_TestUnitReady(S_lun *pLun)
{
    unsigned char bResult = BOT_STATUS_ERROR;

    // Check current media state
    switch(pLun->pMedia->bState) {
    //-------------------
    case MED_STATE_READY:
    //-------------------
        // Nothing to do
        TRACE_DEBUG_M("Rdy ");
        bResult = BOT_STATUS_SUCCESS;
        break;

    //------------------
    case MED_STATE_BUSY:
    //------------------
        TRACE_DEBUG_M("Bsy ");
        SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                            SBC_SENSE_KEY_NOT_READY,
                            0,
                            0);
        break;

    //------
    default:
    //------
        TRACE_DEBUG_M("? ");
        SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                            SBC_SENSE_KEY_NOT_READY,
                            SBC_ASC_MEDIUM_NOT_PRESENT,
                            0);
        break;
    }

    return bResult;
}

//------------------------------------------------------------------------------
//      Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief  Updates the sense data of a LUN with the given key and codes
//! \param  pRequestSenseData             Pointer to the sense data to update
//! \param  bSenseKey                     Sense key
//! \param  bAdditionalSenseCode          Additional sense code
//! \param  bAdditionalSenseCodeQualifier Additional sense code qualifier
//------------------------------------------------------------------------------
void SBC_UpdateSenseData(S_sbc_request_sense_data *pRequestSenseData,
                         unsigned char bSenseKey,
                         unsigned char bAdditionalSenseCode,
                         unsigned char bAdditionalSenseCodeQualifier)
{
    pRequestSenseData->bSenseKey = bSenseKey;
    pRequestSenseData->bAdditionalSenseCode = bAdditionalSenseCode;
    pRequestSenseData->bAdditionalSenseCodeQualifier
        = bAdditionalSenseCodeQualifier;
}

//------------------------------------------------------------------------------
//! \brief  Return information about the transfer length and direction expected
//!         by the device for a particular command.
//! \param  pCommand Pointer to a buffer holding the command to evaluate
//! \param  pLength  Expected length of the data transfer
//! \param  pType    Expected direction of data transfer
//! \param  pLun     Pointer to the LUN affected by the command
//------------------------------------------------------------------------------
bool SBC_GetCommandInformation(void          *pCommand,
                               unsigned int  *pLength,
                               unsigned char *pType,
                               S_lun         *pLun)
{
    S_sbc_command *pSbcCommand = (S_sbc_command *) pCommand;
    bool          isCommandSupported = true;

    // Identify command
    switch (pSbcCommand->bOperationCode) {
    //---------------
    case SBC_INQUIRY:
    //---------------
        (*pType) = BOT_DEVICE_TO_HOST;

        // Allocation length is stored in big-endian format
        (*pLength) = WORDB(pSbcCommand->sInquiry.pAllocationLength);
        break;

    //--------------------
    case SBC_MODE_SENSE_6:
    //--------------------
        (*pType) = BOT_DEVICE_TO_HOST;
        (*pLength) = min(sizeof(S_sbc_mode_parameter_header_6),
                         pSbcCommand->sModeSense6.bAllocationLength);

        // Only "return all pages" command is supported
        if (pSbcCommand->sModeSense6.bPageCode != SBC_PAGE_RETURN_ALL) {

            // Unsupported page
            TRACE_WARNING("W: SBC_GetCommandInformation: Page code not supported (0x%02X)\n\r",
                          pSbcCommand->sModeSense6.bPageCode);
            isCommandSupported = false;
            (*pLength) = 0;
        }
        break;

    //------------------------------------
    case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
    //------------------------------------
        (*pType) = BOT_NO_TRANSFER;
        break;

    //---------------------
    case SBC_REQUEST_SENSE:
    //---------------------
        (*pType) = BOT_DEVICE_TO_HOST;
        (*pLength) = pSbcCommand->sRequestSense.bAllocationLength;
        break;

    //-----------------------
    case SBC_TEST_UNIT_READY:
    //-----------------------
        (*pType) = BOT_NO_TRANSFER;
        break;

    //---------------------
    case SBC_READ_CAPACITY_10:
    //---------------------
        (*pType) = BOT_DEVICE_TO_HOST;
        (*pLength) = sizeof(S_sbc_read_capacity_10_data);
        break;

    //---------------
    case SBC_READ_10:
    //---------------
        (*pType) = BOT_DEVICE_TO_HOST;
        (*pLength) = WORDB(pSbcCommand->sRead10.pTransferLength)
                     * pLun->dBlockSize;
        break;

    //----------------
    case SBC_WRITE_10:
    //----------------
        (*pType) = BOT_HOST_TO_DEVICE;
        (*pLength) = WORDB(pSbcCommand->sWrite10.pTransferLength)
                     * pLun->dBlockSize;
        break;

    //-----------------
    case SBC_VERIFY_10:
    //-----------------
        (*pType) = BOT_NO_TRANSFER;
        break;

    //------
    default:
    //------
        isCommandSupported = false;
    }

    // If length is 0, no transfer is expected
    if ((*pLength) == 0) {

        (*pType) = BOT_NO_TRANSFER;
    }

    return isCommandSupported;
}

//------------------------------------------------------------------------------
//! \brief  Processes a SBC command by dispatching it to a subfunction.
//! \param  pUsb          Pointer to a S_usb instance
//! \param  pLun          Pointer to the affected LUN
//! \param  pCommandState Pointer to the current command state
//! \return Operation result code
//------------------------------------------------------------------------------
unsigned char SBC_ProcessCommand(const S_usb         *pUsb,
                                 S_lun               *pLun,
                                 S_bot_command_state *pCommandState)
{
    unsigned char bResult = BOT_STATUS_INCOMPLETE;
    S_sbc_command *pCommand = (S_sbc_command *) pCommandState->sCbw.pCommand;

    // Identify command
    switch (pCommand->bOperationCode) {
    //---------------
    case SBC_READ_10:
    //---------------
        TRACE_DEBUG_M("Read(10) ");

        // Perform the Read10 command
        bResult = SBC_Read10(pUsb,
                             pLun,
                             pCommandState);
        break;

    //----------------
    case SBC_WRITE_10:
    //----------------
        TRACE_DEBUG_M("Write(10) ");

        // Perform the Write10 command
        bResult = SBC_Write10(pUsb,
                              pLun,
                              pCommandState);
        break;

    //---------------------
    case SBC_READ_CAPACITY_10:
    //---------------------
        TRACE_DEBUG_M("RdCapacity(10) ");

        // Perform the ReadCapacity command
        bResult = SBC_ReadCapacity10(pUsb, pLun, pCommandState);
        break;

    //---------------------
    case SBC_VERIFY_10:
    //---------------------
        TRACE_DEBUG_M("Verify(10) ");

        // Nothing to do
        bResult = BOT_STATUS_SUCCESS;
        break;

    //---------------
    case SBC_INQUIRY:
    //---------------
        TRACE_DEBUG_M("Inquiry ");

        // Process Inquiry command
        bResult = SBC_Inquiry(pUsb, pLun, pCommandState);
        break;

    //--------------------
    case SBC_MODE_SENSE_6:
    //--------------------
        TRACE_DEBUG_M("ModeSense(6) ");

        // Process ModeSense6 command
        bResult = SBC_ModeSense6(pUsb, pLun, pCommandState);
        break;

    //-----------------------
    case SBC_TEST_UNIT_READY:
    //-----------------------
        TRACE_DEBUG_M("TstUnitRdy ");

        // Process TestUnitReady command
        bResult = SBC_TestUnitReady(pLun);
        break;

    //---------------------
    case SBC_REQUEST_SENSE:
    //---------------------
        TRACE_DEBUG_M("ReqSense ");

        // Perform the RequestSense command
        bResult = SBC_RequestSense(pUsb, pLun, pCommandState);
        break;

    //------------------------------------
    case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
    //------------------------------------
        TRACE_DEBUG_M("PrevAllowRem ");

        // Nothing to do
        bResult = BOT_STATUS_SUCCESS;
        break;

    //------
    default:
    //------
        bResult = BOT_STATUS_PARAMETER;
    }

    return bResult;
}

⌨️ 快捷键说明

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