RaspberryPi에서 동종 복수의 USB 기기를 식별하는 것을 생각해 본다

19137 단어 RaspberryPiUSB

소개



이 기사는 CPS Lab Advent Calendar 2018의 13일째 기사입니다.
12 일째 기사는 【Web Speech API】 Speech Recognition 홈페이지에서 브라우저 음성 인식 사용 (무료)
14 일째 기사는 Labmart의 얼굴 인증 구현하기

배경




이미지와 같이 동종의 드라이버의 USB 기기를 접속했을 때, 각각 꽂은 순서대로 /dev 에 인식되어 버립니다.
예를 들면 이미지와 같이 Arduino를 2개 접속하면 양쪽 모두 ACM의 드라이버이므로 이하와 같이 됩니다.
pi@raspberrypi:~ $ ls /dev | grep ttyACM*
ttyACM0
ttyACM1

이것이라면 어느 것이 ArduinoMEGA이고 어느 것이 ArduinoUNO인지 모르겠습니다.
USB 카메라를 복수개 접속했을 때도 /dev/video* 로 인식되므로 어느 것이 어느 카메라인지 모르게 됩니다.

그래서 지금 USB 포트에 접속되어 있는 기기를 식별하는 방법을 정리해 보았습니다.

환경



RaspberryPi2 (RASBIAN JESSIE)

어떻게 인식되는지 살펴보기



먼저 USB에 연결된 기기를 확인하는 명령으로 lsusb 명령이 있습니다.
이전 이미지의 상태에서 명령을 두드리면
pi@raspberrypi:~ $ lsusb
Bus 001 Device 006: ID 2019:ab2a PLANEX GW-USNano2 802.11n Wireless Adapter [Realtek RTL8188CUS]
Bus 001 Device 005: ID 2341:0043 Arduino SA Uno R3 (CDC ACM)
Bus 001 Device 004: ID 2341:0042 Arduino SA Mega 2560 R3 (CDC ACM)
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

이런 식으로 UNO R3MEGA 2560 R3 가 다른 것으로 제대로 인식되고 있는 것을 알 수 있습니다.
잘 보면 UNO R3ID 2341:0043 , MEGA 2560 R3、ID 2341:0042 로 인식되고 있으므로 여기에서 조건으로 나눠주면 식별할 수 있을 것 같습니다.2341 쪽이 idVendor 그 오른쪽이 idProduct 입니다.

식별하는 1



USB 장치가 연결될 때 마운트하는 방법을 결정하는 규칙은 /etc/udev/rules.d/99-com.rules에 설명되어 있습니다.
이번에는 여기 끝에 UNO R3MEGA 2560 R3 를 식별하는 규칙을 idVendoridProduct 를 기반으로 추가합니다.

/etc/udev/rules.d/99-com.rules
# for UNO
KERNEL=="ttyACM*",  ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0043", SYMLINK+="ttyUSB_UNO"
# for MEGA
KERNEL=="ttyACM*",  ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0042", SYMLINK+="ttyUSB_MEGA"

이러한 기술을 말미에 추가해 재부트 하면(자) 이하와 같이 다른 이름으로 식별되어, 각각이 대응한 ttyACM* 에 링크되고 있는 것을 알 수 있습니다.
pi@raspberrypi:~ $ ls /dev |grep USB
ttyUSB_MEGA
ttyUSB_UNO
pi@raspberrypi:~ $ ls -l /dev |grep USB
lrwxrwxrwx 1 root root           7 Dec 13 19:12 ttyUSB_MEGA -> ttyACM0
lrwxrwxrwx 1 root root           7 Dec 13 19:12 ttyUSB_UNO -> ttyACM1

식별하는 2



lsusb에서 관찰




사진과 같이 esp8266과 esp32 개발 보드를 연결하면 이들은 동일한 ID의 FTDI 칩으로 인식되어 버린다 lsusb
pi@raspberrypi:~ $ ls /dev | grep ttyUSB*
ttyUSB0
ttyUSB1
pi@raspberrypi:~ $ lsusb
Bus 001 Device 006: ID 2019:ab2a PLANEX GW-USNano2 802.11n Wireless Adapter [Realtek RTL8188CUS]
Bus 001 Device 008: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
Bus 001 Device 007: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
lsusb -v 에서 옵션을 붙여 관찰해 보겠습니다.
Bus 001 Device 008: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x0403 Future Technology Devices International, Ltd
  idProduct          0x6015 Bridge(I2C/SPI/UART/FIFO)
  bcdDevice           10.00
  iManufacturer           1
  iProduct                2
  iSerial                 3
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower               90mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              2
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0

Bus 001 Device 007: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x0403 Future Technology Devices International, Ltd
  idProduct          0x6015 Bridge(I2C/SPI/UART/FIFO)
  bcdDevice           10.00
  iManufacturer           1
  iProduct                2
  iSerial                 3
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower               90mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              2
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0

이 정보의 범위라면 독특한 속성은 발견되지 않는 것 같습니다.
그래서 udevadm 명령을 사용합니다.

udevadm에서 관찰


udevadm 에서는 다음과 같이 관찰하고 싶은 디바이스의 패스를 건네줍니다
pi@raspberrypi:~ $ udevadm info -a -p $(udevadm info -q path -n /dev/ttyUSB0)

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0':
    KERNEL=="ttyUSB0"
    SUBSYSTEM=="tty"
    DRIVER==""

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0':
    KERNELS=="ttyUSB0"
    SUBSYSTEMS=="usb-serial"
    DRIVERS=="ftdi_sio"
    ATTRS{port_number}=="0"
    ATTRS{latency_timer}=="1"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0':
    KERNELS=="1-1.2:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="ftdi_sio"
    ATTRS{bInterfaceClass}=="ff"
    ATTRS{bInterfaceSubClass}=="ff"
    ATTRS{bInterfaceProtocol}=="ff"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{authorized}=="1"
    ATTRS{supports_autosuspend}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{interface}=="FT231X USB UART"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2':
    KERNELS=="1-1.2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{devpath}=="1.2"
    ATTRS{idVendor}=="0403"
    ATTRS{speed}=="12"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="7"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="90mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="a0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="0"
    ATTRS{bcdDevice}=="1000"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{serial}=="DN02BCJT"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="16"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="FTDI"
    ATTRS{removable}=="removable"
    ATTRS{idProduct}=="6015"
    ATTRS{bDeviceClass}=="00"
    ATTRS{product}=="FT231X USB UART"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="02"
    ATTRS{devpath}=="1"
    ATTRS{idVendor}=="0424"
    ATTRS{speed}=="480"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="2"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="2mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="5"
    ATTRS{bcdDevice}=="0200"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="101"
    ATTRS{ltm_capable}=="no"
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="9514"
    ATTRS{bDeviceClass}=="09"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{devpath}=="0"
    ATTRS{idVendor}=="1d6b"
    ATTRS{speed}=="480"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{authorized_default}=="1"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="1"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="0mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="1"
    ATTRS{interface_authorized_default}=="1"
    ATTRS{bcdDevice}=="0404"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{serial}=="3f980000.usb"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="25"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Linux 4.4.38-v7+ dwc_otg_hcd"
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="0002"
    ATTRS{bDeviceClass}=="09"
    ATTRS{product}=="DWC OTG Controller"

  looking at parent device '/devices/platform/soc/3f980000.usb':
    KERNELS=="3f980000.usb"
    SUBSYSTEMS=="platform"
    DRIVERS=="dwc_otg"
    ATTRS{hnp}=="HstNegScs = 0x0"
    ATTRS{srp}=="SesReqScs = 0x1"
    ATTRS{regvalue}=="invalid offset"
    ATTRS{hsic_connect}=="HSIC Connect = 0x1"
    ATTRS{guid}=="GUID = 0x2708a000"
    ATTRS{mode}=="Mode = 0x1"
    ATTRS{srpcapable}=="SRPCapable = 0x1"
    ATTRS{regdump}=="Register Dump"
    ATTRS{gpvndctl}=="GPVNDCTL = 0x00000000"
    ATTRS{ggpio}=="GGPIO = 0x00000000"
    ATTRS{hprt0}=="HPRT0 = 0x00001005"
    ATTRS{wr_reg_test}=="Time to write GNPTXFSIZ reg 10000000 times: 520 msecs (52 jiffies)"
    ATTRS{driver_override}=="(null)"
    ATTRS{hcd_frrem}=="HCD Dump Frame Remaining"
    ATTRS{mode_ch_tim_en}=="Mode Change Ready Timer Enable = 0x0"
    ATTRS{gnptxfsiz}=="GNPTXFSIZ = 0x01000306"
    ATTRS{remote_wakeup}=="Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0"
    ATTRS{busconnected}=="Bus Connected = 0x1"
    ATTRS{hcddump}=="HCD Dump"
    ATTRS{gotgctl}=="GOTGCTL = 0x001c0001"
    ATTRS{spramdump}=="SPRAM Dump"
    ATTRS{grxfsiz}=="GRXFSIZ = 0x00000306"
    ATTRS{gsnpsid}=="GSNPSID = 0x4f54280a"
    ATTRS{gusbcfg}=="GUSBCFG = 0x20001700"
    ATTRS{hptxfsiz}=="HPTXFSIZ = 0x02000406"
    ATTRS{devspeed}=="Device Speed = 0x0"
    ATTRS{fr_interval}=="Frame Interval = 0x1d4c"
    ATTRS{rem_wakeup_pwrdn}==""
    ATTRS{bussuspend}=="Bus Suspend = 0x0"
    ATTRS{buspower}=="Bus Power = 0x1"
    ATTRS{hnpcapable}=="HNPCapable = 0x1"
    ATTRS{rd_reg_test}=="Time to read GNPTXFSIZ reg 10000000 times: 1410 msecs (141 jiffies)"
    ATTRS{enumspeed}=="Device Enumeration Speed = 0x1"
    ATTRS{inv_sel_hsic}=="Invert Select HSIC = 0x0"
    ATTRS{regoffset}=="0xffffffff"

  looking at parent device '/devices/platform/soc':
    KERNELS=="soc"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/platform':
    KERNELS=="platform"
    SUBSYSTEMS==""
    DRIVERS==""

2개 늘어놓으면 길기 때문에 할애합니다만 이 안에 있는 독특한 속성을 사용해 식별 룰을 추가해 줍니다.
이번에는 esp8266 쪽 ATTRS{serial}=="DN02BCJT" 와 esp32 쪽 ATTRS{serial}=="DN02TAFR" 를 사용합니다.

/etc/udev/rules.d/99-com.rules
# for esp8266
KERNEL=="ttyUSB*", ATTRS{serial}=="DN02BCJT", SYMLINK+="ttyUSB_esp8266"
# for esp8266
KERNEL=="ttyUSB*", ATTRS{serial}=="DN02TAFR", SYMLINK+="ttyUSB_32"
pi@raspberrypi:~ $ ls -l /dev |grep USB
crw-rw---- 1 root dialout 188,   0 Dec 13 19:50 ttyUSB0
crw-rw---- 1 root dialout 188,   1 Dec 13 19:50 ttyUSB1
lrwxrwxrwx 1 root root           7 Dec 13 19:50 ttyUSB_32 -> ttyUSB1
lrwxrwxrwx 1 root root           7 Dec 13 19:50 ttyUSB_esp8266 -> ttyUSB0

이런 식으로 식별이 가능합니다.

식별하는 3



USB를 꽂은 위치에 의한 식별


udevadm 한 결과를 보면 KERNELS=="1-1.2" 와 같은 부분이 발견된다고 생각합니다. 실은 여기의 값으로 4개의 USB 포트 각각으로 물리적으로 어디에 꽂혀 있는 것인지 식별할 수 있습니다. RaspberryPi2의 경우 대응은 이미지처럼 보입니다.


참고



이쪽을 참고로 했습니다. 감사합니다.
htps //w w. 여러가지. 오 rg/도 c/우 sb-안녕. HTML
htps : // 아스쿠부츠. 코 m / 쿠에 s 치온 s / 49910 / 호 w - ー ぢ s 찢어진 sh 베와 ぇ 엔 - 이 덴치카 루 sb

좋은 웹페이지 즐겨찾기