# Switching /dev/video0 and /dev/video1 using udev rules

## devsk

Folks,

I need a little help. What I want to achieve is to make /dev/video0 always point to my UVC Webcam (don't ask: some programs are hardcoded to use /dev/video0 for webcam) and make /dev/video1 always point to my WinTV USB Tuner.

I wrote this rule:

```
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", ENV{ID_V4L_PRODUCT}=="UVC Camera (046d:0991)", NAME="video0", GROUP="video", OPTIONS="last_rule"

KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", ENV{ID_V4L_PRODUCT}=="WinTV PVR USB2 Model 24xxx", NAME="video1", GROUP="video", OPTIONS="last_rule"
```

This basically renames the NAME to video0 although kernel may be saying UVC is video1 because UVC module got loaded after pvrusb2. This basically throws a UDEV error (although it does work right):

```
kernel-provided name 'video0' and NAME= 'video1' disagree, please use SYMLINK+= or change the kernel to provide the proper name
```

Other approach is load the modules in order and make sure they get same name. But that's buggy and racy. I don't know how long to wait for loading the second module, it will just delay my boot. I will also need to remove them from autoload and put them in local.start...eeks.

Anybody got any ideas to get it working without Udev going nuts on me in future?

----------

## MotivatedTea

I found this information about a change starting with udev-154:

http://lwn.net/Articles/387384/

 *Quote:*   

> Udev now gradually starts to pass control over the primary device nodes
> 
> and their names to the kernel, and will in the end only manage the
> 
> permissions of the node, and possibly create additional symlinks.
> ...

 

It looks like this is a design decision the udev and/or kernel authors made. Apparently, now you can make new symlinks but you can't change the kernel-provided name.

I'm not using that recent a version of udev yet, but the manpage from newer versions of udev now say this about "NAME":

 *Quote:*   

>        NAME
> 
>            The name, a network interface should be renamed to. Or as a
> 
>            temporary workaraound, the name a device node should be named.
> ...

 

So unless you can do what you want with "SYMLINK=" instead, you may be out of luck. This is annoying, because I'm using this to do the same sort of thing you're trying to do. Now -- or at least by the time udev-154 or higher hits stable -- I'm going to have to change it. If you find a work-around, please post do the solution here.

----------

## devsk

Here is what I ended up doing:

1. Put the following in /etc/udev/rules.d/99-myrules.rules

```

KERNEL=="video[0-9]*",SUBSYSTEM=="video4linux",RUN="/usr/bin/makeVideoLinks",OPTIONS="last_rule"
```

2. Create /usr/bin/makeVideoLinks with the following contents, and make it executable with 'chmod +x /usr/bin/makeVideoLinks'

```

#!/bin/bash

# The DEVPATH and DEVNAME are set in the env

major=`udevadm info --query all -p $DEVPATH | grep MAJOR= | awk 'BEGIN{FS="="} {print $2}'`

minor=`udevadm info --query all -p $DEVPATH | grep MINOR= | awk 'BEGIN{FS="="} {print $2}'`

prod=`udevadm info --query all -p $DEVPATH | grep ID_V4L_PRODUCT= | awk 'BEGIN{FS="="} {print $2}'`

case "${prod}" in

        UVC*)

                mknod /dev/mywebcam c ${major} ${minor}

                chmod 664 /dev/mywebcam

                chown root:video /dev/mywebcam

                /bin/rm -f /dev/video1

                /bin/rm -f /dev/video0

                ln -s /dev/mytuner /dev/video1

                ln -s /dev/mywebcam /dev/video0

                ;;

        WinTV*)

                mknod /dev/mytuner c ${major} ${minor}

                chmod 664 /dev/mytuner

                chown root:video /dev/mytuner

                /bin/rm -f /dev/video1

                /bin/rm -f /dev/video0

                ln -s /dev/mytuner /dev/video1

                ln -s /dev/mywebcam /dev/video0

                ;;

        *)

                ;;

esac
```

Its hacky and not scalable but it works reliably! I could not find any better solution without depending on and changing NAME somehow. If someone has one, please post.

@MotivatedTea: Let me know if above works for you.

----------

## devsk

More condensed elegant version...  :Very Happy: 

```

#!/bin/bash

# The DEVPATH and DEVNAME are set in the env

eval $(udevadm info --query property -p $DEVPATH | sed -e "s/[() ]//g")

case "${ID_V4L_PRODUCT}" in

        UVC*)

                /bin/rm -f /dev/mywebcam

                mknod /dev/mywebcam c ${MAJOR} ${MINOR}

                chmod 660 /dev/mywebcam

                chown root:video /dev/mywebcam

                ln -sf /dev/mytuner /dev/video1

                ln -sf /dev/mywebcam /dev/video0

                ;;

        WinTV*)

                /bin/rm -f /dev/mytuner

                mknod /dev/mytuner c ${MAJOR} ${MINOR}

                chmod 660 /dev/mytuner

                chown root:video /dev/mytuner

                ln -sf /dev/mytuner /dev/video1

                ln -sf /dev/mywebcam /dev/video0

                ;;

        *)

                ;;

esac
```

----------

