|
|
|
@ -48,6 +48,7 @@ using System.Security.Cryptography;
|
|
|
|
using fnecore.P25.LC.TSBK;
|
|
|
|
using fnecore.P25.LC.TSBK;
|
|
|
|
using WebSocketSharp;
|
|
|
|
using WebSocketSharp;
|
|
|
|
using NWaves.Signals;
|
|
|
|
using NWaves.Signals;
|
|
|
|
|
|
|
|
using static WhackerLinkConsoleV2.P25Crypto;
|
|
|
|
|
|
|
|
|
|
|
|
namespace WhackerLinkConsoleV2
|
|
|
|
namespace WhackerLinkConsoleV2
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -92,7 +93,7 @@ namespace WhackerLinkConsoleV2
|
|
|
|
|
|
|
|
|
|
|
|
public MainWindow()
|
|
|
|
public MainWindow()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#if DEBUG
|
|
|
|
#if !DEBUG
|
|
|
|
ConsoleNative.ShowConsole();
|
|
|
|
ConsoleNative.ShowConsole();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
InitializeComponent();
|
|
|
|
InitializeComponent();
|
|
|
|
@ -1837,34 +1838,23 @@ namespace WhackerLinkConsoleV2
|
|
|
|
//Log.Logger.Debug($"Decoding IMBE buffer: {FneUtils.HexDump(imbe)}");
|
|
|
|
//Log.Logger.Debug($"Decoding IMBE buffer: {FneUtils.HexDump(imbe)}");
|
|
|
|
|
|
|
|
|
|
|
|
short[] samples = new short[FneSystemBase.MBE_SAMPLES_LENGTH];
|
|
|
|
short[] samples = new short[FneSystemBase.MBE_SAMPLES_LENGTH];
|
|
|
|
int errs = 0;
|
|
|
|
|
|
|
|
#if WIN32
|
|
|
|
|
|
|
|
if (cryptodev)
|
|
|
|
if (cryptodev)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//Console.WriteLine($"MI: {FneUtils.HexDump(channel.mi)}");
|
|
|
|
//Console.WriteLine($"MI: {FneUtils.HexDump(channel.mi)}");
|
|
|
|
//Console.WriteLine($"Algorithm ID: {channel.algId}");
|
|
|
|
//Console.WriteLine($"Algorithm ID: {channel.algId}");
|
|
|
|
//Console.WriteLine($"Key ID: {channel.kId}");
|
|
|
|
//Console.WriteLine($"Key ID: {channel.kId}");
|
|
|
|
|
|
|
|
|
|
|
|
channel.crypter.Process(imbe, frameType, n);
|
|
|
|
channel.crypter.Process(imbe, frameType, n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if WIN32
|
|
|
|
if (channel.extFullRateVocoder == null)
|
|
|
|
if (channel.extFullRateVocoder == null)
|
|
|
|
channel.extFullRateVocoder = new AmbeVocoder(true);
|
|
|
|
channel.extFullRateVocoder = new AmbeVocoder(true);
|
|
|
|
|
|
|
|
|
|
|
|
errs = channel.extFullRateVocoder.decode(imbe, out samples);
|
|
|
|
channel.p25Errs = channel.extFullRateVocoder.decode(imbe, out samples);
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
if (cryptodev)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Console.WriteLine($"MI: {FneUtils.HexDump(channel.mi)}");
|
|
|
|
|
|
|
|
Console.WriteLine($"Algorithm ID: {channel.algId}");
|
|
|
|
|
|
|
|
Console.WriteLine($"Key ID: {channel.kId}");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
channel.crypter.Process(imbe, frameType, n);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Console.WriteLine(FneUtils.HexDump(imbe));
|
|
|
|
channel.p25Errs = channel.decoder.decode(imbe, samples);
|
|
|
|
|
|
|
|
|
|
|
|
errs = channel.decoder.decode(imbe, samples);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (emergency)
|
|
|
|
if (emergency)
|
|
|
|
@ -2020,7 +2010,7 @@ namespace WhackerLinkConsoleV2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Is the call over?
|
|
|
|
// Is the call over?
|
|
|
|
if (((e.DUID == P25DUID.TDU) || (e.DUID == P25DUID.TDULC)) && (slot.RxType != FrameType.TERMINATOR))
|
|
|
|
if (((e.DUID == P25DUID.TDU) || (e.DUID == P25DUID.TDULC)) && (slot.RxType != fnecore.FrameType.TERMINATOR))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
channel.IsReceiving = false;
|
|
|
|
channel.IsReceiving = false;
|
|
|
|
TimeSpan callDuration = pktTime - slot.RxStart;
|
|
|
|
TimeSpan callDuration = pktTime - slot.RxStart;
|
|
|
|
@ -2032,6 +2022,8 @@ namespace WhackerLinkConsoleV2
|
|
|
|
if ((channel.algId != cpgChannel.GetAlgoId() || channel.kId != cpgChannel.GetKeyId()) && channel.algId != P25Defines.P25_ALGO_UNENCRYPT)
|
|
|
|
if ((channel.algId != cpgChannel.GetAlgoId() || channel.kId != cpgChannel.GetKeyId()) && channel.algId != P25Defines.P25_ALGO_UNENCRYPT)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
byte[] newMI = new byte[P25Defines.P25_MI_LENGTH];
|
|
|
|
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
|
|
switch (e.DUID)
|
|
|
|
switch (e.DUID)
|
|
|
|
@ -2107,23 +2099,23 @@ namespace WhackerLinkConsoleV2
|
|
|
|
|
|
|
|
|
|
|
|
// The '6D' record - IMBE Voice 12 + Encryption Sync
|
|
|
|
// The '6D' record - IMBE Voice 12 + Encryption Sync
|
|
|
|
Buffer.BlockCopy(data, count, channel.netLDU2, 50, 17);
|
|
|
|
Buffer.BlockCopy(data, count, channel.netLDU2, 50, 17);
|
|
|
|
channel.mi[0] = data[count + 1];
|
|
|
|
newMI[0] = data[count + 1];
|
|
|
|
channel.mi[1] = data[count + 2];
|
|
|
|
newMI[1] = data[count + 2];
|
|
|
|
channel.mi[2] = data[count + 3];
|
|
|
|
newMI[2] = data[count + 3];
|
|
|
|
count += 17;
|
|
|
|
count += 17;
|
|
|
|
|
|
|
|
|
|
|
|
// The '6E' record - IMBE Voice 13 + Encryption Sync
|
|
|
|
// The '6E' record - IMBE Voice 13 + Encryption Sync
|
|
|
|
Buffer.BlockCopy(data, count, channel.netLDU2, 75, 17);
|
|
|
|
Buffer.BlockCopy(data, count, channel.netLDU2, 75, 17);
|
|
|
|
channel.mi[3] = data[count + 1];
|
|
|
|
newMI[3] = data[count + 1];
|
|
|
|
channel.mi[4] = data[count + 2];
|
|
|
|
newMI[4] = data[count + 2];
|
|
|
|
channel.mi[5] = data[count + 3];
|
|
|
|
newMI[5] = data[count + 3];
|
|
|
|
count += 17;
|
|
|
|
count += 17;
|
|
|
|
|
|
|
|
|
|
|
|
// The '6F' record - IMBE Voice 14 + Encryption Sync
|
|
|
|
// The '6F' record - IMBE Voice 14 + Encryption Sync
|
|
|
|
Buffer.BlockCopy(data, count, channel.netLDU2, 100, 17);
|
|
|
|
Buffer.BlockCopy(data, count, channel.netLDU2, 100, 17);
|
|
|
|
channel.mi[6] = data[count + 1];
|
|
|
|
newMI[6] = data[count + 1];
|
|
|
|
channel.mi[7] = data[count + 2];
|
|
|
|
newMI[7] = data[count + 2];
|
|
|
|
channel.mi[8] = data[count + 3];
|
|
|
|
newMI[8] = data[count + 3];
|
|
|
|
count += 17;
|
|
|
|
count += 17;
|
|
|
|
|
|
|
|
|
|
|
|
// The '70' record - IMBE Voice 15 + Encryption Sync
|
|
|
|
// The '70' record - IMBE Voice 15 + Encryption Sync
|
|
|
|
@ -2144,6 +2136,13 @@ namespace WhackerLinkConsoleV2
|
|
|
|
Buffer.BlockCopy(data, count, channel.netLDU2, 200, 16);
|
|
|
|
Buffer.BlockCopy(data, count, channel.netLDU2, 200, 16);
|
|
|
|
count += 16;
|
|
|
|
count += 16;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (channel.p25Errs > 0) // temp, need to actually get erros I guess
|
|
|
|
|
|
|
|
P25Crypto.CycleP25Lfsr(channel.mi);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
Array.Copy(newMI, channel.mi, P25Defines.P25_MI_LENGTH);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Console.WriteLine(channel.p25Errs);
|
|
|
|
|
|
|
|
|
|
|
|
// decode 9 IMBE codewords into PCM samples
|
|
|
|
// decode 9 IMBE codewords into PCM samples
|
|
|
|
P25DecodeAudioFrame(channel.netLDU2, e, handler, channel, isEmergency, P25Crypto.FrameType.LDU2);
|
|
|
|
P25DecodeAudioFrame(channel.netLDU2, e, handler, channel, isEmergency, P25Crypto.FrameType.LDU2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|