diff --git a/AGWCode.cpp b/AGWCode.cpp
index 00e319f..4c44124 100644
--- a/AGWCode.cpp
+++ b/AGWCode.cpp
@@ -262,7 +262,7 @@ void doAGWBeacon()
char ports[80];
char * ptr, * context;
- int DataLen = (int)strlen(AGWBeaconMsg);
+ int DataLen;
strcpy(ports, AGWBeaconPorts); // strtok changes it
@@ -282,8 +282,9 @@ void doAGWBeacon()
{
while (ptr)
{
- AGW_frame_header(Msg, atoi(ptr) - 1, 'M', 240, AGWTermCall, AGWBeaconDest, DataLen);
+ DataLen = (int)strlen(AGWBeaconMsg);
+ AGW_frame_header(Msg, atoi(ptr) - 1, 'M', 240, AGWTermCall, AGWBeaconDest, DataLen);
memcpy(&Msg[AGWHDDRRLEN], AGWBeaconMsg, DataLen);
DataLen += AGWHDDRRLEN;
AGWSock->write((char *)Msg, DataLen);
@@ -587,7 +588,7 @@ void QtTermTCP::onAGWSocketStateChanged(QAbstractSocket::SocketState socketState
if (Sess)
{
AGWUsers->MonSess = Sess;
- Sess->AGWSession = sender; // Flag as in use
+// Sess->AGWSession = sender; // Flag as in use
if (TermMode == MDI)
Sess->setWindowTitle("AGW Monitor Window");
@@ -864,7 +865,8 @@ void Send_AGW_Ds_Frame(void * Sess)
UCHAR Msg[512];
AGW_frame_header(Msg, AGW->port, 'd', 240, AGW->corrcall, AGW->mycall, 0);
- AGW->socket->write((char *)Msg, AGWHDDRRLEN);
+ if (AGW->socket)
+ AGW->socket->write((char *)Msg, AGWHDDRRLEN);
}
@@ -1036,9 +1038,9 @@ void on_AGW_C_frame(AGWUser * AGW, struct AGWHeader * Frame, byte * Msg)
Sess = newWindow((QObject *)mythis, Listen, "");
}
}
- else
+ else if (TermMode == Tabbed)
{
- // Single or Tabbed - look for free session
+ // Single Tabbed - look for free session
for (i = 0; i < _sessions.size(); ++i)
@@ -1051,15 +1053,33 @@ void on_AGW_C_frame(AGWUser * AGW, struct AGWHeader * Frame, byte * Msg)
break;
}
}
+ }
+ else
+ {
+ // Single - Only one available
+ S = _sessions.at(0);
- if (Sess == NULL)
- {
- // Clear connection
-
- return;
- }
+ if (S->clientSocket == NULL && S->AGWSession == NULL && S->KISSSession == NULL)
+ Sess = S;
}
+ if (Sess == NULL)
+ {
+ // Clear connection by sendinf d fraame
+
+ UCHAR Msg[512];
+
+ int snd_ch = Frame->Port;
+ char * CallFrom = Frame->callfrom;
+ char * CallTo = Frame->callto;
+
+ AGW_frame_header(Msg, Frame->Port, 'd', 240, Frame->callto, Frame->callfrom, 0);
+ if (AGW->socket)
+ AGW->socket->write((char *)Msg, AGWHDDRRLEN);
+
+ return;
+ }
+
if (Sess)
{
sprintf(Title, "Connected to %s", CallFrom);
diff --git a/KISSConfig.ui b/KISSConfig.ui
index b0c1ead..0aede23 100644
--- a/KISSConfig.ui
+++ b/KISSConfig.ui
@@ -7,7 +7,7 @@
0
0
432
- 319
+ 399
@@ -17,7 +17,7 @@
40
- 262
+ 360
351
33
@@ -58,7 +58,7 @@
10
- 120
+ 168
401
57
@@ -140,7 +140,7 @@
10
- 70
+ 118
411
51
@@ -202,7 +202,7 @@
12
- 12
+ 10
149
21
@@ -215,7 +215,7 @@
158
- 10
+ 9
23
25
@@ -231,7 +231,7 @@
214
- 13
+ 11
61
17
@@ -243,7 +243,7 @@
- 286
+ 292
10
91
22
@@ -254,7 +254,7 @@
25
- 192
+ 240
47
13
@@ -267,7 +267,7 @@
98
- 189
+ 240
47
22
@@ -277,7 +277,7 @@
213
- 192
+ 240
66
16
@@ -290,7 +290,7 @@
288
- 189
+ 240
47
22
@@ -300,9 +300,9 @@
25
- 226
+ 270
47
- 13
+ 20
@@ -313,7 +313,7 @@
98
- 223
+ 270
36
22
@@ -323,7 +323,7 @@
213
- 225
+ 273
47
13
@@ -336,7 +336,7 @@
288
- 222
+ 270
36
22
@@ -346,7 +346,7 @@
12
- 38
+ 35
149
21
@@ -359,7 +359,7 @@
158
- 38
+ 34
23
21
@@ -371,6 +371,132 @@
+
+
+
+ 160
+ 60
+ 20
+ 20
+
+
+
+ Qt::RightToLeft
+
+
+
+
+
+
+
+
+ 12
+ 60
+ 141
+ 20
+
+
+
+ Enable checksum
+
+
+
+
+
+ 160
+ 84
+ 20
+ 20
+
+
+
+ Qt::RightToLeft
+
+
+
+
+
+
+
+
+ 12
+ 85
+ 141
+ 20
+
+
+
+ Enable ACKMODE
+
+
+
+
+
+ 150
+ 300
+ 111
+ 21
+
+
+
+ Qt::RightToLeft
+
+
+ Set TXDelay
+
+
+
+
+
+ 99
+ 300
+ 36
+ 22
+
+
+
+
+
+
+ 26
+ 302
+ 71
+ 16
+
+
+
+ TXDelay
+
+
+
+
+
+ 200
+ 80
+ 151
+ 30
+
+
+
+ Open MH Window
+
+
+
+
+
+ 390
+ 83
+ 20
+ 20
+
+
+
+ Qt::RightToLeft
+
+
+
+
+
diff --git a/QtTermTCP.cpp b/QtTermTCP.cpp
index 6328adb..397e11e 100644
--- a/QtTermTCP.cpp
+++ b/QtTermTCP.cpp
@@ -1,6 +1,8 @@
// Qt Version of BPQTermTCP
-#define VersionString "0.0.0.73"
+// Application icon design by Red PE1RRR
+
+#define VersionString "0.0.0.79"
// .12 Save font weight
@@ -8,7 +10,7 @@
// .14 Add YAPP and Listen Mode
// .15 Reuse windows in Listen Mode
// .17 MDI Version 7/1/20
-// .18 Fix input window losing focus when data arrives on other window
+// .18 Fix input window losing focus when data arrivn other window
// .19 Fix Scrollback
// .20 WinXP compatibility changes
// .21 Save Window Positions
@@ -104,7 +106,26 @@
// .73 November 2023
// Raise RTS on KISS serial port
+// .74 April 2024
+// Support BPQKISS TNCs with CHECKSUM and/or ACKMODE enabled
+// .75 May 2024
+// Flush Monitor log file every minute
+
+// .76 August 2024
+// Fix using digs in KISS UI mode.
+// Add option to send TXDELAY to KISS TNC
+
+// .77
+// Support multichannel KISS TNCs (Beta 1)
+// Fix using AGW listen in single terminal mode
+
+// .78
+// Fix restoring monitor flags when connecting to current host
+
+
+// .79
+// Add KISS MHEARD Window (Feb 2025)
#define _CRT_SECURE_NO_WARNINGS
@@ -126,6 +147,7 @@
#include
#include
#include
+#include
#ifdef USESERIAL
#include
#include
@@ -308,12 +330,23 @@ extern "C" int KISSMonEnable;
extern "C" int KISSLocalTime;
extern "C" int KISSMonNodes;
extern "C" int KISSListen;
+extern "C" int KISSChecksum;
+extern "C" int KISSAckMode;
+extern "C" int KISSMH;
+
+extern "C" short txtail[5];
+extern "C" short txdelay[5];
+extern "C" int sendTXDelay[4];
+
+
char SerialPort[80] = "";
char KISSHost[128] = "127.0.0.1";
int KISSPortNum = 1000;
int KISSBAUD = 19200;
-char MYCALL[32];
+char KISSMYCALL[32];
+char KISSVia[128]; // Digi String
+
extern "C" UCHAR axMYCALL[7]; // Mycall in ax.25
int KISSMode = 0; // Connected (0) or UI (1)
@@ -531,6 +564,7 @@ void AGWMonWindowClosing(Ui_ListenSession *Sess);
void AGWWindowClosing(Ui_ListenSession *Sess);
extern "C" void KISSDataReceived(void * socket, unsigned char * data, int length);
void closeSerialPort();
+int newMHWindow(QObject * parent, int Type, const char * Label);
extern void initUTF8();
int checkUTF8(unsigned char * Msg, int Len, unsigned char * out);
@@ -708,12 +742,39 @@ void DoTermResize(Ui_ListenSession * Sess)
}
}
+
+extern "C" Ui_ListenSession * MHWindow;
+
bool QtTermTCP::eventFilter(QObject* obj, QEvent *event)
{
// See if from a Listening Session
Ui_ListenSession * Sess;
+ if (obj == MHWindow)
+ {
+ if (event->type() == QEvent::Resize)
+ {
+ QRect r = MHWindow->rect();
+
+ int H, Width, Border = 3;
+
+ Width = r.width() - 6;
+ H = r.height() - 6;
+
+ MHWindow->monWindow->setGeometry(QRect(Border, Border, Width, H));
+ return true;
+ }
+ if (event->type() == QEvent::Close)
+ {
+ QSettings mysettings(GetConfPath(), QSettings::IniFormat);
+ mysettings.setValue("MHgeometry", MHWindow->saveGeometry());
+ SaveSettings();
+ MHWindow = 0;
+ }
+ }
+
+
for (int i = 0; i < _sessions.size(); ++i)
{
Sess = _sessions.at(i);
@@ -874,6 +935,14 @@ bool QtTermTCP::eventFilter(QObject* obj, QEvent *event)
if (k->button() == Qt::RightButton)
{
+ // Get clipboard data and process a line at a time
+
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ QString Text = clipboard->text();
+ QByteArray ba = Text.toLocal8Bit();
+ char * Msg = ba.data();
+
+
Sess->inputWindow->paste();
return true;
}
@@ -986,9 +1055,9 @@ Ui_ListenSession * newWindow(QObject * parent, int Type, const char * Label)
QSettings settings(GetConfPath(), QSettings::IniFormat);
#ifdef ANDROID
- QFont font = QFont(settings->value("FontFamily", "Driod Sans Mono").value(),
- settings->value("PointSize", 12).toInt(),
- settings->value("Weight", 50).toInt());
+ QFont font = QFont(settings.value("FontFamily", "Driod Sans Mono").value(),
+ settings.value("PointSize", 12).toInt(),
+ settings.value("Weight", 50).toInt());
#else
QFont font = QFont(settings.value("FontFamily", "Courier New").value(),
settings.value("PointSize", 10).toInt(),
@@ -1300,6 +1369,12 @@ QtTermTCP::QtTermTCP(QWidget *parent) : QMainWindow(parent)
updateWindowMenu();
+ if (KISSEnable && KISSMH)
+ {
+ newMHWindow(this, 0, "KISS MH");
+ MHWindow->restoreGeometry(mysettings.value("MHgeometry").toByteArray());
+ }
+
connectMenu = mymenuBar->addMenu(tr("&Connect"));
actHost[16] = new QAction("AGW Connect", this);
@@ -1642,6 +1717,10 @@ QtTermTCP::QtTermTCP(QWidget *parent) : QMainWindow(parent)
connect(timer2, SIGNAL(timeout()), this, SLOT(KISSTimerSlot()));
timer2->start(100);
+ QTimer *timer3 = new QTimer(this);
+ connect(timer3, SIGNAL(timeout()), this, SLOT(SlowTimerSlot()));
+ timer3->start(60000);
+
// Run timer now to connect to AGW if configured
MyTimerSlot();
@@ -1657,7 +1736,7 @@ QtTermTCP::QtTermTCP(QWidget *parent) : QMainWindow(parent)
OpenPTTPort();
memset(axMYCALL, 0, 7);
- ConvToAX25(MYCALL, axMYCALL);
+ ConvToAX25(KISSMYCALL, axMYCALL);
// Do any autoconnects
@@ -2726,7 +2805,8 @@ void QtTermTCP::LreturnPressed(Ui_ListenSession * Sess)
strcpy(Msg, Msgptr);
strcat(Msg, "\r");
- Send_UI(0, 0xF0, MYCALL, Sess->UIDEST, (unsigned char *)Msg, (int)strlen(Msg));
+
+ Send_UI(Sess->UIPORT, 0xF0, KISSMYCALL, Sess->UIDEST, Sess->UIPATH, (unsigned char *)Msg, (int)strlen(Msg));
WritetoOutputWindowEx(Sess, (unsigned char *)Msg, (int)strlen(Msg),
Sess->termWindow, &Sess->OutputSaveLen, Sess->OutputSave, EchoText); // Black
@@ -2818,7 +2898,8 @@ void QtTermTCP::LreturnPressed(Ui_ListenSession * Sess)
strcat(Msg, "\r");
Sess->clientSocket->write(Msg);
-
+ Sess->clientSocket->flush();
+// QThread::msleep(1500); // Try to force as separate packets
WritetoOutputWindowEx(Sess, (unsigned char *)Msg, (int)strlen(Msg),
Sess->termWindow, &Sess->OutputSaveLen, Sess->OutputSave, EchoText); // Black
@@ -2853,6 +2934,23 @@ void QtTermTCP::LreturnPressed(Ui_ListenSession * Sess)
connect(Sess->clientSocket, SIGNAL(readyRead()), this, SLOT(readyRead()));
connect(Sess->clientSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChanged(QAbstractSocket::SocketState)));
+
+ // Set Monitor Params for this host
+
+ sscanf(MonParams[Sess->CurrentHost], "%llx %x %x %x %x %x",
+ &Sess->portmask, &Sess->mtxparam, &Sess->mcomparam,
+ &Sess->MonitorNODES, &Sess->MonitorColour, &Sess->monUI);
+
+ Sess->mlocaltime = (Sess->mtxparam >> 7);
+ Sess->mtxparam &= 1;
+
+ MonLocalTime->setChecked(Sess->mlocaltime);
+ MonTX->setChecked(Sess->mtxparam);
+ MonSup->setChecked(Sess->mcomparam);
+ MonUI->setChecked(Sess->monUI);
+ MonNodes->setChecked(Sess->MonitorNODES);
+ MonColour->setChecked(Sess->MonitorColour);
+
Sess->clientSocket->connectToHost(&Host[Sess->CurrentHost][0], Port[Sess->CurrentHost]);
}
@@ -3450,6 +3548,8 @@ void getAX25Params(int chan)
void GetPortSettings(int Chan)
{
+ txdelay[Chan] = getAX25Param("TXDelay", 250).toInt();
+ sendTXDelay[Chan] = getAX25Param("sendTXDelay", 0).toInt();
maxframe[Chan] = getAX25Param("Maxframe", 4).toInt();
fracks[Chan] = getAX25Param("Retries", 10).toInt();
frack_time[Chan] = getAX25Param("FrackTime", 8).toInt();
@@ -3541,10 +3641,14 @@ void GetSettings()
KISSMonNodes = settings->value("KISSMonNodes", 0).toInt();
KISSListen = settings->value("KISSListen", 1).toInt();
- strcpy(MYCALL, settings->value("MYCALL", "").toString().toUtf8());
+ KISSChecksum = settings->value("KISSChecksum", 0).toInt();
+ KISSAckMode = settings->value("KISSAckMode", 0).toInt();
+ KISSMH = settings->value("KISSMH", 1).toInt();
+ strcpy(KISSMYCALL, settings->value("MYCALL", "").toString().toUtf8());
strcpy(KISSHost, settings->value("KISSHost", "127.0.0.1").toString().toUtf8());
KISSPortNum = settings->value("KISSPort", 8100).toInt();
KISSMode = settings->value("KISSMode", 0).toInt();
+ strcpy(KISSVia, settings->value("KISSVia", "").toString().toUtf8());
strcpy(SerialPort, settings->value("KISSSerialPort", "None").toString().toUtf8());
KISSBAUD = settings->value("KISSBAUD", 19200).toInt();
@@ -3647,7 +3751,8 @@ void saveAX25Params(int chan)
void SavePortSettings(int Chan)
{
- saveAX25Param("Retries", fracks[Chan]);
+ saveAX25Param("TXDelay", txdelay[Chan]);
+ saveAX25Param("sendTXDelay", sendTXDelay[Chan]);
saveAX25Param("Maxframe", maxframe[Chan]);
saveAX25Param("Paclen", kisspaclen[Chan]);
saveAX25Param("FrackTime", frack_time[Chan]);
@@ -3770,12 +3875,17 @@ extern "C" void SaveSettings()
settings->setValue("KISSMonNodes", KISSMonNodes);
settings->setValue("KISSListen", KISSListen);
- settings->setValue("MYCALL", MYCALL);
+ settings->setValue("KISSChecksum", KISSChecksum);
+ settings->setValue("KISSAckMode", KISSAckMode);
+ settings->setValue("KISSMH", KISSMH);
+ settings->setValue("MYCALL", KISSMYCALL);
settings->setValue("KISSHost", KISSHost);
settings->setValue("KISSMode", KISSMode);
settings->setValue("KISSPort", KISSPortNum);
settings->setValue("KISSSerialPort", SerialPort);
settings->setValue("KISSBAUD", KISSBAUD);
+ settings->setValue("KISSVia", KISSVia);
+
saveAX25Params(0);
settings->setValue("VARAEnable", VARAEnable);
@@ -3852,6 +3962,10 @@ void QtTermTCP::closeEvent(QCloseEvent *event)
#endif
if (process)
process->close();
+
+ if (MHWindow)
+ MHWindow->close();
+
}
}
@@ -3893,6 +4007,11 @@ QtTermTCP::~QtTermTCP()
mysettings.setValue("geometry", saveGeometry());
mysettings.setValue("windowState", saveState());
+ if (MHWindow)
+ {
+ mysettings.setValue("MHgeometry", MHWindow->saveGeometry());
+ MHWindow->close();
+ }
SaveSettings();
}
@@ -3958,6 +4077,27 @@ void QtTermTCP::MyTimerSlot()
}
+void QtTermTCP::SlowTimerSlot()
+{
+ // Runs every 60 S
+
+ Ui_ListenSession * Sess;
+
+ for (int i = 0; i < _sessions.size(); ++i)
+ {
+ Sess = _sessions.at(i);
+
+ if (Sess->monLogfile)
+ {
+ Sess->monLogfile->close();
+ Sess->monLogfile = nullptr;
+ }
+ }
+
+}
+
+
+
extern "C" void myBeep(QString * WAV)
{
if (useBeep)
@@ -4025,7 +4165,13 @@ void QtTermTCP::KISSSlot()
deviceUI = &UI;
KISS->KISSEnable->setChecked(KISSEnable);
KISS->KISSListen->setChecked(KISSListen);
- KISS->MYCALL->setText(MYCALL);
+ KISS->KISSChecksum->setChecked(KISSChecksum);
+ KISS->KISSACKMODE->setChecked(KISSAckMode);
+ KISS->KISSMH->setChecked(KISSMH);
+ KISS->MYCALL->setText(KISSMYCALL);
+
+ KISS->TXDELAY->setText(QString::number(txdelay[0]));
+ KISS->SetTXDelay->setChecked(sendTXDelay[0]);
// connect(KISS->SerialPort, SIGNAL(currentIndexChanged(int)), this, SLOT(PTTPortChanged(int)));
@@ -4079,12 +4225,15 @@ void QtTermTCP::KISSaccept()
KISSEnable = KISS->KISSEnable->isChecked();
KISSListen = KISS->KISSListen->isChecked();
+ KISSChecksum = KISS->KISSChecksum->isChecked();
+ KISSAckMode = KISS->KISSACKMODE->isChecked();
+ KISSMH = KISS->KISSMH->isChecked();
actHost[18]->setVisible(KISSEnable); // Show KISS Connect Line
- strcpy(MYCALL, KISS->MYCALL->text().toUtf8().toUpper());
+ strcpy(KISSMYCALL, KISS->MYCALL->text().toUtf8().toUpper());
memset(axMYCALL, 0, 7);
- ConvToAX25(MYCALL, axMYCALL);
+ ConvToAX25(KISSMYCALL, axMYCALL);
Q = KISS->Port->text();
KISSPortNum = Q.toInt();
@@ -4106,8 +4255,11 @@ void QtTermTCP::KISSaccept()
Q = KISS->Retries->text();
fracks[0] = Q.toInt();
- myStatusBar->setVisible(AGWEnable | VARAEnable | KISSEnable);
+ Q = KISS->TXDELAY->text();
+ txdelay[0] = Q.toInt();
+ sendTXDelay[0] = KISS->SetTXDelay->isChecked();
+ myStatusBar->setVisible(AGWEnable | VARAEnable | KISSEnable);
if (KISSEnable != OldEnable || KISSPortNum != OldPort ||
strcmp(oldHost, KISSHost) != 0 ||
@@ -4131,6 +4283,26 @@ void QtTermTCP::KISSaccept()
}
}
+ if (KISSEnable == 0 && MHWindow)
+ {
+ MHWindow->close();
+ MHWindow = 0;
+ }
+
+ if (KISSEnable && KISSMH && MHWindow == 0)
+ {
+ newMHWindow(this, 0, "KISS MH");
+ QSettings mysettings(GetConfPath(), QSettings::IniFormat);
+ MHWindow->restoreGeometry(mysettings.value("MHgeometry").toByteArray());
+ }
+
+ if (!KISSMH && MHWindow)
+ {
+ MHWindow->close();
+ MHWindow = 0;
+ }
+
+
delete(KISS);
SaveSettings();
deviceUI->accept();
@@ -4602,10 +4774,15 @@ void QtTermTCP::onNewConnection()
datas.chop(2);
datas.truncate(10); // Just in case!
+ strlop(datas.data(), 13);
+
+ if (datas.data()[0] == 0)
+ datas.append("UNKNOWN\0");
+
datas.append('\0');
- sprintf(Title, "Inward Connect from %s:%d Call " + datas,
- Host.data(), clientSocket->peerPort());
+ sprintf(Title, "Inward Connect from %s:%d Call %s",
+ Host.data(), clientSocket->peerPort(), datas.data());
if (TermMode == MDI)
{
@@ -6349,6 +6526,7 @@ void ClosePTTPort()
#endif
}
+#ifndef ANDRIOD
void CM108_set_ptt(int PTTState)
{
@@ -6413,7 +6591,7 @@ void CM108_set_ptt(int PTTState)
}
-
+#endif
void QtTermTCP::RadioPTT(bool PTTState)
{
@@ -6652,6 +6830,16 @@ void QtTermTCP::onKISSSocketStateChanged(QAbstractSocket::SocketState socketStat
KISS_add_stream(sender);
+ // send TXDelay if enabled
+
+ if (sendTXDelay[0])
+ {
+ unsigned char Msg[5] = { FEND, 1, 25 , FEND };
+
+ Msg[2] = txdelay[0] / 10;
+ KISSSock->write((char *)Msg, 4);
+ }
+
// Attach a Monitor Window if available
Ui_ListenSession * Sess = NULL;
@@ -6923,6 +7111,16 @@ int QtTermTCP::openSerialPort()
KISS_add_stream(m_serial);
+ // send TXDelay if enabled
+
+ if (sendTXDelay[0])
+ {
+ unsigned char Msg[5] = { FEND, 1, 25 , FEND };
+
+ Msg[2] = txdelay[0] / 10;
+ m_serial->write((char *)Msg, 4);
+ }
+
// Attach a Monitor Window if available
Ui_ListenSession * Sess = NULL;
@@ -6937,7 +7135,7 @@ int QtTermTCP::openSerialPort()
S = _sessions.at(i);
// for (Ui_ListenSession * S: _sessions)
- // {
+ //
if ((S->SessionType == Mon) && S->clientSocket == NULL && S->KISSSession == NULL)
{
Sess = S;
@@ -7831,7 +8029,7 @@ void WriteMonitorLog(Ui_ListenSession * Sess, char * Msg)
Sess->monLogfile = new QFile(FN);
if (Sess->monLogfile)
- Sess->monLogfile->open(QIODevice::WriteOnly | QIODevice::Text);
+ Sess->monLogfile->open(QIODevice::Append);
else
return;
}
@@ -7862,3 +8060,106 @@ void WriteMonitorLog(Ui_ListenSession * Sess, char * Msg)
}
+// Create MH Window
+
+
+
+int newMHWindow(QObject * parent, int Type, const char * Label)
+{
+ Ui_ListenSession * Sess = new(Ui_ListenSession);
+
+ MHWindow = Sess;
+
+ // Need to explicity initialise on Qt4
+
+ Sess->termWindow = NULL;
+ Sess->monWindow = NULL;
+ Sess->inputWindow = NULL;
+
+ Sess->StackIndex = 0;
+ Sess->InputMode = 0;
+ Sess->SlowTimer = 0;
+ Sess->MonData = 0;
+ Sess->OutputSaveLen = 0;
+ Sess->MonSaveLen = 0;
+ Sess->PortMonString[0] = 0;
+ Sess->portmask = 0;
+ Sess->portmask = 1;
+ Sess->mtxparam = 1;
+ Sess->mlocaltime = 0;
+ Sess->mcomparam = 1;
+ Sess->monUI = 0;
+ Sess->MonitorNODES = 0;
+ Sess->MonitorColour = 1;
+ Sess->CurrentHost = 0;
+
+ Sess->SessionType = Type;
+ Sess->clientSocket = NULL;
+ Sess->AGWSession = NULL;
+ Sess->AGWMonSession = NULL;
+ Sess->KISSSession = NULL;
+ Sess->KISSMode = 0;
+ Sess->TTActive = 0;
+ Sess->TTFlashToggle = 0;
+ Sess->pageBuffer[0] = 0;
+ Sess->Tab = 0;
+
+ Sess->LogMonitor = false;
+ Sess->monSpan = (char *) "";
+ Sess->monLogfile = nullptr;
+ Sess->sessNo = sessNo++;
+
+ QSettings settings(GetConfPath(), QSettings::IniFormat);
+
+#ifdef ANDROID
+ QFont font = QFont(settings.value("FontFamily", "Driod Sans Mono").value(),
+ settings.value("PointSize", 12).toInt(),
+ settings.value("Weight", 50).toInt());
+#else
+ QFont font = QFont(settings.value("FontFamily", "Courier New").value(),
+ settings.value("PointSize", 10).toInt(),
+ settings.value("Weight", 50).toInt());
+#endif
+
+ Sess->monWindow = new QTextEdit(Sess);
+ Sess->monWindow->setReadOnly(1);
+ Sess->monWindow->document()->setMaximumBlockCount(10000);
+ Sess->monWindow->setFont(font);
+ Sess->monWindow->setStyleSheet(monStyleSheet);
+
+ Sess->setWindowTitle(Label);
+
+ Sess->installEventFilter(mythis);
+
+ Sess->show();
+
+
+
+ Sess->monWindow->setGeometry(QRect(2, 2, 400, 400));
+ Sess->setGeometry(QRect(400, 400, 400, 400));
+
+
+ QSize Size(800, 602); // Not actually used, but Event constructor needs it
+
+ QResizeEvent event(Size, Size);
+
+ QApplication::sendEvent(Sess, &event); // Resize Widgets to fix Window
+
+ return true;
+}
+
+extern "C" void WritetoMHWindow(char * Buffer)
+{
+ unsigned char Copy[8192];
+ unsigned char * ptr1, *ptr2;
+ unsigned char Line[8192];
+ unsigned char out[8192];
+ int outlen;
+
+ int num;
+
+ if (MHWindow == NULL || MHWindow->monWindow == NULL)
+ return;
+
+ MHWindow->monWindow->setText(Buffer);
+}
diff --git a/QtTermTCP.h b/QtTermTCP.h
index 7f477c3..81c8449 100644
--- a/QtTermTCP.h
+++ b/QtTermTCP.h
@@ -100,6 +100,7 @@ public:
void * AGWMonSession;
void * KISSSession;
int KISSMode; // Connected or UI
+ int UIPORT;
char UIDEST[32];
char UIPATH[128];
@@ -159,6 +160,7 @@ private slots:
void LDisconnect(Ui_ListenSession * LUI);
void SetupHosts();
void MyTimerSlot();
+ void SlowTimerSlot();
void KISSTimerSlot();
void ListenSlot();
void AGWSlot();
diff --git a/QtTermTCP.pro b/QtTermTCP.pro
index aeb5e0b..4f31da1 100644
--- a/QtTermTCP.pro
+++ b/QtTermTCP.pro
@@ -49,4 +49,6 @@ RESOURCES += QtTermTCP.qrc
RC_ICONS = QtTermTCP.ico
+ICONS = QtTermTCP.icns
+
QMAKE_LFLAGS += -no-pie
diff --git a/QtTermTCP.pro.user b/QtTermTCP.pro.user
index 4bbf667..00b803e 100644
--- a/QtTermTCP.pro.user
+++ b/QtTermTCP.pro.user
@@ -1,14 +1,14 @@
-
+
EnvironmentId
- {49a2cf38-2251-47e3-97df-4ecaa9d41931}
+ {6e41d268-43e9-43ac-b8fa-a3c083d547a3}
ProjectExplorer.Project.ActiveTarget
- 0
+ 0
ProjectExplorer.Project.EditorSettings
@@ -28,7 +28,7 @@
QmlJSGlobal
- 2
+ 2
UTF-8
false
4
@@ -37,6 +37,7 @@
true
true
1
+ false
true
false
0
@@ -45,6 +46,7 @@
0
8
true
+ false
1
true
true
@@ -52,6 +54,7 @@
*.md, *.MD, Makefile
false
true
+ true
@@ -59,6 +62,7 @@
true
+ false
true
true
true
@@ -67,15 +71,12 @@
0
true
-
- -fno-delayed-template-parsing
-
- true
- Builtin.Questionable
+ true
true
Builtin.DefaultTidyAndClazy
- 3
+ 0
+ true
@@ -87,35 +88,28 @@
ProjectExplorer.Project.Target.0
Desktop
- Desktop Qt 5.14.2 MSVC2015 64bit
- Desktop Qt 5.14.2 MSVC2015 64bit
- qt.qt5.5142.win64_msvc2015_64_kit
- 0
- 0
- 0
+ Qt 5.15.10 (5.15.10_1)
+ Qt 5.15.10 (5.15.10_1)
+ {6c3e99da-2293-4df8-901e-49e24d493aeb}
+ 0
+ 0
+ 0
- true
0
- C:\Users\John\OneDrive\Dev\Source\QT\build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Debug
- C:/Users/John/OneDrive/Dev/Source/QT/build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Debug
+ /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Debug
+ /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Debug
true
QtProjectManager.QMakeBuildStep
-
false
true
Qt4ProjectManager.MakeStep
-
- false
-
-
- false
- 2
+ 2
Build
Build
ProjectExplorer.BuildSteps.Build
@@ -124,13 +118,9 @@
true
Qt4ProjectManager.MakeStep
-
- true
clean
-
- false
- 1
+ 1
Clean
Clean
ProjectExplorer.BuildSteps.Clean
@@ -138,36 +128,27 @@
2
false
+ false
Debug
Qt4ProjectManager.Qt4BuildConfiguration
2
- 2
- 2
- true
- 2
- C:\Users\John\OneDrive\Dev\Source\QT\build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Release
- C:/Users/John/OneDrive/Dev/Source/QT/build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Release
+ /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Release
+ /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Release
true
QtProjectManager.QMakeBuildStep
-
false
true
Qt4ProjectManager.MakeStep
-
- false
-
-
- false
- 2
+ 2
Build
Build
ProjectExplorer.BuildSteps.Build
@@ -176,13 +157,9 @@
true
Qt4ProjectManager.MakeStep
-
- true
clean
-
- false
- 1
+ 1
Clean
Clean
ProjectExplorer.BuildSteps.Clean
@@ -190,36 +167,29 @@
2
false
+ false
Release
Qt4ProjectManager.Qt4BuildConfiguration
0
0
- 2
- true
0
- C:\Users\John\OneDrive\Dev\Source\QT\build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Profile
- C:/Users/John/OneDrive/Dev/Source/QT/build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Profile
+ /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Profile
+ /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Profile
true
QtProjectManager.QMakeBuildStep
-
false
true
Qt4ProjectManager.MakeStep
-
- false
-
-
- false
- 2
+ 2
Build
Build
ProjectExplorer.BuildSteps.Build
@@ -228,13 +198,9 @@
true
Qt4ProjectManager.MakeStep
-
- true
clean
-
- false
- 1
+ 1
Clean
Clean
ProjectExplorer.BuildSteps.Clean
@@ -242,6 +208,7 @@
2
false
+ false
Profile
Qt4ProjectManager.Qt4BuildConfiguration
@@ -249,10 +216,10 @@
0
0
- 3
+ 3
- 0
+ 0
Deploy
Deploy
ProjectExplorer.BuildSteps.Deploy
@@ -262,89 +229,28 @@
false
ProjectExplorer.DefaultDeployConfiguration
- 1
-
+ 1
- dwarf
-
- cpu-cycles
-
-
- 250
-
- -e
- cpu-cycles
- --call-graph
- dwarf,4096
- -F
- 250
-
- -F
true
- 4096
- false
- false
- 1000
-
true
-
- false
- false
- false
- false
- true
- 0.01
- 10
- true
- kcachegrind
- 1
- 25
-
- 1
true
- false
- true
- valgrind
-
- 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
-
2
- Qt4ProjectManager.Qt4RunConfiguration:C:/Users/John/OneDrive/Dev/Source/QT/QtTermTCP/QtTermTCP.pro
- C:/Users/John/OneDrive/Dev/Source/QT/QtTermTCP/QtTermTCP.pro
-
- false
-
- false
+ false
+ Qt4ProjectManager.Qt4RunConfiguration:/Volumes/Source/QT/QtTermTCP2/QtTermTCP.pro
+ /Volumes/Source/QT/QtTermTCP2/QtTermTCP.pro
true
true
- false
- false
true
-
- C:/Users/John/OneDrive/Dev/Source/QT/build-QtTermTCP-Desktop_Qt_5_14_2_MSVC2015_64bit-Debug
+ /Volumes/Source/QT/build-QtTermTCP-Qt_5_15_10_5_15_10_1-Debug/QtTermTCP.app/Contents/MacOS
- 1
+ 1
ProjectExplorer.Project.TargetCount
- 1
+ 1
ProjectExplorer.Project.Updater.FileVersion
diff --git a/QtTermTCP.vcxproj b/QtTermTCP.vcxproj
index 506de1f..8b8c32d 100644
--- a/QtTermTCP.vcxproj
+++ b/QtTermTCP.vcxproj
@@ -114,7 +114,7 @@
5.14.2
- core;network;gui;widgets;serialport
+ core;network;gui;widgets;serialport;multimedia
5.14.2_msvc2017
@@ -122,7 +122,7 @@
5.14.2
- core;network;gui;widgets;serialport
+ core;network;gui;widgets;serialport;multimedia
5.14.2_msvc2017_64
@@ -153,7 +153,7 @@
true
- shell32.lib;setupapi.lib;C:\Qt\Qt5.14.2\5.14.2\msvc2017\lib\Qt5Multimedia.lib;%(AdditionalDependencies)
+ shell32.lib;setupapi.lib;%(AdditionalDependencies)
C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories)
-no-pie "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)
true
@@ -279,7 +279,7 @@
true
- shell32.lib;setupapi.lib;%(AdditionalDependencies);C:\Qt\Qt5.14.2\5.14.2\msvc2017\lib\Qt5Multimediad.lib
+ shell32.lib;setupapi.lib;%(AdditionalDependencies);
C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories)
-no-pie "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)
true
diff --git a/QtTermTCP.vcxproj.user b/QtTermTCP.vcxproj.user
index c34359b..114a6e2 100644
--- a/QtTermTCP.vcxproj.user
+++ b/QtTermTCP.vcxproj.user
@@ -1,12 +1,14 @@
- $(APPDATA)
+ C:\DevProgs\BPQ32\Release
WindowsLocalDebugger
+ C:\Dev\Msdev2005\Projects\QtTermTCP\Win32\Debug\QtTermTCP.exe
- ..\..\..\..\..\DevProgs\BPQ32
+ C:\DevProgs\BPQ32\Release
WindowsLocalDebugger
+ C:\Dev\Msdev2005\Projects\QtTermTCP\Win32\Debug\QtTermTCP.exe
2022-05-19T07:28:47.9186341Z
@@ -15,15 +17,15 @@
2022-05-19T07:28:58.9302359Z
- 2023-10-14T13:14:56.5532991Z
+ 2025-02-19T10:20:19.7224236Z
- 2023-10-14T13:14:56.7231497Z
+ 2025-02-19T10:20:19.9860750Z
- 2023-10-14T13:14:55.9367569Z
+ 2025-02-19T10:20:19.2704826Z
- 2023-10-14T13:14:56.2561805Z
+ 2025-02-19T10:20:19.4132585Z
\ No newline at end of file
diff --git a/TabDialog.cpp b/TabDialog.cpp
index 98d3ed9..8e5e17b 100644
--- a/TabDialog.cpp
+++ b/TabDialog.cpp
@@ -56,7 +56,7 @@ extern char UserName[MAXHOSTS + 1][80];
extern char Password[MAXHOSTS + 1][80];
extern char SessName[MAXHOSTS + 1][80];
-extern char MYCALL[32];
+extern char KISSMYCALL[32];
QLineEdit *TermCall;
QGroupBox *groupBox;
@@ -114,6 +114,7 @@ extern char * AGWPortList;
extern QStringList AGWToCalls;
extern int KISSMode;
+extern char KISSVia[128]; // Digi String
extern Ui_ListenSession * ActiveSession;
@@ -470,7 +471,7 @@ KISSConnect::KISSConnect(QWidget *parent) : QDialog(parent)
scrollArea = new QScrollArea(this);
scrollArea->setObjectName(QString::fromUtf8("scrollArea"));
- scrollArea->setGeometry(QRect(5, 5, 250, 200));
+ scrollArea->setGeometry(QRect(5, 5, 260, 200));
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setWidgetResizable(false);
@@ -503,6 +504,13 @@ KISSConnect::KISSConnect(QWidget *parent) : QDialog(parent)
layout->addSpacing(10);
layout->addLayout(formLayout2);
+ Chan = new QComboBox();
+ Chan->setEditable(false);
+ Chan->setInsertPolicy(QComboBox::NoInsert);
+ Chan->addItems(QStringList() << "A" << "B" << "C" << "D");
+
+ formLayout2->addRow(new QLabel("Modem Channel"), Chan);
+
wCallTo = new QComboBox();
wCallTo->setEditable(true);
wCallTo->setInsertPolicy(QComboBox::NoInsert);
@@ -510,6 +518,7 @@ KISSConnect::KISSConnect(QWidget *parent) : QDialog(parent)
formLayout2->addRow(new QLabel("Call To"), wCallTo);
Digis = new QLineEdit();
+
formLayout2->addRow(new QLabel("Digis"), Digis);
layout->addSpacing(2);
@@ -523,6 +532,9 @@ KISSConnect::KISSConnect(QWidget *parent) : QDialog(parent)
wCallTo->addItems(AGWToCalls);
+ Digis->setText(KISSVia);
+ Digis->resize(400, 20);
+
connect(buttonBox, SIGNAL(accepted()), this, SLOT(myaccept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(myreject()));
}
@@ -544,16 +556,20 @@ void KISSConnect::myaccept()
{
QVariant Q;
- char CallTo[32];
- char Via[128];
+ char CallTo[128];;
+ char Port[3];
+
strcpy(CallTo, wCallTo->currentText().toUpper().toUtf8());
- strcpy(Via, Digis->text().toUpper().toUtf8());
+ strcpy(KISSVia, Digis->text().toUpper().toUtf8());
+ memcpy(Port, Chan->currentText().toUpper().toUtf8(), 1);
+
+ int PortNo = Port[0] - 'A';
TAX25Port * AX25Sess = 0;
// Check for duplicate session
- AX25Sess = get_user_port_by_calls(0, MYCALL, CallTo);
+ AX25Sess = get_user_port_by_calls(0, KISSMYCALL, CallTo);
if (AX25Sess)
{
@@ -561,7 +577,7 @@ void KISSConnect::myaccept()
char Msg[256];
- int Len = sprintf(Msg, "You already have a session between %s and %s so can't connect\r", MYCALL, CallTo);
+ int Len = sprintf(Msg, "You already have a session between %s and %s so can't connect\r", KISSMYCALL, CallTo);
WritetoOutputWindow(ActiveSession, (unsigned char *)Msg, Len);
// KISSConnect::accept();
@@ -581,7 +597,7 @@ void KISSConnect::myaccept()
if (KISSMode == 0)
{
- ActiveSession->KISSSession = KISSConnectOut(ActiveSession, MYCALL, CallTo, Via, 0, (void *)KISSSock);
+ ActiveSession->KISSSession = KISSConnectOut(ActiveSession, KISSMYCALL, CallTo, KISSVia, PortNo, (void *)KISSSock);
WritetoOutputWindow(ActiveSession, (unsigned char *)"Connecting...\r", 14);
discAction->setEnabled(true);
}
@@ -597,7 +613,8 @@ void KISSConnect::myaccept()
ActiveSession->KISSSession = (void *)&DummyPort; // Dummy marker to show session in use
strcpy(ActiveSession->UIDEST, CallTo);
- strcpy(ActiveSession->UIPATH, Via);
+ strcpy(ActiveSession->UIPATH, KISSVia);
+ ActiveSession->UIPORT = PortNo;
if (TermMode == Tabbed)
Len = sprintf(Msg, "UI %s", CallTo);
diff --git a/TabDialog.h b/TabDialog.h
index cd21067..a3a58be 100644
--- a/TabDialog.h
+++ b/TabDialog.h
@@ -146,6 +146,7 @@ public:
public:
QLineEdit * wCallFrom;
QComboBox * wCallTo;
+ QComboBox * Chan;
QLineEdit * Digis;
QLineEdit * UIDest;
QListWidget * RadioPorts;
diff --git a/ax25.c b/ax25.c
index f212148..b7f52af 100644
--- a/ax25.c
+++ b/ax25.c
@@ -20,9 +20,13 @@ along with QtSoundModem. If not, see http://www.gnu.org/licenses
// UZ7HO Soundmodem Port by John Wiseman G8BPQ
+// This is a simplified version for QtTermTCP
+
#include "ax25.h"
#include
+extern int KISSChecksum;
+
#ifdef WIN32
__declspec(dllimport) unsigned short __stdcall htons(__in unsigned short hostshort);
@@ -40,7 +44,7 @@ void decode_frame(Byte * frame, int len, Byte * path, string * data,
void SetSessLabel(void * Sess, char * label);
void setMenus(int State);
-
+void MHPROC(unsigned char * Packet, int Len);
/*
unit ax25;
@@ -224,6 +228,8 @@ Byte users[4] = { 0,0,0,0 };
short txtail[5] = { 50, 50, 50, 50, 50 };
short txdelay[5] = { 400, 400, 400, 400, 400 };
+int sendTXDelay[4] = { 0, 0, 0, 0 };
+
short modem_def[5] = { 1, 1, 1, 1, 1 };
@@ -861,7 +867,7 @@ int get_addr(char * Calls, UCHAR * AXCalls)
char * ptr, *Context;
int n = 8; // Max digis
- memset(AXCalls, 0, 70);
+ memset(AXCalls, 0, 72);
ptr = strtok_s(Calls, " ,", &Context);
@@ -877,7 +883,7 @@ int get_addr(char * Calls, UCHAR * AXCalls)
ptr = strtok_s(NULL, " ,", &Context);
- if (ConvToAX25(ptr, axptr) == 0)
+ if (ptr == 0 || ConvToAX25(ptr, axptr) == 0)
return FALSE;
axptr += 7;
@@ -2495,6 +2501,7 @@ void KISSDataReceived(void * socket, unsigned char * data, int length)
void analiz_frame(int snd_ch, string * frame, void * socket, boolean fecflag);
+void KISSSendtoServer(void * Socket, char * Data, int Length);
void ProcessKISSFrame(void * socket, UCHAR * Msg, int Len)
{
@@ -2505,8 +2512,6 @@ void ProcessKISSFrame(void * socket, UCHAR * Msg, int Len)
int Chan;
int Opcode;
string * TXMSG;
- unsigned short CRC;
- UCHAR CRCString[2];
ptr1 = ptr2 = Msg;
@@ -2564,46 +2569,65 @@ void ProcessKISSFrame(void * socket, UCHAR * Msg, int Len)
if (Chan > 3)
return;
+ // This is a lot simpler than QtSM, as frames will always be immediately processed locally, so ack mode isn't needed.
+ // but if enabled ack can be sent immediately
+ // checksum if needed
+
switch (Opcode)
{
case KISS_ACKMODE:
+ {
+ // send ack
- // How best to do ACKMODE?? I think pass whole frame including CMD and ack bytes to all_frame_buf
+ unsigned char ACK[16];
+ unsigned char * ackptr = ACK;
- // But ack should only be sent to client that sent the message - needs more thought!
+ *ackptr++ = FEND;
+ *ackptr++ = Msg[0]; // opcode and channel
- TXMSG = newString();
- stringAdd(TXMSG, &Msg[0], Len); // include Control
+ *ackptr++ = Msg[1];
+ *ackptr++ = Msg[2]; // ACK Bytes
+ *ackptr++ = FEND;
- CRC = get_fcs(&Msg[3], Len - 3); // exclude control and ack bytes
+ KISSSendtoServer(socket, ACK, 5);
- CRCString[0] = CRC & 0xff;
- CRCString[1] = CRC >> 8;
+ // remove ack bytes
- stringAdd(TXMSG, CRCString, 2);
+ memmove(&Msg[1], &Msg[3], Len - 2);
- // Ackmode needs to know where to send ack back to, so save socket on end of data
-
- stringAdd(TXMSG, (unsigned char *)&socket, sizeof(socket));
-
- // if KISS Optimise see if frame is really needed
-
- if (!KISS_opt[Chan])
- Add(&KISS.buffer[Chan], TXMSG);
- else
- {
- if (add_raw_frames(Chan, TXMSG, &KISS.buffer[Chan]))
- Add(&KISS.buffer[Chan], TXMSG);
- }
-
-
- return;
+ // drop through to KISS Data
+ Len -= 2;
+ }
case KISS_DATA:
+ if (KISSChecksum)
+ {
+ // SUM MESSAGE, AND IF DUFF DISCARD. IF OK DECREMENT COUNT TO REMOVE SUM
+
+ int sumlen = Len;
+ char * ptr = &Msg[0];
+ UCHAR sum = 0;
+
+ while (sumlen--)
+ {
+ sum ^= *(ptr++);
+ }
+
+ if (sum)
+ {
+ Debugprintf("KISS Checksum Error");
+ return;
+ }
+
+ Len--; // Remove Checksum
+ }
+
TXMSG = newString();
stringAdd(TXMSG, &Msg[1], Len - 1); // include Control
+ MHPROC(TXMSG->Data, TXMSG->Length);
+
analiz_frame(Chan, TXMSG, socket, 0);
free(TXMSG);
@@ -2702,7 +2726,7 @@ TAX25Port * KISSConnectOut(void * Sess, char * CallFrom, char * CallTo, char * D
strcpy((char *)AX25Sess->Path, (char *)axpath);
reverse_addr(axpath, AX25Sess->ReversePath, AX25Sess->pathLen);
- set_link(AX25Sess, AX25Sess->Path);
+ set_link(AX25Sess, AX25Sess->Path); // Sends SABM
return AX25Sess;
}
return 0;
@@ -2997,6 +3021,221 @@ char * frame_monitor(string * frame, char * code, int tx_stat)
return FrameData;
}
+typedef struct _MHSTRUC
+{
+ UCHAR MHCALL[7];
+ UCHAR MHDIGIS[7][8];
+ time_t MHTIME;
+ int MHCOUNT;
+ unsigned char MHDIGI;
+ char MHFreq[12];
+ char MHLocator[6];
+} MHSTRUC, *PMHSTRUC;
+
+
+#define MHENTRIES 30
+
+MHSTRUC MHEARD[(MHENTRIES + 1) * sizeof(MHSTRUC)] = { 0 };
+
+int CompareCalls(UCHAR * c1, UCHAR * c2)
+{
+ // COMPARE AX25 CALLSIGNS IGNORING EXTRA BITS IN SSID
+
+ if (memcmp(c1, c2, 6))
+ return FALSE; // No Match
+
+ if ((c1[6] & 0x1e) == (c2[6] & 0x1e))
+ return TRUE;
+
+ return FALSE;
+}
+
+static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+void * MHWindow = 0;
+void WritetoMHWindow(char * Buffer);
+int KISSMH = 0;
+
+char * FormatMH(PMHSTRUC MH)
+{
+ struct tm * TM;
+ static char MHTime[50];
+ time_t szClock;
+ char LOC[7];
+
+ memcpy(LOC, MH->MHLocator, 6);
+ LOC[6] = 0;
+
+ szClock = MH->MHTIME;
+// else
+// szClock = time(NULL) - MH->MHTIME;
+
+ TM = gmtime(&szClock);
+
+ sprintf(MHTime, "%s %02d %.2d:%.2d:%.2d %s %s",
+ month[TM->tm_mon], TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec, MH->MHFreq, LOC);
+
+ return MHTime;
+}
+
+
+
+
+void MHPROC(unsigned char * Packet, int Len)
+{
+ PMHSTRUC MH = &MHEARD[0];
+ PMHSTRUC MHBASE = MH;
+ int i;
+ int OldCount = 0;
+ char Freq[64] = "";
+ char DIGI = '*';
+
+ MESSAGE Frame;
+ MESSAGE * Buffer = &Frame;
+
+ memcpy(Buffer->DEST, Packet, Len);
+
+
+ // if port has a freq associated with it use it
+
+
+ // if (Buffer->ORIGIN[6] & 1)
+ DIGI = 0; // Don't think we want to do this
+
+// See if in list
+
+ for (i = 0; i < MHENTRIES; i++)
+ {
+ if ((MH->MHCALL[0] == 0) || (CompareCalls(Buffer->ORIGIN, MH->MHCALL) && MH->MHDIGI == DIGI)) // Spare or our entry
+ {
+ OldCount = MH->MHCOUNT;
+ goto DoMove;
+ }
+ MH++;
+ }
+
+ // TABLE FULL AND ENTRY NOT FOUND - MOVE DOWN ONE, AND ADD TO TOP
+
+ i = MHENTRIES - 1;
+
+ // Move others down and add at front
+DoMove:
+ if (i != 0) // First
+ memmove(MHBASE + 1, MHBASE, i * sizeof(MHSTRUC));
+
+ memcpy(MHBASE->MHCALL, Buffer->ORIGIN, 7 * 9); // Save Digis
+ MHBASE->MHDIGI = DIGI;
+ MHBASE->MHTIME = time(NULL);
+ MHBASE->MHCOUNT = ++OldCount;
+ strcpy(MHBASE->MHFreq, Freq);
+ MHBASE->MHLocator[0] = 0;
+
+ if (MHWindow)
+ {
+ int count = MHENTRIES;
+ int n;
+ char Normcall[20];
+ char From[10];
+ char DigiList[100];
+ char * Output;
+ int len;
+ char Digi = 0;
+ char MHPage[MHENTRIES * 100];
+ char * Bufferptr = MHPage;
+ unsigned char * ptr;
+
+ MH = &MHEARD[0];
+
+ // Note that the MHDIGIS field may contain rubbish. You have to check End of Address bit to find
+ // how many digis there are
+
+ Bufferptr += sprintf(Bufferptr, "Callsign Last heard Pkts RX via Digi\r");
+ Bufferptr += sprintf(Bufferptr, "\r");
+
+ while (count--)
+ {
+ if (MH->MHCALL[0] == 0)
+ break;
+
+ Digi = 0;
+
+ len = ConvFromAX25(MH->MHCALL, Normcall);
+
+ Normcall[len++] = MH->MHDIGI;
+ Normcall[len++] = 0;
+
+ n = 8; // Max number of digi-peaters
+
+ ptr = &MH->MHCALL[6]; // End of Address bit
+
+ Output = &DigiList[0];
+
+ if ((*ptr & 1) == 0)
+ {
+ // at least one digi
+
+ strcpy(Output, "via ");
+ Output += 4;
+
+ while ((*ptr & 1) == 0)
+ {
+ // MORE TO COME
+
+ From[ConvFromAX25(ptr + 1, From)] = 0;
+ Output += sprintf((char *)Output, "%s", From);
+
+ ptr += 7;
+ n--;
+
+ if (n == 0)
+ break;
+
+ // See if digi actioned - put a * on last actioned
+
+ if (*ptr & 0x80)
+ {
+ if (*ptr & 1) // if last address, must need *
+ {
+ *(Output++) = '*';
+ Digi = '*';
+ }
+
+ else
+ if ((ptr[7] & 0x80) == 0) // Repeased by next?
+ {
+ *(Output++) = '*'; // No, so need *
+ Digi = '*';
+ }
+
+ }
+ *(Output++) = ',';
+ }
+ *(--Output) = 0; // remove last comma
+ }
+ else
+ *(Output) = 0;
+
+ // if we used a digi set * on call and display via string
+
+
+ if (Digi)
+ Normcall[len++] = Digi;
+ else
+ DigiList[0] = 0; // Dont show list if not used
+
+ Normcall[len++] = 0;
+
+ ptr = FormatMH(MH);
+
+ Bufferptr += sprintf(Bufferptr, "%-10s %-10s %-10d %-30s\r", Normcall, ptr, MH->MHCOUNT, DigiList);
+
+ MH++;
+ }
+
+ WritetoMHWindow(MHPage);
+ }
+ return;
+}
diff --git a/ax25.h b/ax25.h
index d554b20..06c2fd3 100644
--- a/ax25.h
+++ b/ax25.h
@@ -228,7 +228,7 @@ extern "C" void WriteDebugLog(char * Mess);
extern "C" void SendtoTerm(Ui_ListenSession * Sess, char * Msg, int Len);
extern "C" void ClearSessLabel(Ui_ListenSession * Sess);
extern "C" void rst_timer(TAX25Port * AX25Sess);
-extern "C" void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, Byte * Msg, int MsgLen);
+extern "C" void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, char * Via, Byte * Msg, int MsgLen);
#else
void monitor_frame(int snd_ch, string * frame, char * code, int tx, int excluded);
void SendtoTerm(void * Sess, char * Msg, int Len);
@@ -236,7 +236,7 @@ void ClearSessLabel(void * Sess);
void WriteDebugLog(char * Mess);
void AX25_disc(TAX25Port * AX25Sess, Byte mode);
void rst_timer(TAX25Port * AX25Sess);
-void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, Byte * Msg, int MsgLen);
+void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, char * via, Byte * Msg, int MsgLen);
#endif
BOOL ConvToAX25(char * callsign, unsigned char * ax25call);
diff --git a/ax25_l2.c b/ax25_l2.c
index e4dabb7..0806ef3 100644
--- a/ax25_l2.c
+++ b/ax25_l2.c
@@ -20,12 +20,18 @@ along with QtSoundModem. If not, see http://www.gnu.org/licenses
// UZ7HO Soundmodem Port by John Wiseman G8BPQ
+// This is a simplified version for QtTermTCP
+
+
+
#include "ax25.h"
UCHAR TimerEvent = TIMER_EVENT_OFF;
extern int busy;
int listenEnable;
int KISSListen = 1;
+int KISSChecksum = 0;
+int KISSAckMode = 0;
void * KISSSockCopy[4];
extern UCHAR axMYCALL[7] = ""; // Mycall in ax.25
@@ -301,6 +307,32 @@ int KISS_encode(UCHAR * KISSBuffer, int port, string * frame)
(*ptr2++) = c;
}
}
+
+ // Add checksum if needed
+
+ if (KISSChecksum)
+ {
+ c = TXCCC;
+
+ // We don't support TNCX with Checksum
+
+ switch (c)
+ {
+ case FEND:
+ (*ptr2++) = FESC;
+ (*ptr2++) = TFEND;
+ break;
+
+ case FESC:
+ (*ptr2++) = FESC;
+ (*ptr2++) = TFESC;
+ break;
+
+ default:
+ (*ptr2++) = c;
+ }
+ }
+
(*ptr2++) = FEND;
return (int)(ptr2 - KISSBuffer);
@@ -317,23 +349,13 @@ void add_pkt_buf(TAX25Port * AX25Sess, string * data)
// ? Don't we just send to TNC?
- Length = KISS_encode(KISSBuffer, 0, data);
+ Length = KISS_encode(KISSBuffer, AX25Sess->snd_ch, data);
KISSSendtoServer(AX25Sess->socket, KISSBuffer, Length);
monitor_frame(0, data, "", 1, 0); // Monitor
freeString(data);
-
-// while (i < AX25Sess->frame_buf.Count && !found)
-// {
-// found = compareStrings(Strings(&AX25Sess->frame_buf, i++), data);
-// }
-
-// if (found)
-// freeString(data);
-// else
-// Add(&AX25Sess->frame_buf, data);
}
void add_I_FRM(TAX25Port * AX25Sess)
@@ -1227,20 +1249,9 @@ void timer_event()
for (snd_ch = 0; snd_ch < 4; snd_ch++)
{
//reset the slottime timer
- if (dyn_frack[snd_ch])
- {
- UpdateActiveConnects(snd_ch);
- if (users[snd_ch] > 0)
- active = users[snd_ch] - 1;
- else
- active = 0;
- frack = frack_time[snd_ch] + frack_time[snd_ch] * active * 0.5;
- }
- else
- frack = frack_time[snd_ch];
+ frack = frack_time[snd_ch];
- //
for (port = 0; port < port_num; port++)
{
AX25Sess = &AX25Port[snd_ch][port];
@@ -1703,10 +1714,12 @@ void analiz_frame(int snd_ch, string * frame, void * socket, boolean fecflag)
int get_addr(char * Calls, UCHAR * AXCalls);
-void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, Byte * Msg, int MsgLen)
+void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, char * via, Byte * Msg, int MsgLen)
{
- Byte path[80];
- char Calls[80];
+ char Addrs[256];
+ Byte path[256];
+ int destlen = 0;
+
string * Data = newString();
string * Frame;
@@ -1715,17 +1728,19 @@ void Send_UI(int port, Byte PID, char * CallFrom, char *CallTo, Byte * Msg, int
stringAdd(Data, Msg, MsgLen);
- sprintf(Calls, "%s,%s", CallTo, CallFrom);
+ // We Need Dest, Source, Digis in path, with end of address bit set appropriately.
- get_addr(Calls, path);
+ sprintf(Addrs, "%s %s %s", CallTo, CallFrom, via);
+
+ destlen = get_addr(Addrs, path);
Frame = make_frame(Data, path, PID, 0, 0, U_FRM, U_UI, FALSE, SET_F, SET_C);
// ? Don't we just send to TNC?
- Length = KISS_encode(KISSBuffer, 0, Frame);
+ Length = KISS_encode(KISSBuffer, port, Frame);
- KISSSendtoServer(KISSSockCopy[port], KISSBuffer, Length);
+ KISSSendtoServer(KISSSockCopy[0], KISSBuffer, Length);
monitor_frame(0, Frame, "", 1, 0); // Monitor
freeString(Frame);
diff --git a/debug/moc_predefs.h b/debug/moc_predefs.h
index 6d708a1..62e1baa 100644
--- a/debug/moc_predefs.h
+++ b/debug/moc_predefs.h
@@ -1,7 +1,7 @@
#define _MSC_EXTENSIONS
#define _INTEGRAL_MAX_BITS 64
#define _MSC_VER 1916
-#define _MSC_FULL_VER 191627043
+#define _MSC_FULL_VER 191627051
#define _MSC_BUILD 0
#define _WIN32
#define _M_IX86 600
diff --git a/release/moc_predefs.h b/release/moc_predefs.h
index 54e9037..cf82b6d 100644
--- a/release/moc_predefs.h
+++ b/release/moc_predefs.h
@@ -1,7 +1,7 @@
#define _MSC_EXTENSIONS
#define _INTEGRAL_MAX_BITS 64
#define _MSC_VER 1916
-#define _MSC_FULL_VER 191627043
+#define _MSC_FULL_VER 191627051
#define _MSC_BUILD 0
#define _WIN32
#define _M_IX86 600