[Lazarus] How to list available serial orts on Ubuuntu?

wkitty42 at windstream.net wkitty42 at windstream.net
Tue Nov 29 11:52:04 CET 2022


On 11/28/22 5:31 AM, Bo Berglund via lazarus wrote:
> I haved a debugging tool program created on Windows and I am orting it to Linux
> Ubuntu.
> It seems to build just fine except for a combobox fill function which uses the
> Windows way of populating the selectoer box with the serial ports available on
> the system.
> This is the code I use on Windows:
[...]
> I have looked at /dev/tty* but it lists a large number of items which makes it
> impossible for me. I do not belive all of´them are real serial ports...
> 
> What can I do to get a selector for real serial ports on Ubuntu.


would you believe you asked almost this very same question back in 2015, 2018, 
2020, and here again in 2022 :)


in Sep 2018, giuliano colla posted this procedure to you:

procedure TForm1.btnScanPortClick(Sender: TObject);
var
  PortNr: Integer;
  PortName: String;
  PortHandle: TSerialHandle;
begin
   cbSelPort.Items.Clear;
   cbSelPort.Text:= '';
{$IFDEF MSWINDOWS}
   for PortNr := 1 to 9 do begin
     PortName := 'COM' + IntToStr(PortNr);
     PortHandle := SerOpen('\\.\'+PortName);
     if PortHandle > 0 then begin
       cbSelPort.Items.Add(PortName);
       SerClose(PortHandle);
       if cbSelPort.Text = '' then begin
         cbSelPort.Text:=PortName;
         PortSel.Caption:= PortName;
         end;
       end;
     end;
{$ELSE}
   for PortNr := 0 to 9 do begin
     PortName := '/dev/ttyS' + IntToStr(PortNr);
     PortHandle := SerOpen(PortName);
     if PortHandle > 0 then begin
       if cbSelPort.Text = '' then begin
         cbSelPort.Text:=PortName;
         PortSel.Caption:= PortName;
         end;
       cbSelPort.Items.Add(PortName);
       SerClose(PortHandle);
       end;
     end;
   for PortNr := 0 to 9 do begin
     PortName := '/dev/ttyUSB' + IntToStr(PortNr);
     PortHandle := SerOpen(PortName);
     if PortHandle > 0 then begin
       if cbSelPort.Text = '' then begin
         cbSelPort.Text:=PortName;
         PortSel.Caption:= PortName;
         end;
       cbSelPort.Items.Add(PortName);
       SerClose(PortHandle);
       end;
     end;
{$ENDIF}
end;


and in that same thread in Sep 2018, mark morgan lloyd posted this function to you:

(* If there are no serial ports on the system then return NIL, otherwise a      *)
(* TStringList.        *)
(*        *)
(* This returns an object, it is the caller's (eventual) responsibility to free *)
(* this.        *)
//
FUNCTION EnumeratePorts: TStringList;

(* On a Linux system with udev or similar the /dev directory will only contain  *)
(* devices which have been detected as being present. On an older system it     *)
(* will probably contain all possible devices so we need to restrict the list   *)
(* to what's reasonable; the user should still be able to enter a device name   *)
(* manually if necessary, e.g. where a machine with 2x standard ports plus a    *)
(* 2-port card insists that it's got ttyS0, ttyS1, ttyS45 and ttyS46.        *)

CONST   countTtyS= 12;                  (* Main board plus an 8-port card       *)
         countTtyUSB= 8;                 (* Four dual-port adapters         *)
         countTtyI= 4;                   (* A single 4-port ISDN card.         *)

VAR     searchRec: TSearchRec;
         counter: INTEGER;

BEGIN
   RESULT:= TStringList.Create;
   RESULT.Sorted:= TRUE;
   counter:= countTtyS;
   IF FindFirst('/dev/ttyS*', faSysFile, searchRec) = 0 THEN
     REPEAT
       RESULT.Append('/dev/' + searchRec.Name);
       DEC(counter)
     UNTIL (FindNext(searchRec) <> 0) OR (counter <= 0);
   FindClose(searchRec);
   counter:= countTtyUSB;
   IF FindFirst('/dev/ttyUSB*', faSysFile, searchRec) = 0 THEN
     REPEAT
       RESULT.Append('/dev/' + searchRec.Name);
       DEC(counter)
     UNTIL (FindNext(searchRec) <> 0) OR (counter <= 0);
   FindClose(searchRec);
   counter:= countTtyI;
   IF FindFirst('/dev/ttyI*', faSysFile, searchRec) = 0 THEN
     REPEAT
       RESULT.Append('/dev/' + searchRec.Name);
       DEC(counter)
     UNTIL (FindNext(searchRec) <> 0) OR (counter <= 0);
   FindClose(searchRec);
   IF Result.Count = 0 THEN
     FreeAndNil(RESULT)
END { EnumeratePorts } ;


in another thread back in Oct 2020, corpsman at web.de posted this function to you:

Function GetSerialPortNames(): String;
Var
   sl: TStringlist;
Var
   Info: TSearchRec;
   hdl: THandle;
   b: Boolean;
Begin
   sl := TStringlist.create;
   If FindFirst('/dev/tty*', faSysFile, Info) = 0 Then Begin
     Repeat
       b := true;
       Try
         hdl := FileOpen('/dev/' + info.Name, fmOpenReadWrite);
         If hdl = -1 Then Begin
           b := false;
         End;
       Except
         b := false;
       End;
       If hdl >= 0 Then Begin
         FileClose(hdl);
       End;
       If b Then Begin
         sl.Add('/dev/' + info.Name);
       End;
     Until FindNext(info) <> 0;
   End;
   FindClose(Info);
   result := sl.CommaText;
   sl.free;
End;


i love having mailing list history in my email reader! :) :) :)


-- 
  NOTE: No off-list assistance is given without prior approval.
        *Please keep mailing list traffic on the list where it belongs!*


More information about the lazarus mailing list