forked from mfulz_github/qmk_firmware
Added ability to write protect Mass Storage disk write operations from the host OS.
This commit is contained in:
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]);
|
||||||
|
|
||||||
@ -302,7 +316,7 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
|
|||||||
/* Adjust the given block address to the real media address based on the selected LUN */
|
/* Adjust the given block address to the real media address based on the selected LUN */
|
||||||
BlockAddress += ((uint32_t)MSInterfaceInfo->State.CommandBlock.LUN * LUN_MEDIA_BLOCKS);
|
BlockAddress += ((uint32_t)MSInterfaceInfo->State.CommandBlock.LUN * LUN_MEDIA_BLOCKS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
||||||
if (IsDataRead == DATA_READ)
|
if (IsDataRead == DATA_READ)
|
||||||
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||||
@ -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,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,9 +281,23 @@ 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:
|
||||||
|
@ -52,18 +52,21 @@
|
|||||||
|
|
||||||
/* Defines: */
|
/* Defines: */
|
||||||
/** Total number of bytes of the storage medium, comprised of one or more dataflash ICs. */
|
/** 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
|
/** 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.
|
* 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
|
/** 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.
|
* 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: */
|
/* 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]);
|
||||||
|
|
||||||
@ -298,7 +312,7 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
||||||
if (IsDataRead == DATA_READ)
|
if (IsDataRead == DATA_READ)
|
||||||
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||||
@ -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]);
|
||||||
|
|
||||||
@ -297,7 +311,7 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
||||||
if (IsDataRead == DATA_READ)
|
if (IsDataRead == DATA_READ)
|
||||||
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||||
@ -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]);
|
||||||
|
|
||||||
@ -297,7 +311,7 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
||||||
if (IsDataRead == DATA_READ)
|
if (IsDataRead == DATA_READ)
|
||||||
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||||
@ -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…
x
Reference in New Issue
Block a user