MODULE WMUsbInfo;
IMPORT
SYSTEM,
KernelLog, Strings, Streams, Modules, Kernel, Plugins, Codecs, Machine,
Usbdi, Usb, UsbHcdi,
WMTabComponents, WMComponents, WMStandardComponents, WMWindowManager, WMTrees, WMGraphics, WMRestorable, WMMessages;
CONST
WindowWidth = 700;
WindowHeight = 400;
WriterSize = 1024;
Debug = TRUE;
VendorIdFile = "WMUsbInfo.tar://usb.if";
ShowIcons = TRUE;
PollInterval = 200;
VmStandard = 0;
VmDetailed = 1;
VmPortStatus = 2;
VmDrivers = 3;
TYPE
KillerMsg = OBJECT
END KillerMsg;
Mode = POINTER TO RECORD;
mode : LONGINT;
END;
Driver = POINTER TO RECORD;
driver : Usbdi.Driver;
interface : LONGINT;
next : Driver;
END;
Window = OBJECT (WMComponents.FormWindow)
VAR
usbTree : WMTrees.Tree;
usbTreeView : WMTrees.TreeView;
usbSelected : WMTrees.TreeNode;
drivers : Driver;
drvTree : WMTrees.Tree;
drvTreeView : WMTrees.TreeView;
mainpanel, buttonpanel, treepanel, driverpanel : WMStandardComponents.Panel;
btnRefresh, btnProperties : WMStandardComponents.Button;
tabs : WMTabComponents.Tabs;
infoline : WMStandardComponents.Label;
viewmode : LONGINT;
string : ARRAY WriterSize OF CHAR;
lastNbrOfDriverEvents, lastNbrOfTopologyEvents : LONGINT;
dead, alive : BOOLEAN;
timer : Kernel.Timer;
PROCEDURE AddDeviceDescriptor(d : Usb.DeviceDescriptor; CONST nname: ARRAY OF CHAR; parent : WMTrees.TreeNode; isQualifier : BOOLEAN);
VAR dn, tn : WMTrees.TreeNode; w : Streams.StringWriter; i : LONGINT; vendor, class, subclass, protocol : Strings.String;
BEGIN
NEW(dn); NEW(w, WriterSize);
AddUsbNode(dn, parent, nname);
GetDeviceDescription(d.bDeviceClass, d.bDeviceSubClass, d.bDeviceProtocol, class, subclass, protocol);
vendor := GetVendorString(d.idVendor);
i := 0;
LOOP
NEW(tn); w.Reset;
CASE i OF
0: w.String("USB Version: "); w.Hex(SYSTEM.LSH(d.bcdUSB, -8) MOD 10H, -2); w.Char("."); w.Hex(d.bcdUSB MOD 10H, -2);
|1: w.String("Class: "); w.Hex(d.bDeviceClass, -2); w.Char("H");
IF class # NIL THEN w. String(" ("); w.String(class^); w.Char(")"); END;
|2: w.String("SubClass: "); w.Hex(d.bDeviceSubClass, -2); w.Char("H");
IF subclass # NIL THEN w. String(" ("); w.String(subclass^); w.Char(")"); END;
|3: w.String("Protocoll: "); w.Hex(d.bDeviceProtocol, -2); w.Char("H");
IF protocol # NIL THEN w. String(" ("); w.String(protocol^); w.Char(")"); END;
|4: w.String("idVendor: "); w.Hex(SYSTEM.LSH(d.idVendor, -8) MOD 100H, -2); w.Hex(d.idVendor MOD 100H, -2); w.Char("H");
IF vendor # NIL THEN w.String(" ("); w.String(vendor^); w.Char(")"); END;
|5: w.String("idProduct: "); w.Hex(SYSTEM.LSH(d.idProduct, -8) MOD 100H, -2); w.Hex(d.idProduct MOD 100H, -2); w.Char("H");
|6: w.String("Device Version: "); w.Hex(SYSTEM.LSH(d.bcdDevice, -8) MOD 10H, -2); w.Char("."); w.Hex(d.bcdDevice MOD 10H, -2);
|7: w.String("NumConfigurations: "); w.Int(d.bNumConfigurations, 0);
|8: w.String("iManufacturer: "); w.Int(d.iManufacturer, 0); w.String(" (");
IF d.iManufacturer = 0 THEN w.String("No string descriptor)");
ELSIF d.sManufacturer # NIL THEN w.String(d.sManufacturer^); w.Char(")");
ELSE w.String("Not parsed)");
END;
|9: w.String("iProduct: "); w.Int(d.iProduct, 0); w.String(" (");
IF d.iProduct = 0 THEN w.String("No string descriptor)");
ELSIF d.sProduct # NIL THEN w.String(d.sProduct^); w.Char(")");
ELSE w.String("Not parsed)");
END;
|10: w.String("iSerial: "); w.Int(d.iSerialNumber, 0); w.String(" (");
IF d.iSerialNumber = 0 THEN w.String("No string descriptor)");
ELSIF d.sSerialNumber # NIL THEN w.String(d.sSerialNumber^); w.Char(")");
ELSE w.String("Not parsed)");
END;
|11: w.String("MaxPacketSize0: "); w.Int(d.bMaxPacketSize0, 0); w.String(" Bytes");
END;
w.Get(string); AddUsbNode(tn, dn, string);
INC(i); IF (i > 11) OR (isQualifier & (i > 7)) THEN EXIT; END;
END;
END AddDeviceDescriptor;
PROCEDURE AddIad(iads : Usbdi.Iads; parent : WMTrees.TreeNode);
VAR dn, tn, in : WMTrees.TreeNode; w : Streams.StringWriter; c, s, p : Strings.String; j, k : LONGINT; i : Usb.InterfaceAssociationDescriptor;
BEGIN
NEW(dn); NEW(w, WriterSize);
AddUsbNode(dn, parent, "Interface Association Descriptors");
FOR k := 0 TO LEN(iads)-1 DO
NEW(in);
w.Reset; w.String("Interface Associtation Descriptor "); w.Int(k, 0); w.Get(string);
AddUsbNode(in, dn, string);
i := iads[k] (Usb.InterfaceAssociationDescriptor) ;
GetIadDescription(i.bFunctionClass, i.bFunctionSubClass, i.bFunctionProtocol, c, s, p);
FOR j := 0 TO 5 DO
NEW(tn); w.Reset;
CASE j OF
0: w.String("bFirstInterface: "); w.Int(i.bFirstInterface, 0);
|1: w.String("bInterfaceCount: "); w.Int(i.bInterfaceCount, 0);
|2: w.String("bFunctionClass: "); w.Int(i.bFunctionClass, 0);
IF c # NIL THEN w.String(" ("); w.String(c^); w.String(")"); END;
|3: w.String("bFunctionSubClass: "); w.Int(i.bFunctionSubClass, 0);
IF s # NIL THEN w.String(" ("); w.String(s^); w.String(")"); END;
|4: w.String("bFunctionProtocol: "); w.Int(i.bFunctionProtocol, 0);
IF p # NIL THEN w.String(" ("); w.String(p^); w.String(")"); END;
|5: w.String("iFunction: "); w.Int(i.iFunction, 0); w.String(" (");
IF i.iFunction = 0 THEN w.String("No string descriptor)");
ELSIF i.sFunction # NIL THEN w.String(i.sFunction^); w.Char(")");
ELSE w.String("Not parsed)");
END;
END;
w.Get(string); AddUsbNode(tn, in, string);
END;
END;
END AddIad;
PROCEDURE AddNonStandard(u : Usbdi.UnknownDescriptor ; intf : Usbdi.InterfaceDescriptor; parent : WMTrees.TreeNode);
VAR dn, tn : WMTrees.TreeNode; w : Streams.StringWriter;
BEGIN
IF u = NIL THEN RETURN; END;
NEW(dn); NEW(w, WriterSize);
AddUsbNode(dn, parent, "Non-Standard Descriptors");
WHILE(u # NIL) DO
IF intf.bInterfaceClass = 0EH THEN
AddVideoClass(u, intf, dn);
ELSIF intf.bInterfaceClass = 03H THEN
AddHidClass(u, intf, dn);
ELSE
NEW(tn); w.Reset;
w.String("Non-Standard Descriptor (Type: "); w.Hex(u.bDescriptorType, -2); w.Char("H");
w.String(", Length: "); w.Int(u.bLength, 0); w.String(")");
w.Get(string); AddUsbNode(tn, dn, string);
AddDescriptorData(u.descriptor^, dn);
END;
u := u.next;
END;
END AddNonStandard;
PROCEDURE AddDescriptorData(CONST data: ARRAY OF CHAR; parent : WMTrees.TreeNode);
VAR n : WMTrees.TreeNode; i : LONGINT; w : Streams.StringWriter;
BEGIN
NEW(n); NEW(w, WriterSize);
w.String("Data: ");
FOR i := 0 TO LEN(data)-1 DO
w.Hex(ORD(data[i]), -2); w.Char(" ");
END;
w.Get(string); AddUsbNode(n, parent, string);
END AddDescriptorData;
PROCEDURE AddHidClass(u : Usbdi.UnknownDescriptor; intf : Usbdi.InterfaceDescriptor; parent : WMTrees.TreeNode);
VAR w : Streams.StringWriter; cl, n, dn : WMTrees.TreeNode; i : LONGINT;
PROCEDURE AddDescriptorType(type : LONGINT; w : Streams.StringWriter);
BEGIN
CASE type OF
21H: w.String("(HID Descriptor)");
|22H: w.String("(Report Descriptor)");
|23H: w.String("(Physical Descriptor)");
ELSE
w.String("(Unknown)");
END;
END AddDescriptorType;
PROCEDURE AddClassDescriptor(offset : LONGINT);
BEGIN
NEW(n); w.Reset;
w.String("bDescriptorType: "); w.Hex(ORD(u.descriptor[offset]), -2); w.String("H ");
AddDescriptorType(ORD(u.descriptor[offset]), w);
w.String(", bDescriptorLength: ");
w.Int(ORD(u.descriptor[offset + 1]) + 10H*ORD(u.descriptor[offset + 2]), 0); w.String(" Bytes");
w.Get(string); AddUsbNode(n, cl, string);
END AddClassDescriptor;
BEGIN
NEW(dn); NEW(w, WriterSize);
AddUsbNode(dn, parent, "HID class-specific descriptor");
IF u.bLength >= 9 THEN
i := 0;
LOOP
NEW(n); w.Reset;
CASE i OF
0: w.String("HID Class Specification Release: ");
w.Hex(ORD(u.descriptor[3]), -2); w.Char("."); w.Hex(ORD(u.descriptor[2]), -2);
|1: w.String("Country Code: "); w.Int(ORD(u.descriptor[4]), 0);
IF ORD(u.descriptor[4]) = 0 THEN w.String(" (Not Supported)"); END;
|2: w.String("bNumDescriptors: "); w.Int(ORD(u.descriptor[5]), 0);
END;
INC(i);
w.Get(string); AddUsbNode(n, dn, string);
IF i > 2 THEN EXIT; END;
END;
NEW(cl); AddUsbNode(cl, dn, "Class Descriptors");
i := 6;
LOOP
AddClassDescriptor(i); INC(i, 3);
IF i >= LEN(u.descriptor) - 3 THEN EXIT; END;
END;
ELSE
NEW(n); w.Reset; w.String("Parse Error: Descriptor < 9 Bytes"); w.Get(string);
AddUsbNode(n, dn, string);
END;
END AddHidClass;
PROCEDURE AddVideoClass(u : Usbdi.UnknownDescriptor; intf : Usbdi.InterfaceDescriptor; parent : WMTrees.TreeNode);
VAR subtype : LONGINT; v, w : Streams.StringWriter; tn, n : WMTrees.TreeNode;
PROCEDURE AddVCHeader(u : Usbdi.UnknownDescriptor; parent : WMTrees.TreeNode);
VAR n : WMTrees.TreeNode; i : LONGINT; w : Streams.StringWriter;
BEGIN
ASSERT(LEN(u.descriptor) >= 12);
NEW(w, WriterSize);
FOR i := 1 TO 4 DO
NEW(n); w.Reset;
CASE i OF
1: w.String("bcdVDC: "); w.Hex(ORD(u.descriptor[4]), -2); w.Char("."); w.Hex(ORD(u.descriptor[3]), -2);
|2: w.String("wTotalLength: "); w.Int(ORD(u.descriptor[5]) + 100H*ORD(u.descriptor[6]), 0);
|3: w.String("dwClockFrequency: ");
w.Int(ORD(u.descriptor[7]) + 100H*ORD(u.descriptor[8]) + 10000H*ORD(u.descriptor[9])
+1000000H*ORD(u.descriptor[10]), 0); w.String(" Hz");
|4: w.String("bInCollection: "); w.Int(ORD(u.descriptor[11]), 0);
END;
w.Get(string); AddUsbNode(n, parent, string);
END;
FOR i := 12 TO LEN(u.descriptor)-1 DO
NEW(n); w.Reset;
w.String("baInterfaceNr("); w.Int(i-11, 0); w.String("): ");
w.Int(ORD(u.descriptor[i]), 0);
w.Get(string); AddUsbNode(n, parent, string);
END;
END AddVCHeader;
PROCEDURE AddTerminal(u : Usbdi.UnknownDescriptor; parent : WMTrees.TreeNode);
VAR n : WMTrees.TreeNode; i, subtype : LONGINT; w : Streams.StringWriter;
BEGIN
NEW(w, WriterSize);
FOR i := 1 TO 3 DO
NEW(n); w.Reset;
CASE i OF
1: w.String("bTerminalID: "); w.Int(ORD(u.descriptor[3]), 0);
|2: w.String("wTerminalType: "); subtype := ORD(u.descriptor[4]) + 100H*ORD(u.descriptor[5]);
w.Int(subtype, 0); w.String(" (");
IF subtype = 100H THEN w.String("Vendor-Specific Terminal)");
ELSIF subtype = 101H THEN w.String("Streaming Terminal)");
ELSIF subtype = 200H THEN w.String("Vendor-Specific Input Terminal)");
ELSIF subtype = 201H THEN w.String("Camera Input Terminal)");
ELSIF subtype = 202H THEN w.String("Media Transport Inpurt Terminal)");
ELSIF subtype = 300H THEN w.String("Vendor-Specific Output Terminal)");
ELSIF subtype = 301H THEN w.String("Display Output Terminal)");
ELSIF subtype = 302H THEN w.String("Media Transport Output Terminal)");
ELSIF subtype = 400H THEN w.String("Vendor-Specific External Terminal)");
ELSIF subtype = 401H THEN w.String("Composite Connector)");
ELSIF subtype = 402H THEN w.String("S-Video Connector)");
ELSIF subtype = 403H THEN w.String("Component Connector)");
ELSE
w.String("Unknown Terminal Type)");
END;
|3: w.String("bAssocTerminal: "); w.Int(ORD(u.descriptor[6]), 0);
END;
w.Get(string); AddUsbNode(n, parent, string);
END;
NEW(n); w.Reset;
subtype := ORD(u.descriptor[2]);
IF subtype = 02H THEN
w.String("iTerminal: "); w.Int(ORD(u.descriptor[7]), 0);
w.Get(string); AddUsbNode(n, parent, string);
ELSIF subtype = 03H THEN
w.String("bSourceID: "); w.Int(ORD(u.descriptor[8]), 0);
w.Get(string); AddUsbNode(n, parent, string);
NEW(n); w.Reset;
w.String("iTerminal: "); w.Int(ORD(u.descriptor[8]), 0);
w.Get(string); AddUsbNode(n, parent, string);
END;
AddDescriptorData(u.descriptor^, parent);
END AddTerminal;
PROCEDURE AddUnit(u : Usbdi.UnknownDescriptor; parent : WMTrees.TreeNode);
VAR n : WMTrees.TreeNode; i, j, subtype : LONGINT; w : Streams.StringWriter;
BEGIN
NEW(n); NEW(w, WriterSize);
w.String("bUnitID: "); w.Int(ORD(u.descriptor[3]), 0);
w.Get(string); AddUsbNode(n, parent, string);
subtype := ORD(u.descriptor[2]);
IF subtype = 4 THEN
NEW(n); w.Reset;
w.String("bNrInPins: "); w.Int(ORD(u.descriptor[4]), 0);
w.Get(string); AddUsbNode(n, parent, string);
FOR i := 5 TO LEN(u.descriptor)-2 DO
NEW(n); w.Reset;
w.String("baSourceID("); w.Int(i-4, 0); w.String("): "); w.Int(ORD(u.descriptor[i]), 0);
w.Get(string); AddUsbNode(n, parent, string);
END;
NEW(n); w.Reset;
w.String("iSelector: "); w.Int(ORD(u.descriptor[LEN(u.descriptor)-1]), 0);
w.Get(string); AddUsbNode(n, parent, string);
ELSIF subtype = 6 THEN
FOR i := 1 TO 7 DO
NEW(n); w.Reset;
CASE i OF
1: w.String("guidExtensionCode: ");
FOR j := 0 TO 15 DO w.Hex(ORD(u.descriptor[4+j]), -2); w.Char(" "); END;
|2: w.String("bNumControls: "); w.Int(ORD(u.descriptor[20]), 0);
|3: w.String("bNrInPins: "); w.Int(ORD(u.descriptor[21]), 0);
|4: FOR j := 0 TO ORD(u.descriptor[21])-1 DO
w.String("baSourceID("); w.Int(j+1, 0); w.String("): "); w.Int(ORD(u.descriptor[22+j]), 0);
END;
|5: w.String("bControlSize: "); w.Int(ORD(u.descriptor[22 + ORD(u.descriptor[21])]), 0);
|6: FOR j := 0 TO ORD(u.descriptor[22 + ORD(u.descriptor[21])])-1 DO
w.String("bmControls("); w.Int(j+1, 0); w.String("): ");
w.Int(ORD(u.descriptor[23 + ORD(u.descriptor[21])]), 0);
END;
|7: w.String("iExtension: "); w.Int(ORD(u.descriptor[LEN(u.descriptor)-1]), 0);
END;
w.Get(string); AddUsbNode(n, parent, string);
END;
ELSE
AddDescriptorData(u.descriptor^, parent);
END;
END AddUnit;
PROCEDURE AddOutputHeader(u : Usbdi.UnknownDescriptor; parent : WMTrees.TreeNode);
VAR n : WMTrees.TreeNode; i : LONGINT; w : Streams.StringWriter;
BEGIN
NEW(w, WriterSize);
FOR i := 1 TO 4 DO
NEW(n); w.Reset;
CASE i OF
1: w.String("bNumFormats: "); w.Int(ORD(u.descriptor[3]), 0);
|2: w.String("wTotalLength: "); w.Int(ORD(u.descriptor[4]) + 100H*ORD(u.descriptor[5]), 0);
|3: w.String("bEndpointAddress: "); w.Int(ORD(u.descriptor[6]), 0);
|4: w.String("bTerminalLink: "); w.Int(ORD(u.descriptor[7]), 0);
END;
w.Get(string); AddUsbNode(n, parent, string);
END;
END AddOutputHeader;
PROCEDURE AddInputHeader(u : Usbdi.UnknownDescriptor; parent : WMTrees.TreeNode);
VAR n : WMTrees.TreeNode; i, temp : LONGINT; w : Streams.StringWriter;
BEGIN
NEW(w, WriterSize);
FOR i := 1 TO 9 DO
NEW(n); w.Reset;
CASE i OF
1: w.String("bNumFormats: "); w.Int(ORD(u.descriptor[3]), 0);
|2: w.String("wTotalLength: "); w.Int(ORD(u.descriptor[4]) + 100H*ORD(u.descriptor[5]), 0);
|3: w.String("bEndpointAddress: "); w.Int(ORD(u.descriptor[6]), 0);
|4: w.String("bmInfo: "); w.Int(ORD(u.descriptor[7]), 0);
|5: w.String("bTerminalLink: "); w.Int(ORD(u.descriptor[8]), 0);
|6: w.String("bStillCaptureMethod: "); temp := ORD(u.descriptor[9]); w.Int(temp, 0);
IF temp = 0 THEN w.String(" (None)");
ELSIF temp = 1 THEN w.String(" (Method 1)");
ELSIF temp = 2 THEN w.String(" (Method 2)");
ELSIF temp = 3 THEN w.String(" (Method 3)");
ELSE w.String(" (Unknown)");
END;
|7: w.String("bTriggerSupport: "); temp := ORD(u.descriptor[10]); w.Int(temp, 0);
IF temp = 0 THEN w.String(" (Not supported)");
ELSIF temp = 1 THEN w.String(" (Supported)");
ELSE w.String(" (Unknown)");
END;
|8: w.String("bTriggerUsage: "); temp :=ORD(u.descriptor[11]); w.Int(temp, 0);
IF ORD(u.descriptor[10]) = 0 THEN w.String(" (No Trigger Support)");
ELSIF temp = 0 THEN w.String(" (Initiate Still Image Captue)");
ELSIF temp = 1 THEN w.String(" (General Purpose Button Event)");
ELSE w.String(" (Unknown)");
END;
|9: w.String("bControlSize: "); w.Int(ORD(u.descriptor[12]), 0);
END;
w.Get(string); AddUsbNode(n, parent, string);
END;
FOR i := 13 TO LEN(u.descriptor)-1 DO
NEW(n); w.Reset;
w.String("bmaControls("); w.Int(i-12, 0); w.String("): "); w.Set(SYSTEM.VAL(SET, u.descriptor[i]));
w.Get(string); AddUsbNode(n, parent, string);
END;
END AddInputHeader;
PROCEDURE AddVcInterruptEp(u : Usbdi.UnknownDescriptor; parent : WMTrees.TreeNode);
VAR wMaxTransferSize : LONGINT; n : WMTrees.TreeNode; w : Streams.StringWriter;
BEGIN
NEW(n); NEW(w, WriterSize);
IF (LEN(u.descriptor) = 5) THEN
wMaxTransferSize := ORD(u.descriptor[3]) + 100H*ORD(u.descriptor[4]);
w.String("wMaxTransferSize: "); w.Int(wMaxTransferSize, 0);
ELSE
w.String("Parse Error (Length#5)");
END;
w.Get(string); AddUsbNode(n, parent, string);
END AddVcInterruptEp;
PROCEDURE AddLength(u : Usbdi.UnknownDescriptor; parent : WMTrees.TreeNode);
VAR n : WMTrees.TreeNode; w : Streams.StringWriter;
BEGIN
NEW(n); NEW(w, WriterSize);
w.String("bLength: "); w.Int(u.bLength, 0); w.String(" Bytes");
w.Get(string); AddUsbNode(n, parent, string);
END AddLength;
BEGIN
NEW(tn); NEW(w, WriterSize); NEW(v, WriterSize);
w.String("Video Class-Specific ");
IF u.bDescriptorType = 020H THEN
w.String("Undefined Descriptor"); AddLength(u, tn); AddDescriptorData(u.descriptor^, tn);
ELSIF u.bDescriptorType = 021H THEN
w.String("Device Descriptor"); AddLength(u, tn); AddDescriptorData(u.descriptor^, tn);
ELSIF u.bDescriptorType = 022H THEN
w.String("Configuration Descriptor"); AddLength(u, tn); AddDescriptorData(u.descriptor^, tn);
ELSIF u.bDescriptorType = 023H THEN
w.String("String Descriptor"); AddLength(u, tn); AddDescriptorData(u.descriptor^, tn);
ELSIF u.bDescriptorType = 024H THEN
subtype := ORD(u.descriptor[2]);
IF intf.bInterfaceSubClass = 01H THEN
w.String("Video Control Interface Descriptor: "); AddLength(u, tn);
CASE subtype OF
0: w.String("Undefined Descriptor"); AddDescriptorData(u.descriptor^, tn);
|1: w.String("VC Header"); AddVCHeader(u, tn);
|2: w.String("VC Input Terminal"); AddTerminal(u, tn);
|3: w.String( "VC Output Terminal"); AddTerminal(u, tn);
|4: w.String( "VC Selector Unit"); AddUnit(u, tn);
|5: w.String( "VC Processing Unit"); AddUnit(u, tn);
|6: w.String("VC Extension Unit"); AddUnit(u, tn);
ELSE
w.String("Unknown");
v.String("Unknown (Type: "); v.Int(u.bDescriptorType, 0); v.String(", Length: "); v.Int(u.bLength, 0); v.String(")");
v.Get(string); AddUsbNode(n, tn, string);
AddDescriptorData(u.descriptor^, tn);
END;
ELSIF intf.bInterfaceSubClass = 02H THEN
w.String("Video Streaming Interface Descriptor: "); AddLength(u, tn);
CASE subtype OF
0: w.String("Undefined Descriptor");
|1: w.String("VS Input Header"); AddInputHeader(u, tn);
|2: w.String("VS Output Header"); AddOutputHeader(u, tn);
|3: w.String("VS Still Image Frame"); AddDescriptorData(u.descriptor^, tn);
|4: w.String("VS Format Uncompressed"); AddDescriptorData(u.descriptor^, tn);
|5: w.String("VS Frame Uncompressed"); AddDescriptorData(u.descriptor^, tn);
|6: w.String("VS Format MJPEG"); AddDescriptorData(u.descriptor^, tn);
|7: w.String("VS Frame MJPEG"); AddDescriptorData(u.descriptor^, tn);
|8: w.String("VS Format MPEG1"); AddDescriptorData(u.descriptor^, tn);
|9: w.String("VS Format MPEG2 PS"); AddDescriptorData(u.descriptor^, tn);
|10: w.String("VS Format MPEG2 TS"); AddDescriptorData(u.descriptor^, tn);
|11: w.String("VS Format MPEG4 SL"); AddDescriptorData(u.descriptor^, tn);
|12: w.String("VS Format DV"); AddDescriptorData(u.descriptor^, tn);
|13: w.String("VS Color Format"); AddDescriptorData(u.descriptor^, tn);
|14: w.String("VS Format Vendor"); AddDescriptorData(u.descriptor^, tn);
|15: w.String("VS Frame Vendor"); AddDescriptorData(u.descriptor^, tn);
ELSE
w.String("Unknown");
v.String("Unknown (Type: "); v.Int(u.bDescriptorType, 0); v.String(", Length: "); v.Int(u.bLength, 0); v.String(")");
v.Get(string); AddUsbNode(n, tn, string);
AddDescriptorData(u.descriptor^, tn);
END;
ELSE
w.String("Undefined Interface Descriptor"); AddLength(u, tn); AddDescriptorData(u.descriptor^, tn);
END;
ELSIF u.bDescriptorType = 025H THEN
subtype := ORD(u.descriptor[2]);
w.String("Endpoint Descriptor"); AddLength(u, tn);
NEW(n);
CASE subtype OF
0: AddUsbNode(n, tn, "Endpoint Undefined"); AddDescriptorData(u.descriptor^, tn);
|1: AddUsbNode(n, tn, "Endpoint General"); AddDescriptorData(u.descriptor^, tn);
|2: AddUsbNode(n, tn, "Endpoint"); AddDescriptorData(u.descriptor^, tn);
|3: AddUsbNode(n, tn, "Endpoint Interrupt"); AddVcInterruptEp(u, tn);
ELSE
v.String("Unknown (Type: "); v.Int(u.bDescriptorType, 0); v.String(", Length: "); v.Int(u.bLength, 0); v.String(")");
v.Get(string); AddUsbNode(n, tn, string);
AddDescriptorData(u.descriptor^, tn);
END;
ELSE
END;
w.Get(string); AddUsbNode(tn, parent, string);
END AddVideoClass;
PROCEDURE AddConfiguration(c : Usb.ConfigurationDescriptor; nbr: SYSTEM.ADDRESS; parent : WMTrees.TreeNode);
VAR dn, tn : WMTrees.TreeNode; w : Streams.StringWriter; i : LONGINT;
BEGIN
NEW(dn); NEW(w, WriterSize);
w.String("Configuration "); w.Address(nbr); w.Get(string);
AddUsbNode(dn, parent, string);
IF c.iads # NIL THEN
AddIad(c.iads, dn);
END;
IF c.interfaces # NIL THEN
FOR i := 0 TO LEN(c.interfaces)-1 DO AddInterface(c.interfaces[i] (Usb.InterfaceDescriptor), i, dn); END;
END;
FOR i := 0 TO 6 DO
NEW(tn); w.Reset;
CASE i OF
0: w.String("bNumInterfaces: "); w.Int(c.bNumInterfaces, 0);
|1: w.String("bConfigurationValue: "); w.Int(c.bConfigurationValue, 0);
|2: w.String("iConfiguration: "); w.Int(c.iConfiguration, 0); w.String(" (");
IF c.iConfiguration = 0 THEN w.String("No string descriptor)");
ELSIF c.sConfiguration # NIL THEN w.String(c.sConfiguration^); w.Char(")");
ELSE w.String("Not parsed)");
END;
|3: w.String("Max Power: "); w.Int(c.bMaxPower, 0); w.String("mA");
|4: w.String("Total Length: "); w.Int(c.wTotalLength, 0); w.String(" Bytes");
|5: w.String("Can be Self-Powered: "); IF c.selfPowered THEN w.String("Yes"); ELSE w.String("No"); END;
|6: w.String("Remote Wakeup support: "); IF c.remoteWakeup THEN w.String("Yes"); ELSE w.String("No"); END;
END;
w.Get(string); AddUsbNode(tn, dn, string);
END;
END AddConfiguration;
PROCEDURE AddInterface(i : Usb.InterfaceDescriptor; nbr : LONGINT; parent : WMTrees.TreeNode);
VAR dn, tn, en : WMTrees.TreeNode; w : Streams.StringWriter; j : LONGINT; class, subclass, protocol : Strings.String;
BEGIN
NEW(dn);
NEW(w, WriterSize);
IF i.bAlternateSetting # 0 THEN w.String("Alternate "); END;
w.String("Interface "); w.Int(nbr, 0); w.Get(string);
AddUsbNode(dn, parent, string);
GetInterfaceDescription(i.bInterfaceClass, i.bInterfaceSubClass, i.bInterfaceProtocol, class, subclass, protocol);
IF i.unknown # NIL THEN
AddNonStandard(i.unknown, i, dn);
END;
IF i.endpoints # NIL THEN
NEW(en); AddUsbNode(en, dn, "Endpoints");
FOR j := 0 TO LEN(i.endpoints)-1 DO AddEndpoint(i.endpoints[j] (Usb.EndpointDescriptor), i , j+1, en); END;
END;
FOR j := 0 TO 8 DO
NEW(tn); w.Reset;
CASE j OF
0: w.String("Interface Number: "); w.Int(i.bInterfaceNumber, 0);
|1: w.String("Alternate Setting: "); w.Int(i.bAlternateSetting, 0);
|2: w.String("Class: "); w.Hex(i.bInterfaceClass, -2); w.Char("H");
IF class # NIL THEN w.String(" ("); w.String(class^); w.Char(")"); END;
|3: w.String("SubClass: "); w.Hex(i.bInterfaceSubClass, -2); w.Char("H");
IF subclass # NIL THEN w.String(" ("); w.String(subclass^); w.Char(")"); END;
|4: w.String("Protocol: "); w.Hex(i.bInterfaceProtocol, -2); w.Char("H");
IF protocol # NIL THEN w.String(" ("); w.String(protocol^); w.Char(")"); END;
|5: w.String("NumAlternateInterfaces: "); w.Int(i.numAlternateInterfaces , 0);
|6: w.String("NumEndPoints: "); w.Int(i.bNumEndpoints , 0);
|7: w.String("iInterface: "); w.Int(i.iInterface, 0); w.String(" (");
IF i.iInterface = 0 THEN w.String("No string descriptor)");
ELSIF i.sInterface # NIL THEN w.String(i.sInterface^); w.Char(")");
ELSE w.String("Not parsed)");
END;
|8: w.String("Driver: ");
IF i.driver = NIL THEN w.String("No driver installed");
ELSE
w.String(i.driver.name); w.String(" ("); w.String(i.driver.desc); w.Char(")");
END;
END;
w.Get(string); AddUsbNode(tn, dn, string);
END;
IF i.alternateInterfaces # NIL THEN
FOR j := 0 TO LEN(i.alternateInterfaces)-1 DO
AddInterface(i.alternateInterfaces[j] (Usb.InterfaceDescriptor), j, dn);
END;
END;
END AddInterface;
PROCEDURE AddEndpoint(e : Usb.EndpointDescriptor;intf : Usbdi.InterfaceDescriptor; nbr : LONGINT; parent : WMTrees.TreeNode);
VAR dn : WMTrees.TreeNode; w : Streams.StringWriter; i : LONGINT;
BEGIN
NEW(dn); NEW(w, WriterSize);
FOR i := 0 TO 4 DO
CASE i OF
0: w.String("Endpoint Number: "); w.Int(e.bEndpointAddress, 0);
IF SYSTEM.VAL(SET, e.bmAttributes) * {0,1} # {} THEN
IF SYSTEM.VAL(SET, e.bEndpointAddress) * {7} = {} THEN w.String(" (OUT)"); ELSE w.String(" (IN)"); END;
END;
|1: w.String(", Type: ");
CASE SYSTEM.VAL(LONGINT, e.bmAttributes * {0..1}) OF
0: w.String("Control");
|1: w.String("Isochronous");
|2: w.String("Bulk");
|3: w.String("Interrupt");
END;
|2: w.String(", MaxPacketSize: "); w.Int(e.wMaxPacketSize, 0); w.String("Bytes");
|3: w.String(" (Mult: "); w.Int(e.mult, 0); w.String(")");
|4: w.String(", Interval: "); w.Int(e.bInterval, 0); w.String("ms");
END;
END;
IF SYSTEM.VAL(LONGINT, e.bmAttributes * {0..1}) = 1 THEN
w.String(" (Synchronization: ");
CASE SYSTEM.VAL(LONGINT, SYSTEM.LSH(e.bmAttributes * {2..3}, -2)) OF
0: w.String("None");
|1: w.String("Asynchronous");
|2: w.String("Adaptive");
|3: w.String("Synchronous");
END;
w.String(", Usage: ");
CASE SYSTEM.VAL(LONGINT, SYSTEM.LSH(e.bmAttributes * {4..5}, -4)) OF
0: w.String("Data");
|1: w.String("Feedback");
|2: w.String("Implicit Feedback Data");
|3: w.String("Reserved");
END;
w.Char(")");
END;
w.Get(string); AddUsbNode(dn, parent, string);
IF e.unknown # NIL THEN
AddNonStandard(e.unknown, intf, parent);
END;
END AddEndpoint;
PROCEDURE ViewModeDetailed(dev : Usb.UsbDevice; parent : WMTrees.TreeNode; w : Streams.StringWriter);
VAR i : SYSTEM.ADDRESS; cn : WMTrees.TreeNode;
BEGIN
ASSERT((dev # NIL) & (parent # NIL) & (w # NIL) );
ASSERT(viewmode = VmDetailed);
IF (dev.parent = dev) THEN
i := Machine.PhysicalAdr(dev.controller.iobase, 4);
IF (i = -1) & Debug THEN KernelLog.String("UsbInfo: Address mapping error."); KernelLog.Ln; END;
w.String(" (I/O base address: "); w.Hex(i, -8); w.String("H, Interrupt Line: ");
w.Int(dev.controller.irq, 0); w.Char(")");
ELSE
w.String(" (");
IF dev.speed = UsbHcdi.LowSpeed THEN w.String("LowSpeed");
ELSIF dev.speed = UsbHcdi.FullSpeed THEN w.String("FullSpeed");
ELSIF dev.speed = UsbHcdi.HighSpeed THEN w.String("HighSpeed");
ELSE w.String("Speed unknown!");
END;
w.String(", Address: "); w.Int(dev.address, 0); w.Char(")");
AddDeviceDescriptor(dev.descriptor (Usb.DeviceDescriptor), "Device Descriptor", parent, FALSE);
IF dev.qualifier # NIL THEN
AddDeviceDescriptor(dev.qualifier (Usb.DeviceDescriptor), "Device Qualifier", parent, TRUE);
END;
NEW(cn);
AddUsbNode(cn, parent, "Configurations");
FOR i := 0 TO LEN(dev.configurations)-1 DO
AddConfiguration(dev.configurations[i] (Usb.ConfigurationDescriptor), i, cn);
END;
IF dev.otherconfigurations # NIL THEN
NEW(cn);
AddUsbNode(cn, parent, "Other-speed Configurations");
FOR i := 0 TO LEN(dev.configurations)-1 DO
AddConfiguration(dev.otherconfigurations[i] (Usb.ConfigurationDescriptor), i, cn);
END;
END;
END;
END ViewModeDetailed;
PROCEDURE Dev2Node(dev : Usb.UsbDevice; port : LONGINT; parent : WMTrees.TreeNode);
VAR tn, pn : WMTrees.TreeNode; w : Streams.StringWriter; i : LONGINT; deviceAttached : BOOLEAN;
image : WMGraphics.Image;
BEGIN
ASSERT(dev # NIL);
NEW(tn); NEW(w, WriterSize);
usbTree.Acquire;
usbTree.SetNodeData(tn, dev);
usbTree.Release;
IF ShowIcons THEN
image := GetImage(dev);
IF image # NIL THEN usbTree.Acquire; usbTree.SetNodeImage(tn, image); usbTree.Release; END;
END;
IF dev.parent = dev THEN w.String("Root");
ELSE w.String("Port "); w.Int(port, 0); w.String(": ");
END;
IF dev.hubFlag THEN w.String("Hub with "); w.Int(dev.nbrOfPorts, 0); w.String(" ports: "); END;
IF ((dev.descriptor(Usb.DeviceDescriptor).sManufacturer # NIL) OR (dev.descriptor(Usb.DeviceDescriptor).sProduct # NIL)) THEN
IF dev.descriptor(Usb.DeviceDescriptor).sManufacturer # NIL THEN w.String(dev.descriptor(Usb.DeviceDescriptor).sManufacturer^); w.Char(" "); END;
IF dev.descriptor(Usb.DeviceDescriptor).sProduct # NIL THEN w.String(dev.descriptor(Usb.DeviceDescriptor).sProduct^); END;
ELSE
w.String("Unnamed device");
END;
IF viewmode = VmDetailed THEN ViewModeDetailed(dev, tn, w); END;
w.Get(string);
AddUsbNode(tn, parent, string);
usbTree.Acquire; usbTree.ExpandToRoot(tn); usbTree.Release;
IF dev.hubFlag THEN
pn := tn;
deviceAttached := FALSE;
FOR i := 0 TO dev.nbrOfPorts-1 DO
IF dev.deviceAtPort[i] # NIL THEN
Dev2Node(dev.deviceAtPort[i], i+1, pn);
deviceAttached := TRUE;
END;
END;
IF ~deviceAttached THEN
NEW(tn);
AddUsbNode(tn, pn, "No devices attached");
END;
END;
END Dev2Node;
PROCEDURE BuildTree;
VAR i : LONGINT; tn, node : WMTrees.TreeNode; rootHubs : Usb.RootHubArray;
BEGIN
usbTreeView.visible.Set(FALSE);
usbTree.Acquire;
NEW(tn);
usbTree.SetRoot(tn);
usbTree.SetNodeCaption(tn, Strings.NewString("Universal Serial Bus(ses)"));
usbTree.Release;
Usb.GetRootHubs(rootHubs);
IF rootHubs # NIL THEN
FOR i := 0 TO LEN(rootHubs)-1 DO
Dev2Node(rootHubs[i], i+1, tn);
rootHubs[i] := NIL;
END;
ELSE
NEW(node);
AddUsbNode(node, tn, "No USB host controller drivers installed");
usbTree.Acquire; usbTree.ExpandToRoot(node); usbTree.Release;
END;
usbTreeView.visible.Set(TRUE);
END BuildTree;
PROCEDURE BuildDrivers;
VAR i, j : LONGINT; tn, node, n : WMTrees.TreeNode;
drivers : POINTER TO ARRAY OF Usb.RegisteredDriver; driverFound : BOOLEAN;
drv : Usb.RegisteredDriver; plugin : Plugins.Plugin;
w : Streams.StringWriter; dev : Usb.UsbDevice;
BEGIN
drvTreeView.visible.Set(FALSE);
drvTree.Acquire;
NEW(tn);
drvTree.SetRoot(tn);
drvTree.SetNodeCaption(tn, Strings.NewString("Registered USB device drivers"));
drvTree.Release;
NEW(drivers, LEN(Usb.drivers.drivers));
FOR i := 0 TO LEN(Usb.drivers.drivers)-1 DO drivers[i] := Usb.drivers.drivers[i]; END;
driverFound := FALSE; NEW(w, WriterSize);
FOR i := 0 TO LEN(drivers)-1 DO
IF drivers[i] # NIL THEN
drv := drivers[i].next;
WHILE drv # NIL
driverFound := TRUE;
NEW(node);
w.Reset; w.String(drv.name); w.String(" ("); w.String(drv.desc); w.String(") ");
w.String("Priority: "); w.Int(i, 0);
w.Get(string);
AddDrvNode(node, tn, string);
drvTree.Acquire; drvTree.ExpandToRoot(node); drvTree.Release;
FOR j := 0 TO 99 DO
IF drv.usedSuffix[j] THEN
plugin := Usb.usbDrivers.Get(Usb.drivers.AddSuffix(drv.name, j));
IF plugin # NIL THEN
NEW(n);
w.Reset; w.String("Instance: "); w.String(plugin.name);
w.String(" assigned to ");
dev := plugin(Usbdi.Driver).device (Usb.UsbDevice);
IF dev # NIL THEN
IF (dev.descriptor(Usb.DeviceDescriptor).sManufacturer # NIL) OR (dev.descriptor(Usb.DeviceDescriptor).sProduct # NIL) THEN
IF dev.descriptor(Usb.DeviceDescriptor).sManufacturer # NIL THEN w.String(dev.descriptor(Usb.DeviceDescriptor).sManufacturer^); w.Char(" ");END;
IF dev.descriptor(Usb.DeviceDescriptor).sProduct # NIL THEN w.String(dev.descriptor(Usb.DeviceDescriptor).sProduct^); END;
ELSE
w.String("Unnamed device");
END;
ELSE
w.String("no device!?!");
END;
w.Get(string); AddDrvNode(n, node, string);
drvTree.Acquire; drvTree.ExpandToRoot(n); drvTree.Release;
END;
END;
END;
drv := drv.next;
END;
END;
END;
IF ~driverFound THEN
NEW(node);
AddDrvNode(node, tn, "No USB device drivers registered");
drvTree.Acquire; drvTree.ExpandToRoot(node); drvTree.Release;
END;
drvTreeView.visible.Set(TRUE);
END BuildDrivers;
PROCEDURE GetDriversOf(dev : Usb.UsbDevice) : Driver;
VAR drivers, d, temp : Driver; con : Usb.ConfigurationDescriptor; i : LONGINT;
BEGIN
IF dev # NIL THEN
con := dev.actConfiguration (Usb.ConfigurationDescriptor);
FOR i := 0 TO LEN(con.interfaces)-1 DO
IF con.interfaces[i](Usb.InterfaceDescriptor).driver # NIL THEN
IF drivers = NIL THEN
NEW(drivers); drivers.interface := i;
drivers.driver := con.interfaces[i](Usb.InterfaceDescriptor).driver;
ELSE
NEW(d); d.interface := i;
d.driver := con.interfaces[i](Usb.InterfaceDescriptor).driver;
temp := drivers; WHILE(temp.next # NIL) DO temp := temp.next; END;
temp.next := d;
END;
END;
END;
END;
RETURN drivers;
END GetDriversOf;
PROCEDURE GetUsbInfo(VAR nbrOfRootHubs, nbrOfPorts, nbrOfDevices : LONGINT);
VAR i : LONGINT; rootHubs : Usb.RootHubArray;
PROCEDURE ProcessHub(hub : Usb.UsbDevice; VAR nbrOfPorts, nbrOfDevices : LONGINT);
VAR i : LONGINT; dev : Usb.UsbDevice;
BEGIN
ASSERT((hub # NIL) & (hub.hubFlag = TRUE) & (hub.deviceAtPort # NIL));
INC(nbrOfPorts, LEN(hub.deviceAtPort));
FOR i := 0 TO LEN(hub.deviceAtPort)-1 DO
dev := hub.deviceAtPort[i];
IF (dev # NIL) THEN
INC(nbrOfDevices);
IF dev.hubFlag THEN ProcessHub(hub.deviceAtPort[i], nbrOfPorts, nbrOfDevices); END;
END;
END;
END ProcessHub;
BEGIN
Usb.GetRootHubs(rootHubs);
IF rootHubs # NIL THEN
nbrOfRootHubs := LEN(rootHubs); nbrOfPorts := 0; nbrOfDevices := 0;
FOR i := 0 TO LEN(rootHubs)-1 DO
ProcessHub(rootHubs[i], nbrOfPorts, nbrOfDevices);
rootHubs[i] := NIL;
END;
ELSE
nbrOfRootHubs := 0; nbrOfPorts := 0; nbrOfDevices := 0;
END;
END GetUsbInfo;
PROCEDURE BuildInfoLine;
VAR w : Streams.StringWriter; nbrOfRootHubs, nbrOfPorts, nbrOfDevices : LONGINT;
BEGIN
NEW(w, WriterSize);
GetUsbInfo(nbrOfRootHubs, nbrOfPorts, nbrOfDevices);
IF nbrOfRootHubs = 0 THEN
w.String(" No USB host controllers found");
ELSE
w.String(" Root Hubs: "); w.Int(nbrOfRootHubs, 0);
w.String(" Total port count: "); w.Int(nbrOfPorts, 0);
w.String(" Devices connected: "); w.Int(nbrOfDevices, 0);
END;
w.Get(string);
infoline.caption.Set(Strings.NewString(string));
END BuildInfoLine;
PROCEDURE ButtonHandler(sender, data : ANY);
VAR btn : WMStandardComponents.Button;
BEGIN
btn := sender (WMStandardComponents.Button);
IF btn = btnRefresh THEN
lastNbrOfDriverEvents := -1; lastNbrOfTopologyEvents := -1;
timer.Wakeup;
END;
END ButtonHandler;
PROCEDURE TabSelected(sender, data : ANY);
VAR m : Mode; viewChanged : BOOLEAN;
BEGIN
IF (data # NIL) & (data IS WMTabComponents.Tab) THEN
m := data(WMTabComponents.Tab).data (Mode);
IF m.mode # viewmode THEN
IF (viewmode = VmDrivers) & (m.mode # VmDrivers) THEN
treepanel.visible.Set(TRUE); driverpanel.visible.Set(FALSE);
END;
viewmode := m.mode;
IF m.mode = VmStandard THEN viewChanged := TRUE;
ELSIF m.mode = VmDetailed THEN viewChanged := TRUE;
ELSIF m.mode = VmDrivers THEN
treepanel.visible.Set(FALSE); driverpanel.visible.Set(TRUE);
ELSIF m.mode = VmPortStatus THEN viewChanged := TRUE;
END;
IF viewChanged THEN lastNbrOfTopologyEvents := -1; timer.Wakeup; END;
END;
END
END TabSelected;
PROCEDURE NodeSelected(sender, data : ANY);
VAR dev : Usb.UsbDevice; ndata : ANY; d : Driver;
BEGIN
usbSelected := NIL; drivers := NIL;
IF (data # NIL) & (data IS WMTrees.TreeNode) THEN
usbTree.Acquire;
usbSelected := data (WMTrees.TreeNode);
ndata := usbTree.GetNodeData(usbSelected);
usbTree.Release;
IF ndata # NIL THEN
dev := ndata (Usb.UsbDevice);
d := GetDriversOf(dev);
drivers := d;
END;
END;
END NodeSelected;
PROCEDURE AddUsbNode(node, parent : WMTrees.TreeNode; CONST caption : ARRAY OF CHAR);
BEGIN
usbTree.Acquire;
usbTree.AddChildNode(parent, node);
usbTree.SetNodeCaption(node, Strings.NewString(caption));
usbTree.Release;
END AddUsbNode;
PROCEDURE AddDrvNode(node, parent : WMTrees.TreeNode; CONST caption : ARRAY OF CHAR);
BEGIN
drvTree.Acquire;
drvTree.AddChildNode(parent, node);
drvTree.SetNodeCaption(node, Strings.NewString(caption));
drvTree.Release;
END AddDrvNode;
PROCEDURE Handle(VAR x: WMMessages.Message);
BEGIN
IF (x.msgType = WMMessages.MsgExt) & (x.ext # NIL) THEN
IF (x.ext IS KillerMsg) THEN Close
ELSE Handle^(x)
END
ELSE Handle^(x)
END
END Handle;
PROCEDURE &New*(c : WMRestorable.Context);
VAR
label : WMStandardComponents.Label;
tab : WMTabComponents.Tab;
mode : Mode;
string : ARRAY 32 OF CHAR;
i : LONGINT;
BEGIN
NEW(timer);
dead := FALSE; alive := TRUE;
NEW(mainpanel);
mainpanel.bounds.SetExtents(WindowWidth, WindowHeight); mainpanel.fillColor.Set(SHORT(0FFFFFFFFH));
NEW(buttonpanel);
buttonpanel.fillColor.Set(0F0F0F0FH);
buttonpanel.bounds.SetHeight(20); buttonpanel.alignment.Set(WMComponents.AlignTop);
mainpanel.AddContent(buttonpanel);
NEW(label); label.caption.SetAOC(" View mode: ");
label.bounds.SetWidth(100); label.alignment.Set(WMComponents.AlignLeft);
buttonpanel.AddContent(label);
NEW(tabs); tabs.bounds.SetWidth(250); tabs.alignment.Set(WMComponents.AlignLeft);
tabs.onSelectTab.Add(TabSelected);
buttonpanel.AddContent(tabs);
FOR i := 0 TO 2 DO
tab := tabs.NewTab();
tabs.AddTab(tab);
NEW(mode);
CASE i OF
0: string := "Standard"; mode.mode := VmStandard;
|1 : string := "Detailed"; mode.mode := VmDetailed;
|2 : string := "Drivers"; mode.mode := VmDrivers;
|3 : string := "PortStatus"; mode.mode := VmPortStatus;
END;
tabs.SetTabCaption(tab, Strings.NewString(string));
tabs.SetTabData(tab, mode);
END;
NEW(btnRefresh); btnRefresh.caption.SetAOC("Refresh"); btnRefresh.alignment.Set(WMComponents.AlignRight);
btnRefresh.onClick.Add(ButtonHandler);
buttonpanel.AddContent(btnRefresh);
NEW(btnProperties); btnProperties.caption.SetAOC("Properties"); btnProperties.alignment.Set(WMComponents.AlignRight);
btnProperties.onClick.Add(ButtonHandler); btnProperties.visible.Set(FALSE);
buttonpanel.AddContent(btnProperties);
NEW(infoline);
infoline.bounds.SetHeight(20); infoline.alignment.Set(WMComponents.AlignBottom);
infoline.fillColor.Set(0F0F0F0FH);
mainpanel.AddContent(infoline);
NEW(treepanel);
treepanel.alignment.Set(WMComponents.AlignClient);
mainpanel.AddContent(treepanel);
NEW(usbTreeView);
usbTreeView.alignment.Set(WMComponents.AlignClient);
usbTreeView.onSelectNode.Add(NodeSelected);
usbTree := usbTreeView.GetTree();
treepanel.AddContent(usbTreeView);
NEW(driverpanel);
driverpanel.alignment.Set(WMComponents.AlignClient);
driverpanel.visible.Set(FALSE);
mainpanel.AddContent(driverpanel);
NEW(drvTreeView);
drvTreeView.alignment.Set(WMComponents.AlignClient);
drvTree := drvTreeView.GetTree();
driverpanel.AddContent(drvTreeView);
viewmode := VmStandard;
BuildTree;
BuildDrivers;
BuildInfoLine;
Init(mainpanel.bounds.GetWidth(), mainpanel.bounds.GetHeight(), FALSE);
SetContent(mainpanel);
SetTitle(Strings.NewString("USB Viewer"));
SetIcon(WMGraphics.LoadImage("WMIcons.tar://WMUsbInfo.png", TRUE));
WMWindowManager.DefaultAddWindow(SELF);
IncCount;
END New;
PROCEDURE Close;
BEGIN
Close^;
alive := FALSE; timer.Wakeup;
BEGIN {EXCLUSIVE} AWAIT(dead); END;
DecCount;
END Close;
BEGIN {ACTIVE}
WHILE(alive) DO
(* Have drivers been added or removed? *)
IF Usb.drivers.nbrOfDriverEvents # lastNbrOfDriverEvents THEN
lastNbrOfDriverEvents := Usb.drivers.nbrOfDriverEvents;
BuildDrivers;
BuildInfoLine;
END;
(* Has the bus topology changes? *)
IF Usb.nbrOfTopologyEvents # lastNbrOfTopologyEvents THEN
lastNbrOfTopologyEvents := Usb.nbrOfTopologyEvents;
BuildTree;
BuildInfoLine;
END;
timer.Sleep(PollInterval);
END;
BEGIN {EXCLUSIVE} dead := TRUE; END;
END Window;
VAR
nofWindows : LONGINT;
PROCEDURE GetVendorString(vendorId : LONGINT) : Strings.String;
CONST Trace = FALSE;
VAR
in : Streams.Reader;
line, vendor : LONGINT; char : CHAR;
vendorStr : ARRAY 128 OF CHAR;
BEGIN
in := Codecs.OpenInputStream(VendorIdFile);
IF in # NIL THEN
LOOP
INC(line);
char := in.Peek();
IF in.Available() = 0 THEN EXIT; END;
in.Int(vendor, FALSE);
in.Char(char);
IF in.res # Streams.Ok THEN KernelLog.String("res: "); KernelLog.Int(in.res,0); KernelLog.Ln; END;
IF char # "|" THEN
IF Debug THEN
KernelLog.String("UsbInfo: Parse error while parsing vendor id file at line ");
KernelLog.Int(line, 0); KernelLog.Ln;
END;
EXIT;
END;
in.Ln(vendorStr);
IF Trace THEN KernelLog.Int(vendor, 0); KernelLog.String(": "); KernelLog.String(vendorStr); KernelLog.Ln; END;
IF vendorId = vendor THEN RETURN Strings.NewString(vendorStr); END;
IF in.res # Streams.Ok THEN EXIT; END;
END;
ELSIF Debug THEN KernelLog.String("UsbInfo: Could not load file: "); KernelLog.String(VendorIdFile); KernelLog.Ln;
END;
RETURN Strings.NewString("Unknown");
END GetVendorString;
PROCEDURE GetImage(dev : Usb.UsbDevice) : WMGraphics.Image;
VAR if : Usb.InterfaceDescriptor; image : WMGraphics.Image;
BEGIN
if := dev.actConfiguration.interfaces[0] (Usb.InterfaceDescriptor);
IF dev.parent = dev THEN
IF dev.controller.isHighSpeed THEN
image := WMGraphics.LoadImage("WMUsbInfo.tar://UsbControllerHs.png", TRUE);
ELSE
image := WMGraphics.LoadImage("WMUsbInfo.tar://UsbController.png", TRUE);
END;
ELSIF dev.hubFlag THEN
IF dev.speed = UsbHcdi.HighSpeed THEN
image := WMGraphics.LoadImage("WMUsbInfo.tar://UsbHubHs.png", TRUE);
ELSE
image := WMGraphics.LoadImage("WMUsbInfo.tar://UsbHub.png", TRUE);
END;
ELSIF (if.bInterfaceClass = 03H) & (if.bInterfaceSubClass = 01H) & (if.bInterfaceProtocol = 02H) THEN
image := WMGraphics.LoadImage("WMUsbInfo.tar://UsbMouse.png", TRUE);
ELSIF (if.bInterfaceClass = 03H) & (if.bInterfaceSubClass = 01H) & (if.bInterfaceProtocol = 01H) THEN
image := WMGraphics.LoadImage("WMUsbInfo.tar://UsbKeyboard.png", TRUE);
ELSIF (if.bInterfaceClass = 08H) THEN
IF dev.speed = UsbHcdi.HighSpeed THEN
image := WMGraphics.LoadImage("WMUsbInfo.tar://UsbMassStorageHs.png", TRUE);
ELSE
image := WMGraphics.LoadImage("WMUsbInfo.tar://UsbMassStorage.png", TRUE);
END;
END;
RETURN image;
END GetImage;
PROCEDURE GetDeviceDescription(class, subclass, protocol : LONGINT; VAR c, s, p : Strings.String);
BEGIN
c := NIL; s := NIL; p := NIL;
IF class = 0 THEN
c := Strings.NewString("Class information at interface level");
ELSIF class = 2 THEN
c := Strings.NewString("Communication");
ELSIF class = 9 THEN
c := Strings.NewString("Hub");
IF protocol = 0 THEN p := Strings.NewString("No TT");
ELSIF protocol = 1 THEN p := Strings.NewString("Single TT");
ELSIF protocol = 2 THEN p := Strings.NewString("Multi TT");
END;
ELSIF class = 220 THEN
c := Strings.NewString("Diagnostic Device");
IF (subclass = 1) THEN s := Strings.NewString("Reprogrammable Diagnostic Device"); END;
IF (protocol = 1) THEN s := Strings.NewString("USB2 Compliance Device"); END;
ELSIF class = 224 THEN
c := Strings.NewString("Wireless Controller");
IF (subclass = 1) THEN s := Strings.NewString("RF Controller"); END;
IF (protocol = 1) THEN s := Strings.NewString("Bluetooth Programming Interface"); END;
ELSIF class = 239 THEN
c := Strings.NewString("Miscellaneous Device Class");
IF (subclass = 2) THEN s := Strings.NewString("Common Class"); END;
IF (protocol = 1) THEN s := Strings.NewString("Interface Association Descriptor"); END;
END;
IF class = 0FFH THEN c := Strings.NewString("Vendor-Specific"); END;
IF subclass = 0FFH THEN s := Strings.NewString("Vendor-Specific"); END;
IF protocol = 0FFH THEN p := Strings.NewString("Vendor-Specific"); END;
END GetDeviceDescription;
PROCEDURE GetInterfaceDescription(class, subclass, protocol : LONGINT; VAR c, s, p: Strings.String);
BEGIN
c := NIL; s := NIL; p := NIL;
IF class = 1 THEN
c := Strings.NewString("Audio");
IF subclass = 0 THEN s := Strings.NewString("Undefined");
ELSIF subclass = 1 THEN s := Strings.NewString("Audio Control");
ELSIF subclass = 2 THEN s := Strings.NewString("Audio Streaming");
ELSIF subclass = 3 THEN s := Strings.NewString("MIDI Streaming");
END;
IF protocol = 0 THEN p := Strings.NewString("Undefined"); END;
ELSIF class = 2 THEN
c := Strings.NewString("CDC-Control");
ELSIF class = 3 THEN
c := Strings.NewString("HID");
IF subclass = 0 THEN s := Strings.NewString("No Subclass");
ELSIF subclass = 1 THEN s := Strings.NewString("Boot Interface Subclass");
IF protocol = 0 THEN p := Strings.NewString("None");
ELSIF protocol = 1 THEN p := Strings.NewString("Keyboard");
ELSIF protocol = 2 THEN p := Strings.NewString("Mouse");
ELSE p := Strings.NewString("Reserved");
END;
ELSE s := Strings.NewString("Reserved");
END;
ELSIF class = 5 THEN
c := Strings.NewString("Physical");
ELSIF class = 6 THEN
IF (subclass = 1) & (protocol = 1) THEN c := Strings.NewString("Image"); END;
ELSIF class = 7 THEN
c := Strings.NewString("Printer");
IF subclass = 1 THEN s := Strings.NewString("Printers"); END;
IF protocol = 00H THEN p := Strings.NewString("Undefined");
ELSIF protocol = 01H THEN p := Strings.NewString("Unidirectional Interface");
ELSIF protocol = 02H THEN p := Strings.NewString("Bidirectional Interface");
ELSIF protocol = 03H THEN p := Strings.NewString("1284.4 Compatible Bidirectional Interface");
END;
ELSIF class = 8 THEN
c := Strings.NewString("Mass-Storage");
IF subclass = 1 THEN s := Strings.NewString("Reduced Block Commands");
ELSIF subclass = 2 THEN s := Strings.NewString("SFF-8020i, MMC-2 (ATAPI)");
ELSIF subclass = 3 THEN s := Strings.NewString("QIC-157");
ELSIF subclass = 4 THEN s := Strings.NewString("UFI");
ELSIF subclass = 5 THEN s := Strings.NewString("SFF-8070i");
ELSIF subclass = 6 THEN s := Strings.NewString("SCSI Transparent Command Set");
ELSIF (subclass >= 7) & (subclass < 256) THEN
s := Strings.NewString("Reserved");
END;
IF protocol = 00H THEN p := Strings.NewString("CBI Transport (with completion interrupt)");
ELSIF protocol = 01H THEN p := Strings.NewString("CBI Transport (w/o completion interrupt)")
ELSIF protocol = 50H THEN p := Strings.NewString("Bulk-Only Transport")
END;
ELSIF class = 9 THEN
c := Strings.NewString("Hub");
ELSIF class = 10 THEN
c := Strings.NewString("CDC-Data");
ELSIF class = 11 THEN
c := Strings.NewString("Chip/Smartcard");
ELSIF class = 13 THEN
c := Strings.NewString("Content-Security");
ELSIF class = 14 THEN
c := Strings.NewString("Video");
IF subclass = 0 THEN s := Strings.NewString("Undefined");
ELSIF subclass = 1 THEN s := Strings.NewString("Video Control");
ELSIF subclass = 2 THEN s := Strings.NewString("Video Streaming");
ELSIF subclass = 3 THEN s := Strings.NewString("Video Interface Collection");
END;
IF protocol = 0 THEN p := Strings.NewString("Undefined"); END;
ELSIF class = 220 THEN
c := Strings.NewString("Diagnostic Device");
IF (subclass = 1) THEN s := Strings.NewString("Reprogrammable Diagnostic Device"); END;
IF (protocol = 1) THEN s := Strings.NewString("USB2 Compliance Device"); END;
ELSIF class = 224 THEN
c := Strings.NewString("Wireless Controller");
IF (subclass = 1) THEN s := Strings.NewString("RF Controller"); END;
IF (protocol = 1) THEN s := Strings.NewString("Bluetooth Programming Interface"); END;
ELSIF class = 254 THEN
c := Strings.NewString("Application-Specific");
IF (subclass = 1) THEN s := Strings.NewString("Device Firmware Update");
ELSIF (subclass = 2) THEN s := Strings.NewString("IrDA Bridge");
ELSIF (subclass = 3) THEN s := Strings.NewString("Test & Measurement Class");
END;
END;
IF class = 0FFH THEN c := Strings.NewString("Vendor-Specific"); END;
IF subclass = 0FFH THEN s := Strings.NewString("Vendor-Specific"); END;
IF protocol = 0FFH THEN p := Strings.NewString("Vendor-Specific"); END;
END GetInterfaceDescription;
PROCEDURE GetIadDescription(class, subclass, protocol : LONGINT; VAR c, s, p : Strings.String);
BEGIN
c := NIL; s := NIL; p := NIL;
IF class = 0EH THEN
c := Strings.NewString("Video");
IF subclass = 00H THEN s := Strings.NewString("Undefined");
ELSIF subclass = 01H THEN s := Strings.NewString("Video Control");
ELSIF subclass = 02H THEN s := Strings.NewString("Video Streaming");
ELSIF subclass = 03H THEN s := Strings.NewString("Video Interface Collection");
END;
IF protocol = 00H THEN p := Strings.NewString("Undefined"); END;
END;
END GetIadDescription;
PROCEDURE Open*;
VAR w : Window;
BEGIN
NEW(w, NIL);
END Open;
PROCEDURE Restore*(context : WMRestorable.Context);
VAR w : Window;
BEGIN
NEW(w, context)
END Restore;
PROCEDURE IncCount;
BEGIN {EXCLUSIVE}
INC(nofWindows);
END IncCount;
PROCEDURE DecCount;
BEGIN {EXCLUSIVE}
DEC(nofWindows);
END DecCount;
PROCEDURE Cleanup;
VAR die : KillerMsg; msg : WMMessages.Message; m : WMWindowManager.WindowManager;
BEGIN {EXCLUSIVE}
NEW(die); msg.ext := die; msg.msgType := WMMessages.MsgExt;
m := WMWindowManager.GetDefaultManager();
m.Broadcast(msg);
AWAIT(nofWindows = 0);
END Cleanup;
BEGIN
Modules.InstallTermHandler(Cleanup);
END WMUsbInfo.
WMUsbInfo.Open ~ SystemTools.Free WMUsbInfo ~