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. # Flag indicating whether or not the host will acknowledge message packets.
noMessageAck: true noMessageAck: true
# Flag indicating that unit-to-unit availiability checks should be performed for a private call. # 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. # Flag indicating explicit source ID support is enabled.
allowExplicitSourceId: true allowExplicitSourceId: true
# Flag indicating whether or not the host will respond to SNDCP data grant requests. # 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> /// <returns>True, if data is added to ring buffer, otherwise false.</returns>
bool addData(const T* buffer, uint32_t length) bool addData(const T* buffer, uint32_t length)
{ {
if (length >= freeSpace()) { if (length > freeSpace()) {
LogError(LOG_HOST, "**** Overflow in %s ring buffer, %u >= %u, clearing the buffer", m_name, length, freeSpace()); LogError(LOG_HOST, "**** Overflow in %s ring buffer, %u > %u, clearing the buffer", m_name, length, freeSpace());
clear(); clear();
return false; return false;
} }

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

@ -49,9 +49,9 @@ namespace dmr
virtual ~DMRAffiliationLookup(); virtual ~DMRAffiliationLookup();
/// <summary>Helper to grant a channel.</summary> /// <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> /// <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> /// <summary>Helper to release the channel grant for the destination ID.</summary>
bool releaseGrant(uint32_t dstId, bool releaseAll) override; bool releaseGrant(uint32_t dstId, bool releaseAll) override;
/// <summary>Helper to determine if the channel number is busy.</summary> /// <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 { 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); chNo = m_tscc->m_affiliations->getGrantedCh(dstId);
slot = m_tscc->m_affiliations->getGrantedSlot(dstId); slot = m_tscc->m_affiliations->getGrantedSlot(dstId);
//m_tscc->m_siteData.setChCnt(m_tscc->m_affiliations->getRFChCnt() + m_tscc->m_affiliations->getGrantedRFChCnt()); //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 { 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); chNo = m_tscc->m_affiliations->getGrantedCh(dstId);
slot = m_tscc->m_affiliations->getGrantedSlot(dstId); slot = m_tscc->m_affiliations->getGrantedSlot(dstId);

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

@ -146,7 +146,7 @@ namespace lookups
/// <summary>Gets the grant table.</summary> /// <summary>Gets the grant table.</summary>
std::unordered_map<uint32_t, uint32_t> grantTable() const { return m_grantChTable; } std::unordered_map<uint32_t, uint32_t> grantTable() const { return m_grantChTable; }
/// <summary>Helper to grant a channel.</summary> /// <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> /// <summary>Helper to start the destination ID grant timer.</summary>
virtual void touchGrant(uint32_t dstId); virtual void touchGrant(uint32_t dstId);
/// <summary>Helper to release the channel grant for the destination ID.</summary> /// <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; virtual bool isChBusy(uint32_t chNo) const;
/// <summary>Helper to determine if the destination ID is already granted.</summary> /// <summary>Helper to determine if the destination ID is already granted.</summary>
virtual bool isGranted(uint32_t dstId) const; 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> /// <summary>Helper to determine if the destination ID is granted by network traffic.</summary>
virtual bool isNetGranted(uint32_t dstId) const; virtual bool isNetGranted(uint32_t dstId) const;
/// <summary>Helper to get the channel granted for the given destination ID.</summary> /// <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_grantChTable;
std::unordered_map<uint32_t, uint32_t> m_grantSrcIdTable; 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, bool> m_netGrantedTable;
std::unordered_map<uint32_t, Timer> m_grantTimers; 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 { 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); 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_TSBK_RAW.h"
#include "p25/lc/tsbk/OSP_U_DEREG_ACK.h" #include "p25/lc/tsbk/OSP_U_DEREG_ACK.h"
#include "p25/lc/tsbk/OSP_U_REG_CMD.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/AMBT.h"
#include "p25/lc/tsbk/MBT_IOSP_ACK_RSP.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 (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) { if (m_p25->m_authoritative) {
uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
(tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted 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) { 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_ANS);
writeRF_TSDU_Deny(P25_WUID_FNE, dstId, P25_DENY_RSN_TGT_UNIT_REFUSED, TSBK_IOSP_UU_VCH);
} }
else if (iosp->getResponse() == P25_ANS_RSP_WAIT) { 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_ANS, false, false);
writeRF_TSDU_Queue(P25_WUID_FNE, dstId, P25_QUE_RSN_TGT_UNIT_QUEUED, TSBK_IOSP_UU_VCH, false, false);
} }
} }
break; break;
@ -2262,7 +2256,7 @@ bool ControlSignaling::writeRF_TSDU_Grant(uint32_t srcId, uint32_t dstId, uint8_
} }
} }
else { 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); chNo = m_p25->m_affiliations.getGrantedCh(dstId);
m_p25->m_siteData.setChCnt(m_p25->m_affiliations.getRFChCnt() + m_p25->m_affiliations.getGrantedRFChCnt()); 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()) if (m_mbfGrpGrntCnt >= m_p25->m_affiliations.grantSize())
m_mbfGrpGrntCnt = 0U; m_mbfGrpGrntCnt = 0U;
std::unique_ptr<OSP_GRP_VCH_GRANT_UPD> osp = new_unique(OSP_GRP_VCH_GRANT_UPD); std::unique_ptr<lc::TSBK> osp;
DEBUG_LOG_TSBK(osp->toString());
bool noData = false; bool noData = false;
uint8_t i = 0U; uint8_t i = 0U;
@ -2444,6 +2437,7 @@ void ControlSignaling::writeRF_TSDU_Grant_Update()
else { else {
uint32_t dstId = entry.first; uint32_t dstId = entry.first;
uint32_t chNo = entry.second; uint32_t chNo = entry.second;
bool grp = m_p25->m_affiliations.isGroup(dstId);
::lookups::VoiceChData voiceChData = m_p25->m_affiliations.getRFChData(chNo); ::lookups::VoiceChData voiceChData = m_p25->m_affiliations.getRFChData(chNo);
@ -2453,14 +2447,34 @@ void ControlSignaling::writeRF_TSDU_Grant_Update()
break; break;
} }
else { else {
// transmit group voice grant update if (grp) {
osp->setLCO(TSBK_OSP_GRP_VCH_GRANT_UPD); osp = new_unique(OSP_GRP_VCH_GRANT_UPD);
osp->setDstId(dstId); DEBUG_LOG_TSBK(osp->toString());
osp->setGrpVchId(voiceChData.chId());
osp->setGrpVchNo(chNo);
m_mbfGrpGrntCnt++; // transmit group voice grant update
break; 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; return false;
} }
else { 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); uint32_t chNo = m_p25->m_affiliations.getGrantedCh(srcId);
::lookups::VoiceChData voiceChData = m_p25->m_affiliations.getRFChData(chNo); ::lookups::VoiceChData voiceChData = m_p25->m_affiliations.getRFChData(chNo);

Loading…
Cancel
Save

Powered by TurnKey Linux.