Accessing the Serial Port in Linux in C - c

I am trying to write and read data through serial port to a USB device in linux.I am able to write the data but I am not read the complete data that the USB device is sending to me.The underlying code is mine.Please do point out any mistake if so.
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<fcntl.h>
#include<termios.h>
#include<unistd.h>
#define SERIAL_PORT_PATH "/dev/ttyACM0"
struct termios SerialPortSettings;
unsigned char Buffer[256] = {0X01,0X04,0X00,0X4B,0x01,0XB1};
int Serial_Port_Descriptor = 0;
int Open_flag = O_RDWR | O_NOCTTY | O_NDELAY;
int Set_Nonblock_Open_flag();
int Serial_Port_Configuring();
int Read_Serial_Port();
int main()
{
Serial_Port_Descriptor = open(SERIAL_PORT_PATH,Open_flag);
if(Serial_Port_Descriptor > 0)
{
printf("Serial_Port has been Opened \n");
Set_Nonblock_Open_flag();
}
else
{
perror("Error:");
}
Serial_Port_Configuring();
write(Serial_Port_Descriptor,&Buffer,sizeof(Buffer));
sleep(2);
while(1)
{
Read_Serial_Port();
}
close(Serial_Port_Descriptor);
return 0;
}
int Set_Nonblock_Open_flag()
{
Open_flag = fcntl(Serial_Port_Descriptor,F_GETFL,Open_flag);
if(Open_flag == -1)
{
return -1;
}
else if (0)
{
Open_flag |= O_NONBLOCK;
printf("The Flag is set to Nonblock \n");
}
else
{
Open_flag &= ~O_NONBLOCK;
}
return fcntl(Serial_Port_Descriptor,F_SETFL,Open_flag);
}
int Serial_Port_Configuring()
{
tcgetattr(Serial_Port_Descriptor,&SerialPortSettings);
cfsetispeed(&SerialPortSettings,B115200);
cfsetospeed(&SerialPortSettings,B115200);
SerialPortSettings.c_cflag &= ~PARENB;
SerialPortSettings.c_cflag &= ~CSTOPB;
SerialPortSettings.c_cflag &= ~CSIZE;
SerialPortSettings.c_cflag |= CS8;
SerialPortSettings.c_cflag &= ~CRTSCTS;
SerialPortSettings.c_cflag |= CREAD | CLOCAL;
SerialPortSettings.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY);
SerialPortSettings.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG | IEXTEN);
SerialPortSettings.c_oflag &= ~OPOST; /* No Ouptut Processing */
SerialPortSettings.c_cc[VMIN] = 1; /* Read atleast 1 character */
SerialPortSettings.c_cc[VTIME] = 0; /* Wait Indefinitely */
tcflush(Serial_Port_Descriptor,TCIOFLUSH);
if(tcsetattr(Serial_Port_Descriptor,TCSANOW,&SerialPortSettings) != 0)
{
printf("Error: The Settings are not been Configured \n");
return -1;
}
else
{
printf("Settings have been Configured \n");
}
return 0;
}
int Read_Serial_Port()
{
int Serial_Port_Read = read(Serial_Port_Descriptor,&Buffer,sizeof(Buffer));
if(Serial_Port_Read < 0)
{
fputs("Read of bytes() has failed \n",stderr);
return -1;
}
else if(Serial_Port_Read > 0)
{
printf("%d bytes has been read \n",Serial_Port_Read);
for(int i=0;i <= Serial_Port_Read;i++)
{
printf("%02X",(unsigned char)Buffer[i]);
}
}
return 0;
}

Related

How to listen on serial port with C using CRTSCTS

I am trying to listen to a serial port with a C program utilizing CRTSCTS (to prevent an independently powered Arduino from rebooting after the computer it is connected to restarts).
I started with the code from here: Canonical Mode Linux Serial Port
After some adaptations it looks like this:
#define SERIALTERMINAL "/dev/ttyUSB0"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag |= CLOCAL | CREAD;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
//tty.c_cflag &= ~CRTSCTS;
tty.c_cflag |= ~CRTSCTS; //trying to turn on CRTSCTS
tty.c_cflag &= ~HUPCL; //trying turning off HUPCL - it works!
tty.c_lflag |= ICANON | ISIG; /* canonical input */
tty.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN);
tty.c_iflag &= ~IGNCR; /* preserve carriage return */
tty.c_iflag &= ~INPCK;
tty.c_iflag &= ~(INLCR | ICRNL | IUCLC | IMAXBEL);
tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* no SW flowcontrol */
//tty.c_iflag |= ~IXON; //try ixon
tty.c_oflag &= ~OPOST;
tty.c_cc[VEOL] = 0;
tty.c_cc[VEOL2] = 0;
tty.c_cc[VEOF] = 0x04;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
int main()
{
char *portname = SERIALTERMINAL;
int fd;
int wlen;
//fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); original version
fd = open(portname, O_RDONLY | O_NOCTTY);
if (fd < 0) {
printf("Error opening %s: %s\n", portname, strerror(errno));
return -1;
}
/*baudrate 115200, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd, B115200);
/* simple canonical input */
do {
unsigned char buf[700];
unsigned char *p;
int rdlen;
rdlen = read(fd, buf, sizeof(buf) - 1);
if (rdlen > 0) {
buf[rdlen] = 0;
printf("%s", buf);
} else if (rdlen < 0) {
printf("Error from read: %d: %s\n", rdlen, strerror(errno));
} else { /* rdlen == 0 */
printf("Nothing read. EOF?\n");
}
/* repeat read */
} while (1);
}
When the program is run it doesn't show any output.
Going back out of CRTSCTS mode by swapping:
tty.c_cflag |= ~CRTSCTS;
with
tty.c_cflag &= ~CRTSCTS;
the program will show output but it is then not in the CRTSCTS mode which I need in order to prevent sending a DTR signal which results in an Arduino reset.
I have tried quite a few different options after reading through the Termios documentation: http://man7.org/linux/man-pages/man3/termios.3.html but to no avail.
So the question is what combination of options will allow reading from the serial port without sending a DTR signal?

Serial port read is not complete

The functions below are used consequently to read data from serial port under Linux. I can read the complete data when I debug, but when I launch the program, read_buffer seems not to be complete. I receive the small part of the data correctly but the rest of the buffer is completely zero. What could be the problem?
int8_t __serial_port_open(uint8_t *port)
{
mode_t perms = S_IRWXU;
fd = open(port, O_RDWR | O_NOCTTY | O_SYNC, perms);
if (fd < 0)
{
return -1;
}
if (__serial_port_configure() != 0)
return -1;
return 0;
}
static int8_t __serial_port_configure(void)
{
struct termios attr;
if (tcgetattr(fd, &attr) == -1)
{
return -1;
}
if (cfsetispeed(&attr, B115200) == -1)
{
return -1;
}
if (cfsetospeed(&attr, B115200) == -1)
{
return -1;
}
attr.c_cflag |= (CLOCAL | CREAD);
attr.c_cflag &= ~PARENB;
attr.c_cflag &= ~CSTOPB;
attr.c_cflag &= ~CSIZE;
attr.c_cflag |= (CS8);
attr.c_cflag |= CRTSCTS;
attr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
attr.c_iflag &= ~(IXON | IXOFF | IXANY);
attr.c_oflag &= ~OPOST;
if (tcsetattr(fd, TCSANOW, &attr) == -1)
{
return -1;
}
return 0;
}
int8_t __serial_port_read(uint8_t *read_buffer, uint32_t nbytes_to_read, uint32_t *nbytes_read)
{
do
{
*nbytes_read = read(fd, read_buffer, nbytes_to_read);
if (*nbytes_read == -1)
{
return -1;
}
} while (*nbytes_read == 0);
return 0;
}
From the man
read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf.
Return Value
On success, the number of bytes read is returned (zero indicates end of file),
In other words count parameter is the maximum bytes you want to read, but read can return a different number of bytes.
Returned value gives you the number of read bytes from FD.
To simply solve it you can do a loop receiving bytes until the expected length is reached, reading 1 byte a time.
Other solution can be implemented using Read Timeouts

How to read character using serial port in Linux

I trying to read serial raw bytes from using serial port "/dev/ttyS0".In my program, What i want to do is to press the letter and immediately see the the letter I introduced repeated without pressing ENTER. For example, if I press the letter 'a' I want to see an other 'a' next to it.
My code is here:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
int main()
{
int n = 0, fd = 0;
struct termios term,trm;
printf("%d\n",getpid());
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open");
return 1;
}
else
{
fcntl(fd, F_SETFL, 0);
perror("Port");
}
if (n = tcgetattr(fd, &term) == -1)
{
perror("tcgetattr");
return 1;
}
if (n = cfsetispeed(&term, B115200) == -1)
{
perror("cfsetispeed");
return 1;
}
if (n = cfsetospeed(&term, B115200) == -1)
{
perror("cfsetospeed");
return 1;
}
term.c_cflag |= (CLOCAL | CREAD);
term.c_cflag &= ~PARENB;
term.c_cflag &= ~CSTOPB;
term.c_cflag &= ~CSIZE;
term.c_cflag |= CS8;
term.c_cflag &= ~CRTSCTS;
term.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
term.c_iflag &= ~(IXON | IXOFF | IXANY);
term.c_iflag |= (INPCK | ISTRIP);
term.c_oflag &= ~OPOST;
unsigned char c,d;
ssize_t s=0;
tcflush(fd, TCIOFLUSH);
system("/bin/stty raw");
while((c=getchar()) != 'q')
{
write(fd, &c,1);
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 0;
tcsetattr(fd, TCSANOW, &term);
if((s=read(fd, &d,1)) != -1)
{
perror("read");
printf("%c",d);
}
}
system("/bin/stty cooked");
close(fd);
return 0;
}
I don't know if it is the solution you are looking for, but you must disable stdin buffering to make getchar exits each char user enter.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
int main()
{
int n = 0, fd = 0;
struct termios term, old_stdin, new_stdin;
printf("%d\n",getpid());
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open");
return 1;
}
else
{
fcntl(fd, F_SETFL, 0);
perror("Port");
}
if (n = tcgetattr(fd, &term) == -1)
{
perror("tcgetattr");
return 1;
}
if (n = cfsetispeed(&term, B115200) == -1)
{
perror("cfsetispeed");
return 1;
}
if (n = cfsetospeed(&term, B115200) == -1)
{
perror("cfsetospeed");
return 1;
}
term.c_cflag |= (CLOCAL | CREAD);
term.c_cflag &= ~PARENB;
term.c_cflag &= ~CSTOPB;
term.c_cflag &= ~CSIZE;
term.c_cflag |= CS8;
term.c_cflag &= ~CRTSCTS;
term.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
term.c_iflag &= ~(IXON | IXOFF | IXANY);
term.c_iflag |= (INPCK | ISTRIP);
term.c_oflag &= ~OPOST;
unsigned char c,d;
ssize_t s=0;
tcflush(fd, TCIOFLUSH);
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 0;
tcsetattr(fd, TCSADRAIN, &term);
// get the terminal settings for stdin
tcgetattr(STDIN_FILENO,&old_stdin);
new_stdin = old_stdin;
// disable canonical mode (buffered i/o) and local echo
new_stdin.c_lflag &=(~ICANON & ~ECHO);
// set the new settings
tcsetattr(STDIN_FILENO,TCSANOW,&new_stdin);
while((c=getchar()) != 'q')
{
write(fd, &c,1);
if((s=read(fd, &d,1)) != -1)
{
perror("read");
printf("%c",d);
}
}
close(fd);
// Restore the old stdin setup
tcsetattr(STDIN_FILENO,TCSANOW,&old_stdin);
return 0;
}
You should change the terminal device's mode to "raw", by using
tty.setraw(file_descriptor)

Linux - reading from serial port error in C (Resource temporarily unavaliable)

I am trying to read some data from serial port using usb/rs232 converter. I am sending data from atmega and it is received properly in minicom. But trying to read sth in my program ends up with an error "Resource temporarily unavailable". I know that this is caused by O_NDELAY, but removing that gives me plenty of empty messages which also isn't good.
Actually, what I want to achieve is a program, which every second will transmit some char to atmega and wait for a response. Depending on a response it will do different actions. Also after few unanswered transmissions program will indicate an error with communication.
But for now I'd like to at least receive something properly.
Here is my code:
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int fd; //file descriptor
int bytes; // bytes to read
int PortOpen(void)
{
fd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0)
{
//opening error
printf("Port opening error\r\n");
}
else
{
printf("Port opened\r\n");
//port config
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag |= CLOCAL;
options.c_cflag |= CREAD;
options.c_cflag &= ~CRTSCTS;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 5;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
//Modifying c_iflag by bitwise OR and AND
options.c_iflag &= ~(ICRNL | INLCR | IGNCR | IUCLC);
options.c_iflag &= ~(IXON | IXOFF | IXANY);
//Modifying c_oflag by bitwise OR and AND
options.c_oflag &= ~OPOST;
tcflush(fd, TCIFLUSH);
//Setting the new settings for the port immediately
tcsetattr(fd, TCSANOW, &options);
}
return 1;
}
int PortRead(void)
{
int n = 0, spot = 0;
char buf = '\0';
/* Whole response*/
char response[1024];
memset(response, '\0', sizeof response);
do {
n = read( fd, &buf, 1 );
sprintf( &response[spot], "%c", buf );
spot += n;
} while( buf != '\r' && n > 0);
if (n < 0)
{
printf("Error reading: %s\r\n",strerror(errno));
}
else if (n == 0)
{
printf("Read nothing!\r\n");
}
else
{
printf("Response: %s", response);
}
return 1;
}
int main(void)
{
PortOpen();
int j;
for(j=0; j<100; j++) //just testing
{
PortRead();
}
return 0;
}

Linux, failing to read from serial port

I'm trying to connect via RS232 connection.
Communication parameters:
*Transmission rate: 1200 baud
*Character coding: 8-bit ASCII
*Parity: None
*Stop bits: 1
Commands are composed of two byte codes with the following format
Transmit format
CODE + "FFh"
Hex code
Receive format
CODE + "FFh"
Hex code
I tried various initializations but I still fail to read anything from the port the following code is one of them:
//RS232test.c
//Transmission rate: 1200 Baud
//8 bit, no parity 1 stop bits.
//Transmit format: CODE + "FFh"
//Receive format: CODE + "FFh"
//Last edited: 23/08/2014
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#define BAUDRATE B1200
#define MULTI "/dev/ttyS0"
//#define MULTI "/dev/ttyUSB0"
int open_port(struct termios *,struct termios *);
int setDtrRts(int, int);
void close_port(int, struct termios *);
int open_port(struct termios *tty, struct termios *tty_old)
//This opens the tty port for linux saves old port setting
//and saves the new ones
{
int fd; //file descriptor
fd = open(MULTI, O_RDWR | O_NOCTTY);
if (fd < 0) {
perror(MULTI);
printf("failed to open port\n");
exit(-1);
}
//get previous port settings so it can be restored on exit
tcgetattr(fd,tty_old);
//get port settings so they can be set
tcgetattr(fd,tty);
//Set baud rates to 1200
cfsetispeed(tty, BAUDRATE);
cfsetospeed(tty, BAUDRATE);
//ICANON -choosing canonical input.
tty->c_lflag |= (ICANON);
//tty->c_lflag &= ~(ISIG);
//unselecting echo
tty->c_lflag &= ~(ECHO | ECHOE);
//CLOCAL - setting local mode, CREAD - enabling receiver
tty->c_cflag |= (CLOCAL | CREAD);
//close doesn't change signals
tty->c_cflag &= ~HUPCL;
//8N1 no parity 1 stop bit
tty->c_cflag |= CS8;
//tty->c_cflag &= ~(PARENB | CSTOPB | CSIZE);
tty->c_cflag &= ~(PARENB | PARODD /**/| CSIZE);
tty->c_cflag &= ~CSTOPB;
//Raw output mode
tty->c_oflag &= ~OPOST;
//Enable hardware handshaking
//tty->c_cflag &= ~CRTSCTS;
//tty->c_iflag &= ~(IXON | IXOFF | IXANY); //*
//Flushing communication buffer and changing port setting
//tcflush(fd, TCIFLUSH);
//tcsetattr(fd, TCSANOW, tty);
tcsetattr(fd, TCSAFLUSH, tty);
setDtrRts(fd,1);
return fd;
}
int setDtrRts(int fd, int set)
//sets or clears the dtr and rts
//the needs both set during operation
//otherwise it switches off after approx. 20 seconds
{
int setbits;
setbits |= (TIOCM_DTR | TIOCM_RTS);
if(set)
return(ioctl(fd, TIOCMBIC, &setbits));
else
return(ioctl(fd, TIOCMBIS, &setbits));
}
void close_port(int fd, struct termios *tty_old)
//closing port
{
//reset to old options
//tcsetattrb(fd, TCSANOW, tty_old);
setDtrRts(fd,0);
close(fd);
}
int main(void)
{
int fd=0; //system file number
int buff_size; //no of characters in buffer
int bytes; //no of bytes in buffer
int ctr=0; //general counter
char in_buffer[] = "F3\xFF";
char out_buffer[255]; //serial character buffer
//new port setting and a structure to keep the old ones
struct termios tty,tty_old;
//checking if root
if (getuid()){
printf("You must be root to use this program.\n");
exit(-4);
}
printf("fd = %d\n",fd);
//opening port for reading and writing
fd = open_port(&tty,&tty_old);
printf("fd = %d\n",fd);
//flushing
tcflush(fd,TCIOFLUSH);
//sending command to serial port
//strcpy(in_buffer, "F3\xFF"); //placing a command in the buffer
printf("%s",in_buffer);
if((buff_size = write(fd, in_buffer, strlen(in_buffer))) < 0){
printf("Error while sending message\nBuffer contents:\t%s\n",in_buffer);
return -2;
}
usleep(50000); //delay for 50ms
out_buffer[0] = '\0';
ioctl(fd,FIONREAD,&bytes);
printf("\nThere are %d bytes in the buffer\n",bytes);
if(bytes > 0) {
//reading response from serial port
if((buff_size = read(fd, out_buffer,sizeof(out_buffer))) < 0){
printf("Error while reading message\n");
return -3;
}
//printing the decimal ASCII values of the response
printf("Multimeter response:\t");
while(out_buffer[ctr] != '\0')
{
printf("%i ",out_buffer[ctr]);
ctr++;
}
printf("\n%s\n",out_buffer);
} else printf("Buffer Empty\n");
//wrap things up
close_port(fd, &tty_old);
exit(0);
}
The programs output is as follows:
fd = 0
fd = 3
F3�h
There are 0 bytes in the buffer
Buffer Empty
Toyed around with several suggestions in previous posts but did not succeed.
The protocol you describe is not line oriented, so using canonical input mode is wrong. You should use the good old raw mode, defined as :
tty->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
tty->c_oflag &= ~OPOST;
tty->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty->c_cflag &= ~(CSIZE | PARENB);
tty->c_cflag |= CS8;
In canonical mode, characters are only made available for a read after the eol has been received to allow line edition, which is not what you want here. (reference : man termios)
following code is written by myself, and it's working on my embedded system all the time.
int wrap_uart_init(char *port, int baudrate, int datab, int parity, int stopb){
int fd=open_and_init_tty(port);
if (fd==-1) {
perror("cannot open device");
return fd;
}
set_baudrate(fd,baudrate);
set_dataformat(fd,datab,parity,stopb);
swflow_ctrl(fd);
return fd;
}
call this function like this:
int fd = wrap_uart_init("/dev/ttyUSB0", 1200, 8, 'N', 1);
super easy to use. it's even not important that what the physical layer protocol is, as long as Linux has masked the device into a tty file.
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
static struct termios origin_attrs;
static struct termios old_attrs;
int open_tty(const char *dev){
int fd=open(dev, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC);
if (fd==-1)
perror(FILE_OPEN_ERROR);
if (fcntl(fd, F_SETFL, 0)<0){
perror("fcntl error!");
close(fd);
fd=-1;
}
if (!isatty(STDIN_FILENO)){
perror("standard input error! ");
close(fd);
fd=-1;
}
return fd;
}
void close_tty(int fd){
if (tcsetattr(fd,TCSANOW,&old_attrs)) {
perror(GET_ATTR_ERROR);
}
close(fd);
}
int open_and_init_tty(const char *dev){
int fd=open_tty(dev);
if (fd==-1){
perror(FILE_OPEN_ERROR);
return -1;
}
if (tcgetattr(fd,&old_attrs)) {
perror(GET_ATTR_ERROR);
return -1;
}
struct termios opt;
int br=B9600;
cfsetispeed(&opt, br);
cfsetospeed(&opt, br);
opt.c_cflag = (CS8 | CLOCAL | CREAD);
opt.c_iflag = (IGNPAR | IXON | IXOFF | IXANY);
opt.c_lflag = 0;
opt.c_oflag = 0;
opt.c_cc[VTIME] = 30;
opt.c_cc[VMIN] = 5;
tcflush(fd, TCIOFLUSH);
if (tcsetattr(fd,TCSANOW,&opt) != 0) {
perror(SET_ATTR_ERROR);
return -1;
}
return fd;
}
int set_baudrate(int fd, int baud){
int br;
int status;
struct termios opt;
if (tcgetattr(fd, &opt)) {
perror(GET_ATTR_ERROR);
return -1;
}
switch (baud) {
case 115200: br=B115200;break;
// case 76800: br=B76800; break;
case 57600: br=B57600; break;
case 38400: br=B38400; break;
case 19200: br=B19200; break;
case 9600: br=B9600; break;
case 4800: br=B4800; break;
case 2400: br=B2400; break;
case 1200: br=B1200; break;
case 600: br=B600; break;
case 300: br=B300; break;
default: perror("Wrong Baud rate!");
return -1;
}
tcflush(fd, TCIOFLUSH);
cfsetispeed(&opt, br);
cfsetospeed(&opt, br);
status = tcsetattr(fd, TCSANOW, &opt);
if (status) {
perror(BAUD_RATE_ERROR);
return -2;
}
tcflush(fd,TCIOFLUSH);
return 0;
}
int set_dataformat(int fd,int databits,int parity,int stopbits){
struct termios options;
if (tcgetattr(fd,&options)) {
perror(GET_ATTR_ERROR);
return -1;
}
options.c_cflag &= ~CSIZE;
switch (databits) {
case 5:
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
perror("Unsupported data size");
return -2;
}
switch (parity) {
case 'n': //no parity check
case 'N':
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o': //odd check
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= (INPCK | ISTRIP);
break;
case 'e': //even check
case 'E':
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= (INPCK | ISTRIP);
break;
default:
perror("Unsupported parity");
return -3;
}
switch (stopbits) {
case 1: //1 stop bit
options.c_cflag &= ~CSTOPB;
break;
case 2: //2 stop bits
options.c_cflag |= CSTOPB;
break;
default:
perror("Unsupported stop bits");
return -4;
}
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME] = 50;
options.c_cc[VMIN] = 1;
if (tcsetattr(fd,TCSANOW,&options) != 0) {
perror(SET_ATTR_ERROR);
return -1;
}
return 0;
}
int set_databit(int fd, int databits){
struct termios options;
if (tcgetattr(fd,&options)) {
perror(GET_ATTR_ERROR);
return -1;
}
options.c_cflag &= ~CSIZE;
switch (databits) {
case 5:
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
perror("Unsupported data size");
return -1;
}
tcflush(fd,TCIFLUSH);
if (tcsetattr(fd,TCSANOW,&options) != 0) {
perror(SET_ATTR_ERROR);
return -2;
}
return 0;
}
int set_parity(int fd, int parity) {
struct termios options;
if (tcgetattr(fd,&options)) {
perror(GET_ATTR_ERROR);
return -1;
}
options.c_cflag &= ~CSIZE;
switch (parity) {
case 'n': //no parity check
case 'N':
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o': //odd check
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= (INPCK | ISTRIP);
break;
case 'e': //even check
case 'E':
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= (INPCK | ISTRIP);
break;
default:
perror("Unsupported parity");
return -1;
}
tcflush(fd,TCIFLUSH);
if (tcsetattr(fd,TCSANOW,&options) != 0) {
perror(SET_ATTR_ERROR);
return -2;
}
return 0;
}
int set_stopbit(int fd, int stopbits) {
struct termios options;
if (tcgetattr(fd,&options)) {
perror(GET_ATTR_ERROR);
return -1;
}
options.c_cflag &= ~CSIZE;
switch (stopbits) {
case 1: //1 stop bit
options.c_cflag &= ~CSTOPB;
break;
case 2: //2 stop bits
options.c_cflag |= CSTOPB;
break;
default:
perror("Unsupported stop bits");
return -1;
}
tcflush(fd,TCIFLUSH);
if (tcsetattr(fd,TCSANOW,&options) != 0) {
perror(SET_ATTR_ERROR);
return -2;
}
return 0;
}
int hwflow_ctrl(int fd){
struct termios options;
if (tcgetattr(fd,&options)) {
perror(GET_ATTR_ERROR);
return -1;
}
options.c_cflag |= CRTSCTS;
options.c_iflag &= ~(IXON | IXOFF | IXANY);
tcflush(fd,TCIFLUSH);
if (tcsetattr(fd,TCSANOW,&options) != 0) {
perror(SET_ATTR_ERROR);
return -2;
}
return 0;
}
int swflow_ctrl(int fd){
struct termios options;
if (tcgetattr(fd,&options)) {
perror(GET_ATTR_ERROR);
return -1;
}
options.c_cflag &= ~CRTSCTS;
options.c_iflag |= (IXON | IXOFF | IXANY);
tcflush(fd,TCIFLUSH);
if (tcsetattr(fd,TCSANOW,&options) != 0) {
perror(SET_ATTR_ERROR);
return -2;
}
return 0;
}
int store_termios(int fd){
if (tcgetattr( fd,&origin_attrs)) {
perror(GET_ATTR_ERROR);
return -1;
}
return 0;
}
int recover_termios(int fd){
tcflush(fd, TCIOFLUSH);
if (tcsetattr(fd,TCSANOW,&origin_attrs)) {
perror(SET_ATTR_ERROR);
return -1;
}
tcflush(fd, TCIOFLUSH);
return 0;
}

Resources