momentan schreibe ich eine Software, um über die serielle Schnittstelle eine Hardware zu Parametrisieren. Der Compiler (PureBasic, https://www.purebasic.com/german/) ist kein Cross-Compiler, und die Platformen Linux und MacOS stehen mir nicht zur Verfügung. Linux werde ich in eine VirtualBox installieren, für MacOS werde ich meine Nichte bitten, das zu kompilieren.
Problem: Zum Einstellen der seriellen Schnittstelle durchforste ich im Windows-Branch (Compiler-Select) einfach alle COM-Ports von 1...32 und stelle alle Gefundenen in einer ComboBox zur Auswahl bereit. Die Prozedur dafür ist:
Als Workaround hätte ich die ComboBox editable gemacht, dann kann der User den Eintrag manuell machen. Kann ich davon ausgehen, dass ich einem Linux- oder Mac-User mehr zumuten kann? Die User sind Modelleisenbähnler.
Kann ich bei Linux davon ausgehen, dass die Enumeration immer
"/dev/ttyUSBx" ist?
Nein. /dev/ttyACMx ist auch gängig. Bei MacOS heißen sie wiederum anders. Letztendlich kann da jeder Treiber auch noch sein eigenes Süppchen kochen. Ein Programm dass sich auf ein bestimmtes Muster beschränkt, wird früher oder später Probleme bereiten. Ich würde zusätzlich zur Drop-Down Liste auch noch eine freie Texteingabe zulassen.
Unter Linux sind da, wie bereits angesprochen, mehrere Namen üblich.
Ich würde, wenn ich wirklich sichergehen will, dass ich alle seriellen Schnittstellen aufliste, in /sys/class/tty gucken und alles weglassen, was bekanntermaßen keine serielle Schnittstelle ist.
Problem: Zum Einstellen der seriellen Schnittstelle durchforste ich im
Windows-Branch (Compiler-Select) einfach alle COM-Ports von 1...32 und
stelle alle Gefundenen in einer ComboBox zur Auswahl bereit.
SO macht man das eigentlich nicht. Die Win32 API stellt zwei Wege für das Enumerieren von (beliebigen) Devices zur Verfügung:
Wenn Du Ports wahllos öffnest und wieder schließt, könnten das einige Geräte übelnehmen. Über die offiziellen APIs kannst Du auch USB-Devices durchenumerieren, nach bestimmten VID/PID/SerialNum filtern und dann abfragen, ob und wenn ja welcher COM: dann da dran hängt. Im Netz gibts genug Dokumentation dazu. Das hat den Vorteil, dass Du nur DEINE EIGENEN FTDI-UARTs bekommst und nicht irgendwelche fremden Geräte, die zufällig auch die gleichen FTDI-Bridges drin haben.
Bei Linux kannst Du entweder das sysfs durchiterieren (z.B. /sys/bus/usb/devices für alle USB-Devices oder /sys/class/tty für alle ttys), oder Du kannst über udev gehen.
Bei MacOS bin ich aktuell nicht im Bilde. Ich hab hier zwar einen stehen, aber auf dem mache ich keine Entwicklung.
Dein jetziger Weg ist jedenfalls nicht im Sinne der Erfinder.
Wenn man das auch in Zukunft wörtlich nimmt und keinen extra Treiber installiert, gibt es nur /dev/ttyUSBx; auch mit den 2-fach und 4-fach Konvertern von FTDI.
Die Idee mit dmesg finde ich nicht schön, das ist ein Ringpuffer. Wenn auf einem Rechner viel los ist, fehlen die ältesten Einträge irgendwann. Konverter, die schon beim Einschalten eingesteckt waren, findet man dann nicht. Das sicherste ist, in /dev nach ttyUSBx zu suchen. Man könnte auch ein paar andere Verzeichnisse nehmen, aber die sind teils bewegliche Ziele oder nicht immer vorhanden oder nicht aktuell. /dev wird es noch lange geben und es wird direkt vom Kernel selbst in Echtzeit aktualisiert.
/dev/ttySx sind die klassischen COM-Ports aus DOS-Zeiten. 2 bis 4 davon tauchen auch bei modernen Boards auf und auch, wenn es die Stecker garnicht gibt. Die würde ich direkt ignorieren.
Niemand hindert dich daran, per einfacher Udev-Rule alle FTDI-Ports (oder auch nur die mit deiner Seriennummer etc.) als z.B. /dev/ttyFTDI0…99 oder /dev/dasGerät anzulegen.
Ansonsten erleuchtet vielleicht ein Blick in die Datei "/usr/lib/udev/rules.d/60-serial.rules" aus dem default udev/systemd-Regelwerk:
unter /dev/serial/by-id finden sich die USB-Seriel-Ports mit sehr aussagekräftigen Dateinamen. Da die Richtigen für deine Hardware rauszufiltern ist einfach.
Niemand hindert dich daran, per einfacher Udev-Rule alle FTDI-Ports
(oder auch nur die mit deiner Seriennummer etc.) als z.B.
/dev/ttyFTDI0…99 oder /dev/dasGerät anzulegen.
Klar, wenn es praktikabel ist, im System herumzuwursteln. Hier scheint es ja um ein Produkt zu gehen, das auf fremden Systemen laufen soll.
Ohne Eingriffe heissen normalerweise nur CDC/ACM-Devices /dev/ttyACM*, die mit herstellerspezifischen Treibern /dev/ttyUSB*, daher mein Einwand bzgl. der FTDI-Chips.
geht hier auf einem Win7-Rechner. Aber jetzt fangen weitere Probleme an:
Auf einem Win10-Rechner hat es den Befehl nicht gefunden. Gegoogelt: Aha, der heisst jetzt neu
1
change port /query
Funktioniert auch auf Win7, aber auf dem Win10-Rechner ums verrecken nicht => wieder nicht gefunden. Da dreht man doch durch!
Kann ich bei Linux davon ausgehen, dass die Enumeration immer
"/dev/ttyUSBx" ist?
Nein. /dev/ttyACMx ist auch gängig. Bei MacOS heißen sie wiederum
anders. Letztendlich kann da jeder Treiber auch noch sein eigenes
Süppchen kochen. Ein Programm dass sich auf ein bestimmtes Muster
beschränkt, wird früher oder später Probleme bereiten. Ich würde
zusätzlich zur Drop-Down Liste auch noch eine freie Texteingabe
zulassen.
Hier ein Beispiel:
iMac $ ls -l /dev/cu.*
crw-rw-rw- 1 root wheel 0x16000007 22 Nov 06:58 /dev/cu.Bluetooth-Incoming-Port
crw-rw-rw- 1 root wheel 0x16000001 22 Nov 06:58 /dev/cu.usbserial-143340
crw-rw-rw- 1 root wheel 0x16000005 22 Nov 06:58 /dev/cu.usbserial-FTGHPOLK
crw-rw-rw- 1 root wheel 0x16000003 22 Nov 06:58 /dev/cu.usbserial-FTH9L0T7
iMac $
Das sind 2 FTDI, ein Prolific 2303 und ein Bluetooth-Device (das aber nicht aktiv ist). Andere Devices melden sich manchmal mit -000000...
D.h. man könnte auf "/dev/ci.usbserial-FT*" filtern wenn man nur die FTDIs haben will.
Wenn man keinen ollen Serial-Port sondern native USB-Geräte verwenden würde, könnte man unter allen Plattformen mit libusb sehr einfach alle angeschlossenen Geräte finden...
Wenn man keinen ollen Serial-Port sondern native USB-Geräte verwenden
würde, könnte man unter allen Plattformen mit libusb sehr einfach alle
angeschlossenen Geräte finden...
So ein FTDI-Konverter ist doch ein "native USB-Gerät"? Und genau solche will man finden.
So ein FTDI-Konverter ist doch ein "native USB-Gerät"?
Nach der Logik sind alle USB-Geräte "nativ". Ich meinte damit ein eigenes anwendungsspezifisches USB-Protokoll zu definieren, statt einen Serial-Port zu emulieren. Problem Nr. 1 ist ja offensichtlich dass aus PC-Sicht alle USB-Serial-Ports gleich sind und dem FTDI nicht anzusehen ist was für ein serielles Protokoll da jetzt drüber gehen soll; bei spezifischen USB-Protokollen kann man das Gerät eindeutig identifizieren.
Dann ist Dein Windows 10 merkwürdig. Alle Windows-Versionen, die ich hier im Büro habe (beginnend bei 2012 Server bis hin zum 2022 Server sowie Windows 10 und Windows 11) kennen "change".
Problem Nr. 1 ist ja offensichtlich dass aus
PC-Sicht alle USB-Serial-Ports gleich sind
Sind sie das? Jeder wird mit dem dafür vorgesehenen Treiber angesprochen, FTDI mit FTDI-Treibern, WCH mit WCH-Treibern, Prolific mit Prolific-Treibern. Der generischen CDC-Treiber kommt nur selten zum Einsatz, denn die meisten USB-Seriell-Bridges sind keine CDC-Geräte.
Jeder wird mit dem dafür vorgesehenen Treiber
angesprochen, FTDI mit FTDI-Treibern, WCH mit WCH-Treibern, Prolific mit
Prolific-Treibern.
Aber alle erzeugen einen generischen COMx-Port. Aus Anwendungssicht gibt es da keinen Unterschied außer eben mit speziellen APIs. Aber auch daran kann man nur den Hersteller des Adapters identifizieren, nicht das tatsächliche Gerät. Zu wissen ob es ein Prolific, FTDI, ... -IC ist hilft kaum dabei zu entscheiden ob da ein Arduino, STK500, Analogmodem oder GPS-Tracker dran hängt.
Wobei: Eigentlich ist die CDC-ACM-Klasse nur dafür gemacht, Analog-Modems mit AT-Command-Set anzusteuern, somit sollten alle CDC-ACM-COM-Ports solchen Modems entsprechen. "Zufällig" erlauben alle(?) Betriebssysteme die Verwendung von solchen Ports auch mit anderen Geräten und anderen Anwendungen als Dial-Up. Daher werden wohl so gut wie alle der CDC-ACM-COM-Ports nicht für Analog-Modems genutzt.
Aber auch daran
kann man nur den Hersteller des Adapters identifizieren, nicht das
tatsächliche Gerät. Zu wissen ob es ein Prolific, FTDI, ... -IC ist
hilft kaum dabei zu entscheiden ob da ein Arduino, STK500, Analogmodem
oder GPS-Tracker dran hängt.
Und? Das war zu den Zeiten, wo man "echte" serielle Schnittstellen verwendete, keinen Deut anders.
Bei USB-Seriell-Bridges ist mehr möglich, da kann dem Ding nämlich über den USB-Descriptor ein Name mitgegeben werden, der sagt, worum es sich handelt -- und dann hat anständig geschriebene Software die Möglichkeit, sich den rauszusuchen und anzuzeigen. Die kann dann natürlich nicht nur die Schnittstellen-API von 1993 verwenden.
Bei USB-Seriell-Bridges ist mehr möglich, da kann dem Ding nämlich über
den USB-Descriptor ein Name mitgegeben werden, der sagt, worum es sich
handelt
Ja, aber wenn man sich schon auf einen ganz spezifischen USB-Serial-IC einschränkt und diesen auch manuell konfiguriert/programmiert, kann man auch gleich sein eigenes Protokoll definieren. Das hat dann auch noch weitere Vorteile, wie eben mehrere Endpoints, automatische Flusskontrolle und Paketierung usw. Das erspart dann auch wieder einiges an Arbeit welche man beim Serialport hat.
Das o.g. C# Snippet habe ich genutzt um eine serielle Kommunikation mit einem eigenen Board zu implementieren. Dank dem gezeigten API war es schön einfach den Port zu finden. Beim Implementieren vom seriellen Protokoll mit Paketierung hab ich aber geflucht und mich gefragt warum ich nicht ein eigenes USB-Protokoll implementiert hab - hätte im Endeffekt wahrscheinlich einiges an Nerven gespart...
Ja, aber wenn man sich schon auf einen ganz spezifischen USB-Serial-IC
einschränkt und diesen auch manuell konfiguriert/programmiert, kann man
auch gleich sein eigenes Protokoll definieren.
Wenn man Lust dazu hat, notfalls einen eigenen Devicetreiber zu klöppeln - und dem Anwender fest vorzuschreiben, mit welcher Software er mit seinen Geräten reden darf, dann kann man das so machen.
und dem Anwender fest vorzuschreiben, mit welcher Software er mit
seinen Geräten reden darf
Der TO entwickelt doch eh seine eigene Software. Ob der Anwender jetzt die serielle Kommunikation oder die USB-Kommunikation sniffen muss um seine eigene Software zu implementieren tut sich nicht viel. Man kann beide Protokolle dokumentieren falls man Eigenentwicklungen erlauben möchte.