如何区分相同的USB转串口适配器?

我在笔记本电脑(Ubuntu 9.10)上使用了许多相同的USB转串口适配器。 这些适配器由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"  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"  

所有适配器都插入一个USB集线器。 由于我无法区分适配器本身,有什么方法可以编写一个udev规则,根据适配器插入的集线器上的哪个物理端口修复每个适配器的名称?

有什么方法可以编写一个udev规则,根据适配器插入的集线器上的哪个物理端口修复每个适配器的名称?

是的,事实certificate。 考虑上面第二个示例中显示的设备层次结构的最后一部分:

看父设备’/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.5’:KERNELS ==“1-4.5”
SUBSYSTEMS == “USB”
DRIVERS == “USB”
ATTRS {配置} == “”
ATTRS {bNumInterfaces} ==“1”
ATTRS {的bConfiguration Value} == “1”
ATTRS {} bmAttributes == “80”
ATTRS {} bMaxPower == “100毫安”
ATTRS {} urbnum == “69”
ATTRS {idVendor} == “067b”
ATTRS {} idProduct == “2303”
ATTRS {} bcdDevice == “0300”
ATTRS {}formsbDeviceClass == “00”
ATTRS {} bDeviceSubClass == “00”
ATTRS {} bDeviceProtocol == “00”
ATTRS {bNumConfigurations指定} == “1”
ATTRS {bMaxPacketSize0} == “64”
ATTRS {速度} == “12”
ATTRS {BUSNUM} == “1”
ATTRS {devnum} ==“7”ATTRS {version} ==“1.10”ATTRS {maxchild} ==“0”ATTRS {quirks} ==“0x0”
ATTRS {}授权== “1”
ATTRS {manufacturer} ==“Prolific Technology Inc.”
ATTRS {product} ==“USB-Serial Controller”

内核为此设备指定的名称(KERNELS ==“1-4.5”)表示此设备已插入连接到总线1上端口4的集线器的第五个端口(有关如何解码的详细信息,请参阅此常见问题解答) sysfs usb设备层次结构)。 在本指南的帮助下编写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转串口转换器都插入同一个集线器(“1-8.1。*”)。 如果将USB转串口转换器插入另一个USB端口,则可以为其分配名称“ttyUSB0”,这将与上述命名方案冲突。 但是,由于我将所有转换器都插入集线器,我可以忍受这种约束。

虽然在这种特定情况下没有帮助,但是为某些适配器分配了唯一的串行ID:

 udevadm info -a -n /dev/ttyUSB1 | grep '{serial}' 

示例适配器序列ID:

  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重新编程序列号,Silicon labs提供了一个工具,但它只是Windows:

产品页面 – >工具 – >固定function自定义实用程序

直接链接

可以在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/

因为我需要格式化,所以使用答案而不是评论。

这些规则有一个明显的缺点:它们假设所有USB转串口转换器都插入同一个集线器(“1-8.1。*”)。 如果将USB转串口转换器插入另一个USB端口,则可以为其分配名称“ttyUSB0”,这将与上述命名方案冲突。 但是,由于我将所有转换器都插入集线器,我可以忍受这种约束。

我有这个问题,通过使用一个小的C程序来操作%devpath的文本或你选择的其他一些USB属性很容易解决。

然后,您可以像这样调用该程序:

 ACTION!="add|change", GOTO="99-local-end SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6001", ENV{ID_MM_DEVICE_IGNORE}="1" SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", GOTO="99-local-tty-ftdi" GOTO="99-local-end" LABEL="99-local-tty-ftdi" IMPORT{program}="/usr/local/lib/udev/multiusbserial-id %s{devpath}" # Hayes-style Modem ENV{ID_MULTIUSBSERIAL_DEVNAME_MINOR}=="1", GROUP="dialout", MODE="0660", SYMLINK+="modem" # Console for network device ENV{ID_MULTIUSBSERIAL_DEVNAME_MINOR}=="2", GROUP="wheel", MODE="0660", SYMLINK+="ttyswitch" # Serial port for software development ENV{ID_MULTIUSBSERIAL_DEVNAME_MINOR}=="3", GROUP="eng", MODE="0660", SYMLINK+="ttyrouter" # Unused ENV{ID_MULTIUSBSERIAL_DEVNAME_MINOR}=="4", GROUP="wheel", MODE="0660" LABEL="99-local-end" 

其中multiusbserial-id是已编译的C程序。

程序只需要在特定点之后打印文本,因此它并不复杂

 /* multiusbserial.c */ #include  #include  #define PROGRAM_NAME "multiusbserial-id" #define VARIABLE_PREFIX "ID_MULTIUSBSERIAL_" int main(int argc, char *argv[]) { char *p; int found = 0; if (argc != 2) { fprintf(stderr, "Usage: " PROGRAM_NAME " ATTRS{devpath}\n"); exit(1); } for (p = argv[1]; *p != '\0'; p++) { if (*p == '.') { p++; found = (*p != '\0'); break; } } if (!found) { fprintf(stderr, PROGRAM_NAME ": unexpected format\n"); exit(1); } printf(VARIABLE_PREFIX "DEVNAME_MINOR=%s\n", p); return 0; } 

我写了一篇博客文章 ,详细介绍。 这是建立嵌入式系统团队编程环境的系列之一。

您可以列出这样的USB串行设备

 ls -l /sys/bus/usb-serial/devices total 0 lrwxrwxrwx 1 root root 0 Oct 9 09:10 ttyUSB0 -> ../../../devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/ttyUSB0 lrwxrwxrwx 1 root root 0 Oct 9 09:10 ttyUSB1 -> ../../../devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.0/ttyUSB1 

这两行以。结尾

 1-1.3:1.0/ttyUSB0 1-1.5:1.0/ttyUSB1 

这是在Raspberry Pi上。 我现在将设备ttyUSB1连接起来,拔出适配器ttyUSB0并将其插入另一个端口,然后再插入另一个端口,然后再返回初始端口

在此处输入图像描述

 # original setup ['1-1.3:1.0', 'ttyUSB0'] -- ['1-1.5:1.0', 'ttyUSB1'] # move it to port above 1.3 ['1-1.3:1.0', 'ttyUSB0'] ['1-1.5:1.0', 'ttyUSB1'] ['1-1.2:1.0', 'ttyUSB2'] -- # move it to port above 1.5 ['1-1.3:1.0', 'ttyUSB0'] ['1-1.5:1.0', 'ttyUSB1'] ['1-1.4:1.0', 'ttyUSB2'] -- # move it back to the original port ['1-1.3:1.0', 'ttyUSB0'] -- ['1-1.5:1.0', 'ttyUSB1'] 

我不知道为什么1-1.3:1.0在断开连接时没有得到清理,但我可以忍受,因为我很少将适配器从一个USB端口更改为另一个USB端口。


我的问题是在Raspberry Pi上通过USB电缆连接的Arduino控制快门继电器,并通过另一个Arduino(同一制造商,相同型号)读取环境传感器数据,偶尔,当百叶窗被激活时,传感器数据Arduino被踢离开电路板并从ttyUSB0重新分配到ttyUSB2(ttyUSB1是快门)。 我最终得到了这个Python脚本,因为不必通过反复试验找出传感器数据现在在哪个设备上。

 usb_devices = collections.OrderedDict() usb_device_list = subprocess.check_output('ls -l /sys/bus/usb-serial/devices', shell=True, universal_newlines=True).split('\n') for usb_device in usb_device_list: match = re.search("([^/]+)/([^/]+)$", usb_device) if match: usb_devices[match.group(1)] = match.group(2) for key, value in usb_devices.items(): print key, value # I know that 1.3 is the environment sensor device if '1-1.3:1.0' in usb_devices: print '1-1.3:1.0 -->', usb_devices['1-1.3:1.0'] # == ttyUSB0 

这给了我以下输出

 1-1.3:1.0 ttyUSB0 1-1.5:1.0 ttyUSB1 1-1.3:1.0 --> ttyUSB0 

我只在由于连接错误而发生超时时执行此检查。