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