diff --git a/HandheldCompanion.iss b/HandheldCompanion.iss index c4a2f7826..82349543c 100644 --- a/HandheldCompanion.iss +++ b/HandheldCompanion.iss @@ -26,7 +26,7 @@ #define InstallerVersion '0.2' #define MyAppSetupName 'Handheld Companion' #define MyBuildId 'HandheldCompanion' -#define MyAppVersion '0.21.6.0' +#define MyAppVersion '0.21.6.1' #define MyAppPublisher 'BenjaminLSR' #define MyAppCopyright 'Copyright @ BenjaminLSR' #define MyAppURL 'https://github.com/Valkirie/HandheldCompanion' diff --git a/HandheldCompanion/Controllers/IController.xaml.cs b/HandheldCompanion/Controllers/IController.xaml.cs index c6fb395ea..f4683422c 100644 --- a/HandheldCompanion/Controllers/IController.xaml.cs +++ b/HandheldCompanion/Controllers/IController.xaml.cs @@ -90,7 +90,7 @@ public partial class IController : UserControl private Thread workingThread; private bool workingThreadRunning; - protected object hidlock = new(); + protected object hidLock = new(); public virtual bool IsReady => true; public virtual bool IsWireless => false; diff --git a/HandheldCompanion/Controllers/NeptuneController.cs b/HandheldCompanion/Controllers/NeptuneController.cs index b92469a09..c58672cf9 100644 --- a/HandheldCompanion/Controllers/NeptuneController.cs +++ b/HandheldCompanion/Controllers/NeptuneController.cs @@ -289,7 +289,7 @@ private void Close() public override void Hide(bool powerCycle = true) { - lock (hidlock) + lock (hidLock) { Close(); base.Hide(powerCycle); @@ -305,7 +305,7 @@ public override void Unhide(bool powerCycle = true) if (IsExclusiveMode) return; - lock (hidlock) + lock (hidLock) { Close(); base.Unhide(powerCycle); diff --git a/HandheldCompanion/Controllers/RumbleConverter.cs b/HandheldCompanion/Controllers/RumbleConverter.cs index a9b0d0319..62658c656 100644 --- a/HandheldCompanion/Controllers/RumbleConverter.cs +++ b/HandheldCompanion/Controllers/RumbleConverter.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace HandheldCompanion.Controllers +namespace HandheldCompanion.Controllers { // Function to map the Xbox rumble value to Nintendo Switch HD Rumble public class RumbleConverter diff --git a/HandheldCompanion/Controls/ProcessEx.cs b/HandheldCompanion/Controls/ProcessEx.cs index 166d0f992..921107803 100644 --- a/HandheldCompanion/Controls/ProcessEx.cs +++ b/HandheldCompanion/Controls/ProcessEx.cs @@ -377,6 +377,7 @@ public void Dispose() Process?.Dispose(); MainThread?.Dispose(); ChildrenProcessIds.Dispose(); + ProcessWindows.Clear(); GC.SuppressFinalize(this); //now, the finalizer won't be called } diff --git a/HandheldCompanion/Devices/ASUS/ROGAlly.cs b/HandheldCompanion/Devices/ASUS/ROGAlly.cs index a220b463e..38f4a3fb7 100644 --- a/HandheldCompanion/Devices/ASUS/ROGAlly.cs +++ b/HandheldCompanion/Devices/ASUS/ROGAlly.cs @@ -129,7 +129,7 @@ public ROGAlly() OEMPowerMode = (int)AsusMode.Silent, OSPowerMode = OSPowerMode.BetterBattery, CPUBoostLevel = CPUBoostLevel.Disabled, - Guid = new("961cc777-2547-4f9d-8174-7d86181b8a7a"), + Guid = BetterBatteryGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 10.0d, 10.0d, 10.0d } }); @@ -140,7 +140,7 @@ public ROGAlly() DeviceDefault = true, OEMPowerMode = (int)AsusMode.Performance, OSPowerMode = OSPowerMode.BetterPerformance, - Guid = new("3af9B8d9-7c97-431d-ad78-34a8bfea439f"), + Guid = BetterPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 15.0d, 15.0d, 15.0d } }); @@ -151,7 +151,7 @@ public ROGAlly() DeviceDefault = true, OEMPowerMode = (int)AsusMode.Turbo, OSPowerMode = OSPowerMode.BestPerformance, - Guid = new("ded574b5-45a0-4f42-8737-46345c09c238"), + Guid = BestPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 25.0d, 25.0d, 25.0d } }); @@ -367,6 +367,8 @@ public override void Close() } } + hidDevices.Clear(); + base.Close(); } @@ -709,7 +711,6 @@ public void SendHidControlWrite(byte[] data) if (device.IsConnected) device.WriteFeatureData(data); } - } public void SetBatteryChargeLimit(int chargeLimit) diff --git a/HandheldCompanion/Devices/ASUS/ROGAllyX.cs b/HandheldCompanion/Devices/ASUS/ROGAllyX.cs new file mode 100644 index 000000000..7331c8e8c --- /dev/null +++ b/HandheldCompanion/Devices/ASUS/ROGAllyX.cs @@ -0,0 +1,33 @@ +using HandheldCompanion.Misc; +using System.Linq; +using System.Numerics; + +namespace HandheldCompanion.Devices; + +public class ROGAllyX : ROGAlly +{ + public ROGAllyX() + { + // device specific settings + ProductIllustration = "device_rog_ally_x"; + + // used to monitor OEM specific inputs + _pid = 0x1B4C; + + // overwrite ROGAlly default gyrometer axis settings + GyrometerAxis = new Vector3(1.0f, 1.0f, -1.0f); + + // overwrite ROGAlly default power profiles + PowerProfile powerProfile = DevicePowerProfiles.FirstOrDefault(profile => profile.Guid == BetterBatteryGuid); + if (powerProfile != null) + powerProfile.TDPOverrideValues = new[] { 13.0d, 13.0d, 13.0d }; + + powerProfile = DevicePowerProfiles.FirstOrDefault(profile => profile.Guid == BetterPerformanceGuid); + if (powerProfile != null) + powerProfile.TDPOverrideValues = new[] { 17.0d, 17.0d, 17.0d }; + + powerProfile = DevicePowerProfiles.FirstOrDefault(profile => profile.Guid == BestPerformanceGuid); + if (powerProfile != null) + powerProfile.TDPOverrideValues = new[] { 25.0d, 25.0d, 25.0d }; + } +} \ No newline at end of file diff --git a/HandheldCompanion/Devices/IDevice.cs b/HandheldCompanion/Devices/IDevice.cs index b58b86283..82681834e 100644 --- a/HandheldCompanion/Devices/IDevice.cs +++ b/HandheldCompanion/Devices/IDevice.cs @@ -12,7 +12,6 @@ using Sentry; using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.Linq; using System.Numerics; using System.Windows.Media; @@ -66,6 +65,10 @@ public abstract class IDevice public delegate void KeyReleasedEventHandler(ButtonFlags button); public delegate void PowerStatusChangedEventHandler(IDevice device); + public static readonly Guid BetterBatteryGuid = new Guid("961cc777-2547-4f9d-8174-7d86181b8a7a"); + public static readonly Guid BetterPerformanceGuid = new Guid("3af9B8d9-7c97-431d-ad78-34a8bfea439f"); + public static readonly Guid BestPerformanceGuid = new Guid("ded574b5-45a0-4f42-8737-46345c09c238"); + protected static OpenLibSys openLibSys; protected object updateLock = new(); @@ -479,6 +482,9 @@ public static IDevice GetCurrent() case "RC71L": device = new ROGAlly(); break; + case "RC72LA": + device = new ROGAllyX(); + break; } } break; @@ -865,48 +871,6 @@ public bool HasKey() return false; } - protected void ResumeDevices() - { - List successes = []; - - StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedDevices"); - - if (deviceInstanceIds is null) - deviceInstanceIds = []; - - foreach (string InstanceId in deviceInstanceIds) - { - if (PnPUtil.EnableDevice(InstanceId)) - successes.Add(InstanceId); - } - - foreach (string InstanceId in successes) - deviceInstanceIds.Remove(InstanceId); - - SettingsManager.SetProperty("SuspendedDevices", deviceInstanceIds); - } - - protected bool SuspendDevice(string InterfaceId) - { - PnPDevice pnPDevice = PnPDevice.GetDeviceByInterfaceId(InterfaceId); - if (pnPDevice is not null) - { - StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedDevices"); - - if (deviceInstanceIds is null) - deviceInstanceIds = []; - - if (!deviceInstanceIds.Contains(pnPDevice.InstanceId)) - deviceInstanceIds.Add(pnPDevice.InstanceId); - - SettingsManager.SetProperty("SuspendedDevices", deviceInstanceIds); - - return PnPUtil.DisableDevice(pnPDevice.InstanceId); - } - - return false; - } - public static IEnumerable GetHidDevices(int vendorId, int deviceId, int minFeatures = 1) { HidDevice[] HidDeviceList = HidDevices.Enumerate(vendorId, new int[] { deviceId }).ToArray(); diff --git a/HandheldCompanion/Devices/Lenovo/LegionGo.cs b/HandheldCompanion/Devices/Lenovo/LegionGo.cs index 955f7780b..abef4e090 100644 --- a/HandheldCompanion/Devices/Lenovo/LegionGo.cs +++ b/HandheldCompanion/Devices/Lenovo/LegionGo.cs @@ -245,7 +245,7 @@ public LegionGo() OSPowerMode = OSPowerMode.BetterBattery, CPUBoostLevel = CPUBoostLevel.Disabled, OEMPowerMode = (int)LegionMode.Quiet, - Guid = new("961cc777-2547-4f9d-8174-7d86181b8a7a"), + Guid = BetterBatteryGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 8.0d, 8.0d, 8.0d } }); @@ -257,7 +257,7 @@ public LegionGo() DeviceDefault = true, OSPowerMode = OSPowerMode.BetterPerformance, OEMPowerMode = (int)LegionMode.Balanced, - Guid = new("3af9B8d9-7c97-431d-ad78-34a8bfea439f"), + Guid = BetterPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 15.0d, 15.0d, 15.0d } }); @@ -269,7 +269,7 @@ public LegionGo() DeviceDefault = true, OSPowerMode = OSPowerMode.BestPerformance, OEMPowerMode = (int)LegionMode.Performance, - Guid = new("ded574b5-45a0-4f42-8737-46345c09c238"), + Guid = BestPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 20.0d, 20.0d, 20.0d } }); @@ -381,6 +381,8 @@ public override void Close() device.CloseDevice(); } + hidDevices.Clear(); + // Reset the fan speed to default before device shutdown/restart SetFanFullSpeedAsync(false); diff --git a/HandheldCompanion/Devices/MSI/ClawA1M.cs b/HandheldCompanion/Devices/MSI/ClawA1M.cs index f1c145db0..b17d51c7c 100644 --- a/HandheldCompanion/Devices/MSI/ClawA1M.cs +++ b/HandheldCompanion/Devices/MSI/ClawA1M.cs @@ -115,7 +115,7 @@ public ClawA1M() DeviceDefault = true, OSPowerMode = OSPowerMode.BetterBattery, CPUBoostLevel = CPUBoostLevel.Disabled, - Guid = new("961cc777-2547-4f9d-8174-7d86181b8a7a"), + Guid = BetterBatteryGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 20.0d, 20.0d, 20.0d } }); @@ -125,7 +125,7 @@ public ClawA1M() Default = true, DeviceDefault = true, OSPowerMode = OSPowerMode.BetterPerformance, - Guid = new("3af9B8d9-7c97-431d-ad78-34a8bfea439f"), + Guid = BetterPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 30.0d, 30.0d, 30.0d } }); @@ -135,7 +135,7 @@ public ClawA1M() Default = true, DeviceDefault = true, OSPowerMode = OSPowerMode.BestPerformance, - Guid = new("ded574b5-45a0-4f42-8737-46345c09c238"), + Guid = BestPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 35.0d, 35.0d, 35.0d } }); diff --git a/HandheldCompanion/Devices/Minisforum/MinisforumV3.cs b/HandheldCompanion/Devices/Minisforum/MinisforumV3.cs index 18baf305d..1e1d6ce2e 100644 --- a/HandheldCompanion/Devices/Minisforum/MinisforumV3.cs +++ b/HandheldCompanion/Devices/Minisforum/MinisforumV3.cs @@ -1,5 +1,4 @@ using HandheldCompanion.Managers; -using HandheldCompanion.Misc; using System.Collections.Generic; using System.Numerics; using System.Runtime.InteropServices; @@ -63,7 +62,7 @@ public MinisforumV3() OSPowerMode = OSPowerMode.BetterBattery, OEMPowerMode = (int)MinisForumMode.Quiet, CPUBoostLevel = CPUBoostLevel.Disabled, - Guid = new("961cc777-2547-4f9d-8174-7d86181b8a7a"), + Guid = BetterBatteryGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 15.0d, 15.0d, 15.0d } }); @@ -74,7 +73,7 @@ public MinisforumV3() DeviceDefault = true, OSPowerMode = OSPowerMode.BetterPerformance, OEMPowerMode = (int)MinisForumMode.Balanced, - Guid = new("3af9B8d9-7c97-431d-ad78-34a8bfea439f"), + Guid = BetterPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 22.0d, 22.0d, 22.0d } }); @@ -85,7 +84,7 @@ public MinisforumV3() DeviceDefault = true, OSPowerMode = OSPowerMode.BestPerformance, OEMPowerMode = (int)MinisForumMode.Performance, - Guid = new("ded574b5-45a0-4f42-8737-46345c09c238"), + Guid = BestPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 28.0d, 28.0d, 28.0d } }); diff --git a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1.cs b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1.cs index 8818be810..7c1b19f50 100644 --- a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1.cs +++ b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1.cs @@ -129,23 +129,27 @@ public override bool Open() if (EnableSerialPort) { - var devices = GetSerialDevices(); + List devices = GetSerialDevices(); USBDeviceInfo deviceInfo = devices.FirstOrDefault(a => a.Name.Contains(SerialPortDeviceName)); - - var SerialPortName = Regex.Match(deviceInfo.Name, "COM\\d+").Value; - - // Add the serial port name to be excluded for other instances - SerialUSBIMU.SerialPortNamesInUse.Add(SerialPortName); - - // Initialize and open the serial port if it has not been initialized yet - if (_serialPort is null) + if (deviceInfo is null) { - _serialPort = new SerialPort(SerialPortName, SerialPortBaudRate, SerialPortParity, SerialPortDataBits, - SerialPortStopBits); - _serialPort.Open(); - - LogManager.LogInformation("Enabled Serial Port Control: {0}", _serialPort.PortName); + LogManager.LogInformation("Failed to retrieve serial device with name: {0}", SerialPortDeviceName); + } + else + { + // Add the serial port name to be excluded for other instances + string SerialPortName = Regex.Match(deviceInfo.Name, "COM\\d+").Value; + SerialUSBIMU.SerialPortNamesInUse.Add(SerialPortName); + + // Initialize and open the serial port if it has not been initialized yet + if (_serialPort is null) + { + _serialPort = new SerialPort(SerialPortName, SerialPortBaudRate, SerialPortParity, SerialPortDataBits, SerialPortStopBits); + _serialPort.Open(); + + LogManager.LogInformation("Enabled Serial Port Control: {0}", _serialPort.PortName); + } } } diff --git a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1Intel.cs b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1Intel.cs index 87b816c5d..1b993e36d 100644 --- a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1Intel.cs +++ b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1Intel.cs @@ -20,7 +20,7 @@ public OneXPlayerX1Intel() DeviceDefault = true, OSPowerMode = OSPowerMode.BetterBattery, CPUBoostLevel = CPUBoostLevel.Disabled, - Guid = new("961cc777-2547-4f9d-8174-7d86181b8a7a"), + Guid = BetterBatteryGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 15.0d, 15.0d, 15.0d } }); @@ -32,7 +32,7 @@ public OneXPlayerX1Intel() DeviceDefault = true, OSPowerMode = OSPowerMode.BetterPerformance, CPUBoostLevel = CPUBoostLevel.Enabled, - Guid = new("3af9B8d9-7c97-431d-ad78-34a8bfea439f"), + Guid = BetterPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 30.0d, 30.0d, 30.0d } }); @@ -44,7 +44,7 @@ public OneXPlayerX1Intel() DeviceDefault = true, OSPowerMode = OSPowerMode.BestPerformance, CPUBoostLevel = CPUBoostLevel.Enabled, - Guid = new("ded574b5-45a0-4f42-8737-46345c09c238"), + Guid = BestPerformanceGuid, TDPOverrideEnabled = true, TDPOverrideValues = new[] { 35.0d, 35.0d, 64.0d }, EPPOverrideEnabled = true, diff --git a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1Mini.cs b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1Mini.cs index 61dd57882..8d8bf86ea 100644 --- a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1Mini.cs +++ b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerX1Mini.cs @@ -9,5 +9,7 @@ public OneXPlayerX1Mini() cTDP = new double[] { 15, 30 }; GfxClock = new double[] { 100, 2700 }; CpuClock = 5100; + + EnableSerialPort = false; } } diff --git a/HandheldCompanion/HandheldCompanion.csproj b/HandheldCompanion/HandheldCompanion.csproj index 5c432154c..3ab4ad427 100644 --- a/HandheldCompanion/HandheldCompanion.csproj +++ b/HandheldCompanion/HandheldCompanion.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -12,7 +12,7 @@ HandheldCompanion.App $(SolutionDir)bin\$(Configuration) Resources\icon.ico - 0.21.6.0 + 0.21.6.1 app.manifest AnyCPU;x64;x86 true @@ -81,6 +81,7 @@ + @@ -179,6 +180,7 @@ + @@ -201,7 +203,7 @@ - + @@ -210,17 +212,17 @@ - - + + - - - + + + - + diff --git a/HandheldCompanion/Managers/ControllerManager.cs b/HandheldCompanion/Managers/ControllerManager.cs index 4251e1d32..5c478f57a 100644 --- a/HandheldCompanion/Managers/ControllerManager.cs +++ b/HandheldCompanion/Managers/ControllerManager.cs @@ -10,12 +10,13 @@ using Nefarius.Utilities.DeviceManagement.Drivers; using Nefarius.Utilities.DeviceManagement.Extensions; using Nefarius.Utilities.DeviceManagement.PnP; +using Newtonsoft.Json; using SharpDX.DirectInput; using SharpDX.XInput; using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Collections.Specialized; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -79,6 +80,9 @@ static ControllerManager() public static Task Start() { + // get driver store + DriversStore = DeserializeDriverStore(); + // Flushing possible JoyShocks... JslDisconnectAndDisposeAll(); @@ -91,8 +95,10 @@ public static Task Start() SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged; + /* UIGamepad.GotFocus += GamepadFocusManager_GotFocus; UIGamepad.LostFocus += GamepadFocusManager_LostFocus; + */ ProcessManager.ForegroundChanged += ProcessManager_ForegroundChanged; @@ -167,6 +173,7 @@ private enum FocusedWindow Quicktools } + /* private static void GamepadFocusManager_LostFocus(string Name) { switch (Name) @@ -200,6 +207,7 @@ private static void GamepadFocusManager_GotFocus(string Name) // check applicable scenarios CheckControllerScenario(); } + */ private static void ProcessManager_ForegroundChanged(ProcessEx? processEx, ProcessEx? backgroundEx) { @@ -273,10 +281,11 @@ private static void ScenarioTimer_Elapsed(object? sender, ElapsedEventArgs e) } } + /* // either main window or quicktools are focused - // set flag if (focusedWindows != FocusedWindow.None) ControllerMuted = true; + */ } private static void CheckControllerScenario() @@ -717,9 +726,7 @@ private static void watchdogThreadLoop(object? obj) if (ControllerManagementAttempts == ControllerManagementMaxAttempts) { // resume all physical controllers - StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedControllers"); - if (deviceInstanceIds is not null && deviceInstanceIds.Count != 0) - ResumeControllers(); + ResumeControllers(); UpdateStatus(ControllerManagerStatus.Failed); ControllerManagementAttempts = 0; @@ -760,9 +767,7 @@ private static void watchdogThreadLoop(object? obj) VirtualManager.Resume(false); // resume all physical controllers - StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedControllers"); - if (deviceInstanceIds is not null && deviceInstanceIds.Count != 0) - ResumeControllers(); + ResumeControllers(); // suspend and resume virtual controller VirtualManager.Suspend(false); @@ -777,9 +782,7 @@ private static void watchdogThreadLoop(object? obj) else { // resume all physical controllers - StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedControllers"); - if (deviceInstanceIds is not null && deviceInstanceIds.Count != 0) - ResumeControllers(); + ResumeControllers(); // give us one extra loop to make sure we're good if (managerStatus != ControllerManagerStatus.Succeeded) @@ -1014,14 +1017,11 @@ public static void SetTargetController(string baseContainerDeviceInstanceId, boo } } + public static string DriversPath = Path.Combine(MainWindow.SettingsPath, "drivers.json"); + public static Dictionary DriversStore = []; + public static bool SuspendController(string baseContainerDeviceInstanceId) { - // PnPUtil.StartPnPUtil(@"/delete-driver C:\Windows\INF\xusb22.inf /uninstall /force"); - StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedControllers"); - - if (deviceInstanceIds is null) - deviceInstanceIds = []; - try { PnPDevice pnPDevice = PnPDevice.GetDeviceByInstanceId(baseContainerDeviceInstanceId); @@ -1038,16 +1038,15 @@ public static bool SuspendController(string baseContainerDeviceInstanceId) switch (enumerator) { case "USB": - if (pnPDriver is not null) + if (!string.IsNullOrEmpty(pnPDriver?.InfPath)) { + // store driver to collection + AddOrUpdateDriverStore(baseContainerDeviceInstanceId, pnPDriver.InfPath); + pnPDevice.InstallNullDriver(out bool rebootRequired); usbPnPDevice.CyclePort(); } - if (!deviceInstanceIds.Contains(baseContainerDeviceInstanceId)) - deviceInstanceIds.Add(baseContainerDeviceInstanceId); - - SettingsManager.SetProperty("SuspendedControllers", deviceInstanceIds); PowerCyclers[baseContainerDeviceInstanceId] = true; return true; } @@ -1059,20 +1058,16 @@ public static bool SuspendController(string baseContainerDeviceInstanceId) public static bool ResumeControllers() { - // PnPUtil.StartPnPUtil(@"/add-driver C:\Windows\INF\xusb22.inf /install"); - StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedControllers"); - - if (deviceInstanceIds is null || deviceInstanceIds.Count == 0) - return true; - - foreach (string baseContainerDeviceInstanceId in deviceInstanceIds) + // loop through controllers + foreach (string baseContainerDeviceInstanceId in DriversStore.Keys) { try { PnPDevice pnPDevice = PnPDevice.GetDeviceByInstanceId(baseContainerDeviceInstanceId); UsbPnPDevice usbPnPDevice = pnPDevice.ToUsbPnPDevice(); - DriverMeta pnPDriver = null; + // get current driver + DriverMeta pnPDriver = null; try { pnPDriver = pnPDevice.GetCurrentDriver(); @@ -1083,18 +1078,21 @@ public static bool ResumeControllers() switch (enumerator) { case "USB": - if (pnPDriver is null || pnPDriver.InfPath != "xusb22.inf") { - pnPDevice.RemoveAndSetup(); - pnPDevice.InstallCustomDriver("xusb22.inf", out bool rebootRequired); - } + // todo: check PnPDevice PID/VID to deploy the appropriate inf + string InfPath = GetDriverFromDriverStore(baseContainerDeviceInstanceId); + if (pnPDriver?.InfPath != InfPath && !string.IsNullOrEmpty(InfPath)) + { + pnPDevice.RemoveAndSetup(); + pnPDevice.InstallCustomDriver(InfPath, out bool rebootRequired); + } - if (deviceInstanceIds.Contains(baseContainerDeviceInstanceId)) - deviceInstanceIds.Remove(baseContainerDeviceInstanceId); + // remove device from store + RemoveFromDriverStore(baseContainerDeviceInstanceId); - SettingsManager.SetProperty("SuspendedControllers", deviceInstanceIds); - PowerCyclers.TryRemove(baseContainerDeviceInstanceId, out _); - return true; + PowerCyclers.TryRemove(baseContainerDeviceInstanceId, out _); + return true; + } } } catch { } @@ -1103,6 +1101,53 @@ public static bool ResumeControllers() return false; } + private static void SerializeDriverStore() + { + string json = JsonConvert.SerializeObject(DriversStore, Formatting.Indented); + File.WriteAllText(DriversPath, json); + } + + private static Dictionary DeserializeDriverStore() + { + if (!File.Exists(DriversPath)) + return []; + + string json = File.ReadAllText(DriversPath); + return JsonConvert.DeserializeObject>(json); + } + + private static string GetDriverFromDriverStore(string path) + { + if (DriversStore.TryGetValue(path, out string driver)) + return driver; + + return "xusb22.inf"; + } + + private static void AddOrUpdateDriverStore(string path, string calibration) + { + // upcase + path = path.ToUpper(); + + // update array + DriversStore[path] = calibration; + + // serialize store + SerializeDriverStore(); + } + + private static void RemoveFromDriverStore(string path) + { + // upcase + path = path.ToUpper(); + + // update array + DriversStore.Remove(path); + + // serialize store + SerializeDriverStore(); + } + public static IController GetTargetController() { return targetController; @@ -1172,6 +1217,7 @@ private static void UpdateInputs(ControllerState controllerState, GamepadMotion { // compute layout controllerState = LayoutManager.MapController(controllerState); + InputsUpdated2?.Invoke(controllerState); } VirtualManager.UpdateInputs(controllerState, gamepadMotion); @@ -1213,9 +1259,20 @@ internal static IController GetEmulatedController() public static event ControllerSelectedEventHandler ControllerSelected; public delegate void ControllerSelectedEventHandler(IController Controller); + /// + /// Controller state has changed, before layout manager + /// + /// The updated controller state. public static event InputsUpdatedEventHandler InputsUpdated; public delegate void InputsUpdatedEventHandler(ControllerState Inputs); + /// + /// Controller state has changed, after layout manager + /// + /// The updated controller state. + public static event InputsUpdated2EventHandler InputsUpdated2; + public delegate void InputsUpdated2EventHandler(ControllerState Inputs); + public static event StatusChangedEventHandler StatusChanged; public delegate void StatusChangedEventHandler(ControllerManagerStatus status, int attempts); diff --git a/HandheldCompanion/Managers/DeviceManager.cs b/HandheldCompanion/Managers/DeviceManager.cs index 6d15ab843..34b0414e4 100644 --- a/HandheldCompanion/Managers/DeviceManager.cs +++ b/HandheldCompanion/Managers/DeviceManager.cs @@ -78,8 +78,9 @@ static DeviceManager() public static void Start() { - // fail-safe - PnPUtil.StartPnPUtil(@"/add-driver C:\Windows\INF\xusb22.inf /install"); + // fail-safe: restore drivers from incomplete controller suspend/resume process (if any) + foreach (string InfPath in ControllerManager.DriversStore.Values) + PnPUtil.StartPnPUtil($@"/add-driver C:\Windows\INF\{InfPath} /install"); UsbDeviceListener.StartListen(DeviceInterfaceIds.UsbDevice); UsbDeviceListener.DeviceArrived += UsbDevice_DeviceArrived; @@ -122,8 +123,9 @@ public static void Stop() HidDeviceListener.DeviceArrived -= HidDevice_DeviceArrived; HidDeviceListener.DeviceRemoved -= HidDevice_DeviceRemoved; - // fail-safe - PnPUtil.StartPnPUtil(@"/add-driver C:\Windows\INF\xusb22.inf /install"); + // fail-safe: restore drivers from incomplete controller suspend/resume process (if any) + foreach (string InfPath in ControllerManager.DriversStore.Values) + PnPUtil.StartPnPUtil($@"/add-driver C:\Windows\INF\{InfPath} /install"); LogManager.LogInformation("{0} has stopped", "DeviceManager"); } diff --git a/HandheldCompanion/Managers/InputsManager.cs b/HandheldCompanion/Managers/InputsManager.cs index 0462e3aa4..b72e5adbd 100644 --- a/HandheldCompanion/Managers/InputsManager.cs +++ b/HandheldCompanion/Managers/InputsManager.cs @@ -442,7 +442,13 @@ private static void M_GlobalHook_KeyEvent(object? sender, KeyEventArgs e) switch (args.KeyValue) { case 165: + // KeyboardSimulator.KeyUp((VirtualKeyCode)KeyCode.RMenu); + KeyboardSimulator.KeyUp((VirtualKeyCode)KeyCode.LMenu); KeyboardSimulator.KeyUp((VirtualKeyCode)KeyCode.LControl); + KeyboardSimulator.KeyUp((VirtualKeyCode)KeyCode.RControl); + KeyboardSimulator.KeyUp((VirtualKeyCode)KeyCode.Alt); + KeyboardSimulator.KeyUp((VirtualKeyCode)KeyCode.LAlt); + // KeyboardSimulator.KeyUp((VirtualKeyCode)KeyCode.RAlt); break; } } diff --git a/HandheldCompanion/Managers/PerformanceManager.cs b/HandheldCompanion/Managers/PerformanceManager.cs index ac83597fe..b9aaf243b 100644 --- a/HandheldCompanion/Managers/PerformanceManager.cs +++ b/HandheldCompanion/Managers/PerformanceManager.cs @@ -17,7 +17,7 @@ public static class OSPowerMode /// /// Better Battery mode. /// - public static Guid BetterBattery = new("961cc777-2547-4f9d-8174-7d86181b8a7a"); + public static Guid BetterBattery = IDevice.BetterBatteryGuid; /// /// Better Performance mode. @@ -28,7 +28,7 @@ public static class OSPowerMode /// /// Best Performance mode. /// - public static Guid BestPerformance = new("ded574b5-45a0-4f42-8737-46345c09c238"); + public static Guid BestPerformance = IDevice.BestPerformanceGuid; } public enum CPUBoostLevel diff --git a/HandheldCompanion/Managers/ProcessManager.cs b/HandheldCompanion/Managers/ProcessManager.cs index c8b619a22..38f24147c 100644 --- a/HandheldCompanion/Managers/ProcessManager.cs +++ b/HandheldCompanion/Managers/ProcessManager.cs @@ -306,10 +306,8 @@ private static void ProcessHalted(object? sender, EventArgs e) ForegroundChanged?.Invoke(null, foregroundProcess); } - bool success = Processes.TryRemove(new KeyValuePair(processId, processEx)); - // raise event - if (success) + if (Processes.TryRemove(processId, out _)) { ProcessStopped?.Invoke(processEx); diff --git a/HandheldCompanion/Managers/VirtualManager.cs b/HandheldCompanion/Managers/VirtualManager.cs index 417c2ed6d..4f383b3a1 100644 --- a/HandheldCompanion/Managers/VirtualManager.cs +++ b/HandheldCompanion/Managers/VirtualManager.cs @@ -111,24 +111,19 @@ public static void Resume(bool OS) // update DSU status SetDSUStatus(SettingsManager.GetBoolean("DSUEnabled")); } - - // set controller mode - SetControllerMode(HIDmode); } + + // set controller mode + SetControllerMode(HIDmode); } public static void Suspend(bool OS) { + // dispose virtual controller + SetControllerMode(HIDmode.NoController); + lock (threadLock) { - // dispose virtual controller - if (vTarget is not null) - { - vTarget.Disconnect(); - vTarget.Dispose(); - vTarget = null; - } - if (OS) { // dispose ViGEm drivers @@ -247,12 +242,7 @@ public static void SetControllerMode(HIDmode mode) { default: case HIDmode.NoController: - if (vTarget is not null) - { - vTarget.Disconnect(); - vTarget.Dispose(); - vTarget = null; - } + // controller was disposed already above break; case HIDmode.DualShock4Controller: diff --git a/HandheldCompanion/Properties/Settings.Designer.cs b/HandheldCompanion/Properties/Settings.Designer.cs index ecfe53096..ce0a6666b 100644 --- a/HandheldCompanion/Properties/Settings.Designer.cs +++ b/HandheldCompanion/Properties/Settings.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 @@ -7,15 +7,16 @@ // the code is regenerated. // //------------------------------------------------------------------------------ + using System.Configuration; -namespace HandheldCompanion.Properties -{ +namespace HandheldCompanion.Properties { [SettingsProvider(typeof(CustomSettingsProvider))] internal sealed partial class Settings : ApplicationSettingsBase { + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); public static Settings Default { @@ -732,17 +733,6 @@ public bool ControllerManagement { } } - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public global::System.Collections.Specialized.StringCollection SuspendedControllers { - get { - return ((global::System.Collections.Specialized.StringCollection)(this["SuspendedControllers"])); - } - set { - this["SuspendedControllers"] = value; - } - } - [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("False")] @@ -935,17 +925,6 @@ public int LEDPresetIndex { } } - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public global::System.Collections.Specialized.StringCollection SuspendedDevices { - get { - return ((global::System.Collections.Specialized.StringCollection)(this["SuspendedDevices"])); - } - set { - this["SuspendedDevices"] = value; - } - } - [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("False")] diff --git a/HandheldCompanion/Properties/Settings.settings b/HandheldCompanion/Properties/Settings.settings index 73fbc98ec..9228258d2 100644 --- a/HandheldCompanion/Properties/Settings.settings +++ b/HandheldCompanion/Properties/Settings.settings @@ -179,9 +179,6 @@ True - - - False @@ -230,9 +227,6 @@ 0 - - - False diff --git a/HandheldCompanion/Resources/DeviceImages/device_rog_ally_x.png b/HandheldCompanion/Resources/DeviceImages/device_rog_ally_x.png new file mode 100644 index 000000000..91cf3ce9a Binary files /dev/null and b/HandheldCompanion/Resources/DeviceImages/device_rog_ally_x.png differ diff --git a/HandheldCompanion/UI/UIGamepad.cs b/HandheldCompanion/UI/UIGamepad.cs index adfdf1630..1abc9e622 100644 --- a/HandheldCompanion/UI/UIGamepad.cs +++ b/HandheldCompanion/UI/UIGamepad.cs @@ -96,7 +96,7 @@ public UIGamepad(GamepadWindow gamepadWindow, Frame contentFrame) tooltipTimer = new Timer(2000) { AutoReset = false }; tooltipTimer.Elapsed += TooltipTimer_Elapsed; - ControllerManager.InputsUpdated += InputsUpdated; + ControllerManager.InputsUpdated2 += InputsUpdated; } private void _currentWindow_ContentDialogClosed(ContentDialog contentDialog) @@ -618,7 +618,7 @@ private void InputsUpdated(ControllerState controllerState) // get the associated ComboBox comboBox = ItemsControl.ItemsControlFromItemContainer(focusedElement) as ComboBox; - if (comboBox.IsDropDownOpen) + if (comboBox.IsDropDownOpen && comboBoxItem.IsEnabled) { int idx = comboBox.Items.IndexOf(comboBoxItem); if (idx == -1) @@ -880,22 +880,39 @@ private void InputsUpdated(ControllerState controllerState) if (idx == -1) idx = comboBox.Items.IndexOf(comboBoxItem.Content); - switch (direction) + while (true) // Loop to skip disabled items { - case WPFUtils.Direction.Up: - idx--; - break; + switch (direction) + { + case WPFUtils.Direction.Up: + idx--; + break; - case WPFUtils.Direction.Down: - idx++; + case WPFUtils.Direction.Down: + idx++; + break; + } + + // Ensure index is within bounds + if (idx < 0 || idx >= comboBox.Items.Count) + { + // We've reached the top or bottom, so stop the loop break; - } + } - // Get the ComboBoxItem - idx = Math.Max(0, Math.Min(comboBox.Items.Count - 1, idx)); + // Get the ComboBoxItem at the new index + focusedElement = (ComboBoxItem)comboBox.ItemContainerGenerator.ContainerFromIndex(idx); - focusedElement = (ComboBoxItem)comboBox.ItemContainerGenerator.ContainerFromIndex(idx); - Focus(focusedElement, comboBox, true); + // Check if the focused element is enabled + if (focusedElement != null && focusedElement.IsEnabled) + { + // If the element is enabled, focus it and break out of the loop + Focus(focusedElement, comboBox, true); + break; + } + + // If the element is not enabled, continue to the next item in the loop + } } return; } diff --git a/HandheldCompanion/Utils/DeviceUtils.cs b/HandheldCompanion/Utils/DeviceUtils.cs index e3779932a..327fa18da 100644 --- a/HandheldCompanion/Utils/DeviceUtils.cs +++ b/HandheldCompanion/Utils/DeviceUtils.cs @@ -57,21 +57,17 @@ public static USBDeviceInfo GetUSBDevice(string DeviceId) public static List GetSerialDevices() { - var serials = new List(); + List serials = new List(); try { - using (var searcher = - new ManagementObjectSearcher( - "SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%COM%' AND PNPClass = 'Ports'")) + using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%COM%' AND PNPClass = 'Ports'")) { - var devices = searcher.Get().Cast().ToList(); - foreach (var device in devices) + List devices = searcher.Get().Cast().ToList(); + foreach (ManagementBaseObject device in devices) serials.Add(new USBDeviceInfo(device)); } } - catch - { - } + catch { } return serials; } diff --git a/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml.cs b/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml.cs index 4efdca2ef..f5214f897 100644 --- a/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml.cs +++ b/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml.cs @@ -935,7 +935,7 @@ private void Button_PowerSettings_Create_Click(object sender, RoutedEventArgs e) }; PowerProfileManager.UpdateOrCreateProfile(powerProfile, UpdateSource.Creation); - + // localize me new Dialog(OverlayQuickTools.GetCurrent()) { diff --git a/HandheldCompanion/Views/SplashScreen.xaml b/HandheldCompanion/Views/SplashScreen.xaml index 5209f700a..64bd50c85 100644 --- a/HandheldCompanion/Views/SplashScreen.xaml +++ b/HandheldCompanion/Views/SplashScreen.xaml @@ -4,9 +4,10 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:common="clr-namespace:HandheldCompanion.Views.Classes" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:resx="clr-namespace:HandheldCompanion.Properties" - xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf" + xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" Width="450" Height="450" ui:ThemeManager.IsThemeAware="True" @@ -22,19 +23,13 @@ Margin="0,0,0,32" HorizontalAlignment="Center" VerticalAlignment="Center"> - - - - + + diff --git a/HandheldCompanion/Views/Windows/MainWindow.xaml.cs b/HandheldCompanion/Views/Windows/MainWindow.xaml.cs index 9a589f58d..9f1423b4e 100644 --- a/HandheldCompanion/Views/Windows/MainWindow.xaml.cs +++ b/HandheldCompanion/Views/Windows/MainWindow.xaml.cs @@ -24,7 +24,6 @@ using System.Windows.Input; using System.Windows.Interop; using System.Windows.Navigation; -using System.Windows.Threading; using Windows.UI.ViewManagement; using Application = System.Windows.Application; using Control = System.Windows.Controls.Control; @@ -99,8 +98,6 @@ public MainWindow(FileVersionInfo _fileVersionInfo, Assembly CurrentAssembly) #endif } - SplashScreen.LoadingSequence.Text = "Preparing UI..."; - InitializeComponent(); this.Tag = "MainWindow"; @@ -160,7 +157,6 @@ public MainWindow(FileVersionInfo _fileVersionInfo, Assembly CurrentAssembly) Title += $" ({fileVersionInfo.FileVersion})"; // initialize device - SplashScreen.LoadingSequence.Text = "Initializing device..."; CurrentDevice = IDevice.GetCurrent(); CurrentDevice.PullSensors(); @@ -184,18 +180,10 @@ public MainWindow(FileVersionInfo _fileVersionInfo, Assembly CurrentAssembly) UISounds uiSounds = new UISounds(); // load window(s) - SplashScreen.LoadingSequence.Text = "Drawing windows..."; - Dispatcher.Invoke(new Action(() => - { - loadWindows(); - }), DispatcherPriority.Background); // Lower priority + loadWindows(); // load page(s) - SplashScreen.LoadingSequence.Text = "Drawing pages..."; - Dispatcher.Invoke(new Action(() => - { - loadPages(); - }), DispatcherPriority.Background); // Lower priority + loadPages(); // manage events SystemManager.SystemStatusChanged += OnSystemStatusChanged; @@ -206,8 +194,7 @@ public MainWindow(FileVersionInfo _fileVersionInfo, Assembly CurrentAssembly) ToastManager.Start(); ToastManager.IsEnabled = SettingsManager.GetBoolean("ToastEnable"); - // start static managers in sequence - SplashScreen.LoadingSequence.Text = "Initializing managers..."; + // start static managers in sequence GPUManager.Start(); PowerProfileManager.Start(); ProfileManager.Start(); @@ -574,6 +561,9 @@ private async void OnSystemStatusChanged(SystemManager.SystemStatus status, Syst // close current device CurrentDevice.Close(); + // free memory + GC.Collect(); + // Allow system to sleep SystemManager.SetThreadExecutionState(SystemManager.ES_CONTINUOUS); LogManager.LogDebug("Tasks completed. System can now suspend if needed.");