Como distinguir entre adaptadores USB para serial idênticos?

24

Eu uso um número de adaptadores USB para serial idênticos com meu laptop (Ubuntu 9.10). Os adaptadores são fabricados pela Sabrent e são construídos em torno de um IC PL2303 da Prolific, como mostrado por 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  

Nenhum dos atributos exibidos por udevadm parece ser exclusivo de um determinado adaptador:

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>

Todos os adaptadores estão conectados em um único hub USB. Como não consigo distinguir entre os próprios adaptadores, existe alguma maneira de escrever uma regra do udev que conserte o nome de cada adaptador com base na porta física no hub em que o adaptador está conectado?

    
por Chris OBrien 21.06.2011 / 20:39

6 respostas

20

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?

Sim, existe, como se constata. Considere a última parte da hierarquia de dispositivos mostrada no segundo exemplo acima:

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"

O nome dado a este dispositivo pelo kernel (KERNELS == "1-4.5") indica que este dispositivo está conectado à quinta porta de um hub conectado à porta quatro no barramento 1 (consulte esta FAQ para mais informações sobre como decodificar a hierarquia de dispositivos usb sysfs). Com alguma ajuda de este guia para escrever regras do udev, criei o seguinte conjunto de regras do udev para o meu USB-to-serial- conversores de porta:

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"

Essas regras têm uma desvantagem óbvia: elas assumem que todos os conversores USB para serial serão conectados ao mesmo hub ("1-8.1. *"). Se um conversor USB para serial fosse conectado a outra porta USB, poderia ser atribuído o nome "ttyUSB0", o que entraria em conflito com o esquema de nomenclatura descrito acima. No entanto, desde que eu deixo todos os conversores conectados ao hub eu posso viver com essa restrição.

    
por Chris OBrien 24.06.2011 / 20:55
14

Embora isso não ajudasse nesse caso específico, alguns adaptadores recebem IDs seriais exclusivos:

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

Um ID de série de adaptador de exemplo:

  ATTRS{serial}=="A6008isP"'
As regras do

e do udev conteriam:

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

Fonte

    
por Cas 18.07.2012 / 22:57
7

Você examinou o conteúdo de /dev/serial/by-id/ ? Em uma situação semelhante, cada dispositivo recebeu um ID persistente exclusivo (admito que não sei o que ele realmente representa).

    
por Rob Tirrell 20.06.2012 / 01:59
3

Como a pergunta original foi feita há 3 anos, isso pode não indicar o autor da pergunta, mas eu a postarei para referência futura.

Existe uma maneira de reprogramar o número de série acessando a EEPROM dos FTDI-Chips, o Silicon labs fornece uma ferramenta, mas é somente Windows:

Página do produto - > Ferramentas- > Utilitário de personalização de função fixa

Link direto

Uma instrução pode ser encontrada em remotehq:

link

Existe também uma biblioteca Unix no Sourceforge. Só é testado com CP2101 / CP2102 / CP2103 e eu não tentei pessoalmente.

link

    
por Smundo 07.11.2014 / 09:22
0

Você pode listar os dispositivos seriais USB como este

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

As duas linhas estão terminando com

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

Isto está em um Raspberry Pi. Agora deixarei o dispositivo ttyUSB1 conectado e puxe o adaptador ttyUSB0 e conecte-o a outra porta, depois a outra e, em seguida, retorne à porta inicial

#originalsetup['1-1.3:1.0','ttyUSB0']--['1-1.5:1.0','ttyUSB1']#moveittoportabove1.3['1-1.3:1.0','ttyUSB0']['1-1.5:1.0','ttyUSB1']['1-1.2:1.0','ttyUSB2']--#moveittoportabove1.5['1-1.3:1.0','ttyUSB0']['1-1.5:1.0','ttyUSB1']['1-1.4:1.0','ttyUSB2']--#moveitbacktotheoriginalport['1-1.3:1.0','ttyUSB0']--['1-1.5:1.0','ttyUSB1']

Eunãoseiporque1-1.3:1.0nãoestásendolimpoapósadesconexão,maseupossovivercomisso,jáqueeuraramentemudoosadaptadoresdeumaportaUSBparaoutra.

MeuproblemafoiqueemumRaspberryPiquecontrolaosrelésdoobturadoratravésdeumArduinoconectadoviacaboUSBelêdadosdosensordeambienteatravésdeoutroArduino(mesmofabricante,mesmomodelo),ocasionalmente,quandoosobturadoressãoativados,osdadosdosensorOArduinofoiexpulsodaplacaetransferidodettyUSB0parattyUSB2(ttyUSB1éoobturador).AcabeicomestescriptPythonparanãoterquedescobrirportentativaeerroemqualdispositivoosdadosdosensorestavamagora.

usb_devices=collections.OrderedDict()usb_device_list=subprocess.check_output('ls-l/sys/bus/usb-serial/devices',shell=True,universal_newlines=True).split('\n')forusb_deviceinusb_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

que me dá a seguinte saída

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

Eu só faço essa verificação quando os tempos limite devido a um erro de conexão estão ocorrendo.

    
por Daniel F 09.10.2018 / 09:59
0

Usando uma resposta em vez de um comentário, pois preciso de formatação.

These rules have one obvious disadvantage: they assume that all USB-to-serial converters will be plugged into the same hub ("1-8.1.*"). If a USB to serial converter was plugged into another USB port it could be assigned the name "ttyUSB0" which would conflict with the naming scheme described above. However, since I leave all of the converters plugged into the hub I can live with this constraint.

Eu tive esse problema e é facilmente corrigido usando um pequeno programa em C para manipular o texto de% devpath ou algum outro atributo USB de sua escolha.

Você chama esse programa assim:

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"

em que multiusbserial-id é o programa C compilado.

O programa só precisa imprimir o texto depois de um determinado ponto, por isso não é complexo

/* 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 != '
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"
'; p++) { if (*p == '.') { p++; found = (*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 != '%pre%'; p++) {
    if (*p == '.') {
      p++;
      found = (*p != '%pre%');
      break;
    }
  }

  if (!found) {
    fprintf(stderr, PROGRAM_NAME ": unexpected format\n");
    exit(1);
  }

  printf(VARIABLE_PREFIX "DEVNAME_MINOR=%s\n", p);
  return 0;
}
'); break; } } if (!found) { fprintf(stderr, PROGRAM_NAME ": unexpected format\n"); exit(1); } printf(VARIABLE_PREFIX "DEVNAME_MINOR=%s\n", p); return 0; }

Eu escrevi um artigo de blog com mais detalhes. É uma de uma série na criação de um ambiente de programação de equipe de sistemas embarcados.

    
por vk5tu 14.04.2017 / 15:22