public static void GetDfuDevices(List <USBDeviceList> devicelist, IReadOnlyList <HardwareIds> FilterDevices) { string DeviceSearchQuery = "SELECT * FROM Win32_USBControllerDevice"; ManagementObjectSearcher USBControllerDeviceCollection = new ManagementObjectSearcher(DeviceSearchQuery); if (USBControllerDeviceCollection == null) { return; } foreach (ManagementObject queryObj in USBControllerDeviceCollection.Get()) { // Get the DeviceID of the device entity string Dependent = (queryObj["Dependent"] as string).Split(new Char[] { '=' })[1]; foreach (HardwareIds FilterDevice in FilterDevices) { // Filter out USB devices without VID and PID Match match = Regex.Match(Dependent, "VID_[0-9|A-F]{4}&PID_[0-9|A-F]{4}"); if (!match.Success) { continue; } UInt16 VendorID = Convert.ToUInt16(match.Value.Substring(4, 4), 16); // Vendor ID if (FilterDevice.Vid == UInt16.MinValue || FilterDevice.Vid != VendorID) { continue; } UInt16 ProductID = Convert.ToUInt16(match.Value.Substring(13, 4), 16); // Product Number if (FilterDevice.Pid == UInt16.MinValue || FilterDevice.Pid != ProductID) { continue; } // Check to see if our interface number is available for uploads Match matchInterface = Regex.Match(Dependent, "VID_[0-9|A-F]{4}&PID_[0-9|A-F]{4}&MI_[0-9|A-F]"); if (matchInterface.Success) { continue; // Skip interface nodes, since we are only interested in the main composite device. } UInt64 SerialNum = 0; // The match fails if the interface is not available, meaning that this is the "parent" node. // When this is the case, the serial number will be available at the end of the string. try { SerialNum = Convert.ToUInt64(Dependent.Substring(25, 12), 16); } catch (Exception) { // Could not retrieve the serial number, perhaps this device does not advertise one. } string PnPEntrySearchQuery = "SELECT * FROM Win32_PnPEntity WHERE DeviceID=" + Dependent; ManagementObjectCollection PnPEntityCollection = new ManagementObjectSearcher(PnPEntrySearchQuery).Get(); if (PnPEntityCollection == null) { continue; } foreach (ManagementObject Entity in PnPEntityCollection) { USBDeviceList Element = new USBDeviceList( "" as string, // Device ID not available right now Entity["PNPDeviceID"] as string, // PnP Device ID Entity["Description"] as string // Device Description ); Guid ClassGuid = new Guid(Entity["ClassGuid"] as String); // Device installation class GUID if (GUID_USB_CLASS_USB_DEVICE != Guid.Empty && ClassGuid == GUID_USB_CLASS_USB_DEVICE) { Element.MachineName = USBDeviceList.MachineType.StBootloader; // Uses a generic USB device ClassGUID } else if (GUID_USB_CLASS_BUS_DEVICES != Guid.Empty && ClassGuid == GUID_USB_CLASS_BUS_DEVICES) { Element.MachineName = USBDeviceList.MachineType.StDevice; // Makes use of WinUsb driver ClassGuid } else { continue; } Element.VendorId = VendorID; // Vendor ID Element.ProductId = ProductID; // Product Number // Get a user-friendly name from the filter device. Element.Name = GetString(FilterDevice); Element.ClassGuid = ClassGuid.ToString(); // Device installation class GUID Element.SerialNumber = SerialNum; devicelist.Add(Element); } } // foreach (HardwareIds FilterDevice in FilterDevices) } // foreach( ManagementObject queryObj in USBControllerDeviceCollection ) }
/* Update connected COM ports * - Retrieve all used USB ports and filter 3devo specific devices * * Code derived from: https://stackoverflow.com/questions/3331043/get-list-of-connected-usb-devices */ private void UpdateDeviceList() { DisableInterface(); DeviceInfoList.Clear(); Util.InvokeIfRequired(this, c => { this.cmbPort.Items.Clear(); }); // Get all the serial devices which do not make use of DFU programming USBDeviceList.GetSerialDevices(DeviceInfoList, DevoHardware.SerialDevices); // Get all the other devices in the list (such as Airid Dryer) USBDeviceList.GetDfuDevices(DeviceInfoList, DevoHardware.DfuDevices); // Add all components to the combobox list bool valid_device = false; UInt16 DeviceCount = 0; string NewHardwareField = ""; foreach (USBDeviceList Device in DeviceInfoList) { valid_device = true; NewHardwareField = ""; switch (Device.MachineName) { case USBDeviceList.MachineType.AtmelDevice: NewHardwareField = (DeviceCount + 1).ToString() + ". " + Device.Name; // Hardware friendly name break; case USBDeviceList.MachineType.StBootloader: NewHardwareField = (DeviceCount + 1).ToString() + ". " + "Generic ST device" + $" ({Device.SerialNumber:X})"; break; case USBDeviceList.MachineType.StDevice: NewHardwareField = (DeviceCount + 1).ToString() + ". " + Device.Name + $" ({Device.SerialNumber:X})"; break; case USBDeviceList.MachineType.None: NewHardwareField = (DeviceCount + 1).ToString() + ". " + "Unsupported device"; break; default: valid_device = false; Util.InvokeIfRequired(this, c => { txtStatusInfo.AppendText($"An unexpected machine found in device list ({Device.MachineName})"); }); break; } if (valid_device) { Util.InvokeIfRequired(this, c => { this.cmbPort.Items.Add(NewHardwareField); }); DeviceCount += 1; } } // Pre-select the first item in the list if only one device is selectable. Changing the selected index // when no device is preselected raises the comboboxDropdown_Handler a second time. Util.InvokeIfRequired(this, c => { if (this.cmbPort.Items.Count > 0 && this.cmbPort.SelectedIndex == -1) { this.cmbPort.SelectedIndex = 0; } else { // Refresh the selected combobox index manually. // Note that this assumes that the interface will also be refreshed in this handler. ComboboxDropdown_Handler(); } }); }