diff --git a/app/AsusMouseSettings.cs b/app/AsusMouseSettings.cs index 8bf30f6a..ac5b2a4a 100644 --- a/app/AsusMouseSettings.cs +++ b/app/AsusMouseSettings.cs @@ -376,9 +376,11 @@ namespace GHelper sliderDPI.Max = mouse.MaxDPI(); sliderDPI.Min = mouse.MinDPI(); + sliderDPI.Step = mouse.DPIIncrements(); numericUpDownCurrentDPI.Minimum = mouse.MinDPI(); numericUpDownCurrentDPI.Maximum = mouse.MaxDPI(); + numericUpDownCurrentDPI.Increment = mouse.DPIIncrements(); if (!mouse.HasDPIColors()) @@ -391,9 +393,9 @@ namespace GHelper buttonDPI4.Image = ControlHelper.TintImage(Properties.Resources.lighting_dot_24, Color.Green); buttonDPI1.BorderColor = Color.Red; - buttonDPI1.BorderColor = Color.Purple; - buttonDPI1.BorderColor = Color.Blue; - buttonDPI1.BorderColor = Color.Green; + buttonDPI2.BorderColor = Color.Purple; + buttonDPI3.BorderColor = Color.Blue; + buttonDPI4.BorderColor = Color.Green; } if (mouse.CanSetPollingRate()) @@ -473,6 +475,8 @@ namespace GHelper if (mouse.HasRGB()) { + sliderBrightness.Max = mouse.MaxBrightness(); + foreach (LightingMode lm in Enum.GetValues(typeof(LightingMode))) { if (mouse.IsLightingModeSupported(lm)) diff --git a/app/Peripherals/Mouse/AsusMouse.cs b/app/Peripherals/Mouse/AsusMouse.cs index 35cf9134..a49d6f33 100644 --- a/app/Peripherals/Mouse/AsusMouse.cs +++ b/app/Peripherals/Mouse/AsusMouse.cs @@ -211,9 +211,14 @@ namespace GHelper.Peripherals.Mouse } } + public virtual int USBTimeout() + { + return 300; + } + public override void SetProvider() { - _usbProvider = new WindowsUsbProvider(_vendorId, _productId, path); + _usbProvider = new WindowsUsbProvider(_vendorId, _productId, path, USBTimeout()); } protected virtual void OnDisconnect() @@ -235,6 +240,21 @@ namespace GHelper.Peripherals.Mouse #endif } + protected virtual bool IsMouseError(byte[] packet) + { + return packet[1] == 0xFF && packet[2] == 0xAA; + } + + protected virtual long MeasuredIO(Action ioFunc, byte[] param) + { + var watch = System.Diagnostics.Stopwatch.StartNew(); + + ioFunc(param); + + watch.Stop(); + return watch.ElapsedMilliseconds; + } + [MethodImpl(MethodImplOptions.Synchronized)] protected virtual byte[]? WriteForResponse(byte[] packet) { @@ -245,12 +265,31 @@ namespace GHelper.Peripherals.Mouse if (IsPacketLoggerEnabled()) Logger.WriteLine(GetDisplayName() + ": Sending packet: " + ByteArrayToString(packet)); - Write(packet); + long time = MeasuredIO(Write, packet); + Logger.WriteLine(GetDisplayName() + ": Write took " + time + "ms"); - Read(response); + time = MeasuredIO(Read, response); + Logger.WriteLine(GetDisplayName() + ": Read took " + time + "ms"); if (IsPacketLoggerEnabled()) Logger.WriteLine(GetDisplayName() + ": Read packet: " + ByteArrayToString(response)); + + if (IsMouseError(response)) + { + Logger.WriteLine(GetDisplayName() + ": Mouse returned error (FF AA). Packet probably not supported by mouse firmware."); + //Error. Mouse could not understand or process the sent packet + return response; + } + + //Not the response we were looking for, continue reading + while (response[0] != packet[0] || response[1] != packet[1] || response[2] != packet[2]) + { + Logger.WriteLine(GetDisplayName() + ": Read wrong packet left in buffer: " + ByteArrayToString(response) + ". Retrying..."); + //Read again + time = MeasuredIO(Read, response); + Logger.WriteLine(GetDisplayName() + ": Read took " + time + "ms"); + } + } catch (IOException e) { @@ -258,12 +297,12 @@ namespace GHelper.Peripherals.Mouse OnDisconnect(); return null; } - catch (System.TimeoutException e) + catch (TimeoutException e) { Logger.WriteLine(GetDisplayName() + ": Timeout reading packet " + e.Message); return null; } - catch (System.ObjectDisposedException e) + catch (ObjectDisposedException) { Logger.WriteLine(GetDisplayName() + ": Channel closed "); OnDisconnect(); @@ -295,9 +334,9 @@ namespace GHelper.Peripherals.Mouse ReadProfile(); ReadDPI(); - ReadLightingSetting(); - ReadLiftOffDistance(); ReadPollingRate(); + ReadLiftOffDistance(); + ReadLightingSetting(); } // ------------------------------------------------------------------------------ @@ -695,6 +734,11 @@ namespace GHelper.Peripherals.Mouse return false; } + public virtual int DPIIncrements() + { + return 50; + } + public virtual bool CanChangeDPIProfile() { return DPIProfileCount() > 1; @@ -709,6 +753,11 @@ namespace GHelper.Peripherals.Mouse return 100; } + public virtual bool HasXYDPI() + { + return false; + } + protected virtual byte[] GetChangeDPIProfilePacket(int profile) { return new byte[] { 0x00, 0x51, 0x31, 0x0A, 0x00, (byte)profile }; @@ -720,7 +769,7 @@ namespace GHelper.Peripherals.Mouse } //profiles start to count at 1 - public void SetDPIProfile(int profile) + public virtual void SetDPIProfile(int profile) { if (!CanChangeDPIProfile()) { @@ -745,6 +794,11 @@ namespace GHelper.Peripherals.Mouse protected virtual byte[] GetReadDPIPacket() { + if (!HasXYDPI()) + { + return new byte[] { 0x00, 0x12, 0x04, 0x00 }; + } + return new byte[] { 0x00, 0x12, 0x04, 0x02 }; } @@ -758,7 +812,7 @@ namespace GHelper.Peripherals.Mouse { return null; } - ushort dpiEncoded = (ushort)((dpi.DPI - 50) / 50); + ushort dpiEncoded = (ushort)((dpi.DPI - DPIIncrements()) / DPIIncrements()); if (HasDPIColors()) { @@ -773,7 +827,7 @@ namespace GHelper.Peripherals.Mouse protected virtual void ParseDPI(byte[] packet) { - if (packet[1] != 0x12 || packet[2] != 0x04 || packet[3] != 0x02) + if (packet[1] != 0x12 || packet[2] != 0x04 || (packet[3] != 0x02 && HasXYDPI())) { return; } @@ -785,12 +839,13 @@ namespace GHelper.Peripherals.Mouse DpiSettings[i] = new AsusMouseDPI(); } - int offset = 5 + (i * 4); + int offset = HasXYDPI() ? (5 + (i * 4)) : (5 + (i * 2)); + uint b1 = packet[offset]; uint b2 = packet[offset + 1]; - DpiSettings[i].DPI = (uint)(b2 << 8 | b1) * 50 + 50; + DpiSettings[i].DPI = (uint)((b2 << 8 | b1) * DPIIncrements() + DPIIncrements()); } } @@ -931,6 +986,11 @@ namespace GHelper.Peripherals.Mouse return false; } + public virtual int MaxBrightness() + { + return 100; + } + //Override to remap lighting mode IDs. //From OpenRGB code it looks like some mice have different orders of the modes or do not support some modes at all. protected virtual byte IndexForLightingMode(LightingMode lightingMode) diff --git a/app/Peripherals/Mouse/Models/ChakramX.cs b/app/Peripherals/Mouse/Models/ChakramX.cs index f4ecde35..f630e3c2 100644 --- a/app/Peripherals/Mouse/Models/ChakramX.cs +++ b/app/Peripherals/Mouse/Models/ChakramX.cs @@ -45,6 +45,11 @@ namespace GHelper.Peripherals.Mouse.Models return 36_000; } + public override bool HasXYDPI() + { + return true; + } + public override bool HasLiftOffSetting() { return true; diff --git a/app/Peripherals/Mouse/Models/GladiusIII.cs b/app/Peripherals/Mouse/Models/GladiusIIIAimpoint.cs similarity index 77% rename from app/Peripherals/Mouse/Models/GladiusIII.cs rename to app/Peripherals/Mouse/Models/GladiusIIIAimpoint.cs index 3459b457..fedd5fc7 100644 --- a/app/Peripherals/Mouse/Models/GladiusIII.cs +++ b/app/Peripherals/Mouse/Models/GladiusIIIAimpoint.cs @@ -1,12 +1,12 @@ namespace GHelper.Peripherals.Mouse.Models { - public class GladiusIII : AsusMouse + public class GladiusIIIAimpoint : AsusMouse { - public GladiusIII() : base(0x0B05, 0x1A70, "mi_00", true) + public GladiusIIIAimpoint() : base(0x0B05, 0x1A70, "mi_00", true) { } - protected GladiusIII(ushort vendorId, bool wireless) : base(0x0B05, vendorId, "mi_00", wireless) + protected GladiusIIIAimpoint(ushort vendorId, bool wireless) : base(0x0B05, vendorId, "mi_00", wireless) { } @@ -40,6 +40,11 @@ return 36_000; } + public override bool HasXYDPI() + { + return true; + } + public override bool HasLiftOffSetting() { return true; @@ -76,9 +81,9 @@ } } - public class GladiusIIIWired : GladiusIII + public class GladiusIIIAimpointWired : GladiusIIIAimpoint { - public GladiusIIIWired() : base(0x1A72, false) + public GladiusIIIAimpointWired() : base(0x1A72, false) { } diff --git a/app/Peripherals/Mouse/Models/TUFM4Wireless.cs b/app/Peripherals/Mouse/Models/TUFM4Wireless.cs new file mode 100644 index 00000000..e7141ad6 --- /dev/null +++ b/app/Peripherals/Mouse/Models/TUFM4Wireless.cs @@ -0,0 +1,80 @@ +namespace GHelper.Peripherals.Mouse.Models +{ + //P306_Wireless + public class TUFM4Wirelss : AsusMouse + { + public TUFM4Wirelss() : base(0x0B05, 0x19F4, "mi_00", true) + { + } + + public override int DPIProfileCount() + { + return 4; + } + + public override string GetDisplayName() + { + return "TUF GAMING M4 (Wireless)"; + } + + + public override PollingRate[] SupportedPollingrates() + { + return new PollingRate[] { + PollingRate.PR125Hz, + PollingRate.PR250Hz, + PollingRate.PR500Hz, + PollingRate.PR1000Hz + }; + } + + public override int ProfileCount() + { + return 3; + } + public override int MaxDPI() + { + return 12_000; + } + + public override bool HasLiftOffSetting() + { + return false; + } + + public override bool HasAutoPowerOff() + { + return true; + } + + public override bool HasAngleSnapping() + { + return true; + } + + public override bool HasAngleTuning() + { + return false; + } + + public override bool HasLowBatteryWarning() + { + return true; + } + + public override bool HasDPIColors() + { + return false; + } + + public override int DPIIncrements() + { + return 100; + } + + public override bool CanChangeDPIProfile() + { + return true; + } + } +} diff --git a/app/Peripherals/PeripheralsProvider.cs b/app/Peripherals/PeripheralsProvider.cs index 2a6a4ca4..c2edb5f9 100644 --- a/app/Peripherals/PeripheralsProvider.cs +++ b/app/Peripherals/PeripheralsProvider.cs @@ -20,6 +20,8 @@ namespace GHelper.Peripherals } + private static long lastRefresh; + public static bool IsMouseConnected() { lock (_LOCK) @@ -51,6 +53,15 @@ namespace GHelper.Peripherals public static void RefreshBatteryForAllDevices() { + RefreshBatteryForAllDevices(false); + } + + public static void RefreshBatteryForAllDevices(bool force) + { + //Polling the battery every 20s should be enough + if (!force && Math.Abs(DateTimeOffset.Now.ToUnixTimeMilliseconds() - lastRefresh) < 20_000) return; + lastRefresh = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + List l = AllPeripherals(); foreach (IPeripheral m in l) @@ -174,8 +185,9 @@ namespace GHelper.Peripherals //Add one line for every supported mouse class here to support them. DetectMouse(new ChakramX()); DetectMouse(new ChakramXWired()); - DetectMouse(new GladiusIII()); - DetectMouse(new GladiusIIIWired()); + DetectMouse(new GladiusIIIAimpoint()); + DetectMouse(new GladiusIIIAimpointWired()); + DetectMouse(new TUFM4Wirelss()); } public static void DetectMouse(AsusMouse am) diff --git a/app/Settings.cs b/app/Settings.cs index d8fd0f0e..6cb45584 100644 --- a/app/Settings.cs +++ b/app/Settings.cs @@ -236,11 +236,16 @@ namespace GHelper { screenControl.InitScreen(); gpuControl.InitXGM(); - Task.Run((Action)PeripheralsProvider.RefreshBatteryForAllDevices); + Task.Run((Action)RefreshPeripheralsBattery); updateControl.CheckForUpdates(); } } + private void RefreshPeripheralsBattery() + { + PeripheralsProvider.RefreshBatteryForAllDevices(true); + } + private void ButtonUpdates_Click(object? sender, EventArgs e) { if (updates == null || updates.Text == "")