Reputation: 13035
I'm working with a firmware for a hardware that has an USB interface. When the device is connected to USB port, it enumerates as 2 classes: CDC & MSC.
For the MSC part, the device is user configurable in such a way that the device could be write-protected. So the user can choose whether the device is read-only or having read-write capability.
I'm using a pre written USB library that can enumerate the device with 2 interfaces. The part I'm struggling with is how can I let my firmware act as if the device is read-only.
The microcontroller is in the STM32L4 series. Most of the code is generated from STM32CubeMX software.
After some investigation, I've figured out that the SCSI Write10 along with SCSI Request Sense commands can check whether the MSC is write protected. Current implementation is as follows:
static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
{
USBD_CDC_MSC_HandleTypeDef *hmsc = pdev->pClassData;
uint32_t len;
if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
{
/* case 8 : Hi <> Do */
if ((hmsc->cbw.bmFlags & 0x80U) == 0x80U)
{
SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
return -1;
}
/* Check whether Media is ready */
if(((USBD_CDC_StorageItfTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
{
SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
return -1;
}
/* Check If media is write-protected */
if(((USBD_CDC_StorageItfTypeDef *)pdev->pUserData)->IsWriteProtected(lun) !=0 )
{
SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED);
return -1;
}
// Other code
}
I've debugged and checked that IsWriteProtected()
is correctly returning non zero value when the device is configured as write protected. The SCSI_SenseCode()
is pushing the error code in a circular list. Windows is supposed to send Request Sense SCSI command to retrieve the error code, but I've checked with breakpoint that Windows never sent this command!
int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd)
{
switch (cmd[0])
{
case SCSI_TEST_UNIT_READY:
SCSI_TestUnitReady(pdev, lun, cmd);
break;
case SCSI_REQUEST_SENSE:
SCSI_RequestSense (pdev, lun, cmd); // <<-- This is never reached
break;
case SCSI_INQUIRY:
SCSI_Inquiry(pdev, lun, cmd);
break;
....
If I configure the device in write-protect manner, the disk drive enumeration in PC takes a very long time and File Explorer is kept busy for a very long time. After the enumeration, I can open the disk drive and if I try to write to the disk, Windows reports that a disk I/O has occurred and write fails. I was expecting Windows to tell me that the disk is read-only.
If I configure the device as write-enabled, then the disk drive enumeration takes regular time as if I've plugged a regular pen drive.
Upvotes: 2
Views: 968