How to bind USB device under a static name?
Solution 1
As suggested, you can add some udev rules. I edited the /etc/udev/rules.d/10-local.rules
to contain:
ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="my_uart"
You can check for the variables of your device by running
udevadm info -a -p $(udevadm info -q path -n /dev/ttyUSB0)
There is a more in depth guide you can read on http://www.reactivated.net/writing_udev_rules.html
Solution 2
The rule syntax above may work on some distributions, but did not work on mine (Raspbian). Since I never found a single document that explains all the ins and outs, I wrote my own, to be found here. This is what it boils down to.
-
Find out what's on ttyUSB:
dmesg | grep ttyUSB
-
List all attributes of the device:
udevadm info --name=/dev/ttyUSBx --attribute-walk
(with your device number(s) instead of x, of course). Pick out a unique identifier set, eg idVendor + idProduct. You may also need SerialNumber if you have more than one device with the same idVendor and idProduct. SerialNumbers ought to be unique for each device.
-
Create a file
/etc/udev/rules.d/99-usb-serial.rules
with something like this line in it:SUBSYSTEM=="tty", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678", SYMLINK+="your_device_name"
assuming you don't need a serial number there, and of course with the numbers for idVendor and idProduct that you found in step 2.
-
Load the new rule:
sudo udevadm trigger
Edit 2021, july 6: While this worked fine on said distribution at the time (2015), on Archlinux, and perhaps other distributions, you may need to first do
sudo udevadm control --reload
, if automatic loading fails. -
Verify what happened:
ls -l /dev/your_device_name
will show what ttyUSB number the symlink went to. If it's
/dev/ttyUSB1
, then verify who owns that and to which group it belongs:ls -l /dev/ttyUSB1
-
Then just for the fun of it:
udevadm test -a -p $(udevadm info -q path -n /dev/your_device_name)
Solution 3
The multiple-identical-USB-device problem
I have a Rasperry Pi with four cameras. I take pix with fswebcam
which identifies the cameras as /dev/video0
.. video3
. Sometimes the camera is video0
, vide02
, video4
and video6
but we can forget about that for now.
I need a persistent ID to identify a camera number so that, e.g. video0
is always the same camera because I caption the pictures. Unfortunately this doesn’t happen reliably - on boot, the cameras get enumerated as video0
..video3
but not always the same way.
The cameras all have the same ID and serial number.
The solution to this problem involves udev rules, but there's a lot of fishhooks there as well.
If you issue the command
udevadm info –attribute-walk –path=/dev/video0
you get a screed of output but the salient bits are
KERNEL=”video0”, SUBSYSTEM=”video4linux” and KERNELS=”1:1.2.4:1.0”.
The KERNELS bit is a USB hub port. With four cameras there are four of these - they do not change on reboot , but the video{x}
associated with a port may change.
So we need a udev rule to tie a video number to a USB hub port - something like:
KERNEL==”video0”,SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0”,SYMLINK+=”camera0”
Looks simple – access the camera with
fswebcam –d $realpath /dev/camera0
Except it doesn’t work – if you put this in a udev rule and the system has allocated video0 (on boot) to a different port, the udev rule is ignored. The symlink to /dev/camera0
basically says no such device
. Square one.
What we want is to bind a symlink to a USB hub address, not a video{x}
number. It took a Python program.
First step was to run
fswebcam –d /dev/video${x} tst.jpg
for x
between 1 and 8. The existence of tst.jpg
after each call identifies whether there is a camera on this video number. From this make a list of active video numbers. My experience has been that it is either 0,1,2,3
or 0,2,4,6
for cameras I have used.
Others may of course build this list using a different process.
Then for each video number in the list run
udevadm info –attribute-walk –path=/dev/videox > dd
and extract the KERNELS= line
from dd
. From this process you end up with a list of the USB port addresses for the cameras. Sort this list so that at the next step, you always process it in the same order. Call this the "address list".
Run the udevadm … > dd
thing again and make a list that looks like
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camerax”. Call this the “video list”.
Now step through the address list - for each entry find the corresponding entry from the video list. Create a new list that looks like a collection of lines like
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camera2”
The x (symlink number) is replaced by the sequence number in the address list.
Now you have a udev rule that works. A symlink that is tied to a USB hub address no matter what video number is allocated to that port at boot.
Write the final list into a file /etc/udev/rules.d/cam.rules
. Run udevadm trigger
to activate it and the job is done. /dev/camera2
will be the same camera (USB port) regardless of its video number.
Solution 4
I was also able to find a unique device in /dev/serial/by-id
. I haven't tried a reboot yet, but the files in that directory were just links to the appropriate device file (ttyACM[0-9]
).`
I am running arch linux on Raspberry Pi, but I stumbled across them just by doing a find
for filenames containing "Arduino". My python programs run fine using those files as devices to read/write data to/from my Arduinos (so far, two on a single Pi).
Solution 5
There are plenty of good answers here, but they all work for a specific VID:PID. After a lot of fiddling with udev rules for multiple brands of serial adapters, I find this simple udev rule works best for me:
ACTION=="add", SUBSYSTEM=="tty", SUBSYSTEMS=="usb", DRIVERS=="usb", SYMLINK+="tty.usb-$attr{devpath}"
It yields persistent symlinks based on the path to the device on the USB bus, for example:
$ lsusb -t # output filtered for tty devices only
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 1: Dev 5, If 0, Class=, Driver=, 480M
|__ Port 2: Dev 6, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 3: Dev 20, If 1, Class=CDC Data, Driver=cdc_acm, 12M
|__ Port 3: Dev 20, If 0, Class=Communications, Driver=cdc_acm, 12M
|__ Port 2: Dev 7, If 0, Class=Hub, Driver=hub/5p, 480M
|__ Port 3: Dev 17, If 0, Class=Vendor Specific Class, Driver=cp210x, 12M
|__ Port 4: Dev 16, If 0, Class=Vendor Specific Class, Driver=cp210x, 12M
|__ Port 5: Dev 10, If 0, Class=Hub, Driver=hub/5p, 480M
|__ Port 5: Dev 12, If 0, Class=Vendor Specific Class, Driver=cp210x, 12M
$ ls -alF /dev/tty.usb*
lrwxrwxrwx 1 root root 7 Aug 2 10:33 /dev/tty.usb-1.2.2.3 -> ttyUSB2
lrwxrwxrwx 1 root root 7 Aug 2 10:33 /dev/tty.usb-1.2.2.4 -> ttyUSB1
lrwxrwxrwx 1 root root 7 Aug 2 09:04 /dev/tty.usb-1.2.2.5.5 -> ttyUSB0
lrwxrwxrwx 1 root root 7 Aug 2 10:40 /dev/tty.usb-1.2.3 -> ttyACM0
Related videos on Youtube
Nghia Nguyen
Updated on September 18, 2022Comments
-
Nghia Nguyen over 1 year
How do I use
ScrollToHorizontalOffset
in windows phone 7? My code doesn't work:imagesScrollview.InvalidateScrollInfo(); imagesScrollview.ScrollToHorizontalOffset(current); imagesScrollview.UpdateLayout();
a working example would be nice!
-
Matt Lacey almost 13 yearspossible duplicate of why my scrollviewer don't work in WP7?
-
Matt Lacey almost 13 yearsplease don't repost your questions. see stackoverflow.com/faq#bounty
-
Nghia Nguyen almost 13 yearssorry I'm frustrated Just wonder if anyone has work with ScrollToHorizontalOffset in windows phone 7 before :-s
-
Nghia Nguyen almost 13 yearsCan anyone give me a very simple working of ScrollToHorizontalOffset in windows phone 7 please?
-
Admin about 11 yearsJust write a simple udev-rule which will assign symlink /dev/arduino to right devise by its VID & PID.
-
Admin about 11 yearsCheck arch-wiki: wiki.archlinux.org/index.php/Udev#Writing_udev_rules
-
-
k0pernikus about 11 yearsWorked like a charm. One question: How to exit
udevam
? And it is important to note thatmy_uart
creates the symlink under/dev/my_uart
. I first wrote/dev/arduino
the first time and it failed whilstarduino
is sufficient. -
Kotte about 11 years
udevadm
should exit by itself when it's done. -
k0pernikus about 11 yearsThen for some unknown reason it froze the terminal session to my Raspberry Pi while generating the report.
-
Steven Lu almost 9 yearsSo is there any solution if the
idVendor
andidProduct
are exactly the same? (two sensors attached on identical model USB to UART modules) -
RolfBly almost 9 years@StevenLu Yes, see step 2, do
udevadm info --name=/dev/ttyUSB1 --attribute-walk
for both devices and look for serial numbers, they should be unique for each device. If your sensors have no serial number, can you specify what they are? -
Steven Lu almost 9 yearsthat's awesome, i will report back when i try this out
-
Steven Lu almost 9 yearsMy $2 USB to UART dongles have serial number 0001. Can't say I'm surprised. Looks like I have to identify the sensors based on their output protocol.
-
RolfBly over 8 years@StevenLu Bad luck. FTDI USB-UART converters do have a unique serial number, AFAIK. A few extra bucks, but less time to develop.
-
mcr almost 8 yearsIf we could get the physical port # on the USB hub (whether internal or external), then we could name things somewhat better. I haven't found a way to do this. The USB device numbers are assigned, and not consistently on each boot.
-
k0pernikus over 7 yearsWelcome on unix stackexchange. Please format your answer using markdown. I just did it for you. Also keep in mind that we want answers to be to the point. This reads more like a blog entry (which is not entirely bad) yet it's not that helpful to first read about approaches that didn't work. You may scrap that part.
-
Ian Boag over 7 yearsSorry. I'm new here. I have researched this problem for months. I did find others struggling with the same problem and I did not find an answer that worked for me. Just so I know, where would you advise that I post something like this? I did restrain myself and not include the Python source :-)
-
Daniel Porteous about 4 yearsFor anyone else stumbling along this, I was able to make it work with just
ATTRS{idVendor}=="1058", ATTRS{idProduct}=="259f", SYMLINK+="externalhdd"
. The device then appeared at/dev/externalhdd
after runningsudo udevadm trigger
. This is on Ubuntu 18.04. -
Pylinux about 4 yearsWhat's the benefit of doing your command vs. just
udevadm info -a -n /dev/ttyUSB0
-
aggieNick02 over 3 yearsI think this answer is great. :-) It shows an approach to take when the serial number answer is not an option. It outlines the thought process behind the answer and why the first more obvious option doesn't work.
-
Nigel Atkinson about 3 yearsNice - now my esp32 and my ft232h for debugging get swapped if I plug them in different orders, but the aliases stay the same :-)
-
Pro Backup almost 3 years@RolfBly Without
# udevadm control --reload
the# udevadm trigger
doesn't use the new/changed rules on Raspberry-Arch in my case. -
mrid almost 3 yearsWeird how my converter has the exact same vendor ID and product ID :/
-
domsson almost 3 yearsIs
ACTION=="add"
required? What does it do? Other examples do not have it; it is also not explained in the link to the guide. Also, what would be the difference betweenSYMLINK+="my_uart"
andNAME="my_uart"
? -
Pablo A over 2 yearsOn some systems
ll
isn't an alias ofls -alF
and the path might be different,ls -alF /dev/ttyUSB*
-
G-Man Says 'Reinstate Monica' about 2 years(1) You obviously put a lot of work into this. But, maybe I’m missing something — I don’t see how it answers the question. The OP wants to write a script that access his device without needing to determine its dynamic name. How can he do that? (2) What is the
ID_PATH
variable? (3) It’s difficult (if not impossible) to use quotes in a{program}="/bin/sh -c '…'"
command because it’s already quoted twice. But what does that have to do with anything? You can say-d-
or-d -
without using quotes. … … Please do not respond in comments; edit your answer to make it clearer and more complete. -
user8472 about 2 yearsGreat thoughts. I've tried to clarify a few points and address each of the issues you listed. - Thanks