diff --git a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs index 1d0e7d6..810a825 100644 --- a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs +++ b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs @@ -273,7 +273,12 @@ public sealed class CorsairDeviceProvider : AbstractRGBDeviceProvider break; case CorsairChannelDeviceType.EightLedSeriesFan: - yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "8-Led-Series Fan Fan"), updateQueue); + string fanModelName = "8-Led-Series Fan"; + + if (device.model == "iCUE LINK System Hub") + fanModelName = "RX Fan"; + + yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, fanModelName), updateQueue); break; case CorsairChannelDeviceType.DAP: @@ -289,20 +294,20 @@ public sealed class CorsairDeviceProvider : AbstractRGBDeviceProvider break; case CorsairChannelDeviceType.Strip: - string modelName = "LED Strip"; + string stripModelName = "LED Strip"; // LS100 Led Strips are reported as one big strip if configured in monitor mode in iCUE, 138 LEDs for dual monitor, 84 for single if ((device.model == "LS100 Starter Kit") && (ledCount == 138)) - modelName = "LS100 LED Strip (dual monitor)"; + stripModelName = "LS100 LED Strip (dual monitor)"; else if ((device.model == "LS100 Starter Kit") && (ledCount == 84)) - modelName = "LS100 LED Strip (single monitor)"; + stripModelName = "LS100 LED Strip (single monitor)"; // Any other value means an "External LED Strip" in iCUE, these are reported per-strip, 15 for short strips, 27 for long else if ((device.model == "LS100 Starter Kit") && (ledCount == 15)) - modelName = "LS100 LED Strip (short)"; + stripModelName = "LS100 LED Strip (short)"; else if ((device.model == "LS100 Starter Kit") && (ledCount == 27)) - modelName = "LS100 LED Strip (long)"; + stripModelName = "LS100 LED Strip (long)"; - yield return new CorsairLedStripRGBDevice(new CorsairLedStripRGBDeviceInfo(device, ledCount, offset, modelName), updateQueue); + yield return new CorsairLedStripRGBDevice(new CorsairLedStripRGBDeviceInfo(device, ledCount, offset, stripModelName), updateQueue); break; case CorsairChannelDeviceType.DRAM: @@ -310,7 +315,12 @@ public sealed class CorsairDeviceProvider : AbstractRGBDeviceProvider break; default: - Throw(new RGBDeviceException("Unknown Device-Type")); + + //Workaround to support LX Fans because they have an invalid ChannelDeviceType + if ((device.model == "iCUE LINK System Hub") && (ledCount == 18)) + yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "LX Fan"), updateQueue); + else + Throw(new RGBDeviceException("Unknown Device-Type")); break; } diff --git a/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs b/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs index edf61ec..8ebe7f0 100644 --- a/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs +++ b/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs @@ -73,6 +73,7 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider { 0xC541, RGBDeviceType.Keyboard, "G915", LedMappings.PerKey, 0 }, { 0xC359, RGBDeviceType.Keyboard, "G915 X", LedMappings.PerKey, 0 }, { 0xC547, RGBDeviceType.Keyboard, "G915 X TKL", LedMappings.PerKey, 0 }, + { 0xC358, RGBDeviceType.Keyboard, "G515", LedMappings.PerKey, 0 }, //non-rgb { 0xC333, RGBDeviceType.Keyboard, "G610", LedMappings.PerKey, 0 }, diff --git a/RGB.NET.Devices.Razer/RazerDeviceProvider.cs b/RGB.NET.Devices.Razer/RazerDeviceProvider.cs index e7e3d87..d14e62c 100644 --- a/RGB.NET.Devices.Razer/RazerDeviceProvider.cs +++ b/RGB.NET.Devices.Razer/RazerDeviceProvider.cs @@ -151,9 +151,11 @@ public sealed class RazerDeviceProvider : AbstractRGBDeviceProvider { 0x02A0, RGBDeviceType.Keyboard, "Blade 18", LedMappings.Blade, RazerEndpointType.Keyboard }, { 0x02A1, RGBDeviceType.Keyboard, "Ornata V3", LedMappings.Keyboard, RazerEndpointType.Keyboard }, { 0x02A5, RGBDeviceType.Keyboard, "BlackWidow V4 75%", LedMappings.Keyboard, RazerEndpointType.Keyboard }, + { 0x02A6, RGBDeviceType.Keyboard, "Huntsman V3 Pro", LedMappings.Keyboard, RazerEndpointType.Keyboard }, { 0x02A7, RGBDeviceType.Keyboard, "Huntsman V3 Pro TKL", LedMappings.Keyboard, RazerEndpointType.Keyboard }, { 0x0A24, RGBDeviceType.Keyboard, "BlackWidow V3 TKL", LedMappings.Keyboard, RazerEndpointType.Keyboard }, { 0x02BA, RGBDeviceType.Keyboard, "BlackWidow V4 Mini HyperSpeed", LedMappings.Keyboard, RazerEndpointType.Keyboard }, + { 0x02B4, RGBDeviceType.Keyboard, "BlackWidow V4 Pro 75%", LedMappings.Keyboard, RazerEndpointType.Keyboard }, // Mice { 0x0013, RGBDeviceType.Mouse, "Orochi 2011", LedMappings.Mouse, RazerEndpointType.Mouse }, @@ -255,6 +257,8 @@ public sealed class RazerDeviceProvider : AbstractRGBDeviceProvider { 0x0527, RGBDeviceType.Headset, "Kraken Ultimate", LedMappings.Headset, RazerEndpointType.Headset }, { 0x0560, RGBDeviceType.Headset, "Kraken Kitty V2", LedMappings.Headset, RazerEndpointType.Headset }, { 0x0F19, RGBDeviceType.Headset, "Kraken Kitty Edition", LedMappings.Headset, RazerEndpointType.Headset }, + { 0X0533, RGBDeviceType.Headset, "Kraken V3 HyperSense", LedMappings.Headset, RazerEndpointType.Headset}, + { 0X0574, RGBDeviceType.Headset, "Barracuda X Chroma", LedMappings.Headset, RazerEndpointType.Headset}, // Keypads { 0x0111, RGBDeviceType.Keypad, "Nostromo", LedMappings.Keypad, RazerEndpointType.Keypad }, diff --git a/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs b/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs index 5748511..bbf913b 100644 --- a/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs +++ b/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs @@ -96,6 +96,7 @@ public sealed class SteelSeriesDeviceProvider : AbstractRGBDeviceProvider //Mousepads { 0x1507, RGBDeviceType.Mousepad, "QCK Prism", LedMappings.MousepadTwelveZone, SteelSeriesDeviceType.TwelveZone }, { 0x150D, RGBDeviceType.Mousepad, "QCK Prism Cloth", LedMappings.MousepadTwoZone, SteelSeriesDeviceType.TwoZone }, + { 0x1516, RGBDeviceType.Mousepad, "QCK Prism Cloth 3XL", LedMappings.MousepadTwoZone, SteelSeriesDeviceType.TwoZone }, //Monitors { 0x1126, RGBDeviceType.Monitor, "MGP27C", LedMappings.MonitorOnehundredandthreeZone, SteelSeriesDeviceType.OneHundredAndThreeZone }, diff --git a/RGB.NET.Devices.Wooting/Enum/WootingLayoutType.cs b/RGB.NET.Devices.Wooting/Enum/WootingLayoutType.cs index 70c1520..c3085ef 100644 --- a/RGB.NET.Devices.Wooting/Enum/WootingLayoutType.cs +++ b/RGB.NET.Devices.Wooting/Enum/WootingLayoutType.cs @@ -15,5 +15,8 @@ public enum WootingLayoutType { Unknown = -1, ANSI = 0, - ISO = 1 -} \ No newline at end of file + ISO = 1, + JIS = 2, + ANSI_SPLIT_SPACEBAR = 3, + ISO_SPLIT_SPACEBAR = 4, +} diff --git a/RGB.NET.Devices.Wooting/Generic/WootingLedMappings.cs b/RGB.NET.Devices.Wooting/Generic/WootingLedMappings.cs index 1ed0790..9e07926 100644 --- a/RGB.NET.Devices.Wooting/Generic/WootingLedMappings.cs +++ b/RGB.NET.Devices.Wooting/Generic/WootingLedMappings.cs @@ -11,6 +11,10 @@ namespace RGB.NET.Devices.Wooting.Generic; /// internal static class WootingLedMappings { + + public const int ROWS = 6; + public const int COLUMNS = 21; + #region Properties & Fields private static readonly Dictionary TKL = new() @@ -126,7 +130,7 @@ internal static class WootingLedMappings { LedId.Keyboard_F10, (0, 11) }, { LedId.Keyboard_F11, (0, 12) }, { LedId.Keyboard_F12, (0, 13) }, - { LedId.Keyboard_Custom1, (0, 14) }, + { LedId.Keyboard_Profile, (0, 14) }, { LedId.Keyboard_PrintScreen, (0, 15) }, { LedId.Keyboard_PauseBreak, (0, 16) }, @@ -200,7 +204,11 @@ internal static class WootingLedMappings { LedId.Keyboard_LeftGui, (5, 1) }, { LedId.Keyboard_LeftAlt, (5, 2) }, { LedId.Keyboard_International3, (5, 3) },//JIS key + { LedId.Keyboard_Custom1, (5, 4) }, + { LedId.Keyboard_Custom2, (5, 5) }, { LedId.Keyboard_Space, (5, 6) }, + { LedId.Keyboard_Custom3, (5, 7) }, + { LedId.Keyboard_Custom4, (5, 8) }, { LedId.Keyboard_International4, (5, 9) },//JIS key { LedId.Keyboard_RightAlt, (5, 10) }, { LedId.Keyboard_RightGui, (5, 11) }, diff --git a/RGB.NET.Devices.Wooting/Generic/WootingRGBDevice.cs b/RGB.NET.Devices.Wooting/Generic/WootingRGBDevice.cs index 7bc089e..9204708 100644 --- a/RGB.NET.Devices.Wooting/Generic/WootingRGBDevice.cs +++ b/RGB.NET.Devices.Wooting/Generic/WootingRGBDevice.cs @@ -1,40 +1,47 @@ -using RGB.NET.Core; -using RGB.NET.Devices.Wooting.Native; +using System.Collections.Generic; +using RGB.NET.Core; +using RGB.NET.Devices.Wooting.Enum; namespace RGB.NET.Devices.Wooting.Generic; -/// -/// -/// -/// Represents a Wooting-device -/// public abstract class WootingRGBDevice : AbstractRGBDevice, IWootingRGBDevice where TDeviceInfo : WootingRGBDeviceInfo { - #region Constructors + #region Properties & Fields - /// - /// Initializes a new instance of the class. - /// - /// The generic information provided by Wooting for the device. - /// The update queue used to update this device. - protected WootingRGBDevice(TDeviceInfo info, IUpdateQueue updateQueue) - : base(info, updateQueue) - { - } + private readonly Dictionary _mapping; #endregion + #region Constructors + + internal WootingRGBDevice(WootingDeviceType deviceType, TDeviceInfo info, IUpdateQueue updateQueue) + : base(info, updateQueue) + { + _mapping = WootingLedMappings.Mapping[deviceType]; + InitializeLayout(); + } + + #endregion #region Methods + private void InitializeLayout() + { + foreach (KeyValuePair led in _mapping) + AddLed(led.Key, new Point(led.Value.column * 19, led.Value.row * 19), new Size(19, 19)); + } + + /// + protected override object GetLedCustomData(LedId ledId) => _mapping[ledId]; + + /// public override void Dispose() { - _WootingSDK.SelectDevice(DeviceInfo.WootingDeviceIndex); - _WootingSDK.Reset(); + UpdateQueue.Dispose(); base.Dispose(); } - + #endregion -} \ No newline at end of file +} diff --git a/RGB.NET.Devices.Wooting/Generic/WootingRGBDeviceInfo.cs b/RGB.NET.Devices.Wooting/Generic/WootingRGBDeviceInfo.cs index ec4500d..d77f190 100644 --- a/RGB.NET.Devices.Wooting/Generic/WootingRGBDeviceInfo.cs +++ b/RGB.NET.Devices.Wooting/Generic/WootingRGBDeviceInfo.cs @@ -1,14 +1,8 @@ using RGB.NET.Core; -using RGB.NET.Devices.Wooting.Enum; -using RGB.NET.Devices.Wooting.Native; namespace RGB.NET.Devices.Wooting.Generic; -/// -/// -/// Represents a generic information for a Wooting-. -/// -public class WootingRGBDeviceInfo : IRGBDeviceInfo +public abstract class WootingRGBDeviceInfo : IRGBDeviceInfo { #region Properties & Fields @@ -27,37 +21,16 @@ public class WootingRGBDeviceInfo : IRGBDeviceInfo /// public object? LayoutMetadata { get; set; } - /// - /// Gets the of the . - /// - public WootingDeviceType WootingDeviceType { get; } - - /// - /// Gets the of the . - /// - public WootingLayoutType WootingLayoutType { get; } - - public byte WootingDeviceIndex { get; } - #endregion #region Constructors - /// - /// Internal constructor of managed . - /// - /// The type of the . - /// The of the . - internal WootingRGBDeviceInfo(RGBDeviceType deviceType, _WootingDeviceInfo deviceInfo, byte deviceIndex) + protected WootingRGBDeviceInfo(RGBDeviceType deviceType, string model, string name) { this.DeviceType = deviceType; - this.WootingDeviceType = deviceInfo.DeviceType; - this.WootingLayoutType = deviceInfo.LayoutType; - this.WootingDeviceIndex = deviceIndex; - - Model = deviceInfo.Model; - DeviceName = DeviceHelper.CreateDeviceName(Manufacturer, Model); + this.Model = model; + this.DeviceName = name; } #endregion -} \ No newline at end of file +} diff --git a/RGB.NET.Devices.Wooting/Grpc/WootingGrpcDeviceProvider.cs b/RGB.NET.Devices.Wooting/Grpc/WootingGrpcDeviceProvider.cs new file mode 100644 index 0000000..a7070d3 --- /dev/null +++ b/RGB.NET.Devices.Wooting/Grpc/WootingGrpcDeviceProvider.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using Grpc.Net.Client; +using RGB.NET.Core; +using RGB.NET.Devices.Wooting.Enum; +using RGB.NET.Devices.Wooting.Keyboard; +using RGB.NET.Devices.Wooting.Keypad; +using WootingRgbSdk; + +namespace RGB.NET.Devices.Wooting.Grpc; + +/// +/// +/// Represents a device provider responsible for Wooting devices. +/// +public sealed class WootingGrpcDeviceProvider : AbstractRGBDeviceProvider +{ + #region Properties & Fields + + // ReSharper disable once InconsistentNaming + private static readonly Lock _lock = new(); + + private GrpcChannel? _channel; + private RgbSdkService.RgbSdkServiceClient? _client; + + private static WootingGrpcDeviceProvider? _instance; + /// + /// Gets the singleton instance. + /// + public static WootingGrpcDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new WootingGrpcDeviceProvider(); + } + } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// Thrown if this constructor is called even if there is already an instance of this class. + public WootingGrpcDeviceProvider() + { + lock (_lock) + { + if (_instance != null) + throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingGrpcDeviceProvider)}"); + _instance = this; + } + } + + #endregion + + #region Methods + + /// + protected override void InitializeSDK() + { + _channel = GrpcChannel.ForAddress("http://127.0.0.1:50051"); + _client = new RgbSdkService.RgbSdkServiceClient(_channel); + } + + /// + protected override IEnumerable LoadDevices() + { + ArgumentNullException.ThrowIfNull(_client, nameof(_client)); + + foreach (RgbGetConnectedDevicesResponse.Types.RgbDevice? device in _client.GetConnectedDevices(new()).Devices) + { + if (device.DeviceType == RgbDeviceType.None) + continue; // Skip devices that are not supported + + _client.Initialize(new RgbInitializeRequest { Id = device.Id }); + + WootingGrpcUpdateQueue updateQueue = new(GetUpdateTrigger(device.SerialNumber.GetHashCode()), device, _client); + + WootingDeviceType deviceType = device.DeviceType switch + { + RgbDeviceType.Tkl => WootingDeviceType.KeyboardTKL, + RgbDeviceType.FullSize => WootingDeviceType.Keyboard, + RgbDeviceType.SixtyPercent => WootingDeviceType.KeyboardSixtyPercent, + RgbDeviceType.ThreeKey => WootingDeviceType.Keypad3Keys, + RgbDeviceType.EighyPercent => WootingDeviceType.KeyboardEightyPercent, + _ or RgbDeviceType.None => throw new ArgumentOutOfRangeException() + }; + KeyboardLayoutType layoutType = device.LayoutType switch + { + RgbDeviceLayout.Ansi => KeyboardLayoutType.ANSI, + RgbDeviceLayout.Iso => KeyboardLayoutType.ISO, + RgbDeviceLayout.Jis => KeyboardLayoutType.JIS, + RgbDeviceLayout.AnsiSplitSpacebar => KeyboardLayoutType.ANSI, + RgbDeviceLayout.IsoSplitSpacebar => KeyboardLayoutType.ISO, + RgbDeviceLayout.Unknown => KeyboardLayoutType.Unknown, + _ => throw new ArgumentOutOfRangeException() + }; + + //NOTE: this model name ends up kind of ugly, since `ModelName` is like `Wooting 60HE`. We cannot remove the `Wooting` prefix, + //since that makes loadouts fail to load. The deviceName part, however, is fine to strip. + string model = device.ModelName; + string name = + DeviceHelper.CreateDeviceName("Wooting", $"{device.ModelName.Replace("Wooting", "").Trim()} ({device.SerialNumber})"); + + yield return deviceType switch + { + WootingDeviceType.Keypad3Keys => new WootingKeypadRGBDevice(deviceType, new(model, name), updateQueue), + _ => new WootingKeyboardRGBDevice(deviceType, new(layoutType, model, name), updateQueue) + }; + } + } + + /// + protected override void Dispose(bool disposing) + { + lock (_lock) + { + base.Dispose(disposing); + + try + { + _client = null; + _channel?.Dispose(); + } + catch + { /* at least we tried */ + } + + _instance = null; + } + } + + #endregion +} diff --git a/RGB.NET.Devices.Wooting/Grpc/WootingGrpcUpdateQueue.cs b/RGB.NET.Devices.Wooting/Grpc/WootingGrpcUpdateQueue.cs new file mode 100644 index 0000000..83ff7b9 --- /dev/null +++ b/RGB.NET.Devices.Wooting/Grpc/WootingGrpcUpdateQueue.cs @@ -0,0 +1,96 @@ +using System; +using System.Runtime.InteropServices; +using Google.Protobuf; +using RGB.NET.Core; +using RGB.NET.Devices.Wooting.Generic; +using WootingRgbSdk; + +namespace RGB.NET.Devices.Wooting.Grpc; + +/// +/// +/// Represents the update-queue performing updates for cooler master devices. +/// +public sealed class WootingGrpcUpdateQueue : UpdateQueue +{ + #region Properties & Fields + + private readonly RgbSdkService.RgbSdkServiceClient _client; + private readonly RgbGetConnectedDevicesResponse.Types.RgbDevice _wootDevice; + private readonly WootingColor[] _colors; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The update trigger used by this queue. + public WootingGrpcUpdateQueue(IDeviceUpdateTrigger updateTrigger, RgbGetConnectedDevicesResponse.Types.RgbDevice wootDevice, + RgbSdkService.RgbSdkServiceClient client) + : base(updateTrigger) + { + this._client = client; + this._wootDevice = wootDevice; + this._colors = new WootingColor[WootingLedMappings.COLUMNS * WootingLedMappings.ROWS]; + } + + #endregion + + #region Methods + + /// + protected override bool Update(ReadOnlySpan<(object key, Color color)> dataSet) + { + try + { + foreach ((object key, Color color) in dataSet) + { + (int row, int column) = ((int, int))key; + int index = (WootingLedMappings.COLUMNS * row) + column; + + _colors[index] = new WootingColor(color.GetR(), color.GetG(), color.GetB()); + } + + _client.SetColors(new RgbSetColorsRequest + { + Id = _wootDevice.Id, + Colors = ByteString.CopyFrom(MemoryMarshal.AsBytes(_colors.AsSpan())) + }); + return true; + } + catch (Exception ex) + { + WootingGrpcDeviceProvider.Instance.Throw(ex); + } + + return false; + } + + /// + public override void Dispose() + { + _client.Close(new RgbCloseRequest { Id = _wootDevice.Id }); + base.Dispose(); + } + + #endregion +} + +[StructLayout(LayoutKind.Sequential, Pack = 1)] +internal readonly struct WootingColor +{ + public readonly byte r; + public readonly byte g; + public readonly byte b; + public readonly byte a; + + public WootingColor(byte r, byte g, byte b) + { + this.r = r; + this.g = g; + this.b = b; + this.a = 0; // Alpha is not used in Wooting devices + } +} diff --git a/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs b/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs index 0ba3600..d8d4410 100644 --- a/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs +++ b/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDevice.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; -using RGB.NET.Core; +using RGB.NET.Core; +using RGB.NET.Devices.Wooting.Enum; using RGB.NET.Devices.Wooting.Generic; namespace RGB.NET.Devices.Wooting.Keyboard; @@ -22,28 +22,12 @@ public sealed class WootingKeyboardRGBDevice : WootingRGBDevice /// Initializes a new instance of the class. /// + /// The type of the Wooting device. /// The specific information provided by Wooting for the keyboard - /// The update trigger used to update this device. - internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info, IUpdateQueue updateQueue) - : base(info, updateQueue) - { - InitializeLayout(); - } + /// The update queue used to update this device. + internal WootingKeyboardRGBDevice(WootingDeviceType deviceType, WootingKeyboardRGBDeviceInfo info, IUpdateQueue updateQueue) + : base(deviceType, info, updateQueue) + { } #endregion - - #region Methods - - private void InitializeLayout() - { - Dictionary mapping = WootingLedMappings.Mapping[DeviceInfo.WootingDeviceType]; - - foreach (KeyValuePair led in mapping) - AddLed(led.Key, new Point(led.Value.column * 19, led.Value.row * 19), new Size(19, 19)); - } - - /// - protected override object GetLedCustomData(LedId ledId) => WootingLedMappings.Mapping[DeviceInfo.WootingDeviceType][ledId]; - - #endregion -} \ No newline at end of file +} diff --git a/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDeviceInfo.cs b/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDeviceInfo.cs index e3f8bbf..1b8695a 100644 --- a/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDeviceInfo.cs +++ b/RGB.NET.Devices.Wooting/Keyboard/WootingKeyboardRGBDeviceInfo.cs @@ -23,17 +23,14 @@ public sealed class WootingKeyboardRGBDeviceInfo : WootingRGBDeviceInfo, IKeyboa /// /// Internal constructor of managed . /// - /// The native . - internal WootingKeyboardRGBDeviceInfo(_WootingDeviceInfo deviceInfo, byte deviceIndex) - : base(RGBDeviceType.Keyboard, deviceInfo, deviceIndex) + /// The layout of the keyboard. + /// The model of the keyboard. + /// The name of the keyboard. + internal WootingKeyboardRGBDeviceInfo(KeyboardLayoutType layout, string model, string name) + : base(RGBDeviceType.Keyboard, model, name) { - Layout = WootingLayoutType switch - { - WootingLayoutType.ANSI => KeyboardLayoutType.ANSI, - WootingLayoutType.ISO => KeyboardLayoutType.ISO, - _ => KeyboardLayoutType.Unknown - }; + Layout = layout; } #endregion -} \ No newline at end of file +} diff --git a/RGB.NET.Devices.Wooting/Keypad/WootingKeypadRGBDevice.cs b/RGB.NET.Devices.Wooting/Keypad/WootingKeypadRGBDevice.cs index 984072b..20af0ee 100644 --- a/RGB.NET.Devices.Wooting/Keypad/WootingKeypadRGBDevice.cs +++ b/RGB.NET.Devices.Wooting/Keypad/WootingKeypadRGBDevice.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using RGB.NET.Core; +using RGB.NET.Devices.Wooting.Enum; using RGB.NET.Devices.Wooting.Generic; namespace RGB.NET.Devices.Wooting.Keypad; @@ -16,28 +17,12 @@ public sealed class WootingKeypadRGBDevice : WootingRGBDevice /// Initializes a new instance of the class. /// + /// The type of the Wooting device. /// The specific information provided by Wooting for the keyboard /// The update queue used to update this device. - internal WootingKeypadRGBDevice(WootingKeypadRGBDeviceInfo info, IUpdateQueue updateQueue) - : base(info, updateQueue) - { - InitializeLayout(); - } + internal WootingKeypadRGBDevice(WootingDeviceType deviceType, WootingKeypadRGBDeviceInfo info, IUpdateQueue updateQueue) + : base(deviceType, info, updateQueue) + { } #endregion - - #region Methods - - private void InitializeLayout() - { - Dictionary mapping = WootingLedMappings.Mapping[DeviceInfo.WootingDeviceType]; - - foreach (KeyValuePair led in mapping) - AddLed(led.Key, new Point(led.Value.column * 19, led.Value.row * 19), new Size(19, 19)); - } - - /// - protected override object GetLedCustomData(LedId ledId) => WootingLedMappings.Mapping[DeviceInfo.WootingDeviceType][ledId]; - - #endregion -} \ No newline at end of file +} diff --git a/RGB.NET.Devices.Wooting/Keypad/WootingKeypadRGBDeviceInfo.cs b/RGB.NET.Devices.Wooting/Keypad/WootingKeypadRGBDeviceInfo.cs index 55088e1..fb90592 100644 --- a/RGB.NET.Devices.Wooting/Keypad/WootingKeypadRGBDeviceInfo.cs +++ b/RGB.NET.Devices.Wooting/Keypad/WootingKeypadRGBDeviceInfo.cs @@ -9,9 +9,7 @@ namespace RGB.NET.Devices.Wooting.Keypad; /// public sealed class WootingKeypadRGBDeviceInfo : WootingRGBDeviceInfo { - internal WootingKeypadRGBDeviceInfo(_WootingDeviceInfo deviceInfo, byte deviceIndex) - : base(RGBDeviceType.Keypad, deviceInfo, deviceIndex) - { - - } + internal WootingKeypadRGBDeviceInfo(string model, string name) + : base(RGBDeviceType.Keypad, model, name) + { } } diff --git a/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs b/RGB.NET.Devices.Wooting/Native/WootingDeviceProvider.cs similarity index 68% rename from RGB.NET.Devices.Wooting/WootingDeviceProvider.cs rename to RGB.NET.Devices.Wooting/Native/WootingDeviceProvider.cs index cb58d18..6bc749a 100644 --- a/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs +++ b/RGB.NET.Devices.Wooting/Native/WootingDeviceProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; @@ -72,7 +72,8 @@ public sealed class WootingDeviceProvider : AbstractRGBDeviceProvider { lock (_lock) { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}"); + if (_instance != null) + throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}"); _instance = this; } } @@ -99,18 +100,35 @@ public sealed class WootingDeviceProvider : AbstractRGBDeviceProvider { for (byte i = 0; i < _WootingSDK.GetDeviceCount(); i++) { - WootingUpdateQueue updateQueue = new(GetUpdateTrigger(), i); + WootingNativeUpdateQueue updateQueue = new(GetUpdateTrigger(), i); _WootingSDK.SelectDevice(i); - _WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!; - + _WootingDeviceInfo nativeDeviceInfo = + (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!; + //Uwu non-rgb returns zero here. if (nativeDeviceInfo.MaxLedIndex == 0) continue; + KeyboardLayoutType layoutType = nativeDeviceInfo.LayoutType switch + { + WootingLayoutType.Unknown => KeyboardLayoutType.Unknown, + WootingLayoutType.ANSI => KeyboardLayoutType.ANSI, + WootingLayoutType.ISO => KeyboardLayoutType.ISO, + WootingLayoutType.JIS => KeyboardLayoutType.JIS, + WootingLayoutType.ANSI_SPLIT_SPACEBAR => KeyboardLayoutType.ANSI, + WootingLayoutType.ISO_SPLIT_SPACEBAR => KeyboardLayoutType.ISO, + _ => throw new ArgumentOutOfRangeException() + }; + + //Note: we cannot change *any* of these here or the local database Artemis has will no longer match up and everything breaks. + string model = nativeDeviceInfo.Model; + string name = DeviceHelper.CreateDeviceName("Wooting", model); + yield return nativeDeviceInfo.DeviceType switch { - WootingDeviceType.Keypad3Keys => new WootingKeypadRGBDevice(new WootingKeypadRGBDeviceInfo(nativeDeviceInfo, i), updateQueue), - _ => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(nativeDeviceInfo, i), updateQueue), + WootingDeviceType.Keypad3Keys => new WootingKeypadRGBDevice(nativeDeviceInfo.DeviceType, new(model, name), + updateQueue), + _ => new WootingKeyboardRGBDevice(nativeDeviceInfo.DeviceType, new(layoutType, model, name), updateQueue) }; } } @@ -127,7 +145,9 @@ public sealed class WootingDeviceProvider : AbstractRGBDeviceProvider lock (_WootingSDK.SdkLock) { try { _WootingSDK.UnloadWootingSDK(); } - catch { /* at least we tried */ } + catch + { /* at least we tried */ + } } _instance = null; @@ -135,4 +155,4 @@ public sealed class WootingDeviceProvider : AbstractRGBDeviceProvider } #endregion -} \ No newline at end of file +} diff --git a/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs b/RGB.NET.Devices.Wooting/Native/WootingNativeUpdateQueue.cs similarity index 72% rename from RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs rename to RGB.NET.Devices.Wooting/Native/WootingNativeUpdateQueue.cs index be942cf..ec895f0 100644 --- a/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs +++ b/RGB.NET.Devices.Wooting/Native/WootingNativeUpdateQueue.cs @@ -1,14 +1,13 @@ -using System; +using System; using RGB.NET.Core; -using RGB.NET.Devices.Wooting.Native; -namespace RGB.NET.Devices.Wooting.Generic; +namespace RGB.NET.Devices.Wooting.Native; /// /// /// Represents the update-queue performing updates for cooler master devices. /// -public sealed class WootingUpdateQueue : UpdateQueue +public sealed class WootingNativeUpdateQueue : UpdateQueue { #region Properties & Fields @@ -19,10 +18,10 @@ public sealed class WootingUpdateQueue : UpdateQueue #region Constructors /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The update trigger used by this queue. - public WootingUpdateQueue(IDeviceUpdateTrigger updateTrigger, byte deviceId) + public WootingNativeUpdateQueue(IDeviceUpdateTrigger updateTrigger, byte deviceId) : base(updateTrigger) { this._deviceid = deviceId; @@ -60,5 +59,14 @@ public sealed class WootingUpdateQueue : UpdateQueue return false; } + /// + public override void Dispose() + { + _WootingSDK.SelectDevice(_deviceid); + _WootingSDK.Reset(); + + base.Dispose(); + } + #endregion -} \ No newline at end of file +} diff --git a/RGB.NET.Devices.Wooting/RGB.NET.Devices.Wooting.csproj b/RGB.NET.Devices.Wooting/RGB.NET.Devices.Wooting.csproj index 778d0b9..966cad2 100644 --- a/RGB.NET.Devices.Wooting/RGB.NET.Devices.Wooting.csproj +++ b/RGB.NET.Devices.Wooting/RGB.NET.Devices.Wooting.csproj @@ -64,4 +64,17 @@ + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + \ No newline at end of file diff --git a/RGB.NET.Devices.Wooting/WootingRgb.proto b/RGB.NET.Devices.Wooting/WootingRgb.proto new file mode 100644 index 0000000..4ba7548 --- /dev/null +++ b/RGB.NET.Devices.Wooting/WootingRgb.proto @@ -0,0 +1,68 @@ +syntax = "proto3"; + +package wooting_rgb_sdk; + +//from C rgb_sdk +enum RgbDeviceType { + None = 0; + Tkl = 1; + FullSize = 2; + SixtyPercent = 3; + ThreeKey = 4; + EighyPercent = 5; +} + +//from C rgb_sdk +enum RgbDeviceLayout { + ANSI = 0; + ISO = 1; + JIS = 2; + ANSI_SPLIT_SPACEBAR = 3; + ISO_SPLIT_SPACEBAR = 4; + Unknown = -1; +} + +message RgbGetConnectedDevicesRequest {} + +message RgbGetConnectedDevicesResponse { + message RgbDevice { + uint64 id = 1; + uint32 rows = 2; + uint32 columns = 3; + string model_name = 4; + string serial_number = 5; + RgbDeviceType device_type = 6; + RgbDeviceLayout layout_type = 7; + } + + repeated RgbDevice devices = 1; +} + +message RgbInitializeRequest { + uint64 id = 1; +} + +message RgbInitializeResponse { +} + +message RgbSetColorsRequest { + uint64 id = 1; + bytes colors = 2; +} + +message RgbSetColorsResponse { +} + +message RgbCloseRequest { + uint64 id = 1; +} + +message RgbCloseResponse { +} + +service RgbSdkService { + rpc GetConnectedDevices(RgbGetConnectedDevicesRequest) returns (RgbGetConnectedDevicesResponse); + rpc Initialize(RgbInitializeRequest) returns (RgbInitializeResponse); + rpc SetColors(RgbSetColorsRequest) returns (RgbSetColorsResponse); + rpc Close(RgbCloseRequest) returns (RgbCloseResponse); +} \ No newline at end of file