• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer navigation

The Geek Diary

  • OS
    • Linux
    • CentOS/RHEL
    • Solaris
    • Oracle Linux
    • VCS
  • Interview Questions
  • Database
    • oracle
    • oracle 12c
    • ASM
    • mysql
    • MariaDB
  • DevOps
    • Docker
    • Shell Scripting
  • Big Data
    • Hadoop
    • Cloudera
    • Hortonworks HDP

Serial Port Programming: tcflush – TCIFLUSH,TCOFLUSH example

by admin

termios

The termios module provides a POSIX-style interface for controlling the behavior of TTYs and other serial communication devices on UNIX systems. All the functions operate on integer file descriptors such as those returned by the os.open() function or the fileno() method of a file object. In addition, the module relies on a large collection of constants that are also defined in this module.

tcflush flushes/discards:

  • data which is written but not transmitted and/or
  • data which is received but not read by user

The exact operation depends on the ‘queue_selector’ argument.

#include <termios.h>
int tcflush(int fildes, int queue_selector);

Possible values of queue_selector are:

  • TCIFLUSH – Flushes/Discards received data, but not read.
  • TCOFLUSH – Flushes/Discards written data, but not transmitted.
  • TCIOFLUSH – Flushes/Discards both.

For example, the following example flushes pending input data:

int rc;
rc = tcflush(fd,TCIFLUSH);

Let’s write a sample code to check what happens when we:

  1. Loop until there are bytes in input buffer using ‘FIONREAD’ ioctl.
  2. Call tcflush with queue selector ‘TCIFLUSH’.
  3. Check how many bytes are present in input buffer with ‘FIONREAD’ ioctl.

Need two USB to serial/serial devices connected (TX-RX/RX-TX)

Code:

#include <stdio.h>
#include <sys/types.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>

#define MAX_BYTES_TO_READ	50
#define SERIAL_DEVICE	"/dev/ttyUSB0"

int main()
{
	struct termios serial_port_settings;
	int fd;
	int retval;
	char buf[256];
	int bytes_available;
	int i;

	fd = open(SERIAL_DEVICE, O_RDWR);
	if (fd < 0) {
		perror("Failed to open SERIAL_DEVICE");
		exit(1);
	}
	
	retval = tcgetattr(fd, &serial_port_settings);
	if (retval < 0) {
		perror("Failed to get termios structure");
		exit(2);
	}

	//setting baud rate to B38400
	retval = cfsetospeed(&serial_port_settings, B38400);
	if (retval < 0) {
		perror("Failed to set 38400 output baud rate");
		exit(3);
	}
	retval = cfsetispeed(&serial_port_settings, B38400);
	if (retval < 0) {
		perror("Failed to set 38400 input baud rate");
		exit(4);
	}
	serial_port_settings.c_lflag &= ~(ICANON);
	serial_port_settings.c_lflag &= ~(ECHO | ECHOE);
	retval = tcsetattr(fd, TCSANOW, &serial_port_settings);
	if (retval < 0) {
		perror("Failed to set serial attributes");
		exit(5);
	}
	printf("Successfully set the baud rate\n");
	while (1) {
		retval = ioctl(fd, FIONREAD, &bytes_available);
		if (retval < 0) {
			perror("FIONREAD ioctl failed\n");
			exit(6);
		}
		usleep(50*1000L);
		if (bytes_available > 0)
			break;
	}
	printf("tcflush: Bytes available in the input buffer before TCIFLUSH:%d\n",
			bytes_available);
	tcflush(fd, TCIFLUSH);
	retval = ioctl(fd, FIONREAD, &bytes_available);
	if (retval < 0) {
		perror("FIONREAD ioctl failed\n");
		exit(7);
	}
	printf("tcflush:Bytes available in the input buffer after TCIFLUSH:%d\n",
			bytes_available);
	close(fd);
	return 0;
}

Output:

tcflush input

Same behavior will happen when we call write on the serial port with large number of bytes, and in the next statement call tcflush with queue selector ‘TCOFLUSH’ not all data will be received by the other serial port.

Receive Code: (fionread)

Consider the example shown below:

#include <stdio.h>
#include <sys/types.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>

#define SERIAL_DEVICE	"/dev/ttyUSB0"

int main()
{
	struct termios serial_port_settings;
	int fd;
	int retval;
	char buf[256];
	int i;
	int bytes_available;

	fd = open(SERIAL_DEVICE, O_RDWR);
	if (fd < 0) {
		perror("Failed to open SERIAL_DEVICE");
		exit(1);
	}
	
	retval = tcgetattr(fd, &serial_port_settings);
	if (retval < 0) {
		perror("Failed to get termios structure");
		exit(2);
	}

	//setting baud rate to B38400
	retval = cfsetospeed(&serial_port_settings, B38400);
	if (retval < 0) {
		perror("Failed to set 38400 output baud rate");
		exit(3);
	}
	retval = cfsetispeed(&serial_port_settings, B38400);
	if (retval < 0) {
		perror("Failed to set 38400 input baud rate");
		exit(4);
	}
	serial_port_settings.c_lflag &= ~(ICANON);
	serial_port_settings.c_lflag &= ~(ECHO | ECHOE);
	retval = tcsetattr(fd, TCSANOW, &serial_port_settings);
	if (retval < 0) {
		perror("Failed to set serial attributes");
		exit(5);
	}
	printf("/dev/ttyUSB0:Successfully set the baud rate\n");
	while (1) {
		retval = ioctl(fd, FIONREAD, &bytes_available);
		if (retval < 0) {
			perror("FIONREAD ioctl failed\n");
			exit(6);
		}
		sleep(5);
		if (bytes_available > 0)
			break;
	}
	printf("/dev/ttyUSB0:Bytes in input buffer:%d\n", bytes_available);
	close(fd);
	return 0;
}

TransmitCode:(tcflush_output)

Consider the example shown below:

#include <stdio.h>
#include <sys/types.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#define SERIAL_DEVICE	"/dev/ttyUSB1"

int main()
{
	struct termios serial_port_settings;
	int fd;
	int retval;
	char *buf = NULL;
	int bufsize = 0;

	fd = open(SERIAL_DEVICE, O_RDWR);
	if (fd < 0) {
		perror("Failed to open SERIAL_DEVICE");
		exit(1);
	}
	
	retval = tcgetattr(fd, &serial_port_settings);
	if (retval < 0) {
		perror("Failed to get termios structure");
		exit(2);
	}

	//setting baud rate to B38400
	retval = cfsetospeed(&serial_port_settings, B38400);
	if (retval < 0) {
		perror("Failed to set 38400 output baud rate");
		exit(3);
	}
	retval = cfsetispeed(&serial_port_settings, B38400);
	if (retval < 0) {
		perror("Failed to set 38400 input baud rate");
		exit(4);
	}
	serial_port_settings.c_lflag |= ICANON; 
	serial_port_settings.c_oflag |= OCRNL;
	serial_port_settings.c_oflag |= OLCUC;
	retval = tcsetattr(fd, TCSANOW, &serial_port_settings);
	if (retval < 0) {
		perror("Failed to set serial attributes");
		exit(5);
	}
	printf("/dev/ttyUSB1:Successfully set the baud rate\n");
loop:	
	printf("/dev/ttyUSB1:Enter size of the buffer:");
	scanf("%d", &bufsize);
	if (bufsize <= 0) {
		printf("Buffer size should be greater > 0\n");
		goto loop;
	}
	buf = malloc(bufsize);
	if (!buf) {
		perror("Failed to allocate buffer\n");
		exit(6);
	}
	memset(buf, 'A', bufsize);
	buf[bufsize-2] = '\n';
	buf[bufsize-1] = '\0';
	retval = write(fd, buf, bufsize);
	if (retval < 0) {
		perror("write on SERIAL_DEVICE failed");
		exit(7);
	}
	tcflush(fd, TCOFLUSH);
	printf("/dev/ttyUSB1: Flushing output buffer\n");
	free(buf);
	close(fd);
	return 0;
}

Output:

tcflush output

Filed Under: C, C Library

Some more articles you might also be interested in …

  1. C Pointers
  2. Basics of C Structures
  3. Basics of C Arrays
  4. make: Nothing to be done for `default’
  5. C Arrays
  6. StringCchCat Function example
  7. Introduction to C Language
  8. Basics of C Functions
  9. C Looping Statements
  10. Yocto recipetool tutorial

You May Also Like

Primary Sidebar

Recent Posts

  • powertop Command Examples in Linux
  • powertop: command not found
  • powerstat: command not found
  • powerstat Command Examples in Linux

© 2023 · The Geek Diary

  • Archives
  • Contact Us
  • Copyright