command to determine ports of a device (like /dev/ttyUSB0)

I have a question regarding the ports in Linux. If I connect my device via USB and want to check its port I can’t do it using the command lsusb, which only specifies bus number and device number on this bus:

[ziga@Ziga-PC ~]$ lsusb
Bus 003 Device 007: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC

Is there a command that tells me the port the device is connected to directly? Only way to do this until now was to disconect and reconnect and using the command:

[ziga@Ziga-PC ~]$ dmesg | grep tty
[    0.000000] console [tty0] enabled
[    0.929510] 00:09: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[    4.378109] systemd[1]: Starting system-getty.slice.
[    4.378543] systemd[1]: Created slice system-getty.slice.
[    8.786474] usb 3-4.4: FTDI USB Serial Device converter now attached to ttyUSB0

In the last line it can be seen that my device is connected to /dev/ttyUSB0.

Asked By: 71GA

||

I’m not quite certain what you’re asking. You mention ‘port’ several times, but then in your example, you say the answer is /dev/ttyUSB0, which is a device dev path, not a port. So this answer is about finding the dev path for each device.

Below is a quick and dirty script which walks through devices in /sys looking for USB devices with a ID_SERIAL attribute. Typically only real USB devices will have this attribute, and so we can filter with it. If we don’t, you’ll see a lot of things in the list that aren’t physical devices.

#!/bin/bash

for sysdevpath in $(find /sys/bus/usb/devices/usb*/ -name dev); do
    (
        syspath="${sysdevpath%/dev}"
        devname="$(udevadm info -q name -p $syspath)"
        [[ "$devname" == "bus/"* ]] && exit
        eval "$(udevadm info -q property --export -p $syspath)"
        [[ -z "$ID_SERIAL" ]] && exit
        echo "/dev/$devname - $ID_SERIAL"
    )
done

On my system, this results in the following:

/dev/ttyACM0 - LG_Electronics_Inc._LGE_Android_Phone_VS930_4G-991c470
/dev/sdb - Lexar_USB_Flash_Drive_AA26MYU15PJ5QFCL-0:0
/dev/sdb1 - Lexar_USB_Flash_Drive_AA26MYU15PJ5QFCL-0:0
/dev/input/event5 - Logitech_USB_Receiver
/dev/input/mouse1 - Logitech_USB_Receiver
/dev/input/event2 - Razer_Razer_Diamondback_3G
/dev/input/mouse0 - Razer_Razer_Diamondback_3G
/dev/input/event3 - Logitech_HID_compliant_keyboard
/dev/input/event4 - Logitech_HID_compliant_keyboard

Explanation:

find /sys/bus/usb/devices/usb*/ -name dev

Devices which show up in /dev have a dev file in their /sys directory. So we search for directories matching this criteria.
 

syspath="${sysdevpath%/dev}"

We want the directory path, so we strip off /dev.
 

devname="$(udevadm info -q name -p $syspath)"

This gives us the path in /dev that corresponds to this /sys device.
 

[[ "$devname" == "bus/"* ]] && exit

This filters out things which aren’t actual devices. Otherwise you’ll get things like USB controllers & hubs. The exit exits the subshell, which flows to the next iteration of the loop.
 

eval "$(udevadm info -q property --export -p $syspath)"

The udevadm info -q property --export command lists all the device properties in a format that can be parsed by the shell into variables. So we simply call eval on this. This is also the reason why we wrap the code in the parenthesis, so that we use a subshell, and the variables get wiped on each loop.
 

[[ -z "$ID_SERIAL" ]] && exit

More filtering of things that aren’t actual devices.
 

echo "/dev/$devname - $ID_SERIAL"

I hope you know what this line does 🙂

Answered By: phemmer

You can use this command to explore your device if connected to usb0:

udevadm info -a -p  $(udevadm info -q path -n /dev/ttyUSB0)
Answered By: Naveen

You could try something like this below.

echo -n "/dev/"; dmesg | grep tty|grep USB|rev|awk '{print $1}'|rev
Answered By: VeggieVampire

Perhaps you would like to know just the path to USB-serial adapter that connected last?

dmesg | awk '/tty/ && /USB/ {print "/dev/"$10}'|tail -1
Answered By: HRmeteohub

Assuming that you know what the device you plugged in is, in 14.04 Ubuntu, at least, there is the command usb-devices that you can look through and find the information:

$ usb-devices

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480 MxCh= 3
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0002 Rev=04.04
S:  Manufacturer=Linux 4.4.0-131-generic ehci_hcd
S:  Product=EHCI Host Controller
S:  SerialNumber=0000:00:1a.0
C:  #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=0mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub

And the first line lists bus and port, as well as the device number that lsusb gives.

Answered By: Gertlex

You can get all that info from sysfs, no need for udevadm or other programs which are not available on embedded linux systems.

vidpid_to_devs(){
        find $(grep -l "PRODUCT=$(printf "%x/%x" "0x${1%:*}" "0x${1#*:}")" 
                  /sys/bus/usb/devices/[0-9]*:*/uevent | sed 's,uevent$,,') 
           /dev/null -name dev -o -name dev_id |
        sed 's,[^/]*$,uevent,' |
        xargs sed -n -e s,DEVNAME=,/dev/,p -e s,INTERFACE=,,p
}

% vidpid_to_devs 067b:2303
/dev/ttyUSB0
% vidpid_to_devs 00da:8510
/dev/input/event6
/dev/input/event4
/dev/input/mouse1
/dev/input/event5
/dev/hidraw3
/dev/input/event7
/dev/hidraw4

The procedure is

a) look through /sys/bus/usb/devices/*:* for a device interface which matches your vendor:product tuple — the uevent file in that directory contains a PRODUCT=vendor/product/revision (all in hex form without leading zeros).

b) look for any subdirectories which contain a dev file, then get the device name from the DEVNAME= entry from the uevent file in that subdirectory. Same with dev_id and INTERFACE= for network interfaces.

Answered By: zevzek

I found @phemmer’s accepted answer regularly helpful and turned it into a bash script. I added shell process backgrounding to make it run a bit faster for lots of USB devices connected to a system (which when this is most useful).

#!/bin/bash                                                            
#findusbdev.sh
                                                           
if [[ "$1" =~ ^(-h|--help)$ ]]; then                                   
                                                                       
echo "Find which USB devices are associated with which /dev/ nodes     
Usage:                                                                 
  $0 [-h|--help] [searchString]                                        
                                                                       
  -h | --help   Prints this message                                    
  searchString  Print only /dev/<device> of matching output            
                With no arguments $0 prints information for all        
                possible USB device nodes                              
                                                                       
E.g. $0 "FTDI_FT232" - will show /dev/ttyUSBX for a device using     
the FTDI FT232 chipset.                                                
"                                                                      
    exit 0                                                             
fi                                                                     
                                                                       
devs=$( (                                                              
for sysdevpath in $(find /sys/bus/usb/devices/usb*/ -name dev ); do    
    # ( to launch a subshell here                                      
    (                                                                  
        syspath="${sysdevpath%/dev}"                                   
        devname="$(udevadm info -q name -p $syspath)"                  
        [[ "$devname" == "bus/"* ]] && exit                            
        eval "$(udevadm info -q property --export -p $syspath)"        
        [[ -z "$ID_SERIAL" ]] && exit                                  
        echo "/dev/$devname - $ID_SERIAL"                              
    )& # & here is causing all of these queries to run simultaneously  
done                                                                   
# wait then gives a chance for all of the iterations to complete       
wait                                                                   
# output order is random due to multiprocessing so sort results        
) | sort )                                                             
                                                                       
                                                                       
if [ -z "$1" ]; then                                                   
    echo "${devs}"                                                     
else                                                                   
    echo "${devs}" | grep "$1" | awk '{print $1}'                      
fi                                                                     

Example usage:

$ ./findusbdev.sh 
/dev/input/event15 - Peppercon_AG_Multidevice_E999EC989B0BAFB78F9F225288EC6B0A
/dev/input/event16 - Peppercon_AG_Multidevice_E999EC989B0BAFB78F9F225288EC6B0A
/dev/input/mouse0 - Peppercon_AG_Multidevice_E999EC989B0BAFB78F9F225288EC6B0A
/dev/ttyUSB0 - FTDI_FT230X_Basic_UART_D308B2AI
/dev/ttyUSB1 - FTDI_FT232R_USB_UART_AH07DPSR
$ ./findusbdev.sh FT230X
/dev/ttyUSB0
$ ./findusbdev.sh -h
Find which USB devices are associated with which /dev/ nodes
Usage:
  ./findusbdev.sh [-h|--help] [searchString]

  -h | --help   Prints this message
  searchString  Print only /dev/<device> of matching output
                With no arguments ./findusbdev.sh prints information for all 
                possible USB device nodes

E.g. ./findusbdev.sh "FTDI_FT232" - will show /dev/ttyUSBX for a device using 
the FTDI FT232 chipset.

Answered By: user8472
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.