programatically determine and set the correct SerialPort(#) for known attached USB devices

I’m setting up some RPi systems with attached serial (USB) devices, and at restart I’m not 100% certain that the USB (FTDI USB Serial Device) devices will always retain their same names. So rather than count on ‘/dev/ttyACM0’ always being a correct port-name I want to sort it out thru some solid code.

I’ve tried a number of things, for instance using the ‘lsusb’ command gets me the following:

pi@raspberrypi:/dev $ lsusb Bus 001 Device 005: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port Bus 001 Device 004: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO) Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

…but that doesn’t tell me what System.SerialPort(port#) the device is connected to, only what it’s position on the bus is.

Newer linux distributions have good support for the ‘dmesg’ command, and when I use that I can see this…

pi@raspberrypi:/dev $ dmesg | grep -i ttyUSB [22880.344951] usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB0 [23141.726348] usb 1-1.4: pl2303 converter now attached to ttyUSB1

My thought was to use a Shell.Execute to pull this data, then knowing that I want to know about ‘PL2303’, I could use the information telling me that it’s on ‘ttyUSB1’ and loop over System.SerialPort(i).Name values to find the right one.

This isn’t ideal, because the ‘dmesg | grep -i ttyUSB’ command doesn’t return information consistently across all linux distributions.

Another complication is that a couple of attached USB devices (in my case a series of weighing scales) both use identical drivers, so the ‘lsusb’ info returns two identical lines for both of the attached scales.

Having said all that, my question is if there’s a way to use a Shell or other means of ‘asking’ the RPi about it’s attached serial devices, using the returned information to set the correct System.SerialPort(port#).


I just loop thru all serialports and try to open. If it opens, I’ll ask if it is right device.
If it does not open or does not answer, I’ll go to next port.
When I find right port, I save it, and check that first next time.

First scan takes a little longer but usually next time it’s the same, so it’s fast.


Hi Jukka,

That’s how I’d usually do it - but in this case the serial devices on the other end do not respond to any ‘requests’, they run silent. In other words there may be no system online at the time the system boots, and someone may plug a device in after boot up. The ports (RS-232) are labeled on the box, and users would plug the right device into the right port, but at the time the system boots the port may be empty. This is where I’m hoping to use magic to query the OS, find out that Virtual Serial Port is assigned to which hardware address.

Thanks for your help!


Hi William

I have exactly ther same problem 3 RS232to USB converters on one RPI3, I managed solved such issue with creation of Symlink.
First you have to find port of connected device. If it is for example ttyUSB1 use the code for additional parameters

udevadm info -a -p  $(udevadm info -q path -n /dev/ttyUSB1)

Find the following attributes.

 ATTRS{idVendor}=="0557" // is the same for all devices in my case
 ATTRS{idProduct}=="2008" //  is the same for all devices in my case
 ATTRS{devpath}=="1.2" //port to which USB device is connected is different

Create symlink

Sudo nano /etc/udev/rules.d/99-usb-serial.rules

Add line

SUBSYSTEM=="tty", ATTRS{idVendor}=="0557", ATTRS{idProduct}=="2008", ATTRS{devpath}=="1.3", SYMLINK+="printer" 
sudo udevadm trigger
ls -l /dev/printer

Nov you have your device available as /dev/printer
Sometimes you have to restart device for simlink to start working.


This worked perfectly, thanks! I’d tinkered with symbolic links a bit before and gave up with it seemed like it might be unreliable - however it turns out that isn’t the case.

I did learn a few things along the way and I’ll leave the breadcrumbs in here to help others. First, when using ‘nano’ to edit the .rules file be sure not to paste bad characters in. I got hung up for the longest time with a bad ‘quote’ character that I only found when things didn’t work, and when I processed the rules manually via ‘udevadm test’, and the terminal output called out an unexpected character it encountered when processing my .rules file.

I also had great luck when shortening the link to just the idVendor and idProduct as in my case these are two totally unique devices on my system. Thanks again for everyones help!

ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", SYMLINK+="ttyUSB-Anybus" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", SYMLINK+="ttyUSB-Sensor"

Hi @alll

I’m using RPi 3 with the latest Raspbian Jessie with Pixel Version 4.4 2017-01-11.
I tried a USB 2 Serial adapter (FTDI) and it don’t work with “Serial Port Bar Code Reader” Example.

Test on CLI and hexdump works fine. Test with MacOS too.

Any ideas what’s wrong?

What is “CLI”?

CLI Command line Interface = Shell

pi@raspberrypi:~ $ cat /dev/ttyUSBxx | hexdump

Hi Volkmar, I compiled and ran the “Serial Port Bar Code Reader” example and for me it worked fine. I was able to see all the USB devices, including those I created symlinks for.

I’m using “Raspbian Jessie”, here are the details on my OS:

pi@raspberrypi:~ $ cat /proc/version
Linux version 4.4.38-v7+ (dc4@dc4-XPS13-9333) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611) )

Question: Does the compiled app run on your system? Does the SerialPortsPopupMenu populate with any entries?