2011-12-06

Linux Udev: How to uniquely ring a bell or run a script upon hardware insertion

Microsoft Windows usually emits an acoustic signal to confirm the action of insertion or removal of a peripheral device. On a Linux box, this is easy to achieve as well.

First of all, you need to decide which sound files to use -- one for the hardware insertion action, and the other for removal. Secondly, you need a sound playing program. I would recommend aplay(1) for simple PCM wav files.

Simply create a udev-rule-file in the directory /etc/udev/rules.d/, say, z99_my.rules. Note that the filename must end with ".rules".
$ sudo vim /etc/udev/rules.d/z99_my.rules
and put in the file the following two "rules":
ACTION=="add", SUBSYSTEM=="mmc|pcmcia|usb_device", RUN+="/usr/bin/aplay /full_path/hw_insert.wav"
ACTION=="remove", SUBSYSTEM=="mmc|pcmcia|usb_device", RUN+="/usr/bin/aplay /full_path/hw_remove.wav"
Restart or reload the udev-rules:
$ sudo /etc/init.d/udev reload
to make the new rules effective.  Voila, your system shall now ring a bell upon insertion or removal of, say, a USB thumb drive.

Note that the full paths must be specified for both aplay(1) and the sound file and that aplay(1) hardly handles encoding schemes other than simple PCM.

You may like to use another sound player of your choice but note that there's no tty available under such circumstance.

Note also that using "usb" instead of "usb_device" would trigger the sound effect more than once. So, the expression SUBSYSTEM=="usb" does not uniquely match each usb hardware insertion or removal action.

If one would like to do more than just playing a sound file, a shell-script may be invoked to handle the udev-events by modifying the above udev-rule-file:
$ cat /etc/udev/rules.d/z99_my.rules
SUBSYSTEM=="mmc|pcmcia|usb_device", RUN+="/usr/local/bin/my_script"
$ chmod 755 /usr/local/bin/my_script
$ ls -l /usr/local/bin/my_script
-rwxr-xr-x 1 nobody nobody 106 Dec 4 21:46 /usr/local/bin/my_script
where my_script contains the following lines:
#!/bin/sh
LOGFILE=/tmp/my_script.log
exec 3>> $LOGFILE && exec >& 3 && exec 2>&1

if [ "$ACTION" = "add" ]
then
    aplay -q /full_path/hw_insert.wav &

elif [ "$ACTION" = "remove" ]
then
    aplay -q /full_path/hw_remove.wav &
fi
exit $?
Since no tty is associated to the process when this script is executed, the stdout and stderr have to be redirected to a logfile for debugging. This is why we introduced the variable LOGFILE and did
exec 3>> $LOGFILE && exec >& 3 && exec 2>&1
so that one is able to see what actually happened. For instance:
/full-path/hw_insert.wav: No such file or directory
Although the shell script has a primitive environment at run-time, many useful variables are available for checking the details of  the udev-event. They are pre-defined by the udev daemon before running our shell-script. Particularly useful environment variables are SUBSYSTEM, ACTION, DEVTYPEDEVNAME, and DEVPATH. It depends which SUBSYSTEM an uevent (udev event) has been generated, many more variables are also pre-defined to describe the particular event and are very useful for the shell script to accomplish its task.

To find out which variables, issue the command as root:
$ sudo udevmonitor --environment
 or
$ sudo udevadm monitor --environment
Besides, the variable DEVPATH will also lead us to a bunch of  information about the device in question, that is, the directory
/sys/$DEVPATH/
For example, in case of DEVPATH==block/sda/sda1, the file:
/sys/$DEVPATH/size
can be read for the size of the first partition of the block device. Note, however,  that we have already excluded such case as SUBSYSTEM==block in the above udev rule.

The variable SUBSYSTEM can assume the following values:
input pci usb usb_device usb_endpoint tty block power_supply pcmcia net video4linux mmc scsi scsi_host scsi_device scsi_disk drivers ide ide_port bdi firmware sound ieee1394 module class platform
when invoked by the udev daemon.


Related Articles

2011-11-04 Linux 的 udev 是個有趣又有用的玩具(1)
2011-11-11 Linux 的 udev 是個有趣又有用的玩具(2)
2011-11-11 Linux 的 udev 是個有趣又有用的玩具(3)
2011-11-21 Linux 的 udev 是個有趣又有用的玩具(4)
2012-06-13 Linux 的 udev 是個有趣又有用的玩具 (5en) : Smallest Working Bourne-Shell Automounter

沒有留言:

張貼留言