Assume the following situation under Linux:
A process is continuously reading from an USB-serial converter device (/dev/ttyUSB0). That device is suddenly unplugged and plugged in again (or is resetting itself for some reason). The process continues to have a valid file handle for /dev/ttyUSB0 but won't receive any data from the device unless the process re-opens the device (because udev has deleted and re-created the device node).
Is there a direct way to detect such a situation (ie. not indirectly by detecting a timeout in data flow) so that the process knows it has to re-open the device? Would it be reliable to monitor the modification time of /dev/ttyUSB0 using stat()?
Additional details:
The process opens the device file by using the standard open() function.
/dev is a tmpfs controlled by udev.
Note: I do not want to use any udev rules for this and prefer a solution implemented directly in the process.
If a USB device is hot-unplugged, operations on the device will begin failing with -EIO; you can detect this and take appropriate action.
If the device node is actually being removed and re-created (which I believe it is if you have udev), then you should be able to use the inode number to tell when this happens.
Just call fstat() on your open file descriptor, stat() on /dev/ttyUSB0, and compare the st_ino fields of the two struct stats.
And let me know if it actually works. :-)
I think FAM or gamin will detect these events.
Related
I'm new in developing Linux driver.
Traditionally, If i want to create char device, I just need to implement read write and ioctl functions, and register it by register_chrdev_region with corresponding Major device ID. And then use mknod to create a device file of that Major device ID. Then call read write open in user space will then call the corresponding functions by kernel.
But now i'm studying Linux device model and sys filesystem, which is added in kernel 2.6. I'm told if possible, Don't use /dev filesystem, as linux now has a good device model to handle device and driver.This confused me, so I'll summarize my confusion into some questions:
How do I create a char device in /sys? To be more specific, how do I create a null device just like /dev/null?
How do I call my char device driver function from userspace?
I heard that udev is based on sys filesystem to create device file in /dev. Why? Since I'm told "If possible, Don't use /dev filesystem", why does udev use /sys to create file in /dev?
Does a file in sys have any conceptions like char device file or block device?
In /dev, open write from user space will finally map to functions in file operation structure defined by me, then what functions will be called when I open or write to files in /ssy?
Without context your statement about /dev is not clear. Anyway:
You cannot create char devices on sysfs. The main purpose of sysfs is to export information and allow the user to adjust single values (just navigate under /sys/ for some examples). Char devices usually does much complicated things.
If you mean how you call your driver's open,read,write,ioctl, ... well, by doing open(2), read(2), write(2), ioctl(2) (look at man pages of these commands)
when a device appear, the kernel create a directory under /sys. For example take a look at ls /sys/bus/usb/devices/. All that directories are created when an USB device appear. You can try by plug/unplug USB devices. udev put an eye on sysfs to detect new devices and according to the information from sysfs it create the device under /dev. This happens when the driver, somehow, calls device_add(). Often this functions is invoked by other register functions like: device_create, device_register, or other from other sub-systems.
the idea of sysfs is to provide information about the devices and drivers loaded. So you can change device, bus and driver options. Or manually attach a device to a module
Actually, behind the sysfs attributes there is a set of file_operation, where open, read and write are managed by the kernel and not by your driver. In order to create a sysfs attribute you have to provide the pair of function show and store to read/write something from/to the driver. Then the kernel will route the requests to your correct attribute
I am just starting to look at the I2C support on (embedded) linux (Beaglebone Black, to be precise). Since it's linux, everything is a file, so it's no surprise that I2C is too.
int file = open( "/dev/i2c-0", O_RDWR );
and then the actual address on that bus is selected through ioctl(). My question is this - is it safe, or even legal, to cache file for the duration of application execution? It would seem to my naive eyes that the overheading of opening a resource to read every 250ms would be an unnecessary strain on the kernel. So it is valid to open, and then just use ioctl() to switch address whenever I need to, or must I close() the descriptor between reads and writes?
is it safe, or even legal, to cache file for the duration of application execution?
The file descriptor (that is returned from open()) is valid for as long as your program needs to keep executing.
Device nodes in /dev may resemble filenames, but they are treated differently from filesystem entries once you look past the syscall interface. An open() or read() on a file descriptor for a device will invoke the device driver, whereas for an actual file its filesystem is invoked, which may eventually call a storage device driver.
It would seem to my naive eyes that the overheading of opening a resource to read every 250ms would be an unnecessary strain on the kernel.
Yes it would since those open() and close() syscalls are unnecessary.
So it is valid to open, and then just use ioctl() to switch address whenever I need to,
Yes, that is the proper useage.
or must I close() the descriptor between reads and writes?
That is not necessary nor advised.
I've got a quick question, but I can't find an answer.
Is it possible in linux (or in python) to see if an external usb pen drive is idling?
I need to know this for a python script I'm writing.
I need to rename a folder on an external usb pen drive as soon as nothing is writing to it.
edit: I know there is lsof command to list open files. 'lsof /theDir' only works half. It works OK when the process copying to the USB is still running. But when the process stops, lsof shows nothing. But the OS is still writing to the USB from its buffer.
You can check if all I/O has been processed by having a look at /sys/block/<dev>/stat.
The ninth column contains the number of I/Os currently in flight. Check https://www.kernel.org/doc/Documentation/block/stat.txt
Once this numner is zero the device should be idle.
To force all buffers to be written immediately you could execute sync and wait until it returns.
Nevertheless be aware that you have a race condition here if you are not controlling the writing - after you decided that the device is idle some other process could start writing to it.
I need to write a program in linux (debian, to be exact) that disables a USB device if it doesn't pass specific filters. For example, the program might be set to disallow webcams, usb sticks and keyboards, enable mice and printer (through usb). The filters may change in runtime. For example, the program might receive a message to enable usb sticks and it should respond without rebooting the system. The program is written in python but embedding c code (or others) is also acceptable.
What I have tried
I have tried many methods but some of them aren't about programming.
First, I tried to mess with udev. I can monitor the activities when a device is plugged and write filters. There used to be an option "ignore_device" that ignored the filtered devices. For example, to ignore all the devices that are a member of usb subsystem, I would write this as a udev rule:
ACTION=="add", SUBSYSTEM=="usb", OPTIONS+="ignore_device"
But this option is released in this release of udev. What I get so far is that udev can currently be used mainly for monitoring. Sure, I can write additional rules for the rule above that runs a script, but I have to do the disabling elsewhere.
Second, I tried ioctl to send a DISCONNECT signal to device handle. I'm testing this with a USB mouse. This is the python code for that: (I have also tried this in C, nothing changed)
import fcntl
import sys
USBDEVFS_RESET = ord('U') << (4*2) | 20
USBDEVFS_DISCONNECT = ord('U') << (4*2) | 22
raw_name = "/dev/bus/usb/{:03d}/{:03d}"
filename = raw_name.format(1,2)
fd = open(filename, "wb")
fcntl.ioctl(fd, USBDEVFS_DISCONNECT, 0)
Here, if I would send USBDEVFS_RESET, it works, the mouse input is ignored for a second or two. But disconnect signal raises an error:
IOError: [Errno 25] Inappropriate ioctl for device
What I get from here is, I cannot send disconnect signal to a mouse. Maybe a usb stick or printer or some other devices would work, I haven't tried. I want to develop the program as generic as possible so as to prevent writing additional device-specific code, so this approach seems useless for me. And another point here is that when I manually disconnect/connect my mouse, I see events in udev monitor. But when I send reset signal, no event is sent.
The udev monitor says that the mouse was mounted to this path: /sys/bus/usb/devices/1-3 (which is a symlink for /sys/devices/pci0000:00/0000:00:14.0/usb1/1-3). Some documents told me that this folder contains the device's settings and setting /power/level to "off" or "suspended" would turn the device power off. But I cannot manipulate any files in /power. Come to think about it, it might not be a good idea after all.
The Question
So, the question is, what is the best way to achieve such task? I have an idea but I'm not sure whether it will work and even if it does, it might be overkill. My idea is writing a "wrapper driver" that identifies itself to linux kernel as driver for all usb devices. The "wrapper driver" reads the device information and if the device is good to go, it acts as a wrapper for real drivers in the kernel, calling their functions. If not, the "wrapper driver" just ignores the device.
I'm not sure it can even be done, I'm not experienced in kernel or driver programming.
Another way is, -somehow- getting the handle of the device programatically and telling it to power off (or making it busy forever, whatever works). I have also done some little research but couldn't find a proper-easy way. They say all devices are considered as "files" but I cannot reach those files at all.
Note:
The question is mostly about linux internals but it also involves kernel programming. I read a lot about usb manipulation/monitoring programs, I read manual pages of udevadm. But these approaches do not help me at all. I think I need to alter either kernel or device internals programatically.
I have also tried manipulating authorized file that resides in /sys/devices/pci0000:00/0000:00:14.0/usb1/1-4 (for a keyboard). It's default value is 1. Changing it to 0 successfully disabled the bus (NOT device, but the physical usb port. The same device can still be used when plugged in another port). But making it 0 also stopped udev events from this usb port. So, I can disable the port if the user plugs in a forbidden device but I cannot decide when to enable it since I cannot listen to remove events in udev. Would it make sense if I delve deeper to lower levels of code (possibly kernel) and listen to usb events in some other way?
I think the simplest way to solve your problem is balcklisting all usb device drivers excepting mouse, keyboard etc.
The cleanest way is whitlisting mouse etc. with udev using usb device id's
Writing a wrapper driver is an absolute overkill never chose that way.
One possible solution could be tying usb access to user permissions. here is a related link you may find handy
http://robots.mobilerobots.com/wiki/Linux_udev_USB_Device_Permissions_Configuration
Somewhere I read that opening the same file twice has an undefined semantics and should be avoided. In my situation I would like to open my own device multiple times associating multiple file descriptors to it. The file operations of my device are all safe. Is there some part of Linux between the sys call open() and the point it calls the registered file operation .open() that is unsafe?
It is perfectly fine to open the same device file twice, as long as your driver is ok with that.
There is no hidden part that would make it unsafe if it is safe in the kernel.
For example, some video application use one process to do the display or capture, while another opens the device file to handle the controls.
If the driver does not support multiple open, then it should return an error when a second open happens.
You may open a device twice in the same process, if the driver will let you do so. Synchronization is the responsibility of the driver.
However, if you are opening, say, a raw disk device as a privileged user, you will want to make sure you don't clobber your own data in your process.
Opening the same file twice has well-defined semantics in cases which make sense. Processes still need some form of synchronisation if they're all doing read/write, otherwise the file is likely to end up full of rubbish.
For a device driver, the semantics of multiple opens is entirely up to the driver - some drivers prohibit it, in others it works fine (think /dev/null for instance). In some drivers it has a very special meaning (e.g. sound cards may mix the sound output between multiple apps)