1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-13 10:08:31 +00:00

Added linux-paths to wooting and changed the native part to use function pointers

This commit is contained in:
Darth Affe 2022-08-21 16:30:23 +02:00
parent b06d070848
commit 4dc04286b7
5 changed files with 73 additions and 70 deletions

View File

@ -23,7 +23,7 @@ public class WootingUpdateQueue : UpdateQueue
public WootingUpdateQueue(IDeviceUpdateTrigger updateTrigger, byte deviceId) public WootingUpdateQueue(IDeviceUpdateTrigger updateTrigger, byte deviceId)
: base(updateTrigger) : base(updateTrigger)
{ {
_deviceid = deviceId; this._deviceid = deviceId;
} }
#endregion #endregion

View File

@ -56,5 +56,6 @@ public class WootingKeyboardRGBDevice : WootingRGBDevice<WootingKeyboardRGBDevic
base.Dispose(); base.Dispose();
} }
#endregion #endregion
} }

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using RGB.NET.Core; using RGB.NET.Core;
@ -32,27 +31,36 @@ internal static class _WootingSDK
{ {
if (_handle != IntPtr.Zero) return; if (_handle != IntPtr.Zero) return;
// HACK: Load library at runtime to support both, x86 and x64 with one managed dll List<string> possiblePathList = GetPossibleLibraryPaths().ToList();
List<string> possiblePathList = (Environment.Is64BitProcess ? WootingDeviceProvider.PossibleX64NativePaths : WootingDeviceProvider.PossibleX86NativePaths)
.Select(Environment.ExpandEnvironmentVariables)
.ToList();
string? dllPath = possiblePathList.FirstOrDefault(File.Exists); string? dllPath = possiblePathList.FirstOrDefault(File.Exists);
if (dllPath == null) throw new RGBDeviceException($"Can't find the Wooting-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'"); if (dllPath == null) throw new RGBDeviceException($"Can't find the Wooting-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'");
if (!NativeLibrary.TryLoad(dllPath, out _handle)) throw new RGBDeviceException($"Wooting LoadLibrary failed with error code {Marshal.GetLastWin32Error()}");
_handle = NativeLibrary.Load(dllPath);
if (_handle == IntPtr.Zero) throw new RGBDeviceException($"Wooting LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); if (!NativeLibrary.TryGetExport(_handle, "wooting_rgb_device_info", out _getDeviceInfoPointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_rgb_device_info'");
if (!NativeLibrary.TryGetExport(_handle, "wooting_rgb_kbd_connected", out _keyboardConnectedPointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_rgb_kbd_connected'");
_getDeviceInfoPointer = (GetDeviceInfoPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_device_info"), typeof(GetDeviceInfoPointer)); if (!NativeLibrary.TryGetExport(_handle, "wooting_rgb_reset_rgb", out _resetPointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_rgb_reset_rgb'");
_keyboardConnectedPointer = (KeyboardConnectedPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_kbd_connected"), typeof(KeyboardConnectedPointer)); if (!NativeLibrary.TryGetExport(_handle, "wooting_rgb_close", out _closePointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_rgb_close'");
_resetPointer = (ResetPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_reset_rgb"), typeof(ResetPointer)); if (!NativeLibrary.TryGetExport(_handle, "wooting_rgb_array_update_keyboard", out _arrayUpdateKeyboardPointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_rgb_array_update_keyboard'");
_closePointer = (ClosePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_close"), typeof(ClosePointer)); if (!NativeLibrary.TryGetExport(_handle, "wooting_rgb_array_set_single", out _arraySetSinglePointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_rgb_array_set_single'");
_arrayUpdateKeyboardPointer = (ArrayUpdateKeyboardPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_array_update_keyboard"), typeof(ArrayUpdateKeyboardPointer)); if (!NativeLibrary.TryGetExport(_handle, "wooting_usb_keyboard_count", out _getDeviceCountPointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_usb_keyboard_count'");
_arraySetSinglePointer = (ArraySetSinglePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_array_set_single"), typeof(ArraySetSinglePointer)); if (!NativeLibrary.TryGetExport(_handle, "wooting_usb_select_device", out _selectDevicePointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_usb_select_device'");
_getDeviceCountPointer = (GetDeviceCountPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_usb_keyboard_count"), typeof(GetDeviceCountPointer));
_selectDevicePointer = (SelectDevicePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_usb_select_device"), typeof(SelectDevicePointer));
} }
private static IEnumerable<string> GetPossibleLibraryPaths()
{
IEnumerable<string> possibleLibraryPaths;
if (OperatingSystem.IsWindows())
possibleLibraryPaths = Environment.Is64BitProcess ? WootingDeviceProvider.PossibleX64NativePaths : WootingDeviceProvider.PossibleX86NativePaths;
else if (OperatingSystem.IsLinux())
possibleLibraryPaths = Environment.Is64BitProcess ? WootingDeviceProvider.PossibleX64NativePathsLinux : WootingDeviceProvider.PossibleX86NativePathsLinux;
else
possibleLibraryPaths = Enumerable.Empty<string>();
return possibleLibraryPaths.Select(Environment.ExpandEnvironmentVariables);
}
internal static void UnloadWootingSDK() internal static void UnloadWootingSDK()
{ {
@ -60,14 +68,15 @@ internal static class _WootingSDK
Close(); Close();
_getDeviceInfoPointer = null; _getDeviceInfoPointer = IntPtr.Zero;
_keyboardConnectedPointer = null; _keyboardConnectedPointer = IntPtr.Zero;
_arrayUpdateKeyboardPointer = null; _resetPointer = IntPtr.Zero;
_arraySetSinglePointer = null; _closePointer = IntPtr.Zero;
_resetPointer = null; _arrayUpdateKeyboardPointer = IntPtr.Zero;
_closePointer = null; _arraySetSinglePointer = IntPtr.Zero;
_getDeviceCountPointer = IntPtr.Zero;
_selectDevicePointer = IntPtr.Zero;
// 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
NativeLibrary.Free(_handle); NativeLibrary.Free(_handle);
_handle = IntPtr.Zero; _handle = IntPtr.Zero;
} }
@ -78,52 +87,32 @@ internal static class _WootingSDK
#region Pointers #region Pointers
private static GetDeviceInfoPointer? _getDeviceInfoPointer; private static IntPtr _getDeviceInfoPointer;
private static KeyboardConnectedPointer? _keyboardConnectedPointer; private static IntPtr _keyboardConnectedPointer;
private static ResetPointer? _resetPointer; private static IntPtr _resetPointer;
private static ClosePointer? _closePointer; private static IntPtr _closePointer;
private static ArrayUpdateKeyboardPointer? _arrayUpdateKeyboardPointer; private static IntPtr _arrayUpdateKeyboardPointer;
private static ArraySetSinglePointer? _arraySetSinglePointer; private static IntPtr _arraySetSinglePointer;
private static GetDeviceCountPointer? _getDeviceCountPointer; private static IntPtr _getDeviceCountPointer;
private static SelectDevicePointer? _selectDevicePointer; private static IntPtr _selectDevicePointer;
#endregion #endregion
#region Delegates internal static unsafe IntPtr GetDeviceInfo() => ((delegate* unmanaged[Cdecl]<IntPtr>)ThrowIfZero(_getDeviceInfoPointer))();
internal static unsafe bool KeyboardConnected() => ((delegate* unmanaged[Cdecl]<bool>)ThrowIfZero(_keyboardConnectedPointer))();
internal static unsafe bool Reset() => ((delegate* unmanaged[Cdecl]<bool>)ThrowIfZero(_resetPointer))();
internal static unsafe bool Close() => ((delegate* unmanaged[Cdecl]<bool>)ThrowIfZero(_closePointer))();
internal static unsafe bool ArrayUpdateKeyboard() => ((delegate* unmanaged[Cdecl]<bool>)ThrowIfZero(_arrayUpdateKeyboardPointer))();
internal static unsafe bool ArraySetSingle(byte row, byte column, byte red, byte green, byte blue)
=> ((delegate* unmanaged[Cdecl]<byte, byte, byte, byte, byte, bool>)ThrowIfZero(_arraySetSinglePointer))(row, column, red, green, blue);
internal static unsafe byte GetDeviceCount() => ((delegate* unmanaged[Cdecl]<byte>)ThrowIfZero(_getDeviceCountPointer))();
internal static unsafe void SelectDevice(byte index) => ((delegate* unmanaged[Cdecl]<byte, void>)ThrowIfZero(_selectDevicePointer))(index);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] private static IntPtr ThrowIfZero(IntPtr ptr)
private delegate IntPtr GetDeviceInfoPointer(); {
if (ptr == IntPtr.Zero) throw new RGBDeviceException("The Wooting-SDK is not initialized.");
return ptr;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool KeyboardConnectedPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ResetPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ClosePointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ArrayUpdateKeyboardPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ArraySetSinglePointer(byte row, byte column, byte red, byte green, byte blue);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate byte GetDeviceCountPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void SelectDevicePointer(byte index);
#endregion
internal static IntPtr GetDeviceInfo() => (_getDeviceInfoPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
internal static bool KeyboardConnected() => (_keyboardConnectedPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
internal static bool Reset() => (_resetPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
internal static bool Close() => (_closePointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
internal static bool ArrayUpdateKeyboard() => (_arrayUpdateKeyboardPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
internal static bool ArraySetSingle(byte row, byte column, byte red, byte green, byte blue) => (_arraySetSinglePointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke(row, column, red, green, blue);
internal static byte GetDeviceCount() => (_getDeviceCountPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
internal static void SelectDevice(byte index) => (_selectDevicePointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke(index);
#endregion #endregion
} }

View File

@ -36,6 +36,7 @@
<IncludeSymbols>True</IncludeSymbols> <IncludeSymbols>True</IncludeSymbols>
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
<SymbolPackageFormat>snupkg</SymbolPackageFormat> <SymbolPackageFormat>snupkg</SymbolPackageFormat>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'"> <PropertyGroup Condition="'$(Configuration)'=='Debug'">

View File

@ -23,17 +23,29 @@ public class WootingDeviceProvider : AbstractRGBDeviceProvider
public static WootingDeviceProvider Instance => _instance ?? new WootingDeviceProvider(); public static WootingDeviceProvider Instance => _instance ?? new WootingDeviceProvider();
/// <summary> /// <summary>
/// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications. /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 windows applications.
/// The first match will be used. /// The first match will be used.
/// </summary> /// </summary>
public static List<string> PossibleX86NativePaths { get; } = new() { "x86/wooting-rgb-sdk.dll" }; public static List<string> PossibleX86NativePaths { get; } = new() { "x86/wooting-rgb-sdk.dll" };
/// <summary> /// <summary>
/// Gets a modifiable list of paths used to find the native SDK-dlls for x64 applications. /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 linux applications.
/// The first match will be used.
/// </summary>
public static List<string> PossibleX86NativePathsLinux { get; } = new() { "x86/wooting-rgb-sdk.so" };
/// <summary>
/// Gets a modifiable list of paths used to find the native SDK-dlls for x64 windows applications.
/// The first match will be used. /// The first match will be used.
/// </summary> /// </summary>
public static List<string> PossibleX64NativePaths { get; } = new() { "x64/wooting-rgb-sdk64.dll" }; public static List<string> PossibleX64NativePaths { get; } = new() { "x64/wooting-rgb-sdk64.dll" };
/// <summary>
/// Gets a modifiable list of paths used to find the native SDK-dlls for x64 linux applications.
/// The first match will be used.
/// </summary>
public static List<string> PossibleX64NativePathsLinux { get; } = new() { "x64/wooting-rgb-sdk64.so" };
#endregion #endregion
#region Constructors #region Constructors
@ -70,7 +82,7 @@ public class WootingDeviceProvider : AbstractRGBDeviceProvider
{ {
for (byte i = 0; i < _WootingSDK.GetDeviceCount(); i++) for (byte i = 0; i < _WootingSDK.GetDeviceCount(); i++)
{ {
var updateQueue = new WootingUpdateQueue(GetUpdateTrigger(), i); WootingUpdateQueue updateQueue = new(GetUpdateTrigger(), i);
_WootingSDK.SelectDevice(i); _WootingSDK.SelectDevice(i);
_WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!; _WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!;