diff options
author | Dean Camera <dean@fourwalledcubicle.com> | 2010-11-26 04:16:47 +0000 |
---|---|---|
committer | Dean Camera <dean@fourwalledcubicle.com> | 2010-11-26 04:16:47 +0000 |
commit | 9f7883fa2b78fd7907162987fc65b71d3c6b19fa (patch) | |
tree | ee3e4fc2497bce62e965054fe6957a7b239839ac /Projects/Incomplete | |
parent | b634ec50a0646a1575d89add8ac851f7d8a66332 (diff) | |
download | lufa-9f7883fa2b78fd7907162987fc65b71d3c6b19fa.tar.gz lufa-9f7883fa2b78fd7907162987fc65b71d3c6b19fa.tar.bz2 lufa-9f7883fa2b78fd7907162987fc65b71d3c6b19fa.zip |
Added ability to write protect Mass Storage disk write operations from the host OS.
Diffstat (limited to 'Projects/Incomplete')
3 files changed, 44 insertions, 5 deletions
diff --git a/Projects/Incomplete/StandaloneProgrammer/Lib/DataflashManager.h b/Projects/Incomplete/StandaloneProgrammer/Lib/DataflashManager.h index 9bd59d7e0..b963fa22b 100644 --- a/Projects/Incomplete/StandaloneProgrammer/Lib/DataflashManager.h +++ b/Projects/Incomplete/StandaloneProgrammer/Lib/DataflashManager.h @@ -52,18 +52,21 @@ /* Defines: */ /** Total number of bytes of the storage medium, comprised of one or more dataflash ICs. */ - #define VIRTUAL_MEMORY_BYTES ((uint32_t)DATAFLASH_PAGES * DATAFLASH_PAGE_SIZE * DATAFLASH_TOTALCHIPS) + #define VIRTUAL_MEMORY_BYTES ((uint32_t)DATAFLASH_PAGES * DATAFLASH_PAGE_SIZE * DATAFLASH_TOTALCHIPS) /** Block size of the device. This is kept at 512 to remain compatible with the OS despite the underlying * storage media (Dataflash) using a different native block size. Do not change this value. */ - #define VIRTUAL_MEMORY_BLOCK_SIZE 512 + #define VIRTUAL_MEMORY_BLOCK_SIZE 512 /** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. Do not * change this value; change VIRTUAL_MEMORY_BYTES instead to alter the media size. */ - #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: */ #if defined(USB_CAN_BE_DEVICE) void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, diff --git a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c index 7b2a8fa83..a23e21109 100644 --- a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c +++ b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c @@ -114,6 +114,9 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) 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_TEST_UNIT_READY: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: 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; 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) */ BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); @@ -298,7 +312,7 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa return false; } - + /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */ if (IsDataRead == DATA_READ) DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks); @@ -310,5 +324,26 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa 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
\ No newline at end of file diff --git a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h index 36ad66d90..34ed85232 100644 --- a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h +++ b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h @@ -82,6 +82,7 @@ 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, const bool IsDataRead); + static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); #endif #endif |