Reputation: 67
D5-pro: Using TurboPower APro and the ComPort and Terminal Components with USB Arduino Nano for a very basic Comms-Terminal. All works fine until I unplug the USB to simulate losing the Port. It all just hangs and will not restart without closing and restarting.
I cannot find an Event or process that is monitoring the Port status so I can gracefully shut the Port. I am able to prevent the Port being opened if it doesn't exist, but once opened and data streaming in, I seem to lose all access to it.
I also tried TComPort and Terminal by Dejan Crnila and it also does not stop gracefully either. It actually crashes and I have to use TaskManager to shut it all down.
Can someone please guide me with some code snippets that might give an indication that the port has gone missing. Or is there a better free Component for doing this.
Upvotes: 0
Views: 396
Reputation: 390
Some modifications in the AwUser unit are required.
Add a new event for I/O errors.
TPortIOErrorEvent = procedure(CP : TObject; Error : Cardinal) of object; property OnPortIOError: TPortIOErrorEvent read FOnPortIOError write FOnPortIOError;
Modify the TComThread.Execute method in the AwUser unit.
{Release time slice until we get a communications event}
if not WaitComEvent(CurrentEvent, @ComOL) then begin
if GetLastError = ERROR_IO_PENDING then begin
if GetOverLappedResult(CidEx,
ComOL,
Junk,
True) then begin
{WIN32 bug workaround: Apro gets the modem status bits
with a call (later) to GetCommModemStatus. Unfortunately,
that routine never seems to return either RI or TERI.
So, we note either EV_RING or EV_RINGTE here and later
manually merge the TERI bit into ModemStatus.}
if ((CurrentEvent and EV_RINGTE) <> 0) or
((CurrentEvent and EV_RING) <> 0) then
RingFlag := True;
{Read complete, reset event}
ResetEvent(ComOL.hEvent);
end else begin
{Port closed or other fatal condition, just exit the thread}
SetEvent(GeneralEvent);
CloseHandle(ComOL.hEvent);
H.ThreadGone(Self);
Exit;
end;
end else begin
Err := GetLastError; {!!! added code}
{ If we get an ERROR_INVALID_PARAMETER, we assume it's our }
{ use of ev_RingTe -- clear the flag and try again }
if (GetLastError = ERROR_INVALID_PARAMETER) and
(LastMask and EV_RINGTE <> 0) then begin
LastMask := DefEventMask and not EV_RINGTE;
SetCommMask(CidEx, LastMask);
end;
{!!! added code begin}
if (Err <> ERROR_INVALID_PARAMETER) and (Err>0) and Assigned(FOnPortIOError) then
FOnPortIOError(H.fOwner, Err)
{!!! added code end}
end;
end;
Add the similar code to "ProcessOutputEvent".
Upvotes: 0