December 08, 2005
udev: eliminating scripts, setting GROUP, understanding variables
In response to a few queries, here's some more information about udev.
%p or $devpath or DEVPATH is the path under /sys, but without the leading "/sys." E.g., the device path will be /sys/block/sdc, and DEVPATH will be "/block/sdc." $kernel or %k is the path *under* dev, e.g., bus/usb/002/017, so /dev/%k is the actual path to the device name.
Using Program. PROGRAM runs *before* the anything is done in the rule. If PROGRAM fails, the entire rule fails. When I was making errors in PROGRAM -- for example, when I was using the wrong SUBSYTEM, or I didn't give a full path name to umount -- then the SYMLINK wasn't created because PROGRAM returned an error.
So, let's say I want to mount a flash drive. I don't need an external script; I can use:
SUBSYSTEM=="block", ACTION=="add", SYSFS{product}=="Flash Disk", SYMLINK="ums", ENV{flashdrive}="%p", RUN+="/bin/mount -t vfat -o user,sync,umask=0000 /dev/%k /ums"
Note that you must give the full path name to "mount," otherwise RUN will assume it's a udev script and try to find it in /lib/udev or some other udev-specific location.
If I'd used "PROGRAM" instead of run, then udev would attempt to execute mount before adding the /dev entry, PROGRAM would return a non-zero exit code, and the rule would not execute and the /dev entry would not be made. (Well certainly the SYMLINK would not be made; it's possible the /dev entry is made, but I don't think it is.)
The man page mentions the ENV, but what are the contents of this mysterious variable? They can be viewed by using "udevmonitor --env" -- it gives a printout of each ENV variable as it's used/set. I suspect that there are more than the ones we see...
Aras Vaichas explains that "SUBSYSTEMs are what you find in /sys/class/ /sys/block/ /sys/bus/, e.g. usb, scsi, serio, etc." You can see the SUBSYSTEMs by using "udevmonitor --evn" and looking for SUBSYTEM. The PHYSDEVDRIVER variable is the associated kernel module.
Finally, setting GROUP for a device you've hotplugged. Instead of using an external script as was the case with hotplug, you can use a simple rule instead. This is how I set GROUP when I mount my USB-enabled camera:
SUBSYSTEM=="usb_device", SYSFS{idVendor}=="04a9", SYSFS{idProduct}=="3051", GROUP="camera"
The trick is knowing that it's the "usb_device" SUBSYSTEM that creates the USB device entry that gtkam and libgphoto2 use, e.g., /dev/usb/002/017. Finding out what SUBSYSTEM to use is a trail-and-error process, but udevmonitor --env does display the /dev entry when it's created, and that's a very good start.
Posted by Moshe Yudkowsky at December 8, 2005 08:42 AM