Blog

Fester Gerätepfad zum USB Gerät mit udev unter Linux

am in: Linux

Verbindet man einen Microcontroller per USB an ein Linuxsystem, wird das Gerät typischerweise1 unter /dev/ttyUSB[0-9]* (FT232, CH340, CP210x) oder /dev/ttyACM[0-9]* (Arduino) angelegt. Die Nummer hängt von der Reihenfolge ab, mit welcher die Geräte am System angeschlossen werden. Das Erste bekommt die Null, das Darauffolgende die Eins und so weiter.

Benutzt man nun mehrere Geräte gleichzeitig, kann es schnell unübersichtlich werden und häufig verliert man dabei den Überblick, welches Gerät nun unter einem bestimmten Pfad erreichbar ist. Zu allem Überfluss werden auch noch beim Ab- und Anstecken die Gerätepfade neu vergeben. Das Chaos ist also vorprogrammiert.

In diesem Beispiel sind folgende Geräte am Rechner angeschlossen. Für diese werden fixe Gerätepfade konfiguriert:

Um den Geräten nun eine eindeutige Adresse zu vergeben, verschafft man sich zunächst einmal einen Überblick über die verfügbaren USB Geräte.

$ lsusb
Bus 006 Device 005: ID 1a86:7523 QinHeng Electronics CH340 serial converter
Bus 002 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Bus 002 Device 003: ID 2341:0042 Arduino SA Mega 2560 R3 (CDC ACM)
Bus 002 Device 004: ID 2341:003d Arduino SA Due Programming Port

Die tabellarische Ausgabe von lsusb2 liefert - neben USB-Busnummer, Gerätenummer und Beschreibung - ein idVendor:idProduct Paar. Dabei ist der erste Teil, wie der Name schon sagt, die Herstelleridentifikationsnummer und der zweite Teil die Produktnummer. Diese werden vom USB Implementers Forum, Inc. (USB-IF)3 vergeben.

Anschließend werden die Gerätepfade ausgelesen:

$ ls -w1 {/dev/ttyUSB*,/dev/ttyACM*}
/dev/ttyACM0
/dev/ttyACM1
/dev/ttyUSB0
/dev/ttyUSB1

Mit dieser Information lässt es sich leider nicht ableiten, welche Geräte nun hinter den Pfadangaben stecken. Daher werden nun neue udev-Regeln erstellt, um ein Schema nach /dev/HERSTELLER/GERÄT/SERIENNUMMER zu erzeugen:

$ vim /etc/udev/rules.d/77-arduino-ftdi.rules
# Arduino Due
SUBSYSTEMS=="usb", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="003d", SYMLINK+="arduino/due/%s{serial}"
# Arduino Mega
SUBSYSTEMS=="usb", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0042", SYMLINK+="arduino/mega/%s{serial}"
# NodeMCU ESP8266
SUBSYSTEMS=="usb", KERNEL=="ttyUSB[0-9]*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="nodemcu/%s{serial}"
# FTDI UART
SUBSYSTEMS=="usb", KERNEL=="ttyUSB[0-9]*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="ftdi/%s{serial}"

Abschließend:

$ udevadm trigger
Ergebnis:
$ ls /dev/arduino/
due mega
$ ls /dev/arduino/due/
9573033383
$ ls /dev/arduino/mega/
7573432393

  1. What is the difference between /dev/ttyUSB and /dev/ttyACM?, Samuel Tardieu 

  2. lsusb ist in usbutils enthalten. 

  3. Wer selber mal USB Geräte herstellen möchte, kann sich gegen eine kleine Menge Geld eine eigene vendor ID besorgen.