diff --git a/WhackerLinkConsoleV2/ChannelBox.xaml.cs b/WhackerLinkConsoleV2/ChannelBox.xaml.cs
index b57659f..18c9d2d 100644
--- a/WhackerLinkConsoleV2/ChannelBox.xaml.cs
+++ b/WhackerLinkConsoleV2/ChannelBox.xaml.cs
@@ -57,6 +57,7 @@ namespace WhackerLinkConsoleV2.Controls
public int p25N { get; set; } = 0;
public int p25SeqNo { get; set; } = 0;
+ public int p25Errs { get; set; } = 0;
public byte[] mi = new byte[P25Defines.P25_MI_LENGTH]; // Message Indicator
public byte algId = 0; // Algorithm ID
diff --git a/WhackerLinkConsoleV2/FneSystemBase.P25.cs b/WhackerLinkConsoleV2/FneSystemBase.P25.cs
index 5bca64f..34eafbb 100644
--- a/WhackerLinkConsoleV2/FneSystemBase.P25.cs
+++ b/WhackerLinkConsoleV2/FneSystemBase.P25.cs
@@ -453,11 +453,9 @@ namespace WhackerLinkConsoleV2
{
DateTime pktTime = DateTime.Now;
- if ( e.DUID == P25DUID.TSDU || e.DUID == P25DUID.PDU)
+ if (e.DUID == P25DUID.HDU || e.DUID == P25DUID.TSDU || e.DUID == P25DUID.PDU)
return;
- byte control = e.Data[14U];
-
if (e.CallType == CallType.GROUP)
{
if (e.SrcId == 0)
diff --git a/WhackerLinkConsoleV2/MainWindow.xaml.cs b/WhackerLinkConsoleV2/MainWindow.xaml.cs
index d61b829..529f157 100644
--- a/WhackerLinkConsoleV2/MainWindow.xaml.cs
+++ b/WhackerLinkConsoleV2/MainWindow.xaml.cs
@@ -48,6 +48,7 @@ using System.Security.Cryptography;
using fnecore.P25.LC.TSBK;
using WebSocketSharp;
using NWaves.Signals;
+using static WhackerLinkConsoleV2.P25Crypto;
namespace WhackerLinkConsoleV2
{
@@ -92,7 +93,7 @@ namespace WhackerLinkConsoleV2
public MainWindow()
{
-#if DEBUG
+#if !DEBUG
ConsoleNative.ShowConsole();
#endif
InitializeComponent();
@@ -1837,34 +1838,23 @@ namespace WhackerLinkConsoleV2
//Log.Logger.Debug($"Decoding IMBE buffer: {FneUtils.HexDump(imbe)}");
short[] samples = new short[FneSystemBase.MBE_SAMPLES_LENGTH];
- int errs = 0;
-#if WIN32
+
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);
}
+#if WIN32
if (channel.extFullRateVocoder == null)
channel.extFullRateVocoder = new AmbeVocoder(true);
- errs = channel.extFullRateVocoder.decode(imbe, out samples);
+ channel.p25Errs = channel.extFullRateVocoder.decode(imbe, out samples);
#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));
-
- errs = channel.decoder.decode(imbe, samples);
+ channel.p25Errs = channel.decoder.decode(imbe, samples);
#endif
if (emergency)
@@ -2020,7 +2010,7 @@ namespace WhackerLinkConsoleV2
}
// 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;
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)
continue;
+ byte[] newMI = new byte[P25Defines.P25_MI_LENGTH];
+
int count = 0;
switch (e.DUID)
@@ -2107,23 +2099,23 @@ namespace WhackerLinkConsoleV2
// The '6D' record - IMBE Voice 12 + Encryption Sync
Buffer.BlockCopy(data, count, channel.netLDU2, 50, 17);
- channel.mi[0] = data[count + 1];
- channel.mi[1] = data[count + 2];
- channel.mi[2] = data[count + 3];
+ newMI[0] = data[count + 1];
+ newMI[1] = data[count + 2];
+ newMI[2] = data[count + 3];
count += 17;
// The '6E' record - IMBE Voice 13 + Encryption Sync
Buffer.BlockCopy(data, count, channel.netLDU2, 75, 17);
- channel.mi[3] = data[count + 1];
- channel.mi[4] = data[count + 2];
- channel.mi[5] = data[count + 3];
+ newMI[3] = data[count + 1];
+ newMI[4] = data[count + 2];
+ newMI[5] = data[count + 3];
count += 17;
// The '6F' record - IMBE Voice 14 + Encryption Sync
Buffer.BlockCopy(data, count, channel.netLDU2, 100, 17);
- channel.mi[6] = data[count + 1];
- channel.mi[7] = data[count + 2];
- channel.mi[8] = data[count + 3];
+ newMI[6] = data[count + 1];
+ newMI[7] = data[count + 2];
+ newMI[8] = data[count + 3];
count += 17;
// The '70' record - IMBE Voice 15 + Encryption Sync
@@ -2144,6 +2136,13 @@ namespace WhackerLinkConsoleV2
Buffer.BlockCopy(data, count, channel.netLDU2, 200, 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
P25DecodeAudioFrame(channel.netLDU2, e, handler, channel, isEmergency, P25Crypto.FrameType.LDU2);
}
diff --git a/WhackerLinkConsoleV2/P25Crypto.cs b/WhackerLinkConsoleV2/P25Crypto.cs
index e7f2e92..57b4b9a 100644
--- a/WhackerLinkConsoleV2/P25Crypto.cs
+++ b/WhackerLinkConsoleV2/P25Crypto.cs
@@ -116,6 +116,41 @@ namespace WhackerLinkConsoleV2
return false;
}
+ ///
+ /// Cycles the P25 LFSR (Linear Feedback Shift Register) based on the given polynomial.
+ ///
+ /// The message indicator array to be processed.
+ public static void CycleP25Lfsr(byte[] MI)
+ {
+ if (MI == null || MI.Length < 9)
+ throw new ArgumentException("MI must be at least 9 bytes long.");
+
+ ulong lfsr = 0;
+
+ // Load the first 8 bytes into the LFSR
+ for (int i = 0; i < 8; i++)
+ {
+ lfsr = (lfsr << 8) | MI[i];
+ }
+
+ // Perform 64-bit LFSR cycling using the polynomial:
+ // C(x) = x^64 + x^62 + x^46 + x^38 + x^27 + x^15 + 1
+ for (int cnt = 0; cnt < 64; cnt++)
+ {
+ ulong bit = ((lfsr >> 63) ^ (lfsr >> 61) ^ (lfsr >> 45) ^ (lfsr >> 37) ^ (lfsr >> 26) ^ (lfsr >> 14)) & 0x1;
+ lfsr = (lfsr << 1) | bit;
+ }
+
+ // Store the result back into MI
+ for (int i = 7; i >= 0; i--)
+ {
+ MI[i] = (byte)(lfsr & 0xFF);
+ lfsr >>= 8;
+ }
+
+ MI[8] = 0; // Last byte is always set to zero
+ }
+
///
/// Process RC4
///