Subscribe to RSS Feed

Improved udev rules for mcu programmers and usb serial adapters

on July 21st, 2009 by Johan Adler

I wrote earlier about AVRISP MkII, permission problems with avrdude and Ubuntu 9.04 amd64 and have learned a bit more since then. When surfing and searching for something Arduino related I found the Arduino Playground page on udev with a link to this post in the Arduino Forum. The forum post suggests the use of udevinfo, a command that seems to be deprecated. Looking through documentation and man pages I realized that udevadm would give me the information I needed.

I have a bunch of different USB to (UART/TTL) serial adapters and when having more than one connected I have found it quite difficult to find which /dev/ttyUSBx belongs to which adapter, and so I started to write udev rules for giving unique names to them. I will walk you through the process. Start by locating the /sys paths to your currently connected serial adapters, for FTDI and Prolific adapters it will look like this:

jadler@server:~$ ls /sys/bus/usb/drivers/ftdi_sio/
1-2.2:1.0  1-2.7:1.0  2-10.4:1.0  2-3:1.0  bind  module  uevent  unbind
jadler@server:~$ ls /sys/bus/usb/drivers/pl2303/
2-5:1.0  bind  module  uevent  unbind

The entries beginning with digits are links to the actual USB devices:

jadler@server:~$ ls /sys/bus/usb/drivers/ftdi_sio/[0-9]* -l
lrwxrwxrwx 1 root root 0 2009-07-21 10:50 /sys/bus/usb/drivers/ftdi_sio/1-2.2:1.0 -> ../../../../devices/pci0000:00/0000:00:02.1/usb1/1-2/1-2.2/1-2.2:1.0
lrwxrwxrwx 1 root root 0 2009-07-21 10:50 /sys/bus/usb/drivers/ftdi_sio/1-2.7:1.0 -> ../../../../devices/pci0000:00/0000:00:02.1/usb1/1-2/1-2.7/1-2.7:1.0
lrwxrwxrwx 1 root root 0 2009-07-21 10:50 /sys/bus/usb/drivers/ftdi_sio/2-10.4:1.0 -> ../../../../devices/pci0000:00/0000:00:02.0/usb2/2-10/2-10.4/2-10.4:1.0
lrwxrwxrwx 1 root root 0 2009-07-21 10:50 /sys/bus/usb/drivers/ftdi_sio/2-3:1.0 -> ../../../../devices/pci0000:00/0000:00:02.0/usb2/2-3/2-3:1.0

With udevadm it is then possible to find all attributes for the given device and all parents up to the root. An example:

udevadm info –attribute-walk –path=/sys/bus/usb/drivers/ftdi_sio/2-10.4\:1.0
<…>
looking at device ‘/devices/pci0000:00/0000:00:02.0/usb2/2-10/2-10.4/2-10.4:1.0′:
KERNEL==”2-10.4:1.0″
SUBSYSTEM==”usb”
DRIVER==”ftdi_sio”
ATTR{bInterfaceNumber}==”00″
ATTR{bAlternateSetting}==” 0″
ATTR{bNumEndpoints}==”02″
ATTR{bInterfaceClass}==”ff”
ATTR{bInterfaceSubClass}==”ff”
ATTR{bInterfaceProtocol}==”ff”
ATTR{modalias}==”usb:v0403p6001d0600dc00dsc00dp00icFFiscFFipFF”
ATTR{supports_autosuspend}==”0″
ATTR{interface}==”FT232R USB UART”

looking at parent device ‘/devices/pci0000:00/0000:00:02.0/usb2/2-10/2-10.4′:
KERNELS==”2-10.4″
SUBSYSTEMS==”usb”
DRIVERS==”usb”
ATTRS{configuration}==”"
ATTRS{bNumInterfaces}==” 1″
ATTRS{bConfigurationValue}==”1″
ATTRS{bmAttributes}==”a0″
ATTRS{bMaxPower}==” 90mA”
ATTRS{urbnum}==”14″
ATTRS{idVendor}==”0403″
ATTRS{idProduct}==”6001″
ATTRS{bcdDevice}==”0600″
ATTRS{bDeviceClass}==”00″
ATTRS{bDeviceSubClass}==”00″
ATTRS{bDeviceProtocol}==”00″
ATTRS{bNumConfigurations}==”1″
ATTRS{bMaxPacketSize0}==”8″
ATTRS{speed}==”12″
ATTRS{busnum}==”2″
ATTRS{devnum}==”7″
ATTRS{version}==” 2.00″
ATTRS{maxchild}==”0″
ATTRS{quirks}==”0×0″
ATTRS{authorized}==”1″
ATTRS{manufacturer}==”FTDI”
ATTRS{product}==”FT232R USB UART”
ATTRS{serial}==”A6007NVf”
<…>

For udev rules most of the attributes useful to identify the devices are found under the first parent device, where you will find idVendor, idProduct and (for FTDI devices in this case) the serial number. With a slight modification I could use the same commands to find the unique attributes for the MCU programmers, AVRISP MkII and friends, using the symlink that my previous rule assigned to them:

jadler@server:~$ udevadm info –attribute-walk –name=/dev/avrispmkII-1
<…>
looking at device ‘/devices/pci0000:00/0000:00:02.0/usb2/2-1′:
KERNEL==”2-1″
SUBSYSTEM==”usb”
DRIVER==”usb”
ATTR{configuration}==”"
ATTR{bNumInterfaces}==” 1″
ATTR{bConfigurationValue}==”1″
ATTR{bmAttributes}==”c0″
ATTR{bMaxPower}==”100mA”
ATTR{urbnum}==”661″
ATTR{idVendor}==”03eb”
ATTR{idProduct}==”2104″
ATTR{bcdDevice}==”0200″
ATTR{bDeviceClass}==”ff”
ATTR{bDeviceSubClass}==”00″
ATTR{bDeviceProtocol}==”00″
ATTR{bNumConfigurations}==”1″
ATTR{bMaxPacketSize0}==”16″
ATTR{speed}==”12″
ATTR{busnum}==”2″
ATTR{devnum}==”4″
ATTR{version}==” 1.10″
ATTR{maxchild}==”0″
ATTR{quirks}==”0×0″
ATTR{authorized}==”1″
ATTR{manufacturer}==”ATMEL”
ATTR{product}==”AVRISP mkII”
ATTR{serial}==”000200007829″

Using this information I could make the rules for MCU programmers much more simple and correctly targeted. When using udevadm with the attribute-walk option it will give you the attributes in a format that is ready for cutting and pasting into a rules file, quite convenient. As you see the AVRISP mkII also has a serial number, which the Prolific adapters alas are lacking.

My current rules for MCU programmers: 39-mcu-programmers.rule

With comments and empty lines stripped it looks like this:

jadler@server:~$ grep -v ‘^#’ /etc/udev/rules.d/39-mcu-programmers.rules | grep -v ‘^$’
SUBSYSTEM!=”usb”, GOTO=”mcu-prog_rules_end”
SYSFS{idVendor}==”03eb”, SYSFS{idProduct}==”2103″, MODE=”0660″, GROUP=”plugdev”
SYSFS{idVendor}==”03eb”, SYSFS{idProduct}==”2104″, MODE=”0660″, GROUP=”plugdev”, SYMLINK+=”avrispmkII-%n”
SYSFS{idVendor}==”03eb”, SYSFS{idProduct}==”2107″, MODE=”0660″, GROUP=”plugdev”, SYMLINK+=”avrdragon-%n”
SYSFS{idVendor}==”04d8″, SYSFS{idProduct}==”0033″, MODE=”0660″, GROUP=”plugdev”, SYMLINK+=”pickit2-%n”
LABEL=”mcu-prog_rules_end”

Much more clean and logical than my previous version, and I also found that the commands I used in an attempt to force udevd to reload the rules,

sudo invoke-rc.d udev reload
sudo udevadm control –reload-rules

are not needed at all. It works fine any way, just unplugging and replugging the device.

My new rules for USB to serial adapters: 38-usb-serial-adapters.rules

Stripping this file gives this:

jadler@server:~$ grep -v ‘^#’ /etc/udev/rules.d/38-usb-serial-adapters.rules | grep -v ‘^$’
SUBSYSTEM!=”usb”, GOTO=”local_usb__rules_end”
ATTRS{idVendor}==”0403″, ATTRS{idProduct}==”6001″, GOTO=”local_usb__process_ftdi”
ATTRS{idVendor}==”067b”, ATTRS{idProduct}==”2303″, GOTO=”local_usb__process_prolific”
SUBSYSTEM==”usb”, GOTO=”local_usb__rules_end”
LABEL=”local_usb__process_ftdi”
ATTRS{serial}==”A6007NVf”, SYMLINK+=”ftdi-md-bub-$attr{serial}”
ATTRS{serial}==”A6007Cp2″, SYMLINK+=”ftdi-sf-basic-5v-$attr{serial}”
ATTRS{serial}==”A6007CId”, SYMLINK+=”ftdi-sf-basic-5v-$attr{serial}”
ATTRS{serial}==”A6007DtI”, SYMLINK+=”ftdi-sf-bob-$attr{serial}”
ATTRS{serial}==”A6007Dtw”, SYMLINK+=”ftdi-sf-bob-$attr{serial}”
ATTRS{serial}==”FTE3HIKO”, SYMLINK+=”ftdi-ftdi-cable-$attr{serial}”
ATTRS{serial}==”A7006QLL”, SYMLINK+=”ftdi-arduino-2k9-$attr{serial}”
SUBSYSTEM==”usb”, GOTO=”local_usb__rules_end”
LABEL=”local_usb__process_prolific”
ATTRS{bcdDevice}==”0300″, ATTRS{product}==”USB-Serial Controller”, SYMLINK+=”pl2303-gs-ps2-%n”
ATTRS{bcdDevice}==”0202″, SYMLINK+=”pl2303-%M-%m-%n”
LABEL=”local_usb__rules_end”

As you see I use the serial numbers to assign different symlinks to the adapters, and since I have (or might have in the future) more than one of each I chose to attach the serial number to the more readable part of the symlink.

I am not sure how to make an unconditional goto, so I use a condition that I know is true (SUBSYSTEM==”usb”) in order to make unconditional jumps.

Bookmark and Share

Technorati Tags: , , , , ,

One Response to “Improved udev rules for mcu programmers and usb serial adapters”

  1. [...] Improved udev rules for mcu programmers and usb serial adapters [...]

Leave a Reply