我正在编写嵌入式 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 函数,在此期间发生以下情况:
- 定义了用于发送 SCSI 命令的结构 sg_io_hdr_t。
- SCSI 命令'允许移除介质' (allowRmBlk) 已发出。
- 如果 allowRmBlk 成功,SCSI 命令'开始_停止' (startStop1Blk) 已发出。
- 如果成功,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 是处理弹射的正确命令。摘录如下: