progpib/pty-gpib-emulator/middle-man/MiddleMan.cpp

144 lines
3.5 KiB
C++

#include "MiddleMan.h"
#include <iostream>
#include <unistd.h>
#include <pty.h>
#include <termios.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
static void setPort(int fd) {
/* *** Configure Port *** */
struct termios tty;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if ( tcgetattr ( fd, &tty ) != 0 ) {
std::cout << "Error tcgetattr()" << std::endl;
}
/* Set Baud Rate */
cfsetospeed (&tty, B9600);
cfsetispeed (&tty, B9600);
/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
// no signaling chars, no echo, no canonical processing
tty.c_lflag = 0;
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
// 0.5 seconds read timeout
tty.c_cc[VTIME] = 5;
// turn on READ & ignore ctrl lines
tty.c_cflag |= CREAD | CLOCAL;
// turn off s/w flow ctrl
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
tty.c_oflag &= ~OPOST; // make raw
/* Flush Port, then applies attributes */
tcflush( fd, TCIFLUSH );
if ( tcsetattr ( fd, TCSANOW, &tty ) != 0) {
std::cout << "Error tcsetattr()" << std::endl;
}
}
static void set_noecho(int fd) { // Turn off Slave echo
struct termios stermios;
if (tcgetattr(fd, &stermios) < 0)
std::cout << "Error tcgetattr()" << std::endl;
stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
stermios.c_oflag &= ~(ONLCR);
/* also turn off NL to CR/NL mapping on output */
if (tcsetattr(fd, TCSANOW, &stermios) < 0)
std::cout << "Error tcsetattr()" << std::endl;
}
MiddleMan::MiddleMan(const string tty,
const string fout_name,
int sleepTime) {
char name[40];
if (openpty(&this->mPTY, &this->sPTY, name, NULL, NULL) < 0)
std::cerr << "Could not open pty device" << std::endl;
else {
set_noecho(this->sPTY);
this->ptyname = name;
this->running = false;
}
if ( (this->mTTY = open(tty.c_str(), O_RDWR| O_NONBLOCK)) < 0 ) {
std::cerr << "Could not open tty device" << std::endl;
} else {
this->ttyname = tty;
setPort(this->mTTY);
}
if ( (this->fout = fopen(fout_name.c_str(), "w+")) == NULL )
std::cout << "Error upon opening the output file" << std::endl;
this->sleep = sleepTime;
}
MiddleMan::~MiddleMan() {
close(this->mPTY);
fclose(this->fout);
}
string MiddleMan::getPTY() {
return this->ptyname;
}
string readTTY(int master, int readLen=100) {
char *tty_in = new char[readLen+1];
string tty_full;
int i=0;
tty_full = "";
while ((i=read(master, tty_in, readLen)) >= readLen) {
tty_in[i] = '\0';
tty_full += tty_in;
}
tty_in[i] = '\0';
tty_full += tty_in;
delete[] tty_in;
return tty_full;
}
void MiddleMan::run(int readLen) {
this->running = true;
while (this->running) {
this->handleInput(readTTY(this->mPTY, readLen));
}
}
void MiddleMan::handleInput(string tty_in) {
string buf;
write(this->mTTY, tty_in.c_str(), tty_in.size());
usleep(this->sleep); // microseconds
buf = readTTY(this->mTTY);
write(this->mPTY, buf.c_str(), buf.size());
this->log(tty_in, buf);
}
void MiddleMan::log(string input, string output,
const string format) {
printf(format.c_str(), input.c_str(), output.c_str());
fprintf(this->fout, format.c_str(), input.c_str(), output.c_str());
fflush(this->fout);
}