如何获取/dev/ttyUSB的总线和设备关系

我需要编写一个脚本来重新启动USB dongles。我有所有的工具,但是我无法将我的/dev/ttyUSBx连接到物理总线和设备。问题在于我有三个具有相同供应商ID和产品ID的dongles。
如果我执行lsusb命令,输出如下:
Bus 001 Device 004: ID 12d1:1003 Huawei Technologies Co., Ltd. E220 HSDPA Modem / E270 HSDPA/HSUPA Modem
Bus 001 Device 006: ID 12d1:1003 Huawei Technologies Co., Ltd. E220 HSDPA Modem / E270 HSDPA/HSUPA Modem
Bus 001 Device 007: ID 12d1:1003 Huawei Technologies Co., Ltd. E220 HSDPA Modem / E270 HSDPA/HSUPA Modem
Bus 001 Device 002: ID 80ee:0021
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

我已经附上了。
/dev/ttyUSB0
/dev/ttyUSB3
/dev/ttyUSB5

但是我想知道哪个设备与哪个总线设备相关。例如,我需要获取以下信息:
/dev/ttyUSB0 -> Bus 001 Device 006
/dev/ttyUSB3 -> Bus 001 Device 004
/dev/ttyUSB5 -> Bus 001 Device 007

我正在使用Ubuntu Server 10.04,我已经测试了这些工具:
lsusb
hal
lsmod

但是我无法得到这个关系。
3个回答

实际上,没有一种“好”的方法可以将字符设备(如/dev/ttyUSB0)映射到相应的USB设备和总线号。但是,这是可能的!

类似以下的命令可能有效:

udevadm info --name=/dev/ttyUSB0 --attribute-walk

从那里,您将获得有关设备及其父设备的大量信息。现在,只需解析这些数据以获取所需内容。我过去使用过这个方法:

echo /dev/bus/usb/`udevadm info --name=/dev/ttyUSB0 --attribute-walk | sed -n 's/\s*ATTRS{\(\(devnum\)\|\(busnum\)\)}==\"\([^\"]\+\)\"/\4/p' | head -n 2 | awk '{$1 = sprintf("%03d", $1); print}'` | tr " " "/"

现在,如果这不是一个冗长的话,我就不知道还有什么了!让我们来分解一下: udevadm info --name=/dev/ttyUSB0 --attribute-walk - 返回设备及其父设备的信息。 sed -n 's/\s*ATTRS{\(\(devnum\)\|\(busnum\)\)}==\"\([^\"]\+\)\"/\4/p' - 解析这些数据并返回包含“devnum”或“busnum”属性的行。我们假设“busnum”首先列出...在这种情况下...我们只需获取输出的前两行。 head -n 2 - 获取输出的前两行。我们可以更加复杂一些,但我们只是假设最近的父级“busnum”和“devnum”将首先列出。 awk '{$1 = sprintf("%03d", $1); print}' - 将这些数字填充为零。

echo /dev/bus/usb... - 所有这些花哨的东西都被包装在一个echo语句中,用空格替换换行符。如果你想去掉尾部的换行符,可以在echo后面加上-n

tr " " "/" - 用正斜杠替换输出中的空格。

这将输出类似以下内容:

/dev/bus/usb/001/011

"

... 当然,是设备。如果你愿意,你可以通过一些调整轻松输出像 busnum:001 devnum:011 这样的内容:

"
echo `udevadm info --name=/dev/ttyUSB0 --attribute-walk | sed -n 's/\s*ATTRS{\(\(devnum\)\|\(busnum\)\)}==\"\([^\"]\+\)\"/\1\ \4/p' | head -n 2 | awk '{$1 = sprintf("%s:%03d", $1, $2); print $1;}'`

由于我没有你的硬件,所以无法给出确切的答案。
我建议你去询问相关设备,例如:
ls -l /dev/ttyUSB0

获取主节点和次节点的编号。假设它们分别是116和7。
然后前往:
ls -l /sys/dev/char/116:7

(char,因为 tty 是一个字符设备,如果你要追踪磁盘设备,你将会指定 block 而不是 char

从命令的输出中,你会看到类似以下内容:

lrwxrwxrwx 1 root root 0 Sep 6 00:17 116:7 -> ../../devices//sys/devices/pci0000:00/0000:00:13.5/pci0000:00/0000:00:13.5/usb1/1-3/1-3:1.1/sound/card1/pcmC1D0c

目录/sys/devices/pci0000:00/0000:00:13.5/usb1/1-3/及其子目录包含有关该设备的大量信息。例如,/sys/devices/pci0000:00/0000:00:13.5/usb1/1-3/busnum/sys/devices/pci0000:00/0000:00:13.5/usb1/1-3/devnum 。在我的系统中,这些与/var/log/syslog中的设备热插拔条目中提到的总线和设备号匹配。
对于我的系统上的/dev/video0,还有其他一些方法可行。
find /sys/dev -lname '*video0' -exec cat {}/device/busnum {}/device/devnum \; 2>/dev/null

非常感谢!我已经为此奋斗了很长时间。只是为了给后来的访问者提供一点提示:在我的Ubuntu 10.04.2 LTS中,设备目录是/sys/dev/char/,而不是/sys/char/。 - Ernesto Campohermoso
谢谢你的纠正 - 我已经根据那个更改编辑了答案,并添加了一个查找命令来打印信息。 - John S Gruber
@JohnSGruber 好的,但是怎么安装它呢? - Dr.jacky
1@Mr.Hyde:你无法挂载/dev/ttyUSB;只有像磁盘驱动器一样操作的某些设备可以被挂载。 - John S Gruber

你可以使用以下命令找到有关节点的所有信息:
udevadm info -a -p /sys/bus/usb-serial/devices/ttyUSB0/

请删除末尾的斜杠。这会导致"syspath未找到"的错误。 - nvd