-
Notifications
You must be signed in to change notification settings - Fork 79
Expand file tree
/
Copy path_MsiSDK.cs
More file actions
245 lines (200 loc) · 13 KB
/
_MsiSDK.cs
File metadata and controls
245 lines (200 loc) · 13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#pragma warning disable IDE1006 // Naming Styles
// ReSharper disable UnusedMethodReturnValue.Global
// ReSharper disable UnusedMember.Global
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using RGB.NET.Core;
namespace RGB.NET.Devices.Msi.Native;
// ReSharper disable once InconsistentNaming
internal static class _MsiSDK
{
#region Libary Management
private static nint _handle = 0;
/// <summary>
/// Reloads the SDK.
/// </summary>
internal static void Reload()
{
UnloadMsiSDK();
LoadMsiSDK();
}
private static void LoadMsiSDK()
{
if (_handle != 0) return;
List<string> possiblePathList = GetPossibleLibraryPaths().ToList();
string? dllPath = possiblePathList.FirstOrDefault(File.Exists);
if (dllPath == null) throw new RGBDeviceException($"Can't find the CUE-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'");
SetDllDirectory(Path.GetDirectoryName(Path.GetFullPath(dllPath))!);
if (!NativeLibrary.TryLoad(dllPath, out _handle))
#if NET6_0
throw new RGBDeviceException($"MSI LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}");
#else
throw new RGBDeviceException($"MSI LoadLibrary failed with error code {Marshal.GetLastSystemError()}");
#endif
_initializePointer = (InitializePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_Initialize"), typeof(InitializePointer));
_getDeviceInfoPointer = (GetDeviceInfoPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetDeviceInfo"), typeof(GetDeviceInfoPointer));
_getLedInfoPointer = (GetLedInfoPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedInfo"), typeof(GetLedInfoPointer));
_getLedColorPointer = (GetLedColorPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedColor"), typeof(GetLedColorPointer));
_getLedStylePointer = (GetLedStylePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedStyle"), typeof(GetLedStylePointer));
_getLedMaxBrightPointer = (GetLedMaxBrightPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedMaxBright"), typeof(GetLedMaxBrightPointer));
_getLedBrightPointer = (GetLedBrightPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedBright"), typeof(GetLedBrightPointer));
_getLedMaxSpeedPointer = (GetLedMaxSpeedPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedMaxSpeed"), typeof(GetLedMaxSpeedPointer));
_getLedSpeedPointer = (GetLedSpeedPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedSpeed"), typeof(GetLedSpeedPointer));
_setLedColorPointer = (SetLedColorPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_SetLedColor"), typeof(SetLedColorPointer));
_setLedStylePointer = (SetLedStylePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_SetLedStyle"), typeof(SetLedStylePointer));
_setLedBrightPointer = (SetLedBrightPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_SetLedBright"), typeof(SetLedBrightPointer));
_setLedSpeedPointer = (SetLedSpeedPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_SetLedSpeed"), typeof(SetLedSpeedPointer));
_getErrorMessagePointer = (GetErrorMessagePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetErrorMessage"), typeof(GetErrorMessagePointer));
}
private static IEnumerable<string> GetPossibleLibraryPaths()
{
IEnumerable<string> possibleLibraryPaths;
if (OperatingSystem.IsWindows())
possibleLibraryPaths = Environment.Is64BitProcess ? MsiDeviceProvider.PossibleX64NativePaths : MsiDeviceProvider.PossibleX86NativePaths;
else
possibleLibraryPaths = [];
return possibleLibraryPaths.Select(Environment.ExpandEnvironmentVariables);
}
internal static void UnloadMsiSDK()
{
if (_handle == 0) return;
_initializePointer = null;
_getDeviceInfoPointer = null;
_getLedColorPointer = null;
_getLedColorPointer = null;
_getLedStylePointer = null;
_getLedMaxBrightPointer = null;
_getLedBrightPointer = null;
_getLedMaxSpeedPointer = null;
_getLedSpeedPointer = null;
_setLedColorPointer = null;
_setLedStylePointer = null;
_setLedBrightPointer = null;
_setLedSpeedPointer = null;
_getErrorMessagePointer = null;
NativeLibrary.Free(_handle);
_handle = 0;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern bool SetDllDirectory(string lpPathName);
#endregion
#region SDK-METHODS
#region Pointers
private static InitializePointer? _initializePointer;
private static GetDeviceInfoPointer? _getDeviceInfoPointer;
private static GetLedInfoPointer? _getLedInfoPointer;
private static GetLedColorPointer? _getLedColorPointer;
private static GetLedStylePointer? _getLedStylePointer;
private static GetLedMaxBrightPointer? _getLedMaxBrightPointer;
private static GetLedBrightPointer? _getLedBrightPointer;
private static GetLedMaxSpeedPointer? _getLedMaxSpeedPointer;
private static GetLedSpeedPointer? _getLedSpeedPointer;
private static SetLedColorPointer? _setLedColorPointer;
private static SetLedStylePointer? _setLedStylePointer;
private static SetLedBrightPointer? _setLedBrightPointer;
private static SetLedSpeedPointer? _setLedSpeedPointer;
private static GetErrorMessagePointer? _getErrorMessagePointer;
#endregion
#region Delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int InitializePointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetDeviceInfoPointer(
[Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] pDevType,
[Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] pLedCount);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedInfoPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.BStr)] out string pName,
[Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] pLedStyles);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedColorPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int r,
[Out, MarshalAs(UnmanagedType.I4)] out int g,
[Out, MarshalAs(UnmanagedType.I4)] out int b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedStylePointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.BStr)] out string style);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedMaxBrightPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int maxLevel);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedBrightPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int currentLevel);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedMaxSpeedPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int maxSpeed);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedSpeedPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int currentSpeed);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int SetLedColorPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[In, MarshalAs(UnmanagedType.I4)] int r,
[In, MarshalAs(UnmanagedType.I4)] int g,
[In, MarshalAs(UnmanagedType.I4)] int b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int SetLedStylePointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[In, MarshalAs(UnmanagedType.BStr)] string style);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int SetLedBrightPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[In, MarshalAs(UnmanagedType.I4)] int level);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int SetLedSpeedPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[In, MarshalAs(UnmanagedType.I4)] int speed);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetErrorMessagePointer(
[In, MarshalAs(UnmanagedType.I4)] int errorCode,
[Out, MarshalAs(UnmanagedType.BStr)] out string pDesc);
#endregion
internal static int Initialize() => (_initializePointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke();
internal static int GetDeviceInfo(out string[] pDevType, out int[] pLedCount)
{
// HACK - SDK GetDeviceInfo returns a string[] for ledCount, so we'll parse that to int.
int result = (_getDeviceInfoPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(out pDevType, out string[] ledCount);
pLedCount = new int[ledCount.Length];
for (int i = 0; i < ledCount.Length; i++)
pLedCount[i] = int.Parse(ledCount[i]);
return result;
}
internal static int GetLedInfo(string type, int index, out string pName, out string[] pLedStyles) => (_getLedInfoPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, out pName, out pLedStyles);
internal static int GetLedColor(string type, int index, out int r, out int g, out int b) => (_getLedColorPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, out r, out g, out b);
internal static int GetLedStyle(string type, int index, out string style) => (_getLedStylePointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, out style);
internal static int GetLedMaxBright(string type, int index, out int maxLevel) => (_getLedMaxBrightPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, out maxLevel);
internal static int GetLedBright(string type, int index, out int currentLevel) => (_getLedBrightPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, out currentLevel);
internal static int GetLedMaxSpeed(string type, int index, out int maxSpeed) => (_getLedMaxSpeedPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, out maxSpeed);
internal static int GetLedSpeed(string type, int index, out int currentSpeed) => (_getLedSpeedPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, out currentSpeed);
internal static int SetLedColor(string type, int index, int r, int g, int b) => (_setLedColorPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, r, g, b);
internal static int SetLedStyle(string type, int index, string style) => (_setLedStylePointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, style);
internal static int SetLedBright(string type, int index, int level) => (_setLedBrightPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, level);
internal static int SetLedSpeed(string type, int index, int speed) => (_setLedSpeedPointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(type, index, speed);
internal static string GetErrorMessage(int errorCode)
{
(_getErrorMessagePointer ?? throw new RGBDeviceException("The MSI-SDK is not initialized.")).Invoke(errorCode, out string description);
return description;
}
#endregion
}