使用“eject -s /dev/sdx”似乎通过 USB/MSC 连接发送的不仅仅是 SCSI 弹出命令

使用“eject -s /dev/sdx”似乎通过 USB/MSC 连接发送的不仅仅是 SCSI 弹出命令

我正在编写嵌入式 STMicro.com STM32 处理器代码并使用 STMicro.com 的 USB 驱动程序。STM32 处理器上没有运行其他软件。这有点不寻常,但我们已经设法将 STM32 处理器配置为根据命令从 USB/CDC 切换到 USB/MSC 设备。问题是找到一种方法来从 USB/MSC 切换回 USB/CDC。

为了解决这个问题,我相信我可以使用 USB 电缆将基于 STM32 的设备连接到 Ubuntu 计算机并发送 SCSI Eject 命令。但是这并不总是有效。我发现我必须至少发送两次 SCSI Eject 命令。有时,在我的 STM32 代码看到 1 个 Eject 事件之前,我最多发送了 5 次。为什么?

为了验证 STM32 代码是否有效,我将基于 STM32 的设备连接到 Windows 10 计算机。使用 Windows 文件资源管理器中的弹出功能,我能够看到 Windows 10 计算机发送到基于 STM32 的设备的每个弹出事件。因此,STM32 代码和 STMicro.com USB 驱动程序似乎可以正常工作(适用于 Windows 10)。

进一步深入了解...

当基于 STM32 的设备连接到 Ubuntu 计算机时,我运行了 STM32 处理器调试器。在调试 STMicro.com 的 USB 驱动程序时,我发现可以看到所有 USB/MSC SCSI Eject 命令。但是,在我的代码看到 EJECT 状态之前,驱动程序会用其他 USB/MSC 状态(例如 LOCK 和 UNLOCK)覆盖弹出标志。以下是 STMicro.com 代码的一段,可以在 github.com 上找到:

if ((params[4] & 0x3U) == 0x1U) /* START=1 */
{
hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;
}
else if ((params[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
{
hmsc->scsi_medium_state = SCSI_MEDIUM_EJECTED;
}
else if ((params[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
{
hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;
}
else
{
/* .. */
}

在以下情况下 Ubuntu 是否不仅仅发送 SCSI 弹出命令:

eject -s /dev/sdx

...命令被使用了吗?有没有办法只通过 Ubuntu 的 USB/MSC 连接发送 SCSI Eject 命令?

答案1

jet 发送“ALLOW MEDIUM REMOVAL”然后发送“START STOP”SCSI 命令来弹出设备。

我看过了jet 的源代码在 'eject -s' 期间发生的是调用 jet_scsi 函数,在此期间发生以下情况:

  1. 定义了用于发送 SCSI 命令的结构 sg_io_hdr_t。
  2. SCSI 命令'允许移除介质' (allowRmBlk) 已发出。
  3. 如果 allowRmBlk 成功,SCSI 命令'开始_停止' (startStop1Blk) 已发出。
  4. 如果成功,SCSI 命令'开始_停止' (startStop2Blk) 再次发出,但带有不同的选项。

allowRmBlk、startStop1Blk 和 startStop2Blk 是实际源代码中使用的,但我还在代码中展示了与它们一起使用的实际命令(如它们所定义) - startStop1Blk 和 startStop2Blk 之间的区别是:

unsigned char startStop1Blk[6] = {START_STOP, 0, 0, 0, 1, 0};
unsigned char startStop2Blk[6] = {START_STOP, 0, 0, 0, 2, 0};

我不确定您所说的“仅发送 SCSI EJECT 命令”是什么意思,但假设您的意思是负责弹出的 SCSI 命令,那么弹出只会发出它们。

根据Seagate 的 SCSI 命令参考,START STOP UNIT 是处理弹射的正确命令。摘录如下:

SCSI 命令参考摘录

相关内容