Merge pull request #933 from IceStormNG/asus-mouse-support

Added support for ASUS TUF Gaming M4 Wireless (P306_Wireless) Mouse
This commit is contained in:
Serge
2023-07-30 12:20:37 +02:00
committed by GitHub
7 changed files with 194 additions and 23 deletions

View File

@@ -376,9 +376,11 @@ namespace GHelper
sliderDPI.Max = mouse.MaxDPI(); sliderDPI.Max = mouse.MaxDPI();
sliderDPI.Min = mouse.MinDPI(); sliderDPI.Min = mouse.MinDPI();
sliderDPI.Step = mouse.DPIIncrements();
numericUpDownCurrentDPI.Minimum = mouse.MinDPI(); numericUpDownCurrentDPI.Minimum = mouse.MinDPI();
numericUpDownCurrentDPI.Maximum = mouse.MaxDPI(); numericUpDownCurrentDPI.Maximum = mouse.MaxDPI();
numericUpDownCurrentDPI.Increment = mouse.DPIIncrements();
if (!mouse.HasDPIColors()) if (!mouse.HasDPIColors())
@@ -391,9 +393,9 @@ namespace GHelper
buttonDPI4.Image = ControlHelper.TintImage(Properties.Resources.lighting_dot_24, Color.Green); buttonDPI4.Image = ControlHelper.TintImage(Properties.Resources.lighting_dot_24, Color.Green);
buttonDPI1.BorderColor = Color.Red; buttonDPI1.BorderColor = Color.Red;
buttonDPI1.BorderColor = Color.Purple; buttonDPI2.BorderColor = Color.Purple;
buttonDPI1.BorderColor = Color.Blue; buttonDPI3.BorderColor = Color.Blue;
buttonDPI1.BorderColor = Color.Green; buttonDPI4.BorderColor = Color.Green;
} }
if (mouse.CanSetPollingRate()) if (mouse.CanSetPollingRate())
@@ -473,6 +475,8 @@ namespace GHelper
if (mouse.HasRGB()) if (mouse.HasRGB())
{ {
sliderBrightness.Max = mouse.MaxBrightness();
foreach (LightingMode lm in Enum.GetValues(typeof(LightingMode))) foreach (LightingMode lm in Enum.GetValues(typeof(LightingMode)))
{ {
if (mouse.IsLightingModeSupported(lm)) if (mouse.IsLightingModeSupported(lm))

View File

@@ -211,9 +211,14 @@ namespace GHelper.Peripherals.Mouse
} }
} }
public virtual int USBTimeout()
{
return 300;
}
public override void SetProvider() public override void SetProvider()
{ {
_usbProvider = new WindowsUsbProvider(_vendorId, _productId, path); _usbProvider = new WindowsUsbProvider(_vendorId, _productId, path, USBTimeout());
} }
protected virtual void OnDisconnect() protected virtual void OnDisconnect()
@@ -235,6 +240,21 @@ namespace GHelper.Peripherals.Mouse
#endif #endif
} }
protected virtual bool IsMouseError(byte[] packet)
{
return packet[1] == 0xFF && packet[2] == 0xAA;
}
protected virtual long MeasuredIO(Action<byte[]> ioFunc, byte[] param)
{
var watch = System.Diagnostics.Stopwatch.StartNew();
ioFunc(param);
watch.Stop();
return watch.ElapsedMilliseconds;
}
[MethodImpl(MethodImplOptions.Synchronized)] [MethodImpl(MethodImplOptions.Synchronized)]
protected virtual byte[]? WriteForResponse(byte[] packet) protected virtual byte[]? WriteForResponse(byte[] packet)
{ {
@@ -245,12 +265,31 @@ namespace GHelper.Peripherals.Mouse
if (IsPacketLoggerEnabled()) if (IsPacketLoggerEnabled())
Logger.WriteLine(GetDisplayName() + ": Sending packet: " + ByteArrayToString(packet)); 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()) if (IsPacketLoggerEnabled())
Logger.WriteLine(GetDisplayName() + ": Read packet: " + ByteArrayToString(response)); 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) catch (IOException e)
{ {
@@ -258,12 +297,12 @@ namespace GHelper.Peripherals.Mouse
OnDisconnect(); OnDisconnect();
return null; return null;
} }
catch (System.TimeoutException e) catch (TimeoutException e)
{ {
Logger.WriteLine(GetDisplayName() + ": Timeout reading packet " + e.Message); Logger.WriteLine(GetDisplayName() + ": Timeout reading packet " + e.Message);
return null; return null;
} }
catch (System.ObjectDisposedException e) catch (ObjectDisposedException)
{ {
Logger.WriteLine(GetDisplayName() + ": Channel closed "); Logger.WriteLine(GetDisplayName() + ": Channel closed ");
OnDisconnect(); OnDisconnect();
@@ -295,9 +334,9 @@ namespace GHelper.Peripherals.Mouse
ReadProfile(); ReadProfile();
ReadDPI(); ReadDPI();
ReadLightingSetting();
ReadLiftOffDistance();
ReadPollingRate(); ReadPollingRate();
ReadLiftOffDistance();
ReadLightingSetting();
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
@@ -695,6 +734,11 @@ namespace GHelper.Peripherals.Mouse
return false; return false;
} }
public virtual int DPIIncrements()
{
return 50;
}
public virtual bool CanChangeDPIProfile() public virtual bool CanChangeDPIProfile()
{ {
return DPIProfileCount() > 1; return DPIProfileCount() > 1;
@@ -709,6 +753,11 @@ namespace GHelper.Peripherals.Mouse
return 100; return 100;
} }
public virtual bool HasXYDPI()
{
return false;
}
protected virtual byte[] GetChangeDPIProfilePacket(int profile) protected virtual byte[] GetChangeDPIProfilePacket(int profile)
{ {
return new byte[] { 0x00, 0x51, 0x31, 0x0A, 0x00, (byte)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 //profiles start to count at 1
public void SetDPIProfile(int profile) public virtual void SetDPIProfile(int profile)
{ {
if (!CanChangeDPIProfile()) if (!CanChangeDPIProfile())
{ {
@@ -745,6 +794,11 @@ namespace GHelper.Peripherals.Mouse
protected virtual byte[] GetReadDPIPacket() protected virtual byte[] GetReadDPIPacket()
{ {
if (!HasXYDPI())
{
return new byte[] { 0x00, 0x12, 0x04, 0x00 };
}
return new byte[] { 0x00, 0x12, 0x04, 0x02 }; return new byte[] { 0x00, 0x12, 0x04, 0x02 };
} }
@@ -758,7 +812,7 @@ namespace GHelper.Peripherals.Mouse
{ {
return null; return null;
} }
ushort dpiEncoded = (ushort)((dpi.DPI - 50) / 50); ushort dpiEncoded = (ushort)((dpi.DPI - DPIIncrements()) / DPIIncrements());
if (HasDPIColors()) if (HasDPIColors())
{ {
@@ -773,7 +827,7 @@ namespace GHelper.Peripherals.Mouse
protected virtual void ParseDPI(byte[] packet) 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; return;
} }
@@ -785,12 +839,13 @@ namespace GHelper.Peripherals.Mouse
DpiSettings[i] = new AsusMouseDPI(); DpiSettings[i] = new AsusMouseDPI();
} }
int offset = 5 + (i * 4); int offset = HasXYDPI() ? (5 + (i * 4)) : (5 + (i * 2));
uint b1 = packet[offset]; uint b1 = packet[offset];
uint b2 = packet[offset + 1]; 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; return false;
} }
public virtual int MaxBrightness()
{
return 100;
}
//Override to remap lighting mode IDs. //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. //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) protected virtual byte IndexForLightingMode(LightingMode lightingMode)

View File

@@ -45,6 +45,11 @@ namespace GHelper.Peripherals.Mouse.Models
return 36_000; return 36_000;
} }
public override bool HasXYDPI()
{
return true;
}
public override bool HasLiftOffSetting() public override bool HasLiftOffSetting()
{ {
return true; return true;

View File

@@ -1,12 +1,12 @@
namespace GHelper.Peripherals.Mouse.Models 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; return 36_000;
} }
public override bool HasXYDPI()
{
return true;
}
public override bool HasLiftOffSetting() public override bool HasLiftOffSetting()
{ {
return true; return true;
@@ -76,9 +81,9 @@
} }
} }
public class GladiusIIIWired : GladiusIII public class GladiusIIIAimpointWired : GladiusIIIAimpoint
{ {
public GladiusIIIWired() : base(0x1A72, false) public GladiusIIIAimpointWired() : base(0x1A72, false)
{ {
} }

View File

@@ -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;
}
}
}

View File

@@ -20,6 +20,8 @@ namespace GHelper.Peripherals
} }
private static long lastRefresh;
public static bool IsMouseConnected() public static bool IsMouseConnected()
{ {
lock (_LOCK) lock (_LOCK)
@@ -51,6 +53,15 @@ namespace GHelper.Peripherals
public static void RefreshBatteryForAllDevices() 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<IPeripheral> l = AllPeripherals(); List<IPeripheral> l = AllPeripherals();
foreach (IPeripheral m in l) foreach (IPeripheral m in l)
@@ -174,8 +185,9 @@ namespace GHelper.Peripherals
//Add one line for every supported mouse class here to support them. //Add one line for every supported mouse class here to support them.
DetectMouse(new ChakramX()); DetectMouse(new ChakramX());
DetectMouse(new ChakramXWired()); DetectMouse(new ChakramXWired());
DetectMouse(new GladiusIII()); DetectMouse(new GladiusIIIAimpoint());
DetectMouse(new GladiusIIIWired()); DetectMouse(new GladiusIIIAimpointWired());
DetectMouse(new TUFM4Wirelss());
} }
public static void DetectMouse(AsusMouse am) public static void DetectMouse(AsusMouse am)

View File

@@ -236,11 +236,16 @@ namespace GHelper
{ {
screenControl.InitScreen(); screenControl.InitScreen();
gpuControl.InitXGM(); gpuControl.InitXGM();
Task.Run((Action)PeripheralsProvider.RefreshBatteryForAllDevices); Task.Run((Action)RefreshPeripheralsBattery);
updateControl.CheckForUpdates(); updateControl.CheckForUpdates();
} }
} }
private void RefreshPeripheralsBattery()
{
PeripheralsProvider.RefreshBatteryForAllDevices(true);
}
private void ButtonUpdates_Click(object? sender, EventArgs e) private void ButtonUpdates_Click(object? sender, EventArgs e)
{ {
if (updates == null || updates.Text == "") if (updates == null || updates.Text == "")