-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/spreedated/direct-output-…
- Loading branch information
Showing
7 changed files
with
403 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(<MarshalAsAttribute(UnmanagedType.LPWStr)> ByVal appName As String) As HResult | ||
Private Delegate Function DirectOutput_Deinitialize() As HResult | ||
Private Delegate Function DirectOutput_RegisterDeviceCallback(<MarshalAs(UnmanagedType.FunctionPtr)> ByVal callback As DeviceCallback, ByVal target As IntPtr) As HResult | ||
|
||
|
||
Private Delegate Function DirectOutput_Enumerate(<MarshalAs(UnmanagedType.FunctionPtr)> ByVal callback As EnumarateCallback, ByVal target As IntPtr) As HResult | ||
Private Delegate Function DirectOutput_GetDeviceType(ByVal device As IntPtr, <Out> ByRef guidType As Guid) As HResult | ||
Private Delegate Function DirectOutput_GetDeviceInstance(ByVal device As IntPtr, <Out> 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 | ||
|
||
''' <summary> | ||
''' Initialize the DirectOutput library. | ||
''' </summary> | ||
''' <param name="appName">String that specifies the name of the application. Optional</param> | ||
''' <remarks> | ||
''' This function must be called before calling any others. Call this function when you want to initialize the DirectOutput library. | ||
''' </remarks> | ||
''' <exception cref="DirectOutputVBWrapper.HResultException"></exception> | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
Imports System | ||
Imports System.ComponentModel | ||
Imports System.Runtime.InteropServices | ||
|
||
Namespace DirectOutputVBWrapper | ||
Class DllHelper | ||
<DllImport("kernel32.dll", EntryPoint:="LoadLibrary")> | ||
Private Shared Function _LoadLibrary(ByVal dllPath As String) As IntPtr | ||
End Function | ||
<DllImport("kernel32.dll", EntryPoint:="GetProcAddress")> | ||
Private Shared Function _GetProcAddress(ByVal hModule As IntPtr, ByVal procedureName As String) As IntPtr | ||
End Function | ||
<DllImport("kernel32.dll", EntryPoint:="FreeLibrary")> | ||
Private Shared Function _FreeLibrary(ByVal hModule As IntPtr) As Boolean | ||
End Function | ||
<DllImport("kernel32.dll", EntryPoint:="GetLastError")> | ||
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 | ||
|
||
|
Oops, something went wrong.