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!
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_index
did 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.