private DeviceInfo(string path, string name, ushort vendorID, ushort productID, ushort version) { // remember the settings this.path = path; this.name = name; this.vendorID = (ushort)vendorID; this.productID = (ushort)productID; this.version = version; // set some defaults PlungerEnabled = true; JoystickEnabled = false; TvOnEnabled = false; // open the USB interface this.fp = OpenFile(); // presume valid isValid = true; // assume the maximum input (device to host) report length inputReportLength = 65; // Check the HID interface to see if the HID Usage type is // type 4, for Joystick. If so, the joystick interface is // enabled, which the device uses to send nudge and plunger // readings. If not, the joystick interface is disabled, so // the device only sends private status messages and query // responses. IntPtr ppdata; if (HIDImports.HidD_GetPreparsedData(this.fp, out ppdata)) { // Check the usage. If the joystick is enabled, the // usage will be 4 = Joystick (on usage page 1, "generic // desktop"). If not, the usage is 0 = Undefined, indicating // our private status and query interface. HIDImports.HIDP_CAPS caps; HIDImports.HidP_GetCaps(ppdata, out caps); bool isJoystick = caps.UsagePage == 1 && caps.Usage == 4; bool isPrivate = caps.UsagePage == 1 && caps.Usage == 0; if (isJoystick) { this.JoystickEnabled = true; } // Only count this as a control interface if it's the joystick // interface or the private interface. The device can expose // other interfaces for device-to-host inputs only, such as a // keyboard interface and a media key interface. Also ignore // it if it doesn't accept output reports (host-to-device), // as indicated by a zero output report length. if (!(isJoystick || isPrivate) || caps.OutputReportByteLength == 0) { isValid = false; } // remember the input report (device to host) length inputReportLength = caps.InputReportByteLength; // free the preparsed data HIDImports.HidD_FreePreparsedData(ppdata); } else { // couldn't get the HID caps - mark as invalid isValid = false; } // if it looks like a valid interface so far, try reading a status report byte[] buf; if (isValid) { buf = ReadUSB(); if (buf != null) { // parse the reponse this.PlungerEnabled = (buf[1] & 0x01) != 0; } else { // couldn't read a report - mark it as invalid isValid = false; } } // Ask about the TV ON feature. This is config variable 9; the // results are: [0] power status input pin; [1] latch output pin; // [2] relay trigger pin; [3,4] delay time in 10ms increments. // This is enabled only if all pins are assigned and the delay // is non-zero. if (isValid && (buf = QueryConfigVar(9)) != null) { int delay = buf[3] | (buf[4] << 8); this.TvOnEnabled = (buf[0] != 0xFF && buf[1] != 0xFF && buf[2] != 0xFF && delay != 0); } // figure the LedWiz unit number LedWizUnitNo = (vendorID == 0xFAFA ? ((productID & 0x0F) + 1) : 0); // get more data if the unit is responding if (isValid) { // get the CPU ID this.CPUID = QueryCPUID(); this.OpenSDAID = QueryOpenSDAID(); // get the pinscape unit number if ((buf = QueryConfigVar(2)) != null) { PinscapeUnitNo = buf[0]; } // get the build ID String s; QueryBuildID(out this.BuildDD, out this.BuildTT, out s); this.BuildID = s; } }