Wednesday, August 29, 2007

Lazy mans udev fixed device names

One of the constant annoyances of USB devices under Linux is that they don't get assigned fixed names. In my case I have two USB digital TV receiver cards, one for satellite and another of digital terrestrial. They can be accessed though the device directories: /dev/dvb/adapter0 and /dev/dvb/adapter1. However you never know which will be which and in order for MythTV to work correctly they need to fix these. For example adapter0 must always be the DVB-T and 1 the DVB-S. There is a long and complicated explanation of how to modify the udev rules to do something not entirely unlike this here: http://mythtv.org/wiki/index.php/Device_Filenames_and_udev
however, I can't figure out how to get it to work in my case (dvb devices have a more complicated directory structure) so I made this quick hack.


First you need to make sure that udev no longer maps your DVB cards to /dev/dvb/adapter0/1 but rather /dev/dvb/adapter_real0/1. On Debian you can do this by modifying /etc/udev/rules/udev.rules changing the line that reads:

KERNEL=="dvb*",                 PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter%%i/%%s $${K%%%%.*} $${K#*.}", ACTION=="add", \
NAME="%c"


to:

KERNEL=="dvb*",                 PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter_real%%i/%%s $${K%%%%.*} $${K#*.}", ACTION=="add", \
NAME="%c"


Now create an rc script to assign the fixed device names and place it somewhere in your startup directories. In my case I needed to make it start before mythbackend so I created the file /etc/rc2.d/S23dvbsyms (remember to make it executable) with the following contents:

#dvbs
if [[ `udevinfo -a -p /class/dvb/dvb0.frontend0 | grep UDST702X -c` == "1" ]]
then
echo "DVBS is adapter 0"
ln -s /dev/dvb/adapter_real0 /dev/dvb/adapter1
fi

if [[ `udevinfo -a -p /class/dvb/dvb1.frontend0 | grep UDST702X -c` == "1" ]]
then
echo "DVBS is adapter 1"
ln -s /dev/dvb/adapter_real1 /dev/dvb/adapter1
fi

#dvbt
if [[ `udevinfo -a -p /class/dvb/dvb0.frontend0 | grep VP7041 -c` == "1" ]]
then
echo "DVBT is adapter 0"
ln -s /dev/dvb/adapter_real0 /dev/dvb/adapter0
fi

if [[ `udevinfo -a -p /class/dvb/dvb1.frontend0 | grep VP7041 -c` == "1" ]]
then
echo "DVBT is adapter 1"
ln -s /dev/dvb/adapter_real1 /dev/dvb/adapter0
fi


udevinfo -a -p /class/dvb/dvbX.frontend0 dumps a bunch of information about the device, including product codes. I then grep for these and create a symlink to the real device accordingly. You can find the class path to use with udevinfo with:

udevinfo -a -p $(udevinfo -q path -n /dev/video0)


Where /dev/video0 is the device your after in /dev. One you've put these scripts in place the devices will get fixed names as boot. Of course this doesn't help much if you are plugging in and removing devices but it's a hack that works well enough for me.

1 comment:

Anonymous said...

There's another way I've found that's probably simpler in most cases. You can set the adapter number(s) as modprobe options.

http://www.mythtv.org/wiki/Device_Filenames_and_udev#Alternatives_to_udev_for_naming_for_DVB_cards_.28The_adapter_nr_module_option.29