Wednesday, April 28, 2010

Udev Rules! Not!

If someone tells you how great Linux is, they've probably never had deal with odd ball situations. Take udev, for example. Please! Take udev! I'm begging you! ^_^

I'm using the 8-in/8-out version of this USB I/O unit on a project. This hardware doesn't require any Linux kernel drivers which make me very happy. The manufacturer provides the source to a library which uses libusb to communicate with the device. The device does not store the firmware permanently so it must be downloaded every time you plug in the hardware. One quirk is that after the download, the device disconnects and reconnects with a different product ID, but the manufacturer includes udev rules to handle it.

My big mistake was that I setup the hardware on my desktop system, which is running Debian sid/unstable, before trying it on the production PC, which is running Debian lenny/stable. The configuration requires two udev rules (which are slightly different that the manufacture's version)
SUBSYSTEM=="usb", ACTION=="add", ATTRS{idVendor}=="1605", ATTRS{idProduct}=="001c", RUN+="/sbin/fxload -t fx2 -D $env{DEVNAME} -I /usr/local/lib/USB-IDIO-16.hex"
SUBSYSTEM=="usb", ACTION=="add", ATTRS{idVendor}=="1605", ATTRS{idProduct}=="801c", GROUP="aiousb", MODE="664"
Of course, thinking that I could just copy this configuration over to the production PC, was just too optimistic. The first line works (the firmware is downloaded) but the second line doesn't set the device file group which is stuck as root.

After some (understatement! ^^) investigation, I found that the following udev rule on Debian lenny was causing the problem.
SUBSYSTEM=="usb_device", ACTION=="add|change", PROGRAM="/bin/sh -c 'K=%k; K=$${K#usbdev}; printf bus/usb/%%03i/%%03i $${K%%%%.*} $${K#*.}'", ACTION=="add|change", NAME="$result"
At first I changed my custom rule to match the SUBSYSTEM and ACTION attributes, which worked for hotplugging and cold boot, but not for a warm boot. On a hunch I added the original rule back again, which worked!

The final rule set looks like this:
SUBSYSTEM=="usb", ACTION=="add", ATTRS{idVendor}=="1605", ATTRS{idProduct}=="001c", RUN="/sbin/fxload -t fx2 -D $env{DEVNAME} -I /usr/local/lib/USB-IDIO-16.hex"
SUBSYSTEM=="usb_device", ACTION=="add|change", ATTRS{idVendor}=="1605", ATTRS{idProduct}=="801c", OWNER="root", GROUP="aiousb", MODE="0664"
SUBSYSTEM=="usb", ACTION=="add", ATTRS{idVendor}=="1605", ATTRS{idProduct}=="801c", OWNER="root", GROUP="aiousb", MODE="0664"
It looks a kind of clunky, so there is probably a better way to do it, but I'm way past the limit of my udev-fu, so I not going to poke at it any more. I'll worry about it when it stops working. Which will be at some inconvenient moment, I'm sure. udev works great, until it doesn't. ^_^

No comments:

Post a Comment