📄 sbc_methods.c
字号:
//------------------------------------------------------------------------------
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 + -