PortableSerialLib - Portable Serial Port Library

OP #2586827
Lesenswert?

Hi,

Letztens hatte ich nach einer kleinen C-Lib gesucht, die die Ansteuerung 
der Seriellen Schnittstelle kapselt, so dass für Linux und Windows keine 
Codeanpassungen notwendig sind.

Da die Suchergebnisse recht dürftig waren und das was ich gefunden 
(genau genommen war es nur eine Bibleothek und eine Ausarbeitung) habe 
nicht meinen Vorstellungen entsprochen hat, habe ich was eigenes 
aufgesetzt.

Wichtig war mir ein blockierendes Lesen und die Möglichkeit in einem 
Thread blockierend zu lesen und in einem anderen schreiben zu können.
Unter Windows wird dafür Overlapped IO benutzt. Unter Linux scheint es 
ohne weitere Maßnahmen zu funktionieren.


Die Linuximplementierung gefällt mir noch nicht so richtig.
Ich habe nicht so richtig rausbekommen, wie man beliebige baudraten 
einstellen kann. Zum anderen weiß ich nicht, wie ich das so 
konfigurieren kann, dass er unendlich lange blockiert, bis er alle 
Zeichen des read-requests bekommen hat.
VTIME geht nur maximal 25s. und wenn VMIN < bytesToRead-Param der Read 
Funktion ist, scheint auch undefiniert zu sein, was da passiert.
Deswegen wird jetzt VMIN auf 1 gestellt und im read Byteweise gelesen.

Dennoch ist das Ganze insgesamt auf einem Stand, in dem es mir momentan 
gut ausreicht, weswegen ich jetzt erstmal auf dem Stand lasse.

Wenn jemand Vorschläge/Verbesserungen hat, dann bin ich dafür offen und 
werde das sicherlich auch einpflegen.


Gruß,
Vlad
OP #2587364
Lesenswert?

Ach so,  was in der Linux Implementieurung auch noch fehlt, ist die 
Funktion zum auflisten der verfügbaren devices.

Die Möglichkeiten, die ich gefunden habe, basieren auf dem iterieren 
über alle /dev/ttySxx und /dev/ttyUSBxx Geräteknoten und dem Versuch 
diese zu öffnen. Das ist doch irgendwie Pfusch.
Gast #2587406
Lesenswert?

Vlad Tepesch schrieb:
> Die Möglichkeiten, die ich gefunden habe, basieren auf dem iterieren
> über alle /dev/ttySxx und /dev/ttyUSBxx Geräteknoten und dem Versuch
> diese zu öffnen. Das ist doch irgendwie Pfusch.
Das ist harmlos.

Die Sache mit HKEY_LOCAL_MACHINE/HARDWARE/DEVICEMAP/SERIALCOMM ist ja 
auch  nur die halbe Wahrheit. Vor einer Weile stand ich vor demselben 
Problem (also Schnittstellen auflisten) und habe recherchiert.

Insgesamt musst du praktisch an neun verschiedenen Stellen suchen, um 
wirklich alle Ports zu finden:

[1] 
http://stackoverflow.com/questions/1388871/how-do-i-get-a-list-of-available-serial-ports-in-win32
[2] http://www.naughter.com/enumser.html
OP #2587829
Lesenswert?

Sven P. schrieb:
> Die Sache mit HKEY_LOCAL_MACHINE/HARDWARE/DEVICEMAP/SERIALCOMM ist ja
> auch  nur die halbe Wahrheit.

> [2] http://www.naughter.com/enumser.html


die lib habe ich auch gefunden, fand es aber übertrieben.
Was soll ich mit einer Lib, die auf neun verschiedene Art und weisen die 
Comports sucht? ausßerdem ist mir an der Stelle egal, wie die Methode 
ist, was einen Benutzer interessiert, ist ja eine Liste.
Das ist der große Designfehler dieser Bibliothek.
Interessant wäre genau eine Funktion oder Methode,
die mir eine Liste zurückgibt.
Intern kann die Lib ja meinentwegen so viele Methoden benutzen, wie sie 
will - die gehören nur nicht ins Interface, dass sind Interna.


Sven P. schrieb:
> [1]
> http://stackoverflow.com/questions/1388871/how-do-...

Das hab ich auch gefunden. Genau deswegen habe ich auch die letzte 
Variante gewählt.

Für Windows gibts ja auch diese Pfuschvariante mit Namen aus "COM"+X 
bilden.
Nur dumm, dass die Ports beliebige Namen haben können. Die com0com haben 
defaultmäßig ja auch total schräge bezeichnungen, die dann von den 
ganzen Tools, die auf die Pfuschvariante setzen nicht gefunden werden.

Deswegen scheint mir das ganze auch unter Linux etwas fragwürdig. woher 
weiß ich denn, ob nicht nächtes Jahr eine serielle Schnittstelle auf 
Basis von Thunderbold erscheint, die dann /dev/ttyTB0 oder so heißt, 
oder irgendjemand die Geräteknoten einfach anders benennt.

Es muss doch auch irgendwie anders möglich sein.
Persönliche Seite #2587864
Lesenswert?

Vlad Tepesch schrieb:
> die dann /dev/ttyTB0 oder so heißt,
> oder irgendjemand die Geräteknoten einfach anders benennt

Ich habe mich auch mal vor einiger zeit damit beschäftigt.
Über /proc/tty/drivers kann man sich eine solche Liste abrufen:
http://stackoverflow.com/questions/2530096/linux-how-to-find-all-serial-devices-ttys-ttyusb-without-opening-them
Es werden auch ein paar Alternative angerissen über dbus/hal
Gast #2587868
Lesenswert?

Vlad Tepesch schrieb:
> Interessant wäre genau eine Funktion oder Methode,
> die mir eine Liste zurückgibt.
Naja, dann bau doch eine draus. Für was andres ist die Bibliothek da 
auch garnicht gedacht gewesen.


> Deswegen scheint mir das ganze auch unter Linux etwas fragwürdig. woher
> weiß ich denn, ob nicht nächtes Jahr eine serielle Schnittstelle auf
> Basis von Thunderbold erscheint, die dann /dev/ttyTB0 oder so heißt,
> oder irgendjemand die Geräteknoten einfach anders benennt.
>
> Es muss doch auch irgendwie anders möglich sein.
Mir käme da noch /proc/tty/drivers in den Sinn.
Vielleicht lässt sich über die Major/Minor auch noch was herausfiltern. 
Ginge jedenfalls schneller, als alle durchzuprobieren und jeweils 
irgendein ioctl() drauf zu machen, welches nur bei seriellen 
Schnittstellen funktioniert :-}

Läubi war schneller.
OP #2587916
Lesenswert?

Läubi .. schrieb:
> Über /proc/tty/drivers kann man sich eine solche Liste abrufen:

Den Inhalt dieser Datei konnte ich nicht interpretieren
In der Doku steht nicht mal eine Spaltenbeschreibung.

Hab jetzt folgendes dazu gefunden:
http://lwn.net/images/pdf/LDD3/ch18.pdf

heißt das ich müsste in dieser Datei alle Einträge suchen, die in der 
letzten Spalte serial stehen haben? aus dem Produkt der Differenzen der 
beiden Paare aus den vorstehenden Spalten habe ich dann die maximale 
Anzahl an Geräten dieses Typs. Davor steht der Geräteknoten-Basisname

Was ich jetzt neu gelernt habe, ist das Verzeichnis
/sys/class/tty
zusammen mit dem obigen Wissen kann ich in dem Verzechnis nach 
Verzeichnissen suchen, in denen der Gerätebasisname vorkommt.

Läubi .. schrieb:
> Es werden auch ein paar Alternative angerissen über dbus/hal

das hal Zeugs scheint standardmäßig nicht installiert zu sein (und schon 
gar nicht auf einem kleinen embedded device
Persönliche Seite #2588545
Lesenswert?

Also "so einfach" ist das halt nicht machbar. Ich würde da pragmatisch 
vorgehen und das erst mal so implementieren das es auf deinen 
Zielgeräten zufriedenstellende Ergebnisse liefert.
Du kannst das ja hier auch noch ins SVN stellen, dann kann man das immer 
weiter verfeinern.

Vlad Tepesch schrieb:
> das hal Zeugs scheint standardmäßig nicht installiert zu sein
s.o. man kann versuchen das als zusätzliche Option einzubauen, 
letzendlich wird man aber auch wieder auf viele Optionen kommen welche 
man durchprobieren muss.
Ein paar passende Compileschalter für verschiedene Targets wirds 
vermutlich eh brauchen...
OP #2588559
Lesenswert?

hier eine Version 0.4

hab obigen Ansatz zum Finden von seriellen Geräten unter Linux mal 
implementiert.
wär toll, wenn ihr das mal bei euch auch mal testen könntet.

dann gabs noch eine kleine Interface-Änderung für die Funktion zum 
ermitteln der vorhandenen Seriellen Interfaces.

PortableSerialLib - Change Log
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  * fixed
  ~ changed
  + added
  - removed

v0.4
  ~ PSerLib_getAvailablePorts
    + added linux implementation for PSerLib_getAvailablePorts
    + added define for format of PSerLib_getAvailablePorts-Output
      (full path or just name)
    ~ changed interface of PSerLib_getAvailablePorts function to
      get additional pointer parameter to output number of found
      devices and return a error code.\n
      --> more consistency to all other functions.
    ~ more precise description of o_name parameter
      PSerLib_getAvailablePorts
  ~ set default baud rate of example/test program to a standard
    baud rate value
Angehängte Dateien:
Moderator Persönliche Seite #2588716
Lesenswert?

Vlad Tepesch schrieb:
> Wichtig war mir ein blockierendes Lesen [...]

Du meinst wohl eher nicht-blockierendes Lesen, oder? Oder ein 
blockierendes Read mit Timeout?

> VTIME geht nur maximal 25s. und wenn VMIN < bytesToRead-Param der Read
> Funktion ist, scheint auch undefiniert zu sein, was da passiert.

Du willst einen Timeout implementieren? Nimm select().
Wenn Du weitere Fragen/Unklarheiten zur seriellen Schnittstelle unter 
Linux hast, frag mich einfach. Ich kenne die TTYs aus dem Effeff :-)

Gruß,

Frank
(Firma: von Dänemark) #2966764
Lesenswert?

Hi Vlad

Thanx for the nice library

However i have a small improvement suggestion

I have been using the library with an Arduino , and was always 
triggering an Arduino Reset when using your lib.

I have traced it to this function in PortableSerialLibLinux.c
1
  if(   (tcsetattr(io_port->port, TCSANOW, &newSettings)  < 0) 
2
     || (cfsetispeed(&newSettings, speed) < 0)
3
     || (cfsetospeed(&newSettings, speed) < 0))
4
  {
5
    return PSL_ERROR_configurePort;
6
  }

And changing it to
1
  if(   (cfsetispeed(&newSettings, speed) < 0)
2
     || (cfsetospeed(&newSettings, speed) < 0)
3
     || (tcsetattr(io_port->port, TCSANOW, &newSettings)  < 0))
4
  {
5
    return PSL_ERROR_configurePort;
6
  }

Solves the problem.

Before filling data in the struct , you zero'es the struct.
1
  memset(&newSettings, 0, sizeof(newSettings));  /* clear the new struct */

But according to this , setting a speed/baud to 0 (Seek B0), will clear 
DTR
http://www.easysw.com/~mike/serial/serial.html
http://homepages.cwi.nl/~aeb/linux/man2html/man3/termios.3.html

And in your code you call tcsetattr , before setting the speed , so the 
speed is zero , causing a DTR reset.


In my example i set the speed before calling tcsetattr , and now the 
Arduino isnt reset on opening the SerialPort.


Hope you will correct the nice library

Regards
Karsten Dänemark

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren