So, I have a solution to this problem that requires no flashing, but isn't /quite/ working yet, I was wondering if any skilled coders out there could advise.
What I've done is simply use libftdi [apt-get install libftdi-dev] to write a userland "driver". It creates a unix pseudoterminal and simply proxies data to and from the ftdi device. Instead of using /dev/ttyUSB0 [as you'd usually use], you'd use /dev/pts/{number} [the actual device is printed to stdout by the userspace program]. I think someone knowlegable with udev/hotplug can make this whole thing entirely transparent; plugging in this device would start the process and smylink the pty to /dev/ttyUSBftdi0 or something.
Before posting the code, I'll explain the problem: It seems that regularly, there's some kind of buffering going on. I can open the device using minicom to communicate with my ftdi device [it's an OBDPro usb device]. While using it, it works fine most of the time [now that I've put in the buffer purge calls], but regularly I find that I have to hit enter a couple times to get anything to happen. I think it's blocking in a read from the device [at least, that's kinda what strace suggests], I just don't know how to try and fix it.
The code itself appears thus:
/** \file
\brief Provide a pty to access an ftdi device, in case of missing kernel driver
gcc -o ftdipty ftdipty.c -lftdi
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ftdi.h>
int main(int argc, const char **argv) {
int ret;
// Create an ftdi context
struct ftdi_context *ftdic;
if (NULL == (ftdic = ftdi_new())) {
fprintf(stderr, "ftdi_new failed\n");
return 1;
}
int vendorid = 0x0403;
int product = 0x6001;
// Open the ftdi device
if (0 > (ret = ftdi_usb_open(ftdic, vendorid, product))) {
fprintf(stderr, "unable to open ftdi device: %d (%s)\n", ret, ftdi_get_error_string(ftdic));
ftdi_free(ftdic);
return 1;
}
// Open the pseudoterminal
int fd = posix_openpt(O_RDWR | O_NOCTTY);
if(-1 == fd) {
perror("Couldn't posix_openpt");
return 1;
}
grantpt(fd);
unlockpt(fd);
fcntl(fd,F_SETFL,O_NONBLOCK);
// Print the pty slave name
static char ptyname[1024];
if(0 != ptsname_r(fd, ptyname, sizeof(ptyname))) {
perror("Couldn't get pty slave");
return 1;
}
printf("%s successfully opened pty. Name: %s\n", argv[0], ptyname);
// Seriously, how f**king cheesy is this.
while(1) {
char buf[4096];
int nbytes;
// printf("About to read from the pty\n");
if(0 < (nbytes = read(fd, buf, sizeof(buf)))) {
// printf("About to write to the ftdi\n");
ftdi_write_data(ftdic, buf, nbytes);
}
if(0 < (ret = ftdi_usb_purge_buffers(ftdic))) {
fprintf(stderr, "unable to purge ftdi buffers: %d (%s)\n", ret, ftdi_get_error_string(ftdic));
break;
}
// Just to stop it using 100% cpu
usleep(50);
// printf("About to read from the ftdi\n");
if(0 < (nbytes = ftdi_read_data(ftdic, buf, sizeof(buf)))) {
// printf("About to write to the pty\n");
write(fd, buf, nbytes);
}
if(0 < (ret = ftdi_usb_purge_buffers(ftdic))) {
fprintf(stderr, "unable to purge ftdi buffers: %d (%s)\n", ret, ftdi_get_error_string(ftdic));
break;
}
}
// Close the pty
close(fd);
// Close the ftdi device
if (0 > (ret = ftdi_usb_close(ftdic))) {
fprintf(stderr, "unable to close ftdi device: %d (%s)\n", ret, ftdi_get_error_string(ftdic));
return EXIT_FAILURE;
}
// Free the ftdi context
ftdi_free(ftdic);
return 0;
}
Any help would be massively appreciated,
Gary (-;