Skip to content

Commit

Permalink
#2007 P25 Call events tracking. P25 Traffic channel manager now uses …
Browse files Browse the repository at this point in the history
…event trackers to deconflict between control channel and traffic channel event updates. Protects against Motorola ISSI FQSUID that's all zeros. Resolves issue with running out of traffic channels after losing the control channel and going into CC hunt mode a few times. (#2010)

Co-authored-by: Dennis Sheirer <[email protected]>
  • Loading branch information
DSheirer and Dennis Sheirer authored Oct 13, 2024
1 parent d248955 commit 1b3ce43
Show file tree
Hide file tree
Showing 17 changed files with 1,128 additions and 1,078 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ private void load(File file)

ThreadPool.CACHED.submit(() -> {
List<MessagePackage> messages = new ArrayList<>();
P25P2MessageFramer messageFramer = new P25P2MessageFramer(null, 9600);
P25P2MessageFramer messageFramer = new P25P2MessageFramer(null);
messageFramer.setScrambleParameters(scrambleParameters);
P25P2MessageProcessor messageProcessor = new P25P2MessageProcessor();
messageFramer.setListener(messageProcessor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,15 @@ public Identifier getToIdentifier()
return to;
}

/**
* Returns an encryption key identiier or null.
* @return key or null.
*/
public Identifier getEncryptionIdentifier()
{
return getIdentifier(IdentifierClass.USER, Form.ENCRYPTION_KEY, Role.ANY);
}

@Override
public String toString()
{
Expand Down
34 changes: 21 additions & 13 deletions src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,10 @@ public static List<Module> getPrimaryModules(ChannelMapModel channelMapModel, Ch
processPassport(channel, modules, aliasList, decodeConfig);
break;
case P25_PHASE1:
processP25Phase1(channel, userPreferences, modules, aliasList, trafficChannelManager);
processP25Phase1(channel, userPreferences, modules, aliasList, trafficChannelManager, channelDescriptor);
break;
case P25_PHASE2:
processP25Phase2(channel, userPreferences, modules, aliasList, trafficChannelManager);
processP25Phase2(channel, userPreferences, modules, aliasList, trafficChannelManager, channelDescriptor);
break;
default:
throw new IllegalArgumentException("Unknown decoder type [" + decodeConfig.getDecoderType().toString() + "]");
Expand All @@ -210,7 +210,8 @@ public static List<Module> getPrimaryModules(ChannelMapModel channelMapModel, Ch
* will be created automatically.
*/
private static void processP25Phase2(Channel channel, UserPreferences userPreferences, List<Module> modules,
AliasList aliasList, TrafficChannelManager trafficChannelManager)
AliasList aliasList, TrafficChannelManager trafficChannelManager,
IChannelDescriptor channelDescriptor)
{

modules.add(new P25P2DecoderHDQPSK((DecodeConfigP25Phase2)channel.getDecodeConfiguration()));
Expand All @@ -236,22 +237,25 @@ else if(trafficChannelManager instanceof P25TrafficChannelManager p25)
modules.add(p25TrafficChannelManager);
}

//A single patch group manager is shared across both timeslots
PatchGroupManager patchGroupManager = new PatchGroupManager();
modules.add(new P25P2DecoderState(channel, P25P2Message.TIMESLOT_1, p25TrafficChannelManager, patchGroupManager));
modules.add(new P25P2DecoderState(channel, P25P2Message.TIMESLOT_2, p25TrafficChannelManager, patchGroupManager));

P25P2DecoderState decoderState1 = new P25P2DecoderState(channel, P25P2Message.TIMESLOT_1, p25TrafficChannelManager, patchGroupManager);
decoderState1.setCurrentChannel(channelDescriptor);
P25P2DecoderState decoderState2 = new P25P2DecoderState(channel, P25P2Message.TIMESLOT_2, p25TrafficChannelManager, patchGroupManager);
decoderState2.setCurrentChannel(channelDescriptor);
modules.add(decoderState1);
modules.add(decoderState2);
modules.add(new P25P2AudioModule(userPreferences, P25P2Message.TIMESLOT_1, aliasList));
modules.add(new P25P2AudioModule(userPreferences, P25P2Message.TIMESLOT_2, aliasList));


//Add a channel rotation monitor when we have multiple control channel frequencies specified
if(channel.getSourceConfiguration() instanceof SourceConfigTunerMultipleFrequency &&
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).hasMultipleFrequencies())
if(channel.getSourceConfiguration() instanceof SourceConfigTunerMultipleFrequency sctmf &&
sctmf.hasMultipleFrequencies())
{
List<State> activeStates = new ArrayList<>();
activeStates.add(State.CONTROL);
modules.add(new ChannelRotationMonitor(activeStates,
((SourceConfigTunerMultipleFrequency)channel.getSourceConfiguration()).getFrequencyRotationDelay(),
userPreferences));
modules.add(new ChannelRotationMonitor(activeStates, sctmf.getFrequencyRotationDelay(), userPreferences));
}
}

Expand All @@ -263,7 +267,8 @@ else if(trafficChannelManager instanceof P25TrafficChannelManager p25)
* @param aliasList for the channel
*/
private static void processP25Phase1(Channel channel, UserPreferences userPreferences, List<Module> modules,
AliasList aliasList, TrafficChannelManager trafficChannelManager)
AliasList aliasList, TrafficChannelManager trafficChannelManager,
IChannelDescriptor channelDescriptor)
{
if(channel.getDecodeConfiguration() instanceof DecodeConfigP25Phase1 p1)
{
Expand All @@ -288,7 +293,9 @@ private static void processP25Phase1(Channel channel, UserPreferences userPrefer
}
else if(trafficChannelManager instanceof P25TrafficChannelManager parentTCM)
{
modules.add(new P25P1DecoderState(channel, parentTCM));
P25P1DecoderState decoderState = new P25P1DecoderState(channel, parentTCM);
decoderState.setCurrentChannel(channelDescriptor);
modules.add(decoderState);
}
else
{
Expand Down Expand Up @@ -466,6 +473,7 @@ private static void processAM(Channel channel, List<Module> modules, AliasList a
* @param aliasList for the audio module
* @param decodeConfig for the DMR configuration
* @param trafficChannelManager optional traffic channel manager to re-use
* @param channelDescriptor for the channel.
*/
private static void processDMR(Channel channel, UserPreferences userPreferences, List<Module> modules,
AliasList aliasList, DecodeConfigDMR decodeConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public enum DecodeEventType
/**
* Voice call event types for filtering
*/
public static final EnumSet<DecodeEventType> VOICE_CALLS = EnumSet.of(DecodeEventType.CALL_GROUP,
public static final EnumSet<DecodeEventType> VOICE_CALLS = EnumSet.of(DecodeEventType.CALL, DecodeEventType.CALL_GROUP,
DecodeEventType.CALL_PATCH_GROUP, DecodeEventType.CALL_ALERT, DecodeEventType.CALL_DETECT,
DecodeEventType.CALL_DO_NOT_MONITOR, DecodeEventType.CALL_END, DecodeEventType.CALL_INTERCONNECT,
DecodeEventType.CALL_UNIQUE_ID, DecodeEventType.CALL_UNIT_TO_UNIT, DecodeEventType.CALL_NO_TUNER,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 Dennis Sheirer
* Copyright (C) 2014-2024 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -80,6 +80,7 @@ public static class P25ChannelGrantDecodeEventBuilder
protected IChannelDescriptor mChannelDescriptor;
protected String mDetails;
private ServiceOptions mServiceOptions;
private int mTimeslot = -1;

/**
* Constructs a builder instance with the specified start time in milliseconds
Expand Down Expand Up @@ -144,6 +145,16 @@ public P25ChannelGrantDecodeEventBuilder details(String details)
return this;
}

/**
* Sets the timeslot for the event
* @param timeslot
*/
public P25ChannelGrantDecodeEventBuilder timeslot(int timeslot)
{
mTimeslot = timeslot;
return this;
}

/**
* Builds the decode event
*/
Expand All @@ -156,6 +167,7 @@ public P25ChannelGrantEvent build()
decodeEvent.setDuration(mDuration);
decodeEvent.setIdentifierCollection(mIdentifierCollection);
decodeEvent.setServiceOptions(mServiceOptions);
decodeEvent.setTimeslot(mTimeslot);
return decodeEvent;
}
}
Expand Down
Loading

0 comments on commit 1b3ce43

Please sign in to comment.