The devices in /dev/bus/usb/XXX/YYY
follow naming policies in the kernel as noted Gilles in the comments. XXX
is the bus number which is quite stable, but YYY
changes every time the USB device gets enumerated (when a device just got inserted or reset). This cannot be changed and you shouldn't have to change this either.
If you need to change permissions on the device (for example, to make an unprivileged userspace USB driver possible for testing purposes), then you could make a udev rule. An example where I use udev
to control the permissions such that adb
is able to connect to the device:
# /etc/udev/rules.d/42-usb-permissions.rules
SUBSYSTEM!="usb", GOTO="end_skip_usb"
# CWM 6.0.4.3 in recovery mode
ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="d001", GROUP="peter"
# CM 10.2 with MTP disabled
ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="d002", GROUP="peter"
ATTRS{idVendor}=="148f", ATTRS{idProduct}=="5372", GROUP="peter"
LABEL="end_skip_usb"
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 :-)
Best Answer
Note: This is a Linux answer; other kernels will have a slightly different way to deal with this.
Context:
It is difficult to talk about USB buses without talking about PCI buses. A CPU cannot directly talk to a USB bus but what happens is that the CPU talks to a PCI bus that has a USB controller connected to it (and a USB controller/hub is what
lsusb
calls a USB bus). PCI buses are numbered based on how far from the CPU they are, for example:Looking in
man lspci
we see the following:Therefore we now know how to interpret PCI numbers. Next, we will look at USB controllers connected to the PCI buses. The machine I am currently at has an interesting USB configuration so I'll use it as an example:
Wait wait wait, what are all those pluses? At the top, we have the domain and the PCI bus
-[0000:00]
(this machine has only one PCI bus). And then we have several devices connected to that bus. Let's see which ones are USB devices:Good, now let us compare that against
lsusb
(I usesort
just to make it easier to search the list later):Wait again. We have 7 USB devices according to
lspci
but 10 devices according tolsusb
!lspci
only lists the USB controllers; a controller can have more than one USB device attached to it. Let's explore/sys/bus/
to see how this happens.Now, this is starting to make sense: we have 7 USB controllers which are plugged into the PCI bus as devices. For example, the USB bus 001 corresponds to the PCI device
0000:00:12.2
and USB bus 007 corresponds to the0000:00:14.5
device.Device numbering:
The directories starting with the USB bus number (e.g.
7-1:1.2
) are the actual devices connected to the USB controller. Just like a PCI bus can have several devices connected, a USB controller (a hub) can have several USB devices connected to it.Device numbers are simply counters: the first device connected gets a 1, the next gets a 2, and so on. But there is a little more: USB was designed to be hot-pluggable; therefore you can connect and disconnect devices. When you disconnect a USB device, the device number will not be used by the kernel again for any other device on that USB controller. For example, if you connect and disconnect a pen drive and keep doing
lsusb
you will see the device number for your pen drive going up.Bus numbering:
If you have read the above with attention, you might be wondering about one thing that I did not touch. The order of the PCI numbering does not correspond to the order in which the USB controllers were numbered! Let's see that again:
The list is in order, but not quite. The first two USB controllers seem to be out of order. Yet, there is a reason why: If you look closely at the output of
lspci
above, you will see that those areEHCI
USB (USB 2.0), whilst all other USB controllers areOHCI
USB (USB 1.x).Therefore we can redraw this table as:
And the number assignment becomes clear!