MODULE UsbRS232;
IMPORT SYSTEM, Kernel, KernelLog, Modules, Serials, Usbdi;
CONST
Name = "UsbRs232";
Description = "USB-RS232 Interface Converter Driver";
Priority = 0;
BufSize = 1024;
TraceSend = {0};
TraceReceive = {1};
TraceCommands = {2};
TraceReceiveData = {3};
TraceReceiveStatus = {4};
TraceAll = {0..31};
TraceNone = {};
Trace = TraceNone;
Debug = TRUE;
Verbose = TRUE;
ModuleName = "UsbRS232";
EpBulkOut = 02H;
EpInterruptInData = 082H;
EpInterruptInStatus = 081H;
IdVendorMct = 0711H;
IdProductU232P9 = 230H;
IdProductU232P25 = 210H;
IdProductDUH3SP = 200H;
IdVendorBelkin = 50DH;
IdProductF5U109 = 109H;
MctGetModemStatus = 2;
MctSetBaudrate = 5;
MctGetLineCtrl = 6;
MctSetLineCtrl = 7;
MctSetModemCtrl = 10;
MctSetUnknown1 = 11;
MctSetUnknown2 = 12;
MctLcrSetBreak = 6;
MctData5 = {};
MctData6 = {0};
MctData7 = {1};
MctData8 = {0,1};
MctParityNone = {};
MctParityEven = {3, 4};
MctParityOdd = {3};
MctParityMark = {3, 5};
MctParitySpace = {3,4,5};
MctStop1= {};
MctStop2 = {2};
MctMcrRts = 1;
MctMcrDtr = 0;
MctMcrOut2 = 3;
MctMsrCd = 7;
MctMsrRi = 6;
MctMsrDsr = 5;
MctMsrCts = 4;
MctMsrDcd = 3;
MctMsrDri = 2;
MctMsrDdsr = 1;
MctMsrDcts = 0;
MctLsrErr = 7;
MctLsrTemt = 6;
MctLsrThre = 5;
MctLsrBi = 4;
MctLsrFe = 3;
MctLsrPe = 2;
MctLsrOe = 1;
MctLsrDr = 0;
TYPE
UsbRs232Driver = OBJECT (Usbdi.Driver)
VAR
port : Port;
controlPipe : Usbdi.Pipe;
interruptInData, interruptInStatus : Usbdi.Pipe;
bulkOut : Usbdi.Pipe;
data1, data4, data64 : Usbdi.BufferPtr;
status2 : Usbdi.BufferPtr;
diagnostics : SET;
msr : SET;
lsr : SET;
mcr : SET;
lcr : SET;
mc : SET;
PROCEDURE Connect() : BOOLEAN;
VAR ignore : Usbdi.Status;
BEGIN
controlPipe := device.GetPipe(0);
IF controlPipe = NIL THEN
IF Debug THEN ShowModule("Couldn't get default control pipe."); KernelLog.Ln; END;
RETURN FALSE;
END;
interruptInData := device.GetPipe(EpInterruptInData);
interruptInStatus := device.GetPipe(EpInterruptInStatus);
IF (interruptInData = NIL) OR (interruptInStatus = NIL) THEN
IF Debug THEN ShowModule("Couldn't get interrupt in pipes."); KernelLog.Ln; END;
RETURN FALSE;
END;
bulkOut := device.GetPipe(EpBulkOut);
IF bulkOut = NIL THEN
IF Debug THEN ShowModule("Couldn't get bulk out pipe."); KernelLog.Ln; END;
RETURN FALSE;
END;
interruptInStatus.SetTimeout(0);
interruptInStatus.SetCompletionHandler(UpdateStatus);
ignore := interruptInStatus.Transfer(2, 0, status2^);
interruptInData.SetTimeout(0);
interruptInData.SetCompletionHandler(UpdateData);
ignore := interruptInData.Transfer(64, 0, data64^);
IF ~GetMSR(msr) THEN
IF Debug THEN ShowModule("GetMSR failed during connect."); KernelLog.Ln; END;
RETURN FALSE;
END;
NEW(port); NEW(port.data1, 1); port.driver := SELF;
Serials.RegisterPort(port, Description);
RETURN TRUE;
END Connect;
PROCEDURE Disconnect;
BEGIN
Serials.UnRegisterPort(SELF.port);
END Disconnect;
PROCEDURE UpdateData(status : Usbdi.Status; actLen : LONGINT);
VAR ignore : Usbdi.Status; i : LONGINT;
BEGIN
IF Trace * TraceReceiveData # {} THEN
ShowModule("UpdateData: Received "); KernelLog.Int(actLen, 0); KernelLog.String(" Bytes:");
FOR i := 0 TO actLen - 1 DO KernelLog.Char(" "); KernelLog.Int(ORD(data64[i]), 0); END;
KernelLog.Ln;
END;
IF (status = Usbdi.Ok) OR (status = Usbdi.ShortPacket) THEN
port.HandleData(data64^, actLen);
ignore := interruptInData.Transfer(64, 0, data64^);
ELSE
IF Debug THEN ShowModule("UpdateData failed."); KernelLog.Ln; END;
END;
END UpdateData;
PROCEDURE UpdateStatus(status : Usbdi.Status; actLen : LONGINT);
VAR ignore : Usbdi.Status;
BEGIN
IF Trace * TraceReceiveStatus # {} THEN ShowModule("UpdateStatus: Received "); KernelLog.Int(actLen, 0); KernelLog.String(" Bytes: "); END;
IF (status = Usbdi.Ok) OR (status = Usbdi.ShortPacket) THEN
IF actLen>=1 THEN
msr := SYSTEM.VAL(SET, status2[0]);
IF MctMsrRi IN msr THEN INCL(mc, Serials.RI); ELSE EXCL(mc, Serials.RI); END;
IF MctMsrDsr IN msr THEN INCL(mc, Serials.DSR); ELSE EXCL(mc, Serials.DSR); END;
IF MctMsrCts IN msr THEN INCL(mc, Serials.CTS); ELSE EXCL(mc, Serials.CTS); END;
IF MctMsrCd IN msr THEN INCL(mc, Serials.DCD); ELSE EXCL(mc, Serials.DCD); END;
IF Trace * TraceReceiveStatus # {} THEN
IF Serials.RI IN mc THEN KernelLog.String("[RI]"); END;
IF Serials.DSR IN mc THEN KernelLog.String("[DSR]"); END;
IF Serials.CTS IN mc THEN KernelLog.String("[CTS]"); END;
IF Serials.DCD IN mc THEN KernelLog.String("[DCD]"); END;
END;
END;
IF actLen>=2 THEN
lsr := SYSTEM.VAL(SET, status2[1]);
diagnostics := {};
IF MctLsrOe IN lsr THEN INCL(diagnostics, Serials.OverrunError); END;
IF MctLsrPe IN lsr THEN INCL(diagnostics, Serials.ParityError); END;
IF MctLsrFe IN lsr THEN INCL(diagnostics, Serials.FramingError); END;
IF MctLsrBi IN lsr THEN
INCL(mc, Serials.BreakInterrupt); INCL(diagnostics, Serials.BreakInterrupt);
ELSE
EXCL(mc, Serials.BreakInterrupt);
END;
IF Trace * TraceReceiveStatus # {} THEN
IF Serials.BreakInterrupt IN mc THEN KernelLog.String("[BI]"); END;
KernelLog.String(" Errors: ");
IF diagnostics = {} THEN KernelLog.String("none");
ELSE
IF Serials.OverrunError IN diagnostics THEN KernelLog.String("[Overrun]"); END;
IF Serials.ParityError IN diagnostics THEN KernelLog.String("[Parity]"); END;
IF Serials.FramingError IN diagnostics THEN KernelLog.String("[Framing]"); END;
IF Serials.BreakInterrupt IN diagnostics THEN KernelLog.String("BreakInterrupt]"); END;
END;
END;
END;
ignore := interruptInStatus.Transfer(2, 0, status2^);
ELSE
IF Debug THEN ShowModule("UpdateStatus failed."); KernelLog.Ln; END;
END;
IF Trace * TraceReceiveStatus # {} THEN KernelLog.Ln; END;
END UpdateStatus;
PROCEDURE SetBaudrate(baudrate : LONGINT) : BOOLEAN;
VAR divisor : LONGINT; status : Usbdi.Status;
BEGIN
IF Trace * TraceCommands # {} THEN ShowModule("SetBaudrate to "); KernelLog.Int(baudrate, 0); KernelLog.String(" bps."); KernelLog.Ln; END;
port.portbps := 0;
IF ((device.descriptor.idVendor = IdVendorMct) & (device.descriptor.idProduct = IdProductU232P25)) OR
((device.descriptor.idVendor = IdVendorMct) & (device.descriptor.idProduct = IdProductU232P9)) THEN
IF baudrate = 300 THEN divisor := 01H
ELSIF baudrate = 600 THEN divisor := 02H;
ELSIF baudrate = 1200 THEN divisor := 03H;
ELSIF baudrate = 2400 THEN divisor := 04H;
ELSIF baudrate = 4800 THEN divisor := 06H;
ELSIF baudrate = 9600 THEN divisor := 08H;
ELSIF baudrate = 19200 THEN divisor := 09H;
ELSIF baudrate = 38400 THEN divisor := 0AH;
ELSIF baudrate = 57600 THEN divisor := 0BH;
ELSIF baudrate = 115200 THEN divisor := 0CH;
ELSE
IF Debug THEN ShowModule("SetBaudrate: Wrong baud rate selected."); KernelLog.Ln; END;
RETURN FALSE;
END;
data1[0] := CHR(divisor);
status := device.Request(Usbdi.ToDevice + Usbdi.Vendor + Usbdi.Device, MctSetBaudrate, 0, 0, 1, data1^);
ELSE
IF (115200 MOD baudrate) # 0 THEN
IF Debug THEN ShowModule("SetBaudrate: Wrong baud rate selected."); KernelLog.Ln; END;
RETURN FALSE;
ELSE
divisor := 115200 DIV baudrate;
END;
data4[0] := CHR(divisor);
data4[1] := CHR(SYSTEM.LSH(divisor, -8));
data4[2] := CHR(SYSTEM.LSH(divisor, -16));
data4[3] := CHR(SYSTEM.LSH(divisor, -24));
status := device.Request(Usbdi.ToDevice + Usbdi.Vendor + Usbdi.Device, MctSetBaudrate, 0, 0, 4, data4^);
END;
IF status # Usbdi.Ok THEN
IF Debug THEN ShowModule("SetBaudrate failed (MctSetBaudrate)"); KernelLog.Ln; END;
RETURN FALSE;
END;
data1[0] := CHR(0);
status := device.Request(Usbdi.ToDevice + Usbdi.Vendor + Usbdi.Device, MctSetUnknown1, 0, 0, 1, data1^);
IF status # Usbdi.Ok THEN
IF Debug THEN ShowModule("SetBaudrate failed (MctSetUnknown1). "); KernelLog.Ln; END;
RETURN FALSE;
END;
status := device.Request(Usbdi.ToDevice + Usbdi.Vendor + Usbdi.Device, MctSetUnknown2, 0, 0, 1, data1^);
IF status # Usbdi.Ok THEN
IF Debug THEN ShowModule("SetBaudrate failed (MctSetUnknown1). "); KernelLog.Ln; END;
RETURN FALSE;
END;
port.portbps := baudrate;
RETURN TRUE;
END SetBaudrate;
PROCEDURE SetLCR(set : SET) : BOOLEAN;
VAR status : Usbdi.Status;
BEGIN
data1[0] := SYSTEM.VAL(CHAR, set);
status := device.Request(Usbdi.ToDevice + Usbdi.Vendor + Usbdi.Device, MctSetLineCtrl, 0, 0, 1, data1^);
IF status # Usbdi.Ok THEN
IF Debug THEN ShowModule("SetLCR failed."); KernelLog.Ln; END;
RETURN FALSE;
ELSE
lcr := set;
RETURN TRUE;
END;
END SetLCR;
PROCEDURE GetLCR(VAR lcr : SET) : BOOLEAN;
VAR status : Usbdi.Status;
BEGIN
status := device.Request(Usbdi.ToHost + Usbdi.Vendor + Usbdi.Device, MctGetLineCtrl, 0, 0, 1, data1^);
IF status # Usbdi.Ok THEN
IF Debug THEN ShowModule("GetLCR failed."); KernelLog.Ln; END;
RETURN FALSE;
ELSE
lcr := SYSTEM.VAL(SET, data1[0]);
RETURN TRUE;
END;
END GetLCR;
PROCEDURE SetMCR(set : SET) : BOOLEAN;
VAR status : Usbdi.Status;
BEGIN
IF Serials.DTR IN set THEN INCL(mcr, MctMcrDtr); ELSE EXCL(mcr, MctMcrDtr); END;
IF Serials.RTS IN set THEN INCL(mcr, MctMcrRts); ELSE EXCL(mcr, MctMcrRts); END;
INCL(mcr, MctMcrOut2);
data1[0] := CHR(SYSTEM.VAL(LONGINT, mcr));
status := device.Request(Usbdi.ToDevice + Usbdi.Vendor + Usbdi.Device, MctSetModemCtrl, 0, 0, 1, data1^);
IF status # Usbdi.Ok THEN
IF Debug THEN ShowModule("SetMCR failed: "); KernelLog.Ln; END;
RETURN FALSE;
ELSE
IF Serials.DTR IN set THEN INCL(mc, Serials.DTR) ELSE EXCL(mc, Serials.DTR) END;
IF Serials.RTS IN set THEN INCL(mc, Serials.RTS) ELSE EXCL (mc, Serials.RTS) END;
RETURN TRUE;
END;
END SetMCR;
PROCEDURE GetMSR(VAR value : SET) : BOOLEAN;
VAR status : Usbdi.Status;
BEGIN
status := device.Request(Usbdi.ToHost + Usbdi.Vendor + Usbdi.Device, MctGetModemStatus, 0, 0, 1, data1^);
IF status # Usbdi.Ok THEN
IF Debug THEN ShowModule("GetMSR failed."); KernelLog.Ln; END;
RETURN FALSE;
ELSE
IF Trace * TraceCommands # {} THEN ShowModule("GetMSR succeeded (value: "); KernelLog.Bits(SYSTEM.VAL(SET, data1[0]), 0, 8); KernelLog.String(")"); KernelLog.Ln; END;
msr := SYSTEM.VAL(SET, data1[0]);
IF MctMsrRi IN msr THEN INCL(mc, Serials.RI); ELSE EXCL(mc, Serials.RI); END;
IF MctMsrDsr IN msr THEN INCL(mc, Serials.DSR); ELSE EXCL(mc, Serials.DSR); END;
IF MctMsrCts IN msr THEN INCL(mc, Serials.CTS); ELSE EXCL(mc, Serials.CTS); END;
IF MctMsrCd IN msr THEN INCL(mc, Serials.DCD); ELSE EXCL(mc, Serials.DCD); END;
value := msr;
RETURN TRUE;
END;
END GetMSR;
PROCEDURE &Init*;
BEGIN
NEW(data1, 1); NEW(data4, 4); NEW(data64, 64); NEW(status2, 2);
msr := {}; lsr := {}; mcr := {}; lcr := {};
END Init;
END UsbRs232Driver;
TYPE
Port = OBJECT(Serials.Port)
VAR
driver : UsbRs232Driver;
portbps : LONGINT;
data1 : Usbdi.BufferPtr;
buf: ARRAY BufSize OF CHAR;
head, tail: LONGINT;
open: BOOLEAN;
diagnostic: LONGINT;
PROCEDURE Open*(bps, data, parity, stop : LONGINT; VAR res: LONGINT);
BEGIN {EXCLUSIVE}
IF open THEN
IF Verbose THEN ShowModule(name); KernelLog.String(" already open"); KernelLog.Ln; END;
res := Serials.PortInUse;
RETURN;
END;
SetPortState(bps, data, parity, stop, res);
IF res = Serials.Ok THEN
open := TRUE;
head := 0; tail:= 0;
IF Verbose THEN ShowModule(name); KernelLog.String("opened"); KernelLog.Ln; END;
END
END Open;
PROCEDURE Send*(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: LONGINT);
VAR status : Usbdi.Status; buffer: POINTER TO ARRAY OF CHAR;
BEGIN {EXCLUSIVE}
IF ~open THEN res := Serials.Closed; RETURN; END;
IF Trace * TraceSend # {} THEN ShowModule("Sending "); KernelLog.Int(len, 0); KernelLog.String(" bytes"); KernelLog.Ln; END;
NEW (buffer, len); COPY (buf, buffer^);
status := driver.bulkOut.Transfer(len, ofs, buffer^);
IF status = Usbdi.Ok THEN
res := Serials.Ok;
charactersSent := charactersSent + len;
ELSE
res := Serials.TransportError;
IF Debug THEN ShowModule("Transmission failed, res: "); KernelLog.Int(status, 0); KernelLog.Ln; END;
END;
END Send;
PROCEDURE SendChar*(ch: CHAR; VAR res : LONGINT);
VAR status : Usbdi.Status;
BEGIN {EXCLUSIVE}
IF ~open THEN res := Serials.Closed; RETURN; END;
data1[0] := ch;
IF Trace * TraceSend # {} THEN ShowModule("Sending character ORD: "); KernelLog.Int(ORD(data1[0]), 0); KernelLog.Ln; END;
status := driver.bulkOut.Transfer(1, 0, data1^);
IF status # Usbdi.Ok THEN
res := Serials.Ok;
INC(charactersSent);
ELSE
res := Serials.TransportError;
IF Debug THEN ShowModule("Transmission of character failed."); KernelLog.Ln; END;
END;
END SendChar;
PROCEDURE ReceiveChar*(VAR ch: CHAR; VAR res: LONGINT);
BEGIN {EXCLUSIVE}
IF ~open THEN res := Serials.Closed; RETURN; END;
AWAIT(tail # head);
IF tail = -1 THEN
res := Serials.Closed;
ELSE
ch := buf[head]; head := (head+1) MOD BufSize;
res := diagnostic
END
END ReceiveChar;
PROCEDURE HandleData(data : Usbdi.Buffer; actLen : LONGINT);
VAR n, i : LONGINT; ch : CHAR;
BEGIN {EXCLUSIVE}
charactersReceived := charactersReceived + actLen;
i := 0;
LOOP
IF i >= actLen THEN EXIT; END;
ch := data[i];
n := (tail + 1) MOD BufSize;
IF n # head THEN
buf[tail] := ch; tail := n
ELSE
IF Debug THEN KernelLog.String("Port: HandleData: Buffer overflow detected."); KernelLog.Ln; END;
END;
INC(i);
diagnostic := SYSTEM.VAL(LONGINT, driver.diagnostics);
END;
END HandleData;
PROCEDURE Available*(): LONGINT;
BEGIN {EXCLUSIVE}
RETURN (tail - head) MOD BufSize
END Available;
PROCEDURE SetPortState(bps, data, parity, stop : LONGINT; VAR res: LONGINT);
VAR s : SET;
BEGIN
IF (bps > 0) & (115200 MOD bps = 0) THEN
IF (data >= 5) & (data <= 8) & (parity >= Serials.ParNo) & (parity <= Serials.ParSpace) & (stop >= Serials.Stop1) & (stop <= Serials.Stop1dot5) THEN
IF ~driver.SetBaudrate(bps) THEN
res := Serials.WrongBPS; RETURN;
END;
CASE data OF
5: s := MctData5;
| 6: s := MctData6;
| 7: s := MctData7;
| 8: s := MctData8;
END;
CASE parity OF
Serials.ParNo: s := s + MctParityNone;
| Serials.ParOdd: s := s + MctParityOdd;
| Serials.ParEven: s := s + MctParityEven;
| Serials.ParMark: s := s + MctParityMark;
| Serials.ParSpace: s := s + MctParitySpace;
END;
IF (stop = Serials.Stop1dot5) & (data # 5) THEN res := Serials.WrongStop; RETURN; END;
IF stop # Serials.Stop1 THEN s := s + MctStop2; END;
IF ~driver.SetLCR(s) THEN
res := Serials.WrongData;RETURN;
END;
s := {}; INCL(s, Serials.DTR); INCL(s, Serials.RTS);
IF ~driver.SetMCR(s) THEN
res := Serials.WrongData; RETURN;
END;
res := Serials.Ok
ELSE
res := Serials.WrongData
END
ELSE
res := Serials.WrongBPS
END;
END SetPortState;
PROCEDURE GetPortState*(VAR openstat : BOOLEAN; VAR bps, data, parity, stop : LONGINT);
VAR set : SET; res : BOOLEAN;
BEGIN
openstat := open;
bps := portbps;
res := driver.GetLCR(set);
IF set * {0, 1} = MctData8 THEN data := 8;
ELSIF set * {0, 1} = MctData7 THEN data := 7;
ELSIF set * {0, 1} = MctData6 THEN data := 6;
ELSE data := 5;
END;
IF set * MctStop2 # {} THEN
IF set * {0, 1} = MctData5 THEN stop := Serials.Stop1dot5; ELSE stop := Serials.Stop2; END;
ELSE
stop := Serials.Stop1;
END;
IF set * {3..5} = MctParitySpace THEN parity := Serials.ParSpace;
ELSIF set * {3..5} = MctParityMark THEN parity := Serials.ParMark;
ELSIF set * {3..5} = MctParityEven THEN parity := Serials.ParEven;
ELSIF set * {3..5} = MctParityOdd THEN parity := Serials.ParOdd;
ELSE parity := Serials.ParNo;
END;
IF Trace * TraceCommands # {} THEN
ShowModule("GetPortState of port "); KernelLog.String(name); KernelLog.String(":");
IF res THEN
KernelLog.String(" State: "); IF open THEN KernelLog.String("Open"); ELSE KernelLog.String("Closed"); END;
KernelLog.String(" DataBits: "); KernelLog.Int(data, 0);
KernelLog.String(" StopBits: "); IF stop=3 THEN KernelLog.String("1.5"); ELSE KernelLog.Int(stop, 0); END;
KernelLog.String(" Parity: ");
CASE parity OF
0 : KernelLog.String("None");
|1 : KernelLog.String("Odd");
|2 : KernelLog.String("Even");
|3 : KernelLog.String("Mark");
|4 : KernelLog.String("Space");
ELSE
KernelLog.String("Unknown");
END;
KernelLog.String(" Bps: "); KernelLog.Int(bps, 0); KernelLog.Ln;
ELSE
KernelLog.String("Status request failed."); KernelLog.Ln;
END;
END;
END GetPortState;
PROCEDURE ClearMC*(s: SET);
VAR temp : SET; ignore : BOOLEAN;
BEGIN {EXCLUSIVE}
IF s * {Serials.DTR, Serials.RTS} # {} THEN
temp := driver.mcr;
IF s * {Serials.DTR} # {} THEN EXCL(temp, Serials.DTR); END;
IF s * {Serials.RTS} # {} THEN EXCL(temp, Serials.RTS); END;
ignore := driver.SetMCR(temp);
END;
IF Serials.Break IN s THEN
ignore := driver.GetLCR(temp);
EXCL(temp, Serials.Break);
ignore := driver.SetLCR(temp);
END;
END ClearMC;
PROCEDURE SetMC*(s: SET);
VAR ignore : BOOLEAN;
BEGIN {EXCLUSIVE}
IF s * {Serials.DTR, Serials.RTS} # {} THEN ignore := driver.SetMCR(s * {Serials.DTR, Serials.RTS}); END;
IF Serials.Break IN s THEN
ignore := driver.SetLCR({Serials.Break});
END;
END SetMC;
PROCEDURE GetMC*(VAR s: SET);
BEGIN {EXCLUSIVE}
s := driver.msr;
IF MctLsrBi IN driver.lsr THEN INCL(s, Serials.Break); END;
END GetMC;
PROCEDURE Close*;
VAR timer : Kernel.Timer; counter : LONGINT;
BEGIN {EXCLUSIVE}
IF ~open THEN
IF Verbose THEN ShowModule(name); KernelLog.String(" not open"); KernelLog.Ln; END;
RETURN;
ELSE
IF ~(MctLsrTemt IN driver.lsr) THEN
NEW(timer); counter := 0;
REPEAT
timer.Sleep(1);
INC(counter);
UNTIL (MctLsrTemt IN driver.lsr) OR (counter>100);
END;
tail := -1;
open := FALSE;
IF Verbose THEN ShowModule(name); KernelLog.String(" closed"); KernelLog.Ln END;
END;
END Close;
END Port;
PROCEDURE ShowModule(CONST string : ARRAY OF CHAR);
BEGIN
KernelLog.String(ModuleName); KernelLog.String(": "); KernelLog.String(string);
END ShowModule;
PROCEDURE Probe(dev : Usbdi.UsbDevice; id : Usbdi.InterfaceDescriptor) : Usbdi.Driver;
VAR driver : UsbRs232Driver;
BEGIN
IF ((dev.descriptor.idVendor = IdVendorMct) & (dev.descriptor.idProduct = IdProductU232P9)) THEN
ELSIF ((dev.descriptor.idVendor = IdVendorMct) & (dev.descriptor.idProduct = IdProductU232P25)) THEN
ELSIF ((dev.descriptor.idVendor = IdVendorMct) & (dev.descriptor.idProduct = IdProductDUH3SP)) THEN
ELSIF ((dev.descriptor.idVendor = IdVendorBelkin) & (dev.descriptor.idProduct = IdProductF5U109)) THEN
ELSE
RETURN NIL;
END;
NEW(driver);
RETURN driver;
END Probe;
PROCEDURE Cleanup;
BEGIN
Usbdi.drivers.Remove(Name);
END Cleanup;
PROCEDURE Install*;
END Install;
BEGIN
Modules.InstallTermHandler(Cleanup);
Usbdi.drivers.Add(Probe, Name, Description, Priority)
END UsbRS232.
UsbRS232.Install ~ SystemTools.Free UsbRS232 ~