diff --git a/WhackerLinkConsoleV2/FneSystemBase.cs b/WhackerLinkConsoleV2/FneSystemBase.cs
index 6066580..c101167 100644
--- a/WhackerLinkConsoleV2/FneSystemBase.cs
+++ b/WhackerLinkConsoleV2/FneSystemBase.cs
@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using fnecore.DMR;
using fnecore;
+using fnecore.P25.kmm;
namespace WhackerLinkConsoleV2
{
@@ -180,6 +181,23 @@ namespace WhackerLinkConsoleV2
return;
}
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected override void KeyResponse(object sender, KeyResponseEvent e)
+ {
+ byte[] payload = e.Data.Skip(11).ToArray();
+
+ //Console.WriteLine(FneUtils.HexDump(payload));
+
+ if (e.MessageId == (byte)KmmMessageType.MODIFY_KEY_CMD)
+ {
+ mainWindow.KeyResponseReceived(e);
+ }
+ }
+
///
/// Returns a new stream ID
///
diff --git a/WhackerLinkConsoleV2/KeyStatusWindow.xaml b/WhackerLinkConsoleV2/KeyStatusWindow.xaml
new file mode 100644
index 0000000..6ed6341
--- /dev/null
+++ b/WhackerLinkConsoleV2/KeyStatusWindow.xaml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WhackerLinkConsoleV2/KeyStatusWindow.xaml.cs b/WhackerLinkConsoleV2/KeyStatusWindow.xaml.cs
new file mode 100644
index 0000000..f558589
--- /dev/null
+++ b/WhackerLinkConsoleV2/KeyStatusWindow.xaml.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Windows;
+using WhackerLinkConsoleV2.Controls;
+using WhackerLinkLib.Models.Radio;
+
+namespace WhackerLinkConsoleV2
+{
+ public partial class KeyStatusWindow : Window
+ {
+ public ObservableCollection KeyStatusItems { get; private set; } = new ObservableCollection();
+
+ private Codeplug Codeplug;
+ private MainWindow mainWindow;
+
+ public KeyStatusWindow(Codeplug codeplug, MainWindow mainWindow)
+ {
+ InitializeComponent();
+ this.Codeplug = codeplug;
+ this.mainWindow = mainWindow;
+ DataContext = this;
+
+ LoadKeyStatus();
+ }
+
+ private void LoadKeyStatus()
+ {
+ Dispatcher.Invoke(() =>
+ {
+ KeyStatusItems.Clear();
+
+ foreach (var child in mainWindow.ChannelsCanvas.Children)
+ {
+ if (child == null)
+ {
+ Console.WriteLine("A child in ChannelsCanvas.Children is null.");
+ continue;
+ }
+
+ if (!(child is ChannelBox channelBox))
+ {
+ continue;
+ }
+
+ Codeplug.System system = Codeplug.GetSystemForChannel(channelBox.ChannelName);
+ if (system == null)
+ {
+ Console.WriteLine($"System not found for {channelBox.ChannelName}");
+ continue;
+ }
+
+ Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channelBox.ChannelName);
+ if (cpgChannel == null)
+ {
+ Console.WriteLine($"Channel not found for {channelBox.ChannelName}");
+ continue;
+ }
+
+ if (!system.IsDvm)
+ continue;
+
+ if (cpgChannel.GetKeyId() == 0 || cpgChannel.GetAlgoId() == 0)
+ continue;
+
+ if (channelBox.crypter == null)
+ {
+ Console.WriteLine($"Crypter is null for channel {channelBox.ChannelName}");
+ continue;
+ }
+
+ bool hasKey = channelBox.crypter.HasKey(cpgChannel.GetKeyId());
+
+ KeyStatusItems.Add(new KeyStatusItem
+ {
+ ChannelName = channelBox.ChannelName,
+ AlgId = $"0x{cpgChannel.GetAlgoId():X2}",
+ KeyId = $"0x{cpgChannel.GetKeyId():X4}",
+ KeyStatus = hasKey ? "Key Available" : "No Key"
+ });
+ }
+ });
+ }
+ }
+
+ public class KeyStatusItem
+ {
+ public string ChannelName { get; set; }
+ public string AlgId { get; set; }
+ public string KeyId { get; set; }
+ public string KeyStatus { get; set; }
+ }
+}
diff --git a/WhackerLinkConsoleV2/MainWindow.xaml b/WhackerLinkConsoleV2/MainWindow.xaml
index ef32e73..84f228f 100644
--- a/WhackerLinkConsoleV2/MainWindow.xaml
+++ b/WhackerLinkConsoleV2/MainWindow.xaml
@@ -175,6 +175,19 @@
+