Skip to content

Commit

Permalink
#1914 Adds moto talker alias assembler to phase 1 decoder. Not yet in…
Browse files Browse the repository at this point in the history
…tegrated into decoder state.
  • Loading branch information
Dennis Sheirer committed May 10, 2024
1 parent c53afbe commit 9e64996
Show file tree
Hide file tree
Showing 14 changed files with 661 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2024 Dennis Sheirer
*
* * ******************************************************************************
* * Copyright (C) 2014-2019 Dennis Sheirer
* *
* * 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 3 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, see <http://www.gnu.org/licenses/>
* * *****************************************************************************
* 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 3 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, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.p25.identifier.talkgroup;

import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;

/**
* APCO25 Announcement Talkgroup - grouping of talkgroups within a system.
Expand All @@ -42,7 +38,7 @@ public APCO25AnnouncementTalkgroup(Integer value)
/**
* Creates an APCO-25 announcement group talkgroup identifier
*/
public static TalkgroupIdentifier create(int talkgroup)
public static APCO25Talkgroup create(int talkgroup)
{
return new APCO25AnnouncementTalkgroup(talkgroup);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2024 Dennis Sheirer
*
* * ******************************************************************************
* * Copyright (C) 2014-2019 Dennis Sheirer
* *
* * 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 3 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, see <http://www.gnu.org/licenses/>
* * *****************************************************************************
* 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 3 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, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/

package io.github.dsheirer.module.decode.p25.identifier.talkgroup;
Expand Down Expand Up @@ -47,7 +44,7 @@ public Protocol getProtocol()
/**
* Creates an APCO-25 TO talkgroup identifier
*/
public static TalkgroupIdentifier create(int talkgroup)
public static APCO25Talkgroup create(int talkgroup)
{
return new APCO25Talkgroup(talkgroup);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.standard.osp.UnitToUnitVoiceChannelGrant;
import io.github.dsheirer.module.decode.p25.phase1.message.tsbk.standard.osp.UnitToUnitVoiceChannelGrantUpdate;
import io.github.dsheirer.module.decode.p25.reference.ServiceOptions;
import io.github.dsheirer.module.decode.p25.reference.Vendor;
import io.github.dsheirer.module.decode.p25.reference.VoiceServiceOptions;
import io.github.dsheirer.protocol.Protocol;
import io.github.dsheirer.sample.Listener;
Expand Down Expand Up @@ -316,6 +317,13 @@ public void receive(IMessage iMessage)
break;
}
}
else if(iMessage instanceof LinkControlWord lcw)
{
//Process Motorola talker alias complete LCW that is created by the P25P1MessageProcessor where it is not
//carried in a data unit and was reassembled from a header and data blocks. Since the header and data
// blocks are only carried in TDULC data units, we set isTerminator to true here.
processLC(lcw, iMessage.getTimestamp(), true);
}
}

/**
Expand Down Expand Up @@ -1488,10 +1496,15 @@ private void processTSBK(P25P1Message message)
default:
if(!tsbk.getOpcode().name().startsWith("ISP"))
{
LOGGING_SUPPRESSOR.info(tsbk.getOpcode().name() + tsbk.getMessage().toHexString(),
1, "Unrecognized TSBK Opcode: " + tsbk.getOpcode().name() +
" VENDOR:" + tsbk.getVendor() + " OPCODE:" + tsbk.getOpcodeNumber() +
" MSG:" + tsbk.getMessage().toHexString());
Vendor vendor = tsbk.getVendor();

if(vendor == Vendor.STANDARD || vendor == Vendor.MOTOROLA || vendor == Vendor.HARRIS)
{
LOGGING_SUPPRESSOR.info(tsbk.getOpcode().name() + tsbk.getMessage().toHexString(),
1, "Unrecognized TSBK Opcode: " + tsbk.getOpcode().name() +
" VENDOR:" + tsbk.getVendor() + " OPCODE:" + tsbk.getOpcodeNumber() +
" MSG:" + tsbk.getMessage().toHexString());
}
}
break;
}
Expand Down Expand Up @@ -2001,6 +2014,9 @@ private void processLC(LinkControlWord lcw, long timestamp, boolean isTerminator
closeCurrentCallEvent(timestamp);
}
break;
case MOTOROLA_TALKER_ALIAS_COMPLETE:
//TODO: handle alias once decoding is complete
break;

//Other events
case CALL_ALERT:
Expand Down Expand Up @@ -2164,6 +2180,7 @@ private void processLC(LinkControlWord lcw, long timestamp, boolean isTerminator
{
closeCurrentCallEvent(timestamp);
}

LOGGING_SUPPRESSOR.info(lcw.getVendor().toString() + lcw.getOpcodeNumber() + lcw.getMessage().toHexString(),
1, "Unrecognized LCW Opcode: " + lcw.getOpcode().name() + " VENDOR:" + lcw.getVendor() +
" OPCODE:" + lcw.getOpcodeNumber() + " MSG:" + lcw.getMessage().toHexString() +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.ExtendedSourceLinkControlWord;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.MotorolaTalkerAliasAssemblerP25Phase1;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCSourceIDExtension;
import io.github.dsheirer.module.decode.p25.phase1.message.ldu.LDU1Message;
import io.github.dsheirer.module.decode.p25.phase1.message.tdu.TDULinkControlMessage;
Expand All @@ -38,7 +39,7 @@
/**
* APCO25 Phase 1 Message Processor.
*
* Performs post-message creation processing before the message is sent downstream.
* Performs post-message creation processing and enrichment before the message is sent downstream.
*/
public class P25P1MessageProcessor implements Listener<IMessage>
{
Expand All @@ -60,6 +61,14 @@ public class P25P1MessageProcessor implements Listener<IMessage>
*/
private ExtendedSourceLinkControlWord mExtendedSourceLinkControlWord;

/**
* Motorola talker alias assembler for link control header and data blocks.
*/
private MotorolaTalkerAliasAssemblerP25Phase1 mMotorolaTalkerAliasAssembler = new MotorolaTalkerAliasAssemblerP25Phase1();

/**
* Constructs an instance
*/
public P25P1MessageProcessor()
{
}
Expand All @@ -79,9 +88,17 @@ public void preload(P25FrequencyBandPreloadDataContent content)
}
}

/**
* Processes the message for enrichment or reassembly of fragments and sends the enriched message and any additional
* messages that were created during the enrichment to the registered message listener.
* @param message to process
*/
@Override
public void receive(IMessage message)
{
//Optional message created during processing that should be sent after the current argument is sent.
IMessage additionalMessageToSend = null;

if(message.isValid())
{
//Reassemble extended source link control messages.
Expand All @@ -91,7 +108,13 @@ public void receive(IMessage message)
}
else if(message instanceof TDULinkControlMessage tdu)
{
reassembleLC(tdu.getLinkControlWord());
LinkControlWord lcw = tdu.getLinkControlWord();
reassembleLC(lcw);

if(mMotorolaTalkerAliasAssembler.add(lcw, message.getTimestamp()))
{
additionalMessageToSend = mMotorolaTalkerAliasAssembler.assemble();
}
}

//Insert frequency band identifier update messages into channel-type messages */
Expand Down Expand Up @@ -119,13 +142,25 @@ else if(message instanceof TDULinkControlMessage tdu)
if(message instanceof IFrequencyBand)
{
IFrequencyBand bandIdentifier = (IFrequencyBand)message;
mFrequencyBandMap.put(bandIdentifier.getIdentifier(), bandIdentifier);

//Only store the frequency band if it's new so we don't hold on to more than one instance of the
//frequency band message. Otherwise, we'll hold on to several instances of each message as they get
//injected into other messages with channel information.
if(!mFrequencyBandMap.containsKey(bandIdentifier.getIdentifier()))
{
mFrequencyBandMap.put(bandIdentifier.getIdentifier(), bandIdentifier);
}
}
}

if(mMessageListener != null)
{
mMessageListener.receive(message);

if(additionalMessageToSend != null)
{
mMessageListener.receive(additionalMessageToSend);
}
}
}

Expand Down Expand Up @@ -153,17 +188,27 @@ else if(linkControlWord instanceof LCSourceIDExtension sie && mExtendedSourceLin
}
}

/**
* Prepares for disposal of this instance.
*/
public void dispose()
{
mFrequencyBandMap.clear();
mMessageListener = null;
}

/**
* Sets the message listener to receive the output from this processor.
* @param listener to receive output messages
*/
public void setMessageListener(Listener<IMessage> listener)
{
mMessageListener = listener;
}

/**
* Clears a registered message listener.
*/
public void removeMessageListener()
{
mMessageListener = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ public enum LinkControlOpcode
MOTOROLA_TALK_COMPLETE("MOTOROLA TALK_COMPLETE", 15),
MOTOROLA_TALKER_ALIAS_HEADER("MOTOROLA TALKER ALIAS HEADER", 21),
MOTOROLA_TALKER_ALIAS_DATA_BLOCK("MOTOROLA TALKER ALIAS DATA BLOCK", 23),
//Note: this is not a true LCW opcode ... it is a talker alias reassembled from header and data blocks
MOTOROLA_TALKER_ALIAS_COMPLETE("MOTOROLA TALKER ALIAS COMPLETE", -1),
MOTOROLA_UNKNOWN("MOTOROLA UNKNOWN", -1),

L3HARRIS_RETURN_TO_CONTROL_CHANNEL("UNKNOWN OPCODE 10", 10),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ public abstract class LinkControlWord extends AbstractMessage
public static final int OCTET_10_BIT_80 = 80;
public static final int OCTET_11_BIT_88 = 88;
public static final int OCTET_12_BIT_96 = 96;
public static final int OCTET_13_BIT_104 = 104;
public static final int OCTET_14_BIT_112 = 112;
public static final int OCTET_15_BIT_120 = 120;
public static final int OCTET_16_BIT_128 = 128;
public static final int OCTET_17_BIT_136 = 136;
public static final int OCTET_18_BIT_144 = 144;
public static final int OCTET_19_BIT_152 = 152;
public static final int OCTET_20_BIT_160 = 160;
public static final int OCTET_21_BIT_168 = 168;
public static final int OCTET_22_BIT_176 = 176;
public static final int OCTET_23_BIT_184 = 184;

private static final int ENCRYPTION_FLAG = 0;
private static final int STANDARD_VENDOR_ID_FLAG = 1;
Expand Down
Loading

0 comments on commit 9e64996

Please sign in to comment.