Skip to content
This repository has been archived by the owner on Aug 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #35 from DarthAffe/Development
Browse files Browse the repository at this point in the history
Implemented a reinitialize-functionality
  • Loading branch information
DarthAffe committed Feb 20, 2016
2 parents ced1867 + a64d27c commit 4fd4cb0
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 30 deletions.
69 changes: 69 additions & 0 deletions CueSDK.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// ReSharper disable MemberCanBePrivate.Global

using System.Collections.Generic;
using System.Runtime.InteropServices;
using CUE.NET.Devices.Generic;
using CUE.NET.Devices.Generic.Enums;
Expand Down Expand Up @@ -124,6 +125,74 @@ public static void Initialize(bool exclusiveAccess = false)
}
}

/// <summary>
/// Reinitialize the CUE-SDK and temporarily hand back full control to CUE.
/// </summary>
public static void Reinitialize()
{
Reinitialize(HasExclusiveAccess);
}

/// <summary>
/// Reinitialize the CUE-SDK and temporarily hand back full control to CUE.
/// </summary>
/// <param name="exclusiveAccess">Specifies whether the application should request exclusive access or not.</param>
public static void Reinitialize(bool exclusiveAccess)
{
if (ProtocolDetails == null)
throw new WrapperException("CueSDK isn't initialized.");

KeyboardSDK?.ResetLeds();
MouseSDK?.ResetLeds();
HeadsetSDK?.ResetLeds();

_CUESDK.Reload();

_CUESDK.CorsairPerformProtocolHandshake();

CorsairError error = LastError;
if (error != CorsairError.Success)
Throw(error);

if (ProtocolDetails.BreakingChanges)
throw new WrapperException("The SDK currently used isn't compatible with the installed version of CUE.\r\n" +
$"CUE-Version: {ProtocolDetails.ServerVersion} (Protocol {ProtocolDetails.ServerProtocolVersion})\r\n" +
$"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})");

if (exclusiveAccess)
if (!_CUESDK.CorsairRequestControl(CorsairAccessMode.ExclusiveLightingControl))
Throw(LastError);
HasExclusiveAccess = exclusiveAccess;

int deviceCount = _CUESDK.CorsairGetDeviceCount();
Dictionary<CorsairDeviceType, GenericDeviceInfo> reloadedDevices = new Dictionary<CorsairDeviceType, GenericDeviceInfo>();
for (int i = 0; i < deviceCount; i++)
{
GenericDeviceInfo info = new GenericDeviceInfo((_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo)));
if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting))
continue; // Everything that doesn't support lighting control is useless

reloadedDevices.Add(info.Type, info);

error = LastError;
if (error != CorsairError.Success)
Throw(error);
}

if (KeyboardSDK != null)
if (!reloadedDevices.ContainsKey(CorsairDeviceType.Keyboard)
|| KeyboardSDK.KeyboardDeviceInfo.Model != reloadedDevices[CorsairDeviceType.Keyboard].Model)
throw new WrapperException("The previously loaded Keyboard got disconnected.");
if (MouseSDK != null)
if (!reloadedDevices.ContainsKey(CorsairDeviceType.Mouse)
|| MouseSDK.MouseDeviceInfo.Model != reloadedDevices[CorsairDeviceType.Mouse].Model)
throw new WrapperException("The previously loaded Mouse got disconnected.");
if (HeadsetSDK != null)
if (!reloadedDevices.ContainsKey(CorsairDeviceType.Headset)
|| HeadsetSDK.HeadsetDeviceInfo.Model != reloadedDevices[CorsairDeviceType.Headset].Model)
throw new WrapperException("The previously loaded Headset got disconnected.");
}

private static void Throw(CorsairError error)
{
ProtocolDetails = null;
Expand Down
9 changes: 9 additions & 0 deletions Devices/Generic/AbstractCueDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,15 @@ protected void ManageException(Exception ex)
OnException?.Invoke(this, new OnExceptionEventArgs(ex));
}

/// <summary>
/// Resets all loaded LEDs back to default.
/// </summary>
internal void ResetLeds()
{
foreach (CorsairLed led in Leds.Values)
led.Reset();
}

#endregion
}
}
16 changes: 15 additions & 1 deletion Devices/Generic/CorsairLed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,33 @@ public Color Color
#endregion

#region Constructors

internal CorsairLed() { }

#endregion

#region Methods

/// <summary>
/// Updates the LED to the requested color.
/// </summary>
internal void Update()
{
_color = RequestedColor;
IsUpdated = false;
}

/// <summary>
/// Resets the LED back to default
/// </summary>
internal void Reset()
{
_color = Color.Transparent;
RequestedColor = Color.Transparent;
IsUpdated = false;
IsLocked = false;
}

#endregion
}
}
9 changes: 5 additions & 4 deletions Examples/SimpleDevTest/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ public static void Main(string[] args)

Wait(3);

keyboard.Brush = CueProfiles.LoadProfileByID()[null];
keyboard.Update();
CueSDK.Reinitialize();
//keyboard.Brush = CueProfiles.LoadProfileByID()[null];
//keyboard.Update();

Wait(3);

Expand All @@ -54,8 +55,8 @@ public static void Main(string[] args)
// OR work with a key group containing all keys and leave the background black - this should be always the prefered solution
keyboard.Brush = new SolidColorBrush(Color.Black);
keyboard.Update();
keyboard.Brush = CueProfiles.LoadProfileByID()["K95 RGB Default 2"];
keyboard.Update();
//keyboard.Brush = CueProfiles.LoadProfileByID()["K95 RGB Default 2"];
//keyboard.Update();

Wait(3);

Expand Down
146 changes: 121 additions & 25 deletions Native/_CUESDK.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,79 +10,175 @@ internal static class _CUESDK
{
#region Libary Management

private static IntPtr _dllHandle = IntPtr.Zero;

/// <summary>
/// Gets the loaded architecture (x64/x86).
/// </summary>
internal static string LoadedArchitecture { get; private set; }

static _CUESDK()
{
LoadCUESDK();
}

/// <summary>
/// Reloads the SDK.
/// </summary>
internal static void Reload()
{
UnloadCUESDK();
LoadCUESDK();
}

private static void LoadCUESDK()
{
if (_dllHandle != IntPtr.Zero) return;

// HACK: Load library at runtime to support both, x86 and x64 with one managed dll
LoadLibrary((LoadedArchitecture = Environment.Is64BitProcess ? "x64" : "x86") + "/CUESDK_2013.dll");
_dllHandle = LoadLibrary((LoadedArchitecture = Environment.Is64BitProcess ? "x64" : "x86") + "/CUESDK_2013.dll");

_corsairSetLedsColorsPointer = (CorsairSetLedsColorsPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairSetLedsColors"), typeof(CorsairSetLedsColorsPointer));
_corsairGetDeviceCountPointer = (CorsairGetDeviceCountPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetDeviceCount"), typeof(CorsairGetDeviceCountPointer));
_corsairGetDeviceInfoPointer = (CorsairGetDeviceInfoPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetDeviceInfo"), typeof(CorsairGetDeviceInfoPointer));
_corsairGetLedPositionsPointer = (CorsairGetLedPositionsPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetLedPositions"), typeof(CorsairGetLedPositionsPointer));
_corsairGetLedIdForKeyNamePointer = (CorsairGetLedIdForKeyNamePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetLedIdForKeyName"), typeof(CorsairGetLedIdForKeyNamePointer));
_corsairRequestControlPointer = (CorsairRequestControlPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairRequestControl"), typeof(CorsairRequestControlPointer));
_corsairPerformProtocolHandshakePointer = (CorsairPerformProtocolHandshakePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairPerformProtocolHandshake"), typeof(CorsairPerformProtocolHandshakePointer));
_corsairGetLastErrorPointer = (CorsairGetLastErrorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetLastError"), typeof(CorsairGetLastErrorPointer));
}

private static void UnloadCUESDK()
{
if (_dllHandle == IntPtr.Zero) return;

// ReSharper disable once EmptyEmbeddedStatement - DarthAffe 20.02.2016: We might need to reduce the internal reference counter more than once to set the library free
while (FreeLibrary(_dllHandle)) ;
_dllHandle = IntPtr.Zero;
}

[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport("kernel32.dll")]
private static extern bool FreeLibrary(IntPtr dllHandle);

[DllImport("kernel32.dll")]
private static extern IntPtr GetProcAddress(IntPtr dllHandle, string name);

#endregion

#region SDK-METHODS

#region Pointers

private static CorsairSetLedsColorsPointer _corsairSetLedsColorsPointer;
private static CorsairGetDeviceCountPointer _corsairGetDeviceCountPointer;
private static CorsairGetDeviceInfoPointer _corsairGetDeviceInfoPointer;
private static CorsairGetLedPositionsPointer _corsairGetLedPositionsPointer;
private static CorsairGetLedIdForKeyNamePointer _corsairGetLedIdForKeyNamePointer;
private static CorsairRequestControlPointer _corsairRequestControlPointer;
private static CorsairPerformProtocolHandshakePointer _corsairPerformProtocolHandshakePointer;
private static CorsairGetLastErrorPointer _corsairGetLastErrorPointer;

#endregion

#region Delegates

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool CorsairSetLedsColorsPointer(int size, IntPtr ledsColors);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int CorsairGetDeviceCountPointer();

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr CorsairGetDeviceInfoPointer(int deviceIndex);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr CorsairGetLedPositionsPointer();

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate CorsairKeyboardKeyId CorsairGetLedIdForKeyNamePointer(char keyName);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool CorsairRequestControlPointer(CorsairAccessMode accessMode);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate _CorsairProtocolDetails CorsairPerformProtocolHandshakePointer();

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate CorsairError CorsairGetLastErrorPointer();

#endregion

#region SDK-IMPORTS
// ReSharper disable EventExceptionNotDocumented

/// <summary>
/// CUE-SDK: set specified leds to some colors. The color is retained until changed by successive calls. This function does not take logical layout into account
/// </summary>
[DllImport("CUESDK_2013.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool CorsairSetLedsColors(int size, IntPtr ledsColors);

//#if WIN64
// [DllImport("CUESDK.x64_2013.dll", CallingConvention = CallingConvention.Cdecl)]
//#else
// [DllImport("CUESDK_2013.dll", CallingConvention = CallingConvention.Cdecl)]
//#endif
//internal static extern bool CorsairSetLedsColorsAsync(int size, CorsairLedColor* ledsColors, void(*CallbackType)(void*, bool, CorsairError), void* context);
internal static bool CorsairSetLedsColors(int size, IntPtr ledsColors)
{
return _corsairSetLedsColorsPointer(size, ledsColors);
}

/// <summary>
/// CUE-SDK: returns number of connected Corsair devices that support lighting control.
/// </summary>
[DllImport("CUESDK_2013.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int CorsairGetDeviceCount();
internal static int CorsairGetDeviceCount()
{
return _corsairGetDeviceCountPointer();
}

/// <summary>
/// CUE-SDK: returns information about device at provided index
/// </summary>
[DllImport("CUESDK_2013.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr CorsairGetDeviceInfo(int deviceIndex);
internal static IntPtr CorsairGetDeviceInfo(int deviceIndex)
{
return _corsairGetDeviceInfoPointer(deviceIndex);
}

/// <summary>
/// CUE-SDK: provides list of keyboard LEDs with their physical positions.
/// </summary>
[DllImport("CUESDK_2013.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr CorsairGetLedPositions();
internal static IntPtr CorsairGetLedPositions()
{
return _corsairGetLedPositionsPointer();
}

/// <summary>
/// CUE-SDK: retrieves led id for key name taking logical layout into account.
/// </summary>
[DllImport("CUESDK_2013.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern CorsairKeyboardKeyId CorsairGetLedIdForKeyName(char keyName);
internal static CorsairKeyboardKeyId CorsairGetLedIdForKeyName(char keyName)
{
return _corsairGetLedIdForKeyNamePointer(keyName);
}

/// <summary>
/// CUE-SDK: requestes control using specified access mode.
/// By default client has shared control over lighting so there is no need to call CorsairRequestControl unless client requires exclusive control
/// </summary>
[DllImport("CUESDK_2013.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool CorsairRequestControl(CorsairAccessMode accessMode);
internal static bool CorsairRequestControl(CorsairAccessMode accessMode)
{
return _corsairRequestControlPointer(accessMode);
}

/// <summary>
/// CUE-SDK: checks file and protocol version of CUE to understand which of SDK functions can be used with this version of CUE
/// </summary>
[DllImport("CUESDK_2013.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern _CorsairProtocolDetails CorsairPerformProtocolHandshake();
internal static _CorsairProtocolDetails CorsairPerformProtocolHandshake()
{
return _corsairPerformProtocolHandshakePointer();
}

/// <summary>
/// CUE-SDK: returns last error that occured while using any of Corsair* functions
/// </summary>
[DllImport("CUESDK_2013.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern CorsairError CorsairGetLastError();
internal static CorsairError CorsairGetLastError()
{
return _corsairGetLastErrorPointer();
}

// ReSharper restore EventExceptionNotDocumented

#endregion
}
Expand Down

0 comments on commit 4fd4cb0

Please sign in to comment.