start plumbing for Harris RF OTA User Alias (this is not wired yet...);

pull/128/head
Bryan Biedenkapp 1 month ago
parent cb5429da93
commit fb6a8089ea

@ -782,19 +782,19 @@ namespace p25
// LDUx/TDULC Motorola Link Control Opcode(s)
FAILSOFT = 0x02U, //!< FAILSOFT - Failsoft
MOT_PTT_LOC_HEADER = 0x29U, //!< MOT PTT LOC HEADER - Motorola PTT Location Header
MOT_PTT_LOC_PAYLOAD = 0x2AU, //!< MOT PTT LOC PAYLOAD - Motorola PTT Location Payload
MOT_PTT_LOC_HEADER = 0x29U, //!< MOT PTT LOC HEADER - Motorola PTT Location Header
MOT_PTT_LOC_PAYLOAD = 0x2AU, //!< MOT PTT LOC PAYLOAD - Motorola PTT Location Payload
// LDUx/TDULC Harris Link Control Opcode(s)
HARRIS_PTT_PA_ODD = 0x2AU, //!< HARRIS PTT PA ODD - Harris PTT Position and Altitude Odd
HARRIS_PTT_PB_ODD = 0x2BU, //!< HARRIS PTT PB ODD - Harris PTT Position and Bearing Odd
HARRIS_PTT_PA_EVEN = 0x2CU, //!< HARRIS PTT PA EVEN - Harris PTT Position and Altitude Even
HARRIS_PTT_PB_EVEN = 0x2DU, //!< HARRIS PTT PB EVEN - Harris PTT Position and Bearing Even
HARRIS_USER_ALIAS_PA_ODD = 0x32U, //!< HARRIS USER ALIAS PA ODD - Harris User Alias Position and Altitude Odd
HARRIS_USER_ALIAS_PB_ODD = 0x33U, //!< HARRIS USER ALIAS PB ODD - Harris User Alias Position and Bearing Odd
HARRIS_USER_ALIAS_PA_EVEN = 0x34U, //!< HARRIS USER ALIAS PA EVEN - Harris User Alias Position and Altitude Even
HARRIS_USER_ALIAS_PB_EVEN = 0x35U, //!< HARRIS USER ALIAS PB EVEN - Harris User Alias Position and Bearing Even
HARRIS_PTT_A_ODD = 0x2AU, //!< HARRIS PTT PA ODD - Harris PTT Position and Altitude Odd
HARRIS_PTT_B_ODD = 0x2BU, //!< HARRIS PTT PB ODD - Harris PTT Position and Bearing Odd
HARRIS_PTT_A_EVEN = 0x2CU, //!< HARRIS PTT PA EVEN - Harris PTT Position and Altitude Even
HARRIS_PTT_B_EVEN = 0x2DU, //!< HARRIS PTT PB EVEN - Harris PTT Position and Bearing Even
HARRIS_USER_ALIAS_A_ODD = 0x32U, //!< U_ALIAS_A_ODD - User Alias Part A, odd-numbered conveyance
HARRIS_USER_ALIAS_B_ODD = 0x33U, //!< U_ALIAS_B_ODD - User Alias Part B, odd-numbered conveyance
HARRIS_USER_ALIAS_A_EVEN = 0x34U, //!< U_ALIAS_A_EVEN - User Alias Part A, even-numbered conveyance
HARRIS_USER_ALIAS_B_EVEN = 0x35U, //!< U_ALIAS_B_EVEN - User Alias Part B, even-numbered conveyance
};
}

@ -25,6 +25,7 @@ using namespace p25::lc;
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <cstring>
// ---------------------------------------------------------------------------
@ -1056,20 +1057,19 @@ bool LC::decodeLC(const uint8_t* rs, bool rawOnly)
if (m_mfId == MFG_HARRIS) {
// Harris P25 opcodes
switch (m_lco) {
case LCO::HARRIS_USER_ALIAS_PA_ODD:
case LCO::HARRIS_USER_ALIAS_PA_EVEN:
case LCO::HARRIS_USER_ALIAS_A_ODD:
case LCO::HARRIS_USER_ALIAS_A_EVEN:
m_gotUserAliasPartA = true;
m_gotUserAlias = false;
if (m_userAlias != nullptr) {
::memset(m_userAlias, 0x00U, HARRIS_USER_ALIAS_LENGTH_BYTES);
::memcpy(m_userAlias, rs + 2U, 7U);
m_gotUserAlias = true;
}
break;
case LCO::HARRIS_USER_ALIAS_PB_ODD:
case LCO::HARRIS_USER_ALIAS_PB_EVEN:
case LCO::HARRIS_USER_ALIAS_B_ODD:
case LCO::HARRIS_USER_ALIAS_B_EVEN:
if (m_gotUserAliasPartA && (m_userAlias != nullptr)) {
::memcpy(m_userAlias + 7U, rs + 2U, 7U);
m_gotUserAlias = true;
@ -1166,8 +1166,8 @@ void LC::encodeLC(uint8_t* rs)
if (m_mfId == MFG_HARRIS) {
// Harris P25 opcodes
switch (m_lco) {
case LCO::HARRIS_USER_ALIAS_PA_ODD:
case LCO::HARRIS_USER_ALIAS_PA_EVEN:
case LCO::HARRIS_USER_ALIAS_A_ODD:
case LCO::HARRIS_USER_ALIAS_A_EVEN:
if (m_userAlias != nullptr) {
// split ulong64_t (8 byte) value into bytes
rs[1U] = m_mfId; // Manufacturer ID
@ -1181,8 +1181,8 @@ void LC::encodeLC(uint8_t* rs)
}
return;
case LCO::HARRIS_USER_ALIAS_PB_ODD:
case LCO::HARRIS_USER_ALIAS_PB_EVEN:
case LCO::HARRIS_USER_ALIAS_B_ODD:
case LCO::HARRIS_USER_ALIAS_B_EVEN:
if (m_userAlias != nullptr) {
// split ulong64_t (8 byte) value into bytes
rs[1U] = m_mfId; // Manufacturer ID
@ -1555,11 +1555,12 @@ void LC::getMI(uint8_t* mi) const
std::string LC::getUserAlias() const
{
std::string alias;
if (m_gotUserAlias) {
for (uint32_t i = 0; i < HARRIS_USER_ALIAS_LENGTH_BYTES; i++)
alias[i] = m_userAlias[i];
}
if (!m_gotUserAlias || m_userAlias == nullptr)
return std::string();
std::string alias(reinterpret_cast<const char*>(m_userAlias), HARRIS_USER_ALIAS_LENGTH_BYTES);
while (!alias.empty() && (alias.back() == '\0' || alias.back() == ' '))
alias.pop_back();
return alias;
}
@ -1572,8 +1573,10 @@ void LC::setUserAlias(std::string alias)
m_userAlias = new uint8_t[HARRIS_USER_ALIAS_LENGTH_BYTES];
::memset(m_userAlias, 0x00U, HARRIS_USER_ALIAS_LENGTH_BYTES);
for (uint32_t i = 0; i < HARRIS_USER_ALIAS_LENGTH_BYTES; i++)
m_userAlias[i] = alias[i];
const std::size_t length = std::min<std::size_t>(alias.length(), HARRIS_USER_ALIAS_LENGTH_BYTES);
::memcpy(m_userAlias, alias.data(), length);
m_gotUserAliasPartA = false;
m_gotUserAlias = length > 0U;
}
// ---------------------------------------------------------------------------
@ -1654,12 +1657,14 @@ void LC::copy(const LC& data)
m_userAlias = new uint8_t[HARRIS_USER_ALIAS_LENGTH_BYTES];
::memcpy(m_userAlias, data.m_userAlias, HARRIS_USER_ALIAS_LENGTH_BYTES);
m_gotUserAliasPartA = data.m_gotUserAliasPartA;
m_gotUserAlias = data.m_gotUserAlias;
} else {
delete[] m_userAlias;
m_userAlias = new uint8_t[HARRIS_USER_ALIAS_LENGTH_BYTES];
::memset(m_userAlias, 0x00U, HARRIS_USER_ALIAS_LENGTH_BYTES);
m_gotUserAliasPartA = false;
m_gotUserAlias = false;
}

@ -37,6 +37,7 @@ using namespace p25::packet;
const uint32_t PKT_LDU1_COUNT = 3U;
const uint32_t ROAM_LDU1_COUNT = 1U;
const uint8_t USER_ALIAS_PHASE_COUNT = 6U;
// ---------------------------------------------------------------------------
// Public Class Members
@ -63,6 +64,7 @@ void Voice::resetRF()
m_pktLDU1Count = 0U;
m_grpUpdtCount = 0U;
m_roamLDU1Count = 0U;
m_rfUserAliasPhase = 0U;
m_inbound = false;
}
@ -85,6 +87,7 @@ void Voice::resetNet()
m_pktLDU1Count = 0U;
m_grpUpdtCount = 0U;
m_roamLDU1Count = 0U;
m_netUserAliasPhase = 0U;
m_netLastDUID = DUID::TDU;
}
@ -1442,6 +1445,8 @@ Voice::Voice(Control* p25, bool debug, bool verbose) :
m_pktLDU1Count(0U),
m_grpUpdtCount(0U),
m_roamLDU1Count(0U),
m_rfUserAliasPhase(0U),
m_netUserAliasPhase(0U),
m_inbound(false),
m_verbose(verbose),
m_debug(debug)
@ -2370,6 +2375,57 @@ void Voice::resetWithNullAudio(uint8_t* data, bool encrypted)
}
}
/* Replaces an eligible outbound voice LC with the next User Alias conveyance LC. */
bool Voice::applyUserAlias(lc::LC& control, uint8_t& phase)
{
// User Alias is an outbound voice-channel LC. Do not displace scheduled
// status, update, explicit-source-ID, or vendor-specific LCs.
if (!control.isStandardMFId() ||
(control.getLCO() != LCO::GROUP && control.getLCO() != LCO::PRIVATE &&
control.getLCO() != LCO::PRIVATE_EXT)) {
return false;
}
const uint8_t currentPhase = phase;
phase = (phase + 1U) % USER_ALIAS_PHASE_COUNT;
// leave one normal voice-user LC between complete alias conveyances
if (currentPhase == 2U || currentPhase == 5U)
return false;
// bryanb: this needs to be changed to use the actual Radio Alias from the new radio alias lookups
// and not the radio ID ACL alias data
// TODO FIXME TODO
::lookups::RadioId rid = m_p25->m_ridLookup->find(control.getSrcId());
if (rid.radioDefault())
return false;
std::string radioAlias = rid.radioAlias();
control.setUserAlias(radioAlias);
control.setMFId(MFG_HARRIS);
switch (currentPhase) {
case 0U:
control.setLCO(LCO::HARRIS_USER_ALIAS_A_ODD);
break;
case 1U:
control.setLCO(LCO::HARRIS_USER_ALIAS_B_ODD);
break;
case 3U:
control.setLCO(LCO::HARRIS_USER_ALIAS_A_EVEN);
break;
case 4U:
control.setLCO(LCO::HARRIS_USER_ALIAS_B_EVEN);
break;
default:
return false;
}
return true;
}
/* Helper to determine the next active talkgroup in a active multi-group scenario. */
bool Voice::nextActiveTalkgroups(const std::vector<uint32_t>& activeTG, uint8_t& groupUpdtIndex, uint32_t& dstId, uint32_t& dstIdB, bool& hasDstIdB)

@ -137,6 +137,9 @@ namespace p25
uint8_t m_grpUpdtCount;
uint8_t m_roamLDU1Count;
uint8_t m_rfUserAliasPhase;
uint8_t m_netUserAliasPhase;
bool m_inbound;
bool m_verbose;
@ -222,6 +225,14 @@ namespace p25
*/
void resetWithNullAudio(uint8_t* data, bool encrypted);
/**
* @brief Replaces an eligible outbound voice LC with the next User Alias conveyance LC.
* @param control Link control to update.
* @param phase Per-call User Alias conveyance phase.
* @returns bool True if a User Alias LC was selected.
*/
bool applyUserAlias(lc::LC& control, uint8_t& phase);
/**
* @brief Helper to determine the next active talkgroup in a active multi-group scenario,
* this is intended to update the GROUP_UPDT LC field for the next transmission.

@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - Test Suite
* GPLv2 Open Source. Use is subject to license terms.
*/
#include "host/Defines.h"
#include "common/p25/P25Defines.h"
#include "common/p25/lc/LC.h"
using namespace p25::defines;
using namespace p25::lc;
#include <catch2/catch_test_macros.hpp>
#include <cstring>
TEST_CASE("P25 User Alias LCW encoding", "[p25][lc][user-alias]")
{
LC control;
control.setMFId(MFG_HARRIS);
control.setUserAlias("TEST");
REQUIRE(control.getUserAlias() == "TEST");
uint8_t raw[P25_TDULC_PAYLOAD_LENGTH_BYTES + 1U];
SECTION("Part A carries the first seven alias octets") {
::memset(raw, 0xFFU, sizeof(raw));
control.setLCO(LCO::HARRIS_USER_ALIAS_A_ODD);
control.encodeLC(raw);
REQUIRE(raw[0U] == LCO::HARRIS_USER_ALIAS_A_ODD);
REQUIRE(raw[1U] == MFG_HARRIS);
REQUIRE(raw[2U] == 'T');
REQUIRE(raw[3U] == 'E');
REQUIRE(raw[4U] == 'S');
REQUIRE(raw[5U] == 'T');
REQUIRE(raw[6U] == 0x00U);
REQUIRE(raw[7U] == 0x00U);
REQUIRE(raw[8U] == 0x00U);
}
SECTION("Part B carries the final seven padded alias octets") {
::memset(raw, 0xFFU, sizeof(raw));
control.setLCO(LCO::HARRIS_USER_ALIAS_B_EVEN);
control.encodeLC(raw);
REQUIRE(raw[0U] == LCO::HARRIS_USER_ALIAS_B_EVEN);
REQUIRE(raw[1U] == MFG_HARRIS);
for (uint8_t i = 2U; i < 9U; ++i)
REQUIRE(raw[i] == 0x00U);
}
}
Loading…
Cancel
Save

Powered by TurnKey Linux.