Bagaimana cara membedakan antara adapter USB-ke-serial yang identik?

26

Saya menggunakan sejumlah adapter USB-to-serial yang identik dengan laptop saya (Ubuntu 9.10). Adaptor diproduksi oleh Sabrent dan dibangun di sekitar IC PL2303 Prolific, seperti yang ditunjukkan oleh 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  

Tak satu pun dari atribut yang ditampilkan udevadmtampaknya unik untuk adaptor tertentu:

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>

Semua adapter dicolokkan ke hub USB tunggal. Karena saya tidak dapat membedakan antara adaptor itu sendiri, adakah yang bisa saya tuliskan aturan udev yang menetapkan nama setiap adaptor berdasarkan pada port fisik mana pada hub yang dihubungkan adaptor itu?

Chris OBrien
sumber

Jawaban:

24

apakah ada cara saya bisa menulis aturan udev yang memperbaiki nama masing-masing adaptor berdasarkan pada port fisik pada hub adaptor dicolokkan?

Ya ada, ternyata. Pertimbangkan bagian terakhir dari hierarki perangkat yang ditunjukkan pada contoh kedua di atas:

melihat perangkat induk '/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 {berwenang} == "1"
ATTRS {produsen} = = "Teknologi Prolific Inc."
ATTRS {product} == "USB-Serial Controller"

Nama yang diberikan ke perangkat ini oleh kernel (KERNELS == "1-4.5") menunjukkan bahwa perangkat ini dicolokkan ke port kelima hub yang terhubung ke port empat di bus 1 (lihat FAQ ini untuk informasi lebih lanjut tentang cara memecahkan kode hirarki perangkat sysfs usb). Dengan bantuan dari panduan ini untuk menulis aturan udev, saya membuat seperangkat aturan udev berikut untuk konverter USB-to-serial-port saya:

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"

Aturan-aturan ini memiliki satu kelemahan yang jelas: mereka menganggap bahwa semua konverter USB ke serial akan dicolokkan ke hub yang sama ("1-8.1. *"). Jika konverter USB ke serial dicolokkan ke port USB lain, itu dapat diberi nama "ttyUSB0" yang akan bertentangan dengan skema penamaan yang dijelaskan di atas. Namun, karena saya membiarkan semua konverter tersambung ke hub, saya dapat hidup dengan batasan ini.

Chris OBrien
sumber
1
Terima kasih telah mengutip sumber-sumber itu. The Linux USB Pertanyaan yang sering diajukan adalah persis apa yang saya butuhkan.
Lucas
16

Meskipun tidak akan membantu dalam kasus khusus ini, beberapa adapter diberi id seri unik:

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

Contoh id serial adaptor:

  ATTRS{serial}=="A6008isP"`

dan aturan udev akan mengandung:

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

Sumber

Cas
sumber
7
Sayangnya, sebagian besar adaptor serial murahan di luar sana tidak memiliki serial unik :(
portforwardpodcast
7

Sudahkah Anda melihat isinya /dev/serial/by-id/? Dalam situasi yang sama setiap perangkat diberi ID persisten unik di sana (saya akui tidak tahu apa yang sebenarnya diwakilinya).

Rob Tirrell
sumber
<VENDOR><delimeter><MODEL><delimeter><SERIAL>
Pithikos
3

Karena pertanyaan awal diajukan 3 tahun yang lalu, ini mungkin tidak memberi tahu penanya, tetapi saya akan mempostingnya untuk referensi di masa mendatang.

Ada cara untuk memprogram ulang Serial-Number dengan mengakses EEPROM dari FTDI-Chips, Silicon labs menyediakan alat, tetapi hanya Windows:

Halaman produk -> Alat-> Utilitas Kustomisasi Fungsi Tetap

Tautan langsung

Instruksi dapat ditemukan di remotehq:

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

Ada juga perpustakaan Unix di Sourceforge. Ini hanya diuji dengan CP2101 / CP2102 / CP2103 dan saya tidak mencobanya secara pribadi.

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

Smundo
sumber
1

Menggunakan jawaban daripada komentar karena saya perlu memformat.

Aturan-aturan ini memiliki satu kelemahan yang jelas: mereka menganggap bahwa semua konverter USB ke serial akan dicolokkan ke hub yang sama ("1-8.1. *"). Jika konverter USB ke serial dicolokkan ke port USB lain, itu dapat diberi nama "ttyUSB0" yang akan bertentangan dengan skema penamaan yang dijelaskan di atas. Namun, karena saya membiarkan semua konverter tersambung ke hub, saya dapat hidup dengan batasan ini.

Saya punya masalah ini dan mudah diperbaiki dengan menggunakan program C kecil untuk memanipulasi teks% devpath atau atribut USB lain yang Anda pilih.

Anda kemudian memanggil program itu seperti ini:

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"

di mana multiusbserial-id adalah program C yang dikompilasi.

Program hanya perlu mencetak teks setelah titik tertentu, sehingga tidak rumit

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

Saya menulis artikel blog dengan lebih detail. Ini adalah salah satu dari rangkaian pengaturan lingkungan pemrograman tim sistem tertanam.

vk5tu
sumber
0

Anda dapat membuat daftar perangkat serial USB seperti ini

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

Dua baris diakhiri dengan

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

Ini pada Raspberry Pi. Saya sekarang akan membiarkan perangkat ttyUSB1terhubung, dan mengeluarkan adaptor ttyUSB0dan tancapkan ke port lain, lalu yang lain, dan kemudian kembali ke port awal

masukkan deskripsi gambar di sini

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

Saya tidak tahu mengapa 1-1.3:1.0tidak dibersihkan setelah pemutusan, tetapi saya bisa hidup dengan itu, karena saya jarang mengubah adaptor dari satu port USB ke yang lain.


Masalah saya adalah bahwa pada Raspberry Pi yang mengontrol rana relay melalui Arduino yang terpasang melalui kabel USB dan membaca data sensor lingkungan melalui Arduino lain (produsen yang sama, model yang sama), kadang-kadang, ketika jendela diaktifkan, data sensor Arduino ditendang dari papan dan dipindahkan dari ttyUSB0 ke ttyUSB2 (ttyUSB1 adalah penutup). Saya berakhir dengan skrip Python ini karena tidak harus mencari tahu dengan coba-coba perangkat mana data sensor sekarang.

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

yang memberi saya output berikut

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

Saya hanya melakukan pemeriksaan ini ketika batas waktu karena kesalahan koneksi terjadi.

Daniel F
sumber