Merge remote-tracking branch 'g4klx/master'

This commit is contained in:
Andy CA6JAU 2017-05-22 20:23:25 -04:00
commit 5c77cf734d
11 changed files with 3241 additions and 235 deletions

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2012 by Ian Wraith * Copyright (C) 2012 by Ian Wraith
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -118,7 +118,7 @@ bool CDMRDataHeader::put(const unsigned char* bytes)
case DPF_UDT: case DPF_UDT:
CUtils::dump(1U, "DMR, Unified Data Transport Header", m_data, 12U); CUtils::dump(1U, "DMR, Unified Data Transport Header", m_data, 12U);
m_blocks = m_data[8U] & 0x03U; m_blocks = (m_data[8U] & 0x03U) + 1U;
break; break;
default: default:
@ -126,14 +126,6 @@ bool CDMRDataHeader::put(const unsigned char* bytes)
break; break;
} }
if (dpf == DPF_UDT && m_blocks == 0U) {
unsigned char format = m_data[1U] & 0x0FU;
if (format == UDTF_NMEA) {
LogDebug("DMR, fixing broken Tytera MD-390 GPS data block count");
m_blocks = 3U;
}
}
return true; return true;
} }
@ -165,46 +157,6 @@ unsigned int CDMRDataHeader::getBlocks() const
return m_blocks; return m_blocks;
} }
void CDMRDataHeader::getTerminator(unsigned char* bytes) const
{
assert(bytes != NULL);
unsigned char payload[12U];
::memset(payload, 0x00U, 12U);
payload[0U] = m_GI ? FLCO_GROUP : FLCO_USER_USER;
payload[1U] = FID_ETSI;
payload[2U] = (m_dstId >> 16) & 0xFFU;
payload[3U] = (m_dstId >> 8) & 0xFFU;
payload[4U] = (m_dstId >> 0) & 0xFFU;
payload[5U] = (m_srcId >> 16) & 0xFFU;
payload[6U] = (m_srcId >> 8) & 0xFFU;
payload[7U] = (m_srcId >> 0) & 0xFFU;
payload[8U] |= m_GI ? 0x80U : 0x00U;
payload[8U] |= m_A ? 0x40U : 0x00U;
payload[8U] |= m_F ? 0x20U : 0x00U;
payload[8U] |= m_S ? 0x08U : 0x00U;
payload[8U] |= m_Ns & 0x07U;
unsigned char parity[4U];
CRS129::encode(payload, 9U, parity);
payload[9U] = parity[2U] ^ TERMINATOR_WITH_LC_CRC_MASK[0U];
payload[10U] = parity[1U] ^ TERMINATOR_WITH_LC_CRC_MASK[1U];
payload[11U] = parity[0U] ^ TERMINATOR_WITH_LC_CRC_MASK[2U];
CUtils::dump(1U, "Data Terminator payload", payload, 12U);
CBPTC19696 bptc;
bptc.encode(payload, bytes);
CUtils::dump(1U, "Data Terminator bytes", bytes, DMR_FRAME_LENGTH_BYTES);
}
CDMRDataHeader& CDMRDataHeader::operator=(const CDMRDataHeader& header) CDMRDataHeader& CDMRDataHeader::operator=(const CDMRDataHeader& header)
{ {
if (&header != this) { if (&header != this) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -29,8 +29,6 @@ public:
void get(unsigned char* bytes) const; void get(unsigned char* bytes) const;
void getTerminator(unsigned char* bytes) const;
bool getGI() const; bool getGI() const;
unsigned int getSrcId() const; unsigned int getSrcId() const;

3200
DMRIds.dat

File diff suppressed because it is too large Load diff

View file

@ -278,6 +278,48 @@ bool CDMRNetwork::write(const CDMRData& data)
return true; return true;
} }
bool CDMRNetwork::writePosition(unsigned int id, const unsigned char* data)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRG", 4U);
::memcpy(buffer + 4U, m_id, 4U);
buffer[8U] = id >> 16;
buffer[9U] = id >> 8;
buffer[10U] = id >> 0;
::memcpy(buffer + 11U, data + 2U, 7U);
return write(buffer, 18U);
}
bool CDMRNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRA", 4U);
::memcpy(buffer + 4U, m_id, 4U);
buffer[8U] = id >> 16;
buffer[9U] = id >> 8;
buffer[10U] = id >> 0;
buffer[11U] = type;
::memcpy(buffer + 12U, data + 2U, 7U);
return write(buffer, 19U);
}
void CDMRNetwork::close() void CDMRNetwork::close()
{ {
LogMessage("DMR, Closing DMR Network"); LogMessage("DMR, Closing DMR Network");

View file

@ -46,6 +46,10 @@ public:
bool write(const CDMRData& data); bool write(const CDMRData& data);
bool writePosition(unsigned int id, const unsigned char* data);
bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data);
bool wantsBeacon(); bool wantsBeacon();
void clock(unsigned int ms); void clock(unsigned int ms);

View file

@ -12,6 +12,7 @@
*/ */
#include "DMRAccessControl.h" #include "DMRAccessControl.h"
#include "DMRDataHeader.h"
#include "DMRSlotType.h" #include "DMRSlotType.h"
#include "DMRShortLC.h" #include "DMRShortLC.h"
#include "DMRTrellis.h" #include "DMRTrellis.h"
@ -83,8 +84,6 @@ m_netEmbeddedWriteN(1U),
m_netTalkerId(TALKER_ID_NONE), m_netTalkerId(TALKER_ID_NONE),
m_rfLC(NULL), m_rfLC(NULL),
m_netLC(NULL), m_netLC(NULL),
m_rfDataHeader(),
m_netDataHeader(),
m_rfSeqNo(0U), m_rfSeqNo(0U),
m_netSeqNo(0U), m_netSeqNo(0U),
m_rfN(0U), m_rfN(0U),
@ -365,8 +364,6 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfFrames = dataHeader.getBlocks(); m_rfFrames = dataHeader.getBlocks();
m_rfDataHeader = dataHeader;
m_rfSeqNo = 0U; m_rfSeqNo = 0U;
m_rfLC = new CDMRLC(gi ? FLCO_GROUP : FLCO_USER_USER, srcId, dstId); m_rfLC = new CDMRLC(gi ? FLCO_GROUP : FLCO_USER_USER, srcId, dstId);
@ -597,13 +594,20 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
// ::sprintf(text, "DMR Slot %u, Embedded LC", m_slotNo); // ::sprintf(text, "DMR Slot %u, Embedded LC", m_slotNo);
// CUtils::dump(1U, text, data, 9U); // CUtils::dump(1U, text, data, 9U);
break; break;
case FLCO_GPS_INFO: case FLCO_GPS_INFO:
if (m_dumpTAData) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
} }
if (m_network != NULL)
m_network->writePosition(m_rfLC->getSrcId(), data);
break; break;
case FLCO_TALKER_ALIAS_HEADER: case FLCO_TALKER_ALIAS_HEADER:
if (m_network != NULL)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 0U, data);
if (!(m_rfTalkerId & TALKER_ID_HEADER)) { if (!(m_rfTalkerId & TALKER_ID_HEADER)) {
if (m_dumpTAData) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo);
@ -613,7 +617,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfTalkerId |= TALKER_ID_HEADER; m_rfTalkerId |= TALKER_ID_HEADER;
} }
break; break;
case FLCO_TALKER_ALIAS_BLOCK1: case FLCO_TALKER_ALIAS_BLOCK1:
if (m_network != NULL)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 1U, data);
if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) { if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) {
if (m_dumpTAData) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo);
@ -623,7 +631,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfTalkerId |= TALKER_ID_BLOCK1; m_rfTalkerId |= TALKER_ID_BLOCK1;
} }
break; break;
case FLCO_TALKER_ALIAS_BLOCK2: case FLCO_TALKER_ALIAS_BLOCK2:
if (m_network != NULL)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 2U, data);
if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) { if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) {
if (m_dumpTAData) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo);
@ -633,7 +645,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfTalkerId |= TALKER_ID_BLOCK2; m_rfTalkerId |= TALKER_ID_BLOCK2;
} }
break; break;
case FLCO_TALKER_ALIAS_BLOCK3: case FLCO_TALKER_ALIAS_BLOCK3:
if (m_network != NULL)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 3U, data);
if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) { if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) {
if (m_dumpTAData) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo);
@ -643,6 +659,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfTalkerId |= TALKER_ID_BLOCK3; m_rfTalkerId |= TALKER_ID_BLOCK3;
} }
break; break;
default: default:
::sprintf(text, "DMR Slot %u, Unknown Embedded Data", m_slotNo); ::sprintf(text, "DMR Slot %u, Unknown Embedded Data", m_slotNo);
CUtils::dump(1U, text, data, 9U); CUtils::dump(1U, text, data, 9U);
@ -947,6 +964,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
unsigned int dstId = lc->getDstId(); unsigned int dstId = lc->getDstId();
unsigned int srcId = lc->getSrcId(); unsigned int srcId = lc->getSrcId();
FLCO flco = lc->getFLCO();
if (dstId != dmrData.getDstId() || srcId != dmrData.getSrcId() || flco != dmrData.getFLCO())
LogWarning("DMR Slot %u, DMRD header doesn't match the DMR RF header: %u->%s%u %u->%s%u", m_slotNo,
dmrData.getSrcId(), dmrData.getFLCO() == FLCO_GROUP ? "TG" : "", dmrData.getDstId(),
srcId, flco == FLCO_GROUP ? "TG" : "", dstId);
m_netLC = lc; m_netLC = lc;
@ -1002,18 +1025,18 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netState = RS_NET_AUDIO; m_netState = RS_NET_AUDIO;
setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), true); setShortLC(m_slotNo, dstId, flco, true);
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
m_display->writeDMR(m_slotNo, src, m_netLC->getFLCO() == FLCO_GROUP, dst, "N"); m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "N");
#if defined(DUMP_DMR) #if defined(DUMP_DMR)
openFile(); openFile();
writeFile(data); writeFile(data);
#endif #endif
LogMessage("DMR Slot %u, received network voice header from %s to %s%s", m_slotNo, src.c_str(), m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dst.c_str()); LogMessage("DMR Slot %u, received network voice header from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str());
} else if (dataType == DT_VOICE_PI_HEADER) { } else if (dataType == DT_VOICE_PI_HEADER) {
if (m_netState != RS_NET_AUDIO) { if (m_netState != RS_NET_AUDIO) {
CDMRLC* lc = new CDMRLC(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId()); CDMRLC* lc = new CDMRLC(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId());
@ -1153,8 +1176,6 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
return; return;
} }
m_netDataHeader = dataHeader;
bool gi = dataHeader.getGI(); bool gi = dataHeader.getGI();
unsigned int srcId = dataHeader.getSrcId(); unsigned int srcId = dataHeader.getSrcId();
unsigned int dstId = dataHeader.getDstId(); unsigned int dstId = dataHeader.getDstId();

View file

@ -21,7 +21,6 @@
#include "RSSIInterpolator.h" #include "RSSIInterpolator.h"
#include "DMREmbeddedData.h" #include "DMREmbeddedData.h"
#include "DMRDataHeader.h"
#include "DMRNetwork.h" #include "DMRNetwork.h"
#include "RingBuffer.h" #include "RingBuffer.h"
#include "StopWatch.h" #include "StopWatch.h"
@ -69,8 +68,6 @@ private:
unsigned char m_netTalkerId; unsigned char m_netTalkerId;
CDMRLC* m_rfLC; CDMRLC* m_rfLC;
CDMRLC* m_netLC; CDMRLC* m_netLC;
CDMRDataHeader m_rfDataHeader;
CDMRDataHeader m_netDataHeader;
unsigned char m_rfSeqNo; unsigned char m_rfSeqNo;
unsigned char m_netSeqNo; unsigned char m_netSeqNo;
unsigned char m_rfN; unsigned char m_rfN;

View file

@ -66,8 +66,8 @@ static int m_signal = 0;
#if !defined(_WIN32) && !defined(_WIN64) #if !defined(_WIN32) && !defined(_WIN64)
static void sigHandler(int signum) static void sigHandler(int signum)
{ {
m_killed = true; m_killed = true;
m_signal = signum; m_signal = signum;
} }
#endif #endif
@ -78,47 +78,47 @@ const char* HEADER4 = "Copyright(C) 2015-2017 by Jonathan Naylor, G4KLX and othe
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
const char* iniFile = DEFAULT_INI_FILE; const char* iniFile = DEFAULT_INI_FILE;
if (argc > 1) { if (argc > 1) {
for (int currentArg = 1; currentArg < argc; ++currentArg) { for (int currentArg = 1; currentArg < argc; ++currentArg) {
std::string arg = argv[currentArg]; std::string arg = argv[currentArg];
if ((arg == "-v") || (arg == "--version")) { if ((arg == "-v") || (arg == "--version")) {
::fprintf(stdout, "MMDVMHost version %s git #%.7s\n", VERSION, gitversion); ::fprintf(stdout, "MMDVMHost version %s git #%.7s\n", VERSION, gitversion);
return 0; return 0;
} else if (arg.substr(0,1) == "-") { } else if (arg.substr(0,1) == "-") {
::fprintf(stderr, "Usage: MMDVMHost [-v|--version] [filename]\n"); ::fprintf(stderr, "Usage: MMDVMHost [-v|--version] [filename]\n");
return 1; return 1;
} else { } else {
iniFile = argv[currentArg]; iniFile = argv[currentArg];
} }
} }
} }
#if !defined(_WIN32) && !defined(_WIN64) #if !defined(_WIN32) && !defined(_WIN64)
::signal(SIGTERM, sigHandler); ::signal(SIGTERM, sigHandler);
::signal(SIGHUP, sigHandler); ::signal(SIGHUP, sigHandler);
#endif #endif
int ret = 0; int ret = 0;
do { do {
m_signal = 0; m_signal = 0;
CMMDVMHost* host = new CMMDVMHost(std::string(iniFile)); CMMDVMHost* host = new CMMDVMHost(std::string(iniFile));
ret = host->run(); ret = host->run();
delete host; delete host;
if (m_signal == 15) if (m_signal == 15)
::LogInfo("Caught SIGTERM, exiting"); ::LogInfo("Caught SIGTERM, exiting");
if (m_signal == 1) if (m_signal == 1)
::LogInfo("Caught SIGHUP, restarting"); ::LogInfo("Caught SIGHUP, restarting");
} while (m_signal == 1); } while (m_signal == 1);
::LogFinalise(); ::LogFinalise();
return ret; return ret;
} }
CMMDVMHost::CMMDVMHost(const std::string& confFile) : CMMDVMHost::CMMDVMHost(const std::string& confFile) :
@ -173,60 +173,60 @@ int CMMDVMHost::run()
// Create new process // Create new process
pid_t pid = ::fork(); pid_t pid = ::fork();
if (pid == -1) { if (pid == -1) {
::LogWarning("Couldn't fork() , exiting"); LogWarning("Couldn't fork() , exiting");
return -1; return -1;
} } else if (pid != 0) {
else if (pid != 0)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
}
// Create new session and process group // Create new session and process group
if (::setsid() == -1){ if (::setsid() == -1){
::LogWarning("Couldn't setsid(), exiting"); LogWarning("Couldn't setsid(), exiting");
return -1; return -1;
} }
// Set the working directory to the root directory // Set the working directory to the root directory
if (::chdir("/") == -1){ if (::chdir("/") == -1){
::LogWarning("Couldn't cd /, exiting"); LogWarning("Couldn't cd /, exiting");
return -1; return -1;
} }
::close(STDIN_FILENO); ::close(STDIN_FILENO);
::close(STDOUT_FILENO); ::close(STDOUT_FILENO);
::close(STDERR_FILENO); ::close(STDERR_FILENO);
#if !defined(HD44780) && !defined(OLED) #if !defined(HD44780) && !defined(OLED)
//If we are currently root... //If we are currently root...
if (getuid() == 0) { if (getuid() == 0) {
struct passwd* user = ::getpwnam("mmdvm"); struct passwd* user = ::getpwnam("mmdvm");
if (user == NULL) { if (user == NULL) {
::LogError("Could not get the mmdvm user, exiting"); LogError("Could not get the mmdvm user, exiting");
return -1; return -1;
} }
uid_t mmdvm_uid = user->pw_uid; uid_t mmdvm_uid = user->pw_uid;
gid_t mmdvm_gid = user->pw_gid; gid_t mmdvm_gid = user->pw_gid;
//Set user and group ID's to mmdvm:mmdvm //Set user and group ID's to mmdvm:mmdvm
if (setgid(mmdvm_gid) != 0) { if (::setgid(mmdvm_gid) != 0) {
::LogWarning("Could not set mmdvm GID, exiting"); LogWarning("Could not set mmdvm GID, exiting");
return -1; return -1;
} }
if (setuid(mmdvm_uid) != 0) { if (::setuid(mmdvm_uid) != 0) {
::LogWarning("Could not set mmdvm UID, exiting"); LogWarning("Could not set mmdvm UID, exiting");
return -1; return -1;
} }
//Double check it worked (AKA Paranoia) //Double check it worked (AKA Paranoia)
if (setuid(0) != -1){ if (::setuid(0) != -1){
::LogWarning("It's possible to regain root - something is wrong!, exiting"); LogWarning("It's possible to regain root - something is wrong!, exiting");
return -1; return -1;
} }
} }
} }
#else #else
::LogWarning("Dropping root permissions in daemon mode is disabled with HD44780 display"); LogWarning("Dropping root permissions in daemon mode is disabled with HD44780 display");
} }
#endif #endif
#endif #endif

View file

@ -916,7 +916,7 @@ bool CModem::readVersion()
} }
} }
CThread::sleep(1000U); CThread::sleep(1500U);
} }
LogError("Unable to read the firmware version after six attempts"); LogError("Unable to read the firmware version after six attempts");

View file

@ -177,7 +177,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
if (duid == P25_DUID_LDU1) { if (duid == P25_DUID_LDU1) {
if (m_rfState == RS_RF_LISTENING) { if (m_rfState == RS_RF_LISTENING) {
m_rfData.reset(); m_rfData.reset();
bool ret = m_rfData.decodeLDU1(data + 2U, m_network, m_uidOverride); bool ret = m_rfData.decodeLDU1(data + 2U, m_network != NULL, m_uidOverride);
if (!ret) { if (!ret) {
m_lastDUID = duid; m_lastDUID = duid;
return false; return false;

View file

@ -19,6 +19,6 @@
#if !defined(VERSION_H) #if !defined(VERSION_H)
#define VERSION_H #define VERSION_H
const char* VERSION = "20170406"; const char* VERSION = "20170501";
#endif #endif