Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2018-09

Usage of Serial in a testing program?

18 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bo Berglund

I am writing a testing application for checking out a TCP to Serial bridge component. I am using Lazarus 1.8.0 and fpc 3.0.4 on Windows 7

For the serial port handling I found the "built-in" Serial unit described here:
http://wiki.freepascal.org/Hardware_Access#FPC_built_in_Serial_unit

Now I have a few questions about its usage:

1) Serial port name
-------------------
When opening the port the example does this:

str(ComPortNr,tmpstr);
ComPortName:= 'COM'+tmpstr+':';
serialhandle := SerOpen(ComPortName);

So for say port 29 this results in ComPortName 'COM29:' Is this always the case? I have a hunch that for port numbers 1..9 the Windows port naming is different than for higher port numbers...

And if I want to port this to Linux, I guess thta the name is completely different, but no hint is given.

2) Blocking send?
------------------
Is this port blocking for sending?

The example has this:

status := SerWrite(serialhandle, s[1], writecount );

where s is a string holding the text to send (I will actually need to use a TBytes array instead) and writecount returns the bytes actually sent.

If I want to send an array of say 100 kbytes at 9600 baud, will the call return only when the data have been completely sent or earlier? It will take about 100 seconds to send that array...

3) Receiving data
----------------
For data reception I see this:

s:='';
ComIn:='';
while (Length(Comin)<10) and (status>=0) and not keypressed do
begin
   status:= SerRead(serialhandle, s[1], 10);
   ...

Since the call parameters are the receive buffer and the count to read I do not understand how this can work. s has been emptied (length = 0) just before the call so how can SerRead stuff any data into the buffer starting at s[1], which should not even exist???

I would like to have a way to read incoming data asynchronously so I also could handle the user feedback and the TCP connection which is sending the data that ultimately will arrive on the serial line...

Any suggestions on how to do this?

Bo Berglund Developer in Sweden

Reply by email

Bo Berglund
to Bo Berglund
Bo Berglund wrote
3) Receiving data ----------------

I forgot to add a question about read timeouts...

4) Read timeout
---------------
When running this to read incoming data:

status:= SerRead(serialhandle, s[1], 10);

How can I get out of the call if there never arrives 10 bytes? Is there a timeout somewhere so that I can set it to some small value and put the SerRead into a thread that can check arriving data and if found fire off an event or such?

Bo Berglund Developer in Sweden

Reply by email

Bo Berglund
to Bo Berglund
Bo Berglund wrote 17 lines
On Sun, 09 Sep 2018 13:33:22 +0200, Bo Berglund via Lazarus wrote: >3) Receiving data >---------------- I forgot to add a question about read timeouts... 4) Read timeout --------------- When running this to read incoming data: status:= SerRead(serialhandle, s[1], 10); How can I get out of the call if there never arrives 10 bytes? Is there a timeout somewhere so that I can set it to some small value and put the SerRead into a thread that can check arriving data and if found fire off an event or such?

Ok, I went to the sources and found this:

interface
...
{ Reads a maximum of "Count" bytes of data into the specified buffer.
  Result: Number of bytes read. }
function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt):
LongInt;
implementation
...
function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt):
LongInt;
var
  BytesRead: DWORD;
  Timeouts: TCommTimeouts;
begin
  if GetCommTimeouts(Handle, Timeouts) then
  begin
    Timeouts.ReadIntervalTimeout := MAXDWORD;
    Timeouts.ReadTotalTimeoutConstant := 0;
    SetCommTimeouts(Handle, Timeouts)
  end;
  if not ReadFile(Handle, Buffer, Count, BytesRead, nil) then
    result := 0
  else
    result := BytesRead
end { SerRead } ;

So SerRead seems to read *up to* Count bytes, but does it do this by checking what is currently stored in the operating system inbound buffer or does it try to wait until Count bytes are available?

If so how is the timeout that is needed in such a case changed? Seems to be set at infinity in the SerRead function (MAXDWORD).... Or is it ReadTotalTimeoutConstant that is used during read?

If you drill further down you will get into ReadFile, but that is a call into Windows API...

Bo Berglund Developer in Sweden

Reply by email

Mark Morgan Lloyd
to Bo Berglund: I am writing a testing application for checking out a TCP to Serial bridge component. I…
Bo Berglund wrote 7 lines
I am writing a testing application for checking out a TCP to Serialbridge component. I am using Lazarus 1.8.0 and fpc 3.0.4 on Windows 7 For the serial port handling I found the "built-in" Serial unitdescribed here:http://wiki.freepascal.org/Hardware_Access#FPC_built_in_Serial_unit Now I have a few questions about its usage: 1) Serial port name-------------------When opening the port the example does this: str(ComPortNr,tmpstr);ComPortName:= 'COM'+tmpstr+':';serialhandle := SerOpen(ComPortName); So for say port 29 this results in ComPortName 'COM29:'Is this always the case? I have a hunch that for port numbers 1..9 theWindows port naming is different than for higher port numbers... And if I want to port this to Linux, I guess thta the name iscompletely different, but no hint is given.

I did quite lot of work on the serial.pp unit more recently than that wiki page, in fact I didn't even know it existed. Please refer to the comments in that file in the first instance.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Bo Berglund
to Mark Morgan Lloyd: I did quite lot of work on the serial.pp unit more recently than that wiki page, in fact…
Mark Morgan Lloyd wrote
I did quite lot of work on the serial.pp unit more recently than that wiki page, in fact I didn't even know it existed. Please refer to the comments in that file in the first instance.

Thanks Mark,
I did that too and there is stuff I don't find there, like:

Read blocking?
----------------------

From interface section:
{ Reads a maximum of "Count" bytes of data into the specified buffer.
  Result: Number of bytes read. }
function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt):
LongInt;

Does this function read whatever is in the buffer when called up to a maximum of Count, or does it actually wait until Count bytes have arrived? If it waits, for how long?

Concerning the com port name for SerOpen():

{ Open the serial device with the given device name, for example: \COM1, \COM2 (strictly, \\.\COM1...) for normal serial ports. ISDN devices, serial port redirectors/virtualisers etc. normally implement names of this form, but refer to your OS documentation. Returns "0" if device could not be found }
function SerOpen(const DeviceName: String): TSerialHandle;

In the Wiki example they use COMx: where x is a number, but this is probably only working for single digit numbers 1..9. In any case the naming there is not described in serial.pp

I need to huse a high numbered com port since all I have is USB2Serial dongles, which typically get you a port number like 29...

Bo Berglund Developer in Sweden

Reply by email

Sven Barth
to Bo Berglund

Bo Berglund via Lazarus schrieb am Mo., 10.
Sep. 2018, 15:19:

Show quoted text 16 lines
Concerning the com port name for SerOpen(): { Open the serial device with the given device name, for example: \COM1, \COM2 (strictly, \\.\COM1...) for normal serial ports. ISDN devices, serial port redirectors/virtualisers etc. normally implement names of this form, but refer to your OS documentation. Returns "0" if device could not be found } function SerOpen(const DeviceName: String): TSerialHandle; In the Wiki example they use COMx: where x is a number, but this is probably only working for single digit numbers 1..9. In any case the naming there is not described in serial.pp I need to huse a high numbered com port since all I have is USB2Serial dongles, which typically get you a port number like 29...

Did you test it? Cause the serial unit only passes on the name to the platform's API. So \COM29 should work for a Com port with number 29.

Regards,
Sven

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20180910/e537caa9/attachment.html>

Reply by email

Mark Morgan Lloyd
to Bo Berglund: On Sun, 9 Sep 2018 20:44:34 +0000, Mark Morgan Lloyd via Lazarus I did that too and there…
Bo Berglund wrote 6 lines
On Sun, 9 Sep 2018 20:44:34 +0000, Mark Morgan Lloyd via Lazarus wrote: > I did quite lot of work on the serial.pp unit more recently than that >wiki page, in fact I didn't even know it existed. Please refer to the >comments in that file in the first instance. Thanks Mark,I did that too and there is stuff I don't find there, like: Read blocking?----------------------From interface section: { Reads a maximum of "Count" bytes of data into the specified buffer. Result: Number of bytes read. }function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt):LongInt; Does this function read whatever is in the buffer when called up to amaximum of Count, or does it actually wait until Count bytes havearrived? If it waits, for how long?

From further down:

function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt):
LongInt;
begin
   Result := fpRead(Handle, Buffer, Count);
end;

where the documentation for fpread() says

"FpdRead reads at most nbytes bytes from the file descriptor fd, and stores them in buf.

"The function returns the number of bytes actually read"

So this is a unix-style read that is prepared to read Count bytes, but returns the number actually available.

If you want timeouts then see SerReadTimeout(). I'd expect the Windows variants to behave the same (I tested Linux, Solaris and I think W2K, so there's a risk that newer versions behave differently). /If/ you find anomalies, please raise a bug report with the caveat that I have rather a lot of problems on my plate right now.

Concerning the com port name for SerOpen(): { Open the serial device with the given device name, for example: \COM1, \COM2 (strictly, \\.\COM1...) for normal serial ports. ISDN devices, serial port redirectors/virtualisers etc. normally implement names of this form, but refer to your OS documentation. Returns "0" if device could not be found }function SerOpen(const DeviceName: String): TSerialHandle;

On Linux that is, again, a very thin wrapper around the RTL fpOpen() function, on Windows it's a wrapper around CreateFile(). I really can't say the extent that I tested that with odder devices and high port numbers (I think I took SerOpen() etc. pretty much as supplied by the original author), but from other serial libraries on Delphi my recollection is that that leading \\.\ is mandatory for higher-numbered ports... I /think/ I got up to 12 ports but that really was a very long time ago.

Note that C/C++ examples relating to that sort of thing will usually refer to \\\\.\\ because of the special significance of \ in strings.

In the Wiki example they use COMx: where x is a number, but this isprobably only working for single digit numbers 1..9.In any case the naming there is not described in serial.pp I need to huse a high numbered com port since all I have is USB2Serialdongles, which typically get you a port number like 29...

I can't comment on Windows there but on Linux they typically get called something like /dev/USB0 etc., with a risk that the numeric suffix will increment if it's replugged. I've used that library fairly heavily on Linux for instrumentation type stuff, it works fairly well with USB devices except that their timing can get flaky if you're trying to get the exact time at which e.g. CTS changes state relative to a stream of characters faster than about 300 Baud.

When I was working on it the major thing I did was reorganise some of the flush/drain/sync stuff which was generally felt to be in a mess, add a bit more in the way of control signal interfacing, and add SerReadTimeout()... note the provision for an idle callback.

HTH.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Bo Berglund
to Giuliano Colla: An HTML attachment was scrubbed... URL: <http://lists.lazarus-ide.org/pipermail/lazarus/at…
Giuliano Colla wrote 31 lines
Il 09/09/2018 13:33, Bo Berglund via Lazarus ha scritto:<br> >I am writing a testing application for checking out a TCP to Serial >bridge component. I am using Lazarus 1.8.0 and fpc 3.0.4 on Windows 7 > >For the serial port handling I found the "built-in" Serial unit >described here: >http://wiki.freepascal.org/Hardware_Access#FPC_built_in_Serial_unit > >Now I have a few questions about its usage: > >1) Serial port name >------------------- >When opening the port the example does this: > >str(ComPortNr,tmpstr); >ComPortName:= 'COM'+tmpstr+':'; >serialhandle := SerOpen(ComPortName); > >So for say port 29 this results in ComPortName 'COM29:' >Is this always the case? I have a hunch that for port numbers 1..9 the >Windows port naming is different than for higher port numbers... > >And if I want to port this to Linux, I guess that the name is >completely different, but no hint is given. Here is the procedure I'm using to fill up a combo box with the names of the existing serial devices on the platform. Please note the different naming conventions in Linux and Windows. Also note that to report a serial port as existing a test is made to open it (using the fpc serial function), and avoid "phantom" ports.

But does not this listing fail if a port is already in use, i.e. the SerOpen() call will return 0 indicating it is not found?

Show quoted text 48 lines
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); //<= Fail if already open? if PortHandle &gt; 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 &gt; 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 &gt; 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;

This seems only to deal with ports 1..9, what about the higher numbered ports 10..255?
And would it not be a long execution time for testing all 255 possible com ports on Windows?

Show quoted text 15 lines
>2) Blocking send? >------------------ >Is this port blocking for sending? > >The example has this: > >status := SerWrite(serialhandle, s[1], writecount ); > >where s is a string holding the text to send (I will actually need to >use a TBytes array instead) and writecount returns the bytes actually >sent. > >If I want to send an array of say 100 kbytes at 9600 baud, will the >call return only when the data have been completely sent or earlier? >It will take about 100 seconds to send that array...
Yes, SerWrite is blocking.

Does this mean that it is actually waiting for the data to be physically sent out on the wire or until the operating system transmit buffer has absorbed all of the data?
If the latter then a possibility to resize the transmit buffer would help. But how?

Show quoted text 9 lines
I hope you don't plan to send 100 kbytes in a single write on a serial line. The probability of an error in between is near to 100%!<br> What I'm doing in such cases is to create a dedicated thread to handle send and receive, without blocking the main thread, which remains responsive, and split the send in many small blocks (and getting some sort of ACK/NAK from remote receiver), which makes it possible to show a progress bar or whatever visual feedback you like.

Unfortunately not possible in the real case because the file transfer protocol of the device only sends a header with the count of the data to follow and then streams all of the bytes....

Show quoted text 27 lines
>3) Receiving data >---------------- >For data reception I see this: > >s:=''; >ComIn:=''; >while (Length(Comin)&lt;10) and (status&gt;=0) and not keypressed do >begin > status:= SerRead(serialhandle, s[1], 10); > ... > >Since the call parameters are the receive buffer and the count to read >I do not understand how this can work. s has been emptied (length = 0) >just before the call so how can SerRead stuff any data into the buffer >starting at s[1], which should not even exist??? > >I would like to have a way to read incoming data asynchronously so I >also could handle the user feedback and the TCP connection which is >sending the data that ultimately will arrive on the serial line... > >Any suggestions on how to do this? I never use SerRead, but rather SerReadTimeout (from the same unit) which gives a much better control of what is going on. Of course in that case your receiving buffer must be large enough to accommodate the largest block you expect. (This replies also to your further questions).

Did not see this before, but it seems like a good choice for reading data in a loop until the return is less than Count, which means that the timeout has caused the exit.
Thanks for the suggestion!

I hope that it helps.

Yes it does, but it would have been even better if not full of HTML tags and stuff. I have edited out most but I guess there are some still left...
For example inside the code there may be some things like &gt; rather than >

Bo Berglund Developer in Sweden

Reply by email

Giuliano Colla
to Bo Berglund

Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto:

This seems only to deal with ports 1..9, what about the higher numbered ports 10..255? And would it not be a long execution time for testing all 255 possible com ports on Windows?

In my experience both Linux and Windows if you connect a new serial device do set a port number just higher than the previous one already there. This means that you'll have to deal with higher numbers only if you have more than 9 serial lines in your platform, which is a bit unlikely. Not to consider the likelihood of a platform with 200 serial lines!

Do not do to others as you would have them do to you.They might have different tastes.

Reply by email

Giuliano Colla
to Bo Berglund: On Mon, 10 Sep 2018 13:20:35 +0200, Giuliano Colla via Lazarus But does not this listing…

Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto:

Unfortunately not possible in the real case because the file transfer protocol of the device only sends a header with the count of the data to follow and then streams all of the bytes....

I don't know how your application is built, but if the origin is an ftp transfer, then data are sent in small packets. It would appear that you somehow get the ftp data and send them to a serial line. It is at that point of the processs that you should create your records to send them individually via the serial line.

Do not do to others as you would have them do to you.They might have different tastes.

Reply by email

Giuliano Colla
to Bo Berglund: On Mon, 10 Sep 2018 13:20:35 +0200, Giuliano Colla via Lazarus But does not this listing…

Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto:

Show quoted text 6 lines
> I hope that it helps. Yes it does, but it would have been even better if not full of HTML tags and stuff. I have edited out most but I guess there are some still left... For example inside the code there may be some things like &gt; rather than >

Sorry, I forced HTML for better readability.
But you may easily extract the clean text (without &gt and such) by creating an empty html file (whatever.html), and opening it with LibreOffice or OpenOffice. Then you may copy and paste into it the text from the e-mail, and finally save it as a pure text fle (whatever.txt). It is much faster and safer than manual editing.

Giuliano

Do not do to others as you would have them do to you.They might have different tastes. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20180910/e5c87b3a/attachment.html>

Reply by email

Bo Berglund
to Giuliano Colla: Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto: In my experience both Linux and…
Giuliano Colla wrote 8 lines
Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto: > This seems only to deal with ports 1..9, what about the higher > numbered ports 10..255? > And would it not be a long execution time for testing all 255 possible > com ports on Windows? In my experience both Linux and Windows if you connect a new serial device do set a port number just higher than the previous one already there.

On Windows7 at least every time you attach a serial2usb dongle into a different USB port than before it creates a new COM port with a higher number. And this port is sticky on the PC too, it remains "taken". So after a few years (my laptop is from 2011) it stacks up and even though I have currently only attached 6 such converters (one is a 4-way) the com port numbers are 29-30-31-32-33-34...

This means that you'll have to deal with higher numbers only if you have more than 9 serial lines in your platform, which is a bit unlikely. Not to consider the likelihood of a platform with 200 serial lines!

I would eventually get there if I continue to unplug and re-plug these dongles...

Bo Berglund Developer in Sweden

Reply by email

Bo Berglund
to Giuliano Colla: Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto: I don't know how your…
Giuliano Colla wrote 11 lines
Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto: > Unfortunately not possible in the real case because the file transfer > protocol of the device only sends a header with the count of the data > to follow and then streams all of the bytes.... I don't know how your application is built, but if the origin is an ftp transfer, then data are sent in small packets. It would appear that you somehow get the ftp data and send them to a serial line. It is at that point of the processs that you should create your records to send them individually via the serial line.

No FTP!
What I meant is that the device I want to communicate with has a proprietary serial protocol and it can do file transfers too. The protocol is delimited and checksummed, but when a file is transferred there is only one block of file data in the middle of the transfer and it could be up to 1 Mbytes (the memory limit of the device).

My application is meant to test WiFi<=>Serial converters to evaluate those we could use with the data device. So I want to run data through the unit under test in both direction to verify that it is going to work in the real environment. In real use the data device is connected by RS232 wire to the Serial to WiFi converter and a device controller is hooked in via a TCP socket server on the converter.

The test application implements both endpoints since it aims to check out the converter itself.

So I am dealing with one enpoint as a TCP socket (using Indy here) and the other is the serial line where I am trying to use the Serial.pp unit since it is built-in.
Once it is set up I will push a lot of data through and look at the performance.

But now I will be off travelling for a week...

Bo Berglund Developer in Sweden

Reply by email

Bo Berglund
to Bo Berglund: I am writing a testing application for checking out a TCP to Serial bridge component. I…

On Sun, 09 Sep 2018 13:33:22 +0200, Bo Berglund via Lazarus wrote:

Coming back to this issue after I have been travelling...

Show quoted text 17 lines
For the serial port handling I found the "built-in" Serial unit described here: http://wiki.freepascal.org/Hardware_Access#FPC_built_in_Serial_unit Now I have a few questions about its usage: 1) Serial port name ------------------- When opening the port the example does this: str(ComPortNr,tmpstr); ComPortName:= 'COM'+tmpstr+':'; serialhandle := SerOpen(ComPortName); So for say port 29 this results in ComPortName 'COM29:' Is this always the case? I have a hunch that for port numbers 1..9 the Windows port naming is different than for higher port numbers...

I have now come as far in my application as I can test the way the Serial unit opens and closes com ports.
It turns out that on Windows there are two port name syntaxes:

Ports 1..9: COM1 to COM9 will work
Ports 10..255: Only \\.\COM10 to \\.\COM255 will work

But one does not need to use different naming depending on the port number, the second syntax \\.\COMx works also for ports 1..9

Notice that contrary to the wiki example adding a colon to the end like COM32: does NOT work so that is a wiki error.

I have yet to complete other parts of the application so I don't yet know if the data flow will wok as expected.

Bo Berglund Developer in Sweden

Reply by email

Paul Breneman
to Bo Berglund

On 09/23/2018 02:39 AM, Bo Berglund via Lazarus wrote: ...

Notice that contrary to the wiki example adding a colon to the end like COM32: does NOT work so that is a wiki error.

If I remember correctly the colon at the end is required for WinCE?

Reply by email

Bo Berglund
to Bo Berglund: On Sun, 09 Sep 2018 13:33:22 +0200, Bo Berglund via Lazarus Coming back to this issue…
Bo Berglund wrote 9 lines
I have now come as far in my application as I can test the way the Serial unit opens and closes com ports. It turns out that on Windows there are two port name syntaxes: Ports 1..9: COM1 to COM9 will work Ports 10..255: Only \\.\COM10 to \\.\COM255 will work But one does not need to use different naming depending on the port number, the second syntax \\.\COMx works also for ports 1..9

Forgot to add a question regarding making this a cross-platform program:

If I add a check for the platform inside my program, how sghould it look like to work on both Windows and Linux?

Something like this:

function TWiFiCommTester.ConnectSerial(Port: byte; Baud: integer):
boolean;
var
  ComportName: string;
  Flags: TSerialFlags;
begin
  FLastError := '';
  {$IFDEF WINDOWS}
  ComPortName:= '\\.\COM' + IntToStr(Port);
  {$ENDIF}
  {$IFDEF UNIX}
     //What goes here?
     ComPortName := ????
  {$ENDIF}
  FSerial := SerOpen(ComPortName);
  ....
Bo Berglund Developer in Sweden

Reply by email

Mark Morgan Lloyd
to Bo Berglund
Bo Berglund wrote 6 lines
On Sun, 23 Sep 2018 08:39:52 +0200, Bo Berglund via Lazarus wrote: > I have now come as far in my application as I can test the way the>Serial unit opens and closes com ports.>It turns out that on Windows there are two port name syntaxes:>>Ports 1..9: COM1 to COM9 will work>Ports 10..255: Only \\.\COM10 to \\.\COM255 will work>>But one does not need to use different naming depending on the port>number, the second syntax \\.\COMx works also for ports 1..9 Forgot to add a question regarding making this a cross-platformprogram: If I add a check for the platform inside my program, how sghould itlook like to work on both Windows and Linux? Something like this: function TWiFiCommTester.ConnectSerial(Port: byte; Baud: integer):boolean;var ComportName: string; Flags: TSerialFlags;begin FLastError := ''; {$IFDEF WINDOWS} ComPortName:= '\\.\COM' + IntToStr(Port); {$ENDIF} {$IFDEF UNIX} //What goes here? ComPortName := ???? {$ENDIF} FSerial := SerOpen(ComPortName); ....

Sorry Bo and Paul, I mailed you directly when I meant to reply here. This rolls up the messages from earlier.

Ports 1..9: COM1 to COM9 will workPorts 10..255: Only \\.\COM10

to \\.\COM255 will work

Which is something that I pointed out to you, although in my case I think I only tested up to 12 (i.e. with an 8-port card).

What comes after 255: 0 or 1? If 0 which form or name does it require?

I have yet to complete other parts of the application so I don't

yetknow if the data flow will wok as expected.

Note that that unit was specifically written to be usable either with or without separate communications threads. If you're /not/ using threads then there's a callback so that the read-with-timeout functions can periodically call Application.ProcessMessages, and that the places that it is used are OS-specific. You obviously /don't/ want to use that callback if the comms functions are in their own threads, since APM should only be called from the main thread.

I'm probably losing this email address on Tuesday, if there's anything that you think I can possibly clarify please raise it sooner rather than later.

On 09/23/2018 02:39 AM, Bo Berglund via Lazarus wrote:...> Notice

that contrary to the wiki example adding a colon to the end> like COM32: does NOT work so that is a wiki error.

If I remember correctly the colon at the end is required for WinCE?--

OK, but this is something that the application programmer needs to be aware of. I suppose it would be possible to modify the unit so that if it sees a trailing : it changes it to a leading \\.\ if there isn't one there already, but since the exact names are OS-specific and since we're already insisting that the application programmer or user puts in /dev/ for unix I'm not sure that's justifiable.

In any event I'm not in a position to do any mods right now and am probably about to lose access to Solaris (which is probably still worth testing against) permanently.

(* 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 } ;
Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email