Added ability to write protect Mass Storage disk write operations from the host OS.

pull/1469/head
Dean Camera 14 years ago
parent b634ec50a0
commit 9f7883fa2b

@ -113,6 +113,9 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
case SCSI_CMD_READ_10: case SCSI_CMD_READ_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
break; break;
case SCSI_CMD_MODE_SENSE_6:
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
break;
case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10: case SCSI_CMD_VERIFY_10:
@ -281,6 +284,17 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
uint32_t BlockAddress; uint32_t BlockAddress;
uint16_t TotalBlocks; uint16_t TotalBlocks;
/* Check if the disk is write protected or not */
if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT,
SCSI_ASENSE_WRITE_PROTECTED,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */ /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
@ -315,3 +329,24 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
return true; return true;
} }
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
* the SCSI device, as well as the device's Write Protect status.
*
* \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_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
/* Send an empty header response with the Write Protect flag status */
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(DISK_READ_ONLY ? 0x80 : 0x00);
Endpoint_Write_Byte(0x00);
Endpoint_ClearIN();
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
return true;
}

@ -81,6 +81,7 @@
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead); const bool IsDataRead);
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
#endif #endif
#endif #endif

@ -74,6 +74,9 @@
/** Blocks in each LUN, calculated from the total capacity divided by the total number of Logical Units in the device. */ /** Blocks in each LUN, calculated from the total capacity divided by the total number of Logical Units in the device. */
#define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS) #define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS)
/** Indicates if the disk is write protected or not. */
#define DISK_READ_ONLY false
/* Function Prototypes: */ /* Function Prototypes: */
void SetupHardware(void); void SetupHardware(void);

@ -63,12 +63,6 @@
/** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. */ /** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. */
#define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE) #define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)
/** Total number of logical drives within the device - must be non-zero. */
#define TOTAL_LUNS 1
/** Blocks in each LUN, calculated from the total capacity divided by the total number of Logical Units in the device. */
#define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS)
/* Function Prototypes: */ /* Function Prototypes: */
void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const uint32_t BlockAddress, const uint32_t BlockAddress,

@ -113,6 +113,9 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
case SCSI_CMD_READ_10: case SCSI_CMD_READ_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
break; break;
case SCSI_CMD_MODE_SENSE_6:
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
break;
case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10: case SCSI_CMD_VERIFY_10:
@ -281,6 +284,17 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
uint32_t BlockAddress; uint32_t BlockAddress;
uint16_t TotalBlocks; uint16_t TotalBlocks;
/* Check if the disk is write protected or not */
if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT,
SCSI_ASENSE_WRITE_PROTECTED,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */ /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
@ -315,3 +329,24 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
return true; return true;
} }
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
* the SCSI device, as well as the device's Write Protect status.
*
* \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_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
/* Send an empty header response with the Write Protect flag status */
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(DISK_READ_ONLY ? 0x80 : 0x00);
Endpoint_Write_Byte(0x00);
Endpoint_ClearIN();
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
return true;
}

@ -81,6 +81,7 @@
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead); const bool IsDataRead);
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
#endif #endif
#endif #endif

@ -73,6 +73,15 @@
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */ /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
#define LEDMASK_USB_BUSY LEDS_LED2 #define LEDMASK_USB_BUSY LEDS_LED2
/** Total number of logical drives within the device - must be non-zero. */
#define TOTAL_LUNS 1
/** Blocks in each LUN, calculated from the total capacity divided by the total number of Logical Units in the device. */
#define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS)
/** Indicates if the disk is write protected or not. */
#define DISK_READ_ONLY false
/* Function Prototypes: */ /* Function Prototypes: */
void SetupHardware(void); void SetupHardware(void);

@ -111,6 +111,9 @@ bool SCSI_DecodeSCSICommand(void)
case SCSI_CMD_READ_10: case SCSI_CMD_READ_10:
CommandSuccess = SCSI_Command_ReadWrite_10(DATA_READ); CommandSuccess = SCSI_Command_ReadWrite_10(DATA_READ);
break; break;
case SCSI_CMD_MODE_SENSE_6:
CommandSuccess = SCSI_Command_ModeSense_6();
break;
case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10: case SCSI_CMD_VERIFY_10:
@ -278,8 +281,22 @@ static bool SCSI_Command_Send_Diagnostic(void)
*/ */
static bool SCSI_Command_ReadWrite_10(const bool IsDataRead) static bool SCSI_Command_ReadWrite_10(const bool IsDataRead)
{ {
uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&CommandBlock.SCSICommandData[2]); uint32_t BlockAddress;
uint16_t TotalBlocks = SwapEndian_16(*(uint16_t*)&CommandBlock.SCSICommandData[7]); uint16_t TotalBlocks;
/* Check if the disk is write protected or not */
if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT,
SCSI_ASENSE_WRITE_PROTECTED,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
BlockAddress = SwapEndian_32(*(uint32_t*)&CommandBlock.SCSICommandData[2]);
TotalBlocks = SwapEndian_16(*(uint16_t*)&CommandBlock.SCSICommandData[7]);
/* Check if the block address is outside the maximum allowable value for the LUN */ /* Check if the block address is outside the maximum allowable value for the LUN */
if (BlockAddress >= LUN_MEDIA_BLOCKS) if (BlockAddress >= LUN_MEDIA_BLOCKS)
@ -309,3 +326,22 @@ static bool SCSI_Command_ReadWrite_10(const bool IsDataRead)
return true; return true;
} }
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
* the SCSI device, as well as the device's Write Protect status.
*
* \return Boolean true if the command completed successfully, false otherwise.
*/
static bool SCSI_Command_ModeSense_6(void)
{
/* Send an empty header response with the Write Protect flag status */
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(DISK_READ_ONLY ? 0x80 : 0x00);
Endpoint_Write_Byte(0x00);
Endpoint_ClearIN();
/* Update the bytes transferred counter and succeed the command */
CommandBlock.DataTransferLength -= 4;
return true;
}

@ -143,6 +143,7 @@
static bool SCSI_Command_Read_Capacity_10(void); static bool SCSI_Command_Read_Capacity_10(void);
static bool SCSI_Command_Send_Diagnostic(void); static bool SCSI_Command_Send_Diagnostic(void);
static bool SCSI_Command_ReadWrite_10(const bool IsDataRead); static bool SCSI_Command_ReadWrite_10(const bool IsDataRead);
static bool SCSI_Command_ModeSense_6(void);
#endif #endif
#endif #endif

@ -68,6 +68,9 @@
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */ /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
#define LEDMASK_USB_BUSY LEDS_LED2 #define LEDMASK_USB_BUSY LEDS_LED2
/** Indicates if the disk is write protected or not. */
#define DISK_READ_ONLY false
/* Global Variables: */ /* Global Variables: */
extern MS_CommandBlockWrapper_t CommandBlock; extern MS_CommandBlockWrapper_t CommandBlock;
extern MS_CommandStatusWrapper_t CommandStatus; extern MS_CommandStatusWrapper_t CommandStatus;

@ -12,6 +12,7 @@
* - None * - None
* - Library Applications: * - Library Applications:
* - Added new incomplete MIDIToneGenerator project * - Added new incomplete MIDIToneGenerator project
* - Added ability to write protect Mass Storage disk write operations from the host OS
* *
* <b>Changed:</b> * <b>Changed:</b>
* - Core: * - Core:

@ -64,6 +64,9 @@
*/ */
#define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE) #define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)
/** Indicates if the disk is write protected or not. */
#define DISK_READ_ONLY false
/* Function Prototypes: */ /* Function Prototypes: */
#if defined(USB_CAN_BE_DEVICE) #if defined(USB_CAN_BE_DEVICE)
void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,

@ -114,6 +114,9 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
case SCSI_CMD_READ_10: case SCSI_CMD_READ_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
break; break;
case SCSI_CMD_MODE_SENSE_6:
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
break;
case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10: case SCSI_CMD_VERIFY_10:
@ -282,6 +285,17 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
uint32_t BlockAddress; uint32_t BlockAddress;
uint16_t TotalBlocks; uint16_t TotalBlocks;
/* Check if the disk is write protected or not */
if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT,
SCSI_ASENSE_WRITE_PROTECTED,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */ /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
@ -310,5 +324,26 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
return true; return true;
} }
#endif
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
* the SCSI device, as well as the device's Write Protect status.
*
* \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_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
/* Send an empty header response with the Write Protect flag status */
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(DISK_READ_ONLY ? 0x80 : 0x00);
Endpoint_Write_Byte(0x00);
Endpoint_ClearIN();
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
return true;
}
#endif

@ -82,6 +82,7 @@
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead); const bool IsDataRead);
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
#endif #endif
#endif #endif

@ -113,6 +113,9 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
case SCSI_CMD_READ_10: case SCSI_CMD_READ_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
break; break;
case SCSI_CMD_MODE_SENSE_6:
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
break;
case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10: case SCSI_CMD_VERIFY_10:
@ -281,6 +284,17 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
uint32_t BlockAddress; uint32_t BlockAddress;
uint16_t TotalBlocks; uint16_t TotalBlocks;
/* Check if the disk is write protected or not */
if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT,
SCSI_ASENSE_WRITE_PROTECTED,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */ /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
@ -310,3 +324,24 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
return true; return true;
} }
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
* the SCSI device, as well as the device's Write Protect status.
*
* \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_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
/* Send an empty header response with the Write Protect flag status */
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(DISK_READ_ONLY ? 0x80 : 0x00);
Endpoint_Write_Byte(0x00);
Endpoint_ClearIN();
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
return true;
}

@ -81,6 +81,7 @@
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead); const bool IsDataRead);
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
#endif #endif
#endif #endif

@ -78,6 +78,9 @@
/** Default log interval when the EEPROM is blank, in 500ms ticks. */ /** Default log interval when the EEPROM is blank, in 500ms ticks. */
#define DEFAULT_LOG_INTERVAL 20 #define DEFAULT_LOG_INTERVAL 20
/** Indicates if the disk is write protected or not. */
#define DISK_READ_ONLY false
/* Type Defines: */ /* Type Defines: */
typedef struct typedef struct
{ {

@ -64,6 +64,9 @@
*/ */
#define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE) #define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)
/** Indicates if the disk is write protected or not. */
#define DISK_READ_ONLY false
/* Function Prototypes: */ /* Function Prototypes: */
void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const uint32_t BlockAddress, const uint32_t BlockAddress,

@ -113,6 +113,9 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
case SCSI_CMD_READ_10: case SCSI_CMD_READ_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
break; break;
case SCSI_CMD_MODE_SENSE_6:
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
break;
case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10: case SCSI_CMD_VERIFY_10:
@ -281,6 +284,17 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
uint32_t BlockAddress; uint32_t BlockAddress;
uint16_t TotalBlocks; uint16_t TotalBlocks;
/* Check if the disk is write protected or not */
if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT,
SCSI_ASENSE_WRITE_PROTECTED,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */ /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
@ -310,3 +324,24 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
return true; return true;
} }
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
* the SCSI device, as well as the device's Write Protect status.
*
* \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_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
/* Send an empty header response with the Write Protect flag status */
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(0x00);
Endpoint_Write_Byte(DISK_READ_ONLY ? 0x80 : 0x00);
Endpoint_Write_Byte(0x00);
Endpoint_ClearIN();
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
return true;
}

@ -80,6 +80,7 @@
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead); const bool IsDataRead);
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
#endif #endif
#endif #endif

Loading…
Cancel
Save