mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 01:27:34 -05:00
Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* * ******************************************************************************
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* * Copyright (C) 2014-2020 Dennis Sheirer, Zhenyu Mao
|
* it under the terms of the GNU General Public License as published by
|
||||||
* *
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
* (at your option) any later version.
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
package io.github.dsheirer.module.decode.dmr;
|
package io.github.dsheirer.module.decode.dmr;
|
||||||
|
|
||||||
@@ -40,6 +37,7 @@ import io.github.dsheirer.message.IMessage;
|
|||||||
import io.github.dsheirer.module.decode.DecoderType;
|
import io.github.dsheirer.module.decode.DecoderType;
|
||||||
import io.github.dsheirer.module.decode.dmr.channel.DMRChannel;
|
import io.github.dsheirer.module.decode.dmr.channel.DMRChannel;
|
||||||
import io.github.dsheirer.module.decode.dmr.event.DMRDecodeEvent;
|
import io.github.dsheirer.module.decode.dmr.event.DMRDecodeEvent;
|
||||||
|
import io.github.dsheirer.module.decode.dmr.identifier.DMRTalkgroup;
|
||||||
import io.github.dsheirer.module.decode.dmr.message.DMRMessage;
|
import io.github.dsheirer.module.decode.dmr.message.DMRMessage;
|
||||||
import io.github.dsheirer.module.decode.dmr.message.data.DataMessage;
|
import io.github.dsheirer.module.decode.dmr.message.data.DataMessage;
|
||||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
|
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
|
||||||
@@ -307,7 +305,17 @@ public class DMRDecoderState extends TimeslotDecoderState
|
|||||||
*/
|
*/
|
||||||
private void processVoice(VoiceMessage message)
|
private void processVoice(VoiceMessage message)
|
||||||
{
|
{
|
||||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CALL, getTimeslot()));
|
if(message.getSyncPattern().isDirectMode())
|
||||||
|
{
|
||||||
|
updateCurrentCall(DecodeEventType.CALL, "DIRECT MODE", message.getTimestamp());
|
||||||
|
|
||||||
|
//Use the timeslot as the talkgroup identifier since DCDM mode doesn't use talkgroups
|
||||||
|
getIdentifierCollection().update(DMRTalkgroup.create(getTimeslot()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CALL, getTimeslot()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* ******************************************************************************
|
* *****************************************************************************
|
||||||
* sdrtrunk
|
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
* Copyright (C) 2014-2020 Dennis Sheirer, Zhenyu Mao
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -15,7 +14,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
* *****************************************************************************
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
package io.github.dsheirer.module.decode.dmr;
|
package io.github.dsheirer.module.decode.dmr;
|
||||||
|
|
||||||
@@ -34,10 +33,10 @@ public enum DMRSyncPattern
|
|||||||
|
|
||||||
MOBILE_STATION_DATA(0xD5D7F77FD757l, 0xBFBEAEEABEFEl, 0x404151154101l, 0x2A28088028A8l, "MS DATA"),
|
MOBILE_STATION_DATA(0xD5D7F77FD757l, 0xBFBEAEEABEFEl, 0x404151154101l, 0x2A28088028A8l, "MS DATA"),
|
||||||
MOBILE_STATION_VOICE(0x7F7D5DD57DFDl, 0xEAEBFBBFEBABl, 0x151404401454l, 0x8082A22A8202l, "MS VOICE A"),
|
MOBILE_STATION_VOICE(0x7F7D5DD57DFDl, 0xEAEBFBBFEBABl, 0x151404401454l, 0x8082A22A8202l, "MS VOICE A"),
|
||||||
DIRECT_MODE_DATA_TIMESLOT_1(0xF7FDD5DDFD55l, 0xAEABBFBBABFFl, 0x515440445400l, 0x08022A2202AAl, "DM DAT0"),
|
DIRECT_MODE_DATA_TIMESLOT_1(0xF7FDD5DDFD55l, 0xAEABBFBBABFFl, 0x515440445400l, 0x08022A2202AAl, "MS DATA - DUAL CAPACITY DIRECT MODE"),
|
||||||
DIRECT_MODE_DATA_TIMESLOT_2(0xD7557F5FF7F5l, 0xBEFFEAFAAEAFl, 0x410015055150l, 0x28AA80A0080Al, "DM DAT1"),
|
DIRECT_MODE_DATA_TIMESLOT_2(0xD7557F5FF7F5l, 0xBEFFEAFAAEAFl, 0x410015055150l, 0x28AA80A0080Al, "MS DATA - DUAL CAPACITY DIRECT MODE"),
|
||||||
DIRECT_MODE_VOICE_TIMESLOT_1(0x5D577F7757FFl, 0xFBFEEAEEFEAAl, 0x040115110155l, 0xA2A88088A800l, "DM VOX0"),
|
DIRECT_MODE_VOICE_TIMESLOT_1(0x5D577F7757FFl, 0xFBFEEAEEFEAAl, 0x040115110155l, 0xA2A88088A800l, "MS VOICE A - DUAL CAPACITY DIRECT MODE"),
|
||||||
DIRECT_MODE_VOICE_TIMESLOT_2(0x7DFFD5F55D5Fl, 0xEBAABFAFFBFAl, 0x145540500405l, 0x82002A0AA2A0l, "DM VOX1"),
|
DIRECT_MODE_VOICE_TIMESLOT_2(0x7DFFD5F55D5Fl, 0xEBAABFAFFBFAl, 0x145540500405l, 0x82002A0AA2A0l, "MS VOICE A - DUAL CAPACITY DIRECT MODE"),
|
||||||
MOBILE_STATION_REVERSE_CHANNEL(0x77D55F7DFD77l, 0xEEBFFAEBABEEl, 0x114005145411l, 0x882AA0820288l, "MS RVRS"),
|
MOBILE_STATION_REVERSE_CHANNEL(0x77D55F7DFD77l, 0xEEBFFAEBABEEl, 0x114005145411l, 0x882AA0820288l, "MS RVRS"),
|
||||||
|
|
||||||
RESERVED(0xDD7FF5D757DDl, 0xBBEAAFBEFEBBl, 0x441550410144l, 0x22800A28A822l, "RESERVED"),
|
RESERVED(0xDD7FF5D757DDl, 0xBBEAAFBEFEBBl, 0x441550410144l, 0x22800A28A822l, "RESERVED"),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2021 Dennis Sheirer
|
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -102,11 +102,22 @@ public class DMRAudioModule extends AmbeAudioModule implements IdentifierUpdateP
|
|||||||
{
|
{
|
||||||
if(hasAudioCodec() && message.getTimeslot() == getTimeslot())
|
if(hasAudioCodec() && message.getTimeslot() == getTimeslot())
|
||||||
{
|
{
|
||||||
|
//DCDM doesn't provide FLCs or EMBs ... assume that the call is unencrypted.
|
||||||
|
if(!mEncryptedCallStateEstablished && message instanceof VoiceMessage vm &&
|
||||||
|
vm.getSyncPattern().isDirectMode())
|
||||||
|
{
|
||||||
|
mEncryptedCallStateEstablished = true;
|
||||||
|
mEncryptedCall = false;
|
||||||
|
List<byte[]> frames = vm.getAMBEFrames();
|
||||||
|
for(byte[] frame: frames)
|
||||||
|
{
|
||||||
|
processAudio(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
//Both Motorola and Hytera signal their Basic Privacy (BP) scrambling in some of the Voice B-F frames
|
//Both Motorola and Hytera signal their Basic Privacy (BP) scrambling in some of the Voice B-F frames
|
||||||
//in the EMB field.
|
//in the EMB field.
|
||||||
if(!mEncryptedCallStateEstablished && message instanceof VoiceEMBMessage)
|
else if(!mEncryptedCallStateEstablished && message instanceof VoiceEMBMessage voiceMessage)
|
||||||
{
|
{
|
||||||
VoiceEMBMessage voiceMessage = (VoiceEMBMessage)message;
|
|
||||||
if(voiceMessage.getEMB().isValid())
|
if(voiceMessage.getEMB().isValid())
|
||||||
{
|
{
|
||||||
mEncryptedCallStateEstablished = true;
|
mEncryptedCallStateEstablished = true;
|
||||||
@@ -119,23 +130,20 @@ public class DMRAudioModule extends AmbeAudioModule implements IdentifierUpdateP
|
|||||||
processAudio(frame);
|
processAudio(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(message instanceof VoiceMessage)
|
else if(message instanceof VoiceMessage voiceMessage)
|
||||||
{
|
{
|
||||||
VoiceMessage voiceMessage = (VoiceMessage)message;
|
|
||||||
List<byte[]> frames = voiceMessage.getAMBEFrames();
|
List<byte[]> frames = voiceMessage.getAMBEFrames();
|
||||||
for(byte[] frame: frames)
|
for(byte[] frame: frames)
|
||||||
{
|
{
|
||||||
processAudio(frame);
|
processAudio(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!mEncryptedCallStateEstablished && message instanceof VoiceHeader)
|
else if(!mEncryptedCallStateEstablished && message instanceof VoiceHeader voiceHeader)
|
||||||
{
|
{
|
||||||
LCMessage lc = ((VoiceHeader)message).getLCMessage();
|
LCMessage lc = voiceHeader.getLCMessage();
|
||||||
|
|
||||||
if(lc instanceof FullLCMessage) //We know it is, but this null checks as well
|
if(lc instanceof FullLCMessage flc) //We know it is, but this null checks as well
|
||||||
{
|
{
|
||||||
FullLCMessage flc = (FullLCMessage)lc;
|
|
||||||
|
|
||||||
if(flc.isValid())
|
if(flc.isValid())
|
||||||
{
|
{
|
||||||
mEncryptedCallStateEstablished = true;
|
mEncryptedCallStateEstablished = true;
|
||||||
@@ -146,9 +154,9 @@ public class DMRAudioModule extends AmbeAudioModule implements IdentifierUpdateP
|
|||||||
//Note: the DMRMessageProcess extracts Full Link Control messages from Voice Frames B-C and sends them
|
//Note: the DMRMessageProcess extracts Full Link Control messages from Voice Frames B-C and sends them
|
||||||
// independent of any DMR Burst messaging. When encountered, it can be assumed that they are part of
|
// independent of any DMR Burst messaging. When encountered, it can be assumed that they are part of
|
||||||
// an ongoing call and can be used to establish encryption state when the FLC is a voice channel user.
|
// an ongoing call and can be used to establish encryption state when the FLC is a voice channel user.
|
||||||
else if(!mEncryptedCallStateEstablished && message instanceof AbstractVoiceChannelUser)
|
else if(!mEncryptedCallStateEstablished && message instanceof AbstractVoiceChannelUser avcu)
|
||||||
{
|
{
|
||||||
ServiceOptions serviceOptions = ((AbstractVoiceChannelUser)message).getServiceOptions();
|
ServiceOptions serviceOptions = avcu.getServiceOptions();
|
||||||
mEncryptedCallStateEstablished = true;
|
mEncryptedCallStateEstablished = true;
|
||||||
mEncryptedCall = serviceOptions.isEncrypted();
|
mEncryptedCall = serviceOptions.isEncrypted();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.module.decode.dmr.message;
|
package io.github.dsheirer.module.decode.dmr.message;
|
||||||
|
|
||||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||||
@@ -33,6 +52,12 @@ public class DMRMessageFactory
|
|||||||
case BS_VOICE_FRAME_D:
|
case BS_VOICE_FRAME_D:
|
||||||
case BS_VOICE_FRAME_E:
|
case BS_VOICE_FRAME_E:
|
||||||
case BS_VOICE_FRAME_F:
|
case BS_VOICE_FRAME_F:
|
||||||
|
|
||||||
|
case MS_VOICE_FRAME_B:
|
||||||
|
case MS_VOICE_FRAME_C:
|
||||||
|
case MS_VOICE_FRAME_D:
|
||||||
|
case MS_VOICE_FRAME_E:
|
||||||
|
case MS_VOICE_FRAME_F:
|
||||||
return createVoiceMessage(syncPattern, binaryMessage, cach, timestamp, timeslot);
|
return createVoiceMessage(syncPattern, binaryMessage, cach, timestamp, timeslot);
|
||||||
case DIRECT_MODE_VOICE_TIMESLOT_1:
|
case DIRECT_MODE_VOICE_TIMESLOT_1:
|
||||||
return createVoiceMessage(syncPattern, binaryMessage, cach, timestamp, 1);
|
return createVoiceMessage(syncPattern, binaryMessage, cach, timestamp, 1);
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.module.decode.dmr.message.voice;
|
package io.github.dsheirer.module.decode.dmr.message.voice;
|
||||||
|
|
||||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||||
@@ -29,7 +48,16 @@ public class VoiceAMessage extends VoiceMessage
|
|||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(" ").append(getSyncPattern());
|
|
||||||
|
if(getSyncPattern().isDirectMode())
|
||||||
|
{
|
||||||
|
sb.append(getSyncPattern());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append(" ").append(getSyncPattern());
|
||||||
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.module.decode.dmr.message.voice;
|
package io.github.dsheirer.module.decode.dmr.message.voice;
|
||||||
|
|
||||||
import io.github.dsheirer.bits.BinaryMessage;
|
import io.github.dsheirer.bits.BinaryMessage;
|
||||||
@@ -37,25 +56,14 @@ public class VoiceEMBMessage extends VoiceMessage
|
|||||||
|
|
||||||
if(getEMB().isValid())
|
if(getEMB().isValid())
|
||||||
{
|
{
|
||||||
sb.append("CC:").append(getEMB().getColorCode());
|
sb.append("CC:").append(getEMB().getColorCode()).append(" ");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.append("CC:?");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append(" ").append(getSyncPattern().toString());
|
sb.append(getSyncPattern().toString());
|
||||||
|
|
||||||
if(getEMB().isValid())
|
if(getEMB().isValid() && getEMB().isEncrypted())
|
||||||
{
|
{
|
||||||
if(getEMB().isEncrypted())
|
sb.append(" ENCRYPTED");
|
||||||
{
|
|
||||||
sb.append(" ENCRYPTED");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.append(" [EMB CRC-ERROR]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
|||||||
Reference in New Issue
Block a user