UDEV and Multiple Flash Card Readers (Shallow Thoughts)

Akkana's Musings on Open Source, Science, and Nature.

Mon, 07 Nov 2005

UDEV and Multiple Flash Card Readers

Update: Some of this has changed; see my newer entry, Update on writing udev rules for flash card readers.

Dave had one of those nifty front-panel multiple flash card readers sitting on a shelf, so I borrowed it. It's USB based, fits in a CD drive bay, and has slots for all the common types of flash memory, as well as a generic USB socket.

With the device installed, I booted into my usual Ubuntu (hoary) partition, inserted an SD card and checked dmesg. Nothing! The four logical units of the device had been seen at boot time, but nothing new happened when I inserted a card.

I tried mounting /dev/sda1, /dev/sdb1, /dev/sdc1, /dev/sdd1, and /dev/sde1 anyway, but got "No such device" each time.

Dave muttered darkly about udev and hal and said I should try it under an older Debian with a normal /dev. I rebooted my old sid partition, with a kernel I built myself. I needed a kernel with "Probe all LUNs on each SCSI device", of course. I still got no messages or hotplug events when inserting the card, but /dev/sdd1 mounted the SD card.

(For anyone reading this who's not familiar with Linux' handling of USB storage devices, sd in /dev/sdd1 stands for "SCSI disk" and has nothing to do with the fact that I was using a "secure digital" media card. Any USB disk or flash card is supposed to show up under /dev/sdsomething and the main trick is figuring out the something. Which is part of what udev and hal are supposed to help with.)

Then I discovered that doing an fdisk -l /dev/hdd gave the right answer (one partition) for the SD card. And as soon as I did that, the /dev/sdd1 device appeared and I was able to mount it normally.

Apparently, when udev sees the logical units at boot time, with no cards inserted, it decides that there's a /dev/sdd, but it has no partitions on it so there's no such device as /dev/sdd1. Since inserting a card later doesn't generate a hotplug event, udev never re-evaluates this, unless somehow forced to (apparently running fdisk forces it, though I'm not sure why). Dave was right: udev/hal are the culprit here, and the kernel was fine.

A helpful person on #ubuntu pointed me to this tutorial on writing rules for udev. It mentions the problem with multi USB card readers not getting additional events when cards are plugged in, and suggests modifying the NAME key in the rules (which seem to be in /etc/udev/rules.d/udev.rules to:

BUS="usb", SYSFS{product}="USB 2.0 Storage Device", NAME{all_partitions}="usbhd"
Elsewhere in the document, it suggests getting that SYSFS{product} string by running a command like udevinfo -a -p /sys/block/sdd

Unfortunately, that seems to be completely ignored. udevinfo told me the string was "CardReader SD ", but plugging that in to udev.rules did not create any /dev/usbhd* devices. It also seemed clear that udev is using BUS="scsi" rather than BUS="usb" for these devices, based on the device names that are being created (sd* rather than ub*). But making that change didn't help.

Eventually I found a combination that worked. Ubuntu's current rules for usb-storage devices are:

BUS="scsi", KERNEL="sd[a-z]*", PROGRAM="/etc/udev/scripts/removable.sh %k", RESULT="1", NAME="%k", MODE="0640", GROUP="plugdev"
BUS="usb", KERNEL="ub[a-z]*", NAME="%k", MODE="0640", GROUP="plugdev"
(I don't know what devices create the ub* devices. It's nothing I've used so far).

I changed the "sd[a-z]*" to "sd[e-z]*", so that it wouldn't apply to the four devices grabbed by the multicard reader. Then I added these four lines:

BUS="scsi", KERNEL="sda*", PROGRAM="/etc/udev/scripts/removable.sh %k", RESULT="1", NAME{all_partitions}="cfcard", MODE="0640", GROUP="plugdev"
BUS="scsi", KERNEL="sdb*", PROGRAM="/etc/udev/scripts/removable.sh %k", RESULT="1", NAME{all_partitions}="smcard", MODE="0640", GROUP="plugdev"
BUS="scsi", KERNEL="sdc*", PROGRAM="/etc/udev/scripts/removable.sh %k", RESULT="1", NAME{all_partitions}="mscard", MODE="0640", GROUP="plugdev"
BUS="scsi", KERNEL="sdd*", PROGRAM="/etc/udev/scripts/removable.sh %k", RESULT="1", NAME{all_partitions}="sdcard", MODE="0640", GROUP="plugdev"

That worked. Now udev creates /dev/sdcard[1-15] as well as /dev/sdcard (and likewise for the other three flash types), and I can make a normal /etc/fstab entry:

/dev/sdcard1    /sd             auto    rw,user,noauto   0       0

Now as a user I can say mount /sd without needing to su to root or do any extra fiddling. Hurrah!

Tags: , ,
[ 15:49 Nov 07, 2005    More linux | permalink to this entry ]