I have to support an increasing range of hardware that's considered, at least by today's standards, legacy. What nearly all of these devices have in common is an FTDI FT232 UART chip, which acts as a Serial-to-USB converter. Windows sees it as a standard COM port, though it is virtualized.

Consequently, programmatically identifying these devices is troublesome. Since they all use the same chip (or similar), querying by typical Hardware IDs is no help since it's always the same. Are there any other metrics available to ID a device?

My current solution has been to loop through all the active Serial Ports, and issue pre-known "hello" commands at all the common baud rates. If I receive a response on that port at the baud rate tested, it's assumed the device of interest is found. Some pseudocode:

for each(Serial Port)
{
    for each(Device Definition)
    {
        for each(Baud Rate)
        {
            WriteToPort(Device Definition.helloString, Baud Rate)
            ReadPort(response)

            if(response)
                Serial Port = this device // break loop
            else
                continue;
        }
    }
}

This works OK, but is unreliable and slow at best, as I have to wait for the read to timeout for each tested baud rate, multiplied by each device actually connected to the system (there can be one or many). This gets slower with each new piece of hardware that has to be supported.

One of the features of this code is that it "Just Works"™, users don't have to fuss with identifying their device and setting up the COM connection. It's pretty clear that my method isn't scalable; Is there anything I can do, short of empowering the user and forfeiting one of the redeeming qualities of my software?

EDIT: I wanted to update my question with some visuals that demonstrates the issue. The accepted answer had some informative information, but when I decided to give the implementation a go, I'm still not certain how to proceed.

Consider the following two entries in my registry: enter image description here

They both share the same Vendor ID, Hardware ID, and virtually every other distinguishing property. However, they are known to be different devices; The only thing they share in common is the communication interface, ala FTDI chip. Knowing the PortName / COM Address isn't helpful at all since the number they receive from the system is arbitrary... whatever is next in line.

How are the numbers circled in red generated? As far as I can tell, this is the only useful piece of information as it seems like devices receive similar Serial Numbers appended to their entry.

The next image shows an entry that is actually useful: enter image description here

The manufacturer is listed, with a registered Vendor and Hardware ID, and there is a description of the connected device. This I could do something with. Unfortunately, it seems to be the exception rather than the rule.

Is there any other way to proceed IDing these devices? Running checks across the devices in parallel will provide a small boost, but the real bottleneck is testing baud rates against the command sets.

有帮助吗?

解决方案

Since you can be querying all the devices in parallel, this method scales across devices, but not across the protocols/baudrates.

Every USB device can indicate its manufacturer, description, serial number, etc. I very much doubt that those will in fact be identical, since in spite of using the FTDI chip, the vendors can put custom Manufacturer and Description strings, while keeping the VID and PID unchanged to avoid the need to pay the "tax" needed to sign a custom variant of the driver.

For FTDI devices, there's a rather crude driver-specific way of getting the device information. Alternatively, you can use the always-present D2XX functionality, query the devices there, use FT_GetComPortNumber to get the port number, and then proceed to open it using the regular Windows-style com port APIs.

If the devices are truly not different at all (make sure you check that first!!!), then the best you can do is cache the protocol that last worked on a given com port number, and try that one first for a given com port. If it fails, you enumerate other protocols.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top