3

In this program I'm first trying to connect to availalbe port. When found and connected, I want to read the connected USB device ID and vendor ID, How do I do that?

Kind Regards

Program()
    {

        // Get a list of serial port names. 
        string[] ports = SerialPort.GetPortNames();

        // Search for the right port. 
        foreach (string port in ports)
        {
            _serialPort = new SerialPort(port, 250000, Parity.None, 8, StopBits.One);
            _serialPort.Handshake = Handshake.None;
            _serialPort.ReadTimeout = 300;
            _serialPort.WriteTimeout = 300;

            try
            {
                _serialPort.Open();
                break;
            }
            catch (Exception e)
            {
                Console.WriteLine("Serial port " + port + ": " + e.Message);
            }
        }
        /* ENTER CODE TO GET ID HERE */

        Console.WriteLine("Using: " + _serialPort.PortName);
        Console.WriteLine("Device ID: " + _serialPort.DeviceID);
Christian
  • 1,548
  • 2
  • 15
  • 26
  • 3
    Serial port it is not USB port, just COM port. – Hamlet Hakobyan Feb 20 '13 at 23:00
  • possible duplicate of [Need to know whether a device is wired serial or Bluetooth](http://stackoverflow.com/questions/3659939/need-to-know-whether-a-device-is-wired-serial-or-bluetooth) – Hans Passant Feb 20 '13 at 23:21
  • To add some extra information: When I wrote this post I though that you hade to open the port/connection to recive vendor id or device id. I'm writing this code for Windows and by doing so I should gather that kind of information from windows register. I'm trying to acompilsh a code who can find the right device and then run. – Christian Feb 22 '13 at 16:21

1 Answers1

6

I finally got this sorted out myself a couple days ago. There are two parts, one to check the registry and another to check the vid/pid of the device.

The registry method I use just to make sure I don't capture a null modem emulator like com0com.

    /// <summary>
    /// Removes any comm ports that are not explicitly defined as allowed in ALLOWED_TYPES
    /// </summary>
    /// <param name="allPorts">reference to List that will be checked</param>
    /// <returns></returns>
    private static void nullModemCheck(ref List<string> allPorts)
    {
        // Open registry to get the COM Ports available with the system
        RegistryKey regKey = Registry.LocalMachine;

        // Defined as: private const string REG_COM_STRING ="HARDWARE\DEVICEMAP\SERIALCOMM";
        regKey = regKey.OpenSubKey(REG_COM_STRING);

        Dictionary<string, string> tempDict = new Dictionary<string, string>();
        foreach (string p in allPorts)
            tempDict.Add(p, p);

        // This holds any matches we may find
        string match = "";
        foreach (string subKey in regKey.GetValueNames())
        {
            // Name must contain either VCP or Seial to be valid. Process any entries NOT matching
            // Compare to subKey (name of RegKey entry)
            if (!(subKey.Contains("Serial") || subKey.Contains("VCP")))
            {
                // Okay, this might be an illegal port.
                // Peek in the dictionary, do we have this key? Compare to regKey.GetValue(subKey)
                if(tempDict.TryGetValue(regKey.GetValue(subKey).ToString(), out match))         
                {
                    // Kill it!
                    allPorts.Remove(match);

                    // Reset our output string
                    match = "";
                }

            }

        }

        regKey.Close();
    }

The vid/pid portion was gleaned from techinpro

    /// <summary>
    /// Compile an array of COM port names associated with given VID and PID
    /// </summary>
    /// <param name="VID">string representing the vendor id of the USB/Serial convertor</param>
    /// <param name="PID">string representing the product id of the USB/Serial convertor</param>
    /// <returns></returns>
    private static List<string> getPortByVPid(String VID, String PID)
    {
        String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID);
        Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);
        List<string> comports = new List<string>();
        RegistryKey rk1 = Registry.LocalMachine;
        RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");
        foreach (String s3 in rk2.GetSubKeyNames())
        {
            RegistryKey rk3 = rk2.OpenSubKey(s3);
            foreach (String s in rk3.GetSubKeyNames())
            {
                if (_rx.Match(s).Success)
                {
                    RegistryKey rk4 = rk3.OpenSubKey(s);
                    foreach (String s2 in rk4.GetSubKeyNames())
                    {
                        RegistryKey rk5 = rk4.OpenSubKey(s2);
                        RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");
                        comports.Add((string)rk6.GetValue("PortName"));
                    }
                }
            }
        }
        return comports;
    }
cory.todd
  • 516
  • 5
  • 14
  • 2
    This generates a list of ports associated with the PID/VID rather than the PID/VID of an actual port - that is to say, it generates a result even when the device is unplugged. As a manufacture of a USB CDC/ACM device I have a number of ports that are associated with my device, but I need to get the PID/VID of a connected device rather then historically associated devices. I have done this with Qt using `QextPortInfo` but need a .Net method ideally. – Clifford May 25 '16 at 12:11
  • 1
    You are correct. The only way to get that information (that I know of) is to use libusb/winusb. That requires significantly more effort for much the same effect. I believe this is sufficient because the OS must know about the port before it can be opened. Therefore, the retrieved pid/vid is the most recent if you are able to actually connect. – cory.todd May 25 '16 at 13:47