git-svn-id: https://svn.code.sf.net/p/libusbjava/code/trunk@96 94ad28fe-ef68-46b1-9651-e7ae4fcf1c4c
414 lines
13 KiB
Plaintext
414 lines
13 KiB
Plaintext
MODULE UsbBDI;
|
|
IMPORT SYS := SYSTEM, BDI := UsbBDIDll, Log := StdLog, ComTools, WinApi, Services, TextModels, Ports,
|
|
Files, HostFiles;
|
|
|
|
CONST
|
|
ttDefaultPeriod = 500; (*500 ms*) ttPipeHandDisconnected = -1;
|
|
nul = 0X;
|
|
ascLf = 0AX; ascCr = 0DX;
|
|
CONST
|
|
FALSE_ = 0;
|
|
PATH_LENGTH* = 512;
|
|
|
|
CONST
|
|
JAVA_OUT_FILENAME = "JavaOut.txt";
|
|
JAVA_ERR_FILENAME = "JavaErr.txt";
|
|
INVALID_HANDLE_VALUE = -1;
|
|
STD_OUT_COLOR = Ports.green;
|
|
STD_ERR_COLOR = Ports.grey50;
|
|
JAVA_OUT_COLOR = Ports.blue;
|
|
JAVA_ERR_COLOR = Ports.red;
|
|
|
|
CONST
|
|
MAX_UART_DATA_LENGTH* = BDI.MAX_UART_DATA_LENGTH;
|
|
|
|
CONST
|
|
PATH_SEPERATOR = "\";
|
|
CLASSPATH = "Usb\Rsrc\usbpdi.jar";
|
|
|
|
TYPE
|
|
StdReaderWriter = POINTER TO ABSTRACT RECORD (Services.Action)
|
|
stdIoText: TextModels.Model; stdIoTextPos: INTEGER;
|
|
time, endTime: LONGINT; period: INTEGER;
|
|
hStdOut, hStdErr: WinApi.HANDLE;
|
|
connected, running: BOOLEAN; prevChar: SHORTCHAR
|
|
END;
|
|
JvmReaderWriter = POINTER TO EXTENSIBLE RECORD (StdReaderWriter)
|
|
errText: TextModels.Model; stdIoWriter, stdErrWriter: TextModels.Writer;
|
|
hJavaOut, hJavaErr: WinApi.HANDLE;
|
|
END;
|
|
|
|
|
|
VAR
|
|
bool: BDI.BOOL;
|
|
Done-, deviceOpen, jvmCreated: BOOLEAN; (** previous operation successfully completed *)
|
|
readerWriter: JvmReaderWriter;
|
|
|
|
(* ----------- Standard-IO / Java ReaderWriter --------------- *)
|
|
PROCEDURE (task: StdReaderWriter) Clear, NEW, EXTENSIBLE;
|
|
BEGIN
|
|
task.stdIoText := NIL; task.stdIoTextPos := 0;
|
|
task.hStdOut := ttPipeHandDisconnected; task.hStdErr := ttPipeHandDisconnected;
|
|
task.time := 0; task.endTime := 0; task.period := 0;
|
|
task.connected := FALSE; task.running := FALSE;
|
|
task.prevChar := nul;
|
|
END Clear;
|
|
|
|
PROCEDURE (task: StdReaderWriter) Stop, NEW, EXTENSIBLE;
|
|
VAR done: WinApi.BOOL;
|
|
BEGIN
|
|
Services.RemoveAction(task); task.running := FALSE;
|
|
IF task.connected THEN
|
|
done := WinApi.CloseHandle(task.hStdOut);
|
|
done := WinApi.CloseHandle(task.hStdErr);
|
|
END;
|
|
task.Clear
|
|
END Stop;
|
|
|
|
PROCEDURE (task: StdReaderWriter) SetTime (startFromNow, period, timeOut: INTEGER), NEW;
|
|
BEGIN
|
|
task.time := Services.Ticks() + startFromNow;
|
|
IF timeOut <= 0 THEN timeOut := MAX(INTEGER) END;
|
|
task.endTime := task.time + LONG(timeOut) * Services.resolution DIV 1000;
|
|
task.period := period
|
|
END SetTime;
|
|
|
|
PROCEDURE (task: StdReaderWriter) ConnectStdOutPipe (hStdOut: WinApi.HANDLE), NEW;
|
|
VAR done: WinApi.BOOL;
|
|
BEGIN
|
|
IF task.connected & (task.hStdOut # hStdOut) THEN done := WinApi.CloseHandle(task.hStdOut) END;
|
|
task.hStdOut := hStdOut; task.connected := TRUE
|
|
END ConnectStdOutPipe;
|
|
|
|
PROCEDURE (task: StdReaderWriter) ConnectStdErrPipe (hStdErr: WinApi.HANDLE), NEW;
|
|
VAR done: WinApi.BOOL;
|
|
BEGIN
|
|
IF task.connected & (task.hStdErr # hStdErr) THEN done := WinApi.CloseHandle(task.hStdErr) END;
|
|
task.hStdErr := hStdErr; task.connected := TRUE
|
|
END ConnectStdErrPipe;
|
|
|
|
PROCEDURE (task: StdReaderWriter) Start, NEW, ABSTRACT;
|
|
|
|
PROCEDURE NewJvmReaderWriter ( ): JvmReaderWriter;
|
|
VAR rec: JvmReaderWriter;
|
|
BEGIN
|
|
NEW(rec); rec.Clear; RETURN rec
|
|
END NewJvmReaderWriter;
|
|
|
|
PROCEDURE (rec: JvmReaderWriter) Clear, EXTENSIBLE;
|
|
VAR done: WinApi.BOOL;
|
|
BEGIN
|
|
rec.Clear^;
|
|
rec.errText := NIL; rec.stdIoWriter := NIL; rec.stdErrWriter := NIL;
|
|
rec.hJavaOut := ttPipeHandDisconnected; rec.hJavaErr := ttPipeHandDisconnected;
|
|
END Clear;
|
|
|
|
PROCEDURE (rec: JvmReaderWriter) Stop, EXTENSIBLE;
|
|
VAR done: WinApi.BOOL;
|
|
BEGIN
|
|
IF rec.connected THEN
|
|
rec.Stop^; done := WinApi.CloseHandle(rec.hJavaErr); done := WinApi.CloseHandle(rec.hJavaOut)
|
|
END;
|
|
rec.Clear
|
|
END Stop;
|
|
|
|
PROCEDURE (rec: JvmReaderWriter) ConnectJavaOutPipe (hJavaOut: WinApi.HANDLE), NEW;
|
|
VAR done: WinApi.BOOL;
|
|
BEGIN
|
|
IF rec.connected & (rec.hJavaOut # hJavaOut) THEN done := WinApi.CloseHandle(rec.hJavaOut) END;
|
|
rec.hJavaOut := hJavaOut; rec.connected := TRUE
|
|
END ConnectJavaOutPipe;
|
|
|
|
PROCEDURE (rec: JvmReaderWriter) ConnectJavaErrPipe (hJavaErr: WinApi.HANDLE), NEW;
|
|
VAR done: WinApi.BOOL;
|
|
BEGIN
|
|
IF rec.connected & (rec.hJavaErr # hJavaErr) THEN done := WinApi.CloseHandle(rec.hJavaErr) END;
|
|
rec.hJavaErr := hJavaErr; rec.connected := TRUE
|
|
END ConnectJavaErrPipe;
|
|
|
|
PROCEDURE (rec: JvmReaderWriter) Start;
|
|
VAR handle, stdOutHandle, stdErrHandle: WinApi.HANDLE;
|
|
BEGIN
|
|
IF rec.running THEN rec.Stop END;
|
|
IF rec.stdIoText = NIL THEN rec.stdIoText := TextModels.dir.New(); END;
|
|
IF rec.stdIoWriter = NIL THEN rec.stdIoWriter := rec.stdIoText.NewWriter(NIL) END;
|
|
rec.stdIoWriter.SetPos(rec.stdIoTextPos);
|
|
|
|
IF rec.errText = NIL THEN rec.errText := TextModels.dir.New(); END;
|
|
IF rec.stdErrWriter = NIL THEN rec.stdErrWriter := rec.errText.NewWriter(NIL) END;
|
|
rec.stdErrWriter.SetPos(rec.errText.Length());
|
|
|
|
(* Connect Std pipes *)
|
|
(*
|
|
stdOutHandle := BDI.getOutPipeHandle();
|
|
stdErrHandle := BDI.getErrPipeHandle();
|
|
Log.String("stdOutHandle: "); Log.Int(stdOutHandle); Log.Ln;
|
|
Log.String("stdErrHandle: "); Log.Int(stdErrHandle); Log.Ln;
|
|
*)
|
|
rec.ConnectStdOutPipe(BDI.getOutPipeHandle());
|
|
rec.ConnectStdErrPipe(BDI.getErrPipeHandle());
|
|
|
|
(* Connect Java pipes *)
|
|
handle := WinApi.CreateFile(JAVA_OUT_FILENAME, WinApi.GENERIC_READ + WinApi.GENERIC_WRITE,
|
|
WinApi.FILE_SHARE_WRITE, NIL, WinApi.OPEN_EXISTING, {}, 0);
|
|
IF (handle = INVALID_HANDLE_VALUE) THEN
|
|
Log.String("Error opening JAVA_OUT_FILENAME"); Log.Ln;
|
|
ELSE
|
|
rec.ConnectJavaOutPipe(handle)
|
|
END;
|
|
|
|
handle := WinApi.CreateFile(JAVA_ERR_FILENAME, WinApi.GENERIC_READ + WinApi.GENERIC_WRITE,
|
|
WinApi.FILE_SHARE_WRITE, NIL, WinApi.OPEN_EXISTING, {}, 0);
|
|
IF (handle = INVALID_HANDLE_VALUE) THEN
|
|
Log.String("Error opening JAVA_ERR_FILENAME"); Log.Ln;
|
|
ELSE
|
|
rec.ConnectJavaErrPipe(handle)
|
|
END;
|
|
|
|
rec.running := TRUE; Services.DoLater(rec, rec.time)
|
|
END Start;
|
|
|
|
PROCEDURE (rec: JvmReaderWriter) Do;
|
|
VAR
|
|
outModel: TextModels.Model;
|
|
n, ioDone, errDone, nofBytesRead, ioBytesAvail, errBytesAvail, exitCode: INTEGER;
|
|
ch: SHORTCHAR;
|
|
strSC: ARRAY 512 OF SHORTCHAR;
|
|
success: WinApi.BOOL;
|
|
BEGIN
|
|
IF rec.running THEN
|
|
(* STD OUT *)
|
|
IF rec.hStdOut > 0 THEN
|
|
nofBytesRead := 0; ioBytesAvail := 0;
|
|
ioDone := WinApi.PeekNamedPipe(
|
|
rec.hStdOut, (*//handle to pipe to copy from *)
|
|
SYS.ADR(strSC), (*//pointer to data buffer*)
|
|
LEN(strSC), (*//size, in bytes, of data buffer*)
|
|
nofBytesRead, (*nofBytesRead,*) (*//pointer to number of bytes read*)
|
|
ioBytesAvail, (*//pointer to total number of bytes available*)
|
|
NIL (*//pointer to unread bytes in this message*)
|
|
);
|
|
IF (ioDone # 0) & (ioBytesAvail > 0) THEN
|
|
ioDone := WinApi.ReadFile(rec.hStdOut, SYS.ADR(strSC), LEN(strSC), nofBytesRead, NIL);
|
|
IF (ioDone # 0) & (nofBytesRead > 0) THEN
|
|
FOR n := 0 TO nofBytesRead - 1 DO
|
|
ch := strSC[n];
|
|
IF (ch = ascLf) & (rec.prevChar # ascCr) THEN ch := TextModels.line END;
|
|
rec.stdIoWriter.WriteChar(ch);
|
|
rec.prevChar := ch;
|
|
END
|
|
END;
|
|
rec.stdIoText.SetAttr(0, rec.stdIoText.Length(),
|
|
TextModels.NewColor(TextModels.dir.attr, STD_OUT_COLOR));
|
|
Log.text.Append(rec.stdIoText)
|
|
END;
|
|
END;
|
|
(* STD ERR *)
|
|
IF rec.hStdErr > 0 THEN
|
|
nofBytesRead := 0; errBytesAvail := 0;
|
|
ioDone := WinApi.PeekNamedPipe(
|
|
rec.hStdErr, (*//handle to pipe to copy from *)
|
|
SYS.ADR(strSC), (*//pointer to data buffer*)
|
|
LEN(strSC), (*//size, in bytes, of data buffer*)
|
|
nofBytesRead, (*nofBytesRead,*) (*//pointer to number of bytes read*)
|
|
errBytesAvail, (*//pointer to total number of bytes available*)
|
|
NIL (*//pointer to unread bytes in this message*)
|
|
);
|
|
IF (ioDone # 0) & (errBytesAvail > 0) THEN
|
|
errDone := WinApi.ReadFile(rec.hStdErr, SYS.ADR(strSC), LEN(strSC), nofBytesRead, NIL);
|
|
IF (errDone # 0) & (nofBytesRead > 0) THEN
|
|
FOR n := 0 TO nofBytesRead - 1 DO
|
|
ch := strSC[n];
|
|
IF (ch = ascLf) & (rec.prevChar # ascCr) THEN ch := TextModels.line END;
|
|
rec.stdErrWriter.WriteChar(ch); rec.prevChar := ch
|
|
END
|
|
END;
|
|
rec.errText.SetAttr(0, rec.errText.Length(),
|
|
TextModels.NewColor(TextModels.dir.attr, STD_ERR_COLOR));
|
|
Log.text.Append(rec.errText)
|
|
END
|
|
END;
|
|
(* JAVA OUT *)
|
|
IF rec.hJavaOut > 0 THEN
|
|
ioDone := WinApi.ReadFile(rec.hJavaOut, SYS.ADR(strSC), LEN(strSC), nofBytesRead, NIL);
|
|
IF (ioDone # 0) & (nofBytesRead > 0) THEN
|
|
FOR n := 0 TO nofBytesRead - 1 DO
|
|
ch := strSC[n];
|
|
IF (ch = ascLf) & (rec.prevChar # ascCr) THEN ch := TextModels.line END;
|
|
rec.stdIoWriter.WriteChar(ch);
|
|
rec.prevChar := ch;
|
|
END
|
|
END;
|
|
rec.stdIoText.SetAttr(0, rec.stdIoText.Length(),
|
|
TextModels.NewColor(TextModels.dir.attr, JAVA_OUT_COLOR));
|
|
Log.text.Append(rec.stdIoText)
|
|
END;
|
|
(* JAVA ERR *)
|
|
IF rec.hJavaErr > 0 THEN
|
|
errDone := WinApi.ReadFile(rec.hJavaErr, SYS.ADR(strSC), LEN(strSC), nofBytesRead, NIL);
|
|
IF (errDone # 0) & (nofBytesRead > 0) THEN
|
|
FOR n := 0 TO nofBytesRead - 1 DO
|
|
ch := strSC[n];
|
|
IF (ch = ascLf) & (rec.prevChar # ascCr) THEN ch := TextModels.line END;
|
|
rec.stdErrWriter.WriteChar(ch); rec.prevChar := ch
|
|
END
|
|
END;
|
|
rec.errText.SetAttr(0, rec.errText.Length(),
|
|
TextModels.NewColor(TextModels.dir.attr, JAVA_ERR_COLOR));
|
|
Log.text.Append(rec.errText)
|
|
END;
|
|
INC( rec.time, rec.period ); Services.DoLater(rec, rec.time )
|
|
END;
|
|
END Do;
|
|
|
|
(* ----------- JVM --------------- *)
|
|
|
|
PROCEDURE CreateJVM (classpath: ARRAY OF SHORTCHAR);
|
|
VAR string: WinApi.PtrSTR;
|
|
BEGIN
|
|
string := ComTools.NewSString(classpath);
|
|
bool := BDI.createJVM(string);
|
|
IF bool = FALSE_ THEN
|
|
Done := FALSE;
|
|
Log.String("creating JVM failed"); Log.Ln;
|
|
ELSE
|
|
Done := TRUE;
|
|
Log.String("JVM successfully created"); Log.Ln;
|
|
jvmCreated := TRUE;
|
|
END;
|
|
(* We need to create the jvm before opening the ReaderWriter.
|
|
The javaout, javaerr can only be opened after creating the jvm! *)
|
|
IF readerWriter = NIL THEN
|
|
readerWriter := NewJvmReaderWriter();
|
|
readerWriter.Start();
|
|
END;
|
|
ComTools.FreeSString(string);
|
|
END CreateJVM;
|
|
|
|
PROCEDURE DestroyJVM ;
|
|
BEGIN
|
|
bool := BDI.destroyJVM();
|
|
IF bool = FALSE_ THEN
|
|
Done := FALSE;
|
|
Log.String("destroying JVM failed"); Log.Ln;
|
|
ELSE
|
|
Done := TRUE;
|
|
Log.String("JVM destroyed"); Log.Ln;
|
|
END;
|
|
jvmCreated := FALSE;
|
|
END DestroyJVM;
|
|
|
|
PROCEDURE CheckForExceptions * (): BOOLEAN;
|
|
BEGIN
|
|
RETURN (BDI.checkForExceptions() # FALSE_)
|
|
END CheckForExceptions;
|
|
|
|
(* ----------- USB --------------- *)
|
|
|
|
PROCEDURE USB_Device_open ;
|
|
BEGIN
|
|
BDI.USB_Device_open;
|
|
Done := ~CheckForExceptions();
|
|
IF Done THEN
|
|
deviceOpen := TRUE;
|
|
END
|
|
END USB_Device_open;
|
|
|
|
PROCEDURE USB_Device_close ;
|
|
BEGIN
|
|
BDI.USB_Device_close;
|
|
Done := ~CheckForExceptions();
|
|
deviceOpen := FALSE;
|
|
END USB_Device_close;
|
|
|
|
PROCEDURE USB_Device_reset * ;
|
|
BEGIN
|
|
BDI.USB_Device_reset;
|
|
Done := ~CheckForExceptions();
|
|
deviceOpen := FALSE;
|
|
END USB_Device_reset;
|
|
|
|
|
|
(* --------- UART0 ----------------- *)
|
|
|
|
PROCEDURE UART0_read * (VAR data: ARRAY OF SHORTCHAR; VAR length: INTEGER): BOOLEAN;
|
|
BEGIN
|
|
length := BDI.UART0_read(data);
|
|
RETURN length # FALSE_;
|
|
END UART0_read;
|
|
|
|
PROCEDURE UART0_write * (VAR data: ARRAY OF SHORTCHAR; length: INTEGER): BOOLEAN;
|
|
VAR
|
|
result: INTEGER;
|
|
BEGIN
|
|
RETURN BDI.UART0_write(SYS.ADR(data[0]), length) # FALSE_;
|
|
END UART0_write;
|
|
|
|
(* -------------- Helper Functions ------------------*)
|
|
|
|
PROCEDURE GetUserStartUpPath (VAR startupPath: ARRAY OF SHORTCHAR);
|
|
VAR
|
|
userStartUpLocator: Files.Locator; userStartUpHostLoc: HostFiles.Locator;
|
|
startupPathChar: ARRAY PATH_LENGTH OF CHAR;
|
|
i: INTEGER;
|
|
BEGIN
|
|
userStartUpLocator := Files.dir.This(""); userStartUpHostLoc := userStartUpLocator(HostFiles.Locator);
|
|
startupPathChar := userStartUpHostLoc.path$;
|
|
FOR i := 0 TO LEN(startupPathChar) - 1 DO
|
|
startupPath[i] := SYS.VAL(SHORTCHAR, startupPathChar[i]);
|
|
END
|
|
END GetUserStartUpPath;
|
|
|
|
|
|
PROCEDURE ConnectDevice * ;
|
|
VAR
|
|
startupPath: ARRAY PATH_LENGTH OF SHORTCHAR;
|
|
BEGIN
|
|
IF ~deviceOpen THEN
|
|
IF ~jvmCreated THEN
|
|
GetUserStartUpPath(startupPath);
|
|
Log.String("Startup Path: " + startupPath); Log.Ln;
|
|
CreateJVM(startupPath + PATH_SEPERATOR + CLASSPATH);
|
|
(*
|
|
CreateJVM("D:\work\USB\eclipse\mcdp\bin\");
|
|
*)
|
|
IF ~Done THEN HALT(77) END;
|
|
jvmCreated := TRUE;
|
|
END;
|
|
BDI.USB_Device_open;
|
|
IF ~Done THEN HALT(78) END;
|
|
END
|
|
END ConnectDevice;
|
|
|
|
PROCEDURE DeviceOpen * (): BOOLEAN ;
|
|
BEGIN
|
|
RETURN deviceOpen
|
|
END DeviceOpen;
|
|
|
|
(* Close and reopen the device *)
|
|
PROCEDURE ReopenDevice * ;
|
|
BEGIN
|
|
USB_Device_close;
|
|
USB_Device_open;
|
|
IF Done THEN
|
|
Log.String("Device opened successfully"); Log.Ln;
|
|
ELSE
|
|
Log.String("Error while opening Device"); Log.Ln;
|
|
END
|
|
END ReopenDevice;
|
|
|
|
BEGIN
|
|
deviceOpen := FALSE;
|
|
jvmCreated := FALSE;
|
|
CLOSE
|
|
IF readerWriter # NIL THEN
|
|
readerWriter.Stop;
|
|
END;
|
|
IF deviceOpen THEN
|
|
USB_Device_close;
|
|
END;
|
|
IF jvmCreated THEN
|
|
DestroyJVM
|
|
END
|
|
END UsbBDI.
|