From cb51a145753870699a2c725dc711f2233e47ed73 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 25 Jun 2020 21:17:38 +0100 Subject: [PATCH] Create a pseudo TTY for the AX25 Network. --- AX25Network.h | 16 ++-- MMDVMHost.vcxproj | 2 + MMDVMHost.vcxproj.filters | 6 ++ Makefile | 2 +- PseudoTTYController.cpp | 161 ++++++++++++++++++++++++++++++++++++++ PseudoTTYController.h | 40 ++++++++++ 6 files changed, 218 insertions(+), 9 deletions(-) create mode 100644 PseudoTTYController.cpp create mode 100644 PseudoTTYController.h diff --git a/AX25Network.h b/AX25Network.h index 37804d6..34aa43b 100644 --- a/AX25Network.h +++ b/AX25Network.h @@ -19,7 +19,7 @@ #ifndef AX25Network_H #define AX25Network_H -#include "SerialController.h" +#include "PseudoTTYController.h" #include #include @@ -42,13 +42,13 @@ public: void close(); private: - CSerialController m_serial; - unsigned char* m_txData; - unsigned char* m_rxData; - unsigned int m_rxLength; - unsigned char m_rxLastChar; - bool m_debug; - bool m_enabled; + CPseudoTTYController m_serial; + unsigned char* m_txData; + unsigned char* m_rxData; + unsigned int m_rxLength; + unsigned char m_rxLastChar; + bool m_debug; + bool m_enabled; }; #endif diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index 8c3375b..7f64db6 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -227,6 +227,7 @@ + @@ -326,6 +327,7 @@ + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index a144fce..00ed473 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -320,6 +320,9 @@ Header Files + + Header Files + @@ -601,5 +604,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index 985ab3c..3f34ccd 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ OBJECTS = AX25Control.o AX25Network.o \ DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o \ ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o \ NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o \ - P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ + P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o \ YSFFICH.o YSFNetwork.o YSFPayload.o diff --git a/PseudoTTYController.cpp b/PseudoTTYController.cpp new file mode 100644 index 0000000..a21fb3d --- /dev/null +++ b/PseudoTTYController.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2019,2020 by Jonathan Naylor G4KLX + * Copyright (C) 1999-2001 by Thomas Sailor HB9JNX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(_WIN32) && !defined(_WIN64) + +#include "SerialController.h" +#include "Log.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +CPseudoTTYController::CPseudoTTYController(const std::string& device, unsigned int speed, bool assertRTS) : +CSerialController(device, speed, assertRTS) +{ +} + +CPseudoTTYController::~CPseudoTTYController() +{ +} + +bool CPseudoTTYController::open() +{ + assert(m_fd == -1); + + m_fd = ::posix_openpt(O_RDWR | O_NOCTTY | O_NDELAY); + if (m_fd < 0) { + LogError("Cannot open device - %s", m_device.c_str()); + return false; + } + + std::string slave = std::string(::ptsname(m_fd)); + + // Remove any previous stale symlink + ::unlink(m_device.c_str()); + + int ret = ::symlink(slave.c_str(), m_device.c_str()); + if (ret != 0) { + LogError("Cannot make symlink to %s with %s", slave.c_str(), m_device.c_str()); + close(); + return false; + } + + m_device = std::string(::ttyname(m_fd)); + + if (::isatty(m_fd)) { + termios termios; + if (::tcgetattr(m_fd, &termios) < 0) { + LogError("Cannot get the attributes for %s", m_device.c_str()); + ::close(m_fd); + return false; + } + + termios.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK); + termios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL); + termios.c_iflag &= ~(IXON | IXOFF | IXANY); + termios.c_oflag &= ~(OPOST); + termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS); + termios.c_cflag |= (CS8 | CLOCAL | CREAD); + termios.c_lflag &= ~(ISIG | ICANON | IEXTEN); + termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); + termios.c_cc[VMIN] = 0; + termios.c_cc[VTIME] = 10; + + switch (m_speed) { + case 1200U: + ::cfsetospeed(&termios, B1200); + ::cfsetispeed(&termios, B1200); + break; + case 2400U: + ::cfsetospeed(&termios, B2400); + ::cfsetispeed(&termios, B2400); + break; + case 4800U: + ::cfsetospeed(&termios, B4800); + ::cfsetispeed(&termios, B4800); + break; + case 9600U: + ::cfsetospeed(&termios, B9600); + ::cfsetispeed(&termios, B9600); + break; + case 19200U: + ::cfsetospeed(&termios, B19200); + ::cfsetispeed(&termios, B19200); + break; + case 38400U: + ::cfsetospeed(&termios, B38400); + ::cfsetispeed(&termios, B38400); + break; + case 115200U: + ::cfsetospeed(&termios, B115200); + ::cfsetispeed(&termios, B115200); + break; + case 230400U: + ::cfsetospeed(&termios, B230400); + ::cfsetispeed(&termios, B230400); + break; + case 460800U: + ::cfsetospeed(&termios, B460800); + ::cfsetispeed(&termios, B460800); + break; + default: + LogError("Unsupported serial port speed - %u", m_speed); + ::close(m_fd); + return false; + } + + if (::tcsetattr(m_fd, TCSANOW, &termios) < 0) { + LogError("Cannot set the attributes for %s", m_device.c_str()); + ::close(m_fd); + return false; + } + + if (m_assertRTS) { + unsigned int y; + if (::ioctl(m_fd, TIOCMGET, &y) < 0) { + LogError("Cannot get the control attributes for %s", m_device.c_str()); + ::close(m_fd); + return false; + } + + y |= TIOCM_RTS; + + if (::ioctl(m_fd, TIOCMSET, &y) < 0) { + LogError("Cannot set the control attributes for %s", m_device.c_str()); + ::close(m_fd); + return false; + } + } + } + + return true; +} + +#endif + diff --git a/PseudoTTYController.h b/PseudoTTYController.h new file mode 100644 index 0000000..9f9a921 --- /dev/null +++ b/PseudoTTYController.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 by Jonathan Naylor G4KLX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PseudoTTYController_H +#define PseudoTTYController_H + +#if !defined(_WIN32) && !defined(_WIN64) + +#include + +#include "SerialController.h" + +class CPseudoTTYController : public CSerialController { +public: + CPseudoTTYController(const std::string& device, unsigned int speed, bool assertRTS = false); + virtual ~CPseudoTTYController(); + + virtual bool open(); + +protected: +}; + +#endif + +#endif