0

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;
}
Gaurav Minocha
  • 706
  • 1
  • 5
  • 10
msc
  • 33,420
  • 29
  • 119
  • 214
  • It is not necessary to integrate your port configuration into the while loop. Better to put them before the tcflush call. In addition, using system() to configure your port via stty is not necessary too, you are already configuring by using termios struct. – ogs Feb 04 '16 at 06:13
  • include fntl, stlib, stdio. termios and add return value. Please compile your code first, before you post it here – Gaurav Minocha Feb 04 '16 at 06:20
  • Possible duplicate of [How to avoid press enter with any getchar()](http://stackoverflow.com/questions/1798511/how-to-avoid-press-enter-with-any-getchar) – user253751 Feb 04 '16 at 06:23
  • @Gaurav My mistake, already added the header file. – msc Feb 04 '16 at 06:25
  • 1
    *" What i want to do is to press the letter and immediately see the the letter I introduced repeated without pressing ENTER"* -- This seems like a question only about **stdin** and **stdout**, and nothing to do with a serial port. – sawdust Feb 04 '16 at 06:31
  • @sawdust How to do in serial port? – msc Feb 04 '16 at 06:34
  • 1
    Assuming you have properly configured the serial port using the termios, then a character sent to the serial port can be *echoed* (a) ***locally*** by enabling ECHO in *c_lflag*, and/or (b) ***remotely*** by the device on the other end of the serial link. Note that this means that you can get a single or double echo (or no echo at all) depending on how ***everything*** is setup. – sawdust Feb 04 '16 at 06:54

2 Answers2

1

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;
}
LPs
  • 16,045
  • 8
  • 30
  • 61
0

You should change the terminal device's mode to "raw", by using

tty.setraw(file_descriptor)
Emre Tapcı
  • 1,743
  • 17
  • 16