This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Relating COM port name and Segger ID

Dear Fellow developers

I am developing an application where I need several nrf51 USB dongles (S120) attached to a PC, and I need a way to distinguish one dongle from another. I am using the ble_driver_win_0.3.0 S120 softdevice with unmanaged C++ on a win8 PC.

An easy way of distinguishing the dongles is by their Segger ID, which is needed anyway for resetting the dongle using nrfjprog. Problem is, how do I know which COM port they are on?

In the ‘Master Emulator’ (managed-) dll there is a function called something like ‘Enumerate Dongles’ which I suppose does exactly this, but unfortunately the same function does not exist in the ble_driver_win_0.3.0.

My first idea to solve the problem is to read the MAC address on each dongle by using nrfjprog, and then opening each COM port and read the MAC address using the ble_driver_win_0.3.0 dll, but this seems like a long way around a relative small problem.

Do you have any suggestions to how I relate COM ports and Segger IDs?

  • @Rasmus: Do you want to detect the Segger ID on each COMport automatically in runtime in the code or it's OK if you can have the list and use them manually ?

    If you simply need a list that matches COM Port and Segger ID, you can just open Master Control Panel on PC there is a dropdown list of COM Port-SeggerID there.

  • One way is to use the Windows Registry:

    SYSTEM\CurrentControlSet\Enum\USB

    Search for "VID_1366" and then take a look at the layout of the Registry tree.

    Here's some sample code in C# to do this:

    public bool getCOMPort(string snr, out string com)
    {
      snr = snr.Trim();
      com = "NOT_SET";
      string segger_id_pidprefix = "";
      Dictionary<string, string> com_ports = new Dictionary<string, string>();
      string ROOT = "SYSTEM\\CurrentControlSet\\Enum\\USB";
    
      using (RegistryKey key = Registry.LocalMachine.OpenSubKey(ROOT))
      {
        foreach (var segger_root_entry in key.GetSubKeyNames())
        {
          // Filter on Segger Vendor ID
          if (! segger_root_entry.StartsWith("VID_1366")) continue;
    
          using (RegistryKey segger_root_key = Registry.LocalMachine.OpenSubKey(ROOT + "\\" + segger_root_entry))
          {
            foreach (var segger_entry in segger_root_key.GetSubKeyNames())
            {
              using (RegistryKey segger_key = Registry.LocalMachine.OpenSubKey(ROOT + "\\" + segger_root_entry + "\\" + segger_entry))
              {
                string service = Convert.ToString(segger_key.GetValue("Service"));
                if (service == "usbccgp")
                {
                  var segger_entry_trimmed = segger_entry.TrimStart('0');
                  Console.WriteLine("usbccgp " + segger_entry_trimmed + " - " + Convert.ToString(segger_key.GetValue("ParentIdPrefix")));
                  if (segger_entry_trimmed.StartsWith(snr))
                  {
                    if (segger_id_pidprefix != "")
                    {
                      Console.WriteLine("Error: Found more than one usbccgp entry for snr");
                    }
                    segger_id_pidprefix = Convert.ToString(segger_key.GetValue("ParentIdPrefix"));
                  }
                }
                if (service == "usbser" || service == "JLinkCDC_x64")
                {
                  using (RegistryKey dev_param_key = Registry.LocalMachine.OpenSubKey(ROOT + "\\" + segger_root_entry + "\\" + segger_entry + "\\Device Parameters"))
                  {
                    if (dev_param_key == null) continue;
    
                    string portname = Convert.ToString(dev_param_key.GetValue("PortName"));
                    com_ports[segger_entry] = portname;
                    Console.WriteLine("usbser " + segger_entry + " - " + portname);
                  }
                }
              }
            }
          }
        }
      }
    
      Console.WriteLine("segger_id_pidprefix " + segger_id_pidprefix);
    
      if (segger_id_pidprefix == "")
      {
        Console.WriteLine("Error: Could not find com port (empty pidprefix) for " + snr);
        return false;
      }
    
      foreach (var item in com_ports)
      {
        if (item.Key.StartsWith(segger_id_pidprefix))
        {
          com = item.Value;
          Console.WriteLine("Found com " + com);
          return true;
        }
      }
      Console.WriteLine("Error: Could not find com port (unknown pidprefix) for " + snr);
      return false;
    }
    

    Carles

  • Hello Rasmus. I tested that, and in my case it works, except if I have both the dongle and the dev kit (plugged to the PC by USB to get power supply). Then both port names are found and we cannot know which one should be picked up...is there a way to fix that?

  • You could make an exclude list and skip the Segger IDs that is on the list. I suppose you have a limited amount of dev kits to exclude.

Related