internal void FindEv3() { int index = 0; bool found = false; Guid guid; // 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 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(); // yeah, yeah...well, see, on Win x86, cbSize must be 5 for some reason. On x64, apparently 8 is what it wants. // someday I should figure this out. Thanks to Paul Miller on this... 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("{0}: {1} - {2}", index, diDetail.DevicePath, Marshal.GetLastWin32Error()); // open a read/write handle to our device using the DevicePath returned _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 == VID && attrib.ProductID == PID) { // it's a Ev3 Debug.WriteLine("Found one!"); found = true; IntPtr preparsedData; if (!HidImports.HidD_GetPreparsedData(_handle.DangerousGetHandle(), out preparsedData)) { throw new Exception("Could not get preparsed data for HID device"); } HidImports.HIDP_CAPS caps; if (HidImports.HidP_GetCaps(preparsedData, out caps) != HidImports.HIDP_STATUS_SUCCESS) { throw new Exception("Could not get CAPS for HID device"); } HidImports.HidD_FreePreparsedData(ref preparsedData); _inputReport = new byte[caps.InputReportByteLength]; _outputReport = new byte[caps.OutputReportByteLength]; // create a nice .NET FileStream wrapping the handle above _stream = new FileStream(_handle, FileAccess.ReadWrite, _inputReport.Length, true); break; } _handle.Close(); } } else { // failed to get the detail struct throw new Exception("SetupDiGetDeviceInterfaceDetail failed on index " + index); } // move to the next device index++; } // clean up our list HidImports.SetupDiDestroyDeviceInfoList(hDevInfo); // if we didn't find a EV3, throw an exception if (!found) { throw new Exception("No LEGO EV3s found in HID device list."); } }
internal void FindEv3() { int index = 0; bool found = false; Guid guid; // 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 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(); // yeah, yeah...well, see, on Win x86, cbSize must be 5 for some reason. On x64, apparently 8 is what it wants. // someday I should figure this out. Thanks to Paul Miller on this... 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("{0}: {1} - {2}", index, diDetail.DevicePath, Marshal.GetLastWin32Error()); // open a read/write handle to our device using the DevicePath returned _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 == VID && attrib.ProductID == PID) { // it's a Ev3 Debug.WriteLine("Found one!"); found = true; IntPtr preparsedData; if(!HidImports.HidD_GetPreparsedData(_handle.DangerousGetHandle(), out preparsedData)) throw new Exception("Could not get preparsed data for HID device"); HidImports.HIDP_CAPS caps; if(HidImports.HidP_GetCaps(preparsedData, out caps) != HidImports.HIDP_STATUS_SUCCESS) throw new Exception("Could not get CAPS for HID device"); HidImports.HidD_FreePreparsedData(ref preparsedData); _inputReport = new byte[caps.InputReportByteLength]; _outputReport = new byte[caps.OutputReportByteLength]; // create a nice .NET FileStream wrapping the handle above _stream = new FileStream(_handle, FileAccess.ReadWrite, _inputReport.Length, true); break; } _handle.Close(); } } else { // failed to get the detail struct throw new Exception("SetupDiGetDeviceInterfaceDetail failed on index " + index); } // move to the next device index++; } // clean up our list HidImports.SetupDiDestroyDeviceInfoList(hDevInfo); // if we didn't find a EV3, throw an exception if(!found) throw new Exception("No LEGO EV3s found in HID device list."); }