I'm trying to use a pseudo tty to send and receive data, in order to later use a real tty linked to a serial RS232 USB adapter.
I first create the pseudo tty using socat
:
sudo socat -d -d pty,link=./ttyUSB0,echo=0,perm=0666 pty,link=./ttyUSB1,echo=0,perm=0666
The transmiter seems to manage to send data, but the receiver doesn't receive it. I first run the receiver that block on the first call to read()
function. Then I run the transmiter to send data to it.
Here is the transmiter program:
#define _GNU_SOURCE
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
float data[100000];
int main() {
int fdm = -1;
fdm = open("./ttyUSB0",O_RDWR);
if(fdm < 0) { perror("Error"); exit(EXIT_FAILURE); }
grantpt(fdm);
unlockpt(fdm);
int i;
for(i=0; i<100000; i++) {
if(i%100 == 0) { printf("\rTransmit %d / %d",i,100000); fflush(stdout); }
write(fdm,&data[i],sizeof(float));
}
}
And the receiver program:
#define _GNU_SOURCE
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
float data[100000];
int main() {
int fds = open("./ttyUSB1",O_RDWR);
if(fds < 0) { perror("Error"); exit(EXIT_FAILURE); }
grantpt(fds);
unlockpt(fds);
int i;
for(i=0; i<100000; i++) {
if(i%100 == 0) { printf("\rReceive %d / %d",i,100000); fflush(stdout); }
read(fds,&data[i],sizeof(float));
}
}
When I run cat ./ttyUSB1
and echo abcd >> ./ttyUSB0
, the cat
command print the message sent with echo
.
So the problem seems to come from my program.
I followed the tutorial of mbedded ninja about serial port programming, to configure the pseudo tty like a real tty. Now it seems to work without problems.
Here is the code of the transmitter, having done the same tty settings for the receiver:
#define _GNU_SOURCE
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
float data[100000];
int main() {
int fdm = -1;
fdm = open("./ttyUSB0",O_RDWR);
if(fdm < 0) { perror("Error"); exit(EXIT_FAILURE); }
grantpt(fdm);
unlockpt(fdm);
struct termios tty;
if(tcgetattr(fdm, &tty) != 0) {
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
}
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
tty.c_cflag &= ~CSIZE; // Clear all the size bits, then use one of the statements below
tty.c_cflag |= CS8; // 8 bits per byte (most common)
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
tty.c_lflag &= ~ICANON; // disable input cannonical mode
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
tty.c_cc[VMIN] = 0;
cfsetispeed(&tty, B115200);
cfsetospeed(&tty, B115200);
cfsetspeed(&tty, B115200); // set both input and output speed
if (tcsetattr(fdm, TCSANOW, &tty) != 0) {
printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
}
int i;
for(i=0; i<100000; i++) {
if(i%100 == 0) { printf("\rTransmit %d / %d",i,100000); fflush(stdout); }
write(fdm,&data[i],sizeof(float));
}
}