MODULE UsbPrinter;
IMPORT SYSTEM, KernelLog, Modules, Usbdi;
CONST
Name = "UsbPrinter";
Description = "USB Printing Device Class Driver";
Priority = 10;
Debug = TRUE;
Trace = TRUE;
StatusPaperEmpty = {5};
StatusSelected = {4};
StatusNoError = {3};
PrGetDeviceId = 0;
PrGetPortStatus = 1;
PrSoftReset = 2;
PitUnidirectional = 01H;
PitBidirectional = 02H;
Pit1284 = 03H;
PitVendorSpecific = 0FFH;
TYPE
Printer= OBJECT (Usbdi.Driver)
VAR
defaultpipe, bulkInPipe, bulkOutPipe : Usbdi.Pipe;
interfaceType : LONGINT;
deviceId : ARRAY 256 OF CHAR;
PROCEDURE Connect() : BOOLEAN;
BEGIN
defaultpipe := device.GetPipe(0);
IF defaultpipe = NIL THEN
IF Debug THEN KernelLog.String("UsbPrinter: Could not get default pipe."); KernelLog.Ln; END;
RETURN FALSE;
END;
bulkOutPipe := device.GetPipe(1);
IF bulkOutPipe = NIL THEN
IF Debug THEN KernelLog.String("UsbPrinter: Could not get bulk out pipe."); KernelLog.Ln; END;
RETURN FALSE;
END;
IF interfaceType # PitUnidirectional THEN
bulkInPipe := device.GetPipe(82H);
IF bulkInPipe = NIL THEN
IF Debug THEN KernelLog.String("UsbPrinter: Could not get bulk in pipe."); KernelLog.Ln; END;
RETURN FALSE;
END;
END;
IF ~GetDeviceId(deviceId, 0,0,0) THEN
IF Debug THEN KernelLog.String("UsbPrinter: Could not get device ID."); KernelLog.Ln; END;
RETURN FALSE;
END;
RETURN TRUE;
END Connect;
PROCEDURE Disconnect;
BEGIN
KernelLog.String("UsbPrinter: "); KernelLog.String(name); KernelLog.String(" disconnected."); KernelLog.Ln;
END Disconnect;
PROCEDURE GetDeviceId(VAR deviceId : ARRAY OF CHAR; config, intf, alt : LONGINT) : BOOLEAN;
VAR
buffer : Usbdi.BufferPtr;
wValue, wIndex, len, i : LONGINT;
string : POINTER TO ARRAY OF CHAR;
BEGIN
wValue := config;
wIndex := SYSTEM.LSH(intf, 8) + alt;
NEW(buffer, 2);
IF device.Request(Usbdi.ToHost + Usbdi.Class + Usbdi.Interface, PrGetDeviceId, wValue, wIndex, 2, buffer^) = Usbdi.Ok THEN
len := SYSTEM.VAL(LONGINT, ORD(buffer[0]))*100H + SYSTEM.VAL(LONGINT, ORD(buffer[1]));
NEW(buffer, len);
IF device.Request(Usbdi.ToHost + Usbdi.Class + Usbdi.Interface, PrGetDeviceId, wValue, wIndex, len, buffer^) = Usbdi.Ok THEN
NEW(string, len-2);
FOR i := 0 TO len-3 DO string[i] := buffer[i+2]; END;
COPY(string^, deviceId);
IF Trace THEN KernelLog.String("UsbPrinter: DeviceID: "); KernelLog.String(deviceId); KernelLog.Ln; END;
RETURN TRUE;
ELSIF Debug THEN KernelLog.String("UsbPrinter: Could not read device ID."); KernelLog.Ln;
END;
ELSIF Debug THEN KernelLog.String("UsbPrinter: GetDeviceID's first two bytes failed."); KernelLog.Ln;
END;
RETURN FALSE;
END GetDeviceId;
PROCEDURE GetPortStatus(VAR portstatus : SET) : BOOLEAN;
VAR buffer : Usbdi.BufferPtr;
BEGIN
NEW(buffer, 1);
IF device.Request(Usbdi.ToHost + Usbdi.Class + Usbdi.Interface, PrGetPortStatus, 0, interface.bInterfaceNumber, 1, buffer^) = Usbdi.Ok THEN
portstatus := SYSTEM.VAL(SET, buffer[0]);
IF Trace THEN ShowPrinterStatus(portstatus); END;
RETURN TRUE;
ELSE
IF Debug THEN KernelLog.String("UsbPrinter: GetPortStatus failed."); KernelLog.Ln; END;
RETURN FALSE;
END;
END GetPortStatus;
PROCEDURE SoftReset() : BOOLEAN;
VAR dummy : Usbdi.BufferPtr;
BEGIN
NEW(dummy, 1);
IF device.Request(Usbdi.ToDevice + Usbdi.Class + Usbdi.Interface, PrSoftReset, 0, interface.bInterfaceNumber, 0, dummy^) = Usbdi.Ok THEN
IF Trace THEN KernelLog.String("UsbPrinter: Printer resetted."); KernelLog.Ln; END;
RETURN TRUE;
ELSE
IF Debug THEN KernelLog.String("UsbPrinter: SoftReset failed."); KernelLog.Ln; END;
RETURN FALSE;
END;
END SoftReset;
END Printer;
PROCEDURE ShowPrinterStatus(status : SET);
BEGIN
KernelLog.String("UsbPrinter: Printer status: Paper: ");
IF status * StatusPaperEmpty # {} THEN KernelLog.String("Empty"); ELSE KernelLog.String("Not Empty"); END;
KernelLog.String(", Selected: ");
IF status * StatusSelected # {} THEN KernelLog.String("Selected"); ELSE KernelLog.String("Not Selected"); END;
KernelLog.String(", ");
IF status * StatusNoError # {} THEN KernelLog.String("No Error"); ELSE KernelLog.String("Error"); END;
KernelLog.Ln;
END ShowPrinterStatus;
PROCEDURE Probe(dev : Usbdi.UsbDevice; id : Usbdi.InterfaceDescriptor) : Usbdi.Driver;
VAR driver : Printer;
BEGIN
IF id.bInterfaceClass # 7 THEN RETURN NIL END;
IF id.bInterfaceSubClass # 1 THEN RETURN NIL END;
NEW(driver); driver.interfaceType := id.bInterfaceProtocol;
IF Trace THEN KernelLog.String("USB Printer found."); KernelLog.Ln; END;
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 UsbPrinter.