P25 work in progress

This commit is contained in:
dennis.sheirer
2015-01-02 14:08:22 +00:00
parent 95ddadc598
commit 03460eeb19
122 changed files with 5372 additions and 279 deletions

View File

@@ -381,58 +381,102 @@ public class BitSetBuffer extends BitSet
}
/**
* Returns the integer value represented by the bit range
* @param start - MSB of the integer
* @param end - LSB of the integer
* @return - integer value of the bit range
* Returns the int value represented by the bit range. This method will
* parse the bits in big endian or little endian format. The start value
* represents the MSB and the end value represents the LSB of the value.
*
* start < end: little endian interpretation
* end < start: big endian interpretation
*
* @param start - MSB of the value
* @param end - LSB of the value
*
* @return - int value of the bit range
*/
public int getInt( int start, int end )
{
if( end - start > 32 )
if( Math.abs( end - start ) > 32 )
{
throw new IllegalArgumentException( "Overflow - must be 32 bits "
+ "or less to fit into a primitive integer value" );
}
int value = 0;
for( int x = start; x <= end; x++ )
{
value = Integer.rotateLeft( value, 1 );
if( get( x ) )
{
value++;;
}
if( start < end )
{
for( int x = start; x <= end; x++ )
{
value = Integer.rotateLeft( value, 1 );
if( get( x ) )
{
value++;;
}
}
}
else
{
for( int x = end; x >= start; x-- )
{
value = Integer.rotateLeft( value, 1 );
if( get( x ) )
{
value++;;
}
}
}
return value;
}
/**
* Returns the long value represented by the bit range
* @param start - MSB of the long
* @param end - LSB of the long
* Returns the long value represented by the bit range. This method will
* parse the bits in big endian or little endian format. The start value
* represents the MSB and the end value represents the LSB of the value.
*
* start < end: little endian interpretation
* end < start: big endian interpretation
*
* @param start - MSB of the value
* @param end - LSB of the value
*
* @return - long value of the bit range
*/
public long getLong( int start, int end )
{
if( end - start > 64 )
if( Math.abs( end - start ) > 64 )
{
throw new IllegalArgumentException( "Overflow - must be 64 bits "
+ "or less to fit into a primitive long value" );
}
long value = 0;
for( int x = start; x <= end; x++ )
if( start < end )
{
value = Long.rotateLeft( value, 1 );
if( get( x ) )
{
value++;
}
for( int x = start; x <= end; x++ )
{
value = Long.rotateLeft( value, 1 );
if( get( x ) )
{
value++;
}
}
}
else
{
for( int x = end; x >= start; x-- )
{
value = Long.rotateLeft( value, 1 );
if( get( x ) )
{
value++;
}
}
}
return value;

View File

@@ -67,7 +67,7 @@ public enum DecoderType
DecoderType.LTR_STANDARD,
DecoderType.MPT1327,
DecoderType.NBFM,
// DecoderType.P25_PHASE1,
DecoderType.P25_PHASE1,
DecoderType.PASSPORT );
}
@@ -86,7 +86,7 @@ public enum DecoderType
}
/**
* Returns listing of auxiliary decoders.
* Available auxiliary decoders.
*/
public static ArrayList<DecoderType> getAuxDecoders()
{

View File

@@ -32,8 +32,8 @@ import org.jdesktop.swingx.mapviewer.GeoPosition;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import crc.CRCFleetsync;
import edac.CRC;
import edac.CRCFleetsync;
public class FleetsyncMessage extends Message
{

View File

@@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import crc.CRCLJ;
import edac.CRC;
import edac.CRCLJ;
public class LJ1200Message extends Message
{

View File

@@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import crc.CRCLJ;
import edac.CRC;
import edac.CRCLJ;
public class LJ1200TransponderMessage extends Message
{

View File

@@ -25,8 +25,8 @@ import message.MessageType;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import crc.CRCLTR;
import edac.CRC;
import edac.CRCLTR;
public class LTRNetISWMessage extends LTRNetMessage
{

View File

@@ -26,9 +26,9 @@ import message.MessageType;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import crc.CRCLTR;
import decode.DecoderType;
import edac.CRC;
import edac.CRCLTR;
public abstract class LTRNetMessage extends Message
{

View File

@@ -26,9 +26,9 @@ import message.MessageType;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import crc.CRCLTR;
import decode.DecoderType;
import edac.CRC;
import edac.CRCLTR;
public abstract class LTRStandardMessage extends Message
{

View File

@@ -30,8 +30,8 @@ import message.Message;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import crc.CRCFleetsync;
import edac.CRC;
import edac.CRCFleetsync;
public class MPT1327Message extends Message
{

View File

@@ -34,6 +34,7 @@ import sample.Listener;
import alias.Alias;
import alias.AliasList;
import controller.activity.ActivitySummaryProvider;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.message.pdu.osp.control.NetworkStatusBroadcastExtended;
import decode.p25.message.pdu.osp.control.ProtectionParameterBroadcast;
@@ -295,7 +296,7 @@ public class P25ActivitySummary implements ActivitySummaryProvider,
sb.append( "\nFREQUENCY BANDS:" );
for( Integer id: identifiers )
{
IdentifierUpdate band = mBands.get( id );
IdentifierProvider band = mBands.get( id );
sb.append( "\n\t" + id );
sb.append( "- BASE: " + mFrequencyFormatter.format(

View File

@@ -20,6 +20,7 @@ package decode.p25;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
@@ -104,7 +105,8 @@ public class P25ChannelState extends ChannelState
private String mLastRegistrationEventID;
private String mLastResponseEventID;
private ArrayList<ActiveCall> mActiveCalls = new ArrayList<ActiveCall>();
private CopyOnWriteArrayList<ActiveCall> mActiveCalls =
new CopyOnWriteArrayList<ActiveCall>();
private P25ActivitySummary mActivitySummary;
private String mNAC;

View File

@@ -8,27 +8,27 @@ import org.slf4j.LoggerFactory;
import bits.BitSetBuffer;
/**
* Utility class to process interleave of P25 196-bit packet blocks.
* Utility class to process interleave of P25 Voice and Data messages.
*/
public class P25Interleave
{
private final static Logger mLog =
LoggerFactory.getLogger( P25Interleave.class );
private static int[] INTERLEAVE = new int[] { 0,1,2,3,52,53,54,55,100,101,
102,103,148,149,150,151,4,5,6,7,56,57,58,59,104,105,106,107,152,153,154,
155,8,9,10,11,60,61,62,63,108,109,110,111,156,157,158,159,12,13,14,15,
64,65,66,67,112,113,114,115,160,161,162,163,16,17,18,19,68,69,70,71,116,
117,118,119,164,165,166,167,20,21,22,23,72,73,74,75,120,121,122,123,168,
169,170,171,24,25,26,27,76,77,78,79,124,125,126,127,172,173,174,175,28,
29,30,31,80,81,82,83,128,129,130,131,176,177,178,179,32,33,34,35,84,85,
86,87,132,133,134,135,180,181,182,183,36,37,38,39,88,89,90,91,136,137,
138,139,184,185,186,187,40,41,42,43,92,93,94,95,140,141,142,143,188,189,
190,191,44,45,46,47,96,97,98,99,144,145,146,147,192,193,194,195,48,49,
50,51 };
private static int[] DATA_INTERLEAVE = new int[] { 0,1,2,3,52,53,54,55,100,
101,102,103,148,149,150,151,4,5,6,7,56,57,58,59,104,105,106,107,152,153,
154,155,8,9,10,11,60,61,62,63,108,109,110,111,156,157,158,159,12,13,14,
15,64,65,66,67,112,113,114,115,160,161,162,163,16,17,18,19,68,69,70,71,
116,117,118,119,164,165,166,167,20,21,22,23,72,73,74,75,120,121,122,123,
168,169,170,171,24,25,26,27,76,77,78,79,124,125,126,127,172,173,174,175,
28,29,30,31,80,81,82,83,128,129,130,131,176,177,178,179,32,33,34,35,84,
85,86,87,132,133,134,135,180,181,182,183,36,37,38,39,88,89,90,91,136,
137,138,139,184,185,186,187,40,41,42,43,92,93,94,95,140,141,142,143,188,
189,190,191,44,45,46,47,96,97,98,99,144,145,146,147,192,193,194,195,48,
49,50,51 };
private static int[] DEINTERLEAVE = new int[] { 0,1,2,3,16,17,18,19,32,33,
34,35,48,49,50,51,64,65,66,67,80,81,82,83,96,97,98,99,112,113,114,115,
private static int[] DATA_DEINTERLEAVE = new int[] { 0,1,2,3,16,17,18,19,32,
33,34,35,48,49,50,51,64,65,66,67,80,81,82,83,96,97,98,99,112,113,114,115,
128,129,130,131,144,145,146,147,160,161,162,163,176,177,178,179,192,193,
194,195,4,5,6,7,20,21,22,23,36,37,38,39,52,53,54,55,68,69,70,71,84,85,
86,87,100,101,102,103,116,117,118,119,132,133,134,135,148,149,150,151,
@@ -38,7 +38,24 @@ public class P25Interleave
29,30,31,44,45,46,47,60,61,62,63,76,77,78,79,92,93,94,95,108,109,110,
111,124,125,126,127,140,141,142,143,156,157,158,159,172,173,174,175,188,
189,190,191 };
private static int[] VOICE_DEINTERLEAVE = new int[] { 0,24,48,72,96,120,25,
1,73,49,121,97,2,26,50,74,98,122,27,3,75,51,123,99,4,28,52,76,100,124,
29,5,77,53,125,101,6,30,54,78,102,126,31,7,79,55,127,103,8,32,56,80,104,
128,33,9,81,57,129,105,10,34,58,82,106,130,35,11,83,59,131,107,12,36,60,
84,108,132,37,13,85,61,133,109,14,38,62,86,110,134,39,87,15,63,135,111,
16,40,64,88,112,136,41,17,89,65,137,113,18,42,66,90,114,138,43,19,91,
67,139,115,20,44,68,92,116,140,45,21,93,69,141,117,22,46,70,94,119,142,
47,23,95,71,143,118 };
private static int[] VOICE_INTERLEAVE = new int[] { 0,7,12,19,24,31,36,43,
48,55,60,67,72,79,84,91,96,103,108,115,120,127,132,139,1,6,13,18,25,30,
37,42,49,54,61,66,73,78,85,90,97,102,109,114,121,126,133,138,2,9,14,21,
26,33,38,45,50,57,62,69,74,81,86,93,98,105,110,117,122,129,134,141,3,8,
15,20,27,32,39,44,51,56,63,68,75,80,87,92,99,104,111,116,123,128,135,
140,4,11,16,23,28,35,40,47,52,59,64,71,76,83,88,95,100,107,112,119,124,
131,143,136,5,10,17,22,29,34,41,46,53,58,65,70,77,82,89,94,101,106,113,
118,125,130,137,142 };
/**
* Deinterleaves the 196-bit block in message, identified by start and end
* bit positions. Note: end index (exclusive) should be one more than the
@@ -48,7 +65,20 @@ public class P25Interleave
* @param start - starting bit index for the block
* @param end - ending bit index for the block, plus 1
*/
public static BitSetBuffer deinterleave( BitSetBuffer message, int start, int end )
public static BitSetBuffer deinterleaveData( BitSetBuffer message,
int start, int end )
{
return deinterleave( DATA_DEINTERLEAVE, message, start, end );
}
public static BitSetBuffer deinterleaveVoice( BitSetBuffer message,
int start, int end )
{
return deinterleave( VOICE_DEINTERLEAVE, message, start, end );
}
public static BitSetBuffer deinterleave( int[] pattern, BitSetBuffer message,
int start, int end )
{
BitSet original = message.get( start, end );
@@ -58,10 +88,10 @@ public class P25Interleave
/* Iterate only the set bits in the original message and apply
* the deinterleave -- we don't have to evaluate the 0 bits */
for (int i = original.nextSetBit( 0 );
i >= 0 && i < DEINTERLEAVE.length;
i >= 0 && i < pattern.length;
i = original.nextSetBit( i + 1 ) )
{
message.set( start + DEINTERLEAVE[ i ] );
message.set( start + pattern[ i ] );
}
return message;
@@ -76,7 +106,20 @@ public class P25Interleave
* @param start - starting bit index for the block
* @param end - ending bit index for the block, plus 1
*/
public static BitSetBuffer interleave( BitSetBuffer message, int start, int end )
public static BitSetBuffer interleaveData( BitSetBuffer message,
int start, int end )
{
return interleave( DATA_INTERLEAVE, message, start, end );
}
public static BitSetBuffer interleaveVoice( BitSetBuffer message,
int start, int end )
{
return interleave( VOICE_INTERLEAVE, message, start, end );
}
public static BitSetBuffer interleave( int[] pattern, BitSetBuffer message,
int start, int end )
{
BitSet original = message.get( start, end );
@@ -86,15 +129,15 @@ public class P25Interleave
/* Iterate only the set bits in the original message and apply
* the deinterleave -- we don't have to evaluate the 0 bits */
for (int i = original.nextSetBit( 0 );
i >= 0 && i < INTERLEAVE.length;
i >= 0 && i < pattern.length;
i = original.nextSetBit( i + 1 ) )
{
message.set( start + INTERLEAVE[ i ] );
message.set( start + pattern[ i ] );
}
return message;
}
public static void main( String[] args )
{
TrellisHalfRate halfrate = new TrellisHalfRate();
@@ -116,7 +159,7 @@ public class P25Interleave
mLog.debug( "Interleaved:" + interleaved );
mLog.debug( " Buffer:" + b.toString() );
P25Interleave.deinterleave( b, start, end );
P25Interleave.deinterleaveData( b, start, end );
mLog.debug( "Deinterleav:" + b.toString() );

View File

@@ -11,7 +11,7 @@ import sample.Broadcaster;
import sample.Listener;
import alias.AliasList;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
public class P25MessageProcessor implements Listener<Message>
{
@@ -39,9 +39,9 @@ public class P25MessageProcessor implements Listener<Message>
if( message.isValid() )
{
/* Insert band identifier update messages into channel-type messages */
if( message instanceof IdentifierUpdateReceiver )
if( message instanceof IdentifierProviderReceiver )
{
IdentifierUpdateReceiver receiver = (IdentifierUpdateReceiver)message;
IdentifierProviderReceiver receiver = (IdentifierProviderReceiver)message;
int[] identifiers = receiver.getIdentifiers();

View File

@@ -0,0 +1,32 @@
package decode.p25.message;
public interface IdentifierProvider
{
/**
* (Band) Identifier
*/
public abstract int getIdentifier();
/**
* Channel spacing in hertz
*/
public abstract long getChannelSpacing();
/**
* Base frequency in hertz
*/
public abstract long getBaseFrequency();
/**
* Channel bandwidth in hertz
*/
public abstract int getBandwidth();
/**
* Transmit offset in hertz
*/
public abstract long getTransmitOffset();
}

View File

@@ -7,9 +7,8 @@ import message.Message;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.reference.DataUnitID;
import edac.CRC;
public class P25Message extends Message
{
@@ -42,6 +41,16 @@ public class P25Message extends Message
mAliasList = aliasList;
}
public BitSetBuffer getSourceMessage()
{
return mMessage;
}
public AliasList getAliasList()
{
return mAliasList;
}
public String getNAC()
{
return mMessage.getHex( NAC, 3 );
@@ -165,7 +174,7 @@ public class P25Message extends Message
* @param channel - channel number
* @return - frequency in Hertz
*/
protected static long calculateUplink( IdentifierUpdate iden, int channel )
protected static long calculateUplink( IdentifierProvider iden, int channel )
{
long downlink = calculateDownlink( iden, channel );
@@ -185,7 +194,7 @@ public class P25Message extends Message
* @param channel - channel number
* @return - frequency in Hertz
*/
protected static long calculateDownlink( IdentifierUpdate iden, int channel )
protected static long calculateDownlink( IdentifierProvider iden, int channel )
{
if( iden != null )
{

View File

@@ -0,0 +1,36 @@
package decode.p25.message.filter;
import java.util.Collections;
import java.util.List;
import message.Message;
import decode.p25.message.hdu.HDUMessage;
import decode.p25.message.tdu.lc.TDULinkControlMessage;
import filter.Filter;
import filter.FilterElement;
public class HDUMessageFilter extends Filter<Message>
{
public HDUMessageFilter()
{
super( "Header Data Unit" );
}
@Override
public boolean passes( Message message )
{
return mEnabled && canProcess( message );
}
@Override
public boolean canProcess( Message message )
{
return message instanceof HDUMessage;
}
@Override
public List<FilterElement<?>> getFilterElements()
{
return Collections.EMPTY_LIST;
}
}

View File

@@ -0,0 +1,35 @@
package decode.p25.message.filter;
import java.util.Collections;
import java.util.List;
import message.Message;
import decode.p25.message.ldu.LDUMessage;
import filter.Filter;
import filter.FilterElement;
public class LDUMessageFilter extends Filter<Message>
{
public LDUMessageFilter()
{
super( "Link Data Unit" );
}
@Override
public boolean passes( Message message )
{
return mEnabled && canProcess( message );
}
@Override
public boolean canProcess( Message message )
{
return message instanceof LDUMessage;
}
@Override
public List<FilterElement<?>> getFilterElements()
{
return Collections.EMPTY_LIST;
}
}

View File

@@ -10,8 +10,11 @@ public class P25MessageFilterSet extends FilterSet<Message>
{
super( "P25 Message Filter" );
addFilter( new HDUMessageFilter() );
addFilter( new LDUMessageFilter() );
addFilter( new PDUMessageFilter() );
addFilter( new TDUMessageFilter() );
addFilter( new TDULCMessageFilter() );
addFilter( new TSBKMessageFilterSet() );
}

View File

@@ -0,0 +1,36 @@
package decode.p25.message.filter;
import java.util.Collections;
import java.util.List;
import message.Message;
import decode.p25.message.tdu.TDUMessage;
import decode.p25.message.tdu.lc.TDULinkControlMessage;
import filter.Filter;
import filter.FilterElement;
public class TDULCMessageFilter extends Filter<Message>
{
public TDULCMessageFilter()
{
super( "TDU Terminator Data Unit with Link Control" );
}
@Override
public boolean passes( Message message )
{
return mEnabled && canProcess( message );
}
@Override
public boolean canProcess( Message message )
{
return message instanceof TDULinkControlMessage;
}
@Override
public List<FilterElement<?>> getFilterElements()
{
return Collections.EMPTY_LIST;
}
}

View File

@@ -2,12 +2,26 @@ package decode.p25.message.hdu;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import decode.p25.message.P25Message;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Encryption;
import edac.CRC;
public class HDUMessage extends P25Message
{
public static final int[] MESSAGE_INDICATOR_A = { 64,65,66,67,68,69,82,83,
84,85,86,87,100,101,102,103,104,105,118,119,120,121,122,123,136,137,138,
139,140,141,154,155,156,157,158,159 };
public static final int[] MESSAGE_INDICATOR_B = { 172,173,174,175,176,177,
190,191,192,193,194,195,208,209,210,211,212,213,226,227,228,229,230,231,
244,245,246,247,248,249,262,263,264,265,266,267 };
public static final int[] VENDOR_ID = { 280,281,282,283,284,285,298,299 };
public static final int[] ALGORITHM_ID = { 300,301,302,303,316,317,318,319 };
public static final int[] KEY_ID = { 320,321,334,335,336,337,338,339,352,
353,354,355,356,357,370,371 };
public static final int[] TALKGROUP_ID = { 372,373,374,375,388,389,390,391,
392,393,406,407,408,409,410,411 };
public HDUMessage( BitSetBuffer message, DataUnitID duid,
AliasList aliasList )
{
@@ -17,8 +31,16 @@ public class HDUMessage extends P25Message
* means it passed the CRC */
mCRC = new CRC[ 2 ];
mCRC[ 0 ] = CRC.PASSED;
checkCRC();
}
private void checkCRC()
{
/* Do Golay(18,6,8) check here */
/* Do RS(36,20,17) check here */
}
@Override
public String getMessage()
{
@@ -28,13 +50,50 @@ public class HDUMessage extends P25Message
sb.append( getNAC() );
sb.append( " " );
sb.append( getDUID().getLabel() );
sb.append( " " );
sb.append( " TALKGROUP:" + getTalkgroupID() );
Encryption encryption = getEncryption();
if( encryption != Encryption.UNENCRYPTED )
{
sb.append( " ENCRYPTION:" );
sb.append( encryption.name() );
sb.append( " KEY ID:" + getKeyID() );
sb.append( " IV:" + getEncryptionInitializationVector() );
}
sb.append( " " );
sb.append( mMessage.toString() );
return sb.toString();
}
public String getEncryptionInitializationVector()
{
StringBuilder sb = new StringBuilder();
sb.append( mMessage.getHex( MESSAGE_INDICATOR_A, 9 ) );
sb.append( mMessage.getHex( MESSAGE_INDICATOR_B, 9 ) );
return sb.toString();
}
public Encryption getEncryption()
{
return Encryption.fromValue( mMessage.getInt( ALGORITHM_ID ) );
}
public int getKeyID()
{
return mMessage.getInt( KEY_ID );
}
public String getTalkgroupID()
{
return mMessage.getHex( TALKGROUP_ID, 4 );
}
/* Temporary override */
public boolean isValid()
{

View File

@@ -2,25 +2,95 @@ package decode.p25.message.ldu;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import decode.p25.message.P25Message;
import decode.p25.P25Interleave;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.LinkControlOpcode;
import decode.p25.reference.Vendor;
import decode.p25.reference.VendorLinkControlOpcode;
import edac.CRC;
public class LDU1Message extends P25Message
public class LDU1Message extends LDUMessage
{
public static final int IMBE_1 = 64;
public static final int IMBE_2 = 208;
public static final int IMBE_3 = 392;
public static final int IMBE_4 = 576;
public static final int IMBE_5 = 760;
public static final int IMBE_6 = 944;
public static final int IMBE_7 = 1128;
public static final int IMBE_8 = 1312;
public static final int IMBE_9 = 1488;
public static final int ENCRYPTION_FLAG = 352;
public static final int IMPLICIT_VENDOR_FLAG = 353;
public static final int[] OPCODE = { 354,355,356,357,362,363 };
public static final int[] VENDOR = { 364,365,366,367,372,373,374,375 };
public static final int[] OCTET_1 = { 364,365,366,367,372,373,374,375 };
public static final int[] OCTET_2 = { 376,377,382,383,384,385,386,387 };
public static final int[] OCTET_3 = { 536,537,538,539,540,541,546,547 };
public static final int[] OCTET_4 = { 548,549,550,551,556,557,558,559 };
public static final int[] OCTET_5 = { 560,561,566,567,568,569,570,571 };
public static final int[] OCTET_6 = { 720,721,722,723,724,725,730,731 };
public static final int[] OCTET_7 = { 732,733,734,735,740,741,742,743 };
public static final int[] OCTET_8 = { 744,745,750,751,752,753,754,755 };
public LDU1Message( BitSetBuffer message, DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
deinterleaveVoiceFrames();
/* NID CRC is checked in the message framer, thus a constructed message
* means it passed the CRC */
mCRC = new CRC[ 2 ];
mCRC[ 0 ] = CRC.PASSED;
checkCRC();
}
/**
* Subclass constructor from an existing LDU1Message
*/
protected LDU1Message( LDU1Message message )
{
super( message.getSourceMessage(), DataUnitID.LDU1, message.getAliasList() );
mCRC = message.mCRC;
}
private void deinterleaveVoiceFrames()
{
P25Interleave.deinterleaveVoice( mMessage, IMBE_1, IMBE_1 + 144 );
P25Interleave.deinterleaveVoice( mMessage, IMBE_2, IMBE_2 + 144 );
P25Interleave.deinterleaveVoice( mMessage, IMBE_3, IMBE_3 + 144 );
P25Interleave.deinterleaveVoice( mMessage, IMBE_4, IMBE_4 + 144 );
P25Interleave.deinterleaveVoice( mMessage, IMBE_5, IMBE_5 + 144 );
P25Interleave.deinterleaveVoice( mMessage, IMBE_6, IMBE_6 + 144 );
P25Interleave.deinterleaveVoice( mMessage, IMBE_7, IMBE_7 + 144 );
P25Interleave.deinterleaveVoice( mMessage, IMBE_8, IMBE_8 + 144 );
P25Interleave.deinterleaveVoice( mMessage, IMBE_9, IMBE_9 + 144 );
}
private void checkCRC()
{
}
@Override
public String getMessage()
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " " );
sb.append( mMessage.toString() );
return sb.toString();
}
public String getMessageStub()
{
StringBuilder sb = new StringBuilder();
@@ -30,10 +100,55 @@ public class LDU1Message extends P25Message
sb.append( getDUID().getLabel() );
sb.append( " " );
sb.append( mMessage.toString() );
if( isEncrypted() )
{
sb.append( "ENCRYPTED" );
}
else
{
if( isImplicitFormat() || getVendor() == Vendor.STANDARD )
{
sb.append( getOpcode().getLabel() );
}
else
{
sb.append( "VENDOR:" + getVendor().getLabel() + " " );
sb.append( getVendorOpcode().getLabel() );
}
}
return sb.toString();
}
public boolean isEncrypted()
{
return mMessage.get( ENCRYPTION_FLAG );
}
public boolean isImplicitFormat()
{
return mMessage.get( IMPLICIT_VENDOR_FLAG );
}
public LinkControlOpcode getOpcode()
{
return LinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
public VendorLinkControlOpcode getVendorOpcode()
{
return VendorLinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
public Vendor getVendor()
{
if( isImplicitFormat() )
{
return Vendor.STANDARD;
}
return Vendor.fromValue( mMessage.getInt( VENDOR ) );
}
/* Temporary override */
public boolean isValid()

View File

@@ -2,11 +2,11 @@ package decode.p25.message.ldu;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import decode.p25.message.P25Message;
import decode.p25.reference.DataUnitID;
import edac.CRC;
public class LDU2Message extends P25Message
public class LDU2Message extends LDUMessage
{
public LDU2Message( BitSetBuffer message, DataUnitID duid,
AliasList aliasList )

View File

@@ -1,14 +1,14 @@
package decode.p25.message.tdu;
package decode.p25.message.ldu;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import decode.p25.message.P25Message;
import decode.p25.reference.DataUnitID;
import edac.CRC;
public class TDULCMessage extends P25Message
public class LDUMessage extends P25Message
{
public TDULCMessage( BitSetBuffer message, DataUnitID duid,
public LDUMessage( BitSetBuffer message, DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );

View File

@@ -0,0 +1,127 @@
package decode.p25.message.ldu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.ldu.LDU1Message;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.LinkControlOpcode;
import decode.p25.reference.Service;
public class AdjacentSiteStatusBroadcast extends LDU1Message
implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( AdjacentSiteStatusBroadcast.class );
public static final int[] LRA = { 364,365,366,367,372,373,374,375 };
public static final int[] SYSTEM_ID = { 384,385,386,387,536,537,538,539,540,
541,546,547 };
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 };
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 };
public static final int[] IDENTIFIER = { 720,721,722,723 };
public static final int[] CHANNEL = { 724,725,730,731,732,733,734,735,740,
741,742,743 };
public static final int[] SYSTEM_SERVICE_CLASS = { 744,745,750,751,752,753,
754,755 };
private IdentifierProvider mIdentifierUpdate;
public AdjacentSiteStatusBroadcast( LDU1Message message )
{
super( message );
}
@Override
public String getEventType()
{
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYS:" + getSystemID() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " CHAN:" + getChannel() );
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 1 ];
identifiers[ 0 ] = getIdentifier();
return identifiers;
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
}
public long getUplinkFrequencyB()
{
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
}
}

View File

@@ -0,0 +1,98 @@
package decode.p25.message.ldu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.ldu.LDU1Message;
import decode.p25.reference.LinkControlOpcode;
public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message
{
private final static Logger mLog =
LoggerFactory.getLogger( AdjacentSiteStatusBroadcastExplicit.class );
public static final int[] LRA = { 364,365,366,367,372,373,374,375 };
public static final int[] TRANSMIT_IDENTIFIER = { 376,377,382,383 };
public static final int[] TRANSMIT_CHANNEL = { 384,385,386,387,536,537,538,
539,540,541,546,547 };
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 };
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 };
public static final int[] RECEIVE_IDENTIFIER = { 720,721,722,723 };
public static final int[] RECEIVE_CHANNEL = { 724,725,730,731,732,733,734,
735,740,741,742,743 };
public AdjacentSiteStatusBroadcastExplicit( LDU1Message message )
{
super( message );
}
@Override
public String getEventType()
{
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " DNLINK:" + getTransmitChannelNumber() );
sb.append( " UPLINK:" + getReceiveChannelNumber() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannel()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannelNumber()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannel()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannelNumber()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
}

View File

@@ -0,0 +1,50 @@
package decode.p25.message.ldu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.ldu.LDU1Message;
import decode.p25.reference.LinkControlOpcode;
public class CallAlert extends LDU1Message
{
private final static Logger mLog =
LoggerFactory.getLogger( CallAlert.class );
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
public CallAlert( LDU1Message message )
{
super( message );
}
@Override
public String getEventType()
{
return LinkControlOpcode.CALL_ALERT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SRC ADDR: " + getSourceAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,43 @@
package decode.p25.message.ldu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.ldu.LDU1Message;
import decode.p25.reference.LinkControlOpcode;
public class CallTermination extends LDU1Message
{
private final static Logger mLog = LoggerFactory.getLogger( CallTermination.class );
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
public CallTermination( LDU1Message message )
{
super( message );
}
@Override
public String getEventType()
{
return LinkControlOpcode.CALL_TERMINATION_OR_CANCELLATION.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " FROM:" + getSourceAddress() );
return sb.toString();
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,89 @@
package decode.p25.message.ldu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.ldu.LDU1Message;
import decode.p25.reference.LinkControlOpcode;
public class ChannelIdentifierUpdate extends LDU1Message
implements IdentifierProvider
{
private final static Logger mLog =
LoggerFactory.getLogger( ChannelIdentifierUpdate.class );
public static final int[] IDENTIFIER = { 364,365,366,367 };
public static final int[] BANDWIDTH = { 372,373,374,375,376,377,382,383,384 };
public static final int[] TRANSMIT_OFFSET = { 385,386,387,536,537,538,539,
540,541 };
public static final int[] CHANNEL_SPACING = { 546,547,548,549,550,551,556,
557,558,559 };
public static final int[] BASE_FREQUENCY = { 560,561,566,567,568,569,570,
571,720,721,722,723,724,725,730,731,732,733,734,735,740,741,742,743,744,
745,750,751,752,753,754,755 };
public ChannelIdentifierUpdate( LDU1Message message )
{
super( message );
}
@Override
public String getEventType()
{
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " IDEN:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString();
}
@Override
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
/**
* Channel bandwidth in hertz
*/
@Override
public int getBandwidth()
{
return mMessage.getInt( BANDWIDTH ) * 125;
}
@Override
public long getChannelSpacing()
{
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
}
@Override
public long getBaseFrequency()
{
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
}
@Override
public long getTransmitOffset()
{
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l;
}
}

View File

@@ -0,0 +1,87 @@
package decode.p25.message.ldu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.ldu.LDU1Message;
import decode.p25.reference.LinkControlOpcode;
public class GroupVoiceChannelUser extends LDU1Message
{
private final static Logger mLog =
LoggerFactory.getLogger( GroupVoiceChannelUser.class );
/* Service Options */
public static final int EMERGENCY_FLAG = 376;
public static final int ENCRYPTED_CHANNEL_FLAG = 377;
public static final int DUPLEX_MODE = 378;
public static final int SESSION_MODE = 379;
public static final int[] GROUP_ADDRESS = { 548,549,550,551,556,557,558,559,
560,561,566,567,568,569,570,571 };
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
public GroupVoiceChannelUser( LDU1Message message )
{
super( message );
}
@Override
public String getEventType()
{
return LinkControlOpcode.GROUP_VOICE_CHANNEL_USER.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
if( isEncryptedChannel() )
{
sb.append( " ENCRYPTED CHANNEL" );
}
sb.append( " FROM:" + getSourceAddress() );
sb.append( " TO:" + getGroupAddress() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncryptedChannel()
{
return mMessage.get( ENCRYPTED_CHANNEL_FLAG );
}
public DuplexMode getDuplexMode()
{
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF;
}
public SessionMode getSessionMode()
{
return mMessage.get( SESSION_MODE ) ?
SessionMode.CIRCUIT : SessionMode.PACKET;
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,52 @@
package decode.p25.message.ldu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.ldu.LDU1Message;
import decode.p25.reference.Vendor;
public class LDULCMessageFactory
{
private final static Logger mLog =
LoggerFactory.getLogger( LDULCMessageFactory.class );
/**
* Constructs a new sub-class of the TDULC message if the opcode is recognized
* or returns the original message.
*/
public static LDU1Message getMessage( LDU1Message message )
{
if( message.isImplicitFormat() || message.getVendor() == Vendor.STANDARD )
{
switch( message.getOpcode() )
{
case ADJACENT_SITE_STATUS_BROADCAST:
return new AdjacentSiteStatusBroadcast( message );
case ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT:
return new AdjacentSiteStatusBroadcastExplicit( message );
case CALL_ALERT:
return new CallAlert( message );
case CALL_TERMINATION_OR_CANCELLATION:
return new CallTermination( message );
case CHANNEL_IDENTIFIER_UPDATE:
return new ChannelIdentifierUpdate( message );
case GROUP_VOICE_CHANNEL_USER:
return new GroupVoiceChannelUser( message );
default:
break;
}
}
else
{
switch( message.getVendor() )
{
default:
break;
}
}
return message;
}
}

View File

@@ -0,0 +1,33 @@
package decode.p25.message.pdu;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.reference.DataUnitID;
public class PDUConfirmedMessage extends PDUMessage
{
public final static Logger mLog =
LoggerFactory.getLogger( PDUConfirmedMessage.class );
public PDUConfirmedMessage( BitSetBuffer message, DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
mLog.debug( toString() );
}
/* Override for now */
public boolean isValid()
{
return true;
}
public String toString()
{
return super.toString() + " " + mMessage.toString();
}
}

View File

@@ -2,13 +2,13 @@ package decode.p25.message.pdu;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import decode.p25.message.P25Message;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import decode.p25.reference.PDUFormat;
import decode.p25.reference.ServiceAccessPoint;
import decode.p25.reference.Vendor;
import edac.CRC;
public class PDUMessage extends P25Message
{
@@ -55,8 +55,6 @@ public class PDUMessage extends P25Message
{
sb.append( " " );
sb.append( vendor.getLabel() );
sb.append( " OPCD:" );
sb.append( mMessage.getHex( OPCODE, 2 ) );
}
return sb.toString();
@@ -87,7 +85,7 @@ public class PDUMessage extends P25Message
sb.append( " FMT:" );
sb.append( getFormat().getLabel() );
sb.append( " SAP:" );
sb.append( getServiceAccessPoint().getLabel() );
sb.append( getServiceAccessPoint().name() );
sb.append( " VEND:" );
sb.append( getVendor().getLabel() );
sb.append( " LLID:" );
@@ -100,7 +98,7 @@ public class PDUMessage extends P25Message
public String getConfirmation()
{
return mMessage.get( CONFIRMATION_REQUIRED_INDICATOR ) ? "CON" : "UNC";
return mMessage.get( CONFIRMATION_REQUIRED_INDICATOR ) ? "CONFIRMED" : "UNCONFIRMED";
}
public String getDirection()

View File

@@ -1,15 +1,15 @@
package decode.p25.message.pdu;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public abstract class UnitToUnitChannelGrantExtended extends PDUMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
@@ -39,8 +39,8 @@ public abstract class UnitToUnitChannelGrantExtended extends PDUMessage
326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,
343,344,345,346,347,348,349,350,351 };
private IdentifierUpdate mTransmitIdentifierUpdate;
private IdentifierUpdate mReceiveIdentifierUpdate;
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public UnitToUnitChannelGrantExtended( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )
@@ -174,7 +174,7 @@ public abstract class UnitToUnitChannelGrantExtended extends PDUMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitChannelIdentifier() )
{

View File

@@ -1,17 +1,17 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.message.tsbk.osp.control.SystemService;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class AdjacentStatusBroadcastExtended extends PDUMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
public static final int[] LRA = { 88,89,90,91,92,93,94,95 };
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108,
@@ -31,8 +31,8 @@ public class AdjacentStatusBroadcastExtended extends PDUMessage
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255 };
private IdentifierUpdate mTransmitIdentifierUpdate;
private IdentifierUpdate mReceiveIdentifierUpdate;
private IdentifierProvider mTransmitIdentifierProvider;
private IdentifierProvider mReceiveIdentifierProvider;
public AdjacentStatusBroadcastExtended( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )
@@ -126,25 +126,25 @@ public class AdjacentStatusBroadcastExtended extends PDUMessage
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannel() );
return calculateDownlink( mTransmitIdentifierProvider, getTransmitChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannel() );
return calculateUplink( mReceiveIdentifierProvider, getReceiveChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitIdentifier() )
{
mTransmitIdentifierUpdate = message;
mTransmitIdentifierProvider = message;
}
if( identifier == getReceiveIdentifier() )
{
mReceiveIdentifierUpdate = message;
mReceiveIdentifierProvider = message;
}
}

View File

@@ -1,11 +1,11 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class CallAlertExtended extends PDUMessage
{

View File

@@ -1,11 +1,11 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class GroupAffiliationQueryExtended extends PDUMessage
{

View File

@@ -1,12 +1,12 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import decode.p25.reference.Response;
import edac.CRCP25;
public class GroupAffiliationResponseExtended extends PDUMessage
{

View File

@@ -1,11 +1,11 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class MessageUpdateExtended extends PDUMessage
{

View File

@@ -1,18 +1,18 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.message.tsbk.osp.control.SystemService;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import decode.p25.reference.P25NetworkCallsign;
import edac.CRCP25;
public class NetworkStatusBroadcastExtended extends PDUMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
public static final int[] LRA = { 88,89,90,91,92,93,94,95 };
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108,
@@ -31,8 +31,8 @@ public class NetworkStatusBroadcastExtended extends PDUMessage
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255 };
private IdentifierUpdate mTransmitIdentifierUpdate;
private IdentifierUpdate mReceiveIdentifierUpdate;
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public NetworkStatusBroadcastExtended( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )
@@ -134,7 +134,7 @@ public class NetworkStatusBroadcastExtended extends PDUMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitIdentifier() )
{

View File

@@ -1,12 +1,12 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Encryption;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class ProtectionParameterBroadcast extends PDUMessage
{

View File

@@ -1,17 +1,17 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.message.tsbk.osp.control.SystemService;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class RFSSStatusBroadcastExtended extends PDUMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
public static final int[] LRA = { 88,89,90,91,92,93,94,95 };
public static final int ACTIVE_NETWORK_CONNECTION_INDICATOR = 99;
@@ -31,8 +31,8 @@ public class RFSSStatusBroadcastExtended extends PDUMessage
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255 };
private IdentifierUpdate mTransmitIdentifierUpdate;
private IdentifierUpdate mReceiveIdentifierUpdate;
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public RFSSStatusBroadcastExtended( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )
@@ -138,7 +138,7 @@ public class RFSSStatusBroadcastExtended extends PDUMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitIdentifier() )
{

View File

@@ -1,12 +1,12 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import dsp.fsk.P25MessageFramer;
import edac.CRCP25;
public class RoamingAddressUpdateExtended extends PDUMessage
{

View File

@@ -1,11 +1,11 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class StatusQueryExtended extends PDUMessage
{

View File

@@ -1,11 +1,11 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class StatusUpdateExtended extends PDUMessage
{

View File

@@ -1,12 +1,12 @@
package decode.p25.message.pdu.osp.control;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import decode.p25.reference.Response;
import edac.CRCP25;
public class UnitRegistrationResponseExtended extends PDUMessage
{

View File

@@ -2,17 +2,17 @@ package decode.p25.message.pdu.osp.data;
import java.util.Date;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class GroupDataChannelGrantExtended extends PDUMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
@@ -36,8 +36,8 @@ public class GroupDataChannelGrantExtended extends PDUMessage
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255 };
private IdentifierUpdate mTransmitIdentifierUpdate;
private IdentifierUpdate mReceiveIdentifierUpdate;
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public GroupDataChannelGrantExtended( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )
@@ -153,7 +153,7 @@ public class GroupDataChannelGrantExtended extends PDUMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitChannelIdentifier() )
{

View File

@@ -3,13 +3,13 @@ package decode.p25.message.pdu.osp.data;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.UnitToUnitChannelGrantExtended;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class IndividualDataChannelGrantExtended
extends UnitToUnitChannelGrantExtended
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
public IndividualDataChannelGrantExtended( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )

View File

@@ -1,16 +1,16 @@
package decode.p25.message.pdu.osp.voice;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class GroupVoiceChannelGrantExplicit extends PDUMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
@@ -34,8 +34,8 @@ public class GroupVoiceChannelGrantExplicit extends PDUMessage
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255 };
private IdentifierUpdate mTransmitIdentifierUpdate;
private IdentifierUpdate mReceiveIdentifierUpdate;
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public GroupVoiceChannelGrantExplicit( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )
@@ -151,7 +151,7 @@ public class GroupVoiceChannelGrantExplicit extends PDUMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitChannelIdentifier() )
{

View File

@@ -2,17 +2,17 @@ package decode.p25.message.pdu.osp.voice;
import java.util.Date;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class TelephoneInterconnectChannelGrantExplicit extends PDUMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
@@ -36,8 +36,8 @@ public class TelephoneInterconnectChannelGrantExplicit extends PDUMessage
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255 };
private IdentifierUpdate mTransmitIdentifierUpdate;
private IdentifierUpdate mReceiveIdentifierUpdate;
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public TelephoneInterconnectChannelGrantExplicit( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )
@@ -158,7 +158,7 @@ public class TelephoneInterconnectChannelGrantExplicit extends PDUMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitChannelIdentifier() )
{

View File

@@ -1,11 +1,11 @@
package decode.p25.message.pdu.osp.voice;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class UnitToUnitAnswerRequestExplicit extends PDUMessage
{

View File

@@ -3,13 +3,13 @@ package decode.p25.message.pdu.osp.voice;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.pdu.UnitToUnitChannelGrantExtended;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class UnitToUnitVoiceChannelGrantExtended
extends UnitToUnitChannelGrantExtended
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
public UnitToUnitVoiceChannelGrantExtended( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )

View File

@@ -1,16 +1,16 @@
package decode.p25.message.pdu.osp.voice;
import crc.CRCP25;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.pdu.PDUMessage;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import edac.CRCP25;
public class UnitToUnitVoiceChannelGrantUpdateExtended extends PDUMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
@@ -40,8 +40,8 @@ public class UnitToUnitVoiceChannelGrantUpdateExtended extends PDUMessage
326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,
343,344,345,346,347,348,349,350,351 };
private IdentifierUpdate mTransmitIdentifierUpdate;
private IdentifierUpdate mReceiveIdentifierUpdate;
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public UnitToUnitVoiceChannelGrantUpdateExtended( BitSetBuffer message,
DataUnitID duid, AliasList aliasList )
@@ -181,7 +181,7 @@ public class UnitToUnitVoiceChannelGrantUpdateExtended extends PDUMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitChannelIdentifier() )
{

View File

@@ -0,0 +1,265 @@
package decode.p25.message.tdu;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.P25Message;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.LinkControlOpcode;
import decode.p25.reference.Vendor;
import decode.p25.reference.VendorLinkControlOpcode;
import edac.CRC;
import edac.Galois24;
import edac.ReedSolomon_24_12_13;
public class TDULinkControlMessage extends P25Message
{
public final static Logger mLog = LoggerFactory.getLogger( TDULinkControlMessage.class );
public static final int[] LC_HEX_0 = { 64,65,66,67,68,69 };
public static final int[] LC_HEX_1 = { 70,71,72,73,74,75 };
public static final int[] LC_HEX_2 = { 88,89,90,91,92,93 };
public static final int[] LC_HEX_3 = { 94,95,96,97,98,99 };
public static final int[] LC_HEX_4 = { 112,113,114,115,116,117 };
public static final int[] LC_HEX_5 = { 118,119,120,121,122,123 };
public static final int[] LC_HEX_6 = { 136,137,138,139,140,141 };
public static final int[] LC_HEX_7 = { 142,143,144,145,146,147 };
public static final int[] LC_HEX_8 = { 160,161,162,163,164,165 };
public static final int[] LC_HEX_9 = { 166,167,168,169,170,171 };
public static final int[] LC_HEX_10 = { 184,185,186,187,188,189 };
public static final int[] LC_HEX_11 = { 190,191,192,193,194,195 };
public static final int[] RS_HEX_0 = { 208,209,210,211,212,213 };
public static final int[] RS_HEX_1 = { 214,215,216,217,218,219 };
public static final int[] RS_HEX_2 = { 232,233,234,235,236,237 };
public static final int[] RS_HEX_3 = { 238,239,240,241,242,243 };
public static final int[] RS_HEX_4 = { 256,257,258,259,260,261 };
public static final int[] RS_HEX_5 = { 262,263,264,265,266,267 };
public static final int[] RS_HEX_6 = { 280,281,282,283,284,285 };
public static final int[] RS_HEX_7 = { 286,287,288,289,290,291 };
public static final int[] RS_HEX_8 = { 304,305,306,307,308,309 };
public static final int[] RS_HEX_9 = { 310,311,312,313,314,315 };
public static final int[] RS_HEX_10 = { 328,329,330,331,332,333 };
public static final int[] RS_HEX_11 = { 334,335,336,337,338,339 };
public static final int ENCRYPTION_FLAG = 64;
public static final int IMPLICIT_VENDOR_FLAG = 65;
public static final int[] OPCODE = { 66,67,68,69,70,71 };
public static final int[] VENDOR = { 72,73,74,75,88,89,90,91 };
public static final ReedSolomon_24_12_13 mReedSolomonDecoder =
new ReedSolomon_24_12_13();
public TDULinkControlMessage( BitSetBuffer message, DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
/* NID CRC is checked in the message framer so a constructed message
* means it passed the CRC */
mCRC = new CRC[ 3 ];
mCRC[ 0 ] = CRC.PASSED;
checkCRC();
}
/**
* Constructs a TDULinkControl message from an existing message and bypasses
* the CRC calculation.
*/
protected TDULinkControlMessage( TDULinkControlMessage message )
{
super( message.getSourceMessage(), DataUnitID.TDULC, message.getAliasList() );
mCRC = message.getCRC();
}
public CRC[] getCRC()
{
return mCRC;
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " " );
sb.append( mMessage.toString() );
return sb.toString();
}
public String getMessageStub()
{
StringBuilder sb = new StringBuilder();
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " " );
sb.append( getDUID().getLabel() );
sb.append( " " );
if( isEncrypted() )
{
sb.append( "ENCRYPTED" );
}
else
{
if( isImplicitFormat() || getVendor() == Vendor.STANDARD )
{
sb.append( getOpcode().getLabel() );
}
else
{
sb.append( "VENDOR:" + getVendor().getLabel() + " " );
sb.append( getVendorOpcode().getLabel() );
}
}
return sb.toString();
}
public boolean isEncrypted()
{
return mMessage.get( ENCRYPTION_FLAG );
}
public boolean isImplicitFormat()
{
return mMessage.get( IMPLICIT_VENDOR_FLAG );
}
public LinkControlOpcode getOpcode()
{
return LinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
public VendorLinkControlOpcode getVendorOpcode()
{
return VendorLinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
public Vendor getVendor()
{
if( isImplicitFormat() )
{
return Vendor.STANDARD;
}
return Vendor.fromValue( mMessage.getInt( VENDOR ) );
}
/**
* Checks and repairs the 12 x 24-bit golay(24,12,8) codewords and then
* checks and repairs the 24 x 6-bit link control and reed-solomon
* RS(24,12,13) parity codewords
*/
private void checkCRC()
{
/* Check the Golay codewords */
int x = 64;
mCRC[ 1 ] = CRC.PASSED;
while( x < mMessage.size() )
{
boolean passes = Galois24.checkAndCorrect( mMessage, x );
if( !passes )
{
mCRC[ 1 ] = CRC.FAILED_CRC;
}
x += 24;
}
/* Check the Reed-Solomon parity bits. The RS decoder expects the link
* control data and reed solomon parity hex codewords in reverse order.
* The RS(24,12,13) code used by P25 removes the left-hand 47 data hex
* words, so we replace them with zeros. */
int[] input = new int [63];
int[] output = new int [63];
input[ 0 ] = mMessage.getInt( RS_HEX_11 );
input[ 1 ] = mMessage.getInt( RS_HEX_10 );
input[ 2 ] = mMessage.getInt( RS_HEX_9 );
input[ 3 ] = mMessage.getInt( RS_HEX_8 );
input[ 4 ] = mMessage.getInt( RS_HEX_7 );
input[ 5 ] = mMessage.getInt( RS_HEX_6 );
input[ 6 ] = mMessage.getInt( RS_HEX_5 );
input[ 7 ] = mMessage.getInt( RS_HEX_4 );
input[ 8 ] = mMessage.getInt( RS_HEX_3 );
input[ 9 ] = mMessage.getInt( RS_HEX_2 );
input[ 10 ] = mMessage.getInt( RS_HEX_1 );
input[ 11 ] = mMessage.getInt( RS_HEX_0 );
input[ 12 ] = mMessage.getInt( LC_HEX_11 );
input[ 13 ] = mMessage.getInt( LC_HEX_10 );
input[ 14 ] = mMessage.getInt( LC_HEX_9 );
input[ 15 ] = mMessage.getInt( LC_HEX_8 );
input[ 16 ] = mMessage.getInt( LC_HEX_7 );
input[ 17 ] = mMessage.getInt( LC_HEX_6 );
input[ 18 ] = mMessage.getInt( LC_HEX_5 );
input[ 19 ] = mMessage.getInt( LC_HEX_4 );
input[ 20 ] = mMessage.getInt( LC_HEX_3 );
input[ 21 ] = mMessage.getInt( LC_HEX_2 );
input[ 22 ] = mMessage.getInt( LC_HEX_1 );
input[ 23 ] = mMessage.getInt( LC_HEX_0 );
/* indexes 24 - 62 are defaulted to zero */
boolean irrecoverableErrors = mReedSolomonDecoder.decode( input, output );
if( irrecoverableErrors )
{
mCRC[ 2 ] = CRC.FAILED_CRC;
}
else
{
mCRC[ 2 ] = CRC.PASSED;
/* Only fix the link control data hex codewords */
repairHexCodeword( input, output, 12, LC_HEX_11 );
repairHexCodeword( input, output, 13, LC_HEX_10 );
repairHexCodeword( input, output, 14, LC_HEX_9 );
repairHexCodeword( input, output, 15, LC_HEX_8 );
repairHexCodeword( input, output, 16, LC_HEX_7 );
repairHexCodeword( input, output, 17, LC_HEX_6 );
repairHexCodeword( input, output, 18, LC_HEX_5 );
repairHexCodeword( input, output, 19, LC_HEX_4 );
repairHexCodeword( input, output, 20, LC_HEX_3 );
repairHexCodeword( input, output, 21, LC_HEX_2 );
repairHexCodeword( input, output, 22, LC_HEX_1 );
repairHexCodeword( input, output, 23, LC_HEX_0 );
/* If the golay check failed, mark it as corrected too */
if( mCRC[ 1 ] == CRC.FAILED_CRC )
{
mCRC[ 1 ] = CRC.CORRECTED;
}
}
}
private void repairHexCodeword( int[] input, int[] output, int index, int[] indexSet )
{
if( input[ index ] != output[ index ] )
{
mMessage.load( indexSet[ 0 ], 6, output[ index ] );
mCRC[ 2 ] = CRC.CORRECTED;
}
}
/**
* Indicates if the message passed the golay and reed-solomon parity checks
* or was corrected.
*/
public boolean isValid()
{
// mCRC[ 0 ] - always passes (otherwise message wouldn't be constructed )
// mCRC[ 1 ] - golay - always passes or corrected if mCRC[2] is valid
return mCRC[ 2 ] == CRC.PASSED || mCRC[ 2 ] == CRC.CORRECTED;
}
}

View File

@@ -2,9 +2,9 @@ package decode.p25.message.tdu;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import decode.p25.message.P25Message;
import decode.p25.reference.DataUnitID;
import edac.CRC;
public class TDUMessage extends P25Message
{

View File

@@ -0,0 +1,127 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.message.tsbk.osp.control.SystemService;
import decode.p25.reference.LinkControlOpcode;
import decode.p25.reference.Service;
public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage
implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( AdjacentSiteStatusBroadcast.class );
public static final int[] LRA = { 72,73,74,75,88,89,90,91 };
public static final int[] SYSTEM_ID = { 96,97,98,99,112,113,114,115,
116,117,118,119 };
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,139 };
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
public static final int[] IDENTIFIER = { 160,161,162,163 };
public static final int[] CHANNEL = { 164,165,166,167,168,169,170,
171,184,185,186,187 };
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
194,195 };
private IdentifierProvider mIdentifierUpdate;
public AdjacentSiteStatusBroadcast( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYS:" + getSystemID() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " CHAN:" + getChannel() );
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 1 ];
identifiers[ 0 ] = getIdentifier();
return identifiers;
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
}
public long getUplinkFrequencyB()
{
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
}
}

View File

@@ -0,0 +1,98 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.tsbk.osp.control.SystemService;
import decode.p25.reference.LinkControlOpcode;
public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( AdjacentSiteStatusBroadcastExplicit.class );
public static final int[] LRA = { 72,73,74,75,88,89,90,91 };
public static final int[] TRANSMIT_IDENTIFIER = { 92,93,94,95 };
public static final int[] TRANSMIT_CHANNEL = { 96,97,98,99,112,113,114,115,
116,117,118,119 };
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,139 };
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
public static final int[] RECEIVE_IDENTIFIER = { 160,161,162,163 };
public static final int[] RECEIVE_CHANNEL = { 164,165,166,167,168,169,170,
171,184,185,186,187 };
public AdjacentSiteStatusBroadcastExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " DNLINK:" + getTransmitChannelNumber() );
sb.append( " UPLINK:" + getReceiveChannelNumber() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannel()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannelNumber()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannel()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannelNumber()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
}

View File

@@ -0,0 +1,49 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class CallAlert extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( CallAlert.class );
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
public CallAlert( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.CALL_ALERT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SRC ADDR: " + getSourceAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,42 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class CallTermination extends TDULinkControlMessage
{
private final static Logger mLog = LoggerFactory.getLogger( CallTermination.class );
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public CallTermination( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.CALL_TERMINATION_OR_CANCELLATION.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " FROM:" + getSourceAddress() );
return sb.toString();
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,88 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.reference.LinkControlOpcode;
public class ChannelIdentifierUpdate extends TDULinkControlMessage
implements IdentifierProvider
{
private final static Logger mLog =
LoggerFactory.getLogger( ChannelIdentifierUpdate.class );
public static final int[] IDENTIFIER = { 72,73,74,75 };
public static final int[] BANDWIDTH = { 88,89,90,91,92,93,94,95,96 };
public static final int[] TRANSMIT_OFFSET = { 97,98,99,112,113,114,115,116,
117 };
public static final int[] CHANNEL_SPACING = { 118,119,120,121,122,123,136,
137,138,139 };
public static final int[] BASE_FREQUENCY = { 140,141,142,143,144,145,146,
147,160,161,162,163,164,165,166,167,168,169,170,171,184,185,186,
187,188,189,190,191,192,193,194,195 };
public ChannelIdentifierUpdate( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " IDEN:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString();
}
@Override
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
/**
* Channel bandwidth in hertz
*/
@Override
public int getBandwidth()
{
return mMessage.getInt( BANDWIDTH ) * 125;
}
@Override
public long getChannelSpacing()
{
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
}
@Override
public long getBaseFrequency()
{
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
}
@Override
public long getTransmitOffset()
{
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l;
}
}

View File

@@ -0,0 +1,88 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.reference.LinkControlOpcode;
public class ChannelIdentifierUpdateExplicit extends TDULinkControlMessage
implements IdentifierProvider
{
private final static Logger mLog =
LoggerFactory.getLogger( ChannelIdentifierUpdateExplicit.class );
public static final int[] IDENTIFIER = { 72,73,74,75 };
public static final int[] BANDWIDTH = { 88,89,90,91 };
public static final int[] TRANSMIT_OFFSET = { 92,93,94,95,96,97,98,99,112,
113,114,115,116,117 };
public static final int[] CHANNEL_SPACING = { 118,119,120,121,122,
123,136,137,138,139 };
public static final int[] BASE_FREQUENCY = { 140,141,142,143,144,145,146,
147,160,161,162,163,164,165,166,167,168,169,170,171,184,185,186,
187,188,189,190,191,192,193,194,195 };
public ChannelIdentifierUpdateExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE_EXPLICIT.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " IDEN:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString();
}
@Override
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
/**
* Channel bandwidth in hertz
*/
@Override
public int getBandwidth()
{
return mMessage.getInt( BANDWIDTH ) * 125;
}
@Override
public long getChannelSpacing()
{
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
}
@Override
public long getBaseFrequency()
{
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
}
@Override
public long getTransmitOffset()
{
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l;
}
}

View File

@@ -0,0 +1,86 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.ExtendedFunction;
import decode.p25.reference.LinkControlOpcode;
public class ExtendedFunctionCommand extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( ExtendedFunctionCommand.class );
public static final int[] EXTENDED_FUNCTION = { 72,73,74,75,88,89,90,91,92,
93,94,95,96,97,98,99 };
public static final int[] ARGUMENT = { 112,113,114,115,116,117,118,119,120,
121,122,123,136,137,138,139,140,141,142,143,144,145,145,147 };
public static final int[] TARGET_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
public ExtendedFunctionCommand( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.EXTENDED_FUNCTION_COMMAND.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " EXTENDED FUNCTION:" + getExtendedFunction().getLabel() );
sb.append( " ARGUMENT: " + getTargetAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public ExtendedFunction getExtendedFunction()
{
return ExtendedFunction.fromValue( mMessage.getInt( EXTENDED_FUNCTION ) );
}
public String getArgument()
{
return mMessage.getHex( ARGUMENT, 6 );
}
public String getSourceAddress()
{
switch( getExtendedFunction() )
{
case RADIO_CHECK:
case RADIO_CHECK_ACK:
case RADIO_DETACH:
case RADIO_DETACH_ACK:
case RADIO_INHIBIT:
case RADIO_INHIBIT_ACK:
case RADIO_UNINHIBIT:
case RADIO_UNINHIBIT_ACK:
return getArgument();
default:
break;
}
return null;
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,51 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class GroupAffiliationQuery extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( GroupAffiliationQuery.class );
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public GroupAffiliationQuery( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.GROUP_AFFILIATION_QUERY.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " FROM:" + getSourceAddress() );
sb.append( " TO:" + getTargetAddress() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,158 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.LinkControlOpcode;
public class GroupVoiceChannelUpdate extends TDULinkControlMessage
implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( GroupVoiceChannelUpdate.class );
public static final int[] IDENTIFIER_A = { 72,73,74,75 };
public static final int[] CHANNEL_A = { 88,89,90,91,92,93,94,95,96,97,98,99 };
public static final int[] GROUP_ADDRESS_A = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139 };
public static final int[] IDENTIFIER_B = { 140,141,142,143 };
public static final int[] CHANNEL_B = { 144,145,146,147,160,161,162,163,164,
165,166,167 };
public static final int[] GROUP_ADDRESS_B = { 168,169,170,171,184,185,186,
187,188,189,190,191,192,193,194,195 };
private IdentifierProvider mIdentifierUpdateA;
private IdentifierProvider mIdentifierUpdateB;
public GroupVoiceChannelUpdate( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " CHAN A:" + getChannelA() );
sb.append( " GRP A:" + getGroupAddressA() );
if( hasChannelB() )
{
sb.append( " CHAN B:" + getChannelA() );
sb.append( " GRP B:" + getGroupAddressA() );
}
return sb.toString();
}
public int getChannelIdentifierA()
{
return mMessage.getInt( IDENTIFIER_A );
}
public int getChannelNumberA()
{
return mMessage.getInt( CHANNEL_A );
}
public String getChannelA()
{
return getChannelIdentifierA() + "-" + getChannelNumberA();
}
public int getChannelIdentifierB()
{
return mMessage.getInt( IDENTIFIER_B );
}
public int getChannelNumberB()
{
return mMessage.getInt( CHANNEL_B );
}
public String getChannelB()
{
return getChannelIdentifierB() + "-" + getChannelNumberB();
}
public boolean hasChannelB()
{
return getChannelNumberB() != 0;
}
public String getGroupAddressA()
{
return mMessage.getHex( GROUP_ADDRESS_A, 4 );
}
public String getGroupAddressB()
{
return mMessage.getHex( GROUP_ADDRESS_B, 4 );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getChannelIdentifierA() )
{
mIdentifierUpdateA = message;
}
if( identifier == getChannelIdentifierB() )
{
mIdentifierUpdateB = message;
}
}
@Override
public int[] getIdentifiers()
{
if( hasChannelB() )
{
int[] identifiers = new int[ 2 ];
identifiers[ 0 ] = getChannelIdentifierA();
identifiers[ 1 ] = getChannelIdentifierB();
return identifiers;
}
else
{
int[] identifiers = new int[ 1 ];
identifiers[ 0 ] = getChannelIdentifierA();
return identifiers;
}
}
public long getDownlinkFrequencyA()
{
return calculateDownlink( mIdentifierUpdateA, getChannelNumberA() );
}
public long getUplinkFrequencyA()
{
return calculateUplink( mIdentifierUpdateA, getChannelNumberA() );
}
public long getDownlinkFrequencyB()
{
return calculateDownlink( mIdentifierUpdateB, getChannelNumberA() );
}
public long getUplinkFrequencyB()
{
return calculateUplink( mIdentifierUpdateB, getChannelNumberA() );
}
}

View File

@@ -0,0 +1,156 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.P25Message.DuplexMode;
import decode.p25.message.P25Message.SessionMode;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.LinkControlOpcode;
public class GroupVoiceChannelUpdateExplicit extends TDULinkControlMessage
implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( GroupVoiceChannelUpdateExplicit.class );
public static final int EMERGENCY_FLAG = 92;
public static final int ENCRYPTED_CHANNEL_FLAG = 93;
public static final int DUPLEX_MODE = 94;
public static final int SESSION_MODE = 95;
public static final int[] GROUP_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139 };
public static final int[] TRANSMIT_IDENTIFIER = { 140,141,142,143 };
public static final int[] TRANSMIT_CHANNEL = { 144,145,146,147,160,161,162,
163,164,165,166,167 };
public static final int[] RECEIVE_IDENTIFIER = { 168,169,170,171 };
public static final int[] RECEIVE_CHANNEL = { 184,185,186,187,188,189,190,
191,192,193,194,195,196,197,198,199 };
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public GroupVoiceChannelUpdateExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
if( isEncryptedChannel() )
{
sb.append( " ENCRYPTED CHANNEL" );
}
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncryptedChannel()
{
return mMessage.get( ENCRYPTED_CHANNEL_FLAG );
}
public DuplexMode getDuplexMode()
{
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF;
}
public SessionMode getSessionMode()
{
return mMessage.get( SESSION_MODE ) ?
SessionMode.CIRCUIT : SessionMode.PACKET;
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveChannelIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 2 ];
identifiers[ 0 ] = getTransmitChannelIdentifier();
identifiers[ 1 ] = getReceiveChannelIdentifier();
return identifiers;
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate,
getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate,
getReceiveChannelNumber() );
}
}

View File

@@ -0,0 +1,86 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class GroupVoiceChannelUser extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( GroupVoiceChannelUser.class );
/* Service Options */
public static final int EMERGENCY_FLAG = 92;
public static final int ENCRYPTED_CHANNEL_FLAG = 93;
public static final int DUPLEX_MODE = 94;
public static final int SESSION_MODE = 95;
public static final int[] GROUP_ADDRESS = { 120,121,122,123,136,137,138,139,
140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public GroupVoiceChannelUser( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.GROUP_VOICE_CHANNEL_USER.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
if( isEncryptedChannel() )
{
sb.append( " ENCRYPTED CHANNEL" );
}
sb.append( " FROM:" + getSourceAddress() );
sb.append( " TO:" + getGroupAddress() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncryptedChannel()
{
return mMessage.get( ENCRYPTED_CHANNEL_FLAG );
}
public DuplexMode getDuplexMode()
{
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF;
}
public SessionMode getSessionMode()
{
return mMessage.get( SESSION_MODE ) ?
SessionMode.CIRCUIT : SessionMode.PACKET;
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,57 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class MessageUpdate extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( MessageUpdate.class );
public static final int[] SHORT_DATA_MESSAGE = { 72,73,74,75,88,89,90,91,92,
93,94,95,96,97,98,99 };
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
public MessageUpdate( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.MESSAGE_UPDATE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " MSG:" + getShortDataMessage() );
sb.append( " SRC ADDR: " + getSourceAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getShortDataMessage()
{
return mMessage.getHex( SHORT_DATA_MESSAGE, 4 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,109 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.LinkControlOpcode;
import decode.p25.reference.Service;
public class NetworkStatusBroadcast extends TDULinkControlMessage
implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( NetworkStatusBroadcast.class );
public static final int[] NETWORK_ID = { 72,73,74,75,88,89,90,91,92,93,94,
95,96,97,98,99,112,113,114,115,116,117,118,119,120,121,122,123 };
public static final int[] SYSTEM_ID = { 136,137,138,139,140,141,142,143,144,
145,146,147 };
public static final int[] IDENTIFIER = { 160,161,162,163 };
public static final int[] CHANNEL = { 164,165,166,167,168,169,170,171,184,
185,186,187 };
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
194,195 };
private IdentifierProvider mIdentifierUpdate;
public NetworkStatusBroadcast( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.NETWORK_STATUS_BROADCAST.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " NETWORK:" + getNetworkID() );
sb.append( " SYS:" + getSystemID() );
sb.append( " CHAN:" + getChannel() );
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
return sb.toString();
}
public String getNetworkID()
{
return mMessage.getHex( NETWORK_ID, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 1 ];
identifiers[ 0 ] = getIdentifier();
return identifiers;
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
}
}

View File

@@ -0,0 +1,131 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.LinkControlOpcode;
import decode.p25.reference.Service;
public class NetworkStatusBroadcastExplicit extends TDULinkControlMessage
implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( NetworkStatusBroadcastExplicit.class );
public static final int[] NETWORK_ID = { 72,73,74,75,88,89,90,91,92,93,94,
95,96,97,98,99,112,113,114,115 };
public static final int[] SYSTEM_ID = { 116,117,118,119,120,121,122,123,136,
137,138,139 };
public static final int[] TRANSMIT_IDENTIFIER = { 140,141,142,143 };
public static final int[] TRANSMIT_CHANNEL = { 144,145,146,147,160,161,162,
163,164,165,166,167 };
public static final int[] RECEIVE_IDENTIFIER = { 168,169,170,171 };
public static final int[] RECEIVE_CHANNEL = { 184,185,186,187,188,189,190,
191,192,193,194,195 };
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public NetworkStatusBroadcastExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.NETWORK_STATUS_BROADCAST_EXPLICIT.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " NETWORK:" + getNetworkID() );
sb.append( " SYS:" + getSystemID() );
sb.append( " TRANSMIT:" + getTransmitChannel() );
sb.append( " RECEIVE:" + getReceiveChannel() );
return sb.toString();
}
public String getNetworkID()
{
return mMessage.getHex( NETWORK_ID, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 2 ];
identifiers[ 0 ] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier();
return identifiers;
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate,
getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate,
getReceiveChannelNumber() );
}
}

View File

@@ -0,0 +1,58 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.Encryption;
import decode.p25.reference.LinkControlOpcode;
public class ProtectionParameterBroadcast extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( ProtectionParameterBroadcast.class );
public final static int[] ALGORITHM_ID = { 112,113,114,115,116,117,118,119 };
public final static int[] KEY_ID = { 120,121,122,123,136,137,138,139,140,
141,142,143,144,145,146,147 };
public static final int[] TARGET_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
public ProtectionParameterBroadcast( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.PROTECTION_PARAMETER_BROADCAST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " ENCRYPTION:" + getEncryption().name() );
sb.append( " KEY:" + getEncryptionKey() );
sb.append( " ADDRESSS:" + getTargetAddress() );
return sb.toString();
}
public Encryption getEncryption()
{
return Encryption.fromValue( mMessage.getInt( ALGORITHM_ID ) );
}
public int getEncryptionKey()
{
return mMessage.getInt( KEY_ID );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,132 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.message.tsbk.osp.control.SystemService;
import decode.p25.reference.LinkControlOpcode;
public class RFSSStatusBroadcast extends TDULinkControlMessage
implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( RFSSStatusBroadcast.class );
public static final int[] LRA = { 72,73,74,75,88,89,
90,91 };
public static final int[] SYSTEM_ID = { 96,97,98,99,112,113,114,115,116,117,
118,119 };
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,
139 };
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
public static final int[] IDENTIFIER = { 160,161,162,163 };
public static final int[] CHANNEL = { 164,165,166,167,168,169,170,
171,184,185,186,187 };
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
194,195 };
private IdentifierProvider mIdentifierUpdate;
public RFSSStatusBroadcast( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.RFSS_STATUS_BROADCAST.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYS:" + getSystem() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " CHAN:" + getChannelNumber() );
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
sb.append( " " + mMessage.toString() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getSystem()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public String getChannel()
{
return getIdentifier() + "-" + getChannelNumber();
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
mIdentifierUpdate = message;
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 1 ];
identifiers[ 0 ] = getIdentifier();
return identifiers;
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
}
}

View File

@@ -0,0 +1,152 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.message.tsbk.osp.control.SystemService;
import decode.p25.reference.LinkControlOpcode;
public class RFSSStatusBroadcastExplicit extends TDULinkControlMessage
implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( RFSSStatusBroadcastExplicit.class );
public static final int[] LRA = { 72,73,74,75,88,89,90,91 };
public static final int[] RECEIVE_IDENTIFIER = { 92,93,94,95 };
public static final int[] RECEIVE_CHANNEL = { 96,97,98,99,112,113,114,115,
116,117,118,119 };
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,
139 };
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 };
public static final int[] TRANSMIT_CHANNEL = { 164,165,166,167,168,169,170,
171,184,185,186,187 };
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
194,195 };
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public RFSSStatusBroadcastExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.RFSS_STATUS_BROADCAST_EXPLICIT.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " TRANSMIT:" + getTransmitChannelNumber() );
sb.append( " RECEIVE:" + getReceiveChannelNumber() );
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
sb.append( " " + mMessage.toString() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 2 ];
identifiers[ 0 ] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier();
return identifiers;
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
}
}

View File

@@ -0,0 +1,159 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.message.tsbk.osp.control.SystemService;
import decode.p25.reference.LinkControlOpcode;
public class SecondaryControlChannelBroadcast extends TDULinkControlMessage
implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( SecondaryControlChannelBroadcast.class );
public static final int[] RFSS_ID = { 72,73,74,75,88,89,90,91 };
public static final int[] SITE_ID = { 92,93,94,95,96,97,98,99 };
public static final int[] IDENTIFIER_A = { 112,113,114,115 };
public static final int[] CHANNEL_A = { 116,117,118,119,120,121,122,
123,136,137,138,139 };
public static final int[] SYSTEM_SERVICE_CLASS_A = { 140,141,142,143,144,
145,146,147 };
public static final int[] IDENTIFIER_B = { 160,161,162,163 };
public static final int[] CHANNEL_B = { 164,165,166,167,168,169,170,
171,184,185,186,187 };
public static final int[] SYSTEM_SERVICE_CLASS_B = { 188,189,190,191,192,
193,194,195 };
private IdentifierProvider mIdentifierProviderA;
private IdentifierProvider mIdentifierProviderB;
public SecondaryControlChannelBroadcast( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " CHAN A:" + getChannelA() );
sb.append( " " + SystemService.toString( getSystemServiceClassA() ) );
sb.append( " CHAN B:" + getChannelB() );
sb.append( " " + SystemService.toString( getSystemServiceClassB() ) );
return sb.toString();
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifierA()
{
return mMessage.getInt( IDENTIFIER_A );
}
public int getChannelA()
{
return mMessage.getInt( CHANNEL_A );
}
public String getChannelNumberA()
{
return getIdentifierA() + "-" + getChannelA();
}
public int getIdentifierB()
{
return mMessage.getInt( IDENTIFIER_B );
}
public int getChannelB()
{
return mMessage.getInt( CHANNEL_B );
}
public String getChannelNumberB()
{
return getIdentifierB() + "-" + getChannelB();
}
public int getSystemServiceClassA()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS_A );
}
public int getSystemServiceClassB()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS_B );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getIdentifierA() )
{
mIdentifierProviderA = message;
}
if( identifier == getIdentifierB() )
{
mIdentifierProviderB = message;
}
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 2 ];
identifiers[ 0 ] = getIdentifierA();
identifiers[ 1 ] = getIdentifierB();
return identifiers;
}
public long getDownlinkFrequencyA()
{
return calculateDownlink( mIdentifierProviderA, getChannelA() );
}
public long getUplinkFrequencyA()
{
return calculateUplink( mIdentifierProviderA, getChannelA() );
}
public long getDownlinkFrequencyB()
{
return calculateDownlink( mIdentifierProviderB, getChannelB() );
}
public long getUplinkFrequencyB()
{
return calculateUplink( mIdentifierProviderB, getChannelB() );
}
}

View File

@@ -0,0 +1,140 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.message.tsbk.osp.control.SystemService;
import decode.p25.reference.LinkControlOpcode;
public class SecondaryControlChannelBroadcastExplicit
extends TDULinkControlMessage implements IdentifierProviderReceiver
{
private final static Logger mLog =
LoggerFactory.getLogger( SecondaryControlChannelBroadcastExplicit.class );
public static final int[] RFSS_ID = { 72,73,74,75,88,89,90,91 };
public static final int[] SITE_ID = { 92,93,94,95,96,97,98,99 };
public static final int[] TRANSMIT_IDENTIFIER = { 112,113,114,115 };
public static final int[] TRANSMIT_CHANNEL = { 116,117,118,119,120,121,122,
123,136,137,138,139 };
public static final int[] RECEIVE_IDENTIFIER = { 140,141,142,143 };
public static final int[] RECEIVE_CHANNEL = { 144,145,146,147,160,161,162,
163,164,165,166,167 };
public static final int[] SYSTEM_SERVICE_CLASS = { 168,169,170,171,184,
185,186,187 };
private IdentifierProvider mTransmitIdentifierProvider;
private IdentifierProvider mReceiveIdentifierProvider;
public SecondaryControlChannelBroadcastExplicit( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " TRANSMIT:" + getTransmitChannel() );
sb.append( " RECEIVE:" + getReceiveChannel() );
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
return sb.toString();
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
@Override
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitIdentifier() )
{
mTransmitIdentifierProvider = message;
}
if( identifier == getReceiveIdentifier() )
{
mReceiveIdentifierProvider = message;
}
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 2 ];
identifiers[ 0 ] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier();
return identifiers;
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierProvider,
getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierProvider,
getReceiveChannelNumber() );
}
}

View File

@@ -0,0 +1,51 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class StatusQuery extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( StatusQuery.class );
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public StatusQuery( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.STATUS_QUERY.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " FROM:" + getSourceAddress() );
sb.append( " TO:" + getTargetAddress() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,64 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class StatusUpdate extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( StatusUpdate.class );
public static final int[] USER_STATUS = { 80,81,82,83,84,85,86,87 };
public static final int[] UNIT_STATUS = { 88,89,90,91,92,93,94,95 };
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public StatusUpdate( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.STATUS_UPDATE.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " STATUS USER:" + getUserStatus() );
sb.append( " UNIT:" + getUnitStatus() );
sb.append( " FROM:" + getSourceAddress() );
sb.append( " TO:" + getTargetAddress() );
return sb.toString();
}
public String getUserStatus()
{
return mMessage.getHex( USER_STATUS, 2 );
}
public String getUnitStatus()
{
return mMessage.getHex( UNIT_STATUS, 2 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,63 @@
package decode.p25.message.tdu.lc;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
import decode.p25.reference.Service;
public class SystemServiceBroadcast extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( SystemServiceBroadcast.class );
public static final int[] REQUEST_PRIORITY_LEVEL = { 96,97,98,99 };
public static final int[] AVAILABLE_SERVICES = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SUPPORTED_SERVICES = { 160,161,162,163,164,165,
166,167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public SystemServiceBroadcast( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.SYSTEM_SERVICE_BROADCAST.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SERVICES AVAILABLE " );
sb.append( getAvailableServices() );
sb.append( " SUPPORTED " );
sb.append( getSupportedServices() );
return sb.toString();
}
public List<Service> getAvailableServices()
{
long bitmap = mMessage.getLong( AVAILABLE_SERVICES );
return Service.getServices( bitmap );
}
public List<Service> getSupportedServices()
{
long bitmap = mMessage.getLong( SUPPORTED_SERVICES );
return Service.getServices( bitmap );
}
}

View File

@@ -0,0 +1,95 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.Vendor;
public class TDULCMessageFactory
{
private final static Logger mLog =
LoggerFactory.getLogger( TDULCMessageFactory.class );
/**
* Constructs a new sub-class of the TDULC message if the opcode is recognized
* or returns the original message.
*/
public static TDULinkControlMessage getMessage( TDULinkControlMessage message )
{
if( message.isImplicitFormat() || message.getVendor() == Vendor.STANDARD )
{
switch( message.getOpcode() )
{
case ADJACENT_SITE_STATUS_BROADCAST:
return new AdjacentSiteStatusBroadcast( message );
case ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT:
return new AdjacentSiteStatusBroadcastExplicit( message );
case CALL_ALERT:
return new CallAlert( message );
case CALL_TERMINATION_OR_CANCELLATION:
return new CallTermination( message );
case CHANNEL_IDENTIFIER_UPDATE:
return new ChannelIdentifierUpdate( message );
case CHANNEL_IDENTIFIER_UPDATE_EXPLICIT:
return new ChannelIdentifierUpdateExplicit( message );
case EXTENDED_FUNCTION_COMMAND:
return new ExtendedFunctionCommand( message );
case GROUP_AFFILIATION_QUERY:
return new GroupAffiliationQuery( message );
case GROUP_VOICE_CHANNEL_UPDATE:
return new GroupVoiceChannelUpdate( message );
case GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT:
return new GroupVoiceChannelUpdateExplicit( message );
case GROUP_VOICE_CHANNEL_USER:
return new GroupVoiceChannelUser( message );
case MESSAGE_UPDATE:
return new MessageUpdate( message );
case NETWORK_STATUS_BROADCAST:
return new NetworkStatusBroadcast( message );
case NETWORK_STATUS_BROADCAST_EXPLICIT:
return new NetworkStatusBroadcastExplicit( message );
case PROTECTION_PARAMETER_BROADCAST:
return new ProtectionParameterBroadcast( message );
case RFSS_STATUS_BROADCAST:
return new RFSSStatusBroadcast( message );
case RFSS_STATUS_BROADCAST_EXPLICIT:
return new RFSSStatusBroadcastExplicit( message );
case SECONDARY_CONTROL_CHANNEL_BROADCAST:
return new SecondaryControlChannelBroadcast( message );
case SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT:
return new SecondaryControlChannelBroadcastExplicit( message );
case STATUS_QUERY:
return new StatusQuery( message );
case STATUS_UPDATE:
return new StatusUpdate( message );
case SYSTEM_SERVICE_BROADCAST:
return new SystemServiceBroadcast( message );
case TELEPHONE_INTERCONNECT_ANSWER_REQUEST:
return new TelephoneInterconnectAnswerRequest( message );
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_USER:
return new TelephoneInterconnectVoiceChannelUser( message );
case UNIT_AUTHENTICATION_COMMAND:
return new UnitAuthenticationCommand( message );
case UNIT_REGISTRATION_COMMAND:
return new UnitRegistrationCommand( message );
case UNIT_TO_UNIT_ANSWER_REQUEST:
return new UnitToUnitAnswerRequest( message );
case UNIT_TO_UNIT_VOICE_CHANNEL_USER:
return new UnitToUnitVoiceChannelUser( message );
default:
break;
}
}
else
{
switch( message.getVendor() )
{
default:
break;
}
}
return message;
}
}

View File

@@ -0,0 +1,265 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.P25Message;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.LinkControlOpcode;
import decode.p25.reference.Vendor;
import decode.p25.reference.VendorLinkControlOpcode;
import edac.CRC;
import edac.Galois24;
import edac.ReedSolomon_24_12_13;
public class TDULinkControlMessage extends P25Message
{
public final static Logger mLog = LoggerFactory.getLogger( TDULinkControlMessage.class );
public static final int[] LC_HEX_0 = { 64,65,66,67,68,69 };
public static final int[] LC_HEX_1 = { 70,71,72,73,74,75 };
public static final int[] LC_HEX_2 = { 88,89,90,91,92,93 };
public static final int[] LC_HEX_3 = { 94,95,96,97,98,99 };
public static final int[] LC_HEX_4 = { 112,113,114,115,116,117 };
public static final int[] LC_HEX_5 = { 118,119,120,121,122,123 };
public static final int[] LC_HEX_6 = { 136,137,138,139,140,141 };
public static final int[] LC_HEX_7 = { 142,143,144,145,146,147 };
public static final int[] LC_HEX_8 = { 160,161,162,163,164,165 };
public static final int[] LC_HEX_9 = { 166,167,168,169,170,171 };
public static final int[] LC_HEX_10 = { 184,185,186,187,188,189 };
public static final int[] LC_HEX_11 = { 190,191,192,193,194,195 };
public static final int[] RS_HEX_0 = { 208,209,210,211,212,213 };
public static final int[] RS_HEX_1 = { 214,215,216,217,218,219 };
public static final int[] RS_HEX_2 = { 232,233,234,235,236,237 };
public static final int[] RS_HEX_3 = { 238,239,240,241,242,243 };
public static final int[] RS_HEX_4 = { 256,257,258,259,260,261 };
public static final int[] RS_HEX_5 = { 262,263,264,265,266,267 };
public static final int[] RS_HEX_6 = { 280,281,282,283,284,285 };
public static final int[] RS_HEX_7 = { 286,287,288,289,290,291 };
public static final int[] RS_HEX_8 = { 304,305,306,307,308,309 };
public static final int[] RS_HEX_9 = { 310,311,312,313,314,315 };
public static final int[] RS_HEX_10 = { 328,329,330,331,332,333 };
public static final int[] RS_HEX_11 = { 334,335,336,337,338,339 };
public static final int ENCRYPTION_FLAG = 64;
public static final int IMPLICIT_VENDOR_FLAG = 65;
public static final int[] OPCODE = { 66,67,68,69,70,71 };
public static final int[] VENDOR = { 72,73,74,75,88,89,90,91 };
public static final ReedSolomon_24_12_13 mReedSolomonDecoder =
new ReedSolomon_24_12_13();
public TDULinkControlMessage( BitSetBuffer message, DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
/* NID CRC is checked in the message framer so a constructed message
* means it passed the CRC */
mCRC = new CRC[ 3 ];
mCRC[ 0 ] = CRC.PASSED;
checkCRC();
}
/**
* Constructs a TDULinkControl message from an existing message and bypasses
* the CRC calculation.
*/
protected TDULinkControlMessage( TDULinkControlMessage message )
{
super( message.getSourceMessage(), DataUnitID.TDULC, message.getAliasList() );
mCRC = message.getCRC();
}
public CRC[] getCRC()
{
return mCRC;
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " " );
sb.append( mMessage.toString() );
return sb.toString();
}
public String getMessageStub()
{
StringBuilder sb = new StringBuilder();
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " " );
sb.append( getDUID().getLabel() );
sb.append( " " );
if( isEncrypted() )
{
sb.append( "ENCRYPTED" );
}
else
{
if( isImplicitFormat() || getVendor() == Vendor.STANDARD )
{
sb.append( getOpcode().getLabel() );
}
else
{
sb.append( "VENDOR:" + getVendor().getLabel() + " " );
sb.append( getVendorOpcode().getLabel() );
}
}
return sb.toString();
}
public boolean isEncrypted()
{
return mMessage.get( ENCRYPTION_FLAG );
}
public boolean isImplicitFormat()
{
return mMessage.get( IMPLICIT_VENDOR_FLAG );
}
public LinkControlOpcode getOpcode()
{
return LinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
public VendorLinkControlOpcode getVendorOpcode()
{
return VendorLinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
public Vendor getVendor()
{
if( isImplicitFormat() )
{
return Vendor.STANDARD;
}
return Vendor.fromValue( mMessage.getInt( VENDOR ) );
}
/**
* Checks and repairs the 12 x 24-bit golay(24,12,8) codewords and then
* checks and repairs the 24 x 6-bit link control and reed-solomon
* RS(24,12,13) parity codewords
*/
private void checkCRC()
{
/* Check the Golay codewords */
int x = 64;
mCRC[ 1 ] = CRC.PASSED;
while( x < mMessage.size() )
{
boolean passes = Galois24.checkAndCorrect( mMessage, x );
if( !passes )
{
mCRC[ 1 ] = CRC.FAILED_CRC;
}
x += 24;
}
/* Check the Reed-Solomon parity bits. The RS decoder expects the link
* control data and reed solomon parity hex codewords in reverse order.
* The RS(24,12,13) code used by P25 removes the left-hand 47 data hex
* words, so we replace them with zeros. */
int[] input = new int [63];
int[] output = new int [63];
input[ 0 ] = mMessage.getInt( RS_HEX_11 );
input[ 1 ] = mMessage.getInt( RS_HEX_10 );
input[ 2 ] = mMessage.getInt( RS_HEX_9 );
input[ 3 ] = mMessage.getInt( RS_HEX_8 );
input[ 4 ] = mMessage.getInt( RS_HEX_7 );
input[ 5 ] = mMessage.getInt( RS_HEX_6 );
input[ 6 ] = mMessage.getInt( RS_HEX_5 );
input[ 7 ] = mMessage.getInt( RS_HEX_4 );
input[ 8 ] = mMessage.getInt( RS_HEX_3 );
input[ 9 ] = mMessage.getInt( RS_HEX_2 );
input[ 10 ] = mMessage.getInt( RS_HEX_1 );
input[ 11 ] = mMessage.getInt( RS_HEX_0 );
input[ 12 ] = mMessage.getInt( LC_HEX_11 );
input[ 13 ] = mMessage.getInt( LC_HEX_10 );
input[ 14 ] = mMessage.getInt( LC_HEX_9 );
input[ 15 ] = mMessage.getInt( LC_HEX_8 );
input[ 16 ] = mMessage.getInt( LC_HEX_7 );
input[ 17 ] = mMessage.getInt( LC_HEX_6 );
input[ 18 ] = mMessage.getInt( LC_HEX_5 );
input[ 19 ] = mMessage.getInt( LC_HEX_4 );
input[ 20 ] = mMessage.getInt( LC_HEX_3 );
input[ 21 ] = mMessage.getInt( LC_HEX_2 );
input[ 22 ] = mMessage.getInt( LC_HEX_1 );
input[ 23 ] = mMessage.getInt( LC_HEX_0 );
/* indexes 24 - 62 are defaulted to zero */
boolean irrecoverableErrors = mReedSolomonDecoder.decode( input, output );
if( irrecoverableErrors )
{
mCRC[ 2 ] = CRC.FAILED_CRC;
}
else
{
mCRC[ 2 ] = CRC.PASSED;
/* Only fix the link control data hex codewords */
repairHexCodeword( input, output, 12, LC_HEX_11 );
repairHexCodeword( input, output, 13, LC_HEX_10 );
repairHexCodeword( input, output, 14, LC_HEX_9 );
repairHexCodeword( input, output, 15, LC_HEX_8 );
repairHexCodeword( input, output, 16, LC_HEX_7 );
repairHexCodeword( input, output, 17, LC_HEX_6 );
repairHexCodeword( input, output, 18, LC_HEX_5 );
repairHexCodeword( input, output, 19, LC_HEX_4 );
repairHexCodeword( input, output, 20, LC_HEX_3 );
repairHexCodeword( input, output, 21, LC_HEX_2 );
repairHexCodeword( input, output, 22, LC_HEX_1 );
repairHexCodeword( input, output, 23, LC_HEX_0 );
/* If the golay check failed, mark it as corrected too */
if( mCRC[ 1 ] == CRC.FAILED_CRC )
{
mCRC[ 1 ] = CRC.CORRECTED;
}
}
}
private void repairHexCodeword( int[] input, int[] output, int index, int[] indexSet )
{
if( input[ index ] != output[ index ] )
{
mMessage.load( indexSet[ 0 ], 6, output[ index ] );
mCRC[ 2 ] = CRC.CORRECTED;
}
}
/**
* Indicates if the message passed the golay and reed-solomon parity checks
* or was corrected.
*/
public boolean isValid()
{
// mCRC[ 0 ] - always passes (otherwise message wouldn't be constructed )
// mCRC[ 1 ] - golay - always passes or corrected if mCRC[2] is valid
return mCRC[ 2 ] == CRC.PASSED || mCRC[ 2 ] == CRC.CORRECTED;
}
}

View File

@@ -0,0 +1,80 @@
package decode.p25.message.tdu.lc;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.Digit;
import decode.p25.reference.LinkControlOpcode;
public class TelephoneInterconnectAnswerRequest extends TDULinkControlMessage
{
private final static Logger mLog = LoggerFactory.getLogger( TelephoneInterconnectAnswerRequest.class );
public static final int[] DIGIT_1 = { 72,73,74,75 };
public static final int[] DIGIT_2 = { 88,89,90,91 };
public static final int[] DIGIT_3 = { 92,93,94,95 };
public static final int[] DIGIT_4 = { 96,97,98,99 };
public static final int[] DIGIT_5 = { 112,113,114,115 };
public static final int[] DIGIT_6 = { 116,117,118,119 };
public static final int[] DIGIT_7 = { 120,121,122,123 };
public static final int[] DIGIT_8 = { 136,137,138,139 };
public static final int[] DIGIT_9 = { 140,141,142,143 };
public static final int[] DIGIT_10 = { 144,145,146,147 };
public static final int[] TARGET_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public TelephoneInterconnectAnswerRequest( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.TELEPHONE_INTERCONNECT_ANSWER_REQUEST.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " TEL:" );
sb.append( getTelephoneNumber() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getTelephoneNumber()
{
List<Integer> digits = new ArrayList<Integer>();
digits.add( mMessage.getInt( DIGIT_1 ) );
digits.add( mMessage.getInt( DIGIT_2 ) );
digits.add( mMessage.getInt( DIGIT_3 ) );
digits.add( mMessage.getInt( DIGIT_4 ) );
digits.add( mMessage.getInt( DIGIT_5 ) );
digits.add( mMessage.getInt( DIGIT_6 ) );
digits.add( mMessage.getInt( DIGIT_7 ) );
digits.add( mMessage.getInt( DIGIT_8 ) );
digits.add( mMessage.getInt( DIGIT_9 ) );
digits.add( mMessage.getInt( DIGIT_10 ) );
return Digit.decode( digits );
}
}

View File

@@ -0,0 +1,93 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class TelephoneInterconnectVoiceChannelUser extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( TelephoneInterconnectVoiceChannelUser.class );
/* Service Options */
public static final int EMERGENCY_FLAG = 92;
public static final int ENCRYPTED_CHANNEL_FLAG = 93;
public static final int DUPLEX_MODE = 94;
public static final int SESSION_MODE = 95;
public static final int[] CALL_TIMER = { 120,121,122,123,136,137,138,139,
140,141,142,143,144,145,146,147 };
public static final int[] ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public TelephoneInterconnectVoiceChannelUser( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_USER.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
if( isEncryptedChannel() )
{
sb.append( " ENCRYPTED CHANNEL" );
}
sb.append( " TIMER:" + getCallTimer() + " SECS" );
sb.append( " ADDR:" + getAddress() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncryptedChannel()
{
return mMessage.get( ENCRYPTED_CHANNEL_FLAG );
}
public DuplexMode getDuplexMode()
{
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF;
}
public SessionMode getSessionMode()
{
return mMessage.get( SESSION_MODE ) ?
SessionMode.CIRCUIT : SessionMode.PACKET;
}
public String getAddress()
{
return mMessage.getHex( ADDRESS, 6 );
}
/**
* Call timer in seconds
*/
public int getCallTimer()
{
int units = mMessage.getInt( CALL_TIMER );
return (int)( units / 10 );
}
}

View File

@@ -0,0 +1,58 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class UnitAuthenticationCommand extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( UnitAuthenticationCommand.class );
public static final int[] NETWORK_ID = { 72,73,74,75,88,89,90,91,92,93,94,
95,96,97,98,99,112,113,114,115 };
public static final int[] SYSTEM_ID = { 116,117,118,119,120,121,122,123,
136,137,138,139 };
public static final int[] SOURCE_ID = { 140,141,142,143,144,145,146,147,
160,161,162,163,164,165,166,167,168,169,170,171,184,185,186,187 };
public UnitAuthenticationCommand( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.UNIT_AUTHENTICATION_COMMAND.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " NETWORK:" + getNetworkID() );
sb.append( " SYS:" + getSystemID() );
sb.append( " ID:" + getSourceID() );
return sb.toString();
}
public String getNetworkID()
{
return mMessage.getHex( NETWORK_ID, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
}

View File

@@ -0,0 +1,58 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class UnitRegistrationCommand extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( UnitRegistrationCommand.class );
public static final int[] NETWORK_ID = { 72,73,74,75,88,89,90,91,92,93,94,
95,96,97,98,99,112,113,114,115 };
public static final int[] SYSTEM_ID = { 116,117,118,119,120,121,122,123,
136,137,138,139 };
public static final int[] SOURCE_ID = { 140,141,142,143,144,145,146,147,
160,161,162,163,164,165,166,167,168,169,170,171,184,185,186,187 };
public UnitRegistrationCommand( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.UNIT_REGISTRATION_COMMAND.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " NETWORK:" + getNetworkID() );
sb.append( " SYS:" + getSystemID() );
sb.append( " ID:" + getSourceID() );
return sb.toString();
}
public String getNetworkID()
{
return mMessage.getHex( NETWORK_ID, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
}

View File

@@ -0,0 +1,86 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class UnitToUnitAnswerRequest extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( UnitToUnitAnswerRequest.class );
/* Service Options */
public static final int EMERGENCY_FLAG = 92;
public static final int ENCRYPTED_CHANNEL_FLAG = 93;
public static final int DUPLEX_MODE = 94;
public static final int SESSION_MODE = 95;
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public UnitToUnitAnswerRequest( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.UNIT_TO_UNIT_ANSWER_REQUEST.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
if( isEncryptedChannel() )
{
sb.append( " ENCRYPTED CHANNEL" );
}
sb.append( " FROM:" + getSourceAddress() );
sb.append( " TO:" + getTargetAddress() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncryptedChannel()
{
return mMessage.get( ENCRYPTED_CHANNEL_FLAG );
}
public DuplexMode getDuplexMode()
{
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF;
}
public SessionMode getSessionMode()
{
return mMessage.get( SESSION_MODE ) ?
SessionMode.CIRCUIT : SessionMode.PACKET;
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,86 @@
package decode.p25.message.tdu.lc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import decode.p25.reference.LinkControlOpcode;
public class UnitToUnitVoiceChannelUser extends TDULinkControlMessage
{
private final static Logger mLog =
LoggerFactory.getLogger( UnitToUnitVoiceChannelUser.class );
/* Service Options */
public static final int EMERGENCY_FLAG = 92;
public static final int ENCRYPTED_CHANNEL_FLAG = 93;
public static final int DUPLEX_MODE = 94;
public static final int SESSION_MODE = 95;
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
public UnitToUnitVoiceChannelUser( TDULinkControlMessage source )
{
super( source );
}
@Override
public String getEventType()
{
return LinkControlOpcode.UNIT_TO_UNIT_VOICE_CHANNEL_USER.getDescription();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
if( isEncryptedChannel() )
{
sb.append( " ENCRYPTED CHANNEL" );
}
sb.append( " FROM:" + getSourceAddress() );
sb.append( " TO:" + getTargetAddress() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncryptedChannel()
{
return mMessage.get( ENCRYPTED_CHANNEL_FLAG );
}
public DuplexMode getDuplexMode()
{
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF;
}
public SessionMode getSessionMode()
{
return mMessage.get( SESSION_MODE ) ?
SessionMode.CIRCUIT : SessionMode.PACKET;
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
}

View File

@@ -2,19 +2,19 @@ package decode.p25.message.tsbk;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
public abstract class ChannelGrant extends ServiceMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
public static final int[] PRIORITY = { 85,86,87 };
public static final int[] CHANNEL_IDENTIFIER = { 88,89,90,91 };
public static final int[] CHANNEL_NUMBER = { 92,93,94,95,96,97,98,99,100,
101,102,103 };
private IdentifierUpdate mIdentifierUpdate;
private IdentifierProvider mIdentifierUpdate;
public ChannelGrant( BitSetBuffer message,
DataUnitID duid,
@@ -47,7 +47,7 @@ public abstract class ChannelGrant extends ServiceMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
mIdentifierUpdate = message;
}

View File

@@ -2,7 +2,7 @@ package decode.p25.message.tsbk;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.IdentifierProvider;
import decode.p25.reference.DataUnitID;
public abstract class GroupChannelGrantExplicit extends ChannelGrant
@@ -16,8 +16,8 @@ public abstract class GroupChannelGrantExplicit extends ChannelGrant
public static final int[] GROUP_ADDRESS = { 128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143 };
private IdentifierUpdate mTransmitIdentifierUpdate;
private IdentifierUpdate mReceiveIdentifierUpdate;
private IdentifierProvider mTransmitIdentifierUpdate;
private IdentifierProvider mReceiveIdentifierUpdate;
public GroupChannelGrantExplicit( BitSetBuffer message,
DataUnitID duid,
@@ -85,7 +85,7 @@ public abstract class GroupChannelGrantExplicit extends ChannelGrant
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitChannelIdentifier() )
{

View File

@@ -2,12 +2,12 @@ package decode.p25.message.tsbk;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
public abstract class GroupMultiChannelGrant extends ChannelGrant
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
public static final int[] CHANNEL_IDENTIFIER_1 = { 80,81,82,83 };
public static final int[] CHANNEL_NUMBER_1 = { 84,85,86,87,
@@ -21,8 +21,8 @@ public abstract class GroupMultiChannelGrant extends ChannelGrant
public static final int[] GROUP_ADDRESS_2 = { 128,129,130,131,132,133,134,
135,136,137,138,139,140,141,142,143 };
private IdentifierUpdate mIdentifierUpdate1;
private IdentifierUpdate mIdentifierUpdate2;
private IdentifierProvider mIdentifierUpdate1;
private IdentifierProvider mIdentifierUpdate2;
public GroupMultiChannelGrant( BitSetBuffer message,
DataUnitID duid,
@@ -114,7 +114,7 @@ public abstract class GroupMultiChannelGrant extends ChannelGrant
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getChannelIdentifier1() )
{

View File

@@ -2,14 +2,13 @@ package decode.p25.message.tsbk;
import alias.AliasList;
import bits.BitSetBuffer;
import crc.CRC;
import crc.CRCP25;
import decode.p25.message.P25Message;
import decode.p25.message.tsbk.motorola.MotorolaOpcode;
import decode.p25.message.tsbk.vendor.VendorOpcode;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import decode.p25.reference.Vendor;
import edac.CRC;
public class TSBKMessage extends P25Message
{

View File

@@ -2,12 +2,12 @@ package decode.p25.message.tsbk.motorola;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
public class ChannelCWIDUpdate extends MotorolaTSBKMessage
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
public static final int[] CHARACTER_1 = { 80,81,82,83,84,85 };
public static final int[] CHARACTER_2 = { 86,87,88,89,90,91 };
@@ -22,7 +22,7 @@ public class ChannelCWIDUpdate extends MotorolaTSBKMessage
public static final int[] CHANNEL = { 132,133,134,135,136,137,138,139,140,
141,142,143 };
private IdentifierUpdate mIdentifierUpdate;
private IdentifierProvider mIdentifierUpdate;
public ChannelCWIDUpdate( BitSetBuffer message,
DataUnitID duid,
@@ -104,7 +104,7 @@ public class ChannelCWIDUpdate extends MotorolaTSBKMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
mIdentifierUpdate = message;
}

View File

@@ -2,11 +2,12 @@ package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierUpdateReceiver
public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierProviderReceiver
{
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
86,87 };
@@ -24,7 +25,7 @@ public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierUp
public static final int[] SYSTEM_SERVICE_CLASS = { 136,137,138,139,140,141,
142,143 };
private IdentifierUpdate mIdentifierUpdate;
private IdentifierProvider mIdentifierUpdate;
public AdjacentStatusBroadcast( BitSetBuffer message,
DataUnitID duid,
@@ -161,7 +162,7 @@ public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierUp
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message;

View File

@@ -0,0 +1,15 @@
package decode.p25.message.tsbk.osp.control;
import decode.p25.message.IdentifierProvider;
/**
* Interface to allow messages to be augmented with IdentiferUpdateXXX type
* messages that provide the channel information necessary to calculate the
* uplink and downlink frequency for the channel.
*/
public interface IdentifierProviderReceiver
{
public void setIdentifierMessage( int identifier, IdentifierProvider message );
public int[] getIdentifiers();
}

View File

@@ -2,10 +2,12 @@ package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
public abstract class IdentifierUpdate extends TSBKMessage
public abstract class IdentifierUpdate extends TSBKMessage
implements IdentifierProvider
{
public static final int[] IDENTIFIER = { 80,81,82,83 };
@@ -23,29 +25,24 @@ public abstract class IdentifierUpdate extends TSBKMessage
super( message, duid, aliasList );
}
/**
* (Band) Identifier
*/
@Override
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
/**
* Channel spacing in hertz
*/
@Override
public long getChannelSpacing()
{
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
}
/**
* Base frequency in hertz
*/
@Override
public long getBaseFrequency()
{
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
}
@Override
public abstract long getTransmitOffset();
}

View File

@@ -1,5 +1,7 @@
package decode.p25.message.tsbk.osp.control;
import decode.p25.message.IdentifierProvider;
/**
* Interface to allow messages to be augmented with IdentiferUpdateXXX type
* messages that provide the channel information necessary to calculate the
@@ -7,7 +9,7 @@ package decode.p25.message.tsbk.osp.control;
*/
public interface IdentifierUpdateReceiver
{
public void setIdentifierMessage( int identifier, IdentifierUpdate message );
public void setIdentifierMessage( int identifier, IdentifierProvider message );
public int[] getIdentifiers();
}

View File

@@ -8,13 +8,13 @@ import decode.p25.reference.Opcode;
public class MessageUpdate extends TSBKMessage
{
public static final int[] SHORT_DATA_MESSAGE = { 80,81,82,83,84,85,86,87,88,89,90,91,
92,93,94,95 };
public static final int[] SHORT_DATA_MESSAGE = { 80,81,82,83,84,85,86,87,88,89,90,91,
92,93,94,95 };
public static final int[] TARGET_ADDRESS = { 96,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 };
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 };
public static final int[] SOURCE_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public MessageUpdate( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )

View File

@@ -2,12 +2,13 @@ package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import decode.p25.reference.P25NetworkCallsign;
public class NetworkStatusBroadcast extends TSBKMessage implements IdentifierUpdateReceiver
public class NetworkStatusBroadcast extends TSBKMessage implements IdentifierProviderReceiver
{
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
86,87 };
@@ -21,7 +22,7 @@ public class NetworkStatusBroadcast extends TSBKMessage implements IdentifierUpd
public static final int[] SYSTEM_SERVICE_CLASS = { 136,137,138,139,140,141,
142,143 };
private IdentifierUpdate mIdentifierUpdate;
private IdentifierProvider mIdentifierUpdate;
public NetworkStatusBroadcast( BitSetBuffer message,
DataUnitID duid,
@@ -107,7 +108,7 @@ public class NetworkStatusBroadcast extends TSBKMessage implements IdentifierUpd
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message;

View File

@@ -2,11 +2,12 @@ package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class RFSSStatusBroadcast extends TSBKMessage implements IdentifierUpdateReceiver
public class RFSSStatusBroadcast extends TSBKMessage implements IdentifierProviderReceiver
{
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
86,87 };
@@ -21,7 +22,7 @@ public class RFSSStatusBroadcast extends TSBKMessage implements IdentifierUpdate
public static final int[] SYSTEM_SERVICE_CLASS = { 136,137,138,139,140,141,
142,143 };
private IdentifierUpdate mIdentifierUpdate;
private IdentifierProvider mIdentifierUpdate;
public RFSSStatusBroadcast( BitSetBuffer message,
DataUnitID duid,
@@ -117,7 +118,7 @@ public class RFSSStatusBroadcast extends TSBKMessage implements IdentifierUpdate
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message;

View File

@@ -5,12 +5,13 @@ import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class SecondaryControlChannelBroadcast extends TSBKMessage
implements IdentifierUpdateReceiver, Comparable<SecondaryControlChannelBroadcast>
implements IdentifierProviderReceiver, Comparable<SecondaryControlChannelBroadcast>
{
private final static Logger mLog =
LoggerFactory.getLogger( SecondaryControlChannelBroadcast.class );
@@ -28,8 +29,8 @@ public class SecondaryControlChannelBroadcast extends TSBKMessage
public static final int[] SYSTEM_SERVICE_CLASS_2 = { 136,137,138,139,140,
141,142,143 };
private IdentifierUpdate mIdentifierUpdate1;
private IdentifierUpdate mIdentifierUpdate2;
private IdentifierProvider mIdentifierUpdate1;
private IdentifierProvider mIdentifierUpdate2;
public SecondaryControlChannelBroadcast( BitSetBuffer message,
DataUnitID duid,
@@ -143,7 +144,7 @@ public class SecondaryControlChannelBroadcast extends TSBKMessage
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getIdentifier1() )
{

View File

@@ -8,12 +8,12 @@ import decode.p25.reference.Opcode;
public class StatusUpdate extends TSBKMessage
{
public static final int[] USER_STATUS = { 80,81,82,83,84,85,86,87 };
public static final int[] UNIT_STATUS = { 88,89,90,91,92,93,94,95 };
public static final int[] TARGET_ADDRESS = { 96,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 };
public static final int[] SOURCE_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public static final int[] USER_STATUS = { 72,73,74,75,88,89,90,91 };
public static final int[] UNIT_STATUS = { 92,93,94,95,96,97,98,99 };
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
public StatusUpdate( BitSetBuffer message,
DataUnitID duid,
@@ -25,7 +25,7 @@ public class StatusUpdate extends TSBKMessage
@Override
public String getEventType()
{
return Opcode.STATUS_QUERY.getDescription();
return Opcode.STATUS_UPDATE.getDescription();
}
public String getMessage()

View File

@@ -2,12 +2,12 @@ package decode.p25.message.tsbk.osp.data;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
public class SNDCPDataChannelAnnouncementExplicit extends SNDCPData
implements IdentifierUpdateReceiver
implements IdentifierProviderReceiver
{
public static final int AUTONOMOUS_ACCESS_AVAILABLE_INDICATOR = 88;
public static final int REQUESTED_ACCESS_AVAILABLE_INDICATOR = 89;
@@ -22,8 +22,8 @@ public class SNDCPDataChannelAnnouncementExplicit extends SNDCPData
public static final int[] DATA_ACCESS_CONTROL = { 128,129,130,131,132,133,
134,135,136,137,138,139,140,141,142,143 };
private IdentifierUpdate mIdentifierUpdateTransmit;
private IdentifierUpdate mIdentifierUpdateReceive;
private IdentifierProvider mIdentifierUpdateTransmit;
private IdentifierProvider mIdentifierUpdateReceive;
public SNDCPDataChannelAnnouncementExplicit( BitSetBuffer message,
DataUnitID duid,
@@ -118,7 +118,7 @@ public class SNDCPDataChannelAnnouncementExplicit extends SNDCPData
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitChannelIdentifier() )
{

View File

@@ -2,11 +2,11 @@ package decode.p25.message.tsbk.osp.data;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
import decode.p25.message.IdentifierProvider;
import decode.p25.message.tsbk.osp.control.IdentifierProviderReceiver;
import decode.p25.reference.DataUnitID;
public class SNDCPDataChannelGrant extends SNDCPData implements IdentifierUpdateReceiver
public class SNDCPDataChannelGrant extends SNDCPData implements IdentifierProviderReceiver
{
public static final int[] TRANSMIT_IDENTIFIER = { 88,89,90,91 };
public static final int[] TRANSMIT_NUMBER = { 92,93,94,95,96,97,98,99,100,
@@ -18,8 +18,8 @@ public class SNDCPDataChannelGrant extends SNDCPData implements IdentifierUpdate
public static final int[] TARGET_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
private IdentifierUpdate mIdentifierUpdateTransmit;
private IdentifierUpdate mIdentifierUpdateReceive;
private IdentifierProvider mIdentifierUpdateTransmit;
private IdentifierProvider mIdentifierUpdateReceive;
public SNDCPDataChannelGrant( BitSetBuffer message,
DataUnitID duid,
@@ -91,7 +91,7 @@ public class SNDCPDataChannelGrant extends SNDCPData implements IdentifierUpdate
}
@Override
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
public void setIdentifierMessage( int identifier, IdentifierProvider message )
{
if( identifier == getTransmitChannelIdentifier() )
{

Some files were not shown because too many files have changed in this diff Show More