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); }
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."); } }