วิธีแยกระหว่างอะแดปเตอร์ USB เป็นอนุกรมที่เหมือนกัน


26

ฉันใช้อะแดปเตอร์ USB เป็นอนุกรมจำนวนหนึ่งกับแล็ปท็อปของฉัน (Ubuntu 9.10) อะแดปเตอร์ผลิตโดย 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"  

     <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>

อะแดปเตอร์ทั้งหมดถูกเสียบเข้ากับฮับ USB เดียว เนื่องจากฉันไม่สามารถแยกความแตกต่างระหว่างอะแดปเตอร์ด้วยตนเองได้มีวิธีใดบ้างที่ฉันสามารถเขียนกฎ udev ที่แก้ไขชื่อของแต่ละอะแดปเตอร์ตามฟิสิคัลพอร์ตบนฮับที่อะแดปเตอร์เสียบอยู่

คำตอบ:


24

มีวิธีใดบ้างที่ฉันสามารถเขียนกฎ udev ที่แก้ไขชื่อของอะแดปเตอร์แต่ละตัวตามฟิสิคัลพอร์ตบนฮับที่เสียบอะแดปเตอร์ไว้

ใช่มีเป็นมันกลายเป็น พิจารณาส่วนสุดท้ายของลำดับชั้นอุปกรณ์ที่แสดงในตัวอย่างที่สองด้านบน:

ดูที่อุปกรณ์แม่ '/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 {bMaxPower} ==" 100mA " ATTRS {urbnum} = = "69"
ATTRS {idVendor} == "067b"
ATTRS {idProduct} == "2303"
ATTRS {bcdDevice} == "0300"
ATTRS {bDeviceSubClass} == "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 {อำนาจ} == "1"
ATTRS {ผู้ผลิต} = = "Prolific Technology Inc. "
ATTRS {product} == "คอนโทรลเลอร์ USB-Serial"

ชื่อที่ให้กับอุปกรณ์นี้โดยเคอร์เนล (KERNELS == "1-4.5") ระบุว่าอุปกรณ์นี้เสียบเข้ากับพอร์ตที่ห้าของฮับที่เชื่อมต่อกับพอร์ตสี่บนบัส 1 (ดูคำถามที่พบบ่อยนี้สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการถอดรหัส ลำดับชั้นอุปกรณ์ usb sysfs) ด้วยความช่วยเหลือจากคู่มือนี้ถึงการเขียนกฎ udev ฉันได้รับชุด udev กฎต่อไปนี้สำหรับตัวแปลง USB เป็นพอร์ตอนุกรมของฉัน:

KERNEL == "ttyUSB *", KERNELS == "1-8.1.5", NAME = "ttyUSB0"
KERNEL == "ttyUSB *", KERNELS == "1-8.1.6", NERN = "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" ซึ่งอาจขัดแย้งกับรูปแบบการตั้งชื่อที่อธิบายไว้ข้างต้น อย่างไรก็ตามเนื่องจากฉันปล่อยให้ตัวแปลงทั้งหมดเสียบเข้ากับฮับฉันจึงสามารถใช้ชีวิตกับข้อ จำกัด นี้ได้


1
ขอขอบคุณที่อ้างอิงแหล่งข้อมูลเหล่านั้น ลินุกซ์ USB คำถามที่พบบ่อยคือสิ่งที่ฉันต้องการ
ลูคัส

16

แม้ว่ามันจะไม่ได้ช่วยในกรณีเฉพาะนี้อะแดปเตอร์บางตัวได้รับรหัสประจำตัวที่ไม่ซ้ำกัน:

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

ตัวอย่างซีเรียลของอะแดปเตอร์:

  ATTRS{serial}=="A6008isP"`

และกฎของ udev จะประกอบด้วย:

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

แหล่ง


7
น่าเสียดายที่อะแดปเตอร์อนุกรม cheapo ส่วนใหญ่นั้นไม่มี serials ที่ไม่ซ้ำกัน :(
portforwardpodcast

7

มีคุณดูเนื้อหาของ/dev/serial/by-id/? ในสถานการณ์ที่คล้ายคลึงกันอุปกรณ์แต่ละชิ้นได้รับการระบุ ID ถาวรที่นั่น (ฉันจะยอมรับว่าไม่รู้ว่ามันหมายถึงอะไร)


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

3

เนื่องจากมีการถามคำถามเดิมเมื่อ 3 ปีที่ผ่านมาสิ่งนี้อาจไม่ใช่ที่อยู่ของผู้ถาม แต่ฉันจะโพสต์ไว้เพื่อใช้อ้างอิงในอนาคต

มีวิธีการทำซ้ำหมายเลขซีเรียลโดยการเข้าถึง EEPROM ของ FTDI-Chips ห้องปฏิบัติการซิลิคอนมีเครื่องมือ แต่เป็น Windows เท่านั้น:

หน้าผลิตภัณฑ์ -> เครื่องมือ -> ยูทิลิตี้ปรับแต่งฟังก์ชั่นคงที่

ลิงค์ตรง

คำแนะนำสามารถพบได้ที่ remotehq:

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

นอกจากนี้ยังมีไลบรารี Unix บน Sourceforge มีการทดสอบกับ CP2101 / CP2102 / CP2103 เท่านั้นและฉันไม่ได้ลองใช้เป็นการส่วนตัว

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


1

ใช้คำตอบมากกว่าความคิดเห็นที่ฉันต้องการจัดรูปแบบ

กฎเหล่านี้มีข้อเสียอย่างหนึ่ง: พวกเขาคิดว่าตัวแปลง 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 <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;
}

ฉันเขียนบทความบล็อกพร้อมรายละเอียดเพิ่มเติม เป็นหนึ่งในซีรีส์ในการตั้งค่าสภาพแวดล้อมการเขียนโปรแกรมระบบทีมแบบฝังตัว


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

นี่คือราสเบอร์รี่ 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 หนึ่งไปยังอีกพอร์ตหนึ่ง


ปัญหาของฉันคือที่ Raspberry Pi ซึ่งควบคุมการถ่ายทอดชัตเตอร์ผ่าน Arduino ที่เชื่อมต่อผ่านสาย USB และอ่านข้อมูลเซ็นเซอร์สภาพแวดล้อมผ่าน 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

ฉันจะทำการตรวจสอบนี้เฉพาะเมื่อหมดเวลาเนื่องจากข้อผิดพลาดในการเชื่อมต่อเกิดขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.