aboutsummaryrefslogtreecommitdiffstats
path: root/Projects
diff options
context:
space:
mode:
authorDean Camera <dean@fourwalledcubicle.com>2010-11-26 04:16:47 +0000
committerDean Camera <dean@fourwalledcubicle.com>2010-11-26 04:16:47 +0000
commit9f7883fa2b78fd7907162987fc65b71d3c6b19fa (patch)
treeee3e4fc2497bce62e965054fe6957a7b239839ac /Projects
parentb634ec50a0646a1575d89add8ac851f7d8a66332 (diff)
downloadlufa-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')
-rw-r--r--Projects/Incomplete/StandaloneProgrammer/Lib/DataflashManager.h9
-rw-r--r--Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c39
-rw-r--r--Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h1
-rw-r--r--Projects/TempDataLogger/Lib/SCSI.c37
-rw-r--r--Projects/TempDataLogger/Lib/SCSI.h1
-rw-r--r--Projects/TempDataLogger/TempDataLogger.h3
-rw-r--r--Projects/Webserver/Lib/DataflashManager.h3
-rw-r--r--Projects/Webserver/Lib/SCSI.c37
-rw-r--r--Projects/Webserver/Lib/SCSI.h1
9 files changed, 124 insertions, 7 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
diff --git a/Projects/TempDataLogger/Lib/SCSI.c b/Projects/TempDataLogger/Lib/SCSI.c
index b1e88dc70..6a51c74e8 100644
--- a/Projects/TempDataLogger/Lib/SCSI.c
+++ b/Projects/TempDataLogger/Lib/SCSI.c
@@ -113,6 +113,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:
@@ -281,6 +284,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]);
@@ -297,7 +311,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,3 +324,24 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
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;
+}
diff --git a/Projects/TempDataLogger/Lib/SCSI.h b/Projects/TempDataLogger/Lib/SCSI.h
index 27eab5eb7..e9aa4f074 100644
--- a/Projects/TempDataLogger/Lib/SCSI.h
+++ b/Projects/TempDataLogger/Lib/SCSI.h
@@ -81,6 +81,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
diff --git a/Projects/TempDataLogger/TempDataLogger.h b/Projects/TempDataLogger/TempDataLogger.h
index f81a57410..39aa43c69 100644
--- a/Projects/TempDataLogger/TempDataLogger.h
+++ b/Projects/TempDataLogger/TempDataLogger.h
@@ -78,6 +78,9 @@
/** Default log interval when the EEPROM is blank, in 500ms ticks. */
#define DEFAULT_LOG_INTERVAL 20
+ /** Indicates if the disk is write protected or not. */
+ #define DISK_READ_ONLY false
+
/* Type Defines: */
typedef struct
{
diff --git a/Projects/Webserver/Lib/DataflashManager.h b/Projects/Webserver/Lib/DataflashManager.h
index acbeba54c..a53c88776 100644
--- a/Projects/Webserver/Lib/DataflashManager.h
+++ b/Projects/Webserver/Lib/DataflashManager.h
@@ -64,6 +64,9 @@
*/
#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: */
void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const uint32_t BlockAddress,
diff --git a/Projects/Webserver/Lib/SCSI.c b/Projects/Webserver/Lib/SCSI.c
index b1e88dc70..6a51c74e8 100644
--- a/Projects/Webserver/Lib/SCSI.c
+++ b/Projects/Webserver/Lib/SCSI.c
@@ -113,6 +113,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:
@@ -281,6 +284,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]);
@@ -297,7 +311,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,3 +324,24 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
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;
+}
diff --git a/Projects/Webserver/Lib/SCSI.h b/Projects/Webserver/Lib/SCSI.h
index 8eae210f1..8360234b5 100644
--- a/Projects/Webserver/Lib/SCSI.h
+++ b/Projects/Webserver/Lib/SCSI.h
@@ -80,6 +80,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