// Check for a USB Product/Vendor ID match to the known values. // // NB! We're permissive on PID/VID matching. We'll match ANY IDs, and // instead let the caller rely on the product ID string and device query // messages. We go through the motions of checking for the known ID // codes (the LedWiz codes and our private registered code), but this // is purely for the sake of documentation - we always return true in // the end. public static bool CheckIDMatch(HIDImports.HIDD_ATTRIBUTES attrs) { ushort vid = (ushort)attrs.VendorID; ushort pid = (ushort)attrs.ProductID; // if it's an LedWiz-compatible code, it's one of ours if (vid == 0xFAFA && (pid >= 0x00F0 && pid <= 0x00FF)) { return(true); } // if it's our private Pinscape registration code, it's one of ours if (vid == 0x1209 && pid == 0xEAEA) { return(true); } // It's not one of our known VID/PID combos, but allow it anyway, // in case the user is using a custom ID for some reason. We'll // filter out non-Pinscape devices via other, better tests later. return(true); }
// Get a list of connected Pinscape Controller devices public static List <PinscapeDev> FindDevices() { // set up an empty return list var devices = new List <PinscapeDev>(); // 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); // 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)) { // 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); // read the attributes 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 String name = "<unknown>"; 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, and the // product name contains "pinscape", it's one of ours PinscapeDev di; if (CheckIDMatch(attrs) && Regex.IsMatch(name, @"\b(?i)pinscape controller\b") && (di = PinscapeDev.Create( diDetail.DevicePath, name, attrs.VendorID, attrs.ProductID, attrs.VersionNumber)) != null) { // add the device to our list devices.Add(di); } // done with the file handle if (fp.ToInt32() != 0 && fp.ToInt32() != -1) { HIDImports.CloseHandle(fp); } } } } // done with the device info list HIDImports.SetupDiDestroyDeviceInfoList(hdev); // return the device list return(devices); }