问题描述
我在笔记本电脑(Ubuntu 9.10)上使用了许多相同的 USB-to-serial 适配器。适配器由 Sabrent 制造,围绕 Prolific PL2303 IC 构建,如 lsusb
所示:
Bus 001 Device 008: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
Bus 001 Device 007: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
Bus 001 Device 006: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
udevadm
显示的所有属性似乎都不是特定适配器所独有的:
foo@bar:~$ udevadm info --attribute-walk --path=/sys/bus/usb-serial/devices/ttyUSB0
looking at device
'/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.1/1-4.1:1.0/ttyUSB0':
KERNEL=="ttyUSB0"
SUBSYSTEM=="usb-serial"
DRIVER=="pl2303"
ATTR{port_number}=="0"
looking at parent device
'/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.1/1-4.1:1.0':
KERNELS=="1-4.1:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="pl2303"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bNumEndpoints}=="03"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceSubClass}=="00"
ATTRS{bInterfaceProtocol}=="00"
ATTRS{modalias}=="usb:v067Bp2303d0300dc00dsc00dp00icFFisc00ip00"
ATTRS{supports_autosuspend}=="1"
looking at parent device
'/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.1':
KERNELS=="1-4.1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{configuration}==""
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bmAttributes}=="80"
ATTRS{bMaxPower}=="100mA"
ATTRS{urbnum}=="538"
ATTRS{idVendor}=="067b"
ATTRS{idProduct}=="2303"
ATTRS{bcdDevice}=="0300"
ATTRS{bDeviceClass}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bNumConfigurations}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{speed}=="12"
ATTRS{busnum}=="1"
ATTRS{devnum}=="6"
ATTRS{version}==" 1.10"
ATTRS{maxchild}=="0"
ATTRS{quirks}=="0x0"
ATTRS{authorized}=="1"
ATTRS{manufacturer}=="Prolific Technology Inc."
ATTRS{product}=="USB-Serial Controller"
<snip>
foo@bar:~$ udevadm info --attribute-walk --path=/sys/bus/usb-serial/devices/ttyUSB1
looking at device
'/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.5/1-4.5:1.0/ttyUSB1':
KERNEL=="ttyUSB1"
SUBSYSTEM=="usb-serial"
DRIVER=="pl2303"
ATTR{port_number}=="0"
looking at parent device
'/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.5/1-4.5:1.0':
KERNELS=="1-4.5:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="pl2303"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bNumEndpoints}=="03"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceSubClass}=="00"
ATTRS{bInterfaceProtocol}=="00"
ATTRS{modalias}=="usb:v067Bp2303d0300dc00dsc00dp00icFFisc00ip00"
ATTRS{supports_autosuspend}=="1"
looking at parent device
'/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.5':
KERNELS=="1-4.5"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{configuration}==""
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bmAttributes}=="80"
ATTRS{bMaxPower}=="100mA"
ATTRS{urbnum}=="69"
ATTRS{idVendor}=="067b"
ATTRS{idProduct}=="2303"
ATTRS{bcdDevice}=="0300"
ATTRS{bDeviceClass}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bNumConfigurations}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{speed}=="12"
ATTRS{busnum}=="1"
ATTRS{devnum}=="7"
ATTRS{version}==" 1.10"
ATTRS{maxchild}=="0"
ATTRS{quirks}=="0x0"
ATTRS{authorized}=="1"
ATTRS{manufacturer}=="Prolific Technology Inc."
ATTRS{product}=="USB-Serial Controller"
<snip>
所有适配器都插入一个 USB 集线器。由于我无法区分适配器本身,有什么方法可以编写一个 udev 规则,根据适配器插入的集线器上的哪个物理端口来修复每个适配器的名称?
最佳方法
is there any way I can write a udev rule that fixes the name of each adapter based on which physical port on the hub the adapter is plugged into?
是的,事实证明。考虑上面第二个示例中显示的设备层次结构的最后一部分:
looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.5’: KERNELS==”1-4.5″
SUBSYSTEMS==”usb”
DRIVERS==”usb”
ATTRS{configuration}==””
ATTRS{bNumInterfaces}==” 1″
ATTRS{bConfigurationValue}==”1″
ATTRS{bmAttributes}==”80″
ATTRS{bMaxPower}==”100mA”
ATTRS{urbnum}==”69″
ATTRS{idVendor}==”067b”
ATTRS{idProduct}==”2303″
ATTRS{bcdDevice}==”0300″
ATTRS{bDeviceClass}==”00″
ATTRS{bDeviceSubClass}==”00″
ATTRS{bDeviceProtocol}==”00″
ATTRS{bNumConfigurations}==”1″
ATTRS{bMaxPacketSize0}==”64″
ATTRS{speed}==”12″
ATTRS{busnum}==”1″
ATTRS{devnum}==”7″ ATTRS{version}==” 1.10″ ATTRS{maxchild}==”0″ ATTRS{quirks}==”0x0″
ATTRS{authorized}==”1″
ATTRS{manufacturer}==”Prolific Technology Inc.”
ATTRS{product}==”USB-Serial Controller”
内核赋予此设备的名称 (KERNELS==”1-4.5″) 表明此设备已插入连接到总线 1 上的端口 4 的集线器的第五个端口(有关如何解码 sysfs USB 设备层次结构的更多信息,请参阅 this FAQ )。在 this guide 对编写 udev 规则的帮助下,我为我的 USB-to-serial-port 转换器提出了以下一组 udev 规则:
KERNEL==”ttyUSB*”, KERNELS==”1-8.1.5″, NAME=”ttyUSB0″
KERNEL==”ttyUSB*”, KERNELS==”1-8.1.6″, NAME=”ttyUSB1″
KERNEL==”ttyUSB*”, KERNELS==”1-8.1.1″, NAME=”ttyUSB2″
KERNEL==”ttyUSB*”, KERNELS==”1-8.1.2″, NAME=”ttyUSB3″
这些规则有一个明显的缺点:它们假定所有 USB-to-serial 转换器都将插入同一个集线器 (“1-8.1.*”)。如果将 USB 转串口转换器插入另一个 USB 端口,则可能会为其分配名称 “ttyUSB0″,这将与上述命名方案相冲突。但是,由于我将所有转换器都插入集线器,因此我可以忍受这种限制。
次佳方法
尽管在这种特定情况下无济于事,但为某些适配器分配了唯一的序列号:
udevadm info -a -n /dev/ttyUSB1 | grep '{serial}'
一个示例适配器序列号:
ATTRS{serial}=="A6008isP"`
然后 udev 规则将包含:
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A6008isP", SYMLINK+="arduino"
第三种方法
你看过 /dev/serial/by-id/
的内容了吗?在类似的情况下,每个设备都被分配了一个唯一的持久 ID(我承认不知道它实际代表什么)。
第四种方法
由于最初的问题是 3 年前提出的,因此可能无法解决提问者的问题,但我会发布它以供将来参考。
有一种方法可以通过访问 FTDI-Chips 的 EEPROM 来重新编程 Serial-Number,Silicon labs 提供了一个工具,但它仅适用于 Windows:
Product page -> 工具 -> 固定功能自定义实用程序
可以在 remotehq 找到一条指令:
http://remoteqth.com/wiki/index.php?page=How+to+set+usb+device+SerialNumber
Sourceforge 上还有一个 Unix 库。仅用CP2101 /CP2102 /CP2103测试过,我没有亲自尝试过。
http://sourceforge.net/projects/cp210x-program/