2

我正在使用具有 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 告诉我磁盘是只读的。

如果我将设备配置为允许写入,则磁盘驱动器枚举需要定期的时间,就好像我插入了一个普通的笔式驱动器一样。

  1. 为什么 Windows 从不发送 Request Sense SCSI 命令?
  2. 为什么由于 Write10 命令的写保护而返回 -1 时磁盘枚举需要很长时间?我需要磁盘在有或没有写保护的情况下快速枚举。
4

0 回答 0