/*
LUFA Library
- Copyright (C) Dean Camera, 2013.
+ Copyright (C) Dean Camera, 2015.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
- Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2015 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
- * \return Boolean true if the command completed successfully, false otherwise
+ * \return Boolean \c true if the command completed successfully, \c false otherwise
*/
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
case SCSI_CMD_READ_CAPACITY_10:
CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
break;
- case SCSI_CMD_SEND_DIAGNOSTIC:
- CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
- break;
case SCSI_CMD_WRITE_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
break;
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:
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
- * \return Boolean true if the command completed successfully, false otherwise.
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
- * \return Boolean true if the command completed successfully, false otherwise.
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
- * \return Boolean true if the command completed successfully, false otherwise.
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
- uint32_t LastBlockAddressInLUN = (LUN_MEDIA_BLOCKS - 1);
- uint32_t MediaBlockSize = SECTOR_SIZE_BYTES;
-
- Endpoint_Write_Stream_BE(&LastBlockAddressInLUN, sizeof(LastBlockAddressInLUN), NULL);
- Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NULL);
+ Endpoint_Write_32_BE(LUN_MEDIA_BLOCKS - 1);
+ Endpoint_Write_32_BE(SECTOR_SIZE_BYTES);
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
return true;
}
-/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
- * board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is
- * supported.
- *
- * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
- *
- * \return Boolean true if the command completed successfully, false otherwise.
- */
-static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
-{
- /* Check to see if the SELF TEST bit is not set */
- if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
- {
- /* Only self-test supported - update SENSE key and fail the command */
- SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
- SCSI_ASENSE_INVALID_FIELD_IN_CDB,
- SCSI_ASENSEQ_NO_QUALIFIER);
-
- return false;
- }
-
- /* Succeed the command and update the bytes transferred counter */
- MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
-
- return true;
-}
-
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
* and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual
* reading and writing of the data.
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
* \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
*
- * \return Boolean true if the command completed successfully, false otherwise.
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead)
{
- uint32_t BlockAddress;
+ uint16_t BlockAddress;
uint16_t TotalBlocks;
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
}
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
- if (IsDataRead == DATA_READ)
- VirtualFAT_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
- else
- VirtualFAT_WriteBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
+ for (uint16_t i = 0; i < TotalBlocks; i++)
+ {
+ if (IsDataRead == DATA_READ)
+ VirtualFAT_ReadBlock(BlockAddress + i);
+ else
+ VirtualFAT_WriteBlock(BlockAddress + i);
+ }
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * SECTOR_SIZE_BYTES);
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
- * \return Boolean true if the command completed successfully, false otherwise.
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{