internal static HIDDeviceInfo GetDevice(string hidPath)
        {
            bool          result;
            HIDDeviceInfo hid = new HIDDeviceInfo();

            hid.DIDetail.DevicePath = hidPath;

            // Open the device handle
            if (!hid.OpenHandle())
            {
                return(null);
            }

            // Get the attributes of the current device
            result = NativeMethods.HidD_GetAttributes(hid.Handle.DangerousGetHandle(), ref hid.HIDAttr);
            // Close the device before returning in
            // case the user doesn't want it afterall.
            hid.Close();
            if (result)
            {
                return(hid);
            }

            // Otherwise this isn't an HID device
            return(null);
        }
        internal static IEnumerable <HIDDeviceInfo> EnumerateDevices(CancellationToken token, Predicate <HIDDeviceInfo> match)
        {
            IntPtr hDevInfo = IntPtr.Zero;

            try {
                int           index = -1;
                bool          result;
                int           size;
                HIDDeviceInfo hid;

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

                // 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 Wiimote with that parameter enabled...
                hDevInfo = NativeMethods.SetupDiGetClassDevs(ref HIDGuid, null, IntPtr.Zero, DeviceInfoFlags.DeviceInterface);                // | DeviceInfoFlags.Present);

                while (NativeMethods.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref HIDGuid, ++index, ref diData))
                {
                    hid  = new HIDDeviceInfo(diData);
                    size = 0;

                    if (token.IsCancellationRequested)
                    {
                        yield break;
                    }

                    // Get the buffer size for this device detail instance (returned in the size parameter)
                    NativeMethods.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref hid.DIData, IntPtr.Zero, 0, out size, IntPtr.Zero);

                    // Actually get the detail struct
                    if (!NativeMethods.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref hid.DIData, ref hid.DIDetail, size, out size, IntPtr.Zero))
                    {
                        continue;
                    }

                    //Debug.WriteLine(string.Format("{0}: {1} - {2}", index, hid.Path, Marshal.GetLastWin32Error()));

                    // Open the device handle
                    if (!hid.OpenHandle())
                    {
                        continue;
                    }

                    result = NativeMethods.HidD_GetAttributes(hid.DangerousHandle, ref hid.HIDAttr);
                    // Close the device before returning in
                    // case the user doesn't want it afterall.
                    hid.Close();
                    if (result && (match?.Invoke(hid) ?? true))
                    {
                        yield return(hid);
                    }
                }
            }
            finally {
                // clean up our list
                if (hDevInfo != IntPtr.Zero)
                {
                    NativeMethods.SetupDiDestroyDeviceInfoList(hDevInfo);
                }
            }
        }