Jak odróżnić identyczne adaptery USB-szeregowy?

26

Używam wielu identycznych adapterów USB-szeregowych z moim laptopem (Ubuntu 9.10). Adaptery są produkowane przez Sabrent i są zbudowane wokół układu scalonego Prolific PL2303, jak pokazano 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  

Żaden z wyświetlanych atrybutów nie udevadmwydaje się być unikalny dla konkretnego adaptera:

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>

Wszystkie adaptery są podłączone do jednego koncentratora USB. Ponieważ nie mogę rozróżnić samych adapterów, czy jest jakiś sposób, aby napisać regułę udev, która naprawia nazwę każdego adaptera w oparciu o port fizyczny w koncentratorze, do którego podłączony jest adapter?

Chris OBrien
źródło

Odpowiedzi:

24

czy jest jakiś sposób, aby napisać regułę udev, która naprawia nazwę każdego adaptera na podstawie fizycznego portu w koncentratorze, do którego podłączony jest adapter?

Tak, jak się okazuje. Rozważ ostatnią część hierarchii urządzeń pokazaną w drugim przykładzie powyżej:

patrząc na urządzenie nadrzędne '/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.5': KERNELS == SUBSYSTEMS "1-4.5"
== "usb"
DRIVERS == "usb "
ATTRS {konfiguracja} ==" "
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 {wersja} == "1.10" ATTRS {maxchild} == "0" ATTRS {dziwactwo} == "0x0"
ATTRS {autoryzowany} == "1"
ATTRS {producent} = = „Prolific Technology Inc.”
ATTRS {product} == "Kontroler szeregowy USB"

Nazwa nadana temu urządzeniu przez jądro (KERNELS == "1-4.5") wskazuje, że to urządzenie jest podłączone do piątego portu koncentratora podłączonego do portu czwartego na magistrali 1 ( więcej informacji na temat dekodowania zawiera ten FAQ) sysfs hierarchia urządzeń USB). Z pomocą tego przewodnika po pisaniu reguł udev wymyśliłem następujący zestaw reguł udev dla moich konwerterów USB na port szeregowy:

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”

Reguły te mają jedną oczywistą wadę: zakładają, że wszystkie konwertery USB-na-szeregowe zostaną podłączone do tego samego koncentratora („1-8.1. *”). Jeśli konwerter USB na szeregowy został podłączony do innego portu USB, można mu przypisać nazwę „ttyUSB0”, co byłoby sprzeczne ze schematem nazewnictwa opisanym powyżej. Ponieważ jednak pozostawiam wszystkie konwertery podłączone do koncentratora, mogę żyć z tym ograniczeniem.

Chris OBrien
źródło
1
Dzięki za zacytowanie tych źródeł. USB Linux Często zadawane pytania było dokładnie to, czego potrzebowałem.
Lucas,
16

Chociaż nie pomogłoby to w tym konkretnym przypadku, niektórym adapterom przypisano unikalne identyfikatory szeregowe:

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

Przykładowy identyfikator seryjny adaptera:

  ATTRS{serial}=="A6008isP"`

a reguły udev zawierałyby wówczas:

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

Źródło

Cas
źródło
7
Niestety większość tanich adapterów szeregowych nie ma unikalnych
numerów
7

Czy spojrzałeś na zawartość /dev/serial/by-id/? W podobnej sytuacji każdemu urządzeniu przypisano niepowtarzalny trwały identyfikator (przyznam, że nie wiem, co to właściwie reprezentuje).

Rob Tirrell
źródło
<VENDOR><delimeter><MODEL><delimeter><SERIAL>
Pithikos,
3

Ponieważ pierwotne pytanie zostało zadane 3 lata temu, może to nie dotyczyć pytającego, ale opublikuję je do wglądu w przyszłości.

Istnieje sposób przeprogramowania numeru seryjnego poprzez dostęp do pamięci EEPROM układów FTDI, Silicon labs zapewnia narzędzie, ale jest to tylko system Windows:

Strona produktu -> Narzędzia-> Narzędzie dostosowywania stałej funkcji

Link bezpośredni

Instrukcja znajduje się na remotehq:

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

Istnieje również biblioteka Unix na Sourceforge. Jest testowany tylko z CP2101 / CP2102 / CP2103 i nie wypróbowałem go osobiście.

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

Smundo
źródło
1

Używam odpowiedzi zamiast komentarza, ponieważ potrzebuję formatowania.

Reguły te mają jedną oczywistą wadę: zakładają, że wszystkie konwertery USB-na-szeregowe zostaną podłączone do tego samego koncentratora („1-8.1. *”). Jeśli konwerter USB na szeregowy został podłączony do innego portu USB, można mu przypisać nazwę „ttyUSB0”, co byłoby sprzeczne ze schematem nazewnictwa opisanym powyżej. Ponieważ jednak pozostawiam wszystkie konwertery podłączone do koncentratora, mogę żyć z tym ograniczeniem.

Miałem ten problem i można go łatwo naprawić za pomocą małego programu C do manipulowania tekstem% devpath lub innym wybranym atrybutem USB.

Następnie wywołujesz ten program w następujący sposób:

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"

gdzie multiusbserial-id to skompilowany program C.

Program musi po prostu wydrukować tekst po określonym punkcie, więc nie jest skomplikowany

/* 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;
}

Napisałem artykuł na blogu z dalszymi szczegółami. Jest to jedna z serii konfiguracji środowiska programistycznego zespołu systemów wbudowanych.

vk5tu
źródło
0

Możesz wymienić takie urządzenia szeregowe 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

Dwie linie kończą się na

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

To jest na Raspberry Pi. Teraz pozostawię urządzenie ttyUSB1podłączone, wyciągnę adapter ttyUSB0i podłączę go do innego portu, a następnie do innego, a następnie z powrotem do portu początkowego

wprowadź opis zdjęcia tutaj

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

Nie wiem, dlaczego 1-1.3:1.0nie usuwa się go po odłączeniu, ale mogę z tym żyć, ponieważ rzadko zmieniam adaptery z jednego portu USB na inny.


Mój problem polegał na tym, że na Raspberry Pi, który steruje przekaźnikami migawki za pomocą Arduino podłączonego kablem USB i odczytuje dane czujnika otoczenia przez innego Arduino (ten sam producent, ten sam model), czasami, gdy aktywowane są migawki, dane czujnika Arduino zostały wykopane poza planszą i ponownie przypisany z ttyUSB0 do ttyUSB2 (ttyUSB1 to migawka). Skończyło się na tym skrypcie Python, aby nie musieć próbować i sprawdzać, które urządzenie było teraz na czujniku.

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

co daje mi następujący wynik

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

Wykonuję tę kontrolę tylko wtedy, gdy występują przekroczenia limitu czasu z powodu błędu połączenia.

Daniel F.
źródło