Skip to content

Instantly share code, notes, and snippets.

@codehero
Created September 4, 2015 13:20
Show Gist options
  • Save codehero/fdf059db355073777342 to your computer and use it in GitHub Desktop.
Save codehero/fdf059db355073777342 to your computer and use it in GitHub Desktop.
Test for tcdrain bug in ftdi_sio
#include <termios.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
/* Tests if tcdrain is actually blocking until all bytes are sent over the wire.
* This requires a hardware loopback (short RX and TX pins).
* Tested with FT230X and Linux 3.19.0
*
* A successful test will receive as many bytes as written.
* An unsuccessful test will receive fewer.
*
* -Enabling sleep should always be successful.
* Compile as follows
* gcc ftdi_tcdrain_bug.c -o ftdi_tcdrain_bug -std=gnu11
*
* */
int main(int argc, char **argv){
int ret;
int sleep = 0;
if(argc < 2){
fprintf(stderr, "Usage: TTY_DEV_NODE SLEEP\n");
return 1;
}
if(argc > 2)
sleep = 1;
int fd = open(argv[1], O_RDWR);
if(fd < 0){
fprintf(stderr, "Unable to open port: %s\n", strerror(errno));
return 1;
}
struct termios ser_options;
ret = tcgetattr(fd, &ser_options);
if(ret < 0){
fprintf(stderr, "err tcgetattr: %s\n", strerror(errno));
return 1;
}
unsigned baudrate = B9600;
ret = cfsetispeed(&ser_options, baudrate);
if(ret < 0){
fprintf(stderr, "err cfsetispeed: %s\n", strerror(errno));
return 1;
}
ret = cfsetospeed(&ser_options, baudrate);
if(ret < 0){
fprintf(stderr, "err cfsetospeed: %s\n", strerror(errno));
return 1;
}
/* Setup for raw binary comms. */
cfmakeraw(&ser_options);
/* Reset options for communications. */
ser_options.c_cflag &= ~(PARODD | PARENB | CS5 | CS6 | CS7 | CSTOPB);
ser_options.c_cflag |= CS8;
ret = tcsetattr(fd, TCSANOW, &ser_options);
if(ret < 0){
fprintf(stderr, "err tcsetattr: %s\n", strerror(errno));
return 1;
}
/* Send initial break */
tcsendbreak(fd, 1);
const uint8_t buff[] = "ABCDEFG12345";
ret = write(fd, buff, sizeof(buff));
fprintf(stderr, "Wrote %i\n", ret);
if(tcdrain(fd))
fprintf(stderr, "tcdrain: %s\n", strerror(errno));
/* Safety sleep because tcdrain doesn't work worth a hist. */
if(sleep)
usleep(sizeof(buff) * 2 * 1000);
/* Send final break */
tcsendbreak(fd, 1);
char recvbuff[128];
ret = read(fd, recvbuff, 128);
fprintf(stderr, "Read %i\n", ret);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment