1
votes

I am looking for example code in ansi c/c++ that will find usb devices by their pid/vid/sn# and then find the associated comport number. I have multiple FTDI usb serial ports connected to a pc and need to identify each port by the known SN#. This code I found will display the HWID info but how do I use it to get the comport number? Here is a response to the below code for one of the devices: USB\VID_0403&PID_6001\FTAME7HK Are there an online tutorial that runs through examples for this type of code?

    #include <windows.h> 
    #include <ansi_c.h>
    #include <Setupapi.h>
    #include <devguid.h>
    #include <Setupapi.h>
    HDEVINFO deviceInfoSet;
    GUID *guidDev = (GUID*) &GUID_DEVCLASS_USB; 
    TCHAR buffer [4000];
    DWORD buffersize =4000;
    int memberIndex = 0;
    main()
    {
    deviceInfoSet = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);   
    while (TRUE) {
    SP_DEVINFO_DATA deviceInfoData;
    ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
    deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    if (SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex, &deviceInfoData) == FALSE) {
      if (GetLastError() == ERROR_NO_MORE_ITEMS)
        {
        break;
        }
   }
   DWORD nSize=0 ;
   SetupDiGetDeviceInstanceId (deviceInfoSet, &deviceInfoData, buffer, sizeof(buffer), &nSize);
   buffer [nSize] ='\0';
   printf ("%s\n", buffer);
   memberIndex++;
   }
   if (deviceInfoSet) {
   SetupDiDestroyDeviceInfoList(deviceInfoSet);
   }
   getchar();
   return 0;    
   }
1
How are you opening the port? The Windows API itself will accept a device path which you can get directly from these SetupDi functions, there's no need to ever deal in the DOS device symlinks such as "COM1" and "\\?\COM21". But a lot of serial port libraries make bad assumptions about the format of the pseudofilename of a serial port.Ben Voigt
The goal is to find the port number/description (COM18) using the product ID and unique serial number. I can parse the number from the (COM18) if necessary. I just need to find the port using the ID's USB\VID_0403&PID_6001\FTAME7HK.Jon
Why do you think you want the port number? Is that really your goal, or is your real goal to open the correct port?Ben Voigt
I need the comport number to send to other apps/functions. I am trying to muscle through the microsoft.com documentation. it is very painful!Jon

1 Answers

0
votes

If you want the friendly name, which typically includes the parenthesized com port number, this should do it:

{
    wchar_t friendly_name[128];
    if (!SetupDiGetDeviceRegistryPropertyW(device_list, &device_data, SPDRP_FRIENDLYNAME, nullptr, reinterpret_cast<PBYTE>(friendly_name), sizeof friendly_name, nullptr))
        return;
    StringCopyW(buffer, friendly_name);
}

To get the two parameters device_list and device_data for the above call, I use this function:

void rescan_ports( void )
{
    SP_DEVINFO_DATA device_data = { sizeof device_data };
    HDEVINFO device_list = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_COMPORT, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    DWORD error = GetLastError();
    if (!device_list && device_list == INVALID_HANDLE_VALUE) return;

    bool ended = false;
    for( int i = 0; i < 6000 && !ended; i++ ) {
        if (SetupDiEnumDeviceInfo(device_list, i, &device_data))
            format_and_add_port_detail(device_list, device_data);
        else
            ended = (GetLastError() == ERROR_NO_MORE_ITEMS);
    }

    SetupDiDestroyDeviceInfoList(device_list);
}

It's very similar to what you wrote, except that mine uses GUID_DEVINTERFACE_COMPORT to find only serial ports.