/// <summary> /// HACK: Microsoft CDC driver (usbser.sys) does not register properly as a serial port /// It needs serenum.sys upper port filter which causes problems of its own... /// /// </summary> /// <param name="ports"></param> private static void PatchInZModemSerials(List <SerialPortInfo> ports) { /* SiLabs licensed USB to serial driver PID/VID */ const string SILABS_VID_PID = @"USB\VID_10C4&PID_81E8"; /* Zephyr VID (not specific on PID) */ const string ZEPHYR_VID = @"USB\VID_22F3"; string pnpDevId; int startIndex; int length; System.Management.ManagementScope scope; System.Management.ObjectQuery query; System.Management.ManagementObjectSearcher searcher; System.Management.ManagementObjectCollection returnCollection; System.Management.EnumerationOptions opt = new System.Management.EnumerationOptions(); try { /* get the data NOW, don't put off the query until it is required (30sec timeout) */ opt.ReturnImmediately = false; opt.Timeout = new TimeSpan(0, 0, 30); /* define scope, in this case, this machine */ scope = new System.Management.ManagementScope(@"root\CIMV2"); /* set the query, get all information on the serial ports on the system */ query = new System.Management.ObjectQuery("SELECT * from Win32_SerialPort"); /* stick two together into a search */ searcher = new System.Management.ManagementObjectSearcher(scope, query, opt); /* Run the query */ returnCollection = searcher.Get(); foreach (var oReturn in returnCollection) { pnpDevId = oReturn["PNPDeviceID"] as string; pnpDevId = pnpDevId.ToUpper(); // Vista / Win7 seem to use upper case PID/VID/GUID /* Checks to see if the candidate mySerialPort is a zephyr Serial Port */ if ((pnpDevId.LastIndexOf(SILABS_VID_PID) > -1) || (pnpDevId.LastIndexOf(ZEPHYR_VID) > -1)) { /* Extract the serial number from the PnP mySerialPort ID */ startIndex = pnpDevId.LastIndexOf(@"\") + 1; length = pnpDevId.LastIndexOf(@"_") - startIndex; if (length < 0) { length = pnpDevId.Length - startIndex; } /* If port not already known, add to list */ string serial = pnpDevId.Substring(startIndex, length); string portName = oReturn["DeviceID"] as string; string caption = oReturn["Caption"] as string; var search = ports.FirstOrDefault(item => item.Name == portName); if (search == null) { System.Diagnostics.Debug.WriteLine("Found: " + oReturn["DeviceID"] + " " + oReturn["Caption"]); SerialPortInfo spi = new SerialPortInfo(); spi.SerialName = serial; spi.Name = portName; spi.FriendlyName = caption; spi.Description = caption; spi.Manufacturer = "Zephyr"; spi.Driver = "usbser.sys"; ports.Add(spi); } } } } catch { } }
/// <summary> /// Return the list of all available COM port into the system /// </summary> /// <returns></returns> public static ReadOnlyCollection <SerialPortInfo> GetAvailablePorts() { IntPtr hdevInfo = SetupDi.SetupDiGetClassDevs( ref GUID_DEVINTERFACE_COMPORT, null, IntPtr.Zero, SetupDIGetClassDevsFlags.DIGCF_PRESENT | SetupDIGetClassDevsFlags.DIGCF_DEVICEINTERFACE); if (hdevInfo == INVALID_HANDLE_VALUE) { throw new Exception("can't access to serial port communication information."); } List <SerialPortInfo> ports = new List <SerialPortInfo>(); uint index = 0; SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA(); while (SetupDi.SetupDiEnumDeviceInfo(hdevInfo, index++, deviceInfoData) == true) { IntPtr hKey = SetupDi.SetupDiOpenDevRegKey( hdevInfo, deviceInfoData, SetupDiOpenDevRegKeyScopeFlags.DICS_FLAG_GLOBAL, 0, SetupDiOpenDevRegKeyKeyTypeFlags.DIREG_DEV, REGSAM.KEY_QUERY_VALUE); if (hKey != IntPtr.Zero) { SerialPortInfo portInfo = new SerialPortInfo(); UInt32 resultLength = 1024; IntPtr registryName = Marshal.AllocHGlobal(1024); var retValue = Registry.NtQueryKey(hKey, 3, registryName, 1024, ref resultLength); if (retValue == 0) { string registryNameStr = Marshal.PtrToStringAuto((IntPtr)(registryName.ToInt32() + 4), Marshal.ReadInt32(registryName) / 2); Marshal.FreeHGlobal(registryName); var registryPath = registryNameStr.Split('\\'); if (registryPath != null && registryPath.Length > 3) { var sNumber = registryPath[registryPath.Length - 2]; if (sNumber != null && sNumber.Contains('_')) { portInfo.SerialName = sNumber.Remove(sNumber.IndexOf('_')); } else { portInfo.SerialName = sNumber; } var deviceVidPid = registryPath[registryPath.Length - 3].ToUpperInvariant(); if (deviceVidPid != null && deviceVidPid.Length > 0 && deviceVidPid.Contains("pid_") && deviceVidPid.Contains("vid_")) { try { char separator = '&'; if (deviceVidPid.Contains('&')) { separator = '&'; } else if (deviceVidPid.Contains('+')) { separator = '+'; } var position = deviceVidPid.IndexOf("vid_") + 4; var vid = deviceVidPid.Substring(position, deviceVidPid.IndexOf(separator) - position); position = deviceVidPid.IndexOf("pid_") + 4; var pid = deviceVidPid.Substring(position, deviceVidPid.Length - position); if (pid.Contains(separator)) { pid = pid.Remove(pid.IndexOf(separator)); } portInfo.DevicePid = int.Parse(pid, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); portInfo.DeviceVid = int.Parse(vid, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); } catch { } } } } RegistryType type = RegistryType.REG_NONE; UInt32 capacity; StringBuilder data = new StringBuilder(256); capacity = (UInt32)data.Capacity; int result = Registry.RegQueryValueEx(hKey, "PortName", 0, ref type, data, ref capacity); if ((result == Registry.ERROR_SUCCESS) & (type == RegistryType.REG_SZ)) { portInfo.Name = data.ToString(); string property = GetDeviceRegistryProperty(hdevInfo, deviceInfoData, DeviceRegistryProperty.SPDRP_DEVICEDESC); if (property != null) { portInfo.Description = property; } property = GetDeviceRegistryProperty(hdevInfo, deviceInfoData, DeviceRegistryProperty.SPDRP_MFG); if (property != null) { portInfo.Manufacturer = property; } property = GetDeviceRegistryProperty(hdevInfo, deviceInfoData, DeviceRegistryProperty.SPDRP_FRIENDLYNAME); if (property != null) { portInfo.FriendlyName = property; } property = GetDeviceRegistryProperty(hdevInfo, deviceInfoData, DeviceRegistryProperty.SPDRP_LOCATION_INFORMATION); if (property != null) { portInfo.LocalInformation = property; } property = GetDeviceRegistryProperty(hdevInfo, deviceInfoData, DeviceRegistryProperty.SPDRP_SERVICE); if (property != null) { portInfo.Service = property; } } ports.Add(portInfo); Registry.RegCloseKey(hKey); } } SetupDi.SetupDiDestroyDeviceInfoList(hdevInfo); //PatchInZModemSerials(ports); return(new ReadOnlyCollection <SerialPortInfo>(ports)); }