Initial commit of pty rewrite

merge-requests/4/head
Phil Taylor 2021-05-11 09:38:05 +01:00
rodzic 5ce4e49c5f
commit 944b0f5987
4 zmienionych plików z 123 dodań i 107 usunięć

Wyświetl plik

@ -2,94 +2,54 @@
#include "logcategories.h"
#include <QDebug>
#include <QFile>
#include <sstream>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
// Copyright 2017-2021 Elliott H. Liggett & Phil Taylor
pttyHandler::pttyHandler(QString pty)
{
//constructor
// grab baud rate and other comm port details
// if they need to be changed later, please
// destroy this and create a new one.
port = new QSerialPort();
portName = pty;
#ifdef Q_OS_WIN
port = new QSerialPort();
// TODO: The following should become arguments and/or functions
// Add signal/slot everywhere for comm port setup.
// Consider how to "re-setup" and how to save the state for next time.
baudRate = 115200;
stopBits = 1;
#ifdef Q_OS_WIN
portName = pty;
#else
Q_UNUSED(pty);
portName = "/dev/ptmx";
#endif
if (portName != "" && portName != "None") {
setupPtty(); // basic parameters
openPort();
//qDebug(logSerial()) << "Serial buffer size: " << port->readBufferSize();
//port->setReadBufferSize(1024); // manually. 256 never saw any return from the radio. why...
//qDebug(logSerial()) << "Serial buffer size: " << port->readBufferSize();
connect(port, SIGNAL(readyRead()), this, SLOT(receiveDataIn()));
}
}
pttyHandler::pttyHandler(QString portName, quint32 baudRate)
{
//constructor
// grab baud rate and other comm port details
// if they need to be changed later, please
// destroy this and create a new one.
port = new QSerialPort();
this->portName = portName;
this->baudRate = baudRate;
setupPtty(); // basic parameters
openPort();
// TODO: The following should become arguments and/or functions
// Add signal/slot everywhere for comm port setup.
// Consider how to "re-setup" and how to save the state for next time.
// qDebug(logSerial()) << "Serial buffer size: " << port->readBufferSize();
//port->setReadBufferSize(1024); // manually. 256 never saw any return from the radio. why...
//qDebug(logSerial()) << "Serial buffer size: " << port->readBufferSize();
connect(port, SIGNAL(readyRead()), this, SLOT(receiveDataIn()));
}
void pttyHandler::setupPtty()
{
qDebug(logSerial()) << "Setting up Pseudo Term: " << portName;
serialError = false;
port->setPortName(portName);
#ifdef Q_OS_WIN
port->setBaudRate(baudRate);
port->setStopBits(QSerialPort::OneStop);// OneStop is other option
#endif
}
void pttyHandler::openPort()
{
// qDebug(logSerial()) << "opening pt port";
bool success;
#ifndef Q_OS_WIN
char ptname[128];
int sysResult = 0;
QString ptLinkCmd = "ln -s ";
#endif
success = port->open(QIODevice::ReadWrite);
if (success)
{
#ifndef Q_OS_WIN
serialError = false;
bool success=false;
#ifdef Q_OS_WIN
port->setPortName(portName);
port->setBaudRate(baudRate);
port->setStopBits(QSerialPort::OneStop);// OneStop is other option
success = port->open(QIODevice::ReadWrite);
connect(port, SIGNAL(readyRead()), this, SLOT(receiveDataIn(0)));
#else
// Generic method in Linux/MacOS to find a pty
ptfd = ::posix_openpt(O_RDWR | O_NOCTTY);
if (ptfd >=0)
{
qDebug(logSerial()) << "Opened pt device: " << ptfd << ", attempting to grant pt status";
qDebug(logSerial()) << "Opened pt device, attempting to grant pt status";
ptfd = port->handle();
qDebug(logSerial()) << "ptfd: " << ptfd;
if (grantpt(ptfd))
{
qDebug(logSerial()) << "Failed to grantpt";
@ -101,32 +61,42 @@ void pttyHandler::openPort()
return;
}
// we're good!
qDebug(logSerial()) << "Opened pseudoterminal.";
qDebug(logSerial()) << "Slave name: " << ptsname(ptfd);
qDebug(logSerial()) << "Opened pseudoterminal, slave name :" << ptsname(ptfd);
ptsname_r(ptfd, ptname, 128);
ptDevSlave = QString::fromLocal8Bit(ptname);
ptLinkCmd.append(ptDevSlave);
ptLinkCmd.append(" /tmp/rig");
sysResult = system("rm /tmp/rig");
sysResult = system(ptLinkCmd.toStdString().c_str());
if (sysResult)
{
qDebug(logSerial()) << "Received error from pseudo-terminal symlink command: code: [" << sysResult << "]" << " command: [" << ptLinkCmd << "]";
}
ptReader = new QSocketNotifier(ptfd, QSocketNotifier::Read, this);
connect(ptReader, &QSocketNotifier::activated,
this, &pttyHandler::receiveDataIn);
isConnected = true;
success=true;
}
#endif
}
else {
if (!success)
{
ptfd = 0;
qDebug(logSerial()) << "Could not open pseudo terminal port " << portName << " , please restart.";
qDebug(logSerial()) << "Could not open pseudo terminal port, please restart.";
isConnected = false;
serialError = true;
emit haveSerialPortError(portName, "Could not open pseudo terminal port. Please restart.");
return;
}
#ifndef Q_OS_WIN
ptDevSlave = QString::fromLocal8Bit(ptsname(ptfd));
if (portName != "" && portName != "none")
{
if (!QFile::link(ptDevSlave, portName))
{
qDebug(logSerial()) << "Error creating link to" << ptDevSlave << "from" << portName;
} else {
qDebug(logSerial()) << "Created link to" << ptDevSlave << "from" << portName;
}
}
#endif
isConnected = true;
}
pttyHandler::~pttyHandler()
@ -157,8 +127,11 @@ void pttyHandler::sendDataOut(const QByteArray& writeData)
//printHex(writeData, false, true);
mutex.lock();
#ifdef Q_OS_WIN
bytesWritten = port->write(writeData);
#else
bytesWritten = ::write(ptfd, writeData.constData(), writeData.size());
#endif
if (bytesWritten != writeData.length()) {
qDebug(logSerial()) << "bytesWritten: " << bytesWritten << " length of byte array: " << writeData.length()\
<< " size of byte array: " << writeData.size()\
@ -167,23 +140,44 @@ void pttyHandler::sendDataOut(const QByteArray& writeData)
mutex.unlock();
}
void pttyHandler::receiveDataIn(int fd) {
void pttyHandler::receiveDataIn()
{
// connected to comm port data signal
#ifndef Q_OS_WIN
ssize_t available = 255; // Read up to 'available' bytes
#else
Q_UNUSED(fd);
#endif
// Here we get a little specific to CIV radios
// because we know what constitutes a valid "frame" of data.
// Linux will correctly return the number of available bytes with the FIONREAD ioctl
// Sadly MacOS always returns zero!
#ifdef Q_OS_LINUX
int ret = ::ioctl(fd, FIONREAD, (char *) &available);
if (ret != 0)
return;
#endif
// new code:
#ifdef Q_OS_WIN
port->startTransaction();
inPortData = port->readAll();
#else
inPortData.resize(available);
ssize_t got = ::read(fd, inPortData.data(), available);
int err = errno;
if (got < 0) {
qDebug(logSerial()) << tr("Read failed: %1").arg(QString::fromLatin1(strerror(err)));
return;
}
inPortData.resize(got);
#endif
if (inPortData.startsWith("\xFE\xFE"))
{
if (inPortData.endsWith("\xFD"))
{
// good!
#ifdef Q_OS_WIN
port->commitTransaction();
#endif
// filter 1A 05 01 12/27 = C-IV transceive command before forwarding on.
if (inPortData.contains(QByteArrayLiteral("\x1a\x05\x01\x12")) || inPortData.contains(QByteArrayLiteral("\x1a\x05\x01\x27")))
@ -199,8 +193,8 @@ void pttyHandler::receiveDataIn()
else
{
emit haveDataFromPort(inPortData);
//qDebug(logSerial()) << "Data from pseudo term:";
//printHex(inPortData, false, true);
qDebug(logSerial()) << "Data from pseudo term:";
printHex(inPortData, false, true);
}
if (rolledBack)
@ -214,8 +208,9 @@ void pttyHandler::receiveDataIn()
// did not receive the entire thing so roll back:
// qDebug(logSerial()) << "Rolling back transaction. End not detected. Lenth: " << inPortData.length();
//printHex(inPortData, false, true);
port->rollbackTransaction();
rolledBack = true;
#ifdef Q_OS_WIN
port->rollbackTransaction();
}
}
else {
@ -223,23 +218,29 @@ void pttyHandler::receiveDataIn()
//qDebug(logSerial()) << "Warning: received data with invalid start. Dropping data.";
//qDebug(logSerial()) << "THIS SHOULD ONLY HAPPEN ONCE!!";
// THIS SHOULD ONLY HAPPEN ONCE!
// unrecoverable. We did not receive the start and must
// have missed it earlier because we did not roll back to
// preserve the beginning.
//printHex(inPortData, false, true);
}
#else
}
}
#endif
}
void pttyHandler::closePort()
{
#ifdef Q_OS_WIN
if (port)
{
port->close();
delete port;
}
#else
if (portName != "" && portName != "none")
{
QFile::remove(portName);
}
#endif
isConnected = false;
}

Wyświetl plik

@ -5,6 +5,8 @@
#include <QMutex>
#include <QDataStream>
#include <QIODevice>
#include <QSocketNotifier>
#include <QtSerialPort/QSerialPort>
// This class abstracts the comm port in a useful way and connects to
@ -22,7 +24,7 @@ public:
~pttyHandler();
private slots:
void receiveDataIn(); // from physical port
void receiveDataIn(int fd); // from physical port
void receiveDataFromRigToPtty(const QByteArray& data);
void debugThis();
@ -64,6 +66,8 @@ private:
mutable QMutex mutex;
void printHex(const QByteArray& pdata, bool printVert, bool printHoriz);
QSocketNotifier *ptReader = nullptr;
};
#endif // PTTYHANDLER_H

Wyświetl plik

@ -182,21 +182,33 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, QWidget *parent
ui->serialDeviceListCombo->addItem("Manual...", 256);
ui->serialDeviceListCombo->blockSignals(false);
#ifndef Q_OS_WIN
ui->vspCombo->setVisible(false);
ui->vspLabel->setVisible(false);
#else
i = 0;
ui->vspCombo->blockSignals(true);
#ifdef Q_OS_WIN
ui->vspCombo->addItem(QString("None"), i++);
foreach(const QSerialPortInfo & serialPortInfo, QSerialPortInfo::availablePorts())
{
ui->vspCombo->addItem(serialPortInfo.portName(), i++);
ui->vspCombo->addItem(serialPortInfo.portName());
}
ui->vspCombo->blockSignals(false);
#else
// Provide reasonable names for the symbolic link to the pty device
QString vspName=QDir::homePath()+"/rig-pty";
for (i=1;i<8;i++) {
ui->vspCombo->addItem(vspName+QString::number(i));
if (QFile::exists(vspName+QString::number(i))) {
auto * model = qobject_cast<QStandardItemModel*>(ui->vspCombo->model());
auto *item = model->item(ui->vspCombo->count()-1);
item->setEnabled(false);
}
}
ui->vspCombo->addItem(vspName+QString::number(i));
ui->vspCombo->addItem(QString("None"), i++);
#endif
ui->vspCombo->blockSignals(false);
setDefaultColors(); // set of UI colors with defaults populated

Wyświetl plik

@ -39,7 +39,6 @@ macx:LIBS += -L/usr/local/lib
macx:ICON = wfview.icns
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.13
!win32:DEFINES += HOST=\\\"`hostname`\\\" UNAME=\\\"`whoami`\\\"
!win32:DEFINES += GITSHORT="\\\"$(shell git -C $$PWD rev-parse --short HEAD)\\\""