fix issue with RemoteCommand not properly connecting the UDP socket; fix SNDCP_CH_ANN not properly computing Rx frequency; implement TIA-102.AABF-2015 LC_CONV_FALLBACK specification;

pull/12/head
Bryan Biedenkapp 4 years ago
parent a1b0a929cc
commit ed4c7aca49

@ -64,6 +64,7 @@ using namespace modem;
#define RCD_DMR_BEACON_CMD "dmr-beacon"
#define RCD_P25_CC_CMD "p25-cc"
#define RCD_P25_CC_FALLBACK "p25-cc-fallback"
#define RCD_DMRD_MDM_INJ_CMD "dmrd-mdm-inj"
#define RCD_P25D_MDM_INJ_CMD "p25d-mdm-inj"
@ -315,6 +316,21 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25)
LogError(LOG_RCON, CMD_FAILED_STR "P25 mode is not enabled!");
}
}
else if (rcom == RCD_P25_CC_FALLBACK) {
// Command is in the form of: "p25-cc-fallback 0/1"
uint8_t fallback = getArgUInt8(args, 0U);
if (p25 != NULL) {
if (host->m_controlData) {
p25->trunk()->setConvFallback((fallback == 1U) ? true : false);
}
else {
LogError(LOG_RCON, CMD_FAILED_STR "P25 control data is not enabled!");
}
}
else {
LogError(LOG_RCON, CMD_FAILED_STR "P25 mode is not enabled!");
}
}
else if (rcom == RCD_DMRD_MDM_INJ_CMD && argCnt >= 1U) {
// Command is in the form of: "dmrd-mdm-inj <slot> <bin file>
if (dmr != NULL) {

@ -278,6 +278,7 @@ namespace p25
const uint8_t LC_ADJ_STS_BCAST = 0x22U; // ADJ STS BCAST - Adjacent Site Status Broadcast
const uint8_t LC_RFSS_STS_BCAST = 0x23U; // RFSS STS BCAST - RFSS Status Broadcast
const uint8_t LC_NET_STS_BCAST = 0x24U; // NET STS BCAST - Network Status Broadcast
const uint8_t LC_CONV_FALLBACK = 0x2AU; // CONV FALLBACK - Conventional Fallback
// TSBK ISP/OSP Shared Opcode(s)
const uint8_t TSBK_IOSP_GRP_VCH = 0x00U; // GRP VCH REQ - Group Voice Channel Request (ISP), GRP VCH GRANT - Group Voice Channel Grant (OSP)

@ -131,6 +131,7 @@ const uint32_t ADJ_SITE_UPDATE_CNT = 5U;
const uint32_t TSDU_CTRL_BURST_COUNT = 2U;
const uint32_t TSBK_MBF_CNT = 3U;
const uint32_t GRANT_TIMER_TIMEOUT = 15U;
const uint8_t CONV_FALLBACK_PACKET_DELAY = 8U;
// ---------------------------------------------------------------------------
// Public Class Members
@ -1233,6 +1234,29 @@ void TrunkPacket::writeRF_TSDU_Mot_Patch(uint32_t group1, uint32_t group2, uint3
m_rfTSBK.setMFId(P25_MFG_STANDARD);
}
/// <summary>
/// Helper to change the conventional fallback state.
/// </summary>
/// <param name="verbose">Flag indicating whether conventional fallback is enabled.</param>
void TrunkPacket::setConvFallback(bool fallback)
{
m_convFallback = fallback;
if (m_convFallback && m_p25->m_control) {
m_convFallbackPacketDelay = 0U;
uint8_t lco = m_rfTSBK.getLCO();
m_rfTSBK.setLCO(TSBK_OSP_MOT_PSH_CCH);
m_rfTSBK.setMFId(P25_MFG_MOT);
for (uint8_t i = 0U; i < 3U; i++) {
writeRF_TSDU_SBF(true);
}
m_rfTSBK.setLCO(lco);
m_rfTSBK.setMFId(P25_MFG_STANDARD);
}
}
/// <summary>
/// Helper to change the TSBK verbose state.
/// </summary>
@ -1281,6 +1305,8 @@ TrunkPacket::TrunkPacket(Control* p25, network::BaseNetwork* network, bool dumpT
m_noStatusAck(false),
m_noMessageAck(true),
m_unitToUnitAvailCheck(true),
m_convFallbackPacketDelay(0U),
m_convFallback(false),
m_adjSiteUpdateTimer(1000U),
m_adjSiteUpdateInterval(ADJ_SITE_TIMER_TIMEOUT),
m_ctrlTSDUMBF(true),
@ -1351,6 +1377,26 @@ void TrunkPacket::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS)
resetRF();
if (m_convFallback) {
bool fallbackTx = (frameCnt % 253U) == 0U;
if (fallbackTx && n == 7U) {
if (m_convFallbackPacketDelay >= CONV_FALLBACK_PACKET_DELAY) {
lc::TDULC lc = lc::TDULC(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK);
lc.setLCO(LC_CONV_FALLBACK);
for (uint8_t i = 0U; i < 3U; i++) {
writeRF_TDULC(lc, true);
}
m_convFallbackPacketDelay = 0U;
} else {
m_convFallbackPacketDelay++;
}
}
return;
}
if (m_debug) {
LogDebug(LOG_P25, "writeRF_ControlData, mbfCnt = %u, frameCnt = %u, seq = %u, adjSS = %u", m_mbfCnt, frameCnt, n, adjSS);
}

@ -107,6 +107,9 @@ namespace p25
/// <summary>Helper to write a Motorola patch packet.</summary>
void writeRF_TSDU_Mot_Patch(uint32_t group1, uint32_t group2, uint32_t group3);
/// <summary>Helper to change the conventional fallback state.</summary>
void setConvFallback(bool fallback);
/// <summary>Helper to change the TSBK verbose state.</summary>
void setTSBKVerbose(bool verbose);
@ -154,6 +157,9 @@ namespace p25
bool m_noStatusAck;
bool m_noMessageAck;
bool m_unitToUnitAvailCheck;
uint8_t m_convFallbackPacketDelay;
bool m_convFallback;
Timer m_adjSiteUpdateTimer;
uint32_t m_adjSiteUpdateInterval;

@ -446,7 +446,7 @@ void TDULC::encodeLC(uint8_t* rs)
break;
case LC_SYS_SRV_BCAST:
rs[0U] |= 0x40U; // Implicit Operation
rsValue = 0U; //
rsValue = 0U;
rsValue = (rsValue << 16) + services; // System Services Available
rsValue = (rsValue << 24) + services; // System Services Supported
break;
@ -485,13 +485,22 @@ void TDULC::encodeLC(uint8_t* rs)
break;
case LC_NET_STS_BCAST:
rs[0U] |= 0x40U; // Implicit Operation
rsValue = 0U; //
rsValue = 0U;
rsValue = (rsValue << 20) + m_siteData.netId(); // Network ID
rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID
rsValue = (rsValue << 4) + m_siteData.channelId(); // Channel ID
rsValue = (rsValue << 12) + m_siteData.channelNo(); // Channel Number
rsValue = (rsValue << 8) + m_siteData.serviceClass(); // System Service Class
break;
case LC_CONV_FALLBACK:
rsValue = 0U;
rsValue = (rsValue << 48) + m_siteData.channelId(); // Channel ID 6
rsValue = (rsValue << 40) + m_siteData.channelId(); // Channel ID 5
rsValue = (rsValue << 32) + m_siteData.channelId(); // Channel ID 4
rsValue = (rsValue << 24) + m_siteData.channelId(); // Channel ID 3
rsValue = (rsValue << 16) + m_siteData.channelId(); // Channel ID 2
rsValue = (rsValue << 8) + m_siteData.channelId(); // Channel ID 1
break;
default:
LogError(LOG_P25, "TDULC::encodeLC(), unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
break;

@ -545,7 +545,7 @@ bool TSBK::decode(const uint8_t* data, bool rawTSBK)
/// <param name="data"></param>
/// <param name="rawTSBK"></param>
/// <param name="noTrellis"></param>
void TSBK::encode(uint8_t * data, bool rawTSBK, bool noTrellis)
void TSBK::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
{
assert(data != NULL);
@ -634,6 +634,15 @@ void TSBK::encode(uint8_t * data, bool rawTSBK, bool noTrellis)
tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
break;
case TSBK_OSP_SNDCP_CH_ANN:
{
uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000;
uint32_t rxFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_siteData.channelNo())) + calcTxOffset);
uint32_t rxRootFrequency = rxFrequency - m_siteIdenEntry.baseFrequency();
uint32_t rxChannelNo = rxRootFrequency / (m_siteIdenEntry.chSpaceKhz() * 1000);
tsbkValue = 0U; //
tsbkValue = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_encrypted ? 0x40U : 0x00U); // Encrypted Flag
@ -643,9 +652,10 @@ void TSBK::encode(uint8_t * data, bool rawTSBK, bool noTrellis)
tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (T) ID
tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel (T) Number
tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (R) ID
tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel (R) Number
tsbkValue = (tsbkValue << 12) + rxChannelNo; // Channel (R) Number
tsbkValue = (tsbkValue << 16) + m_sndcpDAC; // Data Access Control
break;
}
break;
case TSBK_IOSP_U_REG:
tsbkValue = 0U;
tsbkValue = (tsbkValue << 2) + (m_response & 0x3U); // Unit Registration Response

@ -50,6 +50,11 @@ using namespace network;
#undef __EXE_NAME__
#define __EXE_NAME__ "dvmcmd"
#define ERRNO_REMOTE_CMD 99
#define ERRNO_SOCK_OPEN 98
#define ERRNO_ADDR_LOOKUP 97
#define ERRNO_FAILED_TO_SEND 96
const uint32_t START_OF_TEXT = 0x02;
const uint32_t REC_SEPARATOR = 0x1E;
@ -181,7 +186,7 @@ int main(int argc, char** argv)
if (argc < 2) {
usage("error: %s", "must specify the remote command!");
return EXIT_FAILURE;
return ERRNO_REMOTE_CMD;
}
if (argc > 1) {
@ -255,7 +260,7 @@ int CRemoteCommand::send(const std::string& command)
bool ret = socket.open();
if (!ret)
return EXIT_FAILURE;
return ERRNO_SOCK_OPEN;
uint8_t buffer[RC_BUFFER_LENGTH];
::memset(buffer, 0x00U, RC_BUFFER_LENGTH);
@ -263,11 +268,9 @@ int CRemoteCommand::send(const std::string& command)
sockaddr_storage addr;
uint32_t addrLen;
if (UDPSocket::lookup(m_address, m_port, addr, addrLen) != 0)
addrLen = 0U;
if (addrLen > 0U) {
return EXIT_FAILURE;
if (UDPSocket::lookup(m_address, m_port, addr, addrLen) != 0) {
::LogError(LOG_HOST, "Could not lookup the address of remote");
return ERRNO_ADDR_LOOKUP;
}
::LogInfoEx(LOG_HOST, "%s: sending command \"%s\" to %s:%u\r\n", g_progExe.c_str(), command.c_str(),
@ -294,11 +297,11 @@ int CRemoteCommand::send(const std::string& command)
buffer[33U] = REC_SEPARATOR;
::memcpy(buffer + 34U, command.c_str(), command.size());
ret = socket.write((uint8_t *)buffer, 34U + command.size(), addr, m_port);
ret = socket.write((uint8_t *)buffer, 34U + command.size(), addr, addrLen);
if (!ret) {
socket.close();
::LogError(LOG_HOST, "Failed to send command: \"%s\"\r\n", command.c_str());
return EXIT_FAILURE;
return ERRNO_FAILED_TO_SEND;
}
socket.close();

Loading…
Cancel
Save

Powered by TurnKey Linux.