Created
September 4, 2015 13:20
-
-
Save codehero/fdf059db355073777342 to your computer and use it in GitHub Desktop.
Test for tcdrain bug in ftdi_sio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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