Exemplo n.º 1
0
    private bool TryReopenHandle()
    {
        // if the last error is 6 ("invalid handle") or 1167 ("Device not connected"),
        // try re-opening the handle
        int err = Marshal.GetLastWin32Error();

        if (err == 6 || err == 1167)
        {
            // try opening a new handle on the device path
            Console.WriteLine("invalid handle on read/write - trying to reopen");
            IntPtr fp2 = OpenFile();

            // if that succeeded, replace the old handle with the new one and retry the read
            if (fp2 != IntPtr.Zero && fp2.ToInt32() != -1)
            {
                // close the old handle
                if (fp != IntPtr.Zero && fp.ToInt32() != -1)
                {
                    HIDImports.CloseHandle(fp);
                }

                // replace the handle
                fp = fp2;

                // tell the caller to try again
                return(true);
            }
        }

        // we didn't successfully reopen the handle
        return(false);
    }
Exemplo n.º 2
0
        /// <summary>
        /// Reading
        /// </summary>
        private void ReadReport()
        {
            byte[] buff = new byte[REPORT_LENGTH];

            uint             numberOfBytesRead = 0;
            NativeOverlapped overlapped        = new NativeOverlapped();

            overlapped.EventHandle = mre.SafeWaitHandle.DangerousGetHandle();
            overlapped.OffsetHigh  = 0;
            overlapped.OffsetLow   = 0;

            bool result = HIDImports.ReadFile(this.SafeFileHandle.DangerousGetHandle(), buff, (uint)buff.Length, out numberOfBytesRead, ref overlapped);

            //Log("ReadReport: " + result.ToString());

            // parse it
            if (buff != null && result)
            {
                if (ParseInputReport(buff))
                {
                    if (WiiControllerStateChanged != null)
                    {
                        WiiControllerStateChanged(this, new WiiControllerStateChangedEventArgs(this.WiiControllerState));
                    }
                }
            }
        }
        private static bool CheckWiiControllerType(SafeFileHandle handle, ControllerType controllerType, HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail, WiiControllerFoundDelegate wiiControllerFound)
        {
            // Get ProductName
            string product = string.Empty;

            byte[] productBuff = new byte[128];
            // attempt to read the serial number string
            if (HIDImports.HidD_GetProductString(handle.DangerousGetHandle(), productBuff, productBuff.Length))
            {
                // convert from unicode to the default encoding
                product = Encoding.Default.GetString(Encoding.Convert(Encoding.Unicode, Encoding.Default, productBuff));
            }
            // Trim the string down by removing any '\0' characters
            product = product.Remove(product.IndexOf('\0'));

            switch (controllerType)
            {
            case ControllerType.WiiBalanceBoard:
                if (product == WBBName_new || product == WBBName_old)
                {
                    if (wiiControllerFound != null)
                    {
                        wiiControllerFound(diDetail.DevicePath, controllerType);
                    }
                    return(true);
                }
                break;

            default:
                break;
            }

            return(false);
        }
Exemplo n.º 4
0
    // clear out the USB input buffer
    public void FlushReadUSB()
    {
        // note the starting time so we don't wait forever
        DateTime t0 = DateTime.Now;

        // wait until a read would block
        int rptLen = inputReportLength;

        while ((DateTime.Now - t0).TotalMilliseconds < 100)
        {
            // set up a non-blocking read
            IntPtr buf = Marshal.AllocHGlobal(rptLen);
            try
            {
                unsafe
                {
                    // set up the overlapped I/O descriptor
                    Overlapped        o  = new Overlapped(0, 0, evov.SafeWaitHandle.DangerousGetHandle(), null);
                    NativeOverlapped *no = o.Pack(null, null);

                    // start the non-blocking read
                    Marshal.WriteByte(buf, 0);
                    HIDImports.ReadFile(fp, buf, rptLen, IntPtr.Zero, no);

                    // check to see if it's ready immediately
                    bool ready = evov.WaitOne(0);
                    if (ready)
                    {
                        // it's ready - complete the read
                        UInt32 readLen;
                        int    result = HIDImports.GetOverlappedResult(fp, no, out readLen, 0);
                    }
                    else
                    {
                        // Not ready - we'd have to wait to do a read, so the
                        // buffer is empty.  Cancel the read.
                        HIDImports.CancelIo(fp);
                    }

                    // done with the overlapped I/O descriptor
                    Overlapped.Unpack(no);
                    Overlapped.Free(no);

                    // if there was nothing ready to read, we've cleared out buffered
                    // inputs, so we're done
                    if (!ready)
                    {
                        return;
                    }
                }
            }
            finally
            {
                Marshal.FreeHGlobal(buf);
            }
        }
    }
Exemplo n.º 5
0
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (evov != null)
            {
                evov.Dispose();
                evov = null;
            }
        }

        if (fp != IntPtr.Zero && fp.ToInt32() != -1)
        {
            HIDImports.CloseHandle(fp);
            fp = IntPtr.Zero;
        }
    }
Exemplo n.º 6
0
        /// <summary>
        /// Write a report to the WiiController
        /// </summary>
        internal bool WriteReport()
        {
            Log("WriteReport: " + buff[0].ToString("x"));

            bool result = HIDImports.HidD_SetOutputReport(this.SafeFileHandle.DangerousGetHandle(), buff, (uint)buff.Length);

            Log("WriteReport: " + result.ToString());

            if (this.buff[0] == (byte)OutputReport.WriteMemory)
            {
                Log("Wait");
                if (!writeDone.WaitOne(1000, false))
                {
                    Log("Wait failed");
                }
            }

            return(result);
        }
Exemplo n.º 7
0
        private const UInt32 PIDAppleMagicKeyboardJIS            = 0x267; // by @Drunkar (https://github.com/mayuki/AppleWirelessKeyboardHelper/pull/3)

        /// <summary>
        ///
        /// </summary>
        internal Boolean Start()
        {
            if (_stream != null)
            {
                throw new InvalidOperationException("ヘルパーはすでに実行中です。");
            }

            Guid guid;

            HIDImports.HidD_GetHidGuid(out guid);

            IntPtr hDevInfo = HIDImports.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, HIDImports.DIGCF_DEVICEINTERFACE);

            HIDImports.SP_DEVICE_INTERFACE_DATA diData = new HIDImports.SP_DEVICE_INTERFACE_DATA();
            diData.cbSize = Marshal.SizeOf(diData);

            UInt32 index = 0;

            while (HIDImports.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guid, index++, ref diData))
            {
                HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail = new HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA();
                diDetail.cbSize = (IntPtr.Size == 8) ? (UInt32)8 : 5; // x64:8, x86:5

                UInt32 size;
                HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, IntPtr.Zero, 0, out size, IntPtr.Zero);
                if (HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, ref diDetail, size, out size, IntPtr.Zero))
                {
                    Debug.WriteLine("Device: " + diDetail.DevicePath); Debug.Indent();
                    SafeFileHandle             mHandle = HIDImports.CreateFile(diDetail.DevicePath, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, HIDImports.EFileAttributes.Overlapped, IntPtr.Zero);
                    HIDImports.HIDD_ATTRIBUTES attrib  = new HIDImports.HIDD_ATTRIBUTES();
                    attrib.Size = Marshal.SizeOf(attrib);
                    if (HIDImports.HidD_GetAttributes(mHandle.DangerousGetHandle(), ref attrib))
                    {
                        Debug.WriteLine(String.Format("VendorID:{0:x}, ProductID:{1:x}, VersionNumber:{2:x}", attrib.VendorID, attrib.ProductID, attrib.VersionNumber));
                        if (attrib.VendorID == VIDApple &&
                            (attrib.ProductID == PIDAppleWirelessKeyboardUS ||
                             attrib.ProductID == PIDAppleWirelessKeyboardJIS ||
                             attrib.ProductID == PIDAppleKeyboardJIS ||
                             attrib.ProductID == PIDAppleKeyboardUS ||
                             attrib.ProductID == PIDAppleWirelessKeyboardFR ||
                             attrib.ProductID == PIDAppleWirelessKeyboardRU_MC184RS ||
                             //attrib.ProductID == PIDAppleKeyboardWithoutTenKeyUS ||
                             attrib.ProductID == PIDAppleWirelessKeyboardJIS_MC184JA ||
                             attrib.ProductID == PIDAppleWirelessKeyboardJIS_MC184JB ||
                             attrib.ProductID == PIDAppleWirelessKeyboardUS_MC184LL ||
                             attrib.ProductID == PIDAppleWirelessKeyboardUS_MC184LLB ||
                             attrib.ProductID == PIDAppleWirelessKeyboardJIS_MB110JB ||
                             attrib.ProductID == PIDAppleMagicKeyboardJIS
                            ))
                        {
                            _stream = new FileStream(mHandle, FileAccess.ReadWrite, 22, true);
                            //break;
                        }
                        else
                        {
                            mHandle.Close();
                        }
                    }
                    Debug.Unindent();
                }
            }

            if (_stream != null)
            {
                Byte[] buffer = new Byte[22];
                _stream.BeginRead(buffer, 0, buffer.Length, SpecialKeyStateChanged, buffer);
                return(true);
            }
            else
            {
                // Not Connected
                return(false);
            }
        }
Exemplo n.º 8
0
    public bool WriteUSB(byte[] buf)
    {
        for (int tries = 0; tries < 3; ++tries)
        {
            unsafe
            {
                // write the data - the file handle is in overlapped mode, so we have to do
                // this as an overlapped write with an OVERLAPPED structure and an event to
                // monitor for completion
                Overlapped        o    = new Overlapped(0, 0, evov.SafeWaitHandle.DangerousGetHandle(), null);
                NativeOverlapped *no   = o.Pack(null, null);
                IntPtr            hbuf = Marshal.AllocHGlobal(buf.Length);
                try
                {
                    Marshal.Copy(buf, 0, hbuf, buf.Length);
                    HIDImports.WriteFile(fp, hbuf, buf.Length, IntPtr.Zero, no);

                    // wait briefly for the write to complete
                    if (evov.WaitOne(250))
                    {
                        // successful completion - get the result
                        UInt32 actual;
                        int    result = HIDImports.GetOverlappedResult(fp, no, out actual, 0);

                        Overlapped.Unpack(no);
                        Overlapped.Free(no);

                        if (result == 0)
                        {
                            // the write failed - try re-opening the handle and go back
                            // for another try
                            TryReopenHandle();
                            continue;
                        }
                        else if (actual != buf.Length)
                        {
                            // length is wrong - the write failed
                            return(false);
                        }
                        else
                        {
                            // success
                            return(true);
                        }
                    }
                    else
                    {
                        // The write timed out.  Cancel the write and try reopening the handle.
                        HIDImports.CancelIo(fp);
                        Overlapped.Unpack(no);
                        Overlapped.Free(no);
                        if (TryReopenHandle())
                        {
                            continue;
                        }
                        return(false);
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(hbuf);
                }
            }
        }

        // maximum retries exceeded - return failure
        return(false);
    }
Exemplo n.º 9
0
    public static List <DeviceInfo> FindDevices(FindDeviceCallback callback = null)
    {
        findDeviceDebugInfo.Clear();

        // set up an empty return list
        List <DeviceInfo> devices = new List <DeviceInfo>();

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

        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);

            String debugInfo = "#" + i + " (" + hdev.ToString() + ")";

            // 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;
            HIDImports.SP_DEVINFO_DATA devInfoData = new HIDImports.SP_DEVINFO_DATA();
            devInfoData.cbSize = Marshal.SizeOf(devInfoData);
            if (HIDImports.SetupDiGetDeviceInterfaceDetail(hdev, ref diData, ref diDetail, size, out size, out devInfoData))
            {
                debugInfo += " path=" + diDetail.DevicePath;

                // create a file handle to access the device
                IntPtr fp = HIDImports.CreateFile(
                    diDetail.DevicePath, HIDImports.GENERIC_READ_WRITE, HIDImports.SHARE_READ_WRITE,
                    IntPtr.Zero, HIDImports.OPEN_EXISTING, 0, IntPtr.Zero);

                debugInfo += " fp=" + fp.ToString();

                // read the attributes
                Thread.Sleep(1);
                HIDImports.HIDD_ATTRIBUTES attrs = new HIDImports.HIDD_ATTRIBUTES();
                attrs.Size = Marshal.SizeOf(attrs);
                if (HIDImports.HidD_GetAttributes(fp, ref attrs))
                {
                    // Read the product name string.  Note that
                    String name    = "<not available>";
                    byte[] nameBuf = new byte[256];
                    if (HIDImports.HidD_GetProductString(fp, nameBuf, 256))
                    {
                        name = System.Text.Encoding.Unicode.GetString(nameBuf).TrimEnd('\0');
                    }
                    else
                    {
                        debugInfo += " [GetProductString failed]";
                    }

                    debugInfo += " productString=\"" + name + "\"";

                    // if the vendor and product ID match an LedWiz, and the
                    // product name contains "pinscape", it's one of ours
                    DeviceInfo di;
                    if (CheckIDMatch(attrs) &&
                        Regex.IsMatch(name, @"\b(?i)pinscape controller\b") &&
                        (di = DeviceInfo.Create(
                             diDetail.DevicePath, name, attrs.VendorID, attrs.ProductID, attrs.VersionNumber)) != null)
                    {
                        debugInfo += " [device added]";

                        // add the device to our list
                        devices.Add(di);

                        // if there's a callback, invoke it
                        if (callback != null)
                        {
                            callback(di, hdev, ref devInfoData);
                        }
                    }

#if false
                    // report the results for debugging
                    Console.Out.WriteLine(
                        "Product " + attrs.ProductID.ToString("X4")
                        + ", vendor " + attrs.VendorID.ToString("X4")
                        + ", version " + attrs.VersionNumber.ToString("X4")
                        + ", name " + name);
#endif
                }
                else
                {
                    debugInfo += " [GetAttributes failed]";
                }

                // done with the file handle
                if (fp.ToInt32() != 0 && fp.ToInt32() != -1)
                {
                    HIDImports.CloseHandle(fp);
                }
            }
            else
            {
                debugInfo += " [GetDeviceInterfaceDetail failed]";
            }

            findDeviceDebugInfo.Add(debugInfo);
        }

        // done with the device info list
        HIDImports.SetupDiDestroyDeviceInfoList(hdev);

        // return the device list
        return(devices);
    }
Exemplo n.º 10
0
 private IntPtr OpenFile()
 {
     return(HIDImports.CreateFile(
                path, HIDImports.GENERIC_READ_WRITE, HIDImports.SHARE_READ_WRITE,
                IntPtr.Zero, HIDImports.OPEN_EXISTING, HIDImports.EFileAttributes.Overlapped, IntPtr.Zero));
 }
Exemplo n.º 11
0
    public byte[] ReadUSB()
    {
        // try reading a few times, in case we lose the connection briefly
        int rptLen = inputReportLength;

        for (int tries = 0; tries < 3; ++tries)
        {
            unsafe
            {
                // set up a non-blocking ("overlapped") read
                IntPtr buf = Marshal.AllocHGlobal((int)rptLen);
                try
                {
                    Marshal.WriteByte(buf, 0);
                    Overlapped        o  = new Overlapped(0, 0, evov.SafeWaitHandle.DangerousGetHandle(), null);
                    NativeOverlapped *no = o.Pack(null, null);
                    HIDImports.ReadFile(fp, buf, rptLen, IntPtr.Zero, no);

                    // Wait briefly for the read to complete.  But don't wait forever - we might
                    // be talking to a device interface that doesn't provide the type of status
                    // report we're looking for, in which case we don't want to get stuck waiting
                    // for something that will never happen.  If this is indeed the controller
                    // interface we're interested in, it will respond within a few milliseconds
                    // with our status report.
                    if (evov.WaitOne(100))
                    {
                        // The read completed successfully!  Get the result.
                        UInt32 readLen;
                        int    result = HIDImports.GetOverlappedResult(fp, no, out readLen, 0);

                        Overlapped.Unpack(no);
                        Overlapped.Free(no);

                        if (result == 0)
                        {
                            // The read failed.  Try re-opening the file handle in case we
                            // dropped the connection, then re-try the whole read.
                            TryReopenHandle();
                            continue;
                        }
                        else if (readLen != rptLen)
                        {
                            // The read length didn't match what we expected.  This might be
                            // a different device (not a Pinscape controller) or a different
                            // version that we don't know how to talk to.  In either case,
                            // return failure.
                            return(null);
                        }
                        else
                        {
                            // The read succeed and was the correct size.  Return the data.
                            byte[] retbuf = new byte[rptLen];
                            Marshal.Copy(buf, retbuf, 0, rptLen);
                            return(retbuf);
                        }
                    }
                    else
                    {
                        // The read timed out.  This must not be our control interface after
                        // all.  Cancel the read and try reopening the handle.
                        HIDImports.CancelIo(fp);
                        Overlapped.Unpack(no);
                        Overlapped.Free(no);
                        if (TryReopenHandle())
                        {
                            continue;
                        }
                        return(null);
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(buf);
                }
            }
        }

        // don't retry more than a few times
        return(null);
    }
Exemplo n.º 12
0
    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;
        }
    }
Exemplo n.º 13
0
        /// <summary>
        /// Reading in another Thread
        /// </summary>
        private void OnReadData(object threadSleepTime)
        {
            Log("Read Thread started");

            try
            {
                int sleepTime = (int)threadSleepTime;
                while (readAsync)
                {
                    byte[] buff = new byte[REPORT_LENGTH];

                    uint             numberOfBytesRead = 0;
                    NativeOverlapped overlapped        = new NativeOverlapped();
                    overlapped.EventHandle = mre.SafeWaitHandle.DangerousGetHandle();
                    overlapped.OffsetHigh  = 0;
                    overlapped.OffsetLow   = 0;

                    bool result = HIDImports.ReadFile(this.SafeFileHandle.DangerousGetHandle(), buff, (uint)buff.Length, out numberOfBytesRead, ref overlapped);

                    Log("ReadReport: " + result.ToString());

                    if (!result)
                    {
                        uint lastError = HIDImports.GetLastError();
                        if (lastError != HIDImports.ERROR_IO_PENDING)
                        {
                            Log("Read failed: " + lastError.ToString("X"));
                            continue;
                        }
                        else
                        {
                            if (!HIDImports.GetOverlappedResult(this.SafeFileHandle.DangerousGetHandle(), ref overlapped, out numberOfBytesRead, true))
                            {
                                lastError = HIDImports.GetLastError();
                                Log("Read failed: " + lastError.ToString("X"));
                                continue;
                            }

                            if (overlapped.InternalHigh.ToInt32() == HIDImports.STATUS_PENDING || overlapped.InternalLow.ToInt32() == HIDImports.STATUS_PENDING)
                            {
                                Log("Read interrupted " + lastError.ToString("X"));
                                if (!HIDImports.CancelIo(this.SafeFileHandle.DangerousGetHandle()))
                                {
                                    lastError = HIDImports.GetLastError();
                                    Log("CancelIO failed: " + lastError.ToString("X"));
                                    continue;
                                }
                            }
                        }
                    }

                    // parse it
                    if (buff != null)
                    {
                        if (ParseInputReport(buff))
                        {
                            if (WiiControllerStateChanged != null)
                            {
                                WiiControllerStateChanged(this, new WiiControllerStateChangedEventArgs(this.WiiControllerState));
                            }
                        }
                    }

                    Thread.Sleep(sleepTime);
                }
            }
            catch (ThreadAbortException ex)
            {
                Log("Thread abort!: " + ex.Message);
            }
        }
Exemplo n.º 14
0
        internal void OpenWiiControllerDeviceHandle(string devicePath, bool onlyOpen = false)
        {
            // open a read/write handle to our device using the DevicePath returned
            SafeFileHandle safeFileHandle = HIDImports.CreateFile(devicePath, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, HIDImports.EFileAttributes.Overlapped, IntPtr.Zero);

            // create an attributes struct and initialize the size
            HIDImports.HIDD_ATTRIBUTES attrib = new HIDImports.HIDD_ATTRIBUTES();
            attrib.Size = Marshal.SizeOf(attrib);

            // get the attributes of the current device
            if (HIDImports.HidD_GetAttributes(safeFileHandle.DangerousGetHandle(), ref attrib))
            {
                // if the vendor and product IDs match up
                if (attrib.VendorID == WiiInputManager.VID)
                {
                    if (attrib.ProductID == WiiInputManager.PID_old || attrib.ProductID == WiiInputManager.PID_new)
                    {
                        // initialize
                        this.WiiControllerState = new WiiControllerState();
                        this.SafeFileHandle     = safeFileHandle;
                        this.HIDDevicePath      = devicePath;

                        if (onlyOpen)
                        {
                            // get calibration infos
                            this.SetCalibrationInfo();

                            this.IsConnected = true;

                            // set LED
                            this.SetLEDs(true, true, true, true);
                        }
                        else
                        {
                            // start reading
                            this.readThread = BeginAsyncRead(10);
                            Thread.Sleep(100);

                            // get calibration infos
                            this.SetCalibrationInfo();

                            this.IsConnected = true;

                            // get status from the WiiContoller
                            this.GetStatus();

                            // set LED
                            this.SetLEDs(true, true, true, true);

                            if (this.readThread != null)
                            {
                                this.readThread.Abort();
                                this.readThread = null;
                            }

                            this.readAsync = false;
                        }
                    }
                }
            }
        }
        private static void SearchWiiController(WiiControllerFoundDelegate wiiControllerFound, ControllerType controllerType, bool breakIfFoundOne = false)
        {
            int            index = 0;
            bool           found = false;
            Guid           guid;
            SafeFileHandle handle;

            // get the GUID of the HID class
            HIDImports.HidD_GetHidGuid(out guid);

            // get a handle to all devices that are part of the HID class
            // Fun fact:  DIGCF_PRESENT worked on my machine just fine.  I reinstalled Vista, and now it no longer finds the WiiController with that parameter enabled...
            IntPtr hDevInfo = HIDImports.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, HIDImports.DIGCF_DEVICEINTERFACE);// | HIDImports.DIGCF_PRESENT);

            // create a new interface data struct and initialize its size
            HIDImports.SP_DEVICE_INTERFACE_DATA diData = new HIDImports.SP_DEVICE_INTERFACE_DATA();
            diData.cbSize = Marshal.SizeOf(diData);

            // get a device interface to a single device (enumerate all devices)
            while (HIDImports.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guid, index, ref diData))
            {
                UInt32 size;

                // get the buffer size for this device detail instance (returned in the size parameter)
                HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, IntPtr.Zero, 0, out size, IntPtr.Zero);

                // create a detail struct and set its size
                HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail = new HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA();

                // on Win x86, cbSize must be 5 for some reason.  On x64, apparently 8 is what it wants.
                diDetail.cbSize = (uint)(IntPtr.Size == 8 ? 8 : 5);

                // actually get the detail struct
                if (HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, ref diDetail, size, out size, IntPtr.Zero))
                {
                    Debug.WriteLine(string.Format("{0}: {1} - {2}", index, diDetail.DevicePath, Marshal.GetLastWin32Error()));

                    // open a read/write handle to our device using the DevicePath returned
                    bool closeHandle = true;
                    handle = HIDImports.CreateFile(diDetail.DevicePath, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, HIDImports.EFileAttributes.Overlapped, IntPtr.Zero);

                    // create an attributes struct and initialize the size
                    HIDImports.HIDD_ATTRIBUTES attrib = new HIDImports.HIDD_ATTRIBUTES();
                    attrib.Size = Marshal.SizeOf(attrib);

                    // get the attributes of the current device
                    if (HIDImports.HidD_GetAttributes(handle.DangerousGetHandle(), ref attrib))
                    {
                        // if the vendor and product IDs match up
                        if (attrib.VendorID == WiiInputManager.VID)
                        {
                            if (attrib.ProductID == WiiInputManager.PID_old || attrib.ProductID == WiiInputManager.PID_new)
                            {
                                found = CheckWiiControllerType(handle, controllerType, diDetail, wiiControllerFound);

                                if (found)
                                {
                                    // it's the right WiiController
                                    Debug.WriteLine("Found one and open!");
                                }

                                // stop at first found
                                if (breakIfFoundOne)
                                {
                                    break;
                                }
                                // dont close the handle
                                closeHandle = false;
                            }
                        }
                    }
                    if (closeHandle)
                    {
                        handle.Close();
                    }
                }
                else
                {
                    // failed to get the detail struct
                    throw new WiiControllerException("SetupDiGetDeviceInterfaceDetail failed on index " + index);
                }

                // move to the next device
                index++;
            }

            // clean up our list
            HIDImports.SetupDiDestroyDeviceInfoList(hDevInfo);

            // if we didn't find a WiiController, throw an exception
            if (!found)
            {
                throw new WiiControllerNotFoundException("No WiiControllers found in HID device list.");
            }
        }