How to lock device id's to port addresses?

13,388

The kernel-assigned names are always assigned in the order the devices are detected, and you cannot change them. (Not anymore, anyway – this function was removed due to various race conditions that "persistent name" rules caused.)

But you can tell udev to create symlinks with whatever names you choose. In fact, on modern systems, you should already have symlinks under /dev/serial named after both the device's path, and its unique ID; for example:

  • /dev/serial/by-path/pci-0000:00:1a.0-usb-0:1.2:1.0ttyUSB0

  • /dev/serial/by-id/usb-Motorola_Inc._Motorola_Phone__C350_-if00ttyACM0

  • /dev/disk/by-id/ata-ST9640320AS_5WX1ZH91-part1sda1

  • /dev/disk/by-partlabel/Archsda3

  • /dev/input/by-id/usb-PIXART_USB_OPTICAL_MOUSE-mousemouse1

And so on. Just run tree /dev or ls -lR /dev to find your device.

You can also run udevadm info /dev/ttyUSB0 and all symlinks to that device will be listed as S: ... lines.


If this is not enough, you can write your own udev rules. First run udevadm info /dev/ttyUSB0 and choose any identifying property (such as ID_PATH for the USB port). It's a good idea to always include the subsystem as well.

Then open (or create) a file in /etc/udev/rules.d/ (named, for example, serial-symlinks.rules), and put the udev rule there.

For example, if the output for ttyUSB0 is:

$ udevadm info /dev/ttyUSB0
. . .
E: ID_PATH=pci-0000:00:1d.0-usb-0:1.2:1.0
. . .
E: SUBSYSTEM=tty
. . .

...you can write this rule:

SUBSYSTEM=="tty", ENV{ID_PATH}=="pci-0000:00:1d.0-usb-0:1.2:1.0", SYMLINK+="tty-xbee"

...and udev will always symlink /dev/tty-xbee to whatever tty device you connected to USB port #2.


(Note: Do not use the same names for symlinks as the kernel uses for device nodes. Using SYMLINK+="ttyUSB0" will cause bad things to happen.)

Share:
13,388

Related videos on Youtube

Christian
Author by

Christian

Updated on September 18, 2022

Comments

  • Christian
    Christian over 1 year

    I want to dedicate certain USB ports to certain devices. How can I do that?

    For example: I want ttyUSB0 to be my mouse and ttyUSB1 to be my keyboard (always). I want to be certain that the startup of Linux never swaps them.

    Acctually the thing is that I have XBee who usally goes to USB0 and a second FTDI that goes to USB1, for security reason I always want them to have the same address in my code I'm running.

    Kind regards

    • Christian
      Christian over 11 years
      How could I possibly be mistaken of what OS I'm running? This is Debian on a Raspberry Pi.
  • Christian
    Christian over 11 years
    Excellent post! Thanks. Some time when I stop my code I note that XBee will change port from USB0 to USB1. I don't know the cause of this, but if I in my code instead of using path /dev/ttyUSB0 uses for example /dev/serial/by-id/usb-Motorola_Inc._Motorola_Phone__C350_-if‌​00 this problem will be solved, right?
  • user1686
    user1686 over 11 years
    @Christian: Yes.
  • Julio Guerra
    Julio Guerra over 8 years
    @grawity are the pci and usb port IDs under ` /dev/serial/by-path/` allocated according to the physical topology or according to a random (for any reason like parallel discovery) discovery order?
  • user1686
    user1686 over 8 years
    @JulioGuerra: They're supposed to represent physical topology (that's pretty much the whole point of by-path over raw sequential tty* names). Note how the pci tag is followed by PCI domain:bus:slot.func, for example. /// That said, the physical topology can change too, if the firmware decides so – I've heard of a few PCs where the same physical PCI slot would get a different ID depending on whether other slots were filled... If that's also a concern, use by-id names.