Search code examples
cserial-porttermiossocat

Programming pseudo terminals communication by termios. Parity bit option doesn't works


I need to make a chat using serial ports. I emulate pty by socat:

socat -d -d PTY PTY

Next I wrote small demo. That's how I initialize termios structure:

    int tty_fd = open(argv[1], O_RDWR | O_NONBLOCK);
    struct termios tio;
    bzero(&tio, sizeof(tio));
    // Frame bus runs at 38,400 BAUD
    const int BAUD_Rate = B38400;

    cfsetispeed(&tio, BAUD_Rate);
    cfsetospeed(&tio, BAUD_Rate);

    // Initialize to raw mode. PARMRK and PARENB will be over-ridden before calling tcsetattr()
    cfmakeraw(&tio);

    // Ignore modem lines and enable receiver and set bit per byte
    tio.c_cflag |= CLOCAL | CREAD | CS8;

    // NOTE: The following block overrides PARMRK and PARENB bits cleared by cfmakeraw.
    tio.c_cflag |=  PARENB;         // Enable even parity generation
    tio.c_iflag |=  INPCK;          // Enable parity checking
    tio.c_iflag |=  PARMRK;         // Enable in-band marking 
    tio.c_iflag &= ~IGNPAR;         // Make sure input parity errors are not ignored
    if (is_odd) 
            tio.c_cflag |= PARODD;
    tcsetattr(tty_fd, TCSANOW, &tio);

Next my whole demo listing:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h> 

struct termios init(int);

int main(int argc,char** argv)
{
        struct termios tio;
        char c = 0;
        int tty_fd = open(argv[1], O_RDWR | O_NONBLOCK);

        tio = init(strcmp(argv[3], "odd"));

        if (tcsetattr(tty_fd, TCSANOW, &tio) == -1)
        {
                printf("Failed to setup the port");
                return -1;
        }

        if (strcmp(argv[2], "write") == 0)
        {
                while (c != 'q')
                {
                        scanf("%c", &c);
                        write(tty_fd, &c, 1);
                }
        }
        if (strcmp(argv[2], "read") == 0)
        {
                while (c != 'q')
                {
                        if (read(tty_fd, &c, 1) > 0)
                                printf("%c", c);
                }
        }
        close(tty_fd);
}

struct termios init(int is_odd)
{
        struct termios tio;
        bzero(&tio, sizeof(tio));
        // Frame bus runs at 38,400 BAUD
        const int BAUD_Rate = B38400;

        cfsetispeed(&tio, BAUD_Rate);
        cfsetospeed(&tio, BAUD_Rate);

        // Initialize to raw mode. PARMRK and PARENB will be over-ridden before calling tcsetattr()
        cfmakeraw(&tio);

        // Ignore modem lines and enable receiver and set bit per byte
        tio.c_cflag |= CLOCAL | CREAD | CS8;

        // NOTE: The following block overrides PARMRK and PARENB bits cleared by cfmakeraw.
        tio.c_cflag |=  PARENB;         // Enable even parity generation
        tio.c_iflag |=  INPCK;          // Enable parity checking
        tio.c_iflag |=  PARMRK;         // Enable in-band marking 
        tio.c_iflag &= ~IGNPAR;         // Make sure input parity errors are not ignored
        if (is_odd == 0) 
                tio.c_cflag |= PARODD;
        return tio;
}

When I starte one application as reader, and other as writer with similar parity, all goes OK. But when I try to test parity bit setting, I start them with different partity, all goes OK too. All messages sends without any error.
Is that because of pseudo terminal use, instead of real COM-port?
Or maybe the way I create a pty?

Also my partner try to do the similar test using python, and has similar result too. I use Linux Mint 17.3.

Thanks for your replays.


Solution

  • I have read pty's man page and found that termios'es c_cflag flags dont supported by pseudo terminal at all.