diff --git a/DStarControl.cpp b/DStarControl.cpp index a8a9670..b941a59 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -60,7 +60,8 @@ m_netHeader(), m_rfState(RS_RF_LISTENING), m_netState(RS_NET_IDLE), m_net(false), -m_slowData(), +m_rfSlowData(), +m_netSlowData(), m_rfN(0U), m_netN(0U), m_networkWatchdog(1000U, 0U, 1500U), @@ -384,6 +385,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_rssiAccum = m_rssi; m_rssiCount = 1U; + m_rfSlowData.start(); + if (m_duplex) { // Modify the header header.setRepeater(false); @@ -465,15 +468,17 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) } else if (m_rfState == RS_RF_LISTENING) { // The sync is regenerated by the modem so can do exact match if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) { - m_slowData.start(); + m_rfSlowData.start(); m_rfState = RS_RF_LATE_ENTRY; } return false; } else if (m_rfState == RS_RF_AUDIO) { // The sync is regenerated by the modem so can do exact match - if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) + if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) { + m_rfSlowData.start(); m_rfN = 0U; + } // Regenerate the sync and send the RSSI data to the display if (m_rfN == 0U) { @@ -495,6 +500,10 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) writeJSONBER(); + const unsigned char* text = m_rfSlowData.addText(data + 1U); + if (text != NULL) + LogMessage("D-Star, slow data text = \"%s\"", text); + if (m_net) { if (m_rfN == 1U) writeNetworkDataRF(m_rfVoiceSyncData, 0U, false); @@ -513,11 +522,11 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) } else if (m_rfState == RS_RF_LATE_ENTRY) { // The sync is regenerated by the modem so can do exact match if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) { - m_slowData.reset(); + m_rfSlowData.reset(); return false; } - CDStarHeader* header = m_slowData.add(data + 1U); + CDStarHeader* header = m_rfSlowData.addHeader(data + 1U); if (header == NULL) return false; @@ -841,8 +850,14 @@ void CDStarControl::writeNetwork() m_netN = n; // Regenerate the sync - if (n == 0U) + if (n == 0U) { CSync::addDStarSync(data + 2U); + m_netSlowData.start(); + } + + const unsigned char* text = m_netSlowData.addText(data + 2U); + if (text != NULL) + LogMessage("D-Star, slow data text = \"%s\"", text); m_packetTimer.start(); m_netFrames++; @@ -1255,12 +1270,12 @@ void CDStarControl::sendAck() ::sprintf(text, "BER: %.1f%% ", float(m_rfErrs * 100U) / float(m_rfBits)); } - m_slowData.setText(text); + m_rfSlowData.setText(text); ::memcpy(data, DSTAR_NULL_FRAME_DATA_BYTES, DSTAR_FRAME_LENGTH_BYTES + 1U); for (unsigned int i = 0U; i < 19U; i++) { - m_slowData.get(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES); + m_rfSlowData.getSlowData(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES); writeQueueDataRF(data); } @@ -1320,12 +1335,12 @@ void CDStarControl::sendError() ::sprintf(text, "BER: %.1f%% ", float(m_rfErrs * 100U) / float(m_rfBits)); } - m_slowData.setText(text); + m_rfSlowData.setText(text); ::memcpy(data, DSTAR_NULL_FRAME_DATA_BYTES, DSTAR_FRAME_LENGTH_BYTES + 1U); for (unsigned int i = 0U; i < 19U; i++) { - m_slowData.get(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES); + m_rfSlowData.getSlowData(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES); writeQueueDataRF(data); } diff --git a/DStarControl.h b/DStarControl.h index 9f24b78..1eef4f8 100644 --- a/DStarControl.h +++ b/DStarControl.h @@ -71,7 +71,8 @@ private: RPT_RF_STATE m_rfState; RPT_NET_STATE m_netState; bool m_net; - CDStarSlowData m_slowData; + CDStarSlowData m_rfSlowData; + CDStarSlowData m_netSlowData; unsigned char m_rfN; unsigned char m_netN; CTimer m_networkWatchdog; diff --git a/DStarSlowData.cpp b/DStarSlowData.cpp index d33ca7e..5f11b70 100644 --- a/DStarSlowData.cpp +++ b/DStarSlowData.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016 by Jonathan Naylor G4KLX +* Copyright (C) 2016,2023 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 @@ -18,6 +18,7 @@ #include "DStarSlowData.h" #include "DStarDefines.h" +#include "Utils.h" #include "CRC.h" #include "Log.h" @@ -31,6 +32,7 @@ m_ptr(0U), m_buffer(NULL), m_text(NULL), m_textPtr(0U), +m_textBits(0x00U), m_state(SDD_FIRST) { m_header = new unsigned char[50U]; // DSTAR_HEADER_LENGTH_BYTES @@ -45,7 +47,7 @@ CDStarSlowData::~CDStarSlowData() delete[] m_text; } -CDStarHeader* CDStarSlowData::add(const unsigned char* data) +CDStarHeader* CDStarSlowData::addHeader(const unsigned char* data) { assert(data != NULL); @@ -93,18 +95,92 @@ CDStarHeader* CDStarSlowData::add(const unsigned char* data) return new CDStarHeader(m_header); } +const unsigned char* CDStarSlowData::addText(const unsigned char* data) +{ + assert(data != NULL); + + switch (m_state) { + case SDD_FIRST: + m_buffer[0U] = data[9U] ^ DSTAR_SCRAMBLER_BYTES[0U]; + m_buffer[1U] = data[10U] ^ DSTAR_SCRAMBLER_BYTES[1U]; + m_buffer[2U] = data[11U] ^ DSTAR_SCRAMBLER_BYTES[2U]; + m_state = SDD_SECOND; + return NULL; + + case SDD_SECOND: + m_buffer[3U] = data[9U] ^ DSTAR_SCRAMBLER_BYTES[0U]; + m_buffer[4U] = data[10U] ^ DSTAR_SCRAMBLER_BYTES[1U]; + m_buffer[5U] = data[11U] ^ DSTAR_SCRAMBLER_BYTES[2U]; + m_state = SDD_FIRST; + break; + } + + switch (m_buffer[0U]) { + case DSTAR_SLOW_DATA_TYPE_TEXT | 0U: + CUtils::dump(1U, "D-Star slow data text fragment", m_buffer, 6U); + m_text[0U] = m_buffer[1U] & 0x7FU; + m_text[1U] = m_buffer[2U] & 0x7FU; + m_text[2U] = m_buffer[3U] & 0x7FU; + m_text[3U] = m_buffer[4U] & 0x7FU; + m_text[4U] = m_buffer[5U] & 0x7FU; + m_textBits |= 0x01U; + break; + case DSTAR_SLOW_DATA_TYPE_TEXT | 1U: + CUtils::dump(1U, "D-Star slow data text fragment", m_buffer, 6U); + m_text[5U] = m_buffer[1U] & 0x7FU; + m_text[6U] = m_buffer[2U] & 0x7FU; + m_text[7U] = m_buffer[3U] & 0x7FU; + m_text[8U] = m_buffer[4U] & 0x7FU; + m_text[9U] = m_buffer[5U] & 0x7FU; + m_textBits |= 0x02U; + break; + case DSTAR_SLOW_DATA_TYPE_TEXT | 2U: + CUtils::dump(1U, "D-Star slow data text fragment", m_buffer, 6U); + m_text[10U] = m_buffer[1U] & 0x7FU; + m_text[11U] = m_buffer[2U] & 0x7FU; + m_text[12U] = m_buffer[3U] & 0x7FU; + m_text[13U] = m_buffer[4U] & 0x7FU; + m_text[14U] = m_buffer[5U] & 0x7FU; + m_textBits |= 0x04U; + break; + case DSTAR_SLOW_DATA_TYPE_TEXT | 3U: + CUtils::dump(1U, "D-Star slow data text fragment", m_buffer, 6U); + m_text[15U] = m_buffer[1U] & 0x7FU; + m_text[16U] = m_buffer[2U] & 0x7FU; + m_text[17U] = m_buffer[3U] & 0x7FU; + m_text[18U] = m_buffer[4U] & 0x7FU; + m_text[19U] = m_buffer[5U] & 0x7FU; + m_text[20U] = 0x00U; + m_textBits |= 0x08U; + break; + default: + return NULL; + } + + if (m_textBits != 0x0FU) + return NULL; + + CUtils::dump(1U, "D-STar slow data text", m_text, 20U); + + m_textBits = 0x00U; + + return m_text; +} + void CDStarSlowData::start() { ::memset(m_header, 0x00U, DSTAR_HEADER_LENGTH_BYTES); - m_ptr = 0U; - m_state = SDD_FIRST; + m_ptr = 0U; + m_state = SDD_FIRST; + m_textBits = 0x00U; } void CDStarSlowData::reset() { - m_ptr = 0U; - m_state = SDD_FIRST; + m_ptr = 0U; + m_state = SDD_FIRST; + m_textBits = 0x00U; } void CDStarSlowData::setText(const char* text) @@ -139,10 +215,11 @@ void CDStarSlowData::setText(const char* text) m_text[22U] = text[18U]; m_text[23U] = text[19U]; - m_textPtr = 0U; + m_textPtr = 0U; + m_textBits = 0x00U; } -void CDStarSlowData::get(unsigned char* data) +void CDStarSlowData::getSlowData(unsigned char* data) { assert(data != NULL); diff --git a/DStarSlowData.h b/DStarSlowData.h index 52e0f5c..eaedf45 100644 --- a/DStarSlowData.h +++ b/DStarSlowData.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016 by Jonathan Naylor G4KLX +* Copyright (C) 2016,2023 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 @@ -26,13 +26,15 @@ public: CDStarSlowData(); ~CDStarSlowData(); - CDStarHeader* add(const unsigned char* data); + CDStarHeader* addHeader(const unsigned char* data); + + const unsigned char* addText(const unsigned char* data); void start(); void reset(); void setText(const char* text); - void get(unsigned char* data); + void getSlowData(unsigned char* data); private: unsigned char* m_header; @@ -40,6 +42,7 @@ private: unsigned char* m_buffer; unsigned char* m_text; unsigned int m_textPtr; + unsigned char m_textBits; enum SDD_STATE { SDD_FIRST, diff --git a/M17Control.cpp b/M17Control.cpp index 75fc13f..e31311d 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -89,6 +89,10 @@ m_rfCollectedLSF(), m_rfLSFn(0U), m_netLSF(), m_netLSFn(0U), +m_rfTextBits(0x00U), +m_netTextBits(0x00U), +m_rfText(NULL), +m_netText(NULL), m_rssiMapper(rssiMapper), m_rssi(0U), m_maxRSSI(0U), @@ -104,10 +108,15 @@ m_fp(NULL) { assert(display != NULL); assert(rssiMapper != NULL); + + m_rfText = new char[4U * M17_META_LENGTH_BYTES]; + m_netText = new char[4U * M17_META_LENGTH_BYTES]; } CM17Control::~CM17Control() { + delete[] m_netText; + delete[] m_rfText; } bool CM17Control::writeModem(unsigned char* data, unsigned int len) @@ -217,7 +226,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_rfLSFn = 0U; m_rfLSFCount = 0U; - + m_rfTextBits = 0x00U; + ::memset(m_rfText, 0x00U, 4U * M17_META_LENGTH_BYTES); #if defined(DUMP_M17) openFile(); #endif @@ -279,7 +289,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_bitsCount = 0U; m_rfLSFCount = 0U; - + m_rfTextBits = 0x00U; + ::memset(m_rfText, 0x00U, 4U * M17_META_LENGTH_BYTES); #if defined(DUMP_M17) openFile(); #endif @@ -312,6 +323,38 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (valid) { m_rfCollectedLSF = m_rfCollectingLSF; m_rfCollectingLSF.reset(); + + unsigned char encryptionType = m_rfCollectedLSF.getEncryptionType(); + unsigned char encryptionSubType = m_rfCollectedLSF.getEncryptionSubType(); + if (encryptionType == M17_ENCRYPTION_TYPE_NONE && encryptionSubType == M17_ENCRYPTION_SUB_TYPE_TEXT) { + unsigned char meta[20U]; + m_rfCollectedLSF.getMeta(meta); + CUtils::dump(1U, "M17, LSF text data fragment", meta, M17_META_LENGTH_BYTES); + + m_rfTextBits |= meta[0U]; + + switch (meta[0U] & 0x0FU) { + case 0x01U: + ::memcpy(m_rfText + 0U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x02U: + ::memcpy(m_rfText + 13U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x04U: + ::memcpy(m_rfText + 26U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x08U: + ::memcpy(m_rfText + 39U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + default: + break; + } + + if (m_rfTextBits == 0x11U || m_rfTextBits == 0x33U || m_rfTextBits == 0x77U || m_rfTextBits == 0xFFU) { + LogMessage("M17, text Data: \"%s\"", m_rfText); + m_rfTextBits = 0x00U; + } + } } } @@ -587,8 +630,10 @@ void CM17Control::writeNetwork() m_netTimeoutTimer.start(); m_elapsed.start(); - m_netFrames = 0U; - m_netLSFn = 0U; + m_netFrames = 0U; + m_netLSFn = 0U; + m_netTextBits = 0x00U; + ::memset(m_netText, 0x00U, 4U * M17_META_LENGTH_BYTES); // Create a dummy start message unsigned char start[M17_FRAME_LENGTH_BYTES + 2U]; @@ -620,6 +665,38 @@ void CM17Control::writeNetwork() m_netLSF.setSource(m_callsign); m_netLSF.setCAN(m_can); + + unsigned char encryptionType = m_netLSF.getEncryptionType(); + unsigned char encryptionSubType = m_netLSF.getEncryptionSubType(); + if (encryptionType == M17_ENCRYPTION_TYPE_NONE && encryptionSubType == M17_ENCRYPTION_SUB_TYPE_TEXT) { + unsigned char meta[20U]; + m_netLSF.getMeta(meta); + CUtils::dump(1U, "M17, LSF text data fragment", meta, M17_META_LENGTH_BYTES); + + m_netTextBits |= meta[0U]; + + switch (meta[0U] & 0x0FU) { + case 0x01U: + ::memcpy(m_netText + 0U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x02U: + ::memcpy(m_netText + 13U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x04U: + ::memcpy(m_netText + 26U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x08U: + ::memcpy(m_netText + 39U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + default: + break; + } + + if (m_netTextBits == 0x11U || m_netTextBits == 0x33U || m_netTextBits == 0x77U || m_netTextBits == 0xFFU) { + LogMessage("M17, text Data: \"%s\"", m_netText); + m_netTextBits = 0x00U; + } + } } unsigned char data[M17_FRAME_LENGTH_BYTES + 2U]; diff --git a/M17Control.h b/M17Control.h index 6cdf45a..81a7282 100644 --- a/M17Control.h +++ b/M17Control.h @@ -78,6 +78,10 @@ private: unsigned int m_rfLSFn; CM17LSF m_netLSF; unsigned int m_netLSFn; + unsigned char m_rfTextBits; + unsigned char m_netTextBits; + char* m_rfText; + char* m_netText; CRSSIInterpolator* m_rssiMapper; unsigned char m_rssi; unsigned char m_maxRSSI;