Was ist der richtige Weg, um eine Liste aller verfügbaren seriellen Ports / Geräte auf einem Linux-System zu erhalten?
Mit anderen Worten, wenn ich über alle Geräte in iteriere /dev/
, wie kann ich dann feststellen, welche auf klassische Weise serielle Ports sind, dh solche, die normalerweise Baudraten und RTS / CTS- Flusskontrolle unterstützen?
Die Lösung würde in C codiert.
Ich frage, weil ich eine Bibliothek eines Drittanbieters verwende, die dies eindeutig falsch macht: Sie scheint nur zu iterieren /dev/ttyS*
. Das Problem ist, dass es beispielsweise serielle Anschlüsse über USB gibt (bereitgestellt von USB-RS232-Adaptern), die unter / dev / ttyUSB * aufgeführt sind. Wenn ich das Serial-HOWTO auf Linux.org lese , komme ich auf die Idee, dass es mit der Zeit auch andere Namensräume geben wird.
Ich muss also den offiziellen Weg finden, um serielle Geräte zu erkennen. Das Problem ist, dass keine dokumentiert zu sein scheint oder ich sie nicht finden kann.
Ich kann mir vorstellen, dass eine Möglichkeit darin besteht, alle Dateien zu öffnen /dev/tty*
und eine bestimmte Datei aufzurufen ioctl()
, die nur auf seriellen Geräten verfügbar ist. Wäre das aber eine gute Lösung?
Aktualisieren
hrickards schlug vor, in der Quelle nach "setserial" zu suchen. Sein Code macht genau das, was ich mir vorgestellt habe:
Zunächst wird ein Gerät geöffnet mit:
fd = open (path, O_RDWR | O_NONBLOCK)
Dann ruft es auf:
ioctl (fd, TIOCGSERIAL, &serinfo)
Wenn dieser Aufruf keinen Fehler zurückgibt, handelt es sich anscheinend um ein serielles Gerät.
Ich habe ähnlichen Code in Serial Programming / termios gefunden , der vorschlug, auch die O_NOCTTY
Option hinzuzufügen .
Bei diesem Ansatz gibt es jedoch ein Problem:
Als ich diesen Code unter BSD Unix (dh Mac OS X) getestet habe, hat er auch funktioniert. jedoch seriellen Geräten, die über Bluetooth bereitgestellt werden, versucht das System (der Treiber) jedoch, eine Verbindung zum Bluetooth-Gerät herzustellen. Es dauert eine Weile, bis ein Timeout-Fehler auftritt. Dies wird durch einfaches Öffnen des Geräts verursacht. Und ich kann mir vorstellen, dass ähnliche Dinge auch unter Linux passieren können - im Idealfall sollte ich das Gerät nicht öffnen müssen, um seinen Typ herauszufinden. Ich frage mich, ob es auch eine Möglichkeit gibt, ioctl
Funktionen ohne Öffnen aufzurufen oder ein Gerät so zu öffnen, dass keine Verbindungen hergestellt werden.
Was soll ich machen?
quelle
Antworten:
Das
/sys
Dateisystem sollte viele Informationen für Ihre Suche enthalten. Mein System (2.6.32-40-generic # 87-Ubuntu) schlägt vor:Hier finden Sie Beschreibungen aller dem System bekannten TTY-Geräte. Ein gekürztes Beispiel:
Folgen Sie einem dieser Links:
Hier
dev
enthält die Datei diese Informationen:Dies ist der Haupt- / Nebenknoten. Diese können im
/dev
Verzeichnis nach benutzerfreundlichen Namen durchsucht werden :Das
/sys/class/tty
Verzeichnis enthält alle TTY-Geräte, aber Sie möchten möglicherweise diese lästigen virtuellen Terminals und Pseudo-Terminals ausschließen. Ich schlage vor, Sie untersuchen nur diejenigen, die einendevice/driver
Eintrag haben:quelle
/dev/zero
. Denken Sie wirklich, dass dies ein serielles Gerät ist?In neueren Kerneln (seit wann nicht sicher) können Sie den Inhalt von / dev / serial auflisten, um eine Liste der seriellen Ports auf Ihrem System zu erhalten. Es handelt sich tatsächlich um Symlinks, die auf den richtigen / dev / node verweisen:
Dies ist ein USB-Serial-Adapter, wie Sie sehen können. Beachten Sie, dass das Verzeichnis / dev / serial / nicht vorhanden ist, wenn keine seriellen Schnittstellen im System vorhanden sind. Hoffe das hilft :).
quelle
Ich mache so etwas wie den folgenden Code. Es funktioniert für USB-Geräte und auch für die dummen serial8250-Geräte, von denen wir alle 30 haben - aber nur ein paar davon funktionieren wirklich.
Grundsätzlich verwende ich das Konzept aus früheren Antworten. Zählen Sie zuerst alle tty-Geräte in / sys / class / tty / auf. Geräte, die kein / device-Unterverzeichnis enthalten, werden weggefiltert. / sys / class / tty / console ist ein solches Gerät. Dann werden die Geräte, die tatsächlich Geräte enthalten, als gültige serielle Schnittstelle akzeptiert, abhängig vom Ziel des Treiber-Symlink-FX.
und für ttyS0
Alle von serial8250 angetriebenen Treiber müssen Sonden sein, die das zuvor erwähnte ioctl verwenden.
Nur der Port, der einen gültigen Gerätetyp meldet, ist gültig.
Die vollständige Quelle für die Aufzählung der seriellen Ports sieht folgendermaßen aus. Ergänzungen sind willkommen.
quelle
Ich glaube, ich habe die Antwort in meiner Kernel-Quelldokumentation gefunden: /usr/src/linux-2.6.37-rc3/Documentation/filesystems/proc.txt
Hier ist ein Link zu dieser Datei: http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=blob_plain;f=Documentation/filesystems/proc.txt;hb = e8883f8057c0f7c9950fa9f20568f37bfa62f34a
quelle
ich fand
den Job machen.
quelle
Setserial mit der Option -g scheint zu tun, was Sie wollen, und die C-Quelle ist unter http://www.koders.com/c/fid39344DABD14604E70DF1B8FEA7D920A94AF78BF8.aspx verfügbar .
quelle
Ich habe hier kein serielles Gerät, um es zu testen, aber wenn Sie Python und dbus haben, können Sie es selbst versuchen.
Wenn es fehlschlägt, können Sie nach innen suchen
hwmanager_i.GetAllDevicesWithProperties()
, ob der soeben vermutete Funktionsname "serial" einen anderen Namen hat.HTH
quelle
Ich habe kein serielles USB-Gerät, aber es muss eine Möglichkeit geben, die realen Ports mithilfe der HAL-Bibliotheken direkt zu finden:
Der veröffentlichte Python-dbus-Code und dieses sh-Skript listen die Bluetooth / dev / rfcomm * -Geräte auf, daher ist dies nicht die beste Lösung.
Beachten Sie, dass auf anderen Unix-Plattformen die seriellen Ports nicht ttyS? Bei einigen seriellen Karten können Sie die Geräte sogar unter Linux benennen. Die Annahme eines Musters in den Namen der seriellen Geräte ist falsch.
quelle
Die Verwendung von / proc / tty / drivers gibt nur an, welche tty-Treiber geladen sind. Wenn Sie nach einer Liste der seriellen Ports suchen, überprüfen Sie / dev / serial. Sie enthält zwei Unterverzeichnisse: by-id und by-path.
EX:
Vielen Dank an diesen Beitrag: /superuser/131044/how-do-i-know-which-dev-ttys-is-my-serial-port
quelle
Mein Ansatz über Gruppen- Dialout , um jedes tty mit Benutzer 'Dialout'
ls -l /dev/tty* | grep 'dialout'
zu bekommen , um nur seinen Ordner zu bekommenls -l /dev/tty* | grep 'dialout' | rev | cut -d " " -f1 | rev
Hören Sie sich einfach die tty-Ausgabe an, z. B. wenn Arduino seriell ausgeht:
head --lines 1 < /dev/ttyUSB0
Hören Sie sich jede Zeile nur für eine Zeile an:
for i in $(ls -l /dev/tty* | grep 'dialout' | rev | cut -d " " -f1 | rev); do head --lines 1 < $i; done
Ich mag den Ansatz über die Suche nach Fahrern sehr:
ll /sys/class/tty/*/device/driver
Sie können jetzt den tty-Namen auswählen:
ls /sys/class/tty/*/device/driver | grep 'driver' | cut -d "/" -f 5
quelle
Die Serial Communication Manager-Bibliothek verfügt über viele APIs und Funktionen, die auf die gewünschte Aufgabe zugeschnitten sind. Wenn das Gerät ein USB-UART ist, kann seine VID / PID verwendet werden. Wenn das Gerät BT-SPP ist, können plattformspezifische APIs verwendet werden. Schauen Sie sich dieses Projekt für die Programmierung der seriellen Schnittstelle an: https://github.com/RishiGupta12/serial-communication-manager
quelle
Ja, ich weiß, ich bin zu spät (wie immer). Hier ist mein Code (basierend auf der Antwort von mk2). Vielleicht hilft das jemandem:
quelle