简体   繁体   English

Linux:在可能不存在的USB设备上调用open()

[英]Linux: calling open() on a USB device which may not be present

I have a device attached to a Raspberry Pi. 我有一个连接到Raspberry Pi的设备。 The Pi is running ARCH Linux. Pi正在运行ARCH Linux。 The device communicates with the Pi via USB. 设备通过USB与Pi进行通信。 The device has to be switched on and off via a pulse and I have control, from the Pi, of a relay which causes this pulse. 必须通过脉冲打开和关闭设备,并且我可以通过Pi控制引起该脉冲的继电器。 However I can never be sure whether the device is initially on or off. 但是我永远不能确定设备最初是打开还是关闭。

In my code I toggle the relay and then speculatively call open() on the device (with flags O_RDWR | O_NOCTTY). 在我的代码中,我切换了中继,然后在设备上以推测方式调用open()(带有标志O_RDWR | O_NOCTTY)。 The problem is that if I am doing this when the device is off the open() call hangs. 问题是,如果我在设备关闭时执行此操作,则open()调用会挂起。 I have tried waiting for 1 second after the toggle, for things to settle, but that hasn't helped. 我试图在切换后等待1秒钟,以解决问题,但这并没有帮助。 I have tried calling stat() before the open() call but this always returns zero (so the device is there as far as stat() is concerned). 我尝试过在open()调用之前调用stat(),但是它总是返回零(因此就stat()而言,设备在那里)。 I have tried specifying O_NON_BLOCK in the open() call but that causes it to always fail. 我尝试在open()调用中指定O_NON_BLOCK,但这导致它始终失败。

Can anyone suggest either (a) what I'm doing wrong or (b) a reliable way forward? 有人可以建议(a)我做错了什么(b)可靠的前进方法吗?

If you can be sure that the device will eventually turn up, the blocking open() ("hangs") may actually be what you want! 如果您可以确定设备最终会启动,则阻塞open() (“挂起”)实际上可能就是您想要的! The call to open() will return, hopefully with success, when your device turns up. 当设备启动时,对open()的调用将返回,希望会成功。

The stat() call simply checks if the device special file is there. stat()调用仅检查设备专用文件是否存在。 It can't tell you if there is anything listening. 它无法告诉您是否正在监听。

One possible way forward, would be to open() with O_NONBLOCK in an exponential back-off loop. 一种可能的前进方式是在指数退避循环中使用O_NONBLOCK open()

Depending on what you mean with "communicates via USB", you may want to use libusb . 根据您对“通过USB通讯”的含义,可能要使用libusb If it's just a USB serial port, wrapping open() yourself is probably the easiest though. 如果只是USB串行端口,那么自己包装open()可能是最简单的。

You can be certain that the device has powered if it has USB enumerated. 如果已枚举USB,则可以确定该设备已通电。 You can use libudev to find the list of USB enumerated devices and check whether your device is on that list. 您可以使用libudev查找USB枚举设备的列表,并检查您的设备是否在该列表中。

The command line "lsusb" does that. 命令行“ lsusb”可以做到这一点。 So if you need an example of how to use libudev then you can read the lsusb source code ( https://github.com/gregkh/lsusb ). 因此,如果您需要有关如何使用libudev的示例,则可以阅读lsusb源代码( https://github.com/gregkh/lsusb )。

It's not clear what you have done to get a device file that survives disconnect. 尚不清楚您做了什么来获取在断开连接后仍然可以生存的设备文件。

The usual approach is to use hotplug + udev to create (and remove) the device symlinks, then the special file would only be there when the device is plugged in. 通常的方法是使用hotplug + udev创建(并删除)设备符号链接,然后,只有在插入设备后,特殊文件才会存在。

Courtesy of all the helpful people below, the quick answer was to include in my .rules file a "remove" action to go with the existing "add" action. 由下面所有有用的人员提供的帮助,快速的答案是在我的.rules文件中包括“删除”操作以及现有的“添加”操作。 So in the file where I have: 所以在我有的文件中:

ACTION=="add", ATTRS{interface}=="Pololu Orangutan X2 Serial Adapter", MODE="7777", SYMLINK+="OrangutanUSB"

...to give me a /dev/OrangutanUSB device, I have included a new line: ...为了给我一个/ dev / OrangutanUSB设备,我添加了一行:

ACTION=="remove", ATTRS{interface}=="Pololu Orangutan X2 Serial Adapter", MODE="7777", SYMLINK-="OrangutanUSB"

...to cause the operating system to remove the /dev/OrangutanUSB device when it has been powered off. ...导致操作系统在关闭/ dev / OrangutanUSB设备后将其删除。 This way the open() call fails correctly when the device has gone, rather than hanging. 这样,当设备用完而不是挂起时,open()调用将正确失败。

Ultimately, what I should do is check that the device is enumerated, rather than expecting open() to fail, but that can wait until I have the time. 最终,我应该做的是检查设备是否枚举,而不是期望open()失败,但是那要等到我有时间时再进行。 For now my code works as originally intended. 现在,我的代码可以按预期运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM