Example #1
0
            public bool WriteUSB(byte[] buf)
            {
                for (int tries = 0; tries < 3; ++tries)
                {
                    UInt32 actual;
                    if (HIDImports.WriteFile(fp, buf, 9, out actual, ref ov) == 0)
                    {
                        // try re-opening the handle, if it's an "invalid handle" error
                        if (TryReopenHandle())
                        {
                            continue;
                        }

                        Log.Write("Pinscape Controller USB error sending request to device: " + GetLastWin32ErrMsg());
                        return(false);
                    }
                    else if (actual != 9)
                    {
                        Log.Write("Pinscape Controller USB error sending request: not all bytes sent");
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }

                // maximum retries exceeded - return failure
                return(false);
            }
Example #2
0
            public byte[] ReadUSB()
            {
                for (int tries = 0; tries < 3; ++tries)
                {
                    const int rptLen = 15;
                    byte[]    buf    = new byte[rptLen];
                    buf[0] = 0x00;
                    uint actual;
                    if (HIDImports.ReadFile(fp, buf, rptLen, out actual, ref ov) == 0)
                    {
                        // if the error is 6 ("invalid handle"), try re-opening the device
                        if (TryReopenHandle())
                        {
                            continue;
                        }

                        Log.Write("Pinscape Controller USB error reading from device: " + GetLastWin32ErrMsg());
                        return(null);
                    }
                    else if (actual != rptLen)
                    {
                        Log.Write("Pinscape Controller USB error reading from device: not all bytes received");
                        return(null);
                    }
                    else
                    {
                        return(buf);
                    }
                }

                // don't retry more than a few times
                return(null);
            }
Example #3
0
        // Search the Windows USB HID device set for Pinscape controllers
        private static List <Device> FindDevices()
        {
            // set up an empty return list
            List <Device> devices = new List <Device>();

            // get the list of devices matching the HID class GUID
            Guid guid;

            HIDImports.HidD_GetHidGuid(out guid);
            IntPtr hdev = HIDImports.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, HIDImports.DIGCF_DEVICEINTERFACE);

            // set up the attribute structure buffer
            HIDImports.SP_DEVICE_INTERFACE_DATA diData = new HIDImports.SP_DEVICE_INTERFACE_DATA();
            diData.cbSize = Marshal.SizeOf(diData);

            // read the devices in our list
            for (uint i = 0;
                 HIDImports.SetupDiEnumDeviceInterfaces(hdev, IntPtr.Zero, ref guid, i, ref diData);
                 ++i)
            {
                // get the size of the detail data structure
                UInt32 size = 0;
                HIDImports.SetupDiGetDeviceInterfaceDetail(hdev, ref diData, IntPtr.Zero, 0, out size, IntPtr.Zero);

                // now actually read the detail data structure
                HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail = new HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA();
                diDetail.cbSize = (IntPtr.Size == 8) ? (uint)8 : (uint)5;
                if (HIDImports.SetupDiGetDeviceInterfaceDetail(hdev, ref diData, ref diDetail, size, out size, IntPtr.Zero))
                {
                    // create a file handle to access the device
                    IntPtr fp = HIDImports.CreateFile(
                        diDetail.DevicePath, HIDImports.GENERIC_READ_WRITE, HIDImports.SHARE_READ_WRITE,
                        IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

                    // read the attributes
                    HIDImports.HIDD_ATTRIBUTES attrs = new HIDImports.HIDD_ATTRIBUTES();
                    attrs.Size = Marshal.SizeOf(attrs);
                    if (HIDImports.HidD_GetAttributes(fp, ref attrs))
                    {
                        // presume this is a Pinscape Controller, then look for reasons it's not
                        bool ok = true;

                        // read the product name string
                        String name    = "<not available>";
                        byte[] nameBuf = new byte[128];
                        if (HIDImports.HidD_GetProductString(fp, nameBuf, 128))
                        {
                            name = System.Text.Encoding.Unicode.GetString(nameBuf).TrimEnd('\0');
                        }

                        // If the vendor and product ID match an LedWiz OR our private ID, and the
                        // product name contains "pinscape", and it's product version 7 or higher,
                        // it's a Pinscape controller with the extended protocol features.
                        bool isLW = ((ushort)attrs.VendorID == 0xFAFA && (attrs.ProductID >= 0x00F0 && attrs.ProductID <= 0x00FF));
                        bool isPS = ((ushort)attrs.VendorID == 0x1209 && ((ushort)attrs.ProductID == 0xEAEA));
                        ok &= ((isLW || isPS) &&
                               Regex.IsMatch(name, @"\b(?i)pinscape\b") &&
                               attrs.VersionNumber >= 7);

                        // Newer versions of the device software can present multiple USB HID
                        // interfaces, including Keyboard (usage page 1, usage 6) and Media
                        // Control (volume up/down/mute buttons) (usage page 12, usage 1).
                        // The output controller is always part of the Joystick interface
                        // (usage page 1, usage 4).  HidP_GetCaps() returns the USB usage
                        // information for the first HID report descriptor associated with
                        // the interface, so we can determine which interface we're looking
                        // at by checking this information.  Start by getting the preparsed
                        // data from the Windows HID driver.
                        IntPtr ppdata;
                        if (ok && HIDImports.HidD_GetPreparsedData(fp, out ppdata))
                        {
                            // get the device caps
                            HIDImports.HIDP_CAPS caps = new HIDImports.HIDP_CAPS();
                            HIDImports.HidP_GetCaps(ppdata, ref caps);

                            // This Pinscape interface accepts output controller commands only
                            // if it's the joystick type (usage page 1 == generic desktop, usage
                            // 4 == joystick).  If it doesn't match, it must be a secondary HID
                            // interface on the same device, such as the keyboard or media
                            // controller interface.  Skip those interfaces, as they don't
                            // accept the output controller commands.
                            ok &= (caps.UsagePage == 1 && caps.Usage == 4);

                            // done with the preparsed data
                            HIDImports.HidD_FreePreparsedData(ppdata);
                        }

                        // If we passed all tests, this is the output controller interface for
                        // a Pinscape controller device, so add the device to our list.
                        if (ok)
                        {
                            // add the device to our list
                            devices.Add(new Device(fp, diDetail.DevicePath, name, attrs.VendorID, attrs.ProductID, attrs.VersionNumber));

                            // the device list object owns the handle nwo
                            fp = System.IntPtr.Zero;
                        }
                    }

                    // done with the file handle
                    if (fp.ToInt32() != 0 && fp.ToInt32() != -1)
                    {
                        HIDImports.CloseHandle(fp);
                    }
                }
            }

            // return the device list
            return(devices);
        }
Example #4
0
 private IntPtr OpenFile()
 {
     return(HIDImports.CreateFile(
                path, HIDImports.GENERIC_READ_WRITE, HIDImports.SHARE_READ_WRITE,
                IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero));
 }