I have a device attached to a Raspberry Pi. The Pi is running ARCH Linux. The device communicates with the Pi via USB. 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. 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). The problem is that if I am doing this when the device is off the open() call hangs. I have tried waiting for 1 second after the toggle, for things to settle, but that hasn't helped. 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). I have tried specifying O_NON_BLOCK in the open() call but that causes it to always fail.
Can anyone suggest either (a) what I'm doing wrong or (b) a reliable way forward?
You can be certain that the device has powered if it has USB enumerated. You can use libudev to find the list of USB enumerated devices and check whether your device is on that list.
The command line "lsusb" does that. So if you need an example of how to use libudev then you can read the lsusb source code (https://github.com/gregkh/lsusb).
If you can be sure that the device will eventually turn up, the blocking open() ("hangs") may actually be what you want! The call to open() will return, hopefully with success, when your device turns up.
The stat() call simply checks if the device special file is there. 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.
Depending on what you mean with "communicates via USB", you may want to use libusb. If it's just a USB serial port, wrapping open() yourself is probably the easiest though.
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.
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. 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:
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. This way the open() call fails correctly when the device has gone, rather than hanging.
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. For now my code works as originally intended.
Related
I'm using linux kernel 3.3 (I cannot upgrade my kernel, sorry!) and am trying to use the wpa_cli utility to monitor the status of my WiFi connection. I'm using an Edimax WiFi dongle to connect to a wireless access point.
I expect to see something like this:
# wpa_cli status
Selected interface 'wlan0'
wpa_state=SCANNING
ip_address=XXX.XXX.XXX.XXX
address=XX:XX:XX:XX:XX:XX
Or the same thing but with wpa_state=COMPLETED, depending upon my connection status.
Parsing the this text output allows me to see if my wireless connection is active or scanning. However, I have noticed that after powering off my access point wpa_state=COMPLETED is still being returned. Using the command:
# iwlist wlan0 scanning
Forces a scan and wpa_state will occasionally be correct, but usually (99%) not.
Here is my /etc/wpa_supplicant.conf:
ctrl_interface=/var/run/wpa_supplicant
ap_scan=1
country=US
network={
ssid="myssid"
psk="mypsk"
key_mgmt=WPA-PSK
eap=
}
After some investigation, I believe something weird is happening causing the kernel to return a cached version of the AP list. I am using the RTL8192cu driver. I've already looked at this issue, and it is not the same as mine.
My belief is that the issue may be somewhere in the kernel. In the file net/mac80211/scan.c, at line 214 in function ieee80211_scan_rx, I see a bssid from the BSS of my AP appear (when AP has power) and get put via ieee80211_rx_bss_put (here). At this point, it is returned in scan results and wpa_supplicant causes the MLME layer in the kernel to authenticate and connect with that AP. However, after disconnecting AP power, I never see the MLME layer relinquish it's atomic_t hold on that BSS. This causes the BSS to never to unlinked in the function
cfg80211_bss_expire at the end of a scan (cfg80211_wext_giwscan), in file net/wireless/scan.c, line 205 (here).
Specifically, I would like to know why the atomic used to "hold" a BSS is not decremented on power removal from the AP - causing linux to miss sufficient beacons for a disconnect? Or, is there some configuration with wpa_supplicant I need to add to have the MLME kernel layer decrement it's hold on the BSS, or is this clearly a kernel bug?
I've already tried:
# wpa_cli bss_expire_age 10
# wpa_cli bss_expire_count 2
and have not resolved my issue.
So after a lot of digging, I found that the issue was because of the kernel's rtlwifi driver. To me, it looks like the rtl8192cu driver was suppose to be responsible for handling missed beacons, by calling the function ieee80211_beacon_loss, but that call is nowhere to be found. I removed support for IEEE80211_HW_BEACON_FILTER in the rtlwifi driver and the issue has been fixed.
This patch is essentially the same changes that I made, and the comments in this file are part of what led to me this answer.
As known, u-boot loader supports some sort of "input device system" that allows to register a set of functions (like getc, tstc, start, etc...). So I need to implement my own hardware-specific "keyboard". What should I do? Sounds simple:
1) Create at least "init", "tstc", "getc" and "start" functions in driver file.
2) In "init" call "stdio_register" to let system know about my device.
3) Call driver "init" from my custom board init code.
What the problem? Unfortunately, it doesn't work. stdio_register returns 0 (like all OK), but "start", "tstc", "getc" were never called.
I guess I'm doing something wrong, but I cannot understand: another keyboards drivers seems to not contain any additional code for keyboard registration. Can anybody tell the truth?
Or maybe I should just hack u-boot and insert polling call somewhere in main_loop? :)
It sounds like you have created a custom device driver.
struct stdio_dev kon_dev
Try something like this at U-Boot command line to switch console to the custom driver
setenv stdin kon_dev
Of course, your custom driver will have to be debugged before you get to the happy place. It may not work the first time.
Using netconsole is similar to what you're doing. With netconsole it's possible for example to keep stdout continuously on serial device, switch stdin to nc device (that is, "setenv stdin nc", enter commands through that netcat session a while, then switch stdin back to serial.
This seems like a simple question, but it is difficult to search for. I need to interface with a device over the serial port. In the event my program (or another) does not finish writing a command to the device, how do I ensure the next run of the program can successfully send a command?
Example:
The foo program runs and begins writing "A_VERY_LONG_COMMAND"
The user terminates the program, but the program has only written, "A_VERY"
The user runs the program again, and the command is resent. Except, the device sees "A_VERYA_VERY_LONG_COMMAND," which isn't what we want.
Is there any way to make this more deterministic? Serial port programming feels very out-of-control due to issues like this.
The required method depends on the device.
Serial ports have additional control signal lines as well as the serial data line; perhaps one of them will reset the device's input. I've never done serial port programming but I think ioctl() handles this.
There may be a single byte which will reset, e.g. some control character.
There might be a timing-based signal, e.g. Hayes command set modems use “pause +++ pause”.
It might just reset after not receiving a complete command after a fixed time.
It might be useful to know whether the device was originally intended to support interactive use (serial terminal), control by a program, or both.
I would guess that if you call write("A_VERY_LONG_COMMAND"), and then the user hits Ctrl+C while the bytes are going out on the line, the driver layer should finish sending the full buffer. And if the user interrupts in the middle of the call, the driver layer will probably just ignore the whole thing.
Just in case, when you open a new COM port, it's always wise to clear the port.
Do you have control over the device end? It might make sense to implement a timeout to make the device ignore unfinished or otherwise corrupt packets.
The embedded device should be implemented such that you can either send an abort/clear/break character that will dump the contents of its command buffer and give you a clean slate on your client app startup.
Or else it should provide a software reset character which will reset the command buffer and all state.
Or else it so be designed so that you can send a command termination (perhaps a newline, etc, depending on command protocol) and possibly have an error generated on the parsing of a garbled partial command that was in its buffer, query/clear the error, and then be good to go.
It wouldn't be a bad idea upon connection of your client program to send some health/status/error query repeatedly until you get a sound response, and only then commence sending configuration or operation commands. Unless you can via a query determine that the device was left in a suitable state, you probably want to assume nothing and configure it from scratch, after a configuration reset if available.
I have a Linux USB HID device (a Hama MCE), and I can read its events manually by reading cat /dev/input/event7 and cat /dev/input/event8. Whenever I press a key on the device, a few bytes become available for reading with one of the cat commands above. I have a default installation of Ubuntu Jaunty 64-bit desktop on the machine.
I think I can write a parser to interpret the bytes emitted by the device, or I'll use libhid if it's more convenient.
My questions are:
How do I prevent the text-mode virtual consoles from receiving some of the key presses on the device as normal keypresses? As of now, some device keys result an Enter, a BackSpace, a PageUp or numeric keypad numbers.
Similarly, how do I prevent the X server from receiving keyboard and mouse events from this device? I have several USB keyboards and mice connected to the computer. I want the X server receive events from all of them, except for this device.
How do I set up that whenever the device gets connected to the computer, the command /usr/local/bin/keydumper /dev/input/event7 /dev/input/event8 (or one command for each /dev/ path) would get run, with the proper /dev/ paths substituted in the command line?
Answering my own question based on answers from the Linux USB HID driver developers:
Question 1. and 2.: Do
ioctl(open("/dev/input/event7", O_RDONLY), EVIOCGRAB, 1);
As long as this filehandle is open, the events generated would go only
to this filehandle (not to other open()s of the same device or to the
system keyboard or mouse event pool). At most one process can hold a
successful EVIOCGRAB at a HID device at a time. Lirc can be configured
to do an EVIOCGRAB.
Question 3.: Configure udev to start the program once the device is connected.
I do not have enough points to comment sadly.
If you are looking for the definition of EVIOCGRAB try
#include <linux/input.h>
I think solution for all questions can be writing own filter device driver, or custom driver for your device. I know such a thing (filter device driver) is available on windows so something similar can be on Linux. In that filter device driver you could block all unwanted events from the target device that you wish to block, I don't really get 3 question so I don't know how to answer for that.
I'm debugging communications with a serial device, and I need to see all the data flowing both directions.
It seems like this should be easy on Linux, where the serial port is represented by a file. Is there some way that I can do a sort of "bi-directional tee", where I tell my program to connect to a pipe that copies the data to a file and also shuffles it to/from the actual serial port device?
I think I might even know how to write such a beast, but it seems non-trivial, especially to get all of the ioctls passed through for port configuration, etc.
Has anyone already built such a thing? It seems too useful (for people debugging serial device drivers) not to exist already.
strace is very useful for this. You have a visualisation of all ioctl calls, with the corresponding structure decoded. The following options seems particularly useful in your case:
-e read=set
Perform a full hexadecimal and ASCII dump of all the data read from
file descriptors listed in the
specified set. For example, to see all
input activity on file descriptors 3
and 5 use -e read=3,5. Note that this
is independent from the normal tracing
of the read(2) system call which is
controlled by the option -e
trace=read.
-e write=set
Perform a full hexadecimal and ASCII
dump of all the data written to file
descriptors listed in the specified
set. For example, to see all output
activity on file descriptors 3 and 5
use -e write=3,5. Note that this is
independent from the normal tracing of
the write(2) system call which is
controlled by the option -e
trace=write.
I have found pyserial to be quite usable, so if you're into Python it shouldn't be too hard to write such a thing.
A simple method would be to write an application which opened
the master side of a pty and the tty under test. You would then
pass your tty application the slave side of the pty as the 'tty device'.
You would have to monitor the pty attributes with tcgetattr() on the pty
master and call tcsetattr() on the real tty, if the attributes changed.
The rest would be a simple select() on both fd's copying data bi-directionally and copying it to a log.
I looked at a lot of serial sniffers. All of them are based on the idea of making a virtual serial port and sniff data from that port. However, any baud/parity/flow changes will break connection.
So, I wrote my own sniffer :). Most of the serial ports now are just USB-to-serial converters. My sniffer collects data from USB through debugfs, parse it and output to the console. Also any baudrate changes, flow control, line events, and serial errors are also recorded. The project is in the early stage of development and for now, only FTDI is supported.
http://code.google.com/p/uscmon/
Much like #MBR, I was looking into serial sniffers, but the ptys broke the parity check. However, his sniffer was not helping me, as I'm using a CP2102, and not a FT232. So I wrote my own sniffer, by following this, and now I have one that can record file I/O on arbitrary files: I called it tracie.