diff --git a/RGB.NET.Devices.Asus/AsusDeviceProvider.cs b/RGB.NET.Devices.Asus/AsusDeviceProvider.cs
new file mode 100644
index 0000000..f8e3834
--- /dev/null
+++ b/RGB.NET.Devices.Asus/AsusDeviceProvider.cs
@@ -0,0 +1,181 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Globalization;
+using AuraServiceLib;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Asus
+{
+ ///
+ ///
+ /// Represents a device provider responsible for Cooler Master devices.
+ ///
+ public class AsusDeviceProvider : IRGBDeviceProvider
+ {
+ #region Properties & Fields
+
+ private static AsusDeviceProvider _instance;
+ ///
+ /// Gets the singleton instance.
+ ///
+ public static AsusDeviceProvider Instance => _instance ?? new AsusDeviceProvider();
+
+ ///
+ ///
+ /// Indicates if the SDK is initialized and ready to use.
+ ///
+ public bool IsInitialized { get; private set; }
+
+ ///
+ ///
+ /// Gets whether the application has exclusive access to the SDK or not.
+ ///
+ public bool HasExclusiveAccess { get; private set; }
+
+ ///
+ public IEnumerable Devices { get; private set; }
+
+ ///
+ /// Gets or sets a function to get the culture for a specific device.
+ ///
+ // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
+ public Func GetCulture { get; set; } = CultureHelper.GetCurrentCulture;
+
+ ///
+ /// The used to trigger the updates for asus devices.
+ ///
+ public DeviceUpdateTrigger UpdateTrigger { get; private set; }
+
+ private IAuraSdk2 _sdk;
+
+ #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 AsusDeviceProvider()
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(AsusDeviceProvider)}");
+ _instance = this;
+
+ UpdateTrigger = new DeviceUpdateTrigger();
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
+ {
+ IsInitialized = false;
+
+ try
+ {
+ UpdateTrigger?.Stop();
+
+ // ReSharper disable once SuspiciousTypeConversion.Global
+ _sdk = (IAuraSdk2)new AuraSdk();
+ _sdk.SwitchMode();
+
+ IList devices = new List();
+ foreach (IAuraSyncDevice device in _sdk.Enumerate(0))
+ {
+ try
+ {
+ IAsusRGBDevice rgbDevice = null;
+ switch (device.Type)
+ {
+ case 0x00010000: //Motherboard
+ rgbDevice = new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name));
+ break;
+
+ case 0x00011000: //Motherboard LED Strip
+ rgbDevice = new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedStripe, device), LedId.LedStripe1);
+ break;
+
+ case 0x00020000: //VGA
+ rgbDevice = new AsusGraphicsCardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.GraphicsCard, device));
+ break;
+
+ case 0x00040000: //Headset
+ rgbDevice = new AsusHeadsetRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Headset, device));
+ break;
+
+ case 0x00070000: //DRAM
+ rgbDevice = new AsusDramRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.DRAM, device));
+ break;
+
+ case 0x00080000: //Keyboard
+ case 0x00081000: //Notebook Keyboard
+ case 0x00081001: //Notebook Keyboard(4 - zone type)
+ rgbDevice = new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device, CultureInfo.CurrentCulture));
+ break;
+
+ case 0x00090000: //Mouse
+ rgbDevice = new AsusMouseRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mouse, device));
+ break;
+
+ case 0x00000000: //All
+ case 0x00012000: //All - In - One PC
+ case 0x00030000: //Display
+ case 0x00050000: //Microphone
+ case 0x00060000: //External HDD
+ case 0x00061000: //External BD Drive
+ case 0x000B0000: //Chassis
+ case 0x000C0000: //Projector
+ rgbDevice = new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Custom1);
+ break;
+ }
+
+ if ((rgbDevice != null) && loadFilter.HasFlag(rgbDevice.DeviceInfo.DeviceType))
+ {
+ rgbDevice.Initialize(UpdateTrigger);
+ devices.Add(rgbDevice);
+ }
+ }
+ catch
+ {
+ if (throwExceptions)
+ throw;
+ }
+ }
+
+ UpdateTrigger?.Start();
+
+ Devices = new ReadOnlyCollection(devices);
+ IsInitialized = true;
+ }
+ catch
+ {
+ if (throwExceptions)
+ throw;
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ public void ResetDevices()
+ {
+ _sdk?.ReleaseControl(0);
+ _sdk?.SwitchMode();
+ }
+
+ ///
+ public void Dispose()
+ {
+ _sdk?.ReleaseControl(0);
+ _sdk = null;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Asus/AsusDeviceProviderLoader.cs b/RGB.NET.Devices.Asus/AsusDeviceProviderLoader.cs
new file mode 100644
index 0000000..576dfb5
--- /dev/null
+++ b/RGB.NET.Devices.Asus/AsusDeviceProviderLoader.cs
@@ -0,0 +1,24 @@
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Asus
+{
+ ///
+ /// Represents a device provider loaded used to dynamically load asus devices into an application.
+ ///
+ public class AsusDeviceProviderLoader : IRGBDeviceProviderLoader
+ {
+ #region Properties & Fields
+
+ ///
+ public bool RequiresInitialization => false;
+
+ #endregion
+
+ #region Methods
+
+ ///
+ public IRGBDeviceProvider GetDeviceProvider() => AsusDeviceProvider.Instance;
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs b/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs
new file mode 100644
index 0000000..7e74550
--- /dev/null
+++ b/RGB.NET.Devices.Asus/Dram/AsusDramRGBDevice.cs
@@ -0,0 +1,44 @@
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Asus
+{
+ ///
+ ///
+ /// Represents a Asus dram.
+ ///
+ public class AsusDramRGBDevice : AsusRGBDevice
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by Asus for the DRAM.
+ internal AsusDramRGBDevice(AsusRGBDeviceInfo info)
+ : base(info)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void InitializeLayout()
+ {
+ //TODO DarthAffe 07.10.2017: Look for a good default layout
+ int ledCount = DeviceInfo.Device.Lights.Count;
+ for (int i = 0; i < ledCount; i++)
+ InitializeLed(LedId.DRAM1 + i, new Rectangle(i * 10, 0, 10, 10));
+
+ //TODO DarthAffe 21.10.2017: We don't know the model, how to save layouts and images?
+ //TODO DarthAffe 07.10.2017: We don't know the model, how to save layouts and images?
+ ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\Asus\Drams\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null);
+ }
+
+ ///
+ protected override object CreateLedCustomData(LedId ledId) => (int)ledId - (int)LedId.DRAM1;
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Asus/Enum/AsusLogicalKeyboardLayout.cs b/RGB.NET.Devices.Asus/Enum/AsusLogicalKeyboardLayout.cs
new file mode 100644
index 0000000..60105e5
--- /dev/null
+++ b/RGB.NET.Devices.Asus/Enum/AsusLogicalKeyboardLayout.cs
@@ -0,0 +1,15 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable UnusedMember.Global
+
+#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
+
+namespace RGB.NET.Devices.Asus
+{
+ ///
+ /// Contains list of available logical layouts for asus keyboards.
+ ///
+ public enum AsusLogicalKeyboardLayout
+ {
+ TODO
+ };
+}
diff --git a/RGB.NET.Devices.Asus/Enum/AsusPhysicalKeyboardLayout.cs b/RGB.NET.Devices.Asus/Enum/AsusPhysicalKeyboardLayout.cs
new file mode 100644
index 0000000..b5e80de
--- /dev/null
+++ b/RGB.NET.Devices.Asus/Enum/AsusPhysicalKeyboardLayout.cs
@@ -0,0 +1,15 @@
+// ReSharper disable UnusedMember.Global
+// ReSharper disable InconsistentNaming
+
+#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
+
+namespace RGB.NET.Devices.Asus
+{
+ ///
+ /// Contains list of available physical layouts for asus keyboards.
+ ///
+ public enum AsusPhysicalKeyboardLayout
+ {
+ TODO
+ }
+}
diff --git a/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs b/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs
new file mode 100644
index 0000000..0241828
--- /dev/null
+++ b/RGB.NET.Devices.Asus/Generic/AsusRGBDevice.cs
@@ -0,0 +1,85 @@
+using System.Collections.Generic;
+using System.Linq;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Asus
+{
+ ///
+ ///
+ ///
+ /// Represents a generic Asus-device. (keyboard, mouse, headset, mousepad).
+ ///
+ public abstract class AsusRGBDevice : AbstractRGBDevice, IAsusRGBDevice
+ where TDeviceInfo : AsusRGBDeviceInfo
+ {
+ #region Properties & Fields
+
+ ///
+ ///
+ /// Gets information about the .
+ ///
+ public override TDeviceInfo DeviceInfo { get; }
+
+ ///
+ /// Gets or sets the update queue performing updates for this device.
+ ///
+ // ReSharper disable once MemberCanBePrivate.Global
+ protected AsusUpdateQueue UpdateQueue { get; set; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The generic information provided by Asus for the device.
+ protected AsusRGBDevice(TDeviceInfo info)
+ {
+ this.DeviceInfo = info;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Initializes the device.
+ ///
+ public void Initialize(IDeviceUpdateTrigger updateTrigger)
+ {
+ InitializeLayout();
+
+ if (Size == Size.Invalid)
+ {
+ Rectangle ledRectangle = new Rectangle(this.Select(x => x.LedRectangle));
+ Size = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y);
+ }
+
+ UpdateQueue = new AsusUpdateQueue(updateTrigger);
+ UpdateQueue.Initialize(DeviceInfo.Device);
+ }
+
+ ///
+ /// Initializes the and of the device.
+ ///
+ protected abstract void InitializeLayout();
+
+ ///
+ protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(ledsToUpdate.Where(x => x.Color.A > 0));
+
+ ///
+ public override void SyncBack()
+ {
+ // DarthAffe 16.06.2019: This doesn't work since the SDK only returns the colors we set.
+ //foreach (Led led in LedMapping.Values)
+ //{
+ // int index = (int)led.CustomData;
+ // IAuraRgbLight light = DeviceInfo.Device.Lights[index];
+ // SetLedColorWithoutRequest(led, new Color(light.Red, light.Green, light.Blue));
+ //}
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Asus/Generic/AsusRGBDeviceInfo.cs b/RGB.NET.Devices.Asus/Generic/AsusRGBDeviceInfo.cs
new file mode 100644
index 0000000..62c7ea9
--- /dev/null
+++ b/RGB.NET.Devices.Asus/Generic/AsusRGBDeviceInfo.cs
@@ -0,0 +1,61 @@
+using System;
+using AuraServiceLib;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Asus
+{
+ ///
+ ///
+ /// Represents a generic information for a Corsair-.
+ ///
+ public class AsusRGBDeviceInfo : IRGBDeviceInfo
+ {
+ #region Properties & Fields
+
+ ///
+ public RGBDeviceType DeviceType { get; }
+
+ ///
+ public string DeviceName { get; }
+
+ ///
+ public string Manufacturer { get; }
+
+ ///
+ public string Model { get; }
+
+ ///
+ public Uri Image { get; set; }
+
+ ///
+ public RGBDeviceLighting Lighting => RGBDeviceLighting.Key;
+
+ ///
+ public bool SupportsSyncBack => false;
+
+ public IAuraSyncDevice Device { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The type of the .
+ /// The backing this RGB.NET device.
+ /// The manufacturer-name of the .
+ /// The model-name of the .
+ internal AsusRGBDeviceInfo(RGBDeviceType deviceType, IAuraSyncDevice device, string model = null, string manufacturer = "Asus")
+ {
+ this.DeviceType = deviceType;
+ this.Device = device;
+ this.Model = model ?? device.Name;
+ this.Manufacturer = manufacturer;
+
+ DeviceName = $"{Manufacturer} {Model}";
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs b/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs
new file mode 100644
index 0000000..3515596
--- /dev/null
+++ b/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs
@@ -0,0 +1,49 @@
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Asus
+{
+ ///
+ ///
+ /// Represents a Asus headset.
+ ///
+ public class AsusUnspecifiedRGBDevice : AsusRGBDevice
+ {
+ #region Properties & Fields
+
+ private LedId _baseLedId;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by Asus for the headset.
+ internal AsusUnspecifiedRGBDevice(AsusRGBDeviceInfo info, LedId baseLedId)
+ : base(info)
+ {
+ this._baseLedId = baseLedId;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void InitializeLayout()
+ {
+ int ledCount = DeviceInfo.Device.Lights.Count;
+ for (int i = 0; i < ledCount; i++)
+ InitializeLed(_baseLedId + i, new Rectangle(i * 10, 0, 10, 10));
+
+ //TODO DarthAffe 19.05.2019: Add a way to define a layout for this kind of devies
+ }
+
+ ///
+ protected override object CreateLedCustomData(LedId ledId) => (int)ledId - (int)_baseLedId;
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs
new file mode 100644
index 0000000..fb32a3e
--- /dev/null
+++ b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using AuraServiceLib;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Asus
+{
+ ///
+ ///
+ /// Represents the update-queue performing updates for asus devices.
+ ///
+ public class AsusUpdateQueue : UpdateQueue
+ {
+ #region Properties & Fields
+
+ ///
+ /// The device to be updated.
+ ///
+ protected IAuraSyncDevice Device { get; private set; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The update trigger used by this queue.
+ public AsusUpdateQueue(IDeviceUpdateTrigger updateTrigger)
+ : base(updateTrigger)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Initializes the queue.
+ ///
+ /// The device to be updated.
+ public void Initialize(IAuraSyncDevice device)
+ {
+ Device = device;
+ }
+
+ ///
+ protected override void Update(Dictionary