Search code examples
c++usbftdi

Can FTDI device port number be known without opening the connection?


I want to list FTDI ports with their description, here is my program:

#include <iostream>
#include "ftd2xx.h"

int main( int argc, char* argv[] )
{
    DWORD numDevs = 0, i = 0;
    FT_DEVICE_LIST_INFO_NODE *ftDevList = NULL;
    FT_STATUS ftStatus;

    /* Get the number of FTDI D2XX devices connected to the system.
     * This also trigs in the driver the creation of a list which we later get
     * using FT_GetDeviceInfoList(). */
    if( (ftStatus = FT_CreateDeviceInfoList(&numDevs)) != FT_OK )
    {
        std::cout << "FT_CreateDeviceInfoList failed with error " << ftStatus << std::endl;
        return 1;
    }

    if( numDevs != 0 )
    {
        /* Ask the FTDI USB driver the list of all numDevs FTDI D2XX devices which
         * are plugged in the PC: */
        ftDevList = (FT_DEVICE_LIST_INFO_NODE *)
                        malloc(numDevs * sizeof(FT_DEVICE_LIST_INFO_NODE));
        if ( !ftDevList )
        {
            std::cout << "Could not get device list" << std::endl;
            return 1;
        }

        if ( (ftStatus = FT_GetDeviceInfoList(ftDevList, &numDevs)) != FT_OK )
        {
            std::cout << "FT_GetDeviceInfoList failed with error " << ftStatus << std::endl;
            return 1;
        }

        for ( i = 0 ; i < numDevs ; i++ )
        {
            FT_HANDLE ftOpenHandle;
            if ((ftStatus = FT_Open(i,&ftOpenHandle)) == FT_OK)
            {
                LONG lComPortNumber = 0;
                if ( (ftStatus = FT_GetComPortNumber(ftOpenHandle,&lComPortNumber)) == FT_OK) 
                {
                    if (lComPortNumber == -1)
                    {
                        // No COM port assigned
                    }
                    else 
                    {
                        std::cout << "COM" << lComPortNumber << " is " << ftDevList[i].Description << std::endl;  
                    }
                }
                else 
                {
                    std::cout << "FT_GetComPortNumber failed with error " << ftStatus << std::endl;
                    return 1;
                }
                FT_Close(ftOpenHandle);
            }
            else
            {
                std::cout << "FT_Open failed with error " << ftStatus << std::endl;
                return 1;
            }
        }

        free( ftDevList );
    }
    // else: No need to build this empty list. We have all the information: "there is 
    // no USB FTDI device plugged in the PC".

    return 0;
}

However, as you can see, this opens the port FT_Open/FT_Close. I'm just surprised the port number is not part of FT_DEVICE_LIST_INFO_NODE...why do I need to open the port to retrieve this basic information? Using WIN32 API for instance, ports can be enumerated without being "opened"...is there no way to do this using FTDI driver?


Solution

  • Yes, the libusbp library is capable of detecting USB virtual COM ports and listing them without doing any I/O on Windows, Linux, or macOS. See the lsport example:

    https://github.com/pololu/libusbp/blob/master/examples/lsport/lsport.cpp