Serielle Schnittstellen erkennen (Linux) [testen]

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von Mathias »

Ein Telefon meldet sich ebenfalls mit zwei Schnittstellen an.
(Soweit ich jedenfalls weiß)
Klem das mal ab und schau mal ob ttyACM0 immer noch da ist.

Ich habe es probiert, es war mein Tablett.

Was genau hast du Eigentlich vor?

Eigentlich nichts, ich hatte nur den obigen Code getestet.

Eine Frage hätte ich trotzdem noch.
Wen ich ls /dev/tty* eingebe, kommen ca.100 tty-Geräte.
So viele serielle Schnittstellen habe ich kaum in meinem PC verbaut.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von pluto »

Eine Frage hätte ich trotzdem noch.
Wen ich ls /dev/tty* eingebe, kommen ca.100 tty-Geräte.
So viele serielle Schnittstellen habe ich kaum in meinem PC verbaut.

Das habe ich mir auch schon gefragt, ein Teil sind die Konsolen, die es gibt, aber ich meine die gehen nur von tty0 bis tty9 oder so(könnte ich mir vorstellen) Was der Rest, ist weiß ich leider auch nicht.
MFG
Michael Springwald

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von Mathias »

tty0 kann kaum eine Konsole sein, bei mir ist dies die Onboard-Schnittstelle.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von pluto »

MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von pluto »

Ich weiß der Beitrag ist alt, aber derzeit habe ich scheinbar mit der Funktion GetSerialPortNames ein kleines Problem:

In einem Projekt, welches im Hintergrund Laufen soll, Blockiert es scheinbar Funktionen aus der Unit Crt wie z.b. KeyPressed
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von pluto »

und wie versprochen: Hier die Test Anwendung. Bereits hier tritt das Problem auf.

Problem gefunden, Lösung noch nicht:

Code: Alles auswählen

fd := FpOpen('/dev/' + sl[i], O_RDWR Or O_NONBLOCK Or O_NOCTTY);


Edit1:
Falsche ZIP Datei hochgeladen, ich lade gleich die Richtige Hoch.

Edit2:
Das sollte jetzt aber die Richtige Datei sein.
Dateianhänge
TestApp.zip
(2.68 KiB) 152-mal heruntergeladen
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von pluto »

Ich habe mir jetzt folgendes überlegt:
Unter Linux konnte ich beobachten, dass die meisten Uart's wie von Arduino sich mit ttyUSB oder ttyACM melden.
Gibt es hier noch mehr Möglichkeiten?

Sonst ist es doch ganz einfach: Einfach nur diese "Dateien" suchen und in eine Stringliste Packen.
Spricht was dagegen?

Gut so weiß man natürlich nicht, ob diese Ports blockiert sind.

Ich denke, dass Problem mit fpOpen wird man nicht leicht lösen können.

Edit01
So in etwa meine ich das und das geht sehr gut...

Code: Alles auswählen

procedure GetSerialPortNames2(var PortListe:TStrings);
var
  sr:TSearchRec;
begin
  if FindFirst('/dev/tty*', LongInt($FFFFFFFF), sr) = 0 then
  begin
    repeat
      if (sr.Name <> '.') and (sr.Name <> '..') Then
        if (sr.Attr and LongInt($FFFFFFFF)) = Sr.Attr then begin
          if (pos('ttyUSB',sr.name) > 0) or (pos('ttyACM',sr.name) > 0) then
            PortListe.Add(sr.Name);
        end;
    until FindNext(sr) <> 0;
  end;
  FindClose(sr);
end;
 
var
  StringList:TStrings;
 
begin
  StringList:=TStringList.Create;
  GetSerialPortNames2(StringList);
  writeln(StringList.Text);
  repeat
    writeln('TEST1');
    sleep(1000);
  until KeyPressed;
  StringList.Free;


Edit2:
In der Datei /proc/tty/drivers steht auch noch einige drin:

Code: Alles auswählen

/dev/tty             /dev/tty        5       0 system:/dev/tty
/dev/console         /dev/console    5       1 system:console
/dev/ptmx            /dev/ptmx       5       2 system
/dev/vc/0            /dev/vc/0       4       0 system:vtmaster
acm                  /dev/ttyACM   166 0-31 serial
usbserial            /dev/ttyUSB   188 0-511 serial
rfcomm               /dev/rfcomm   216 0-255 serial
ttyprintk            /dev/ttyprintk   5       3 console
serial               /dev/ttyS       4 64-111 serial
pty_slave            /dev/pts      136 0-1048575 pty:slave
pty_master           /dev/ptm      128 0-1048575 pty:master
unknown              /dev/tty        4 1-63 console

Also sollte man auch noch nach rfcomm filtern, dann ist man auf der Sicheren seite.
MFG
Michael Springwald

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von Mathias »

Irgendwie muss es gehen.

Wen ich in der Arduino-Software gucke, da habe ich nur die Schnittstellen aufgelistet, welches es auch gibt.

Kann man evt. mit diesem Befehl etwas anfangen ?

Code: Alles auswählen

ll /sys/class/tty
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von pluto »

Schau dir mal meine Funktion(GetSerialPortNames2) an, die macht genau das im Prinzip was du mit deinem ls machst.
Nur wird die Ausgabe gefiltert.

Das klappt sehr gut und der Vorteil ist: Nicht jedes(naja fast) tty device wird geöffnet.
MFG
Michael Springwald

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Serielle Schnittstellen erkennen (Linux) [testen]

Beitrag von Mathias »

In der unit synaser vom Paket LazSerial, hat es auch eine Function, welche der Seriellen-Schnittstellen erkennen soll.

Nur leider erkennt die nicht alle Schnittstellen so zuverlässig wie die obige Function.

ZB., wird die ttyUSB0 nicht erkannt, obwohl sie hier auch aufgelistet wäre:

Code: Alles auswählen

    ScanForPorts( '/dev/rfcomm*');
 //   ScanForPorts( '/dev/pts/*');
    ScanForPorts( '/dev/ttyUSB*');
    ScanForPorts( '/dev/ttyS*');
    ScanForPorts( '/dev/ttyAM*'); // for ARM board 


Die Function ist ganz am ende der unit synaser.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Serielle Schnittstellen erkennen (Linux)

Beitrag von Mathias »

MmVisual hat geschrieben:Danke für den Tipp! Danach war es leicht das um zu setzen. :D :D

Kann die EXE "projekt1" bitte wer auf echten Linux Distris testen und hier Bescheid geben?
Alles im ZIP, EXE und Quellcode:
TestCOMPort_Linux.zip


Wenn das Klappt will ich das den Synaser-Leuten mitteilen, dass die diese Funktion dort rein nehmen. Denn das was dort drin ist funktioniert überhaupt nicht.

Hier der Code:

Code: Alles auswählen

uses BaseUnix;
function GetSerialPortNames: string;
type
TSerialStruct = packed record
  typ: Integer;
  line: Integer;
  port: Cardinal;
  irq: Integer;
  flags: Integer;
  xmit_fifo_size: Integer;
  custom_divisor: Integer;
  baud_base: Integer;
  close_delay: Word;
  io_type: Char;
  reserved_char: Char;
  hub6: Integer;
  closing_wait: Word; // time to wait before closing
  closing_wait2: Word; // no longer used...
  iomem_base: ^Char;
  iomem_reg_shift: Word;
  port_high: Cardinal;
  iomap_base: LongWord; // cookie passed into ioremap
end;
var
  i: Integer;
  sr : TSearchRec;
  sl: TStringList;
  st: stat;
  s: String;
  fd: PtrInt;
  Ser : TSerialStruct;
const TIOCGSERIAL = $541E;
  PORT_UNKNOWN = 0;
begin
  Result := '';
  sl := TStringList.Create;
  try
    // 1. Alle möglichen Ports finden
    if FindFirst('/sys/class/tty/*', LongInt($FFFFFFFF), sr) = 0 then
    begin
      repeat
        if (sr.Name <> '.') and (sr.Name <> '..') Then
          if (sr.Attr and LongInt($FFFFFFFF)) = Sr.Attr then
            sl.Add(sr.Name);
      until FindNext(sr) <> 0;
    end;
    FindClose(sr);
    // 2. heraussuchen ob ./device/driver vorhanden ist
    for i := sl.Count - 1 Downto 0 Do
    Begin
      If Not DirectoryExists('/sys/class/tty/' + sl[i] + '/device/driver') Then
        sl.Delete(i); // Nicht vorhanden >> Port existiert nicht
    end;
    // 3. Herausfinden welcher Treiber
    st.st_mode := 0;
    for i := sl.Count - 1 Downto 0 Do
    Begin
      IF fpLstat('/sys/class/tty/' + sl[i] + '/device', st) = 0 Then
      Begin
        if fpS_ISLNK(st.st_mode) Then
        Begin
          s := fpReadLink('/sys/class/tty/' + sl[i] + '/device/driver');
          s := ExtractFileName(s);
          // 4. Bei serial8250 Treiber muss der Port geprüft werden
          If s = 'serial8250' Then
          Begin
            sl.Objects[i] := TObject(PtrInt(1));
            fd := FpOpen('/dev/' + sl[i], O_RDWR Or O_NONBLOCK Or O_NOCTTY);
            If fd > 0 Then
            Begin
              If FpIOCtl(fd, TIOCGSERIAL, @Ser) = 0 Then
              Begin
                If Ser.typ = PORT_UNKNOWN Then // PORT_UNKNOWN
                  sl.Delete(i);
              end;
              FpClose(fd);
            end else sl.Delete(i); // Port kann nicht geöffnet werden
          end;
        End;
      end;
    end;
    // 5. Dev anhängen
    for i := 0 To sl.Count - 1 Do
      sl[i] := '/dev/' + sl[i];
   Result := sl.CommaText;
  finally
    sl.Free;
  end;
end;


Vielen Dank, Grüße Markus.

Ich weis, der Thread ist etwas alt, aber es scheint immer noch ein Problem zu sein.

Ich habe gerade festgestellt, das synaser.pas, egal ob in TLazSerial oder in Synapse immer noch ein fehlerhaftes GetSerialPortNames vorhanden ist.
Kann man irgendwie dem synaser.pas Autor miteilen, das es diese Funktion fertig gibt.
Es ist schade, hier im Forum wird vielfach synaser.pas verwendet, und da wäre es schön, wen die Unit richtig funtionieren würde. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten