/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches * to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns * a command failure due to a ILLEGAL REQUEST. * * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with * * \return Boolean \c true if the command completed successfully, \c false otherwise */ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { bool CommandSuccess = false; /* Run the appropriate SCSI command hander function based on the passed command */ switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0]) { case SCSI_CMD_INQUIRY: CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo); break; case SCSI_CMD_REQUEST_SENSE: CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo); break; case SCSI_CMD_READ_CAPACITY_10: CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo); break; case SCSI_CMD_WRITE_10: CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); break; case SCSI_CMD_READ_10: CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); break; case SCSI_CMD_MODE_SENSE_6: CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo); break; case SCSI_CMD_START_STOP_UNIT: #if !defined(NO_APP_START_ON_EJECT) /* If the user ejected the volume, signal bootloader exit at next opportunity. */ RunBootloader = ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[4] & 0x03) != 0x02); #endif case SCSI_CMD_SEND_DIAGNOSTIC: case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_VERIFY_10: /* These commands should just succeed, no handling required */ CommandSuccess = true; MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; break; default: /* Update the SENSE key to reflect the invalid command */ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_ASENSE_INVALID_COMMAND, SCSI_ASENSEQ_NO_QUALIFIER); break; } /* Check if command was successfully processed */ if (CommandSuccess) { SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER); return true; } return false; }
/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches * to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns * a command failure due to a ILLEGAL REQUEST. * * \return Boolean true if the command completed successfully, false otherwise */ bool SCSI_DecodeSCSICommand(void) { bool CommandSuccess = false; /* Run the appropriate SCSI command hander function based on the passed command */ switch (CommandBlock.SCSICommandData[0]) { case SCSI_CMD_INQUIRY: CommandSuccess = SCSI_Command_Inquiry(); break; case SCSI_CMD_REQUEST_SENSE: CommandSuccess = SCSI_Command_Request_Sense(); break; case SCSI_CMD_READ_CAPACITY_10: CommandSuccess = SCSI_Command_Read_Capacity_10(); break; case SCSI_CMD_SEND_DIAGNOSTIC: CommandSuccess = SCSI_Command_Send_Diagnostic(); break; case SCSI_CMD_WRITE_10: CommandSuccess = SCSI_Command_ReadWrite_10(DATA_WRITE); break; case SCSI_CMD_READ_10: CommandSuccess = SCSI_Command_ReadWrite_10(DATA_READ); break; case SCSI_CMD_MODE_SENSE_6: CommandSuccess = SCSI_Command_ModeSense_6(); break; case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_VERIFY_10: /* These commands should just succeed, no handling required */ CommandSuccess = true; CommandBlock.DataTransferLength = 0; break; default: /* Update the SENSE key to reflect the invalid command */ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_ASENSE_INVALID_COMMAND, SCSI_ASENSEQ_NO_QUALIFIER); break; } /* Check if command was successfully processed */ if (CommandSuccess) { SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER); return true; } return false; }