add support for properly encoding/decoding the PI header LC;

pull/1/head
Bryan Biedenkapp 5 years ago
parent 33569945fb
commit 30513bb1d2

@ -163,6 +163,7 @@
<ClInclude Include="dmr\Control.h" />
<ClInclude Include="dmr\DataPacket.h" />
<ClInclude Include="dmr\DMRDefines.h" />
<ClInclude Include="dmr\lc\PrivacyLC.h" />
<ClInclude Include="dmr\SiteData.h" />
<ClInclude Include="dmr\Slot.h" />
<ClInclude Include="dmr\SlotType.h" />
@ -241,6 +242,7 @@
<ClCompile Include="dmr\data\EmbeddedData.cpp" />
<ClCompile Include="dmr\Control.cpp" />
<ClCompile Include="dmr\DataPacket.cpp" />
<ClCompile Include="dmr\lc\PrivacyLC.cpp" />
<ClCompile Include="dmr\Slot.cpp" />
<ClCompile Include="dmr\SlotType.cpp" />
<ClCompile Include="dmr\Sync.cpp" />

@ -350,6 +350,9 @@
<ClInclude Include="modem\port\UDPPort.h">
<Filter>Header Files\modem\port</Filter>
</ClInclude>
<ClInclude Include="dmr\lc\PrivacyLC.h">
<Filter>Header Files\dmr\lc</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Log.cpp">
@ -562,6 +565,9 @@
<ClCompile Include="modem\port\ISerialPort.cpp">
<Filter>Source Files\modem\port</Filter>
</ClCompile>
<ClCompile Include="dmr\lc\PrivacyLC.cpp">
<Filter>Source Files\dmr\lc</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="Makefile" />

@ -25,6 +25,7 @@ OBJECTS = \
dmr/lc/CSBK.o \
dmr/lc/FullLC.o \
dmr/lc/LC.o \
dmr/lc/PrivacyLC.o \
dmr/lc/ShortLC.o \
dmr/Control.o \
dmr/ControlPacket.o \

@ -25,6 +25,7 @@ OBJECTS = \
dmr/lc/CSBK.o \
dmr/lc/FullLC.o \
dmr/lc/LC.o \
dmr/lc/PrivacyLC.o \
dmr/lc/ShortLC.o \
dmr/Control.o \
dmr/ControlPacket.o \

@ -25,6 +25,7 @@ OBJECTS = \
dmr/lc/CSBK.o \
dmr/lc/FullLC.o \
dmr/lc/LC.o \
dmr/lc/PrivacyLC.o \
dmr/lc/ShortLC.o \
dmr/Control.o \
dmr/ControlPacket.o \

@ -183,8 +183,6 @@ void Utils::symbols(const std::string& title, const uint8_t* data, uint32_t leng
while (bufLen > 0U) {
std::string output;
uint32_t bytes = (bufLen > 18U) ? 18U : bufLen;
uint32_t symOffset = offset;
// iterate through bytes in groups of 2

@ -131,6 +131,8 @@ namespace dmr
const uint32_t DMR_MAX_PDU_COUNT = 32U;
const uint32_t DMR_MAX_PDU_LENGTH = 512U;
const uint32_t DMR_MI_LENGTH_BYTES = 4U; // This was guessed based on OTA data captures -- the message indicator seems to be the same length as a source/destination address
const uint8_t FID_ETSI = 0x00U; // ETSI Standard Feature Set
const uint8_t FID_DMRA = 0x10U; //

@ -113,8 +113,10 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz
m_netState(RS_NET_IDLE),
m_netLastDstId(0U),
m_rfLC(NULL),
m_rfPrivacyLC(NULL),
m_rfSeqNo(0U),
m_netLC(NULL),
m_netPrivacyLC(NULL),
m_networkWatchdog(1000U, 0U, 1500U),
m_rfTimeoutTimer(1000U, timeout),
m_rfTGHang(1000U, tgHang),

@ -12,7 +12,7 @@
//
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017-2020 by Bryan Biedenkapp N2PLL
* Copyright (C) 2017-2021 by Bryan Biedenkapp N2PLL
*
* 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
@ -113,10 +113,12 @@ namespace dmr
uint32_t m_netLastDstId;
lc::LC* m_rfLC;
lc::PrivacyLC* m_rfPrivacyLC;
uint8_t m_rfSeqNo;
lc::LC* m_netLC;
lc::PrivacyLC* m_netPrivacyLC;
Timer m_networkWatchdog;
Timer m_rfTimeoutTimer;

@ -204,6 +204,14 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
if (m_slot->m_rfState != RS_RF_AUDIO)
return false;
lc::FullLC fullLC;
lc::PrivacyLC* lc = fullLC.decodePI(data + 2U);
/*
if (lc == NULL)
return false;
*/
m_slot->m_rfPrivacyLC = lc;
// Regenerate the Slot Type
slotType.encode(data + 2U);
@ -225,7 +233,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
m_slot->writeNetworkRF(data, DT_VOICE_PI_HEADER);
if (m_verbose) {
LogMessage(LOG_RF, DMR_DT_VOICE_PI_HEADER ", slot = %u", m_slot->m_slotNo);
LogMessage(LOG_RF, DMR_DT_VOICE_PI_HEADER ", slot = %u, algId = %u, kId = %u, dstId = %u", m_slot->m_slotNo, lc->getAlgId(), lc->getKId(), lc->getDstId());
}
return true;
@ -729,6 +737,17 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
m_slot->m_slotNo, srcId, m_slot->m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dstId);
}
lc::FullLC fullLC;
lc::PrivacyLC* lc = fullLC.decodePI(data + 2U);
/*
if (lc == NULL) {
LogWarning(LOG_NET, "DMR Slot %u, DT_VOICE_PI_HEADER, bad LC received from the network, replacing", m_slot->m_slotNo);
lc = new lc::PrivacyLC();
lc->setDstId(dmrData.getDstId());
}
*/
m_slot->m_netPrivacyLC = lc;
// Regenerate the Slot Type
SlotType slotType;
slotType.setColorCode(m_slot->m_colorCode);
@ -750,7 +769,7 @@ void VoicePacket::processNetwork(const data::Data& dmrData)
m_slot->writeQueueNet(data);
if (m_verbose) {
LogMessage(LOG_NET, DMR_DT_VOICE_PI_HEADER ", slot = %u", m_slot->m_slotNo);
LogMessage(LOG_NET, DMR_DT_VOICE_PI_HEADER ", slot = %u, algId = %u, kId = %u, dstId = %u", m_slot->m_slotNo, lc->getAlgId(), lc->getKId(), lc->getDstId());
}
}
else if (dataType == DT_VOICE_SYNC) {

@ -12,7 +12,7 @@
//
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017-2019 by Bryan Biedenkapp N2PLL
* Copyright (C) 2017-2021 by Bryan Biedenkapp N2PLL
*
* 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
@ -35,6 +35,7 @@
#include "dmr/data/Data.h"
#include "dmr/data/EmbeddedData.h"
#include "dmr/lc/LC.h"
#include "dmr/lc/PrivacyLC.h"
#include "dmr/Slot.h"
#include "edac/AMBEFEC.h"
#include "network/BaseNetwork.h"

@ -13,6 +13,7 @@
/*
* Copyright (C) 2012 by Ian Wraith
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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
@ -32,6 +33,7 @@
#include "dmr/DMRDefines.h"
#include "dmr/lc/FullLC.h"
#include "edac/RS129.h"
#include "edac/CRC.h"
#include "Log.h"
#include "Utils.h"
@ -138,3 +140,45 @@ void FullLC::encode(const LC& lc, uint8_t* data, uint8_t type)
// encode BPTC (196,96) FEC
m_bptc.encode(lcData, data);
}
/// <summary>
/// Decode DMR privacy control data.
/// </summary>
/// <param name="data"></param>
/// <param name="type"></param>
/// <returns></returns>
PrivacyLC* FullLC::decodePI(const uint8_t* data)
{
assert(data != NULL);
// decode BPTC (196,96) FEC
uint8_t lcData[DMR_LC_HEADER_LENGTH_BYTES];
m_bptc.decode(data, lcData);
// check CRC-CCITT 16,2
// if (!edac::CRC::checkCCITT162(lcData, DMR_LC_HEADER_LENGTH_BYTES))
// return NULL;
return new PrivacyLC(lcData);
}
/// <summary>
/// Encode DMR privacy control data.
/// </summary>
/// <param name="lc"></param>
/// <param name="data"></param>
/// <param name="type"></param>
void FullLC::encodePI(const PrivacyLC& lc, uint8_t* data)
{
assert(data != NULL);
uint8_t lcData[DMR_LC_HEADER_LENGTH_BYTES];
lc.getData(lcData);
// encode CRC-CCITT 16,2
// uint8_t parity[2U];
// edac::CRC::addCCITT162(lcData, 9U);
// encode BPTC (196,96) FEC
m_bptc.encode(lcData, data);
}

@ -12,6 +12,7 @@
//
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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
@ -32,6 +33,7 @@
#include "Defines.h"
#include "dmr/lc/LC.h"
#include "dmr/lc/PrivacyLC.h"
#include "dmr/SlotType.h"
#include "edac/BPTC19696.h"
@ -56,6 +58,11 @@ namespace dmr
/// <summary>Encode DMR full-link control data.</summary>
void encode(const LC& lc, uint8_t* data, uint8_t type);
/// <summary>Decode DMR privacy control data.</summary>
PrivacyLC* decodePI(const uint8_t* data);
/// <summary>Encode DMR privacy control data.</summary>
void encodePI(const PrivacyLC& lc, uint8_t* data);
private:
edac::BPTC19696 m_bptc;
};

@ -12,6 +12,7 @@
//
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2020-2021 by Bryan Biedenkapp N2PLL
*
* 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
@ -49,7 +50,7 @@ using namespace dmr;
LC::LC(uint8_t flco, uint32_t srcId, uint32_t dstId) :
m_PF(false),
m_FLCO(flco),
m_FID(0U),
m_FID(FID_ETSI),
m_srcId(srcId),
m_dstId(dstId),
m_emergency(false),
@ -68,7 +69,7 @@ LC::LC(uint8_t flco, uint32_t srcId, uint32_t dstId) :
LC::LC(const uint8_t* bytes) :
m_PF(false),
m_FLCO(FLCO_GROUP),
m_FID(0U),
m_FID(FID_ETSI),
m_srcId(0U),
m_dstId(0U),
m_emergency(false),
@ -103,7 +104,7 @@ LC::LC(const uint8_t* bytes) :
LC::LC(const bool* bits) :
m_PF(false),
m_FLCO(FLCO_GROUP),
m_FID(0U),
m_FID(FID_ETSI),
m_srcId(0U),
m_dstId(0U),
m_emergency(false),
@ -152,7 +153,7 @@ LC::LC(const bool* bits) :
LC::LC() :
m_PF(false),
m_FLCO(FLCO_GROUP),
m_FID(0U),
m_FID(FID_ETSI),
m_srcId(0U),
m_dstId(0U),
m_emergency(false),

@ -12,6 +12,7 @@
//
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2020-2021 by Bryan Biedenkapp N2PLL
*
* 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
@ -67,7 +68,7 @@ namespace dmr
/// <summary>Full-link control opcode.</summary>
__PROPERTY(uint8_t, FLCO, FLCO);
/// <summary>CSBK feature ID.</summayr>
/// <summary>Feature ID.</summayr>
__PROPERTY(uint8_t, FID, FID);
/// <summary>Source ID.</summary>

@ -0,0 +1,186 @@
/**
* Digital Voice Modem - Host Software
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Host Software
*
*/
//
// Based on code from the MMDVMHost project. (https://github.com/g4klx/MMDVMHost)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
/*
* Copyright (C) 2021 by Bryan Biedenkapp N2PLL
*
* 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.
*/
#include "Defines.h"
#include "dmr/lc/PrivacyLC.h"
#include "edac/CRC.h"
#include "Utils.h"
using namespace dmr::lc;
using namespace dmr;
#include <cstdio>
#include <cassert>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the PrivacyLC class.
/// </summary>
/// <param name="bytes"></param>
PrivacyLC::PrivacyLC(const uint8_t* bytes) :
m_FID(FID_ETSI),
m_dstId(0U),
m_group(false),
m_algId(0U),
m_kId(0U),
m_mi(NULL)
{
assert(bytes != NULL);
m_mi = new uint8_t[DMR_MI_LENGTH_BYTES];
m_group = (bytes[0U] & 0x20U) == 0x20U;
m_algId = bytes[0U] & 7; // Algorithm ID
m_FID = bytes[1U];
m_kId = bytes[2U];
m_mi[0U] = bytes[3U];
m_mi[1U] = bytes[4U];
m_mi[2U] = bytes[5U];
m_mi[3U] = bytes[6U];
m_dstId = bytes[7U] << 16 | bytes[8U] << 8 | bytes[9U]; // Destination Address
}
/// <summary>
/// Initializes a new instance of the PrivacyLC class.
/// </summary>
/// <param name="bits"></param>
PrivacyLC::PrivacyLC(const bool* bits) :
m_FID(FID_ETSI),
m_dstId(0U),
m_group(false),
m_algId(0U),
m_kId(0U),
m_mi(NULL)
{
assert(bits != NULL);
m_mi = new uint8_t[DMR_MI_LENGTH_BYTES];
uint8_t temp1, temp2, temp3;
Utils::bitsToByteBE(bits + 0U, temp1);
m_group = (temp1 & 0x20U) == 0x20U;
m_algId = temp1 & 7; // Algorithm ID
Utils::bitsToByteBE(bits + 8U, temp2);
m_FID = temp2;
Utils::bitsToByteBE(bits + 16U, temp3);
m_kId = temp3;
uint8_t mi1, mi2, mi3, mi4;
Utils::bitsToByteBE(bits + 24U, mi1);
Utils::bitsToByteBE(bits + 32U, mi2);
Utils::bitsToByteBE(bits + 40U, mi3);
Utils::bitsToByteBE(bits + 48U, mi4);
m_mi[0U] = mi1;
m_mi[1U] = mi2;
m_mi[2U] = mi3;
m_mi[3U] = mi4;
uint8_t d1, d2, d3;
Utils::bitsToByteBE(bits + 56U, d1);
Utils::bitsToByteBE(bits + 64U, d2);
Utils::bitsToByteBE(bits + 72U, d3);
m_dstId = d1 << 16 | d2 << 8 | d3; // Destination Address
}
/// <summary>
/// Initializes a new instance of the PrivacyLC class.
/// </summary>
PrivacyLC::PrivacyLC() :
m_FID(FID_ETSI),
m_dstId(0U),
m_group(false),
m_algId(0U),
m_kId(0U),
m_mi(NULL)
{
/* stub */
}
/// <summary>
/// Finalizes a instance of the PrivacyLC class.
/// </summary>
PrivacyLC::~PrivacyLC()
{
/* stub */
}
/// <summary>
///
/// </summary>
/// <param name="bytes"></param>
void PrivacyLC::getData(uint8_t* bytes) const
{
assert(bytes != NULL);
bytes[0U] = (m_group ? 0x20U : 0x00U) +
(m_algId & 0x07U); // Algorithm ID
bytes[1U] = m_FID;
bytes[2U] = m_kId;
bytes[3U] = m_mi[0U];
bytes[4U] = m_mi[1U];
bytes[5U] = m_mi[2U];
bytes[6U] = m_mi[3U];
bytes[7U] = m_dstId >> 16; // Destination Address
bytes[8U] = m_dstId >> 8; // ..
bytes[9U] = m_dstId >> 0; // ..
}
/// <summary>
///
/// </summary>
/// <param name="bits"></param>
void PrivacyLC::getData(bool* bits) const
{
assert(bits != NULL);
uint8_t bytes[10U];
getData(bytes);
Utils::byteToBitsBE(bytes[0U], bits + 0U);
Utils::byteToBitsBE(bytes[1U], bits + 8U);
Utils::byteToBitsBE(bytes[2U], bits + 16U);
Utils::byteToBitsBE(bytes[3U], bits + 24U);
Utils::byteToBitsBE(bytes[4U], bits + 32U);
Utils::byteToBitsBE(bytes[5U], bits + 40U);
Utils::byteToBitsBE(bytes[6U], bits + 48U);
Utils::byteToBitsBE(bytes[7U], bits + 56U);
Utils::byteToBitsBE(bytes[8U], bits + 64U);
Utils::byteToBitsBE(bytes[9U], bits + 72U);
}

@ -0,0 +1,86 @@
/**
* Digital Voice Modem - Host Software
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Host Software
*
*/
//
// Based on code from the MMDVMHost project. (https://github.com/g4klx/MMDVMHost)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
/*
* Copyright (C) 2021 Bryan Biedenkapp N2PLL <gatekeep@gmail.com>
* Copyright (C) 2020-2021 by Bryan Biedenkapp N2PLL
*
* 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.
*/
#if !defined(__DMR_LC__PRIVACY_LC_H__)
#define __DMR_LC__PRIVACY_LC_H__
#include "Defines.h"
#include "dmr/DMRDefines.h"
namespace dmr
{
namespace lc
{
// ---------------------------------------------------------------------------
// Class Declaration
// Represents DMR privacy indicator link control data.
// ---------------------------------------------------------------------------
class HOST_SW_API PrivacyLC {
public:
/// <summary>Initializes a new instance of the PrivacyLC class.</summary>
PrivacyLC(const uint8_t* bytes);
/// <summary>Initializes a new instance of the PrivacyLC class.</summary>
PrivacyLC(const bool* bits);
/// <summary>Initializes a new instance of the PrivacyLC class.</summary>
PrivacyLC();
/// <summary>Finalizes a instance of the PrivacyLC class.</summary>
~PrivacyLC();
/// <summary>Gets LC data as bytes.</summary>
void getData(uint8_t* bytes) const;
/// <summary>Gets LC data as bits.</summary>
void getData(bool* bits) const;
public:
/// <summary>Feature ID.</summayr>
__PROPERTY(uint8_t, FID, FID);
/// <summary>Destination ID.</summary>
__PROPERTY(uint32_t, dstId, DstId);
/** Service Options */
/// <summary>Flag indicating a group/talkgroup operation.</summary>
__PROPERTY(bool, group, Group);
/** Encryption data */
/// <summary>Encryption algorithm ID.</summary>
__PROPERTY(uint8_t, algId, AlgId);
/// <summary>Encryption key ID.</summary>
__PROPERTY(uint32_t, kId, KId);
private:
/** Encryption data */
uint8_t* m_mi;
};
} // namespace lc
} // namespace dmr
#endif // __DMR_LC__PRIVACY_LC_H__
Loading…
Cancel
Save

Powered by TurnKey Linux.