Initial commit of redesigned internal processing and audio management.

Note: Several of the decoders are currently non-functioning in this
commit.  If you want the latest functioning codebase, please checkout
the commit prior to this one.  All decoders will eventually be updated
with this new architecture.

Currently broken:
- Logging and recording
- Aux decoders (Fleetsync/MDC/LoJack/Tait)
- LTR/Passport decoders

Changes in this commit:
- Module architecture for decoders and components with central
provisioning by the DecoderFactory
- Transition from Complex sample stream processing to float buffer
processing for improved memory management
- Redesigned filter structures - to support buffers and streams
- Resolved several memory leak issues
- Universal sharing of the thread pool manager
- Added centralized audio management with call/user prioritization and
new gui with mute/volume controls
- Embedded audio metadata for eventual streaming support
- Redesigned ProcessingChain to support independent re-use
- Added new TrafficChannelManager to handle traffic channel allocations
- Traffic Channel pool size and Call timeout available in P25 and
MPT1327 configs
- Redesigned channel and decoder gui components
This commit is contained in:
denny
2015-09-01 07:10:26 -04:00
parent 538a299246
commit f4d8ea281d
570 changed files with 21578 additions and 17012 deletions

View File

@@ -0,0 +1,169 @@
package module.decode.p25.message.pdu;
import module.decode.p25.message.P25Message;
import module.decode.p25.message.tsbk.vendor.VendorOpcode;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.PDUFormat;
import module.decode.p25.reference.ServiceAccessPoint;
import module.decode.p25.reference.Vendor;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRC;
public class PDUMessage extends P25Message
{
public static final int CONFIRMATION_REQUIRED_INDICATOR = 65;
public static final int PACKET_DIRECTION_INDICATOR = 66;
public static final int[] FORMAT = { 67,68,69,70,71 };
public static final int[] SAP_ID = { 74,75,76,77,78,79 };
public static final int[] VENDOR_ID = { 80,81,82,83,84,85,86,87 };
public static final int[] LOGICAL_LINK_ID = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] BLOCKS_TO_FOLLOW = { 113,114,115,116,117,118,119 };
public static final int[] PAD_OCTET_COUNT = { 123,124,125,126,127 };
public static final int[] OPCODE = { 122,123,124,125,126,127 };
public static final int[] DATA_HEADER_OFFSET = { 138,139,140,141,142,143 };
public static final int[] PDU_CRC = { 144,145,146,147,148,149,150,151,152,
153,154,155,156,157,158,159 };
public PDUMessage( BinaryMessage message, DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Setup a CRC array to hold the header CRC and the multi-block CRC */
mCRC = new CRC[ 2 ];
mCRC[ 0 ] = CRC.PASSED;
}
protected String getMessageStub()
{
StringBuilder sb = new StringBuilder();
Vendor vendor = getVendor();
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " " );
sb.append( getDUID().getLabel() );
if( vendor == Vendor.STANDARD )
{
sb.append( " " );
sb.append( getOpcode().getLabel() );
}
else
{
sb.append( " " );
sb.append( vendor.getLabel() );
}
return sb.toString();
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
switch( getFormat() )
{
case ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL:
break;
case UNCONFIRMED_MULTI_BLOCK_TRUNKING_CONTROL:
sb.append( " PAD OCTETS:" + getPadOctetCount() );
sb.append( " DATA HDR OFFSET:" + getDataHeaderOffset() );
break;
default:
}
sb.append( " " );
sb.append( getConfirmation() );
sb.append( " " );
sb.append( getDirection() );
sb.append( " FMT:" );
sb.append( getFormat().getLabel() );
sb.append( " SAP:" );
sb.append( getServiceAccessPoint().name() );
sb.append( " VEND:" );
sb.append( getVendor().getLabel() );
sb.append( " LLID:" );
sb.append( getLogicalLinkID() );
sb.append( " BLKS TO FOLLOW:" );
sb.append( getBlocksToFollowCount() );
return sb.toString();
}
public String getConfirmation()
{
return mMessage.get( CONFIRMATION_REQUIRED_INDICATOR ) ? "CONFIRMED" : "UNCONFIRMED";
}
public String getDirection()
{
return mMessage.get( PACKET_DIRECTION_INDICATOR ) ? "OSP" : "ISP";
}
public boolean isOutbound()
{
return mMessage.get( PACKET_DIRECTION_INDICATOR );
}
public PDUFormat getFormat()
{
return PDUFormat.fromValue( mMessage.getInt( FORMAT ) );
}
public ServiceAccessPoint getServiceAccessPoint()
{
return ServiceAccessPoint.fromValue( mMessage.getInt( SAP_ID ) );
}
public Vendor getVendor()
{
return Vendor.fromValue( mMessage.getInt( VENDOR_ID ) );
}
public String getLogicalLinkID()
{
return mMessage.getHex( LOGICAL_LINK_ID, 6 );
}
public int getBlocksToFollowCount()
{
return mMessage.getInt( BLOCKS_TO_FOLLOW );
}
public int getPadOctetCount()
{
return mMessage.getInt( PAD_OCTET_COUNT );
}
public Opcode getOpcode()
{
if( getFormat() == PDUFormat.ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL )
{
return Opcode.fromValue( mMessage.getInt( OPCODE ) );
}
return Opcode.UNKNOWN;
}
public VendorOpcode getVendorOpcode()
{
if( getFormat() == PDUFormat.ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL )
{
return VendorOpcode.fromValue( mMessage.getInt( OPCODE ) );
}
return VendorOpcode.UNKNOWN;
}
public int getDataHeaderOffset()
{
return mMessage.getInt( DATA_HEADER_OFFSET );
}
}

View File

@@ -0,0 +1,131 @@
package module.decode.p25.message.pdu;
import module.decode.p25.message.pdu.osp.control.AdjacentStatusBroadcastExtended;
import module.decode.p25.message.pdu.osp.control.CallAlertExtended;
import module.decode.p25.message.pdu.osp.control.GroupAffiliationQueryExtended;
import module.decode.p25.message.pdu.osp.control.GroupAffiliationResponseExtended;
import module.decode.p25.message.pdu.osp.control.MessageUpdateExtended;
import module.decode.p25.message.pdu.osp.control.NetworkStatusBroadcastExtended;
import module.decode.p25.message.pdu.osp.control.ProtectionParameterBroadcast;
import module.decode.p25.message.pdu.osp.control.RFSSStatusBroadcastExtended;
import module.decode.p25.message.pdu.osp.control.RoamingAddressUpdateExtended;
import module.decode.p25.message.pdu.osp.control.StatusQueryExtended;
import module.decode.p25.message.pdu.osp.control.StatusUpdateExtended;
import module.decode.p25.message.pdu.osp.control.UnitRegistrationResponseExtended;
import module.decode.p25.message.pdu.osp.data.GroupDataChannelGrantExtended;
import module.decode.p25.message.pdu.osp.data.IndividualDataChannelGrantExtended;
import module.decode.p25.message.pdu.osp.voice.GroupVoiceChannelGrantExplicit;
import module.decode.p25.message.pdu.osp.voice.TelephoneInterconnectChannelGrantExplicit;
import module.decode.p25.message.pdu.osp.voice.TelephoneInterconnectChannelGrantUpdateExplicit;
import module.decode.p25.message.pdu.osp.voice.UnitToUnitAnswerRequestExplicit;
import module.decode.p25.message.pdu.osp.voice.UnitToUnitVoiceChannelGrantExtended;
import module.decode.p25.message.pdu.osp.voice.UnitToUnitVoiceChannelGrantUpdateExtended;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.PDUFormat;
import module.decode.p25.reference.Vendor;
import alias.AliasList;
import bits.BinaryMessage;
public class PDUMessageFactory
{
public static PDUMessage getMessage( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
PDUFormat format = PDUFormat.fromValue(
message.getInt( PDUMessage.FORMAT ) );
switch( format )
{
case ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL:
Vendor vendor = Vendor.fromValue(
message.getInt( PDUMessage.VENDOR_ID ) );
switch( vendor )
{
case STANDARD:
Opcode opcode = Opcode.fromValue(
message.getInt( PDUMessage.OPCODE ) );
switch( opcode )
{
case ADJACENT_STATUS_BROADCAST:
return new AdjacentStatusBroadcastExtended(
message, duid, aliasList );
case CALL_ALERT:
return new CallAlertExtended( message, duid,
aliasList );
case GROUP_AFFILIATION_QUERY:
return new GroupAffiliationQueryExtended(
message, duid, aliasList );
case GROUP_AFFILIATION_RESPONSE:
return new GroupAffiliationResponseExtended(
message, duid, aliasList );
case GROUP_DATA_CHANNEL_GRANT:
return new GroupDataChannelGrantExtended(
message, duid, aliasList );
case GROUP_VOICE_CHANNEL_GRANT:
return new GroupVoiceChannelGrantExplicit(
message, duid, aliasList );
case INDIVIDUAL_DATA_CHANNEL_GRANT:
return new IndividualDataChannelGrantExtended(
message, duid, aliasList );
case MESSAGE_UPDATE:
return new MessageUpdateExtended( message, duid,
aliasList );
case NETWORK_STATUS_BROADCAST:
return new NetworkStatusBroadcastExtended(
message, duid, aliasList );
case PROTECTION_PARAMETER_BROADCAST:
return new ProtectionParameterBroadcast(
message, duid, aliasList );
case RFSS_STATUS_BROADCAST:
return new RFSSStatusBroadcastExtended( message,
duid, aliasList );
case ROAMING_ADDRESS_UPDATE:
return new RoamingAddressUpdateExtended(
message, duid, aliasList );
case STATUS_QUERY:
return new StatusQueryExtended( message, duid,
aliasList );
case STATUS_UPDATE:
return new StatusUpdateExtended( message, duid,
aliasList );
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
return new TelephoneInterconnectChannelGrantExplicit(
message, duid, aliasList );
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT_UPDATE:
return new TelephoneInterconnectChannelGrantUpdateExplicit(
message, duid, aliasList );
case UNIT_REGISTRATION_RESPONSE:
return new UnitRegistrationResponseExtended(
message, duid, aliasList );
case UNIT_TO_UNIT_ANSWER_REQUEST:
return new UnitToUnitAnswerRequestExplicit(
message, duid, aliasList );
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT:
return new UnitToUnitVoiceChannelGrantExtended(
message, duid, aliasList );
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE:
return new UnitToUnitVoiceChannelGrantUpdateExtended(
message, duid, aliasList );
default:
break;
}
case MOTOROLA:
break;
default:
break;
}
return new PDUMessage( message, duid, aliasList );
case UNCONFIRMED_MULTI_BLOCK_TRUNKING_CONTROL:
return new PDUMessage( message, duid, aliasList );
default:
return new PDUMessage( message, duid, aliasList );
}
}
}

View File

@@ -0,0 +1,200 @@
package module.decode.p25.message.pdu;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public abstract class UnitToUnitChannelGrantExtended extends PDUMessage
implements IdentifierReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131;
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
135 };
public static final int[] SOURCE_WACN = { 160,161,162,163,164,165,166,167,
168,169,170,171,172,173,174,175,176,177,178,179 };
public static final int[] SOURCE_SYSTEM_ID = { 180,181,182,183,184,185,186,
187,188,189,190,191 };
public static final int[] SOURCE_ID = { 192,193,194,195,196,197,198,199,200,
201,202,203,204,205,206,207,208,209,210,211,212,213,214,215 };
public static final int[] TARGET_ADDRESS = { 216,217,218,219,220,221,222,
223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 };
public static final int[] TRANSMIT_IDENTIFIER = { 240,241,242,243 };
public static final int[] TRANSMIT_NUMBER = { 244,245,246,247,248,249,250,
251,252,253,254,255 };
public static final int[] RECEIVE_IDENTIFIER = { 256,257,258,259 };
public static final int[] RECEIVE_NUMBER = { 260,261,262,263,264,265,266,
267,268,269,270,271 };
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
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 IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public UnitToUnitChannelGrantExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU2( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
sb.append( " FROM ADDR:" );
sb.append( getSourceAddress() );
sb.append( " ID:" );
sb.append( getSourceID() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " WACN:" );
sb.append( getSourceWACN() );
sb.append( " SYS:" );
sb.append( getSourceSystemID() );
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
sb.append( " " + getDownlinkFrequency() );
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
sb.append( " " + getUplinkFrequency() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncrypted()
{
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 getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getSourceWACN()
{
return mMessage.getHex( SOURCE_WACN, 5 );
}
public String getSourceSystemID()
{
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveChannelIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,209 @@
package module.decode.p25.message.pdu.confirmed;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.PDUType;
import module.decode.p25.reference.Vendor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRC;
import edac.CRCP25;
public class PDUConfirmedMessage extends PDUMessage
{
public final static Logger mLog =
LoggerFactory.getLogger( PDUConfirmedMessage.class );
public static final int SEQUENCE_RESET_FLAG = 128; //SYN
public static final int[] PACKET_SEQUENCE_NUMBER = { 129,130,131 };
public static final int FINAL_FRAGMENT_FLAG = 132;
public static final int[] FRAGMENT_SEQUENCE_NUMBER = { 133,134,135 };
public static final int[] PDU_TYPE = { 176,177,178,179 };
public PDUConfirmedMessage( BinaryMessage message, AliasList aliasList )
{
super( message, DataUnitID.PDUC, aliasList );
checkCRC();
}
/**
* Constructor to support subclassing of this message. Initial construction
* of the message enables CRC checks to be calculated and message type to
* be inspected so that we can construct an accurate subclass message,
* without having to recalculate CRC checksums.
*/
protected PDUConfirmedMessage( PDUConfirmedMessage message )
{
super( message.getSourceMessage(), DataUnitID.PDUC, message.getAliasList() );
mCRC = message.getCRCResults();
}
private void checkCRC()
{
int blocks = getBlocksToFollowCount();
/* The NID and Header have already passed CRC */
mCRC = new CRC[ 2 + blocks ];
mCRC[ 0 ] = CRC.PASSED;
mCRC[ 1 ] = CRC.PASSED;
for( int x = 0; x < getBlocksToFollowCount(); x++ )
{
/* Data blocks start at 160 and every 144 thereafter */
mCRC[ x + 2 ] = CRCP25.checkCRC9( mMessage, 160 + ( x * 144 ) );
}
//TODO: check the final 4-byte end of block sequence CRC
}
/* Override for now */
public boolean isValid()
{
return true;
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( "[" + this.getClass() + "]" );
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " " );
sb.append( getDUID().getLabel() );
sb.append( " " );
sb.append( getDirection() );
sb.append( " CRC[" );
sb.append( getErrorStatus() );
sb.append( "] LLID:" );
sb.append( getLogicalLinkID() );
sb.append( " " );
sb.append( getFormat().getLabel() );
sb.append( " SAP:" );
sb.append( getServiceAccessPoint().getLabel() );
if( getVendor() != Vendor.STANDARD )
{
sb.append( " VEND:" );
sb.append( getVendor().getLabel() );
}
sb.append( " PACKET #" );
sb.append( getPacketSequenceNumber() );
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
{
sb.append( ".C" );
}
else
{
sb.append( "." );
sb.append( getFragmentSequenceNumber() );
if( isFinalFragment() )
{
sb.append( "C" );
}
}
sb.append( " BLOCKS:" );
sb.append( getBlocksToFollowCount() );
sb.append( " " );
sb.append( mMessage.toString() );
return sb.toString();
}
/**
* Packet Data Unit Type
*/
public PDUType getPDUType()
{
return PDUType.fromValue( mMessage.getInt( PDU_TYPE ), isOutbound() );
}
/**
* Number of bytes/octets contained in the message, exclusive of the data
* header.
*/
public int getOctetCount()
{
/* 16 octets per block, and 12 octets in final block */
int count = getBlocksToFollowCount() * 16 - 4;
int padding = getPadOctetCount();
/* Hack: motorola sndcp packet data control - when it says there are 15
* pad octets and only 1 data block of 12 data octets, that means there
* are more pad octets than available data and they appear to suppress
* the final padded data block containing the 12 pad octets. The data
* block count should be 2, but it says 1, so they're either not sending
* the final block, or there is an error in the block count */
if( padding > count )
{
count -= ( padding - 12 );
}
else
{
count -= padding;
}
count -= getDataHeaderOffset();
return count;
}
/**
* Indicates that the receiver should accept this packet, despite the
* apparent out-of-order packet and fragment sequence numbering. This
* indicates that something happened to the synchronization between
* the tower and the radio and now the tower commands the radio to reset
* the sequence numbers and accept this packet/fragment instead of discarding
* it as a duplicate.
*/
public boolean isSequenceReset()
{
return mMessage.get( SEQUENCE_RESET_FLAG );
}
/**
* Packet sequence number. Numbers run from 0 to 7 and will continually
* roll-over if there are more than 8 total packets.
*/
public int getPacketSequenceNumber()
{
return mMessage.getInt( PACKET_SEQUENCE_NUMBER );
}
/**
* Indicates that this packet fragment is the final fragment
*/
public boolean isFinalFragment()
{
return mMessage.get( FINAL_FRAGMENT_FLAG );
}
/**
* Packet fragment sequence number
*/
public int getFragmentSequenceNumber()
{
return mMessage.getInt( FRAGMENT_SEQUENCE_NUMBER );
}
public String toString()
{
return getMessage();
}
}

View File

@@ -0,0 +1,80 @@
package module.decode.p25.message.pdu.confirmed;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PDUConfirmedMessageFactory
{
public final static Logger mLog =
LoggerFactory.getLogger( PDUConfirmedMessage.class );
public static PDUConfirmedMessage getMessage( PDUConfirmedMessage message )
{
switch( message.getServiceAccessPoint() )
{
case ADDRESS_RESOLUTION_PROTOCOL:
break;
case CHANNEL_REASSIGNMENT:
break;
case CIRCUIT_DATA:
break;
case CIRCUIT_DATA_CONTROL:
break;
case ENCRYPTED_KEY_MANAGEMENT_MESSAGE:
break;
case ENCRYPTED_TRUNKING_CONTROL:
break;
case ENCRYPTED_USER_DATA:
break;
case EXTENDED_ADDRESS:
break;
case MR_CONFIGURATION:
break;
case MR_LOOPBACK:
break;
case MR_OUT_OF_SERVICE:
break;
case MR_PAGING:
break;
case MR_STATISTICS:
break;
case PACKET_DATA:
break;
case REGISTRATION_AND_AUTHORIZATION:
break;
/* Deliberate fall-through */
case SNDCP_PACKET_DATA_CONTROL:
case UNENCRYPTED_USER_DATA:
switch( message.getPDUType() )
{
case SN_ACTIVATE_TDS_CONTEXT_ACCEPT:
return new SNDCPActivateTDSContextAccept( message );
case SN_ACTIVATE_TDS_CONTEXT_REJECT:
return new SNDCPActivateTDSContextReject( message );
case SN_ACTIVATE_TDS_CONTEXT_REQUEST:
return new SNDCPActivateTDSContextRequest( message );
case SN_DEACTIVATE_TDS_CONTEXT_ACCEPT:
case SN_DEACTIVATE_TDS_CONTEXT_REQUEST:
return new SNDCPDeactivateTDSContext( message );
case SN_RF_CONFIRMED_DATA:
return new SNDCPUserData( message );
case SN_RF_UNCONFIRMED_DATA:
break;
default:
break;
}
break;
case SYSTEM_CONFIGURATION:
break;
case UNENCRYPTED_KEY_MANAGEMENT_MESSAGE:
break;
case UNENCRYPTED_TRUNKING_CONTROL:
break;
default:
}
return message;
}
}

View File

@@ -0,0 +1,253 @@
package module.decode.p25.message.pdu.confirmed;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.MDPConfigurationOption;
import module.decode.p25.reference.PDUType;
import module.decode.p25.reference.SNDCPActivationRejectReason;
import module.decode.p25.reference.Vendor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRC;
import edac.CRCP25;
public class SNDCPActivateTDSContextAccept extends PDUConfirmedMessage
{
public final static Logger mLog =
LoggerFactory.getLogger( SNDCPActivateTDSContextAccept.class );
/* SN-Activate TDS Context Accept */
public static final int[] NSAPI = { 180,181,182,183 };
public static final int[] PDUPM = { 184,185,186,187 };
public static final int[] READY = { 188,189,190,191 };
public static final int[] STANDBY = { 192,193,194,195 };
public static final int[] NAT = { 196,197,198,199 };
public static final int[] IP_1 = { 200,201,202,203,204,205,206,207 };
public static final int[] IP_2 = { 208,209,210,211,212,213,214,215 };
public static final int[] IP_3 = { 216,217,218,219,220,221,222,223 };
public static final int[] IP_4 = { 224,225,226,227,228,229,230,231 };
public static final int[] IPHC = { 232,233,234,235,236,237,238,239 };
public static final int[] TCPSS = { 240,241,242,243 };
public static final int[] UDPSS = { 244,245,246,247 };
public static final int[] MTU = { 248,249,250,251 };
public static final int[] UDPC = { 252,253,254,255 };
public static final int[] MDPCO = { 256,257,258,259,260,261,262,263 };
public static final int[] DATA_ACCESS_CONTROL = { 264,265,266,267,268,
269,270,271,272,273,274,275,276,277,278,279 };
public SNDCPActivateTDSContextAccept( PDUConfirmedMessage message )
{
super( message );
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " PDUC LLID:" );
sb.append( getLogicalLinkID() );
sb.append( " ACCEPT SNDCP PACKET DATA ACTIVATE " );
sb.append( getNetworkAddressType() );
sb.append( " " );
sb.append( getIPAddress() );
sb.append( " NSAPI:" );
sb.append( getNSAPI() );
sb.append( " MTU:" );
sb.append( getMaximumTransmissionUnit() );
sb.append( " CRC[" );
sb.append( getErrorStatus() );
sb.append( "]" );
sb.append( " PACKET #" );
sb.append( getPacketSequenceNumber() );
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
{
sb.append( ".C" );
}
else
{
sb.append( "." );
sb.append( getFragmentSequenceNumber() );
if( isFinalFragment() )
{
sb.append( "C" );
}
}
sb.append( " " );
return sb.toString();
}
/**
* Network Service Access Point Identifier - up to 14 NSAPI's can be
* allocated to the mobile with each NSAPI to be used for a specific
* protocol layer.
*/
public int getNSAPI()
{
return mMessage.getInt( NSAPI );
}
public int getPDUPriorityMaximum()
{
return mMessage.getInt( PDUPM );
}
public String getReadyTimer()
{
switch( mMessage.getInt( READY ) )
{
case 1:
return "1 Second";
case 2:
return "2 Seconds";
case 3:
return "4 Seconds";
case 4:
return "6 Seconds";
case 5:
return "8 Seconds";
case 6:
return "10 Seconds";
case 7:
return "15 Seconds";
case 8:
return "20 Seconds";
case 9:
return "25 Seconds";
case 10:
return "30 Seconds";
case 11:
return "60 Seconds";
case 12:
return "120 Seconds";
case 13:
return "180 Seconds";
case 14:
return "300 Seconds";
case 15:
return "Always in Ready";
}
return "UNKNOWN";
}
public String getStandbyTimer()
{
switch( mMessage.getInt( STANDBY ) )
{
case 1:
return "10 Seconds";
case 2:
return "30 Seconds";
case 3:
return "1 Minutes";
case 4:
return "5 Minutes";
case 5:
return "10 Minutes";
case 6:
return "30 Minutes";
case 7:
return "1 Hour";
case 8:
return "2 Hours";
case 9:
return "4 Hours";
case 10:
return "8 Hours";
case 11:
return "12 Hours";
case 12:
return "24 Hours";
case 13:
return "48 Hours";
case 14:
return "72 Hours";
case 15:
return "Always in Ready";
}
return "Unknown";
}
public String getNetworkAddressType()
{
return mMessage.getInt( NAT ) == 0 ? "IPV4 STATIC" : "IPV4 DYNAMIC";
}
public String getIPAddress()
{
StringBuilder sb = new StringBuilder();
sb.append( mMessage.getInt( IP_1 ) );
sb.append( "." );
sb.append( mMessage.getInt( IP_2 ) );
sb.append( "." );
sb.append( mMessage.getInt( IP_3 ) );
sb.append( "." );
sb.append( mMessage.getInt( IP_4 ) );
return sb.toString();
}
public boolean hasIPHeaderCompression()
{
return mMessage.getInt( IPHC ) == 1;
}
public boolean hasUserDataPayloadCompression()
{
return mMessage.getInt( UDPC ) == 1;
}
public int getTCPStateSlots()
{
return mMessage.getInt( TCPSS );
}
public int getUDPStateSlots()
{
return mMessage.getInt( UDPSS );
}
public String getMaximumTransmissionUnit()
{
int mtu = mMessage.getInt( MTU );
switch( mtu )
{
case 1:
return "296 BYTES";
case 2:
return "510 BYTES";
case 3:
return "1020 BYTES";
case 4:
return "1500 BYTES";
default:
return "UNK-" + mtu;
}
}
public MDPConfigurationOption getMDPConfigurationOption()
{
return MDPConfigurationOption.fromValue( mMessage.getInt( MDPCO ) );
}
public String getDataAccessControl()
{
return mMessage.getHex( DATA_ACCESS_CONTROL, 4 );
}
}

View File

@@ -0,0 +1,54 @@
package module.decode.p25.message.pdu.confirmed;
import module.decode.p25.reference.SNDCPActivationRejectReason;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SNDCPActivateTDSContextReject extends PDUConfirmedMessage
{
public final static Logger mLog =
LoggerFactory.getLogger( SNDCPActivateTDSContextReject.class );
public static final int[] NSAPI = { 180,181,182,183 };
public static final int[] REJECT_CODE = { 184,185,186,187,188,189,190,191 };
public SNDCPActivateTDSContextReject( PDUConfirmedMessage message )
{
super( message );
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " PDUC LLID:" );
sb.append( getLogicalLinkID() );
sb.append( " REJECT SNDCP PACKET DATA ACTIVATE - REASON:" );
sb.append( getReason().getLabel() );
sb.append( " CRC[" );
sb.append( getErrorStatus() );
sb.append( "] " );
sb.append( mMessage.toString() );
return sb.toString();
}
/**
* Network Service Access Point Identifier - up to 14 NSAPI's can be
* allocated to the mobile with each NSAPI to be used for a specific
* protocol layer.
*/
public int getNSAPI()
{
return mMessage.getInt( NSAPI );
}
public SNDCPActivationRejectReason getReason()
{
return SNDCPActivationRejectReason.fromValue( mMessage.getInt( REJECT_CODE ) );
}
}

View File

@@ -0,0 +1,149 @@
package module.decode.p25.message.pdu.confirmed;
import module.decode.p25.reference.MDPConfigurationOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SNDCPActivateTDSContextRequest extends PDUConfirmedMessage
{
public final static Logger mLog =
LoggerFactory.getLogger( SNDCPActivateTDSContextRequest.class );
public static final int[] SNDCP_VERSION = { 180,181,182,183 };
public static final int[] NSAPI = { 184,185,186,187 };
public static final int[] NAT = { 188,189,190,191 };
public static final int[] IP_1 = { 192,193,194,195,196,197,198,199 };
public static final int[] IP_2 = { 200,201,202,203,204,205,206,207 };
public static final int[] IP_3 = { 208,209,210,211,212,213,214,215 };
public static final int[] IP_4 = { 216,217,218,219,220,221,222,223 };
public static final int[] DSUT = { 224,225,226,227 };
public static final int[] UDPC = { 228,229,230,231 };
public static final int[] IPHC = { 232,233,234,235,236,237,238,239 };
public static final int[] TCPSS = { 240,241,242,243 };
public static final int[] UDPSS = { 244,245,246,247 };
public static final int[] MDPCO = { 248,249,250,251,252,253,254,255 };
public SNDCPActivateTDSContextRequest( PDUConfirmedMessage message )
{
super( message );
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " PDUC LLID:" );
sb.append( getLogicalLinkID() );
sb.append( " REQUEST SNDCP PACKET DATA ACTIVATE " );
sb.append( getNetworkAddressType() );
sb.append( " " );
sb.append( getIPAddress() );
sb.append( " NSAPI:" );
sb.append( getNSAPI() );
sb.append( " CRC[" );
sb.append( getErrorStatus() );
sb.append( "]" );
sb.append( " PACKET #" );
sb.append( getPacketSequenceNumber() );
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
{
sb.append( ".C" );
}
else
{
sb.append( "." );
sb.append( getFragmentSequenceNumber() );
if( isFinalFragment() )
{
sb.append( "C" );
}
}
sb.append( " " );
return sb.toString();
}
/**
* SNDCP Version: 1 = P25 SNDCP Version 1
*/
public int getSNDCPVersion()
{
return mMessage.getInt( SNDCP_VERSION );
}
/**
* Network Service Access Point Identifier - up to 14 NSAPI's can be
* allocated to the mobile with each NSAPI to be used for a specific
* protocol layer.
*/
public int getNSAPI()
{
return mMessage.getInt( NSAPI );
}
public String getNetworkAddressType()
{
return mMessage.getInt( NAT ) == 0 ? "IPV4 STATIC" : "IPV4 DYNAMIC";
}
public String getIPAddress()
{
StringBuilder sb = new StringBuilder();
sb.append( mMessage.getInt( IP_1 ) );
sb.append( "." );
sb.append( mMessage.getInt( IP_2 ) );
sb.append( "." );
sb.append( mMessage.getInt( IP_3 ) );
sb.append( "." );
sb.append( mMessage.getInt( IP_4 ) );
return sb.toString();
}
public String getDataSubscriberUnitType()
{
switch( mMessage.getInt( DSUT ) )
{
case 0:
return "DATA ONLY MRC";
case 1:
return "DATA AND VOICE MRC";
}
return "UNKNOWN";
}
public boolean hasIPHeaderCompression()
{
return mMessage.getInt( IPHC ) == 1;
}
public boolean hasUserDataPayloadCompression()
{
return mMessage.getInt( UDPC ) == 1;
}
public int getTCPStateSlots()
{
return mMessage.getInt( TCPSS );
}
public int getUDPStateSlots()
{
return mMessage.getInt( UDPSS );
}
public MDPConfigurationOption getMDPConfigurationOption()
{
return MDPConfigurationOption.fromValue( mMessage.getInt( MDPCO ) );
}
}

View File

@@ -0,0 +1,61 @@
package module.decode.p25.message.pdu.confirmed;
import module.decode.p25.reference.PDUType;
import module.decode.p25.reference.SNDCPActivationRejectReason;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SNDCPDeactivateTDSContext extends PDUConfirmedMessage
{
public final static Logger mLog =
LoggerFactory.getLogger( SNDCPDeactivateTDSContext.class );
public static final int[] NSAPI = { 180,181,182,183 };
public static final int[] DEACTIVATION_TYPE = { 184,185,186,187,188,189,
190,191 };
public SNDCPDeactivateTDSContext( PDUConfirmedMessage message )
{
super( message );
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " PDUC LLID:" );
sb.append( getLogicalLinkID() );
sb.append( " REQUEST SNDCP PACKET DATA DEACTIVATE " );
sb.append( getDeactivationType() );
sb.append( " CRC[" );
sb.append( getErrorStatus() );
sb.append( "] " );
return sb.toString();
}
/**
* Network Service Access Point Identifier - up to 14 NSAPI's can be
* allocated to the mobile with each NSAPI to be used for a specific
* protocol layer.
*/
public int getNSAPI()
{
return mMessage.getInt( NSAPI );
}
public String getDeactivationType()
{
if( getPDUType() == PDUType.SN_DEACTIVATE_TDS_CONTEXT_REQUEST )
{
return mMessage.getInt( DEACTIVATION_TYPE ) == 0 ?
"ALL NSAPIS" : "THIS NSAPI";
}
return null;
}
}

View File

@@ -0,0 +1,356 @@
package module.decode.p25.message.pdu.confirmed;
import module.decode.p25.reference.IPHeaderCompression;
import module.decode.p25.reference.IPProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SNDCPUserData extends PDUConfirmedMessage
{
public final static Logger mLog =
LoggerFactory.getLogger( SNDCPUserData.class );
public static final int DATA_BLOCK_START = 176;
public static final int[] NSAPI = { 180,181,182,183 };
public static final int[] PCOMP = { 184,185,186,187 };
public static final int[] DCOMP = { 188,189,190,191 };
/* IP Packet Header */
public static final int[] IP_VERSION = { 192,193,194,195 };
public static final int[] IHL = { 196,197,198,199 };
public static final int[] DSCP = { 200,201,202,203,204,205 };
public static final int[] ECN = { 206,207 };
public static final int[] TOTAL_LENGTH = { 208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223 };
public static final int[] IDENTIFICATION = { 224,225,226,227,228,229,230,231,
232,233,234,235,236,237,238,239 };
public static final int[] FLAGS = { 240,241,242 };
public static final int[] FRAGMENT_OFFSET = { 243,244,245,246,247,248,249,
250,251,252,253,254,255 };
public static final int[] TTL = { 256,257,258,259,260,261,262,263 };
public static final int[] PROTOCOL = { 264,265,266,267,268,269,270,271 };
public static final int[] HEADER_CHECKSUM = { 272,273,274,275,276,277,278,
279,280,281,282,283,284,285,286,287 };
public static final int[] SOURCE_IP_1 = { 288,289,290,291,292,293,294,295 };
public static final int[] SOURCE_IP_2 = { 296,297,298,299,300,301,302,303 };
public static final int[] BLOCK_SERIAL_2 = { 304,305,306,307,308,309,310 };
public static final int[] BLOCK_CRC9_2 = { 311,312,313,314,315,316,317,318,
319 };
public static final int[] SOURCE_IP_3 = { 320,321,322,323,324,325,326,327 };
public static final int[] SOURCE_IP_4 = { 328,329,330,331,332,333,334,335 };
public static final int[] DESTINATION_IP_1 = { 336,337,338,339,340,341,342,343 };
public static final int[] DESTINATION_IP_2 = { 344,345,346,347,348,349,350,351 };
public static final int[] DESTINATION_IP_3 = { 352,353,354,355,356,357,358,359 };
public static final int[] DESTINATION_IP_4 = { 360,361,362,363,364,365,366,367 };
public static final int IP_DATA_START = 368;
/* User Datagram Protocol */
public static final int[] UDP_SOURCE_PORT = { 368,369,370,371,372,373,374,
375 };
public static final int[] UDP_DESTINATION_PORT = { 376,377,378,379,380,381,
382,383 };
public static final int[] UDP_LENGTH = { 384,385,386,387,388,389,390,391,
392,393,394,395,396,397,398,399 };
public static final int[] UDP_CHECKSUM = { 400,401,402,403,404,405,406,407,
408,409,410,411,412,413,414,415 };
public static final int UDP_DATA_START = 416;
public SNDCPUserData( PDUConfirmedMessage message )
{
super( message );
}
@Override
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " PDUC LLID:" );
sb.append( getLogicalLinkID() );
sb.append( " SNDCP NSAPI:" );
sb.append( getNSAPI() );
sb.append( " " );
IPProtocol protocol = getIPProtocol();
sb.append( protocol.getLabel() );
sb.append( "/IP" );
sb.append( " FM:" );
sb.append( getSourceIPAddress() );
if( protocol == IPProtocol.UDP )
{
sb.append( ":" );
sb.append( getUDPSourcePort() );
}
sb.append( " TO:" );
sb.append( getDestinationIPAddress() );
if( protocol == IPProtocol.UDP )
{
sb.append( ":" );
sb.append( getUDPDestinationPort() );
}
sb.append( " DATA:" );
sb.append( getPayload() );
sb.append( " CRC[" );
sb.append( getErrorStatus() );
sb.append( "]" );
sb.append( " PACKET #" );
sb.append( getPacketSequenceNumber() );
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
{
sb.append( ".C" );
}
else
{
sb.append( "." );
sb.append( getFragmentSequenceNumber() );
if( isFinalFragment() )
{
sb.append( "C" );
}
}
sb.append( " " );
sb.append( mMessage.toString() );
return sb.toString();
}
/**
* Network Service Access Point Identifier - up to 14 NSAPI's can be
* allocated to the mobile with each NSAPI to be used for a specific
* protocol layer.
*/
public int getNSAPI()
{
return mMessage.getInt( NSAPI );
}
public IPHeaderCompression getIPHeaderCompressionState()
{
return IPHeaderCompression.fromValue( mMessage.getInt( PCOMP ) );
}
/**
* No enum values were defined for this
*/
public boolean hasUserDataCompression()
{
return mMessage.getInt( DCOMP ) > 0;
}
/**
* IP Version - should always be 4 (IPV4)
*/
public int getIPVersion()
{
return mMessage.getInt( IP_VERSION );
}
/**
* IP packet header length in 32-bit words
*/
public int getInternetHeaderLength()
{
return mMessage.getInt( IHL );
}
/**
* IP packet DSCP
*/
public int getDifferentiatedServicesCodePoint()
{
return mMessage.getInt( DSCP );
}
/**
* IP packet ECN
*/
public int getExplicitCongestionNotification()
{
return mMessage.getInt( ECN );
}
/**
* IP packet size in bytes, including header and data
*/
public int getTotalLength()
{
return mMessage.getInt( TOTAL_LENGTH );
}
/**
* IP packet identification
*/
public int getIdentification()
{
return mMessage.getInt( IDENTIFICATION );
}
/**
* IP packet flags. 0-Reserved, 1-Don't Fragment, 2-More Fragments
*/
public int getFlags()
{
return mMessage.getInt( FLAGS );
}
public boolean isFragment()
{
return getFlags() > 0;
}
/**
* IP packet - identifies the offset value in 8-byte blocks (64-bit blocks)
* for this packet fragment from the beginning.
*/
public int getFragmentOffset()
{
return mMessage.getInt( FRAGMENT_OFFSET );
}
/**
* IP packet time (hops) to live
*/
public int getTimeToLive()
{
return mMessage.getInt( TTL );
}
/**
* Identifies the IP protocol carried by the IP packet
*/
public IPProtocol getIPProtocol()
{
return IPProtocol.fromValue( mMessage.getInt( PROTOCOL ) );
}
/**
* Source IPV4 address
*/
public String getSourceIPAddress()
{
StringBuilder sb = new StringBuilder();
sb.append( mMessage.getInt( SOURCE_IP_1 ) );
sb.append( "." );
sb.append( mMessage.getInt( SOURCE_IP_2 ) );
sb.append( "." );
sb.append( mMessage.getInt( SOURCE_IP_3 ) );
sb.append( "." );
sb.append( mMessage.getInt( SOURCE_IP_4 ) );
return sb.toString();
}
/**
* Destination IPV4 address
*/
public String getDestinationIPAddress()
{
StringBuilder sb = new StringBuilder();
sb.append( mMessage.getInt( DESTINATION_IP_1 ) );
sb.append( "." );
sb.append( mMessage.getInt( DESTINATION_IP_2 ) );
sb.append( "." );
sb.append( mMessage.getInt( DESTINATION_IP_3 ) );
sb.append( "." );
sb.append( mMessage.getInt( DESTINATION_IP_4 ) );
return sb.toString();
}
/**
* UDP source port
*/
public int getUDPSourcePort()
{
return mMessage.getInt( UDP_SOURCE_PORT );
}
/**
* UDP destination port
*/
public int getUDPDestinationPort()
{
return mMessage.getInt( UDP_DESTINATION_PORT );
}
/**
* UDP data payload size in bytes
*/
public int getUDPDataLength()
{
return mMessage.getInt( UDP_LENGTH );
}
/**
* Hex string representation of the packet data, including packet header
* data if present.
*/
public String getPayload()
{
StringBuilder sb = new StringBuilder();
/* Adjust for PDU header (2 bytes) plus IP Packet header (20 bytes) */
int start = 22;
if( getIPProtocol() == IPProtocol.UDP )
{
/* Adjust for UDP header (8 bytes) */
start = 30;
}
int spacingCounter = 0;
/* Append octets inserting a space between each 32-bit value */
int octets = getOctetCount() + getDataHeaderOffset();
for( int x = start; x < octets; x++ )
{
sb.append( getPacketOctet( x ) );
spacingCounter++;
if( spacingCounter >= 4 )
{
sb.append( " " );
spacingCounter = 0;
}
}
return sb.toString();
}
/**
* Returns the octet identified by the 0-indexed 'octet' argument location.
* If there is a Data Header Offset, the 0 index points to the first octet
* of the data header. Otherwise, the 0 index points to the first octet
* of the packet. You must account for the data header offset when
* specifying the octet.
*/
public String getPacketOctet( int octet )
{
int block = (int)( octet / 16 );
int offset = octet % 16;
int start = DATA_BLOCK_START + ( block * 144 ) + ( offset * 8 );
return mMessage.getHex( start, start + 7, 2 );
}
}

View File

@@ -0,0 +1,161 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class AdjacentStatusBroadcastExtended extends PDUMessage
implements IdentifierReceiver
{
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,
109,110,111 };
public static final int[] RF_SUBSYSTEM_ID = { 128,129,130,131,132,133,134,
135 };
public static final int[] SITE_ID = { 136,137,138,139,140,141,142,143 };
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 };
public static final int[] TRANSMIT_CHANNEL = { 164,165,166,167,168,169,170,
171,172,173,174,175 };
public static final int[] RECEIVE_IDENTIFIER = { 176,177,178,179 };
public static final int[] RECEIVE_CHANNEL = { 180,181,182,183,184,185,186,
187,188,189,190,191 };
public static final int[] SYSTEM_SERVICE_CLASS = { 192,193,194,195,196,197,
198,199 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 IBandIdentifier mTransmitIdentifierProvider;
private IBandIdentifier mReceiveIdentifierProvider;
public AdjacentStatusBroadcastExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.ADJACENT_STATUS_BROADCAST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYS:" + getSystemID() );
sb.append( " RFSS:" + getRFSubsystemID() );
sb.append( " SITE:" + getSiteID() );
sb.append( " CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel() );
sb.append( " DN:" + getDownlinkFrequency() );
sb.append( " " + getTransmitIdentifier() + "-" + getTransmitChannel() );
sb.append( " UP:" + getUplinkFrequency() );
sb.append( " SYS SVC CLASS:" +
SystemService.toString( getSystemServiceClass() ) );
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( RF_SUBSYSTEM_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 int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannel()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierProvider, getTransmitChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierProvider, getReceiveChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitIdentifier() )
{
mTransmitIdentifierProvider = message;
}
if( identifier == getReceiveIdentifier() )
{
mReceiveIdentifierProvider = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitIdentifier();
idens[ 1 ] = getReceiveIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,81 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class CallAlertExtended extends PDUMessage
{
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] WACN = { 128,129,130,131,132,133,134,135,136,137,
138,139,140,141,142,143,160,161,162,163 };
public static final int[] SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
173,174,175 };
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 };
public CallAlertExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.CALL_ALERT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " FROM:" );
sb.append( getSourceID() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " WACN:" );
sb.append( getWACN() );
sb.append( " SYS:" );
sb.append( getSystemID() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
}

View File

@@ -0,0 +1,81 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class GroupAffiliationQueryExtended extends PDUMessage
{
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] WACN = { 128,129,130,131,132,133,134,135,136,137,
138,139,140,141,142,143,160,161,162,163 };
public static final int[] SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
173,174,175 };
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 };
public GroupAffiliationQueryExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.GROUP_AFFILIATION_QUERY.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " FROM:" );
sb.append( getSourceID() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " WACN:" );
sb.append( getWACN() );
sb.append( " SYS:" );
sb.append( getSystemID() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
}

View File

@@ -0,0 +1,132 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Response;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class GroupAffiliationResponseExtended extends PDUMessage
{
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SOURCE_WACN = { 128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143,160,161,162,163 };
public static final int[] SOURCE_SYSTEM_ID = { 164,165,166,167,168,169,170,
171,172,173,174,175 };
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
public static final int[] GROUP_WACN = { 200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,215,216,217,218,219 };
public static final int[] GROUP_SYSTEM_ID = { 220,221,222,223,224,225,226,
227,228,229,230,231 };
public static final int[] GROUP_ID = { 232,233,234,235,236,237,238,239,240,
241,242,243,244,245,246,247 };
public static final int[] ANNOUNCEMENT_GROUP_ID = { 248,249,250,251,252,253,
254,255,256,257,258,259,260,261,262,263 };
public static final int[] GROUP_AFFILIATION_RESPONSE_VALUE = { 270,271 };
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
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 };
public GroupAffiliationResponseExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.GROUP_AFFILIATION_RESPONSE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( "AFFILIATION:" );
sb.append( getResponse().name() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " FROM:" );
sb.append( getSourceID() );
sb.append( " WACN:" );
sb.append( getSourceWACN() );
sb.append( " SYS:" );
sb.append( getSourceSystemID() );
sb.append( " GROUP:" );
sb.append( getGroupID() );
sb.append( " WACN:" );
sb.append( getGroupWACN() );
sb.append( " SYS:" );
sb.append( getGroupSystemID() );
sb.append( " ANNOUNCEMENT GROUP:" );
sb.append( getAnnouncementGroupID() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceWACN()
{
return mMessage.getHex( SOURCE_WACN, 5 );
}
public String getSourceSystemID()
{
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getGroupWACN()
{
return mMessage.getHex( GROUP_WACN, 5 );
}
public String getGroupSystemID()
{
return mMessage.getHex( GROUP_SYSTEM_ID, 3 );
}
public String getGroupID()
{
return mMessage.getHex( GROUP_ID, 4 );
}
public String getAnnouncementGroupID()
{
return mMessage.getHex( GROUP_ID, 4 );
}
public Response getResponse()
{
return Response.fromValue(
mMessage.getInt( GROUP_AFFILIATION_RESPONSE_VALUE ) );
}
}

View File

@@ -0,0 +1,91 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class MessageUpdateExtended extends PDUMessage
{
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SOURCE_WACN = { 128,129,130,131,132,133,134,135,136,137,
138,139,140,141,142,143,160,161,162,163 };
public static final int[] SOURCE_SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
173,174,175 };
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
public static final int[] SHORT_DATA_MESSAGE = { 200,201,202,203,204,205,
206,207,208,209,210,211,212,213,214,215 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 };
public MessageUpdateExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.CALL_ALERT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " MSG:" );
sb.append( getShortDataMessage() );
sb.append( " FROM:" );
sb.append( getSourceID() );
sb.append( " WACN:" );
sb.append( getSourceWACN() );
sb.append( " SYS:" );
sb.append( getSourceSystemID() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceWACN()
{
return mMessage.getHex( SOURCE_WACN, 5 );
}
public String getSourceSystemID()
{
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getShortDataMessage()
{
return mMessage.getHex( SHORT_DATA_MESSAGE, 4 );
}
}

View File

@@ -0,0 +1,160 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.P25NetworkCallsign;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class NetworkStatusBroadcastExtended extends PDUMessage
implements IdentifierReceiver
{
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,
109,110,111 };
public static final int[] WACN = { 160,161,162,163,164,165,166,167,168,169,
170,171,172,173,174,175,176,177,178,179 };
public static final int[] TRANSMIT_IDENTIFIER = { 184,185,186,187 };
public static final int[] TRANSMIT_CHANNEL = { 188,189,190,191,192,193,194,
195,196,197,198,199 };
public static final int[] RECEIVE_IDENTIFIER = { 200,201,202,203 };
public static final int[] RECEIVE_CHANNEL = { 204,205,206,207,208,209,210,
211,212,213,214,215 };
public static final int[] SYSTEM_SERVICE_CLASS = { 216,217,218,219,220,221,
222,223 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public NetworkStatusBroadcastExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.NETWORK_STATUS_BROADCAST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " WACN:" + getWACN() );
sb.append( " SYS:" + getSystemID() );
sb.append( " CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel() );
sb.append( " DN:" + getDownlinkFrequency() );
sb.append( " " + getTransmitIdentifier() + "-" + getTransmitChannel() );
sb.append( " UP:" + getUplinkFrequency() );
sb.append( " SYS SVC CLASS:" +
SystemService.toString( getSystemServiceClass() ) );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getNetworkCallsign()
{
return P25NetworkCallsign.getCallsign( mMessage.getInt( WACN ),
mMessage.getInt( SYSTEM_ID ) );
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannel()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannel()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitIdentifier();
idens[ 1 ] = getReceiveIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,113 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Encryption;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class ProtectionParameterBroadcast extends PDUMessage
{
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] ENCRYPTION_TYPE = { 128,129,130,131,132,133,134,
135 };
public static final int[] ALGORITHM_ID = { 136,137,138,139,140,141,142,143 };
public static final int[] KEY_ID = { 160,161,162,163,164,165,166,167,168,
169,170,171,172,173,174,175 };
public static final int[] INBOUND_INITIALIZATION_VECTOR_A = { 176,177,178,
179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,
197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,
215 };
public static final int[] INBOUND_INITIALIZATION_VECTOR_B = { 216,217,218,
219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,
237,238,239,240,241,242,243,244,245,246,247 };
public static final int[] OUTBOUND_INITIALIZATION_VECTOR_A = { 248,249,250,
251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,
269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,
287 };
public static final int[] OUTBOUND_INITIALIZATION_VECTOR_B = { 288,289,290,
291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,
309,310,311,312,313,314,315,316,317,318,319 };
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
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 };
public ProtectionParameterBroadcast( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.PROTECTION_PARAMETER_BROADCAST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " ENCRYPTION:" );
sb.append( getEncryptionType().name() );
sb.append( " ALGORITHM ID:" );
sb.append( getAlgorithmID() );
sb.append( " KEY ID:" );
sb.append( getKeyID() );
sb.append( " INBOUND IV:" );
sb.append( getInboundInitializationVector() );
sb.append( " OUTBOUND IV:" );
sb.append( getOutboundInitializationVector() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public Encryption getEncryptionType()
{
return Encryption.fromValue( mMessage.getInt( ENCRYPTION_TYPE ) );
}
public String getAlgorithmID()
{
return mMessage.getHex( ALGORITHM_ID, 2 );
}
public String getKeyID()
{
return mMessage.getHex( KEY_ID, 4 );
}
public String getInboundInitializationVector()
{
return mMessage.getHex( INBOUND_INITIALIZATION_VECTOR_A, 10 ) +
mMessage.getHex( INBOUND_INITIALIZATION_VECTOR_B, 8 );
}
public String getOutboundInitializationVector()
{
return mMessage.getHex( OUTBOUND_INITIALIZATION_VECTOR_A, 10 ) +
mMessage.getHex( OUTBOUND_INITIALIZATION_VECTOR_B, 8 );
}
}

View File

@@ -0,0 +1,164 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class RFSSStatusBroadcastExtended extends PDUMessage
implements IdentifierReceiver
{
public static final int[] LRA = { 88,89,90,91,92,93,94,95 };
public static final int ACTIVE_NETWORK_CONNECTION_INDICATOR = 99;
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108,
109,110,111 };
public static final int[] RFSS_ID = { 160,161,162,163,164,165,166,167 };
public static final int[] SITE_ID = { 168,169,170,171,172,173,174,175 };
public static final int[] TRANSMIT_IDENTIFIER = { 184,185,186,187 };
public static final int[] TRANSMIT_CHANNEL = { 188,189,190,191,192,193,194,
195,196,197,198,199 };
public static final int[] RECEIVE_IDENTIFIER = { 200,201,202,203 };
public static final int[] RECEIVE_CHANNEL = { 204,205,206,207,208,209,210,
211,212,213,214,215 };
public static final int[] SYSTEM_SERVICE_CLASS = { 216,217,218,219,220,221,
222,223 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public RFSSStatusBroadcastExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.NETWORK_STATUS_BROADCAST.getDescription();
}
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( " CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel() );
sb.append( " DN:" + getDownlinkFrequency() );
sb.append( " " + getTransmitIdentifier() + "-" + getTransmitChannel() );
sb.append( " UP:" + getUplinkFrequency() );
sb.append( " SYS SVC CLASS:" +
SystemService.toString( getSystemServiceClass() ) );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public boolean hasActiveNetworkConnection()
{
return mMessage.get( ACTIVE_NETWORK_CONNECTION_INDICATOR );
}
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 getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannel()
{
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public int getReceiveIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannel()
{
return mMessage.getInt( RECEIVE_CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitIdentifier();
idens[ 1 ] = getReceiveIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,269 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.P25MessageFramer;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class RoamingAddressUpdateExtended extends PDUMessage
{
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int LAST_MESSAGE_INDICATOR = 128;
public static final int[] MESSAGE_SEQUENCE_NUMBER = { 132,133,134,135 };
public static final int[] WACN_A = { 136,137,138,139,140,141,142,143,160,
161,162,163,164,165,166,167,168,169,170,171 };
public static final int[] SYSTEM_ID_A = { 172,173,174,175,176,177,178,179,
180,181,182,183 };
public static final int[] SOURCE_ID_FORMAT_1 = { 184,185,186,187,188,189,
190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207 };
public static final int[] WACN_B = { 184,185,186,187,188,189,190,191,192,
193,194,195,196,197,198,199,200,201,202,203 };
public static final int[] SYSTEM_ID_B = { 204,205,206,207,208,209,210,211,
212,213,214,215 };
public static final int[] WACN_C = { 216,217,218,219,220,221,222,223,224,
225,226,227,228,229,230,231,232,233,234,235 };
public static final int[] SYSTEM_ID_C = { 236,237,238,239,240,241,242,243,
244,245,246,247 };
public static final int[] WACN_D = { 248,249,250,251,252,253,254,255,256,
257,258,259,260,261,262,263,264,265,266,267 };
public static final int[] SYSTEM_ID_D = { 268,269,270,271,272,273,274,275,
276,277,278,279 };
public static final int[] SOURCE_ID_FORMAT_2 = { 280,281,282,283,284,285,
286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303 };
public static final int[] WACN_E = { 280,281,282,283,284,285,
286,287,288,289,290,291,292,293,294,295,296,297,298,299 };
public static final int[] SYSTEM_ID_E = { 300,301,302,303,304,305,306,307,
308,309,310,311 };
public static final int[] WACN_F = { 312,313,314,315,316,317,318,319,320,
321,322,323,324,325,326,327,328,329,330,331 };
public static final int[] SYSTEM_ID_F = { 332,333,334,335,336,337,338,339,
340,341,342,343 };
public static final int[] WACN_G = { 344,345,346,347,348,349,350,351,352,
353,354,355,356,357,358,359,360,361,362,363 };
public static final int[] SYSTEM_ID_G = { 364,365,366,367,368,369,370,371,
372,373,374,375 };
public static final int[] SOURCE_ID_FORMAT_3 = { 376,377,378,379,380,381,
382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399 };
public static final int[] MULTIPLE_BLOCK_CRC_FORMAT_1 = { 224,225,226,227,
228,229,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 };
public static final int[] MULTIPLE_BLOCK_CRC_FORMAT_2 = { 320,321,322,323,
324,325,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 };
public static final int[] MULTIPLE_BLOCK_CRC_FORMAT_3 = { 416,417,418,419,
420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,
438,439,440,441,442,443,444,445,446,447 };
private enum Format{ FORMAT_1, FORMAT_2, FORMAT_3 };
private Format mFormat;
public RoamingAddressUpdateExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
if( mMessage.size() == P25MessageFramer.PDU2_BEGIN )
{
mFormat = Format.FORMAT_1;
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
else if( mMessage.size() == P25MessageFramer.PDU3_BEGIN )
{
mFormat = Format.FORMAT_2;
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU2( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
else if( mMessage.size() == P25MessageFramer.PDU3_DECODED_END )
{
mFormat = Format.FORMAT_3;
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU3( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
else
{
mFormat = Format.FORMAT_1;
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
}
@Override
public String getEventType()
{
return Opcode.ROAMING_ADDRESS_UPDATE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " ROAMING ADDRESS STACK FROM:" );
sb.append( getSourceID() );
if( isLastBlock() )
{
sb.append( " LAST BLOCK" );
}
sb.append( "MSG SEQ:" );
sb.append( getMessageSequenceNumber() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " WACN A:" + getWACNA() );
sb.append( " SYS A:" + getSystemIDA() );
if( isFormat2() )
{
sb.append( " WACN B:" + getWACNB() );
sb.append( " SYS B:" + getSystemIDB() );
sb.append( " WACN C:" + getWACNC() );
sb.append( " SYS C:" + getSystemIDC() );
sb.append( " WACN D:" + getWACND() );
sb.append( " SYS D:" + getSystemIDD() );
}
if( isFormat3() )
{
sb.append( " WACN E:" + getWACNE() );
sb.append( " SYS E:" + getSystemIDE() );
sb.append( " WACN F:" + getWACNF() );
sb.append( " SYS F:" + getSystemIDF() );
sb.append( " WACN G:" + getWACNG() );
sb.append( " SYS G:" + getSystemIDG() );
}
return sb.toString();
}
public boolean isLastBlock()
{
return mMessage.get( LAST_MESSAGE_INDICATOR );
}
public int getMessageSequenceNumber()
{
return mMessage.getInt( MESSAGE_SEQUENCE_NUMBER );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getWACNA()
{
return mMessage.getHex( WACN_A, 5 );
}
public String getSystemIDA()
{
return mMessage.getHex( SYSTEM_ID_A, 3 );
}
public String getWACNB()
{
return isFormat2() ? mMessage.getHex( WACN_B, 5 ) : null;
}
public String getSystemIDB()
{
return isFormat2() ? mMessage.getHex( SYSTEM_ID_B, 3 ) : null;
}
public String getWACNC()
{
return isFormat2() ? mMessage.getHex( WACN_C, 5 ) : null;
}
public String getSystemIDC()
{
return isFormat2() ? mMessage.getHex( SYSTEM_ID_C, 3 ) : null;
}
public String getWACND()
{
return isFormat2() ? mMessage.getHex( WACN_D, 5 ) : null;
}
public String getSystemIDD()
{
return isFormat2() ? mMessage.getHex( SYSTEM_ID_D, 3 ) : null;
}
public String getWACNE()
{
return isFormat3() ? mMessage.getHex( WACN_E, 5 ) : null;
}
public String getSystemIDE()
{
return isFormat3() ? mMessage.getHex( SYSTEM_ID_E, 3 ) : null;
}
public String getWACNF()
{
return isFormat3() ? mMessage.getHex( WACN_F, 5 ) : null;
}
public String getSystemIDF()
{
return isFormat3() ? mMessage.getHex( SYSTEM_ID_F, 3 ) : null;
}
public String getWACNG()
{
return isFormat3() ? mMessage.getHex( WACN_G, 5 ) : null;
}
public String getSystemIDG()
{
return isFormat3() ? mMessage.getHex( SYSTEM_ID_G, 3 ) : null;
}
public String getSourceID()
{
switch( mFormat )
{
case FORMAT_1:
return mMessage.getHex( SOURCE_ID_FORMAT_1, 6 );
case FORMAT_2:
return mMessage.getHex( SOURCE_ID_FORMAT_2, 6 );
case FORMAT_3:
return mMessage.getHex( SOURCE_ID_FORMAT_2, 6 );
}
return null;
}
public boolean isFormat2()
{
return mFormat != Format.FORMAT_3;
}
public boolean isFormat3()
{
return mFormat == Format.FORMAT_3;
}
}

View File

@@ -0,0 +1,81 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class StatusQueryExtended extends PDUMessage
{
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SOURCE_WACN = { 128,129,130,131,132,133,134,135,136,137,
138,139,140,141,142,143,160,161,162,163 };
public static final int[] SOURCE_SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
173,174,175 };
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 };
public StatusQueryExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.STATUS_QUERY.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " FROM:" );
sb.append( getSourceID() );
sb.append( " WACN:" );
sb.append( getSourceWACN() );
sb.append( " SYS:" );
sb.append( getSourceSystemID() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceWACN()
{
return mMessage.getHex( SOURCE_WACN, 5 );
}
public String getSourceSystemID()
{
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
}

View File

@@ -0,0 +1,97 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class StatusUpdateExtended extends PDUMessage
{
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SOURCE_WACN = { 128,129,130,131,132,133,134,135,136,137,
138,139,140,141,142,143,160,161,162,163 };
public static final int[] SOURCE_SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
173,174,175 };
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
public static final int[] UNIT_STATUS = { 200,201,202,203,204,205,206,207 };
public static final int[] USER_STATUS = { 208,209,210,211,212,213,214,215 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 };
public StatusUpdateExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.STATUS_UPDATE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " FROM:" );
sb.append( getSourceID() );
sb.append( " WACN:" );
sb.append( getSourceWACN() );
sb.append( " SYS:" );
sb.append( getSourceSystemID() );
sb.append( " STATUS USER:" + getUserStatus() );
sb.append( " UNIT:" + getUnitStatus() );
return sb.toString();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public String getSourceWACN()
{
return mMessage.getHex( SOURCE_WACN, 5 );
}
public String getSourceSystemID()
{
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getUserStatus()
{
return mMessage.getHex( USER_STATUS, 2 );
}
public String getUnitStatus()
{
return mMessage.getHex( UNIT_STATUS, 2 );
}
}

View File

@@ -0,0 +1,99 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Response;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class UnitRegistrationResponseExtended extends PDUMessage
{
public static final int[] ASSIGNED_SOURCE_ADDRESS = { 88,89,90,91,92,
93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] WACN = { 128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143,160,161,162,163 };
public static final int[] SYSTEM_ID = { 164,165,166,167,168,169,170,
171,172,173,174,175 };
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
public static final int[] SOURCE_ADDRESS = { 200,201,202,203,204,205,206,
207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223 };
public static final int[] UNIT_REGISTRATION_RESPONSE_VALUE = { 230,231 };
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
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 };
public UnitRegistrationResponseExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.UNIT_REGISTRATION_RESPONSE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( "REGISTRATION:" );
sb.append( getResponse().name() );
sb.append( " SRC ID:" );
sb.append( getSourceID() );
sb.append( " ADDR:" );
sb.append( getSourceAddress() );
sb.append( " WACN:" );
sb.append( getWACN() );
sb.append( " SYS:" );
sb.append( getSystemID() );
return sb.toString();
}
public String getAssignedSourceAddress()
{
return mMessage.getHex( ASSIGNED_SOURCE_ADDRESS, 6 );
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
public Response getResponse()
{
return Response.fromValue(
mMessage.getInt( UNIT_REGISTRATION_RESPONSE_VALUE ) );
}
}

View File

@@ -0,0 +1,179 @@
package module.decode.p25.message.pdu.osp.data;
import java.util.Date;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class GroupDataChannelGrantExtended extends PDUMessage
implements IdentifierReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131;
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
135 };
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 };
public static final int[] TRANSMIT_NUMBER = { 164,165,166,167,168,169,170,
171,172,173,174,175 };
public static final int[] RECEIVE_IDENTIFIER = { 176,177,178,179 };
public static final int[] RECEIVE_NUMBER = { 180,181,182,183,184,185,186,
187,188,189,190,191 };
public static final int[] GROUP_ADDRESS = { 192,193,194,195,196,197,198,199,
200,201,202,203,204,205,206,207 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public GroupDataChannelGrantExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
sb.append( " FROM:" );
sb.append( getSourceAddress() );
sb.append( " TO:" );
sb.append( getGroupAddress() );
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
sb.append( " " + getDownlinkFrequency() );
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
sb.append( " " + getUplinkFrequency() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncrypted()
{
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 getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveChannelIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,25 @@
package module.decode.p25.message.pdu.osp.data;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.UnitToUnitChannelGrantExtended;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class IndividualDataChannelGrantExtended
extends UnitToUnitChannelGrantExtended
implements IdentifierReceiver
{
public IndividualDataChannelGrantExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.INDIVIDUAL_DATA_CHANNEL_GRANT.getDescription();
}
}

View File

@@ -0,0 +1,177 @@
package module.decode.p25.message.pdu.osp.voice;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class GroupVoiceChannelGrantExplicit extends PDUMessage
implements IdentifierReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131;
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
135 };
public static final int[] TRANSMIT_IDENTIFIER = { 176,177,178,179 };
public static final int[] TRANSMIT_NUMBER = { 180,181,182,183,184,185,186,
187,188,189,190,191 };
public static final int[] RECEIVE_IDENTIFIER = { 192,193,194,195 };
public static final int[] RECEIVE_NUMBER = { 196,197,198,199,200,201,202,
203,204,205,206,207 };
public static final int[] GROUP_ADDRESS = { 208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public GroupVoiceChannelGrantExplicit( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.GROUP_VOICE_CHANNEL_GRANT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
sb.append( " FROM:" );
sb.append( getSourceAddress() );
sb.append( " GRP:" );
sb.append( getGroupAddress() );
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
sb.append( " " + getDownlinkFrequency() );
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
sb.append( " " + getUplinkFrequency() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncrypted()
{
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 getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveChannelIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,184 @@
package module.decode.p25.message.pdu.osp.voice;
import java.util.Date;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class TelephoneInterconnectChannelGrantExplicit extends PDUMessage
implements IdentifierReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131;
public static final int[] ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
135 };
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 };
public static final int[] TRANSMIT_NUMBER = { 164,165,166,167,168,169,170,
171,172,173,174,175 };
public static final int[] RECEIVE_IDENTIFIER = { 176,177,178,179 };
public static final int[] RECEIVE_NUMBER = { 180,181,182,183,184,185,186,
187,188,189,190,191 };
public static final int[] CALL_TIMER = { 192,193,194,195,196,197,198,199,
200,201,202,203,204,205,206,207 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public TelephoneInterconnectChannelGrantExplicit( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
sb.append( " ADDR:" );
sb.append( getAddress() );
sb.append( " CALL TIMER:" );
sb.append( mTimeDurationFormat.format( new Date( getCallTimer() ) ) );
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
sb.append( " " + getDownlinkFrequency() );
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
sb.append( " " + getUplinkFrequency() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncrypted()
{
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 milliseconds
*/
public long getCallTimer()
{
int timer = mMessage.getInt( CALL_TIMER );
return timer / 100;
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveChannelIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,22 @@
package module.decode.p25.message.pdu.osp.voice;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class TelephoneInterconnectChannelGrantUpdateExplicit
extends TelephoneInterconnectChannelGrantExplicit
{
public TelephoneInterconnectChannelGrantUpdateExplicit( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT_UPDATE.getDescription();
}
}

View File

@@ -0,0 +1,111 @@
package module.decode.p25.message.pdu.osp.voice;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class UnitToUnitAnswerRequestExplicit extends PDUMessage
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131;
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] WACN = { 168,169,170,171,172,173,174,175,176,177,
178,179,180,181,182,183,184,185,186,187 };
public static final int[] SYSTEM_ID = { 188,189,190,191,192,193,194,195,196,
197,198,199 };
public static final int[] SOURCE_ID = { 200,201,202,203,204,205,206,207,208,
209,210,211,212,213,214,215,216,217,218,219,220,221,222,223 };
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
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 };
public UnitToUnitAnswerRequestExplicit( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU1( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.UNIT_TO_UNIT_ANSWER_REQUEST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
sb.append( " FROM:" );
sb.append( getSourceID() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " WACN:" + getWACN() );
sb.append( " SYS:" + getSystemID() );
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 getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
}

View File

@@ -0,0 +1,25 @@
package module.decode.p25.message.pdu.osp.voice;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.UnitToUnitChannelGrantExtended;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class UnitToUnitVoiceChannelGrantExtended
extends UnitToUnitChannelGrantExtended
implements IdentifierReceiver
{
public UnitToUnitVoiceChannelGrantExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.UNIT_TO_UNIT_VOICE_CHANNEL_GRANT.getDescription();
}
}

View File

@@ -0,0 +1,207 @@
package module.decode.p25.message.pdu.osp.voice;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
import edac.CRCP25;
public class UnitToUnitVoiceChannelGrantUpdateExtended extends PDUMessage
implements IdentifierReceiver
{
/* Service Options */
public static final int EMERGENCY_FLAG = 128;
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
public static final int DUPLEX_MODE = 130;
public static final int SESSION_MODE = 131;
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
135 };
public static final int[] SOURCE_WACN = { 160,161,162,163,164,165,166,167,
168,169,170,171,172,173,174,175,176,177,178,179 };
public static final int[] SOURCE_SYSTEM_ID = { 180,181,182,183,184,185,186,
187,188,189,190,191 };
public static final int[] SOURCE_ID = { 192,193,194,195,196,197,198,199,200,
201,202,203,204,205,206,207,208,209,210,211,212,213,214,215 };
public static final int[] TARGET_ADDRESS = { 216,217,218,219,220,221,222,
223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 };
public static final int[] TRANSMIT_IDENTIFIER = { 240,241,242,243 };
public static final int[] TRANSMIT_NUMBER = { 244,245,246,247,248,249,250,
251,252,253,254,255 };
public static final int[] RECEIVE_IDENTIFIER = { 256,257,258,259 };
public static final int[] RECEIVE_NUMBER = { 260,261,262,263,264,265,266,
267,268,269,270,271 };
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
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 IBandIdentifier mTransmitIdentifierUpdate;
private IBandIdentifier mReceiveIdentifierUpdate;
public UnitToUnitVoiceChannelGrantUpdateExtended( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
/* Header block is already error detected/corrected - perform error
* detection correction on the intermediate and final data blocks */
mMessage = CRCP25.correctPDU2( mMessage );
mCRC[ 1 ] = mMessage.getCRC();
}
@Override
public String getEventType()
{
return Opcode.UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( isEmergency() )
{
sb.append( " EMERGENCY" );
}
sb.append( " FROM ADDR:" );
sb.append( getSourceAddress() );
sb.append( " ID:" );
sb.append( getSourceID() );
sb.append( " TO:" );
sb.append( getTargetAddress() );
sb.append( " WACN:" );
sb.append( getSourceWACN() );
sb.append( " SYS:" );
sb.append( getSourceSystemID() );
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
sb.append( " " + getDownlinkFrequency() );
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
sb.append( " " + getUplinkFrequency() );
return sb.toString();
}
public boolean isEmergency()
{
return mMessage.get( EMERGENCY_FLAG );
}
public boolean isEncrypted()
{
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 getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getSourceWACN()
{
return mMessage.getHex( SOURCE_WACN, 5 );
}
public String getSourceSystemID()
{
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
public int getTransmitChannelIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
}
public int getTransmitChannelNumber()
{
return mMessage.getInt( TRANSMIT_NUMBER );
}
public String getTransmitChannel()
{
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
}
public int getReceiveChannelIdentifier()
{
return mMessage.getInt( RECEIVE_IDENTIFIER );
}
public int getReceiveChannelNumber()
{
return mMessage.getInt( RECEIVE_NUMBER );
}
public String getReceiveChannel()
{
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitChannelIdentifier() )
{
mTransmitIdentifierUpdate = message;
}
if( identifier == getReceiveChannelIdentifier() )
{
mReceiveIdentifierUpdate = message;
}
}
public int[] getIdentifiers()
{
int[] idens = new int[ 2 ];
idens[ 0 ] = getTransmitChannelIdentifier();
idens[ 1 ] = getReceiveChannelIdentifier();
return idens;
}
}