add support for the control byte on P25 TDUs, this implements a required remote grant demand request allowing remote network applications to get a channel grant before sending traffic;

pull/39/head
Bryan Biedenkapp 3 years ago
parent 4f6fcd421b
commit ab1c84243e

@ -9,6 +9,7 @@ daemon: true
#
# Logging Configuration
#
# Logging Levels:
# 1 - Debug
# 2 - Message
@ -392,6 +393,17 @@ system:
# DMR/P25/NXDN Site ID.
siteId: 1
#
# CW ID Configuration
#
cwId:
# Flag indicating whether or not CWID is enabled.
enable: true
# Amount of time between CWID transmissions. (minutes)
time: 15
# Callsign to be transmitted.
callsign: ABCD123
#
# Modem Configuration
#
@ -525,17 +537,6 @@ system:
# Flag indicating whether or not debug logging is enabled.
debug: false
#
# CW ID Configuration
#
cwId:
# Flag indicating whether or not CWID is enabled.
enable: true
# Amount of time between CWID transmissions. (minutes)
time: 15
# Callsign to be transmitted.
callsign: ABCD123
#
# Channel Identity Table Configuration
#

@ -645,6 +645,8 @@ UInt8Array BaseNetwork::createDMR_Message(uint32_t& length, const uint32_t strea
uint32_t slotNo = data.getSlotNo();
buffer[14U] = 0U; // Control Bits
// Individual slot disabling
if (slotNo == 1U && !m_slot1)
return nullptr;
@ -685,52 +687,54 @@ UInt8Array BaseNetwork::createDMR_Message(uint32_t& length, const uint32_t strea
/// <summary>
/// Creates an P25 frame message header.
/// </summary>
/// <param name="data"></param>
/// <param name="buffer"></param>
/// <param name="duid"></param>
/// <param name="control"></param>
/// <param name="lsd"></param>
/// <param name="frameType"></param>
void BaseNetwork::createP25_MessageHdr(uint8_t* data, uint8_t duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
void BaseNetwork::createP25_MessageHdr(uint8_t* buffer, uint8_t duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
uint8_t frameType)
{
assert(data != nullptr);
assert(buffer != nullptr);
// construct P25 message header
::memcpy(data + 0U, TAG_P25_DATA, 4U);
::memcpy(buffer + 0U, TAG_P25_DATA, 4U);
data[4U] = control.getLCO(); // LCO
buffer[4U] = control.getLCO(); // LCO
uint32_t srcId = control.getSrcId(); // Source Address
__SET_UINT16(srcId, data, 5U);
__SET_UINT16(srcId, buffer, 5U);
uint32_t dstId = control.getDstId(); // Target Address
__SET_UINT16(dstId, data, 8U);
__SET_UINT16(dstId, buffer, 8U);
uint16_t sysId = control.getSiteData().sysId(); // System ID
data[11U] = (sysId >> 8) & 0xFFU;
data[12U] = (sysId >> 0) & 0xFFU;
buffer[11U] = (sysId >> 8) & 0xFFU;
buffer[12U] = (sysId >> 0) & 0xFFU;
data[15U] = control.getMFId(); // MFId
buffer[14U] = 0U; // Control Bits
buffer[15U] = control.getMFId(); // MFId
uint32_t netId = control.getSiteData().netId(); // Network ID
__SET_UINT16(netId, data, 16U);
__SET_UINT16(netId, buffer, 16U);
data[20U] = lsd.getLSD1(); // LSD 1
data[21U] = lsd.getLSD2(); // LSD 2
buffer[20U] = lsd.getLSD1(); // LSD 1
buffer[21U] = lsd.getLSD2(); // LSD 2
data[22U] = duid; // DUID
buffer[22U] = duid; // DUID
if (frameType != p25::P25_FT_TERMINATOR) {
data[180U] = frameType; // DVM Frame Type
buffer[180U] = frameType; // DVM Frame Type
}
// is this the first frame of a call?
if (frameType == p25::P25_FT_HDU_VALID) {
data[181U] = control.getAlgId(); // Algorithm ID
buffer[181U] = control.getAlgId(); // Algorithm ID
uint32_t kid = control.getKId();
data[182U] = (kid >> 8) & 0xFFU; // Key ID
data[183U] = (kid >> 0) & 0xFFU;
buffer[182U] = (kid >> 8) & 0xFFU; // Key ID
buffer[183U] = (kid >> 0) & 0xFFU;
// copy MI data
uint8_t mi[p25::P25_MI_LENGTH_BYTES];
@ -742,7 +746,7 @@ void BaseNetwork::createP25_MessageHdr(uint8_t* data, uint8_t duid, const p25::l
}
for (uint8_t i = 0; i < p25::P25_MI_LENGTH_BYTES; i++) {
data[184U + i] = mi[i]; // Message Indicator
buffer[184U + i] = mi[i]; // Message Indicator
}
}
}
@ -1043,6 +1047,8 @@ UInt8Array BaseNetwork::createNXDN_Message(uint32_t& length, const nxdn::lc::RTC
uint32_t dstId = lc.getDstId(); // Target Address
__SET_UINT16(dstId, buffer, 8U);
buffer[14U] = 0U; // Control Bits
buffer[15U] |= lc.getGroup() ? 0x00U : 0x40U; // Group
// pack raw NXDN message bytes

@ -275,7 +275,7 @@ namespace network
UInt8Array createDMR_Message(uint32_t& length, const uint32_t streamId, const dmr::data::Data& data);
/// <summary>Creates an P25 frame message header.</summary>
void createP25_MessageHdr(uint8_t* data, uint8_t duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
void createP25_MessageHdr(uint8_t* buffer, uint8_t duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
uint8_t frameType = p25::P25_FT_DATA_UNIT);
/// <summary>Creates an P25 LDU1 frame message.</summary>

@ -1077,6 +1077,8 @@ void Control::processNetwork()
return;
}
bool grantDemand = (buffer[14U] & 0x80U) == 0x80U;
// process network message header
uint8_t duid = buffer[22U];
uint8_t MFId = buffer[15U];
@ -1218,11 +1220,30 @@ void Control::processNetwork()
}
break;
}
ret = m_voice->processNetwork(data.get(), frameLength, control, lsd, duid, frameType);
if (m_dedicatedControl && m_voiceOnControl) {
ret = m_voice->processNetwork(data.get(), frameLength, control, lsd, duid, frameType);
}
break;
case P25_DUID_TDU:
case P25_DUID_TDULC:
// is this an TDU with a grant demand?
if (duid == P25_DUID_TDU && grantDemand) {
uint8_t serviceOptions = (control.getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
(control.getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
(control.getPriority() & 0x07U); // Priority
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR " remote grant demand, srcId = %u, dstId = %u", srcId, dstId);
}
if (!m_trunk->writeRF_TSDU_Grant(srcId, dstId, serviceOptions, true, true)) {
LogError(LOG_NET, P25_TSDU_STR " call failure, network call not granted, dstId = %u", dstId);
return;
}
}
m_voice->processNetwork(data.get(), frameLength, control, lsd, duid, frameType);
break;

Loading…
Cancel
Save

Powered by TurnKey Linux.