Reputation: 274
I need to communicate with a piece of hardware over a USB virtual serial device. All I need is it to pass raw bytes back and forth at speed with the right UART settings, I do not ever want to use a terminal. The proof of concept software using termios isn't configuring the right bits and doesn't work unless I feed in a magic config string over stty before running.
I attempted to replicate every setting from stty that appears in the POSIX man page for termios.h and it still doesn't work, and now has a screen full of boilerplate flag setting code.
What should be the minimum configuration using termios.h to get a terminal-less serial port? And if there's any additions for Linux specifically I'll need to know those.
Upvotes: 0
Views: 3498
Reputation: 274
On Linux at least the function cfmakeraw()
will set the flags in a struct termios
serial settings blob for raw IO. In this case the workflow, with error checking removed, looks like:
int fd = open(portname, O_RDWR | O_NOCTTY);
struct termios portSettings;
tcgetattr(fd, &portSettings);
cfsetispeed(&portSettings, B115200);
cfsetospeed(&portSettings, B115200);
cfmakeraw(&portSettings);
tcsetattr(fd, TCSANOW, &portSettings);
Upvotes: 1
Reputation: 1098
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
int serial_open(char *port, int baud)
{
int fd;
struct termios tty;
if((fd = open(port, O_RDWR | O_NOCTTY | O_SYNC)) < 0)
{
return -1;
}
if(tcgetattr(fd, &tty) < 0)
{
return -1;
}
cfsetospeed(&tty, (speed_t)baud);
cfsetispeed(&tty, (speed_t)baud);
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~PARENB;
tty.c_cflag |= CSTOPB;
tty.c_cflag &= ~CRTSCTS;
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 1;
if(tcsetattr(fd, TCSANOW, &tty))
{
return -1;
}
return fd;
}
/* example usage */
int fd = serial_open("/dev/ttyUSB0", B9600);
Upvotes: 1