2
votes

In Linux usb-serial converters usually show up as a node in the /dev directory: /dev/ttyUSBx.

To use the serial converter the first step it to open the port, then configure it and so on.

port = open("/dev/ttyUSB0", O_RDWR);

If you want to use a serial device (I2C or SPI), ftdi offers devices (like FT4232 or FT232h) which can be used either as a normal UART port or i2c/spi.

For i2c/spi operation you have to use a separate driver - I use the open source libmpsse. This is a library you have to install so it will work in parallel with the standard FTDI driver since it's build on top of that.

So now, if I want o open a port as UART I use the normal open function (mentioned above). And if I want to connect a i2c/spi device I use the libmpsse open function which opens the port based on VID/PID:

struct mpsse_context *Open(int vid, int pid, enum modes mode, int freq, int endianess, int interface, const char *description, const char *serial)  

Now for the question - can I open the port as UART by using the device vid/pid instead of the path to it's dev mode? It all comes down to ftdi function calls but I can't seem to find an example.

Why I need to do it this way? I don't want to have to know the node path. I should be able to use just the VID/PID and interface number - it's a lot more flexible.

Any help is appreciated!

1
there might be somehting in /dev/serial/ that's better suited:Jasen
@Jasen care to elaborate? :)Pandrei
Elaborating Jasen: if you list /dev/serial/by-id you will find links, named after your device, pointing to virtual file on /dev. There is no vid/pid there, but the manufacturer and product name, but this is likely to be enough in most cases.Gustavo Vargas
I know the question was targeting linux, but, just to keep this here were people can find, in Windows you can list USB devices by get entries on HKLM\SYSTEM\CurrentControlSet\Enum\USB. CDC/ACM devices are likely to have a friendlyName entrie that will be the COMx port associated to this device.Gustavo Vargas

1 Answers

1
votes

I eventually found a solution so I'm posting for anyone that might need this.

You can open the serial port by using one of the ftdi_usb_open_xxx() functions. For me, ftdi_usb_open_desc_indexdid the trick; index is useful in case you have more than one chip of the same kind connected.

Then you configure the port with ftdi_set_baudrate and ftdi_set_line_property. And read/write with ftdi_read_data()/ftdi_write_data().

Here's a short example:

    struct ftdi_context ftdic;

    // ftdilib initialization 
    if(ftdi_init(&ftdic) == 0)
    {

        ftdi_set_interface(&ftdic, IFACE_C);//this is where my serial device is connected


        if(ftdi_usb_open_desc_index(&ftdic, vid, pid, NULL, NULL, 0) == 0)
        {
            printf("serial port open\n");

            if(ftdi_set_baudrate(&ftdic, 9600) < 0)
            {
                printf("baudrate incorrect\n");
            }


            if(ftdi_set_line_property(&ftdic, BITS_8, STOP_BIT_1, NONE)<0)
            {
                printf("line settings incorrect");
            }

            for(;;)
            {
                unsigned char c;
                ftdi_read_data(&ftdic, &c, 1);                  
                printf("0x%2x ",c);             
            }               
        }
        else
        {
            printf("could not open serial port \n");
        }
    }
    else
    {
        printf("init failed\n");
    }

This way you don't seem to have to wait for data to be available so you won't have to deal with blocking ports.