A useful utilities is udevadm
. For example, I have this USB serial adapter:
$ lsusb|grep -i prolific
Bus 001 Device 077: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
Running udevadm
on it yields a bunch of information. Here's the start of it:
$ udevadm info -a /dev/bus/usb/001/077
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4':
KERNEL=="1-3.4.4"
SUBSYSTEM=="usb"
DRIVER=="usb"
ATTR{authorized}=="1"
ATTR{avoid_reset_quirk}=="0"
ATTR{bConfigurationValue}=="1"
ATTR{bDeviceClass}=="00"
ATTR{bDeviceProtocol}=="00"
ATTR{bDeviceSubClass}=="00"
ATTR{bMaxPacketSize0}=="64"
ATTR{bMaxPower}=="100mA"
ATTR{bNumConfigurations}=="1"
ATTR{bNumInterfaces}==" 1"
ATTR{bcdDevice}=="0300"
ATTR{bmAttributes}=="a0"
ATTR{busnum}=="1"
ATTR{configuration}==""
ATTR{devnum}=="77"
ATTR{devpath}=="3.4.4"
ATTR{idProduct}=="2303"
ATTR{idVendor}=="067b"
ATTR{ltm_capable}=="no"
ATTR{manufacturer}=="Prolific Technology Inc."
ATTR{maxchild}=="0"
ATTR{product}=="USB-Serial Controller"
ATTR{quirks}=="0x0"
ATTR{removable}=="unknown"
ATTR{speed}=="12"
ATTR{urbnum}=="22"
ATTR{version}==" 2.00"
You can then look into sysfs
for more details:
$ ls -l '/sys//devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4'
total 0
drwxr-xr-x 7 root root 0 Oct 11 11:03 1-3.4.4:1.0
-r--r--r-- 1 root root 4096 Oct 11 11:03 bcdDevice
-rw-r--r-- 1 root root 4096 Oct 11 11:03 bConfigurationValue
-r--r--r-- 1 root root 4096 Oct 11 11:03 bDeviceClass
-r--r--r-- 1 root root 4096 Oct 11 11:03 bDeviceProtocol
-r--r--r-- 1 root root 4096 Oct 11 11:03 bDeviceSubClass
-r--r--r-- 1 root root 4096 Oct 11 11:03 bmAttributes
-r--r--r-- 1 root root 4096 Oct 11 11:03 bMaxPacketSize0
-r--r--r-- 1 root root 4096 Oct 11 11:03 bMaxPower
-r--r--r-- 1 root root 4096 Oct 11 11:03 bNumConfigurations
-r--r--r-- 1 root root 4096 Oct 11 11:03 bNumInterfaces
-r--r--r-- 1 root root 4096 Oct 11 11:03 busnum
-r--r--r-- 1 root root 4096 Oct 11 11:03 configuration
-r--r--r-- 1 root root 65553 Oct 11 11:03 descriptors
-r--r--r-- 1 root root 4096 Oct 11 11:03 dev
-r--r--r-- 1 root root 4096 Oct 11 11:03 devnum
-r--r--r-- 1 root root 4096 Oct 11 11:03 devpath
lrwxrwxrwx 1 root root 0 Oct 11 11:03 driver -> ../../../../../../../bus/usb/drivers/usb
drwxr-xr-x 3 root root 0 Oct 11 11:03 ep_00
-r--r--r-- 1 root root 4096 Oct 11 11:03 idProduct
-r--r--r-- 1 root root 4096 Oct 11 11:03 idVendor
-r--r--r-- 1 root root 4096 Oct 11 11:03 ltm_capable
-r--r--r-- 1 root root 4096 Oct 11 11:03 manufacturer
-r--r--r-- 1 root root 4096 Oct 11 11:03 maxchild
lrwxrwxrwx 1 root root 0 Oct 11 11:03 port -> ../1-3.4:1.0/1-3.4-port4
drwxr-xr-x 2 root root 0 Oct 11 11:03 power
-r--r--r-- 1 root root 4096 Oct 11 11:03 product
-r--r--r-- 1 root root 4096 Oct 11 11:03 quirks
-r--r--r-- 1 root root 4096 Oct 11 11:03 removable
--w------- 1 root root 4096 Oct 11 11:03 remove
-r--r--r-- 1 root root 4096 Oct 11 11:03 speed
lrwxrwxrwx 1 root root 0 Oct 11 11:03 subsystem -> ../../../../../../../bus/usb
-rw-r--r-- 1 root root 4096 Oct 11 11:03 uevent
-r--r--r-- 1 root root 4096 Oct 11 11:03 urbnum
-r--r--r-- 1 root root 4096 Oct 11 11:03 version
You'll notice a sub-directory (1-3.4.4:1.0
) for each implemented USB device(interface? function?) within the adapter (in my case just one; I have other 4-port USB serial adapter with 4 sub-directories too). If you look in there, you can eventually find the device node:
$ ls -l '/sys//devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4/1-3.4.4:1.0/'
total 0
-rw-r--r-- 1 root root 4096 Oct 11 11:03 authorized
-r--r--r-- 1 root root 4096 Oct 11 11:03 bAlternateSetting
-r--r--r-- 1 root root 4096 Oct 11 11:03 bInterfaceClass
-r--r--r-- 1 root root 4096 Oct 11 11:03 bInterfaceNumber
-r--r--r-- 1 root root 4096 Oct 11 11:03 bInterfaceProtocol
-r--r--r-- 1 root root 4096 Oct 11 11:03 bInterfaceSubClass
-r--r--r-- 1 root root 4096 Oct 11 11:03 bNumEndpoints
lrwxrwxrwx 1 root root 0 Oct 11 11:03 driver -> ../../../../../../../../bus/usb/drivers/pl2303
drwxr-xr-x 3 root root 0 Oct 11 11:03 ep_02
drwxr-xr-x 3 root root 0 Oct 11 11:03 ep_81
drwxr-xr-x 3 root root 0 Oct 11 11:03 ep_83
-r--r--r-- 1 root root 4096 Oct 11 11:03 modalias
drwxr-xr-x 2 root root 0 Oct 11 11:03 power
lrwxrwxrwx 1 root root 0 Oct 11 11:03 subsystem -> ../../../../../../../../bus/usb
-r--r--r-- 1 root root 4096 Oct 11 11:03 supports_autosuspend
drwxr-xr-x 4 root root 0 Oct 11 11:03 ttyUSB0
-rw-r--r-- 1 root root 4096 Oct 11 11:03 uevent
$ ls -l '/sys//devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4/1-3.4.4:1.0/ttyUSB0'
total 0
lrwxrwxrwx 1 root root 0 Oct 11 11:03 driver -> ../../../../../../../../../bus/usb-serial/drivers/pl2303
-r--r--r-- 1 root root 4096 Oct 11 11:03 port_number
drwxr-xr-x 2 root root 0 Oct 11 11:03 power
lrwxrwxrwx 1 root root 0 Oct 11 11:03 subsystem -> ../../../../../../../../../bus/usb-serial
drwxr-xr-x 3 root root 0 Oct 11 11:03 tty
-rw-r--r-- 1 root root 4096 Oct 11 11:03 uevent
$ ls -l '/sys//devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4/1-3.4.4:1.0/ttyUSB0/tty'
total 0
drwxr-xr-x 3 root root 0 Oct 11 11:11 ttyUSB0
$ ls -l '/sys//devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4/1-3.4.4:1.0/ttyUSB0/tty/ttyUSB0'
total 0
-r--r--r-- 1 root root 4096 Oct 11 11:11 dev
lrwxrwxrwx 1 root root 0 Oct 11 11:11 device -> ../../../ttyUSB0
drwxr-xr-x 2 root root 0 Oct 11 11:11 power
lrwxrwxrwx 1 root root 0 Oct 11 11:11 subsystem -> ../../../../../../../../../../../class/tty
-rw-r--r-- 1 root root 4096 Oct 11 11:11 uevent
$ cat '/sys//devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4/1-3.4.4:1.0/ttyUSB0/tty/ttyUSB0/dev'
188:0
That last line is the device node major/minor number, which you can search for in /dev, or use to create your own device node.
The directory /sys/class/tty/
lists all ttys, and /sys/bus/usb-serial/devices/
lists all USB serial adapters. It might be easier to start from those directories (rather than udevadm
) to find all relevant devices, then determine which one of those matches the USB device you care about.
$ ls -l /sys/bus/usb-serial/devices/
total 0
lrwxrwxrwx 1 root root 0 Oct 11 11:16 ttyUSB0 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4/1-3.4.4:1.0/ttyUSB0/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB1 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.1/ttyUSB1/
lrwxrwxrwx 1 root root 0 Oct 11 11:16 ttyUSB10 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.4/1-8.4:1.3/ttyUSB10/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB12 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.6/1-8.6:1.0/ttyUSB12/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB13 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.6/1-8.6:1.1/ttyUSB13/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB14 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.6/1-8.6:1.2/ttyUSB14/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB15 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.6/1-8.6:1.3/ttyUSB15/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB2 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.2/ttyUSB2/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB3 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.3/ttyUSB3/
lrwxrwxrwx 1 root root 0 Oct 11 11:16 ttyUSB4 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.4/1-8.4:1.0/ttyUSB4/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB5 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.1/ttyUSB5/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB6 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.2/ttyUSB6/
lrwxrwxrwx 1 root root 0 Sep 6 13:48 ttyUSB7 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.3/ttyUSB7/
lrwxrwxrwx 1 root root 0 Oct 11 11:16 ttyUSB8 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.4/1-8.4:1.1/ttyUSB8/
lrwxrwxrwx 1 root root 0 Oct 11 11:16 ttyUSB9 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.4/1-8.4:1.2/ttyUSB9/
If you assume that you can take those path names (the link values) and go up to ../..
and find the USB device, and find its bus/dev number. I /think/ this is safe, but it depends on whether different USB devices/drivers always lay out their sysfs identically, which I believe they do for a given device type.
$ cat '/sys/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4/1-3.4.4:1.0/ttyUSB0/../../busnum'
1
$ cat '/sys/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.4/1-3.4.4:1.0/ttyUSB0/../../devnum'
77
In general, sysfs
contains all the information you want; you just have to work out how to traverse it.