MODULE CommV24;
(**
project = "BlackBox"
organization = "www.oberon.ch"
contributors = "Oberon microsystems"
version = "System/Rsrc/About"
copyright = "System/Rsrc/About"
license = "Docu/BB-License"
changes = ""
issues = ""
**)
IMPORT SYSTEM, WinApi;
CONST
bits4* = 0; bits5* = 1; bits6* = 2; bits7* = 3; stop15* = 4; stop2* = 5; even* = 6; odd* = 7;
inXonXoff* = 8; outXonXoff* = 9; inRTS* = 10; inDTR* = 11; outCTS* = 12; outDSR* = 13;
TYPE
Connection* = POINTER TO LIMITED RECORD
hnd: WinApi.HANDLE; (* # 0: open *)
opts: SET
END;
PROCEDURE Open* (device: ARRAY OF CHAR; baud: INTEGER; opts: SET; OUT conn: Connection);
VAR c: Connection; h: WinApi.HANDLE; res: INTEGER; dcb: WinApi.DCB; to: WinApi.COMMTIMEOUTS;
BEGIN
h := WinApi.CreateFileW(
device,WinApi.GENERIC_READ +WinApi.GENERIC_WRITE, {}, NIL,WinApi.OPEN_EXISTING, {}, 0);
IF h # -1 THEN
dcb.DCBlength := SIZE(WinApi.DCB);
res := WinApi.GetCommState(h, dcb);
IF res # 0 THEN
dcb.BaudRate := baud;
dcb.fBits0 := {0}; (* binary *)
IF opts * {even, odd} # {} THEN INCL(dcb.fBits0, 1) END; (* check parity *)
IF outCTS IN opts THEN INCL(dcb.fBits0, 2) END; (* CTS out flow control *)
IF outDSR IN opts THEN INCL(dcb.fBits0, 3) END; (* DSR out flow control *)
IF inDTR IN opts THEN INCL(dcb.fBits0, 5) END; (* DTR flow control handshake *)
IF outXonXoff IN opts THEN INCL(dcb.fBits0, 8) END; (* Xon/Xoff out flow control *)
IF inXonXoff IN opts THEN INCL(dcb.fBits0, 9) END; (* Xob/Xoff in flow control *)
IF inRTS IN opts THEN INCL(dcb.fBits0, 13) END; (* RTS flow control handshake *)
IF bits4 IN opts THEN dcb.ByteSize := 4X
ELSIF bits5 IN opts THEN dcb.ByteSize := 5X
ELSIF bits6 IN opts THEN dcb.ByteSize := 6X
ELSIF bits7 IN opts THEN dcb.ByteSize := 7X
ELSE dcb.ByteSize := 8X
END;
IF stop15 IN opts THEN dcb.StopBits := 1X
ELSIF stop2 IN opts THEN dcb.StopBits := 2X
ELSE dcb.StopBits := 0X
END;
IF even IN opts THEN dcb.Parity := 2X
ELSIF odd IN opts THEN dcb.Parity := 1X
ELSE dcb.Parity := 0X
END;
res := WinApi.SetCommState(h, dcb);
IF res # 0 THEN
to.ReadIntervalTimeout := 0;
to.ReadTotalTimeoutMultiplier := 0;
to.ReadTotalTimeoutConstant := 0;
to.WriteTotalTimeoutMultiplier := 0;
to.WriteTotalTimeoutConstant := 0;
res := WinApi.SetCommTimeouts(h, to);
IF res # 0 THEN
NEW(c); c.hnd := h; c.opts := opts; conn := c
END
END
END
END
END Open;
PROCEDURE Close* (c: Connection);
VAR res: INTEGER;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
res := WinApi.CloseHandle(c.hnd);
c.hnd := -1
END Close;
PROCEDURE SendByte* (c: Connection; x: BYTE);
VAR res, written: INTEGER;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
res := WinApi.WriteFile(c.hnd, SYSTEM.ADR(x), 1, written, NIL);
ASSERT(res # 0, 100)
END SendByte;
PROCEDURE SendBytes* (c: Connection; IN x: ARRAY OF BYTE; beg, len: INTEGER);
VAR res, written: INTEGER;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
ASSERT(LEN(x) >= beg + len, 22);
ASSERT(len > 0, 23);
res := WinApi.WriteFile(c.hnd, SYSTEM.ADR(x) + beg, len, written, NIL);
ASSERT(res # 0, 100)
END SendBytes;
PROCEDURE Available* (c: Connection): INTEGER;
VAR res: INTEGER; errors: SET; status: WinApi.COMSTAT;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
res := WinApi.ClearCommError(c.hnd, errors, status);
ASSERT(res # 0, 100);
RETURN status.cbInQue
END Available;
PROCEDURE ReceiveByte* (c: Connection; OUT x: BYTE);
VAR res, read: INTEGER;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
res := WinApi.ReadFile(c.hnd, SYSTEM.ADR(x), 1, read, NIL);
ASSERT(res # 0, 100)
END ReceiveByte;
PROCEDURE ReceiveBytes* (c: Connection; OUT x: ARRAY OF BYTE; beg, len: INTEGER);
VAR res, read: INTEGER;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
ASSERT(LEN(x) >= beg + len, 22);
ASSERT(len > 0, 23);
res := WinApi.ReadFile(c.hnd, SYSTEM.ADR(x) + beg, len, read, NIL);
ASSERT(res # 0, 100)
END ReceiveBytes;
PROCEDURE SetBuffers* (c: Connection; inpBufSize, outBufSize: INTEGER);
VAR res: INTEGER;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
res := WinApi.SetupComm(c.hnd, inpBufSize, outBufSize)
END SetBuffers;
PROCEDURE SetDTR* (c: Connection; on: BOOLEAN);
VAR res: INTEGER;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
ASSERT(~(inDTR IN c.opts), 22);
IF on THEN res := WinApi.EscapeCommFunction(c.hnd, WinApi.SETDTR)
ELSE res := WinApi.EscapeCommFunction(c.hnd, WinApi.CLRDTR)
END
END SetDTR;
PROCEDURE SetRTS* (c: Connection; on: BOOLEAN);
VAR res: INTEGER;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
ASSERT(~(inRTS IN c.opts), 22);
IF on THEN res := WinApi.EscapeCommFunction(c.hnd, WinApi.SETRTS)
ELSE res := WinApi.EscapeCommFunction(c.hnd, WinApi.CLRRTS)
END
END SetRTS;
PROCEDURE SetBreak* (c: Connection; on: BOOLEAN);
VAR res: INTEGER;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
IF on THEN res := WinApi.EscapeCommFunction(c.hnd, WinApi.SETBREAK)
ELSE res := WinApi.EscapeCommFunction(c.hnd, WinApi.CLRBREAK)
END
END SetBreak;
PROCEDURE CTSState* (c: Connection): BOOLEAN;
VAR res: INTEGER; s: SET;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
res := WinApi.GetCommModemStatus(c.hnd, s);
RETURN s * WinApi.MS_CTS_ON # {}
END CTSState;
PROCEDURE DSRState* (c: Connection): BOOLEAN;
VAR res: INTEGER; s: SET;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
res := WinApi.GetCommModemStatus(c.hnd, s);
RETURN s * WinApi.MS_DSR_ON # {}
END DSRState;
PROCEDURE CDState* (c: Connection): BOOLEAN;
VAR res: INTEGER; s: SET;
BEGIN
ASSERT(c # NIL, 20); ASSERT(c.hnd # -1, 21);
res := WinApi.GetCommModemStatus(c.hnd, s);
RETURN s * WinApi.MS_RLSD_ON # {}
END CDState;
END CommV24.