implement partial fix for trunked UU calls (calls can be made now, but operation is still glitchy);

pull/42/head
Bryan Biedenkapp 2 years ago
parent 26981f1345
commit 685ea4df14

@ -215,7 +215,7 @@ protocols:
# Flag indicating whether or not the host will acknowledge message packets.
noMessageAck: true
# Flag indicating that unit-to-unit availiability checks should be performed for a private call.
unitToUnitAvailCheck: true
unitToUnitAvailCheck: false
# Flag indicating explicit source ID support is enabled.
allowExplicitSourceId: true
# Flag indicating whether or not the host will respond to SNDCP data grant requests.

@ -75,8 +75,8 @@ public:
/// <returns>True, if data is added to ring buffer, otherwise false.</returns>
bool addData(const T* buffer, uint32_t length)
{
if (length >= freeSpace()) {
LogError(LOG_HOST, "**** Overflow in %s ring buffer, %u >= %u, clearing the buffer", m_name, length, freeSpace());
if (length > freeSpace()) {
LogError(LOG_HOST, "**** Overflow in %s ring buffer, %u > %u, clearing the buffer", m_name, length, freeSpace());
clear();
return false;
}

@ -63,9 +63,10 @@ DMRAffiliationLookup::~DMRAffiliationLookup()
/// <param name="dstId"></param>
/// <param name="srcId"></param>
/// <param name="grantTimeout"></param>
/// <param name="grp"></param>
/// <param name="netGranted"></param>
/// <returns></returns>
bool DMRAffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout, bool netGranted)
bool DMRAffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout, bool grp, bool netGranted)
{
uint32_t chNo = m_rfChTable.at(0);
uint8_t slot = getAvailableSlotForChannel(chNo);
@ -74,7 +75,7 @@ bool DMRAffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t gran
return false;
}
return grantChSlot(dstId, srcId, slot, grantTimeout, netGranted);
return grantChSlot(dstId, srcId, slot, grantTimeout, grp, netGranted);
}
/// <summary>
@ -84,9 +85,10 @@ bool DMRAffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t gran
/// <param name="srcId"></param>
/// <param name="slot"></param>
/// <param name="grantTimeout"></param>
/// <param name="grp"></param>
/// <param name="netGranted"></param>
/// <returns></returns>
bool DMRAffiliationLookup::grantChSlot(uint32_t dstId, uint32_t srcId, uint8_t slot, uint32_t grantTimeout, bool netGranted)
bool DMRAffiliationLookup::grantChSlot(uint32_t dstId, uint32_t srcId, uint8_t slot, uint32_t grantTimeout, bool grp, bool netGranted)
{
if (dstId == 0U) {
return false;
@ -111,14 +113,15 @@ bool DMRAffiliationLookup::grantChSlot(uint32_t dstId, uint32_t srcId, uint8_t s
m_grantChSlotTable[dstId] = std::make_tuple(chNo, slot);
m_rfGrantChCnt++;
m_uuGrantedTable[dstId] = !grp;
m_netGrantedTable[dstId] = netGranted;
m_grantTimers[dstId] = Timer(1000U, grantTimeout);
m_grantTimers[dstId].start();
if (m_verbose) {
LogMessage(LOG_HOST, "%s, granting channel, chNo = %u, slot = %u, dstId = %u",
m_name, chNo, slot, dstId);
LogMessage(LOG_HOST, "%s, granting channel, chNo = %u, slot = %u, dstId = %u, group = %u",
m_name, chNo, slot, dstId, grp);
}
return true;

@ -49,9 +49,9 @@ namespace dmr
virtual ~DMRAffiliationLookup();
/// <summary>Helper to grant a channel.</summary>
bool grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout, bool netGranted) override;
bool grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout, bool grp, bool netGranted) override;
/// <summary>Helper to grant a channel and slot.</summary>
bool grantChSlot(uint32_t dstId, uint32_t srcId, uint8_t slot, uint32_t grantTimeout, bool netGranted);
bool grantChSlot(uint32_t dstId, uint32_t srcId, uint8_t slot, uint32_t grantTimeout, bool grp, bool netGranted);
/// <summary>Helper to release the channel grant for the destination ID.</summary>
bool releaseGrant(uint32_t dstId, bool releaseAll) override;
/// <summary>Helper to determine if the channel number is busy.</summary>

@ -860,7 +860,7 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_
}
}
else {
if (m_tscc->m_affiliations->grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, net)) {
if (m_tscc->m_affiliations->grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, grp, net)) {
chNo = m_tscc->m_affiliations->getGrantedCh(dstId);
slot = m_tscc->m_affiliations->getGrantedSlot(dstId);
//m_tscc->m_siteData.setChCnt(m_tscc->m_affiliations->getRFChCnt() + m_tscc->m_affiliations->getGrantedRFChCnt());
@ -1149,7 +1149,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u
}
}
else {
if (m_tscc->m_affiliations->grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, net)) {
if (m_tscc->m_affiliations->grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, grp, net)) {
chNo = m_tscc->m_affiliations->getGrantedCh(dstId);
slot = m_tscc->m_affiliations->getGrantedSlot(dstId);

@ -50,6 +50,7 @@ AffiliationLookup::AffiliationLookup(const char* name, bool verbose) :
m_grpAffTable(),
m_grantChTable(),
m_grantSrcIdTable(),
m_uuGrantedTable(),
m_netGrantedTable(),
m_grantTimers(),
m_releaseGrant(nullptr),
@ -246,9 +247,10 @@ std::vector<uint32_t> AffiliationLookup::clearGroupAff(uint32_t dstId, bool rele
/// <param name="dstId"></param>
/// <param name="srcId"></param>
/// <param name="grantTimeout"></param>
/// <param name="grp"></param>
/// <param name="netGranted"></param>
/// <returns></returns>
bool AffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout, bool netGranted)
bool AffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout, bool grp, bool netGranted)
{
if (dstId == 0U) {
return false;
@ -266,14 +268,15 @@ bool AffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTi
m_grantSrcIdTable[dstId] = srcId;
m_rfGrantChCnt++;
m_uuGrantedTable[dstId] = !grp;
m_netGrantedTable[dstId] = netGranted;
m_grantTimers[dstId] = Timer(1000U, grantTimeout);
m_grantTimers[dstId].start();
if (m_verbose) {
LogMessage(LOG_HOST, "%s, granting channel, chNo = %u, dstId = %u, srcId = %u",
m_name, chNo, dstId, srcId);
LogMessage(LOG_HOST, "%s, granting channel, chNo = %u, dstId = %u, srcId = %u, group = %u",
m_name, chNo, dstId, srcId, grp);
}
return true;
@ -338,6 +341,7 @@ bool AffiliationLookup::releaseGrant(uint32_t dstId, bool releaseAll)
m_grantChTable.erase(dstId);
m_grantSrcIdTable.erase(dstId);
m_uuGrantedTable.erase(dstId);
m_netGrantedTable.erase(dstId);
m_rfChTable.push_back(chNo);
@ -401,6 +405,26 @@ bool AffiliationLookup::isGranted(uint32_t dstId) const
}
}
/// <summary>
/// Helper to determine if the destination ID is network granted.
/// </summary>
/// <param name="dstId"></param>
/// <returns></returns>
bool AffiliationLookup::isGroup(uint32_t dstId) const
{
if (dstId == 0U) {
return true;
}
// lookup dynamic channel grant table entry
try {
bool uu = m_uuGrantedTable.at(dstId);
return !uu;
} catch (...) {
return true;
}
}
/// <summary>
/// Helper to determine if the destination ID is network granted.
/// </summary>

@ -146,7 +146,7 @@ namespace lookups
/// <summary>Gets the grant table.</summary>
std::unordered_map<uint32_t, uint32_t> grantTable() const { return m_grantChTable; }
/// <summary>Helper to grant a channel.</summary>
virtual bool grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout, bool netGranted);
virtual bool grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout, bool grp, bool netGranted);
/// <summary>Helper to start the destination ID grant timer.</summary>
virtual void touchGrant(uint32_t dstId);
/// <summary>Helper to release the channel grant for the destination ID.</summary>
@ -155,6 +155,8 @@ namespace lookups
virtual bool isChBusy(uint32_t chNo) const;
/// <summary>Helper to determine if the destination ID is already granted.</summary>
virtual bool isGranted(uint32_t dstId) const;
/// <summary>Helper to determine if the destination ID granted is a group or not.</summary>
virtual bool isGroup(uint32_t dstId) const;
/// <summary>Helper to determine if the destination ID is granted by network traffic.</summary>
virtual bool isNetGranted(uint32_t dstId) const;
/// <summary>Helper to get the channel granted for the given destination ID.</summary>
@ -194,6 +196,7 @@ namespace lookups
std::unordered_map<uint32_t, uint32_t> m_grantChTable;
std::unordered_map<uint32_t, uint32_t> m_grantSrcIdTable;
std::unordered_map<uint32_t, bool> m_uuGrantedTable;
std::unordered_map<uint32_t, bool> m_netGrantedTable;
std::unordered_map<uint32_t, Timer> m_grantTimers;

@ -563,7 +563,7 @@ bool ControlSignaling::writeRF_Message_Grant(uint32_t srcId, uint32_t dstId, uin
}
}
else {
if (m_nxdn->m_affiliations.grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, net)) {
if (m_nxdn->m_affiliations.grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, grp, net)) {
chNo = m_nxdn->m_affiliations.getGrantedCh(dstId);
}
}

@ -0,0 +1,99 @@
/**
* 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
*
*/
/*
* Copyright (C) 2023 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 "p25/lc/tsbk/OSP_UU_VCH_GRANT_UPD.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc::tsbk;
using namespace p25::lc;
using namespace p25;
#include <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the OSP_UU_VCH_GRANT_UPD class.
/// </summary>
OSP_UU_VCH_GRANT_UPD::OSP_UU_VCH_GRANT_UPD() : TSBK()
{
m_lco = TSBK_OSP_UU_VCH_GRANT_UPD;
}
/// <summary>
/// Decode a trunking signalling block.
/// </summary>
/// <param name="data"></param>
/// <param name="rawTSBK"></param>
/// <returns>True, if TSBK was decoded, otherwise false.</returns>
bool OSP_UU_VCH_GRANT_UPD::decode(const uint8_t* data, bool rawTSBK)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a trunking signalling block.
/// </summary>
/// <param name="data"></param>
/// <param name="rawTSBK"></param>
/// <param name="noTrellis"></param>
void OSP_UU_VCH_GRANT_UPD::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
{
assert(data != NULL);
ulong64_t tsbkValue = 0U;
if (m_grpVchId != 0U) {
tsbkValue = m_grpVchId; // Channel ID
}
else {
tsbkValue = m_siteData.channelId(); // Channel ID
}
tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number
tsbkValue = (tsbkValue << 24) + m_dstId; // Target Address
tsbkValue = (tsbkValue << 24) + m_srcId; // Source Address
std::unique_ptr<uint8_t[]> tsbk = TSBK::fromValue(tsbkValue);
TSBK::encode(data, tsbk.get(), rawTSBK, noTrellis);
}
/// <summary>
/// Returns a string that represents the current TSBK.
/// </summary>
/// <param name="isp"></param>
/// <returns></returns>
std::string OSP_UU_VCH_GRANT_UPD::toString(bool isp)
{
return std::string("TSBK_OSP_UU_VCH_GRANT_UPD (Unit-to-Unit Voice Channel Grant Update)");
}

@ -0,0 +1,60 @@
/**
* 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
*
*/
/*
* Copyright (C) 2023 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(__P25_LC_TSBK__OSP_UU_VCH_GRANT_UPD_H__)
#define __P25_LC_TSBK__OSP_UU_VCH_GRANT_UPD_H__
#include "Defines.h"
#include "p25/lc/TSBK.h"
namespace p25
{
namespace lc
{
namespace tsbk
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements UU VCH GRANT UPD - Unit-to-Unit Voice Channel Grant Update.
// ---------------------------------------------------------------------------
class HOST_SW_API OSP_UU_VCH_GRANT_UPD : public TSBK {
public:
/// <summary>Initializes a new instance of the OSP_UU_VCH_GRANT_UPD class.</summary>
OSP_UU_VCH_GRANT_UPD();
/// <summary>Decode a trunking signalling block.</summary>
bool decode(const uint8_t* data, bool rawTSBK = false);
/// <summary>Encode a trunking signalling block.</summary>
void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
/// <summary>Returns a string that represents the current TSBK.</summary>
virtual std::string toString(bool isp = false) override;
};
} // namespace tsbk
} // namespace lc
} // namespace p25
#endif // __P25_LC_TSBK__OSP_UU_VCH_GRANT_UPD_H__

@ -80,6 +80,7 @@
#include "p25/lc/tsbk/OSP_TSBK_RAW.h"
#include "p25/lc/tsbk/OSP_U_DEREG_ACK.h"
#include "p25/lc/tsbk/OSP_U_REG_CMD.h"
#include "p25/lc/tsbk/OSP_UU_VCH_GRANT_UPD.h"
#include "p25/lc/AMBT.h"
#include "p25/lc/tsbk/MBT_IOSP_ACK_RSP.h"

@ -310,10 +310,6 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len, std::unique_ptr<lc::
}
if (iosp->getResponse() == P25_ANS_RSP_PROCEED) {
if (m_p25->m_ackTSBKRequests) {
writeRF_TSDU_ACK_FNE(dstId, TSBK_IOSP_UU_VCH, false, true);
}
if (m_p25->m_authoritative) {
uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
(tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
@ -325,12 +321,10 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len, std::unique_ptr<lc::
}
}
else if (iosp->getResponse() == P25_ANS_RSP_DENY) {
writeRF_TSDU_ACK_FNE(dstId, TSBK_IOSP_UU_VCH, false, true);
writeRF_TSDU_Deny(P25_WUID_FNE, dstId, P25_DENY_RSN_TGT_UNIT_REFUSED, TSBK_IOSP_UU_VCH);
writeRF_TSDU_Deny(P25_WUID_FNE, dstId, P25_DENY_RSN_TGT_UNIT_REFUSED, TSBK_IOSP_UU_ANS);
}
else if (iosp->getResponse() == P25_ANS_RSP_WAIT) {
writeRF_TSDU_ACK_FNE(dstId, TSBK_IOSP_UU_VCH, false, true);
writeRF_TSDU_Queue(P25_WUID_FNE, dstId, P25_QUE_RSN_TGT_UNIT_QUEUED, TSBK_IOSP_UU_VCH, false, false);
writeRF_TSDU_Queue(P25_WUID_FNE, dstId, P25_QUE_RSN_TGT_UNIT_QUEUED, TSBK_IOSP_UU_ANS, false, false);
}
}
break;
@ -2262,7 +2256,7 @@ bool ControlSignaling::writeRF_TSDU_Grant(uint32_t srcId, uint32_t dstId, uint8_
}
}
else {
if (m_p25->m_affiliations.grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, net)) {
if (m_p25->m_affiliations.grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, grp, net)) {
chNo = m_p25->m_affiliations.getGrantedCh(dstId);
m_p25->m_siteData.setChCnt(m_p25->m_affiliations.getRFChCnt() + m_p25->m_affiliations.getGrantedRFChCnt());
}
@ -2429,8 +2423,7 @@ void ControlSignaling::writeRF_TSDU_Grant_Update()
if (m_mbfGrpGrntCnt >= m_p25->m_affiliations.grantSize())
m_mbfGrpGrntCnt = 0U;
std::unique_ptr<OSP_GRP_VCH_GRANT_UPD> osp = new_unique(OSP_GRP_VCH_GRANT_UPD);
DEBUG_LOG_TSBK(osp->toString());
std::unique_ptr<lc::TSBK> osp;
bool noData = false;
uint8_t i = 0U;
@ -2444,6 +2437,7 @@ void ControlSignaling::writeRF_TSDU_Grant_Update()
else {
uint32_t dstId = entry.first;
uint32_t chNo = entry.second;
bool grp = m_p25->m_affiliations.isGroup(dstId);
::lookups::VoiceChData voiceChData = m_p25->m_affiliations.getRFChData(chNo);
@ -2453,14 +2447,34 @@ void ControlSignaling::writeRF_TSDU_Grant_Update()
break;
}
else {
// transmit group voice grant update
osp->setLCO(TSBK_OSP_GRP_VCH_GRANT_UPD);
osp->setDstId(dstId);
osp->setGrpVchId(voiceChData.chId());
osp->setGrpVchNo(chNo);
if (grp) {
osp = new_unique(OSP_GRP_VCH_GRANT_UPD);
DEBUG_LOG_TSBK(osp->toString());
m_mbfGrpGrntCnt++;
break;
// transmit group voice grant update
osp->setLCO(TSBK_OSP_GRP_VCH_GRANT_UPD);
osp->setDstId(dstId);
osp->setGrpVchId(voiceChData.chId());
osp->setGrpVchNo(chNo);
m_mbfGrpGrntCnt++;
break;
} else {
uint32_t srcId = m_p25->m_affiliations.getGrantedSrcId(dstId);
osp = new_unique(OSP_UU_VCH_GRANT_UPD);
DEBUG_LOG_TSBK(osp->toString());
// transmit group voice grant update
osp->setLCO(TSBK_OSP_UU_VCH_GRANT_UPD);
osp->setSrcId(srcId);
osp->setDstId(dstId);
osp->setGrpVchId(voiceChData.chId());
osp->setGrpVchNo(chNo);
m_mbfGrpGrntCnt++;
break;
}
}
}
}
@ -2522,7 +2536,7 @@ bool ControlSignaling::writeRF_TSDU_SNDCP_Grant(uint32_t srcId, uint32_t dstId,
return false;
}
else {
if (m_p25->m_affiliations.grantCh(srcId, srcId, GRANT_TIMER_TIMEOUT, net)) {
if (m_p25->m_affiliations.grantCh(srcId, srcId, GRANT_TIMER_TIMEOUT, false, net)) {
uint32_t chNo = m_p25->m_affiliations.getGrantedCh(srcId);
::lookups::VoiceChData voiceChData = m_p25->m_affiliations.getRFChData(chNo);

Loading…
Cancel
Save

Powered by TurnKey Linux.