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]