From cd96851fdfb0c05f9c522676da0462853f7d61d3 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Tue, 12 Jun 2018 20:52:10 +0200 Subject: [PATCH] Add support for LGS 9 --- Artemis/Artemis/Artemis.csproj | 1 - .../Artemis/DeviceProviders/Logitech/G810.cs | 23 ++-- .../Artemis/DeviceProviders/Logitech/G910.cs | 23 ++-- .../Logitech/LogitechKeyboard.cs | 19 ++- .../Logitech/Utilities/LogitechGSDK.cs | 116 ------------------ Artemis/Artemis/LogitechLedEnginesWrapper.dll | Bin 20088 -> 20104 bytes 6 files changed, 32 insertions(+), 150 deletions(-) delete mode 100644 Artemis/Artemis/DeviceProviders/Logitech/Utilities/LogitechGSDK.cs diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index 72b2bc4d1..5f9a94ff0 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -311,7 +311,6 @@ - diff --git a/Artemis/Artemis/DeviceProviders/Logitech/G810.cs b/Artemis/Artemis/DeviceProviders/Logitech/G810.cs index 1db03fd91..73f41be21 100644 --- a/Artemis/Artemis/DeviceProviders/Logitech/G810.cs +++ b/Artemis/Artemis/DeviceProviders/Logitech/G810.cs @@ -6,6 +6,7 @@ using Artemis.DAL; using Artemis.DeviceProviders.Logitech.Utilities; using Artemis.Properties; using Artemis.Settings; +using LedCSharp; namespace Artemis.DeviceProviders.Logitech { @@ -54,17 +55,17 @@ namespace Artemis.DeviceProviders.Logitech } // Color G-logo, lets also try some other values to see what happens - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_LOGO, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_BADGE, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_1, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_2, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_3, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_4, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_5, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_6, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_7, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_8, 0, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_9, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_LOGO, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_BADGE, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_1, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_2, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_3, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_4, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_5, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_6, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_7, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_8, 0, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_9, 0, 0); } } diff --git a/Artemis/Artemis/DeviceProviders/Logitech/G910.cs b/Artemis/Artemis/DeviceProviders/Logitech/G910.cs index 26f8ba6a3..177ebdb42 100644 --- a/Artemis/Artemis/DeviceProviders/Logitech/G910.cs +++ b/Artemis/Artemis/DeviceProviders/Logitech/G910.cs @@ -7,6 +7,7 @@ using Artemis.DAL; using Artemis.DeviceProviders.Logitech.Utilities; using Artemis.Properties; using Artemis.Settings; +using LedCSharp; namespace Artemis.DeviceProviders.Logitech { @@ -75,21 +76,21 @@ namespace Artemis.DeviceProviders.Logitech } // Color the extra keys on the left side of the keyboard - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_LOGO, 0, 1); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_1, 0, 2); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_2, 0, 3); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_3, 0, 4); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_4, 0, 5); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_5, 0, 6); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_LOGO, 0, 1); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_1, 0, 2); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_2, 0, 3); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_3, 0, 4); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_4, 0, 5); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_5, 0, 6); // Color the extra keys on the top of the keyboard - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_6, 3, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_7, 4, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_8, 5, 0); - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_9, 6, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_6, 3, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_7, 4, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_8, 5, 0); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_9, 6, 0); // Color the G-badge - SetLogitechColorFromCoordinates(resized, KeyboardNames.G_BADGE, 5, 6); + SetLogitechColorFromCoordinates(resized, keyboardNames.G_BADGE, 5, 6); } } diff --git a/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs b/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs index 72ffe9926..e9445dd36 100644 --- a/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs +++ b/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs @@ -1,9 +1,8 @@ using System; using System.Drawing; using System.Threading; -using Artemis.DeviceProviders.Logitech.Utilities; using Artemis.Utilities.DataReaders; -using Microsoft.Win32; +using LedCSharp; namespace Artemis.DeviceProviders.Logitech { @@ -13,22 +12,20 @@ namespace Artemis.DeviceProviders.Logitech { // Just to be sure, restore the Logitech DLL registry key DllManager.RestoreLogitechDll(); - + int majorNum = 0, minorNum = 0, buildNum = 0; LogitechGSDK.LogiLedInit(); LogitechGSDK.LogiLedGetSdkVersion(ref majorNum, ref minorNum, ref buildNum); LogitechGSDK.LogiLedShutdown(); - // Turn it into one long number... - var version = int.Parse($"{majorNum}{minorNum}{buildNum}"); CantEnableText = "Couldn't connect to your Logitech keyboard.\n" + "Please check your cables and updating the Logitech Gaming Software\n" + $"A minimum version of 8.81.15 is required (detected {majorNum}.{minorNum}.{buildNum}).\n\n" + "If the detected version differs from the version LGS is reporting, reinstall LGS or see the FAQ.\n\n" + "If needed, you can select a different keyboard in Artemis under settings."; - return version >= 88115; + return majorNum >= 9; } public override void Enable() @@ -48,14 +45,14 @@ namespace Artemis.DeviceProviders.Logitech LogitechGSDK.LogiLedShutdown(); } - protected void SetLogitechColorFromCoordinates(Bitmap bitmap, KeyboardNames key, int x, int y) + protected void SetLogitechColorFromCoordinates(Bitmap bitmap, keyboardNames key, int x, int y) { var color = bitmap.GetPixel(x, y); - var rPer = (int)Math.Round(color.R / 2.55); - var gPer = (int)Math.Round(color.G / 2.55); - var bPer = (int)Math.Round(color.B / 2.55); + var rPer = (int) Math.Round(color.R / 2.55); + var gPer = (int) Math.Round(color.G / 2.55); + var bPer = (int) Math.Round(color.B / 2.55); LogitechGSDK.LogiLedSetLightingForKeyWithKeyName(key, rPer, gPer, bPer); } } -} +} \ No newline at end of file diff --git a/Artemis/Artemis/DeviceProviders/Logitech/Utilities/LogitechGSDK.cs b/Artemis/Artemis/DeviceProviders/Logitech/Utilities/LogitechGSDK.cs deleted file mode 100644 index a5a81a558..000000000 --- a/Artemis/Artemis/DeviceProviders/Logitech/Utilities/LogitechGSDK.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Runtime.InteropServices; -using System.Text; - -namespace Artemis.DeviceProviders.Logitech.Utilities -{ - public class LogitechGSDK - { - //LED SDK - private const int LOGI_DEVICETYPE_MONOCHROME_ORD = 0; - private const int LOGI_DEVICETYPE_RGB_ORD = 1; - private const int LOGI_DEVICETYPE_PERKEY_RGB_ORD = 2; - - public const int LOGI_DEVICETYPE_MONOCHROME = 1 << LOGI_DEVICETYPE_MONOCHROME_ORD; - public const int LOGI_DEVICETYPE_RGB = 1 << LOGI_DEVICETYPE_RGB_ORD; - public const int LOGI_DEVICETYPE_PERKEY_RGB = 1 << LOGI_DEVICETYPE_PERKEY_RGB_ORD; - public const int LOGI_LED_BITMAP_WIDTH = 21; - public const int LOGI_LED_BITMAP_HEIGHT = 6; - public const int LOGI_LED_BITMAP_BYTES_PER_KEY = 4; - - public const int LOGI_LED_BITMAP_SIZE = - LOGI_LED_BITMAP_WIDTH*LOGI_LED_BITMAP_HEIGHT*LOGI_LED_BITMAP_BYTES_PER_KEY; - - public const int LOGI_LED_DURATION_INFINITE = 0; - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedInit(); - - //Config option functions - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedGetConfigOptionNumber([MarshalAs(UnmanagedType.LPWStr)] string configPath, - ref double defaultNumber); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedGetConfigOptionBool([MarshalAs(UnmanagedType.LPWStr)] string configPath, - ref bool defaultRed); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedGetConfigOptionColor([MarshalAs(UnmanagedType.LPWStr)] string configPath, - ref int defaultRed, ref int defaultGreen, ref int defaultBlue); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedGetConfigOptionKeyInput([MarshalAs(UnmanagedType.LPWStr)] string configPath, - StringBuilder buffer, int bufsize); - - ///////////////////// - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSetTargetDevice(int targetDevice); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedGetSdkVersion(ref int majorNum, ref int minorNum, ref int buildNum); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSaveCurrentLighting(); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSetLighting(int redPercentage, int greenPercentage, int bluePercentage); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedRestoreLighting(); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedFlashLighting(int redPercentage, int greenPercentage, int bluePercentage, - int milliSecondsDuration, int milliSecondsInterval); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedPulseLighting(int redPercentage, int greenPercentage, int bluePercentage, - int milliSecondsDuration, int milliSecondsInterval); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedStopEffects(); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedExcludeKeysFromBitmap(KeyboardNames[] keyList, int listCount); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSetLightingFromBitmap(byte[] bitmap); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSetLightingForKeyWithScanCode(int keyCode, int redPercentage, - int greenPercentage, int bluePercentage); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSetLightingForKeyWithHidCode(int keyCode, int redPercentage, - int greenPercentage, int bluePercentage); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSetLightingForKeyWithQuartzCode(int keyCode, int redPercentage, - int greenPercentage, int bluePercentage); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSetLightingForKeyWithKeyName(KeyboardNames keyCode, int redPercentage, - int greenPercentage, int bluePercentage); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSaveLightingForKey(KeyboardNames keyName); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedRestoreLightingForKey(KeyboardNames keyName); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedFlashSingleKey(KeyboardNames keyName, int redPercentage, int greenPercentage, - int bluePercentage, int msDuration, int msInterval); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedPulseSingleKey(KeyboardNames keyName, int startRedPercentage, - int startGreenPercentage, int startBluePercentage, int finishRedPercentage, int finishGreenPercentage, - int finishBluePercentage, int msDuration, bool isInfinite); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedStopEffectsOnKey(KeyboardNames keyName); - - [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern void LogiLedShutdown(); - } -} \ No newline at end of file diff --git a/Artemis/Artemis/LogitechLedEnginesWrapper.dll b/Artemis/Artemis/LogitechLedEnginesWrapper.dll index fb707e78a9fc57566d267ecefbad8dbdeca0b5ec..71540b51aa0d3aae15284d856e80def8e29ddf73 100644 GIT binary patch delta 5808 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 f{15r(-3a~V#EtEC@yby-mX(GBtGj>3SqZEhd delta 5385 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