diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..20b3a7c --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at wackermann@nexn.systems. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/DirectInputCSharpWrapper.dll b/DirectInputCSharpWrapper.dll deleted file mode 100644 index 04af355..0000000 Binary files a/DirectInputCSharpWrapper.dll and /dev/null differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7467bbf --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Markus Karl Wackermann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/test_x56_led/Classes/DirectOutput.vb b/test_x56_led/Classes/DirectOutput.vb new file mode 100644 index 0000000..22c5acd --- /dev/null +++ b/test_x56_led/Classes/DirectOutput.vb @@ -0,0 +1,240 @@ +Imports System +Imports System.Collections.Generic +Imports System.Runtime.InteropServices +Imports Microsoft.Win32 + +Imports HResult = System.Int32 + +Namespace DirectOutputVBWrapper + Public Structure SRequestStatus + Public headerError As Integer + Public headerInfo As Integer + Public requestError As Integer + Public requestInfo As Integer + End Structure + + Public Class RegistryKeyNotFound : Inherits Exception + Public Sub New() + MyBase.New("HKEY_LOCAL_MACHINE\SOFTWARE\Saitek\DirectOutput key not found.") + End Sub + End Class + + Public Class RegistryValueNotFound : Inherits Exception + Public Sub New() + MyBase.New("DirectOutput value in key HKEY_LOCAL_MACHINE\SOFTWARE\Saitek\DirectOutput not found.") + End Sub + End Class + + + Public Class HResultException : Inherits Exception + Public Const S_OK As HResult = &H0 + Public Const E_OUTOFMEMORY As HResult = CType(&H8007000E, HResult) + Public Const E_NOTIMPL As HResult = CType(&H80004001, HResult) + Public Const E_INVALIDARG As HResult = CType(&H80070057, HResult) + Public Const E_PAGENOTACTIVE As HResult = CType(&HFF040001, HResult) + Public Const E_HANDLE As HResult = CType(&H80070006, HResult) + Public Const E_UNKNOWN_1 As HResult = CType(&H51B87CE3, HResult) + + Public Sub New(ByVal result As HResult, ByVal errorsMap As Dictionary(Of HResult, String)) + MyBase.New(errorsMap(result)) + HResult = result + End Sub + End Class +End Namespace + +Public Class DirectOutputVB + Public Const IsActive As Integer = &H1 + + 'Callbacks + Public Delegate Sub EnumarateCallback(ByVal device As IntPtr, ByVal target As IntPtr) + Public Delegate Sub DeviceCallback(ByVal device As IntPtr, ByVal added As Boolean, ByVal target As IntPtr) + Public Delegate Sub SoftButtonCallback(ByVal device As IntPtr, ByVal buttons As UInteger, ByVal target As IntPtr) + Public Delegate Sub PageCallback(ByVal device As IntPtr, ByVal page As UInteger, ByVal activated As Boolean, ByVal target As IntPtr) + + 'Library functions + Private Delegate Function DirectOutput_Initialize( ByVal appName As String) As HResult + Private Delegate Function DirectOutput_Deinitialize() As HResult + Private Delegate Function DirectOutput_RegisterDeviceCallback( ByVal callback As DeviceCallback, ByVal target As IntPtr) As HResult + + + Private Delegate Function DirectOutput_Enumerate( ByVal callback As EnumarateCallback, ByVal target As IntPtr) As HResult + Private Delegate Function DirectOutput_GetDeviceType(ByVal device As IntPtr, ByRef guidType As Guid) As HResult + Private Delegate Function DirectOutput_GetDeviceInstance(ByVal device As IntPtr, ByRef guidInstance As Guid) As HResult + + Private Delegate Function DirectOutput_AddPage(ByVal device As IntPtr, ByVal page As Int32, ByVal flags As Int32) As HResult + Private Delegate Function DirectOutput_RemovePage(ByVal device As IntPtr, ByVal page As Int32) As HResult + Private Delegate Function DirectOutput_SetLed(ByVal device As IntPtr, ByVal page As Int32, ByVal index As Int32, ByVal value As Int32) As HResult + + 'Functions placeholders + Private _initialize As DirectOutput_Initialize + Private _deinitialize As DirectOutput_Deinitialize + Private _registerDeviceCallback As DirectOutput_RegisterDeviceCallback + + Private _enumerate As DirectOutput_Enumerate + Private _getDeviceType As DirectOutput_GetDeviceType + Private _getDeviceInstance As DirectOutput_GetDeviceInstance + + Private _addPage As DirectOutput_AddPage + Private _removePage As DirectOutput_RemovePage + Private _setLed As DirectOutput_SetLed + + Private Const directOutputKey As String = "SOFTWARE\Saitek\DirectOutput" + Private hModule As IntPtr + + Public Sub New(ByVal Optional libPath As String = Nothing) + If libPath Is Nothing Then + Dim key As RegistryKey = Registry.LocalMachine.OpenSubKey(directOutputKey) + If key Is Nothing Then + Throw New Exception + End If + + Dim value As String = key.GetValue("DirectOutput") + If (value Is Nothing) OrElse Not (TypeOf value Is String) Then + Throw New Exception + End If + + libPath = value.ToString + End If + + hModule = DirectOutputVBWrapper.DllHelper.LoadLibrary(libPath) + + InitializeLibraryFunctions() + End Sub + + Private Sub InitializeLibraryFunctions() + _initialize = DirectOutputVBWrapper.DllHelper.GetFunction(Of DirectOutput_Initialize)(hModule, "DirectOutput_Initialize") + _deinitialize = DirectOutputVBWrapper.DllHelper.GetFunction(Of DirectOutput_Deinitialize)(hModule, "DirectOutput_Deinitialize") + _registerDeviceCallback = DirectOutputVBWrapper.DllHelper.GetFunction(Of DirectOutput_RegisterDeviceCallback)(hModule, "DirectOutput_RegisterDeviceCallback") + + _enumerate = DirectOutputVBWrapper.DllHelper.GetFunction(Of DirectOutput_Enumerate)(hModule, "DirectOutput_Enumerate") + _getDeviceType = DirectOutputVBWrapper.DllHelper.GetFunction(Of DirectOutput_GetDeviceType)(hModule, "DirectOutput_GetDeviceType") + _getDeviceInstance = DirectOutputVBWrapper.DllHelper.GetFunction(Of DirectOutput_GetDeviceInstance)(hModule, "DirectOutput_GetDeviceInstance") + + _addPage = DirectOutputVBWrapper.DllHelper.GetFunction(Of DirectOutput_AddPage)(hModule, "DirectOutput_AddPage") + _removePage = DirectOutputVBWrapper.DllHelper.GetFunction(Of DirectOutput_RemovePage)(hModule, "DirectOutput_RemovePage") + _setLed = DirectOutputVBWrapper.DllHelper.GetFunction(Of DirectOutput_SetLed)(hModule, "DirectOutput_SetLed") + End Sub + + ''' + ''' Initialize the DirectOutput library. + ''' + ''' String that specifies the name of the application. Optional + ''' + ''' This function must be called before calling any others. Call this function when you want to initialize the DirectOutput library. + ''' + ''' + Public Sub Initialize(ByVal Optional appName As String = "DirectOutputCSharpWrapper") + Dim retVal As HResult = _initialize(appName) + + If retVal <> DirectOutputVBWrapper.HResultException.S_OK Then + Dim errorsMap As Dictionary(Of HResult, String) = New Dictionary(Of HResult, String)() From { + {DirectOutputVBWrapper.HResultException.E_OUTOFMEMORY, "There was insufficient memory to complete this call."}, + {DirectOutputVBWrapper.HResultException.E_INVALIDARG, "The argument is invalid."}, + {DirectOutputVBWrapper.HResultException.E_HANDLE, "The DirectOutputManager prcess could not be found."} + } + Throw New DirectOutputVBWrapper.HResultException(retVal, errorsMap) + End If + End Sub + + Public Sub Deinitialize() + Dim retVal As HResult = _deinitialize() + + If retVal <> DirectOutputVBWrapper.HResultException.S_OK Then + Dim errorsMap As Dictionary(Of HResult, String) = New Dictionary(Of HResult, String)() From { + {DirectOutputVBWrapper.HResultException.E_HANDLE, "DirectOutput was not initialized or was already deinitialized."} + } + Throw New DirectOutputVBWrapper.HResultException(retVal, errorsMap) + End If + End Sub + + Public Sub RegisterDeviceCallback(ByVal callback As DeviceCallback) + Dim retVal As HResult = _registerDeviceCallback(callback, New IntPtr()) + + If retVal <> DirectOutputVBWrapper.HResultException.S_OK Then + Dim errorsMap As Dictionary(Of HResult, String) = New Dictionary(Of HResult, String)() From { + {DirectOutputVBWrapper.HResultException.E_HANDLE, "DirectOutput was not initialized."} + } + Throw New DirectOutputVBWrapper.HResultException(retVal, errorsMap) + End If + End Sub + + Public Sub Enumerate(ByVal callback As EnumarateCallback) + Dim retVal As HResult = _enumerate(callback, New IntPtr()) + + If retVal <> DirectOutputVBWrapper.HResultException.S_OK Then + Dim errorsMap As Dictionary(Of HResult, String) = New Dictionary(Of HResult, String)() From { + {DirectOutputVBWrapper.HResultException.E_HANDLE, "DirectOutput was not initialized."} + } + Throw New DirectOutputVBWrapper.HResultException(retVal, errorsMap) + End If + End Sub + + Public Function GetDeviceType(ByVal device As IntPtr) As Guid + Dim guidType As Guid + Dim retVal As HResult = _getDeviceType(device, guidType) + + If retVal <> DirectOutputVBWrapper.HResultException.S_OK Then + Dim errorsMap As Dictionary(Of HResult, String) = New Dictionary(Of HResult, String)() From { + {DirectOutputVBWrapper.HResultException.E_INVALIDARG, "An argument is invalid."}, + {DirectOutputVBWrapper.HResultException.E_HANDLE, "The device handle specified is invalid."} + } + Throw New DirectOutputVBWrapper.HResultException(retVal, errorsMap) + End If + + Return guidType + End Function + + Public Function GetDeviceInstance(ByVal device As IntPtr) As Guid + Dim guidType As Guid + Dim retVal As HResult = _getDeviceInstance(device, guidType) + + If retVal <> DirectOutputVBWrapper.HResultException.S_OK Then + Dim errorsMap As Dictionary(Of HResult, String) = New Dictionary(Of HResult, String)() From { + {DirectOutputVBWrapper.HResultException.E_NOTIMPL, "This device does not support DirectInput."}, + {DirectOutputVBWrapper.HResultException.E_INVALIDARG, "An argument is invalid."}, + {DirectOutputVBWrapper.HResultException.E_HANDLE, "The device handle specified is invalid."} + } + Throw New DirectOutputVBWrapper.HResultException(retVal, errorsMap) + End If + + Return guidType + End Function + + Public Sub AddPage(ByVal device As IntPtr, ByVal page As Int32, ByVal flags As Int32) + Dim retVal As HResult = _addPage(device, page, flags) + + If retVal <> DirectOutputVBWrapper.HResultException.S_OK Then + Dim errorsMap As Dictionary(Of HResult, String) = New Dictionary(Of HResult, String)() From { + {DirectOutputVBWrapper.HResultException.E_OUTOFMEMORY, "Insufficient memory to complete the request."}, + {DirectOutputVBWrapper.HResultException.E_INVALIDARG, "The page parameter already exists."}, + {DirectOutputVBWrapper.HResultException.E_HANDLE, "The device handle specified is invalid."} + } + Throw New DirectOutputVBWrapper.HResultException(retVal, errorsMap) + End If + End Sub + + Public Sub RemovePage(ByVal device As IntPtr, ByVal page As Int32) + Dim retVal As HResult = _removePage(device, page) + + If retVal <> DirectOutputVBWrapper.HResultException.S_OK Then + Dim errorsMap As Dictionary(Of HResult, String) = New Dictionary(Of HResult, String)() From { + {DirectOutputVBWrapper.HResultException.E_INVALIDARG, "The page parameter argument does not reference a valid page id."}, + {DirectOutputVBWrapper.HResultException.E_HANDLE, "The device handle specified is invalid."} + } + Throw New DirectOutputVBWrapper.HResultException(retVal, errorsMap) + End If + End Sub + + Public Sub SetLed(ByVal device As IntPtr, ByVal page As Int32, ByVal index As Int32, ByVal value As Int32) + Dim retVal As HResult = _setLed(device, page, index, value) + + If retVal <> DirectOutputVBWrapper.HResultException.S_OK Then + Dim errorsMap As Dictionary(Of HResult, String) = New Dictionary(Of HResult, String)() From { + {DirectOutputVBWrapper.HResultException.E_PAGENOTACTIVE, "The specified page is not active. Displaying information is not permitted when the page is not active."}, + {DirectOutputVBWrapper.HResultException.E_INVALIDARG, "The dwPage argument does not reference a valid page id, or the dwIndex argument does not specifiy a valid LED id."}, + {DirectOutputVBWrapper.HResultException.E_HANDLE, "The device handle specified is invalid."} + } + Throw New DirectOutputVBWrapper.HResultException(retVal, errorsMap) + End If + End Sub +End Class diff --git a/test_x56_led/Classes/DllHelper.vb b/test_x56_led/Classes/DllHelper.vb new file mode 100644 index 0000000..5bd1a07 --- /dev/null +++ b/test_x56_led/Classes/DllHelper.vb @@ -0,0 +1,58 @@ +Imports System +Imports System.ComponentModel +Imports System.Runtime.InteropServices + +Namespace DirectOutputVBWrapper + Class DllHelper + + Private Shared Function _LoadLibrary(ByVal dllPath As String) As IntPtr + End Function + + Private Shared Function _GetProcAddress(ByVal hModule As IntPtr, ByVal procedureName As String) As IntPtr + End Function + + Private Shared Function _FreeLibrary(ByVal hModule As IntPtr) As Boolean + End Function + + Private Shared Function _GetLastError() As Integer + End Function + + Public Shared Function LoadLibrary(ByVal dllPath As String) As IntPtr + Dim moduleHandle As IntPtr = _LoadLibrary(dllPath) + + If moduleHandle = New IntPtr(0) Then + Throw New OutOfMemoryException() + ElseIf moduleHandle = New IntPtr(2) Then + Throw New Exception + ElseIf moduleHandle = New IntPtr(3) Then + Throw New Exception + ElseIf moduleHandle = New IntPtr(11) Then + Throw New Exception + End If + + Return moduleHandle + End Function + + Public Shared Function GetFunction(Of T As Class)(ByVal hModule As IntPtr, ByVal procedureName As String) As T + Dim addressOfFunctionToCall As IntPtr = _GetProcAddress(hModule, procedureName) + + If addressOfFunctionToCall = IntPtr.Zero Then + Throw New Win32Exception(_GetLastError()) + End If + + Dim functionDelegate As [Delegate] = Marshal.GetDelegateForFunctionPointer(addressOfFunctionToCall, GetType(T)) + Return TryCast(functionDelegate, T) + End Function + + Public Shared Sub FreeLibrary(ByVal hModule As IntPtr) + Dim isLibraryUnloadedSuccessfully As Boolean = _FreeLibrary(hModule) + + If Not isLibraryUnloadedSuccessfully Then + Throw New Win32Exception(_GetLastError()) + End If + End Sub + End Class + +End Namespace + + diff --git a/test_x56_led/X56_Wrapper.vb b/test_x56_led/Modules/X56_Wrapper.vb similarity index 96% rename from test_x56_led/X56_Wrapper.vb rename to test_x56_led/Modules/X56_Wrapper.vb index a7e624e..00495be 100644 --- a/test_x56_led/X56_Wrapper.vb +++ b/test_x56_led/Modules/X56_Wrapper.vb @@ -1,6 +1,4 @@ -Imports DirectOutputCSharpWrapper - -Public Class X56_Wrapper +Public Class X56_Wrapper Private _DeviceHandles As List(Of (Guid, IntPtr)) = New List(Of (Guid, IntPtr)) Public Property DeviceHandles As List(Of (Guid, IntPtr)) Set(value As List(Of (Guid, IntPtr))) @@ -24,9 +22,9 @@ Public Class X56_Wrapper Both End Enum - Private dcObj As DirectOutput = New DirectOutput - Private cbFuncEnumarateDevice As DirectOutput.EnumerateCallback - Private cbFuncNewDevice As DirectOutput.DeviceCallback + Private dcObj As DirectOutputVB = New DirectOutputVB + Private cbFuncEnumarateDevice As DirectOutputVB.EnumarateCallback + Private cbFuncNewDevice As DirectOutputVB.DeviceCallback Private Sub EnumCallback(device As IntPtr, target As IntPtr) ' GUIDs @@ -170,4 +168,4 @@ Public Class ColorCoding Int32_to_RGB.Add(Blue) Return Int32_to_RGB End Function -End Class +End Class \ No newline at end of file diff --git a/test_x56_led/test_x56_led.vbproj b/test_x56_led/test_x56_led.vbproj index ed2d575..c1726aa 100644 --- a/test_x56_led/test_x56_led.vbproj +++ b/test_x56_led/test_x56_led.vbproj @@ -49,10 +49,6 @@ On - - False - ..\DirectInputCSharpWrapper.dll - @@ -78,6 +74,8 @@ + + Form @@ -100,7 +98,7 @@ Settings.settings True - +