mirror of
https://github.com/g4klx/MMDVMHost
synced 2025-12-20 22:45:44 +08:00
Merge remote-tracking branch 'g4klx/master'
This commit is contained in:
@@ -85,18 +85,18 @@ bool CDMRControl::processWakeup(const unsigned char* data)
|
||||
return false;
|
||||
}
|
||||
|
||||
void CDMRControl::writeModemSlot1(unsigned char *data, unsigned int len)
|
||||
bool CDMRControl::writeModemSlot1(unsigned char *data, unsigned int len)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
m_slot1.writeModem(data, len);
|
||||
return m_slot1.writeModem(data, len);
|
||||
}
|
||||
|
||||
void CDMRControl::writeModemSlot2(unsigned char *data, unsigned int len)
|
||||
bool CDMRControl::writeModemSlot2(unsigned char *data, unsigned int len)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
m_slot2.writeModem(data, len);
|
||||
return m_slot2.writeModem(data, len);
|
||||
}
|
||||
|
||||
unsigned int CDMRControl::readModemSlot1(unsigned char *data)
|
||||
|
||||
@@ -36,8 +36,8 @@ public:
|
||||
|
||||
bool processWakeup(const unsigned char* data);
|
||||
|
||||
void writeModemSlot1(unsigned char* data, unsigned int len);
|
||||
void writeModemSlot2(unsigned char* data, unsigned int len);
|
||||
bool writeModemSlot1(unsigned char* data, unsigned int len);
|
||||
bool writeModemSlot2(unsigned char* data, unsigned int len);
|
||||
|
||||
unsigned int readModemSlot1(unsigned char* data);
|
||||
unsigned int readModemSlot2(unsigned char* data);
|
||||
|
||||
98
DMRIDUpdateBM.sh
Normal file
98
DMRIDUpdateBM.sh
Normal file
@@ -0,0 +1,98 @@
|
||||
#! /bin/bash
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# DMRIDUpdate.sh
|
||||
#
|
||||
# Copyright (C) 2016 by Tony Corbett G0WFV
|
||||
# edit by R2AJV
|
||||
# edit by CT2JAY
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
###############################################################################
|
||||
#
|
||||
# On a Linux based system, such as a Raspberry Pi, this script will perform all
|
||||
# the steps required to maintain the DMRIds.dat (or similar) file for you.
|
||||
#
|
||||
# It is designed to run from crontab and will download the latest IDs from the
|
||||
# BM network database and optionally keep a backup of previously
|
||||
# created files for you.
|
||||
#
|
||||
# It will also prune the number of backup files according to a value specified
|
||||
# by you in the configuration below.
|
||||
#
|
||||
# When done, it will restart MMDVMHost to make the ID changes take effect.
|
||||
#
|
||||
# To install in root's crontab use the command ...
|
||||
#
|
||||
# sudo crontab -e
|
||||
#
|
||||
# ... and add the following line to the bottom of the file ...
|
||||
#
|
||||
# 0 0 * * * /path/to/script/DMRIDUpdateBM.sh 1>/dev/null 2>&1
|
||||
#
|
||||
# ... where /path/to/script/ should be replaced by the path to this script.
|
||||
#
|
||||
###############################################################################
|
||||
#
|
||||
# CONFIGURATION
|
||||
#
|
||||
# Full path to DMR ID file
|
||||
DMRIDFILE=/path/to/DMR/ID/file/DMRIds.dat
|
||||
#
|
||||
# How many DMR ID files do you want backed up (0 = do not keep backups)
|
||||
DMRFILEBACKUP=1
|
||||
#
|
||||
# Command line to restart MMDVMHost
|
||||
RESTARTCOMMAND="systemctl restart mmdvmhost.service"
|
||||
# RESTARTCOMMAND="killall MMDVMHost ; /path/to/MMDVMHost/executable/MMDVMHost /path/to/MMDVM/ini/file/MMDVM.ini"
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Do not edit below here
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
# Check we are root
|
||||
if [ "$(id -u)" != "0" ]
|
||||
then
|
||||
echo "This script must be run as root" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create backup of old file
|
||||
if [ ${DMRFILEBACKUP} -ne 0 ]
|
||||
then
|
||||
cp ${DMRIDFILE} ${DMRIDFILE}.$(date +%d%m%y)
|
||||
fi
|
||||
|
||||
# Prune backups
|
||||
BACKUPCOUNT=$(ls ${DMRIDFILE}.* | wc -l)
|
||||
BACKUPSTODELETE=$(expr ${BACKUPCOUNT} - ${DMRFILEBACKUP})
|
||||
|
||||
if [ ${BACKUPCOUNT} -gt ${DMRFILEBACKUP} ]
|
||||
then
|
||||
for f in $(ls -tr ${DMRIDFILE}.* | head -${BACKUPSTODELETE})
|
||||
do
|
||||
rm $f
|
||||
done
|
||||
fi
|
||||
|
||||
# Generate new file
|
||||
curl 'http://registry.dstar.su/dmr/DMRIds.php' 2>/dev/null | sed -e 's/[[:space:]]\+/ /g' > ${DMRIDFILE}
|
||||
|
||||
# Restart MMDVMHost
|
||||
eval ${RESTARTCOMMAND}
|
||||
243
DMRSlot.cpp
243
DMRSlot.cpp
@@ -100,6 +100,8 @@ m_rfBits(1U),
|
||||
m_netBits(1U),
|
||||
m_rfErrs(0U),
|
||||
m_netErrs(0U),
|
||||
m_rfTimeout(false),
|
||||
m_netTimeout(false),
|
||||
m_lastFrame(NULL),
|
||||
m_lastFrameValid(false),
|
||||
m_rssi(0U),
|
||||
@@ -124,7 +126,7 @@ CDMRSlot::~CDMRSlot()
|
||||
delete[] m_lastFrame;
|
||||
}
|
||||
|
||||
void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
@@ -133,19 +135,24 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
LogMessage("DMR Slot %u, RF voice transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
else
|
||||
LogMessage("DMR Slot %u, RF voice transmission lost, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
writeEndRF(true);
|
||||
return;
|
||||
if (m_rfTimeout) {
|
||||
writeEndRF();
|
||||
return false;
|
||||
} else {
|
||||
writeEndRF(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (data[0U] == TAG_LOST && m_rfState == RS_RF_DATA) {
|
||||
LogMessage("DMR Slot %u, RF data transmission lost", m_slotNo);
|
||||
writeEndRF();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data[0U] == TAG_LOST) {
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Have we got RSSI bytes on the end?
|
||||
@@ -183,12 +190,12 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
|
||||
if (dataType == DT_VOICE_LC_HEADER) {
|
||||
if (m_rfState == RS_RF_AUDIO)
|
||||
return;
|
||||
return true;
|
||||
|
||||
CDMRFullLC fullLC;
|
||||
CDMRLC* lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER);
|
||||
if (lc == NULL)
|
||||
return;
|
||||
return false;
|
||||
|
||||
unsigned int srcId = lc->getSrcId();
|
||||
unsigned int dstId = lc->getDstId();
|
||||
@@ -197,13 +204,13 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
if (!CDMRAccessControl::validateSrcId(srcId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
|
||||
delete lc;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
|
||||
delete lc;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_rfLC = lc;
|
||||
@@ -226,6 +233,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
data[1U] = 0x00U;
|
||||
|
||||
m_rfTimeoutTimer.start();
|
||||
m_rfTimeout = false;
|
||||
|
||||
m_rfFrames = 0U;
|
||||
m_rfSeqNo = 0U;
|
||||
@@ -264,9 +272,11 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
}
|
||||
|
||||
LogMessage("DMR Slot %u, received RF voice header from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str());
|
||||
|
||||
return true;
|
||||
} else if (dataType == DT_VOICE_PI_HEADER) {
|
||||
if (m_rfState != RS_RF_AUDIO)
|
||||
return;
|
||||
return false;
|
||||
|
||||
// Regenerate the Slot Type
|
||||
slotType.getData(data + 2U);
|
||||
@@ -287,9 +297,11 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
writeQueueRF(data);
|
||||
|
||||
writeNetworkRF(data, DT_VOICE_PI_HEADER);
|
||||
|
||||
return true;
|
||||
} else if (dataType == DT_TERMINATOR_WITH_LC) {
|
||||
if (m_rfState != RS_RF_AUDIO)
|
||||
return;
|
||||
return false;
|
||||
|
||||
// Regenerate the LC data
|
||||
CDMRFullLC fullLC;
|
||||
@@ -301,15 +313,17 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
// Convert the Data Sync to be from the BS or MS as needed
|
||||
CSync::addDMRDataSync(data + 2U, m_duplex);
|
||||
|
||||
data[0U] = TAG_EOT;
|
||||
data[1U] = 0x00U;
|
||||
if (!m_rfTimeout) {
|
||||
data[0U] = TAG_EOT;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
|
||||
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
|
||||
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
|
||||
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
|
||||
|
||||
if (m_duplex) {
|
||||
for (unsigned int i = 0U; i < m_hangCount; i++)
|
||||
writeQueueRF(data);
|
||||
if (m_duplex) {
|
||||
for (unsigned int i = 0U; i < m_hangCount; i++)
|
||||
writeQueueRF(data);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_rssi != 0U)
|
||||
@@ -317,15 +331,21 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
else
|
||||
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
|
||||
writeEndRF();
|
||||
if (m_rfTimeout) {
|
||||
writeEndRF();
|
||||
return false;
|
||||
} else {
|
||||
writeEndRF();
|
||||
return true;
|
||||
}
|
||||
} else if (dataType == DT_DATA_HEADER) {
|
||||
if (m_rfState == RS_RF_DATA)
|
||||
return;
|
||||
return true;
|
||||
|
||||
CDMRDataHeader dataHeader;
|
||||
bool valid = dataHeader.put(data + 2U);
|
||||
if (!valid)
|
||||
return;
|
||||
return false;
|
||||
|
||||
bool gi = dataHeader.getGI();
|
||||
unsigned int srcId = dataHeader.getSrcId();
|
||||
@@ -333,12 +353,12 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
|
||||
if (!CDMRAccessControl::validateSrcId(srcId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_rfFrames = dataHeader.getBlocks();
|
||||
@@ -383,15 +403,17 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
LogMessage("DMR Slot %u, ended RF data transmission", m_slotNo);
|
||||
writeEndRF();
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (dataType == DT_CSBK) {
|
||||
CDMRCSBK csbk;
|
||||
bool valid = csbk.put(data + 2U);
|
||||
if (!valid)
|
||||
return;
|
||||
return false;
|
||||
|
||||
CSBKO csbko = csbk.getCSBKO();
|
||||
if (csbko == CSBKO_BSDWNACT)
|
||||
return;
|
||||
return false;
|
||||
|
||||
bool gi = csbk.getGI();
|
||||
unsigned int srcId = csbk.getSrcId();
|
||||
@@ -400,12 +422,12 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
if (srcId != 0U || dstId != 0U) {
|
||||
if (!CDMRAccessControl::validateSrcId(srcId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,9 +470,11 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
LogWarning("DMR Slot %u, unhandled RF CSBK type - 0x%02X", m_slotNo, csbko);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (dataType == DT_RATE_12_DATA || dataType == DT_RATE_34_DATA || dataType == DT_RATE_1_DATA) {
|
||||
if (m_rfState != RS_RF_DATA || m_rfFrames == 0U)
|
||||
return;
|
||||
return false;
|
||||
|
||||
// Regenerate the rate 1/2 payload
|
||||
if (dataType == DT_RATE_12_DATA) {
|
||||
@@ -490,6 +514,8 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
LogMessage("DMR Slot %u, ended RF data transmission", m_slotNo);
|
||||
writeEndRF();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} else if (audioSync) {
|
||||
if (m_rfState == RS_RF_AUDIO) {
|
||||
@@ -508,23 +534,30 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
m_rfBits += 141U;
|
||||
m_rfFrames++;
|
||||
|
||||
data[0U] = TAG_DATA;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
m_rfEmbeddedReadN = (m_rfEmbeddedReadN + 1U) % 2U;
|
||||
m_rfEmbeddedWriteN = (m_rfEmbeddedWriteN + 1U) % 2U;
|
||||
|
||||
m_rfEmbeddedData[m_rfEmbeddedWriteN].reset();
|
||||
|
||||
if (m_duplex)
|
||||
writeQueueRF(data);
|
||||
|
||||
writeNetworkRF(data, DT_VOICE_SYNC, errors);
|
||||
|
||||
m_display->writeDMRRSSI(m_slotNo, m_rssi);
|
||||
|
||||
if (!m_rfTimeout) {
|
||||
data[0U] = TAG_DATA;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
if (m_duplex)
|
||||
writeQueueRF(data);
|
||||
|
||||
writeNetworkRF(data, DT_VOICE_SYNC, errors);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (m_rfState == RS_RF_LISTENING) {
|
||||
m_rfEmbeddedLC.reset();
|
||||
m_rfState = RS_RF_LATE_ENTRY;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (m_rfState == RS_RF_AUDIO) {
|
||||
@@ -626,23 +659,29 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
emb.setLCSS(lcss);
|
||||
emb.getData(data + 2U);
|
||||
|
||||
data[0U] = TAG_DATA;
|
||||
data[1U] = 0x00U;
|
||||
if (!m_rfTimeout) {
|
||||
data[0U] = TAG_DATA;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
writeNetworkRF(data, DT_VOICE, errors);
|
||||
writeNetworkRF(data, DT_VOICE, errors);
|
||||
|
||||
if (m_embeddedLCOnly) {
|
||||
// Only send the previously received LC
|
||||
lcss = m_rfEmbeddedLC.getData(data + 2U, m_rfN);
|
||||
if (m_embeddedLCOnly) {
|
||||
// Only send the previously received LC
|
||||
lcss = m_rfEmbeddedLC.getData(data + 2U, m_rfN);
|
||||
|
||||
// Regenerate the EMB
|
||||
emb.setColorCode(m_colorCode);
|
||||
emb.setLCSS(lcss);
|
||||
emb.getData(data + 2U);
|
||||
// Regenerate the EMB
|
||||
emb.setColorCode(m_colorCode);
|
||||
emb.setLCSS(lcss);
|
||||
emb.getData(data + 2U);
|
||||
}
|
||||
|
||||
if (m_duplex)
|
||||
writeQueueRF(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_duplex)
|
||||
writeQueueRF(data);
|
||||
return false;
|
||||
} else if (m_rfState == RS_RF_LATE_ENTRY) {
|
||||
CDMREMB emb;
|
||||
emb.putData(data + 2U);
|
||||
@@ -650,7 +689,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
// If we haven't received an LC yet, then be strict on the color code
|
||||
unsigned char colorCode = emb.getColorCode();
|
||||
if (colorCode != m_colorCode)
|
||||
return;
|
||||
return false;
|
||||
|
||||
m_rfEmbeddedLC.addData(data + 2U, emb.getLCSS());
|
||||
CDMRLC* lc = m_rfEmbeddedLC.getLC();
|
||||
@@ -662,13 +701,13 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
if (!CDMRAccessControl::validateSrcId(srcId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
|
||||
delete lc;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
|
||||
delete lc;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_rfLC = lc;
|
||||
@@ -695,6 +734,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
start[1U] = 0x00U;
|
||||
|
||||
m_rfTimeoutTimer.start();
|
||||
m_rfTimeout = false;
|
||||
|
||||
m_rfFrames = 0U;
|
||||
m_rfSeqNo = 0U;
|
||||
@@ -759,9 +799,13 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
||||
}
|
||||
|
||||
LogMessage("DMR Slot %u, received RF late entry from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int CDMRSlot::readModem(unsigned char* data)
|
||||
@@ -788,14 +832,8 @@ void CDMRSlot::writeEndRF(bool writeEnd)
|
||||
m_display->clearDMR(m_slotNo);
|
||||
}
|
||||
|
||||
m_rfTimeoutTimer.stop();
|
||||
|
||||
m_rfFrames = 0U;
|
||||
m_rfErrs = 0U;
|
||||
m_rfBits = 1U;
|
||||
|
||||
if (writeEnd) {
|
||||
if (m_netState == RS_NET_IDLE && m_duplex) {
|
||||
if (m_netState == RS_NET_IDLE && m_duplex && !m_rfTimeout) {
|
||||
// Create a dummy start end frame
|
||||
unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];
|
||||
|
||||
@@ -817,6 +855,13 @@ void CDMRSlot::writeEndRF(bool writeEnd)
|
||||
}
|
||||
}
|
||||
|
||||
m_rfTimeoutTimer.stop();
|
||||
m_rfTimeout = false;
|
||||
|
||||
m_rfFrames = 0U;
|
||||
m_rfErrs = 0U;
|
||||
m_rfBits = 1U;
|
||||
|
||||
delete m_rfLC;
|
||||
m_rfLC = NULL;
|
||||
}
|
||||
@@ -831,17 +876,7 @@ void CDMRSlot::writeEndNet(bool writeEnd)
|
||||
|
||||
m_lastFrameValid = false;
|
||||
|
||||
m_networkWatchdog.stop();
|
||||
m_netTimeoutTimer.stop();
|
||||
m_packetTimer.stop();
|
||||
|
||||
m_netFrames = 0U;
|
||||
m_netLost = 0U;
|
||||
|
||||
m_netErrs = 0U;
|
||||
m_netBits = 1U;
|
||||
|
||||
if (writeEnd) {
|
||||
if (writeEnd && !m_netTimeout) {
|
||||
// Create a dummy start end frame
|
||||
unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];
|
||||
|
||||
@@ -867,6 +902,17 @@ void CDMRSlot::writeEndNet(bool writeEnd)
|
||||
}
|
||||
}
|
||||
|
||||
m_networkWatchdog.stop();
|
||||
m_netTimeoutTimer.stop();
|
||||
m_packetTimer.stop();
|
||||
m_netTimeout = false;
|
||||
|
||||
m_netFrames = 0U;
|
||||
m_netLost = 0U;
|
||||
|
||||
m_netErrs = 0U;
|
||||
m_netBits = 1U;
|
||||
|
||||
delete m_netLC;
|
||||
m_netLC = NULL;
|
||||
|
||||
@@ -926,6 +972,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
||||
m_lastFrameValid = false;
|
||||
|
||||
m_netTimeoutTimer.start();
|
||||
m_netTimeout = false;
|
||||
|
||||
m_netFrames = 0U;
|
||||
m_netLost = 0U;
|
||||
@@ -974,6 +1021,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
||||
m_lastFrameValid = false;
|
||||
|
||||
m_netTimeoutTimer.start();
|
||||
m_netTimeout = false;
|
||||
|
||||
if (m_duplex) {
|
||||
m_queue.clear();
|
||||
@@ -1063,15 +1111,18 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
||||
// Convert the Data Sync to be from the BS or MS as needed
|
||||
CSync::addDMRDataSync(data + 2U, m_duplex);
|
||||
|
||||
data[0U] = TAG_EOT;
|
||||
data[1U] = 0x00U;
|
||||
if (!m_netTimeout) {
|
||||
data[0U] = TAG_EOT;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
if (m_duplex) {
|
||||
for (unsigned int i = 0U; i < m_hangCount; i++)
|
||||
writeQueueNet(data);
|
||||
} else {
|
||||
for (unsigned int i = 0U; i < 3U; i++)
|
||||
writeQueueNet(data);
|
||||
if (m_duplex) {
|
||||
for (unsigned int i = 0U; i < m_hangCount; i++)
|
||||
writeQueueNet(data);
|
||||
}
|
||||
else {
|
||||
for (unsigned int i = 0U; i < 3U; i++)
|
||||
writeQueueNet(data);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DUMP_DMR)
|
||||
@@ -1155,6 +1206,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
||||
m_lastFrameValid = false;
|
||||
|
||||
m_netTimeoutTimer.start();
|
||||
m_netTimeout = false;
|
||||
|
||||
if (m_duplex) {
|
||||
m_queue.clear();
|
||||
@@ -1231,7 +1283,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
||||
insertSilence(data, dmrData.getSeqNo());
|
||||
}
|
||||
|
||||
writeQueueNet(data);
|
||||
if (!m_netTimeout)
|
||||
writeQueueNet(data);
|
||||
|
||||
m_netEmbeddedReadN = (m_netEmbeddedReadN + 1U) % 2U;
|
||||
m_netEmbeddedWriteN = (m_netEmbeddedWriteN + 1U) % 2U;
|
||||
@@ -1363,7 +1416,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
||||
insertSilence(data, dmrData.getSeqNo());
|
||||
}
|
||||
|
||||
writeQueueNet(data);
|
||||
if (!m_netTimeout)
|
||||
writeQueueNet(data);
|
||||
|
||||
m_packetTimer.start();
|
||||
m_elapsed.start();
|
||||
@@ -1493,7 +1547,20 @@ void CDMRSlot::clock()
|
||||
m_interval.start();
|
||||
|
||||
m_rfTimeoutTimer.clock(ms);
|
||||
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired()) {
|
||||
if (!m_rfTimeout) {
|
||||
LogMessage("DMR Slot %u, RF user has timed out", m_slotNo);
|
||||
m_rfTimeout = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_netTimeoutTimer.clock(ms);
|
||||
if (m_netTimeoutTimer.isRunning() && m_netTimeoutTimer.hasExpired()) {
|
||||
if (!m_netTimeout) {
|
||||
LogMessage("DMR Slot %u, network user has timed out", m_slotNo);
|
||||
m_netTimeout = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_netState == RS_NET_AUDIO || m_netState == RS_NET_DATA) {
|
||||
m_networkWatchdog.clock(ms);
|
||||
@@ -1549,12 +1616,7 @@ void CDMRSlot::writeQueueRF(const unsigned char *data)
|
||||
}
|
||||
|
||||
m_queue.addData(&len, 1U);
|
||||
|
||||
// If the timeout has expired, replace the audio with idles to keep the slot busy
|
||||
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
|
||||
m_queue.addData(m_idle, len);
|
||||
else
|
||||
m_queue.addData(data, len);
|
||||
m_queue.addData(data, len);
|
||||
}
|
||||
|
||||
void CDMRSlot::writeNetworkRF(const unsigned char* data, unsigned char dataType, FLCO flco, unsigned int srcId, unsigned int dstId, unsigned char errors)
|
||||
@@ -1567,10 +1629,6 @@ void CDMRSlot::writeNetworkRF(const unsigned char* data, unsigned char dataType,
|
||||
if (m_network == NULL)
|
||||
return;
|
||||
|
||||
// Don't send to the network if the timeout has expired
|
||||
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
|
||||
return;
|
||||
|
||||
CDMRData dmrData;
|
||||
dmrData.setSlotNo(m_slotNo);
|
||||
dmrData.setDataType(dataType);
|
||||
@@ -1610,12 +1668,7 @@ void CDMRSlot::writeQueueNet(const unsigned char *data)
|
||||
}
|
||||
|
||||
m_queue.addData(&len, 1U);
|
||||
|
||||
// If the timeout has expired, replace the audio with idles to keep the slot busy
|
||||
if (m_netTimeoutTimer.isRunning() && m_netTimeoutTimer.hasExpired())
|
||||
m_queue.addData(m_idle, len);
|
||||
else
|
||||
m_queue.addData(data, len);
|
||||
m_queue.addData(data, len);
|
||||
}
|
||||
|
||||
void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter)
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
CDMRSlot(unsigned int slotNo, unsigned int timeout);
|
||||
~CDMRSlot();
|
||||
|
||||
void writeModem(unsigned char* data, unsigned int len);
|
||||
bool writeModem(unsigned char* data, unsigned int len);
|
||||
|
||||
unsigned int readModem(unsigned char* data);
|
||||
|
||||
@@ -89,6 +89,8 @@ private:
|
||||
unsigned int m_netBits;
|
||||
unsigned int m_rfErrs;
|
||||
unsigned int m_netErrs;
|
||||
bool m_rfTimeout;
|
||||
bool m_netTimeout;
|
||||
unsigned char* m_lastFrame;
|
||||
bool m_lastFrameValid;
|
||||
unsigned char m_rssi;
|
||||
|
||||
@@ -78,21 +78,21 @@ const char* HEADER4 = "Copyright(C) 2015-2017 by Jonathan Naylor, G4KLX and othe
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* iniFile = DEFAULT_INI_FILE;
|
||||
if (argc > 1) {
|
||||
for (int currentArg = 1; currentArg < argc; ++currentArg) {
|
||||
std::string arg = argv[currentArg];
|
||||
if ((arg == "-v") || (arg == "--version")) {
|
||||
::fprintf(stdout, "MMDVMHost version %s\n", VERSION);
|
||||
return 0;
|
||||
} else if (arg.substr(0,1) == "-") {
|
||||
::fprintf(stderr, "Usage: MMDVMHost [-v|--version] [filename]\n");
|
||||
return 1;
|
||||
} else {
|
||||
iniFile = argv[currentArg];
|
||||
}
|
||||
}
|
||||
}
|
||||
const char* iniFile = DEFAULT_INI_FILE;
|
||||
if (argc > 1) {
|
||||
for (int currentArg = 1; currentArg < argc; ++currentArg) {
|
||||
std::string arg = argv[currentArg];
|
||||
if ((arg == "-v") || (arg == "--version")) {
|
||||
::fprintf(stdout, "MMDVMHost version %s git #%.7s\n", VERSION, gitversion);
|
||||
return 0;
|
||||
} else if (arg.substr(0,1) == "-") {
|
||||
::fprintf(stderr, "Usage: MMDVMHost [-v|--version] [filename]\n");
|
||||
return 1;
|
||||
} else {
|
||||
iniFile = argv[currentArg];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
::signal(SIGTERM, sigHandler);
|
||||
@@ -484,11 +484,13 @@ int CMMDVMHost::run()
|
||||
m_dmrTXTimer.start();
|
||||
}
|
||||
} else {
|
||||
dmr->writeModemSlot1(data, len);
|
||||
dmrBeaconTimer.stop();
|
||||
m_modeTimer.start();
|
||||
if (m_duplex)
|
||||
m_dmrTXTimer.start();
|
||||
bool ret = dmr->writeModemSlot1(data, len);
|
||||
if (ret) {
|
||||
dmrBeaconTimer.stop();
|
||||
m_modeTimer.start();
|
||||
if (m_duplex)
|
||||
m_dmrTXTimer.start();
|
||||
}
|
||||
}
|
||||
} else if (m_mode != MODE_LOCKOUT) {
|
||||
LogWarning("DMR modem data received when in mode %u", m_mode);
|
||||
@@ -519,11 +521,13 @@ int CMMDVMHost::run()
|
||||
m_dmrTXTimer.start();
|
||||
}
|
||||
} else {
|
||||
dmr->writeModemSlot2(data, len);
|
||||
dmrBeaconTimer.stop();
|
||||
m_modeTimer.start();
|
||||
if (m_duplex)
|
||||
m_dmrTXTimer.start();
|
||||
bool ret = dmr->writeModemSlot2(data, len);
|
||||
if (ret) {
|
||||
dmrBeaconTimer.stop();
|
||||
m_modeTimer.start();
|
||||
if (m_duplex)
|
||||
m_dmrTXTimer.start();
|
||||
}
|
||||
}
|
||||
} else if (m_mode != MODE_LOCKOUT) {
|
||||
LogWarning("DMR modem data received when in mode %u", m_mode);
|
||||
|
||||
106
RSSI/RSSI_gm340uhf_RA4NHY.dat
Normal file
106
RSSI/RSSI_gm340uhf_RA4NHY.dat
Normal file
@@ -0,0 +1,106 @@
|
||||
#The data to RSSI.dat by RA4NHY
|
||||
#Values in the RSSI.dat file are obtained using the MMDVMCal calibration program (S mode), the high-frequency generator and the Motorola GM340UHF radio station.
|
||||
#For different radio stations, the values are slightly different.
|
||||
#For example, for those GM340 that I had, the discrepancy is about 10 dB.
|
||||
#Therefore, it is desirable to carry out calibration for each radio station.
|
||||
#More about RSSI and a homebrew MMDVM node you can read here https://drive.google.com/file/d/0B_UNZTdPtyZUUjN2d2llV0RtNTQ/view but unfortunately in Russian only
|
||||
#Anton, RA4NHY
|
||||
|
||||
1045 -43
|
||||
1043 -46
|
||||
1042 -47
|
||||
1041 -48
|
||||
1039 -49
|
||||
1036 -50
|
||||
1030 -51
|
||||
1024 -52
|
||||
1017 -53
|
||||
1009 -54
|
||||
1003 -55
|
||||
992 -56
|
||||
980 -57
|
||||
967 -58
|
||||
955 -59
|
||||
941 -60
|
||||
929 -61
|
||||
916 -62
|
||||
905 -63
|
||||
893 -64
|
||||
884 -65
|
||||
874 -66
|
||||
865 -67
|
||||
856 -68
|
||||
848 -69
|
||||
839 -70
|
||||
831 -71
|
||||
823 -72
|
||||
815 -73
|
||||
805 -74
|
||||
799 -75
|
||||
789 -76
|
||||
778 -77
|
||||
767 -78
|
||||
757 -79
|
||||
746 -80
|
||||
737 -81
|
||||
727 -82
|
||||
719 -83
|
||||
711 -84
|
||||
704 -85
|
||||
696 -86
|
||||
689 -87
|
||||
682 -88
|
||||
674 -89
|
||||
667 -90
|
||||
659 -91
|
||||
650 -92
|
||||
641 -93
|
||||
630 -94
|
||||
621 -95
|
||||
610 -96
|
||||
598 -97
|
||||
586 -98
|
||||
575 -99
|
||||
564 -100
|
||||
554 -101
|
||||
544 -102
|
||||
535 -103
|
||||
526 -104
|
||||
521 -105
|
||||
512 -106
|
||||
504 -107
|
||||
495 -108
|
||||
486 -109
|
||||
477 -110
|
||||
468 -111
|
||||
458 -112
|
||||
449 -113
|
||||
439 -114
|
||||
431 -115
|
||||
421 -116
|
||||
412 -117
|
||||
404 -118
|
||||
395 -119
|
||||
387 -120
|
||||
381 -121
|
||||
374 -122
|
||||
368 -123
|
||||
363 -124
|
||||
360 -125
|
||||
355 -126
|
||||
352 -127
|
||||
348 -128
|
||||
345 -129
|
||||
344 -130
|
||||
342 -131
|
||||
340 -132
|
||||
339 -133
|
||||
338 -134
|
||||
337 -135
|
||||
336 -136
|
||||
335 -137
|
||||
334 -138
|
||||
333 -139
|
||||
332 -140
|
||||
331 -141
|
||||
330 -142
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004,2007-2011,2013,2014-2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -40,27 +40,17 @@
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 1000U;
|
||||
|
||||
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS) :
|
||||
m_device(device),
|
||||
m_speed(speed),
|
||||
m_assertRTS(assertRTS),
|
||||
m_handle(INVALID_HANDLE_VALUE),
|
||||
m_readOverlapped(),
|
||||
m_writeOverlapped(),
|
||||
m_readBuffer(NULL),
|
||||
m_readLength(0U),
|
||||
m_readPending(false)
|
||||
m_handle(INVALID_HANDLE_VALUE)
|
||||
{
|
||||
assert(!device.empty());
|
||||
|
||||
m_readBuffer = new unsigned char[BUFFER_LENGTH];
|
||||
}
|
||||
|
||||
CSerialController::~CSerialController()
|
||||
{
|
||||
delete[] m_readBuffer;
|
||||
}
|
||||
|
||||
bool CSerialController::open()
|
||||
@@ -71,7 +61,7 @@ bool CSerialController::open()
|
||||
|
||||
std::string baseName = m_device.substr(4U); // Convert "\\.\COM10" to "COM10"
|
||||
|
||||
m_handle = ::CreateFileA(m_device.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
m_handle = ::CreateFileA(m_device.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (m_handle == INVALID_HANDLE_VALUE) {
|
||||
LogError("Cannot open device - %s, err=%04lx", m_device.c_str(), ::GetLastError());
|
||||
return false;
|
||||
@@ -85,17 +75,18 @@ bool CSerialController::open()
|
||||
return false;
|
||||
}
|
||||
|
||||
dcb.BaudRate = DWORD(m_speed);
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fParity = FALSE;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
dcb.fInX = FALSE;
|
||||
dcb.fOutX = FALSE;
|
||||
dcb.fOutxCtsFlow = FALSE;
|
||||
dcb.fOutxDsrFlow = FALSE;
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
dcb.BaudRate = DWORD(m_speed);
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fParity = FALSE;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
dcb.fInX = FALSE;
|
||||
dcb.fOutX = FALSE;
|
||||
dcb.fOutxCtsFlow = FALSE;
|
||||
dcb.fOutxDsrFlow = FALSE;
|
||||
dcb.fDsrSensitivity = FALSE;
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
|
||||
if (::SetCommState(m_handle, &dcb) == 0) {
|
||||
LogError("Cannot set the attributes for %s, err=%04lx", m_device.c_str(), ::GetLastError());
|
||||
@@ -139,16 +130,6 @@ bool CSerialController::open()
|
||||
|
||||
::ClearCommError(m_handle, &errCode, NULL);
|
||||
|
||||
::memset(&m_readOverlapped, 0x00U, sizeof(OVERLAPPED));
|
||||
::memset(&m_writeOverlapped, 0x00U, sizeof(OVERLAPPED));
|
||||
|
||||
m_readOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
m_writeOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
m_readLength = 0U;
|
||||
m_readPending = false;
|
||||
::memset(m_readBuffer, 0x00U, BUFFER_LENGTH);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -179,49 +160,29 @@ int CSerialController::readNonblock(unsigned char* buffer, unsigned int length)
|
||||
assert(m_handle != INVALID_HANDLE_VALUE);
|
||||
assert(buffer != NULL);
|
||||
|
||||
if (length > BUFFER_LENGTH)
|
||||
length = BUFFER_LENGTH;
|
||||
|
||||
if (m_readPending && length != m_readLength) {
|
||||
::CancelIo(m_handle);
|
||||
m_readPending = false;
|
||||
}
|
||||
|
||||
m_readLength = length;
|
||||
|
||||
if (length == 0U)
|
||||
return 0;
|
||||
|
||||
if (!m_readPending) {
|
||||
DWORD bytes = 0UL;
|
||||
BOOL res = ::ReadFile(m_handle, m_readBuffer, m_readLength, &bytes, &m_readOverlapped);
|
||||
if (res) {
|
||||
::memcpy(buffer, m_readBuffer, bytes);
|
||||
return int(bytes);
|
||||
}
|
||||
|
||||
DWORD error = ::GetLastError();
|
||||
if (error != ERROR_IO_PENDING) {
|
||||
LogError("Error from ReadFile: %04lx", error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_readPending = true;
|
||||
}
|
||||
|
||||
BOOL res = HasOverlappedIoCompleted(&m_readOverlapped);
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
DWORD bytes = 0UL;
|
||||
res = ::GetOverlappedResult(m_handle, &m_readOverlapped, &bytes, TRUE);
|
||||
if (!res) {
|
||||
LogError("Error from GetOverlappedResult (ReadFile): %04lx", ::GetLastError());
|
||||
DWORD errors;
|
||||
COMSTAT status;
|
||||
if (::ClearCommError(m_handle, &errors, &status) == 0) {
|
||||
LogError("Error from ClearCommError for %s, err=%04lx", m_device.c_str(), ::GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
::memcpy(buffer, m_readBuffer, bytes);
|
||||
m_readPending = false;
|
||||
if (status.cbInQue == 0UL)
|
||||
return 0;
|
||||
|
||||
DWORD readLength = status.cbInQue;
|
||||
if (length < readLength)
|
||||
readLength = length;
|
||||
|
||||
DWORD bytes = 0UL;
|
||||
BOOL ret = ::ReadFile(m_handle, buffer, readLength, &bytes, NULL);
|
||||
if (!ret) {
|
||||
LogError("Error from ReadFile for %s: %04lx", m_device.c_str(), ::GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return int(bytes);
|
||||
}
|
||||
@@ -238,19 +199,10 @@ int CSerialController::write(const unsigned char* buffer, unsigned int length)
|
||||
|
||||
while (ptr < length) {
|
||||
DWORD bytes = 0UL;
|
||||
BOOL res = ::WriteFile(m_handle, buffer + ptr, length - ptr, &bytes, &m_writeOverlapped);
|
||||
if (!res) {
|
||||
DWORD error = ::GetLastError();
|
||||
if (error != ERROR_IO_PENDING) {
|
||||
LogError("Error from WriteFile: %04lx", error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = ::GetOverlappedResult(m_handle, &m_writeOverlapped, &bytes, TRUE);
|
||||
if (!res) {
|
||||
LogError("Error from GetOverlappedResult (WriteFile): %04lx", ::GetLastError());
|
||||
return -1;
|
||||
}
|
||||
BOOL ret = ::WriteFile(m_handle, buffer + ptr, length - ptr, &bytes, NULL);
|
||||
if (!ret) {
|
||||
LogError("Error from WriteFile for %s: %04lx", m_device.c_str(), ::GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr += bytes;
|
||||
@@ -265,9 +217,6 @@ void CSerialController::close()
|
||||
|
||||
::CloseHandle(m_handle);
|
||||
m_handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
::CloseHandle(m_readOverlapped.hEvent);
|
||||
::CloseHandle(m_writeOverlapped.hEvent);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -59,11 +59,6 @@ private:
|
||||
bool m_assertRTS;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HANDLE m_handle;
|
||||
OVERLAPPED m_readOverlapped;
|
||||
OVERLAPPED m_writeOverlapped;
|
||||
unsigned char* m_readBuffer;
|
||||
unsigned int m_readLength;
|
||||
bool m_readPending;
|
||||
#else
|
||||
int m_fd;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user