我正在使用具有 USB 接口的硬件的固件。当设备连接到 USB 端口时,它枚举为 2 个类:CDC 和 MSC。
对于 MSC 部分,该设备是用户可配置的,这样该设备可以被写保护。因此用户可以选择设备是只读的还是具有读写能力的。
我正在使用一个预先编写的 USB 库,它可以枚举具有 2 个接口的设备。我正在努力解决的部分是如何让我的固件像设备是只读的一样工作。
微控制器属于 STM32L4 系列。大部分代码是从 STM32CubeMX 软件生成的。
经过一番调查,我发现 SCSI Write10 和 SCSI Request Sense 命令可以检查 MSC 是否被写保护。目前的实现如下:
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
}
我已经调试并检查了IsWriteProtected()
当设备配置为写保护时是否正确返回非零值。正在将SCSI_SenseCode()
错误代码推送到循环列表中。Windows 应该发送 Request Sense SCSI 命令来检索错误代码,但我已经用断点检查过 Windows 从未发送过这个命令!
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;
....
如果我以写保护的方式配置设备,PC中的磁盘驱动器枚举需要很长时间,并且文件资源管理器会长时间保持忙碌状态。枚举完成后,我可以打开磁盘驱动器,如果我尝试写入磁盘,Windows 会报告发生磁盘 I/O 并且写入失败。我期待 Windows 告诉我磁盘是只读的。
如果我将设备配置为允许写入,则磁盘驱动器枚举需要定期的时间,就好像我插入了一个普通的笔式驱动器一样。
- 为什么 Windows 从不发送 Request Sense SCSI 命令?
- 为什么由于 Write10 命令的写保护而返回 -1 时磁盘枚举需要很长时间?我需要磁盘在有或没有写保护的情况下快速枚举。