📄 sbcmethods.c
字号:
//------------------------------------------------------------------------------
static unsigned char SBC_ModeSense6(MSDCommandState *commandState)
{
unsigned char result = MSDD_STATUS_INCOMPLETE;
unsigned char status;
MSDTransfer *transfer = &(commandState->transfer);
// Check if mode page is supported
if (((SBCCommand *) commandState->cbw.pCommand)->modeSense6.bPageCode
!= SBC_PAGE_RETURN_ALL) {
return MSDD_STATUS_PARAMETER;
}
// Initialize command state if needed
if (commandState->state == 0) {
commandState->state = SBC_STATE_WRITE;
}
// Check current command state
switch (commandState->state) {
//-------------------
case SBC_STATE_WRITE:
//-------------------
// Start transfer
status = MSDD_Write((void *) &modeParameterHeader6,
commandState->length,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
// Check operation result code
if (status != USBD_STATUS_SUCCESS) {
TRACE_WARNING(
"SPC_ModeSense6: Cannot start data transfer\n\r");
result = MSDD_STATUS_ERROR;
}
else {
// Proceed to next state
commandState->state = SBC_STATE_WAIT_WRITE;
}
break;
//------------------------
case SBC_STATE_WAIT_WRITE:
//------------------------
TRACE_INFO_WP("Wait ");
// Check semaphore value
if (transfer->semaphore > 0) {
// Take semaphore and terminate command
transfer->semaphore--;
if (transfer->status != USBD_STATUS_SUCCESS) {
TRACE_WARNING(
"SPC_ModeSense6: Data transfer failed\n\r");
result = MSDD_STATUS_ERROR;
}
else {
result = MSDD_STATUS_SUCCESS;
}
// Update length field
commandState->length -= transfer->transferred;
}
break;
}
return result;
}
//------------------------------------------------------------------------------
//! \brief Performs a TEST UNIT READY COMMAND command.
//! \param lun Pointer to the LUN affected by the command
//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
//! \see MSDLun
//------------------------------------------------------------------------------
static unsigned char SBC_TestUnitReady(MSDLun *lun)
{
unsigned char result = MSDD_STATUS_ERROR;
// Check current media state
switch(lun->media->state) {
//-------------------
case MED_STATE_READY:
//-------------------
// Nothing to do
TRACE_INFO_WP("Rdy ");
result = MSDD_STATUS_SUCCESS;
break;
//------------------
case MED_STATE_BUSY:
//------------------
TRACE_INFO_WP("Bsy ");
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_NOT_READY,
0,
0);
break;
//------
default:
//------
TRACE_INFO_WP("? ");
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_NOT_READY,
SBC_ASC_MEDIUM_NOT_PRESENT,
0);
break;
}
return result;
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Updates the sense data of a LUN with the given key and codes
//! \param requestSenseData Pointer to the sense data to update
//! \param senseKey Sense key
//! \param additionalSenseCode Additional sense code
//! \param additionalSenseCodeQualifier Additional sense code qualifier
//------------------------------------------------------------------------------
void SBC_UpdateSenseData(SBCRequestSenseData *requestSenseData,
unsigned char senseKey,
unsigned char additionalSenseCode,
unsigned char additionalSenseCodeQualifier)
{
requestSenseData->bSenseKey = senseKey;
requestSenseData->bAdditionalSenseCode = additionalSenseCode;
requestSenseData->bAdditionalSenseCodeQualifier
= additionalSenseCodeQualifier;
}
//------------------------------------------------------------------------------
//! \brief Return information about the transfer length and direction expected
//! by the device for a particular command.
//! \param command Pointer to a buffer holding the command to evaluate
//! \param length Expected length of the data transfer
//! \param type Expected direction of data transfer
//! \param lun Pointer to the LUN affected by the command
//------------------------------------------------------------------------------
unsigned char SBC_GetCommandInformation(void *command,
unsigned int *length,
unsigned char *type,
MSDLun *lun)
{
SBCCommand *sbcCommand = (SBCCommand *) command;
unsigned char isCommandSupported = 1;
// Identify command
switch (sbcCommand->bOperationCode) {
//---------------
case SBC_INQUIRY:
//---------------
(*type) = MSDD_DEVICE_TO_HOST;
// Allocation length is stored in big-endian format
(*length) = WORDB(sbcCommand->inquiry.pAllocationLength);
break;
//--------------------
case SBC_MODE_SENSE_6:
//--------------------
(*type) = MSDD_DEVICE_TO_HOST;
if (sbcCommand->modeSense6.bAllocationLength >
sizeof(SBCModeParameterHeader6)) {
*length = sizeof(SBCModeParameterHeader6);
}
else {
*length = sbcCommand->modeSense6.bAllocationLength;
}
// Only "return all pages" command is supported
if (sbcCommand->modeSense6.bPageCode != SBC_PAGE_RETURN_ALL) {
// Unsupported page
TRACE_WARNING(
"SBC_GetCommandInformation: Page code not supported(0x%02X)\n\r",
sbcCommand->modeSense6.bPageCode);
isCommandSupported = 0;
(*length) = 0;
}
break;
//------------------------------------
case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
//------------------------------------
(*type) = MSDD_NO_TRANSFER;
break;
//---------------------
case SBC_REQUEST_SENSE:
//---------------------
(*type) = MSDD_DEVICE_TO_HOST;
(*length) = sbcCommand->requestSense.bAllocationLength;
break;
//-----------------------
case SBC_TEST_UNIT_READY:
//-----------------------
(*type) = MSDD_NO_TRANSFER;
break;
//---------------------
case SBC_READ_CAPACITY_10:
//---------------------
(*type) = MSDD_DEVICE_TO_HOST;
(*length) = sizeof(SBCReadCapacity10Data);
break;
//---------------
case SBC_READ_10:
//---------------
(*type) = MSDD_DEVICE_TO_HOST;
(*length) = WORDB(sbcCommand->read10.pTransferLength)
* lun->blockSize;
break;
//----------------
case SBC_WRITE_10:
//----------------
(*type) = MSDD_HOST_TO_DEVICE;
(*length) = WORDB(sbcCommand->write10.pTransferLength)
* lun->blockSize;
break;
//-----------------
case SBC_VERIFY_10:
//-----------------
(*type) = MSDD_NO_TRANSFER;
break;
//------
default:
//------
isCommandSupported = 0;
}
// If length is 0, no transfer is expected
if ((*length) == 0) {
(*type) = MSDD_NO_TRANSFER;
}
return isCommandSupported;
}
//------------------------------------------------------------------------------
//! \brief Processes a SBC command by dispatching it to a subfunction.
//! \param lun Pointer to the affected LUN
//! \param commandState Pointer to the current command state
//! \return Operation result code
//------------------------------------------------------------------------------
unsigned char SBC_ProcessCommand(MSDLun *lun,
MSDCommandState *commandState)
{
unsigned char result = MSDD_STATUS_INCOMPLETE;
SBCCommand *command = (SBCCommand *) commandState->cbw.pCommand;
// Identify command
switch (command->bOperationCode) {
//---------------
case SBC_READ_10:
//---------------
TRACE_INFO_WP("Read(10) ");
// Perform the Read10 command
result = SBC_Read10(lun, commandState);
break;
//----------------
case SBC_WRITE_10:
//----------------
TRACE_INFO_WP("Write(10) ");
// Perform the Write10 command
result = SBC_Write10(lun, commandState);
break;
//---------------------
case SBC_READ_CAPACITY_10:
//---------------------
TRACE_INFO_WP("RdCapacity(10) ");
// Perform the ReadCapacity command
result = SBC_ReadCapacity10(lun, commandState);
break;
//---------------------
case SBC_VERIFY_10:
//---------------------
TRACE_INFO_WP("Verify(10) ");
// Flush media
MED_Flush(lun->media);
result = MSDD_STATUS_SUCCESS;
break;
//---------------
case SBC_INQUIRY:
//---------------
TRACE_INFO_WP("Inquiry ");
// Process Inquiry command
result = SBC_Inquiry(lun, commandState);
break;
//--------------------
case SBC_MODE_SENSE_6:
//--------------------
TRACE_INFO_WP("ModeSense(6) ");
// Process ModeSense6 command
result = SBC_ModeSense6(commandState);
break;
//-----------------------
case SBC_TEST_UNIT_READY:
//-----------------------
TRACE_INFO_WP("TstUnitRdy ");
// Process TestUnitReady command
//MED_Flush(lun->media);
result = SBC_TestUnitReady(lun);
break;
//---------------------
case SBC_REQUEST_SENSE:
//---------------------
TRACE_INFO_WP("ReqSense ");
// Perform the RequestSense command
result = SBC_RequestSense(lun, commandState);
break;
//------------------------------------
case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
//------------------------------------
TRACE_INFO_WP("PrevAllowRem ");
// Nothing to do
result = MSDD_STATUS_SUCCESS;
break;
//------
default:
//------
result = MSDD_STATUS_PARAMETER;
}
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -