Wie kann man unter Linux mehrere über USB verbundene Arduinos identifizieren?

17

Wenn ich mehrere Arduinos über USB an einen Linux-Computer angeschlossen habe, werden sie als angezeigt

  • / tty / ACM0
  • / tty / ACM1
  • / tty / ACM2

Wie kann ich feststellen, welches Arduino welches ist, ohne eine Verbindung über eine serielle Verbindung herzustellen ? Gibt es eine Seriennummer oder eine eindeutige ID auf dem Arduino?

Vielen Dank für Ihre Zeit.

Situation: Uno R3, Mega, Leonardo mit / ttyACM [1,2,3]

lsusb-Ausgabe mit Geräten in der oben angegebenen Reihenfolge:

...
Bus 001 Gerät 011: ID 2341: 0043
Bus 001 Gerät 013: ID 2341: 8036
...
Bus 001 Gerät 014: ID 2341: 0042

lsusb -d Anbieter: Gerät -vvv zeigt für jeden

Uno

Bus 001 Gerät 014: ID 2341: 0042
Gerätebeschreibung:
  bLänge 18
  bDescriptorType 1
  bcdUSB 1.10
  bDeviceClass 2-Kommunikation
  bDeviceSubClass 0
  bDeviceProtocol 0
  bMaxPacketSize0 8
  idVendor 0x2341
  idProduct 0x0042
  bcdDevice 0.01
  iManufacturer 1 Arduino (www.arduino.cc)
  iProduct 2
  iSerial 220 55330313735351910141
  bAnzahlKonfigurationen 1
  Konfigurationsdeskriptor:
    bLänge 9
    bDescriptorType 2
    Gesamtlänge 62
    bNumInterfaces 2
    bKonfigurationswert 1
    iConfiguration 0
    bmAttributes 0xc0
      Selbstversorgt
    MaxPower 100mA
    Schnittstellendeskriptor:
      bLänge 9
      bDescriptorType 4
      bInterfaceNumber 0
      bAlternateSetting 0
      bAnzahlEndpunkte 1
      bInterfaceClass 2-Kommunikation
      bInterfaceSubClass 2 Abstract (Modem)
      bInterfaceProtocol 1 AT-Befehle (v.25ter)
      iInterface 0
      CDC-Header:
        bcdCDC 10.01
      CDC ACM:
        bmCapabilities 0x06
          Sendet Pause
          Leitungscodierung und serieller Zustand
      CDC Union:
        bMasterInterface 0
        bSlaveInterface 1
      Endpunkt-Deskriptor:
        bLänge 7
        bDescriptorType 5
        bEndpointAddress 0x82 EP 2 IN
        bmAttributes 3
          Übertragungstyp Interrupt
          Synchronisationstyp Keine
          Verwendungsart Daten
        wMaxPacketSize 0x0008 1x 8 Bytes
        bIntervall 255
    Schnittstellendeskriptor:
      bLänge 9
      bDescriptorType 4
      bInterfaceNumber 1
      bAlternateSetting 0
      bAnzahlEndpunkte 2
      bInterfaceClass 10 CDC-Daten
      bInterfaceSubClass 0 Nicht verwendet
      bInterfaceProtocol 0
      iInterface 0
      Endpunkt-Deskriptor:
        bLänge 7
        bDescriptorType 5
        bEndpointAddress 0x04 EP 4 OUT
        bmAttributes 2
          Übertragungsart Bulk
          Synchronisationstyp Keine
          Verwendungsart Daten
        wMaxPacketSize 0x0040 1x 64 Bytes
        bIntervall 1
      Endpunkt-Deskriptor:
        bLänge 7
        bDescriptorType 5
        bEndpointAddress 0x83 EP 3 IN
        bmAttributes 2
          Übertragungsart Bulk
          Synchronisationstyp Keine
          Verwendungsart Daten
        wMaxPacketSize 0x0040 1x 64 Bytes
        bIntervall 1
Gerätestatus: 0x0000
  (Bus Powered)

Leonardo:

Bus 001 Gerät 013: ID 2341: 8036
Gerätebeschreibung:
  bLänge 18
  bDescriptorType 1
  bcdUSB 2.00
  bDeviceClass 0 (auf Schnittstellenebene definiert)
  bDeviceSubClass 0
  bDeviceProtocol 0
  bMaxPacketSize0 64
  idVendor 0x2341
  idProduct 0x8036
  bcdDevice 1.00
  iManufacturer 1 Arduino LLC
  iProduct 2 Arduino Leonardo
  iSerial 0
  bAnzahlKonfigurationen 1
  Konfigurationsdeskriptor:
    bLänge 9
    bDescriptorType 2
    wTotalLength 100
    bNumInterfaces 3
    bKonfigurationswert 1
    iConfiguration 0
    bmAttributes 0x80
      (Bus Powered)
    MaxPower 500mA
    Schnittstellenzuordnung:
      bLänge 8
      bDescriptorType 11
      bErste Schnittstelle 0
      bInterfaceCount 2
      bFunktionsklasse 2 Kommunikation
      bFunctionSubClass 2 Zusammenfassung (Modem)
      bFunctionProtocol 1 AT-Befehle (v.25ter)
      iFunktion 0
    Schnittstellendeskriptor:
      bLänge 9
      bDescriptorType 4
      bInterfaceNumber 0
      bAlternateSetting 0
      bAnzahlEndpunkte 1
      bInterfaceClass 2-Kommunikation
      bInterfaceSubClass 2 Abstract (Modem)
      bInterfaceProtocol 0 Keine
      iInterface 0
      CDC-Header:
        bcdCDC 1.10
      CDC-Anrufverwaltung:
        bmCapabilities 0x01
          Anrufverwaltung
        bDataInterface 1
      CDC ACM:
        bmCapabilities 0x06
          Sendet Pause
          Leitungscodierung und serieller Zustand
      CDC Union:
        bMasterInterface 0
        bSlaveInterface 1
      Endpunkt-Deskriptor:
        bLänge 7
        bDescriptorType 5
        bEndpointAddress 0x81 EP 1 IN
        bmAttributes 3
          Übertragungstyp Interrupt
          Synchronisationstyp Keine
          Verwendungsart Daten
        wMaxPacketSize 0x0040 1x 64 Bytes
        bIntervall 0
      Endpunkt-Deskriptor:
        bLänge 7
        bDescriptorType 5
        bEndpointAddress 0x83 EP 3 IN
        bmAttributes 2
          Übertragungsart Bulk
          Synchronisationstyp Keine
          Verwendungsart Daten
        wMaxPacketSize 0x0040 1x 64 Bytes
        bIntervall 0
    Schnittstellendeskriptor:
      bLänge 9
      bDescriptorType 4
      bInterfaceNumber 2
      bAlternateSetting 0
      bAnzahlEndpunkte 1
      bInterfaceClass 3 Human Interface Device
      bInterfaceSubClass 0 Keine Unterklasse
      bInterfaceProtocol 0 Keine
      iInterface 0
        HID Device Descriptor:
          bLänge 9
          bDescriptorType 33
          bcdHID 1.01
          bCountryCode 0 Wird nicht unterstützt
          bNumDescriptors 1
          bDescriptorType 34-Bericht
          wDescriptorLength 101
          Berichtsdeskriptor: (Länge ist 101)
            Objekt (global): Nutzungsseite, Daten = [0x01] 1
                            Allgemeine Desktop-Steuerelemente
            Objekt (lokal): Verwendung, Daten = [0x02] 2
                            Maus
            Gegenstand (Haupt): Sammlung, Daten = [0x01] 1
                            Anwendung
            Objekt (lokal): Verwendung, Daten = [0x01] 1
                            Zeiger
            Gegenstand (Haupt): Sammlung, Daten = [0x00] 0
                            Körperlich
            Element (global): Berichts-ID, Daten = [0x01] 1
            Item (Global): Usage Page, data = [0x09] 9
                            Tasten
            Element (lokal): Verwendungsminimum, Daten = [0x01] 1
                            Taste 1 (primär)
            Objekt (lokal): Nutzungsmaximum, Daten = [0x03] 3
                            Knopf 3 (Tertiär)
            Element (global): Logisches Minimum, Daten = [0x00] 0
            Element (global): Logisches Maximum, Daten = [0x01] 1
            Element (global): Berichtsanzahl, Daten = [0x03] 3
            Element (global): Berichtsgröße, Daten = [0x01] 1
            Gegenstand (Haupt): Eingang, Daten = [0x02] 2
                            Datenvariable Absolut No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Element (global): Berichtsanzahl, Daten = [0x01] 1
            Element (global): Berichtsgröße, Daten = [0x05] 5
            Gegenstand (Haupt): Eingang, Daten = [0x03] 3
                            Konstante Variable Absolut No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Objekt (global): Nutzungsseite, Daten = [0x01] 1
                            Allgemeine Desktop-Steuerelemente
            Element (lokal): Verwendung, Daten = [0x30] 48
                            Richtung-X
            Element (lokal): Verwendung, Daten = [0x31] 49
                            Richtung-Y
            Element (lokal): Verwendung, Daten = [0x38] 56
                            Rad
            Element (global): Logisches Minimum, Daten = [0x81] 129
            Element (global): Logisches Maximum, Daten = [0x7f] 127
            Element (global): Berichtsgröße, Daten = [0x08] 8
            Element (global): Berichtsanzahl, Daten = [0x03] 3
            Punkt (Haupt): Eingang, Daten = [0x06] 6
                            Datenvariable Relativ No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Gegenstand (Haupt): Sammlung beenden, Daten = keine
            Gegenstand (Haupt): Sammlung beenden, Daten = keine

            ......

      Endpunkt-Deskriptor:
        bLänge 7
        bDescriptorType 5
        bEndpointAddress 0x84 EP 4 IN
        bmAttributes 3
          Übertragungstyp Interrupt
          Synchronisationstyp Keine
          Verwendungsart Daten
        wMaxPacketSize 0x0040 1x 64 Bytes
        bIntervall 1
Gerätestatus: 0x0000
  (Bus Powered)

Und Mega256:

Bus 001 Gerät 014: ID 2341: 0042
Gerätebeschreibung:
  bLänge 18
  bDescriptorType 1
  bcdUSB 1.10
  bDeviceClass 2-Kommunikation
  bDeviceSubClass 0
  bDeviceProtocol 0
  bMaxPacketSize0 8
  idVendor 0x2341
  idProduct 0x0042
  bcdDevice 0.01
  iManufacturer 1 Arduino (www.arduino.cc)
  iProduct 2
  iSerial 220 55330313735351910141
  bAnzahlKonfigurationen 1
  Konfigurationsdeskriptor:
    bLänge 9
    bDescriptorType 2
    Gesamtlänge 62
    bNumInterfaces 2
    bKonfigurationswert 1
    iConfiguration 0
    bmAttributes 0xc0
      Selbstversorgt
    MaxPower 100mA
    Schnittstellendeskriptor:
      bLänge 9
      bDescriptorType 4
      bInterfaceNumber 0
      bAlternateSetting 0
      bAnzahlEndpunkte 1
      bInterfaceClass 2-Kommunikation
      bInterfaceSubClass 2 Abstract (Modem)
      bInterfaceProtocol 1 AT-Befehle (v.25ter)
      iInterface 0
      CDC-Header:
        bcdCDC 10.01
      CDC ACM:
        bmCapabilities 0x06
          Sendet Pause
          Leitungscodierung und serieller Zustand
      CDC Union:
        bMasterInterface 0
        bSlaveInterface 1
      Endpunkt-Deskriptor:
        bLänge 7
        bDescriptorType 5
        bEndpointAddress 0x82 EP 2 IN
        bmAttributes 3
          Übertragungstyp Interrupt
          Synchronisationstyp Keine
          Verwendungsart Daten
        wMaxPacketSize 0x0008 1x 8 Bytes
        bIntervall 255
    Schnittstellendeskriptor:
      bLänge 9
      bDescriptorType 4
      bInterfaceNumber 1
      bAlternateSetting 0
      bAnzahlEndpunkte 2
      bInterfaceClass 10 CDC-Daten
      bInterfaceSubClass 0 Nicht verwendet
      bInterfaceProtocol 0
      iInterface 0
      Endpunkt-Deskriptor:
        bLänge 7
        bDescriptorType 5
        bEndpointAddress 0x04 EP 4 OUT
        bmAttributes 2
          Übertragungsart Bulk
          Synchronisationstyp Keine
          Verwendungsart Daten
        wMaxPacketSize 0x0040 1x 64 Bytes
        bIntervall 1
      Endpunkt-Deskriptor:
        bLänge 7
        bDescriptorType 5
        bEndpointAddress 0x83 EP 3 IN
        bmAttributes 2
          Übertragungsart Bulk
          Synchronisationstyp Keine
          Verwendungsart Daten
        wMaxPacketSize 0x0040 1x 64 Bytes
        bIntervall 1
Gerätestatus: 0x0000
  (Bus Powered)
vlad b.
quelle
lsusb -vvvsagt?
Ignacio Vazquez-Abrams
Kannst du einen herausziehen und sehen, welcher verschwindet?
Anonymous Penguin
1
Nicht wirklich, ich möchte dies für ein ferngesteuertes solarbetriebenes Sensor-Array tun, das für jemanden sehr weit entfernt ist, dies zu tun, wenn es neu gestartet wird.
vlad b.
Ignacio Vasquez-Abrams - Wie kann ich die Informationen von lsusb -vvv zu / dev / ttyACM <x> zuordnen? Gibt es etwas in der lsusb-Ausgabe, das ich analysieren kann? Danke für die Idee!
vlad b.
Haben Sie ein anderes Arduino, mit dem Sie die Ausgabe vergleichen können?
Ignacio Vazquez-Abrams

Antworten:

6

Angenommen, Ihre Distribution verwendet udev:

udevadm info --query=all --name=/dev/ttyACM0

Möglicherweise benötigen Sie Root-Rechte, um dies auszuführen (sudo / su). Es wird eine Liste mit Informationen wie die folgende ausgegeben:

P: /devices/pci0000:00/0000:00:1d.2/usb4/4-2/4-2:1.0/tty/ttyACM0
N: ttyACM0
S: serial/by-id/usb-Dean_Camera_LUFA_USB-RS232_Adapter_74133353537351403012-if00
S: serial/by-path/pci-0000:00:1d.2-usb-0:2:1.0
E: DEVLINKS=/dev/serial/by-id/usb-Dean_Camera_LUFA_USB-RS232_Adapter_74133353537351403012-if00 /dev/serial/by-path/pci-0000:00:1d.2-usb-0:2:1.0
E: DEVNAME=/dev/ttyACM0
E: DEVPATH=/devices/pci0000:00/0000:00:1d.2/usb4/4-2/4-2:1.0/tty/ttyACM0
E: ID_BUS=usb
E: ID_MM_CANDIDATE=1
E: ID_MODEL=LUFA_USB-RS232_Adapter
E: ID_MODEL_ENC=LUFA\x20USB-RS232\x20Adapter
E: ID_MODEL_FROM_DATABASE=Uno R3 (CDC ACM)
E: ID_MODEL_ID=0043
E: ID_PATH=pci-0000:00:1d.2-usb-0:2:1.0
E: ID_PATH_TAG=pci-0000_00_1d_2-usb-0_2_1_0
E: ID_REVISION=0001
E: ID_SERIAL=Dean_Camera_LUFA_USB-RS232_Adapter_74133353537351403012
E: ID_SERIAL_SHORT=74133353537351403012
E: ID_TYPE=generic
E: ID_USB_DRIVER=cdc_acm
E: ID_USB_INTERFACES=:020201:0a0000:
E: ID_USB_INTERFACE_NUM=00
E: ID_VENDOR=Dean_Camera
E: ID_VENDOR_ENC=Dean\x20Camera
E: ID_VENDOR_FROM_DATABASE=Arduino SA
E: ID_VENDOR_ID=2341
E: MAJOR=166
E: MINOR=0
E: SUBSYSTEM=tty
E: UDEV_LOG=3
E: USEC_INITIALIZED=751387324986

Dies ist für ein Uno mit geänderter Firmware auf dem atmega16u2 (USB zu Seriell). Die Linien von Interesse sind wahrscheinlich ID_MODEL_ID und ID_MODEL_FROM_DATABASE.

user2973
quelle
Vielen Dank. In diesem Fall verwende ich OpenWrt standardmäßig mit hotplug2, aber ich werde versuchen, zu udev zu wechseln und dies zu testen.
vlad b.
5

Sie können für jedes einen Alias ​​hinzufügen. Dann weißt du was was ist. Hier ist ein nettes Tutorial, wie man das einrichtet.

Hier ist ein Ausschnitt, den ich basierend auf dem Tutorial geschrieben habe. Im folgenden Beispiel verwende ich einen FTDI RS232RL USB to Serial-Adapter, von dem ich glaube, dass er auch vom Arduino verwendet wird.

  1. Um einem USB-Serial-Gerät einen Alias ​​zuzuweisen, müssen wir einige Informationen auf dem Gerät finden
  2. Schließen Sie den USB an. Dies setzt voraus, dass Sie bereits die Treiber für dieses Gerät installiert haben und das Gerät bei der Eingabe sichtbar ist:

lsusb

  1. Wir werden folgendes brauchen: a. Die Verkäufer-ID b. Die Produkt-ID c. Die Seriennummer des Geräts
  2. Dazu ist ein bisschen Jagd nötig. Alle Ihre Geräte protokollieren Einträge in '/ var / log / messages'.

Daher können wir diese Datei lesen und den richtigen USB finden:

grep "ftdi" /var/log/messages

Sie können auch "USB" verwenden

  1. Hier finden Sie alle mit ftdi getaggten Nachrichten:

  2. Neben ftdi_sio steht eine Zahl wie 1-1.2. Dies ist das USB-Gerät

grep "usb 1-1.2" /var/log/messages

Oder Sie können verwenden:

dmesg | grep "usb 1-1.3"
  1. Dies gibt uns alle Informationen, die wir brauchen:

USB-Alias

  1. Erstellen wir nun mit der Liste der Seriennummern einen UDEV-Regelsatz, der für jedes dieser Geräte eine nette symbolische Verknüpfung darstellt. UDEV-Regeln sind normalerweise in vielen Dateien in /etc/udev/rules.d verteilt. Erstellen Sie eine neue Datei mit dem Namen 99-usb-serial.rules und fügen Sie dort die folgenden Zeilen ein:

In diesem Beispiel heißt mein Alias ​​'lcdbox'

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A601ERJJ", SYMLINK+="lcdbox"
  1. SYMLINK ist der Name Ihres Alias. In diesem Fall ist mein Alias ​​lcdbox.
  2. Speichern Sie die Datei und geben Sie sie ein

    sudo udevadm control --reload-rules

  3. Art

    ls –l / dev / lcdbox

lrwxrwxrwx 1 root root 7. Januar 1970 / dev / lcdbox -> ttyUSB0

  1. Dies zeigt, dass mein lcdbox-Alias ​​ttyUSB0 zugeordnet ist
PhillyNJ
quelle
4

Das ist ganz einfach! Sie müssen die Firmware des ftdi-Chips anpassen und eine udev-Regel hinzufügen:

Holen Sie sich zunächst ftdi_eepromüber apt-getoder aus den Quellen. Identifizieren Sie Ihr Gerät über lsusb und erhalten Sie die ID:

lsusb

Bus 001 Gerät 005: ID 0403: 6001 Future Technology Devices International, Ltd. Serieller FT232-IC (UART)
....

Bereiten Sie eine Konfiguration und stellen Sie sicher, dass vendor_idund anzeigen product_idlassen. Passen Sie die Zeichenfolgen im StringsAbschnitt an, um eine eindeutige ID für Ihr Gerät zu erhalten.

vendor_id = 0x0403 # Vendor ID
product_id = 0x6001 # Produkt-ID

max_power = 50 # max. Stromverbrauch: Wert * 2 mA. Verwenden Sie 0, wenn self_powered = true ist.

###########
# Strings #
########### 
Hersteller = "FTDI" # Hersteller
product = "Arduino Nano" # Produkt
serial = "arduino1" # Serial

###########
# Optionen #
###########
self_powered = false # Deaktivieren Sie diese Option für busgespeiste Geräte
remote_wakeup = false # Aktivieren Sie diese Option für die Remote-Aktivierung
use_serial = true # Verwenden Sie die Seriennummer

# Normalerweise muss eines dieser Flags nicht geändert werden
# BM_type_chip = true # Neuere Chips sind alle vom Typ BM
in_is_isochronous = false # In Endpoint ist Isochronous
out_is_isochronous = false # Out Endpunkt ist isochron
suspend_pull_downs = false # Aktiviert Suspend-Pulldowns für geringere Leistung
change_usb_version = false # Ändert die USB-Version
usb_version = 0x0200 # Wird nur verwendet, wenn change_usb_version aktiviert ist

#########
# Verschiedenes #
#########

filename = "eeprom.old" # Dateiname, leer lassen, um das Schreiben von Dateien zu überspringen
cbus0 = RXLED #
cbus1 = TXLED #

Sichern Sie sich die aktuelle ftdi-Firmware:

ftdi_eeprom --read-eprom

Dieser Befehl erstellt ${pwd}/eeprom.old, welcher die aktuelle Firmware auf dem ftdi enthält. Sichern Sie diese Datei, bevor Sie fortfahren , da sie während flash-eepromder Datei neu geschrieben wird. Flashen Sie nach dem Backup die ftdi:

ftdi_eeprom --flash-eeprom myconfig.conf

Erstellen Sie nun wie folgt eine udev-Regel

SUBSYSTEMS=="usb", ATTRS{idProduct}=="6001", ATTRS{idVendor}=="0403", SYMLINK+="$attr{serial}", OWNER="bananapi", GROUP="pi", MODE="0777"

in /etc/udev/rules.d/90-arduino-usb.rulesund starten Sie udev neu.

service udev restart

Trennen Sie das Gerät vom Stromnetz und schließen Sie es erneut an

ls -lah /dev/arduino1

Wo arduino1ist die Zeichenfolge unter definierten serialin der oben .conf.

Siehe auch: Risiken von ftdi_eeprom? - TX nach dem Blinken immer hoch

ansi_lumen
quelle
3

Ich hätte ein Skript verwendet, um einen Alias ​​unter zu erstellen /dev/und udevwie bei den anderen Antworten auch Gruppe und Rechte darauf festzulegen.

Aber wenn ich nicht hätte, udevwürde ich lsusbin grepoder awkwie pfeifen lsusb|grep -e "idProduct".

Wie auch immer, mit udevRegeln oder mit lsusbund grepUSB - Geräten, die Verwendung zu identifizieren idVendor, idProductund iSerialin Device descriptorTeil lsusbzu der richtigen idenification zu machen. Das idVendorsagt Ihnen der Hersteller, idProductsollte das Produkt vom Hersteller identifizieren, aber manchmal verwenden sie die gleiche Produkt-ID für mehr als ein Produkt. Schließlich iSerialsollte bei Bedarf eine eindeutige ID für jedes Beispiel dieses Produkts angegeben werden.

Anders
quelle
3

Unter Ubuntu 16.04 (und möglicherweise auch früheren Versionen oder anderen Distributionen) können Sie Folgendes tun:

> ls /dev/serial/by-id

welches Display (auf meiner Box, an der ein Arduino UNO angeschlossen ist):

usb-Arduino__www.arduino.cc__0043_A4139363931351318241-if00

Sie können die Geräte-ID 0043 (UNO) hier leicht erkennen.

Diese Datei ist eigentlich ein Link zu /dev/ttyACM0meiner Box.

jfpoilpret
quelle
2

Sie können in void setup () immer eine Art ID-Druck über die serielle Schnittstelle erstellen. Nachdem das bestimmte Board angeschlossen ist, sendet es diese ID an Ihre USB-Schnittstelle (die Sie mit einer Art Daemon-App auf Ihrer Linux-Box hören). Sobald Sie die ID erhalten haben, können Sie sie dem Pfad 'Arduino1' zuordnen: '/ dev / ttyACM0', 'Arduino2': '/ dev / ttyACM1', 'Arduino3': '/dev/ttyACM2' ... etc

Beachten Sie, dass das Gerät den physischen Pfad ändern kann, wenn es aus irgendeinem Grund getrennt wird, sodass Sie möglicherweise alle neu zuordnen müssen. In diesem Fall kann es sinnvoll sein, die Funktion ex: get_id () zu schreiben, die Sie jederzeit aufrufen können (nicht nur beim Start).

Cyberbrain
quelle
1

Ich wäre in der Versuchung, mich auf eine andere Art zu identifizieren, zum Beispiel, wenn die Skizze selbst auf einen speziellen Identifizierungsbefehl reagiert, nur um die ungewöhnlichen Möglichkeiten von USB zu vermeiden, Geräte zu identifizieren.

EternityForest
quelle