On Mon, 31 Aug 2020, Bo Berglund via fpc-pascal wrote:

On Fri, 21 Aug 2020 21:03:31 +0200, Bo Berglund via fpc-pascal
<fpc-pascal@lists.freepascal.org> wrote:

Instead I need to add a thread for reading data so I can have an event
driven reception of data. It would read available data and fire off a
NotifyEvent to handle the incoming data in the main application.

I have now started to implement a simple "fpserialport" class using
the built-in serial unit and I am trying to add a reading thread so I
can get an OnRxData event which is needed by many of the non-GUI
applications I want to port to Fpc/Lazarus.

It can be a simple TNotifyEvent where the user will implement the
actual read or else a specific event procedure providing a TBytes
container with the data. Both are possible.

But when doing this I have run into a problem, how can I check how
many Rx bytes are available to be read from the operating system?

There is some ioctl() function for that, but using that is not recommended.

The normal way of doing is is reading a buffer till no more data is read and then treat the buffer


If I simply use the SerReadTimeout() function it will return either
with 1 or more bytes or after the timeout. But there is a problem
here:

function SerReadTimeout(Handle: TSerialHandle; var Buffer; mSec:
LongInt): LongInt;

When calling this the Buffer length has to be set *beforehand* so the
arriving data can fit inside the buffer, but how can I know how big
Buffer must be?

Serial normally does not handle buffers >4k.

I assume that if the Buffer is too small there will be an exception or
else an overwrite of following memory?

Yes.


The other variant of the read:

function SerReadTimeout(Handle: TSerialHandle; var Buffer: array of
byte; count, mSec: LongInt): LongInt;

Here there is a count argument that will limit the amount of data read
into the buffer, but from the code in serial.pp it seems like the
function can in fact read more data into the buffer than count. The
break condition is:

 while fpSelect(Handle + 1, @readSet, nil, nil, @selectTimeout) > 0
do begin
   Inc(result,fpRead(Handle, Buffer[result], count - result));
   if result >= count then // <== HERE possible overflow
     break;
   if Assigned(SerialIdle) then
     SerialIdle(Handle)
 end

That seems correct. since fpRead will never read more than Count bytes
(count-result is always less than count for positive result) result can at
most be Count.

(if fpRead returns a negative result, the algorithm is simply wrong, the
algorithm assumes the fpRead will always succeed)

Disregarding the error condition you can perfectly use this function.

Michael.
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to