Làm thế nào để phân biệt giữa các bộ chuyển đổi USB nối tiếp giống hệt nhau?


26

Tôi sử dụng một số bộ điều hợp nối tiếp USB giống hệt với máy tính xách tay của mình (Ubuntu 9.10). Các bộ điều hợp được sản xuất bởi Sabrent và được chế tạo xung quanh IC Prolific PL2303, như được hiển thị bởi 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  

Không có thuộc tính nào được hiển thị bởi udevadmdường như là duy nhất cho một bộ điều hợp cụ thể:

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>

Tất cả các bộ điều hợp được cắm vào một bộ chia USB duy nhất. Vì tôi không thể tự phân biệt giữa các bộ điều hợp, có cách nào để tôi có thể viết quy tắc udev sửa tên của từng bộ chuyển đổi dựa trên cổng vật lý nào trên hub mà bộ chuyển đổi được cắm vào không?

Câu trả lời:


24

Có cách nào để tôi có thể viết quy tắc udev sửa tên của từng bộ chuyển đổi dựa trên cổng vật lý nào trên trung tâm mà bộ chuyển đổi được cắm vào không?

Có, như nó hóa ra. Hãy xem xét phần cuối cùng của hệ thống phân cấp thiết bị được hiển thị trong ví dụ thứ hai ở trên:

nhìn vào thiết bị mẹ '/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.5': Kernels == "1-4.5"
SUBSYSTEMS == "usb"
DRIVERS == "usb "
attrs {cấu hình} ==" "
attrs {bNumInterfaces} ==" 1"
attrs {bConfigurationValue} == "1"
attrs {bmAttributes} == "80"
attrs {bMaxPower} == "100mA"
attrs {urbnum} = = "69"
ATTRS {idVendor} == "067b"
ATTRS {idSản phẩm} == "2303"
ATTRS {bcdDevice} == "0300"
ATTRS {bDeviceClass} == "00"
ATTRS {
bDevice {bDeviceProtocol} == "00"
ATTRS {bNumConfigurations} == "1"
ATTRS {bMaxPacketSize0} == "64"
ATTRS {speed} == "12"
ATTRS {busnum} == "1"
ATTRS {devnum} == "7" ATTRS {phiên bản} == "1.10" ATTRS {maxchild} == "0" ATTRS {quirks} == "0x0"
ATTRS {ủy quyền} == "1"
ATTRS {nhà sản xuất} = = "Công nghệ phát triển Inc."
ATTRS {sản phẩm} == "Bộ điều khiển nối tiếp USB"

Tên được đặt cho thiết bị này bởi hạt nhân (KERNELS == "1-4.5") cho biết thiết bị này được cắm vào cổng thứ năm của một trung tâm được kết nối với cổng bốn trên bus 1 (xem Câu hỏi thường gặp này để biết thêm thông tin về cách giải mã hệ thống phân cấp thiết bị usb sysfs). Với một số trợ giúp từ hướng dẫn này để viết các quy tắc udev, tôi đã đưa ra bộ quy tắc udev sau đây cho các bộ chuyển đổi cổng USB sang nối tiếp của tôi:

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"

Các quy tắc này có một nhược điểm rõ ràng: họ cho rằng tất cả các bộ chuyển đổi USB nối tiếp sẽ được cắm vào cùng một trung tâm ("1-8.1. *"). Nếu một bộ chuyển đổi USB sang nối tiếp được cắm vào một cổng USB khác, nó có thể được gán tên "ttyUSB0" sẽ xung đột với sơ đồ đặt tên được mô tả ở trên. Tuy nhiên, vì tôi để tất cả các bộ chuyển đổi cắm vào trung tâm, tôi có thể sống với ràng buộc này.


1
Cảm ơn đã trích dẫn những nguồn đó. Các Linux USB Câu hỏi thường gặp là chính xác những gì tôi cần.
Lucas

16

Mặc dù nó không giúp ích gì trong trường hợp cụ thể này, một số bộ điều hợp được gán id nối tiếp duy nhất:

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

Một ví dụ về bộ nối tiếp id id:

  ATTRS{serial}=="A6008isP"`

và quy tắc udev sau đó sẽ chứa:

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A6008isP", SYMLINK+="arduino"

Nguồn


7
Đáng buồn thay, hầu hết các bộ điều hợp nối tiếp giá rẻ ngoài kia không có các bộ nối tiếp duy nhất :(
portforwardpodcast

7

Bạn đã xem nội dung của /dev/serial/by-id/? Trong tình huống tương tự, mỗi thiết bị được gán một ID liên tục duy nhất ở đó (Tôi sẽ thừa nhận không biết nó thực sự đại diện cho cái gì).


<VENDOR><delimeter><MODEL><delimeter><SERIAL>
Pithikos

3

Vì câu hỏi ban đầu đã được hỏi 3 năm trước, điều này có thể không phụ thuộc vào người hỏi, nhưng tôi sẽ đăng nó để tham khảo trong tương lai.

Có một cách để lập trình lại Số sê-ri bằng cách truy cập EEPROM của FTDI-Chips, các phòng thí nghiệm của Silicon cung cấp một công cụ, nhưng đó chỉ là Windows:

Trang sản phẩm -> Công cụ-> Tiện ích tùy chỉnh chức năng cố định

Đương dân trực tiêp

Một hướng dẫn có thể được tìm thấy tại remotehq:

http://remoteqth.com/wiki/index.php?page=How+to+set+usb+device+SerialNumber

Ngoài ra còn có một thư viện Unix trên Sourceforge. Nó chỉ được thử nghiệm với CP2101 / CP2102 / CP2103 và tôi đã không dùng thử cá nhân.

http://sourceforge.net/projects/cp210x-program/


1

Sử dụng một câu trả lời thay vì một nhận xét như tôi cần định dạng.

Các quy tắc này có một nhược điểm rõ ràng: họ cho rằng tất cả các bộ chuyển đổi USB nối tiếp sẽ được cắm vào cùng một trung tâm ("1-8.1. *"). Nếu một bộ chuyển đổi USB sang nối tiếp được cắm vào một cổng USB khác, nó có thể được gán tên "ttyUSB0" sẽ xung đột với sơ đồ đặt tên được mô tả ở trên. Tuy nhiên, vì tôi để tất cả các bộ chuyển đổi cắm vào trung tâm, tôi có thể sống với ràng buộc này.

Tôi đã gặp vấn đề này và nó dễ dàng được khắc phục bằng cách sử dụng một chương trình C nhỏ để thao tác văn bản của% devpath hoặc một số thuộc tính USB khác mà bạn chọn.

Sau đó, bạn gọi chương trình đó như thế này:

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"

trong đó multiusbserial-id là chương trình C được biên dịch.

Chương trình chỉ cần in văn bản sau một điểm cụ thể, vì vậy nó không phức tạp

/* multiusbserial.c */
#include <stdio.h>
#include <stdlib.h>

#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;
}

Tôi đã viết một bài viết blog với nhiều chi tiết hơn. Đây là một trong những loạt bài trong việc thiết lập môi trường lập trình nhóm hệ thống nhúng.


0

Bạn có thể liệt kê các thiết bị nối tiếp USB như thế này

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

Hai dòng kết thúc bằng

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

Đây là trên một Raspberry Pi. Bây giờ tôi sẽ để thiết bị ttyUSB1được kết nối và rút bộ điều hợp ra ttyUSB0và cắm nó vào một cổng khác, sau đó là một thiết bị khác, sau đó quay lại cổng ban đầu

nhập mô tả hình ảnh ở đây

# 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']

Tôi không biết tại sao 1-1.3:1.0không được dọn dẹp khi ngắt kết nối, nhưng tôi có thể sống với điều đó, vì tôi hiếm khi thay đổi bộ điều hợp từ cổng USB này sang cổng USB khác.


Vấn đề của tôi là trên Raspberry Pi điều khiển rơle màn trập thông qua Arduino được gắn qua cáp USB và đọc dữ liệu cảm biến môi trường thông qua một Arduino khác (cùng nhà sản xuất, cùng kiểu máy), đôi khi, khi cửa chớp được kích hoạt, dữ liệu cảm biến Arduino bị kích hoạt tắt bảng và gán lại từ ttyUSB0 đến ttyUSB2 (ttyUSB1 là màn trập). Tôi đã kết thúc với tập lệnh Python này để không phải tìm ra bằng cách dùng thử và lỗi thiết bị dữ liệu cảm biến hiện đang được bật.

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

cung cấp cho tôi đầu ra sau đây

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

Tôi chỉ thực hiện kiểm tra này khi hết thời gian do lỗi kết nối.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.