From 7eb264a95808b97bf40f345f79d144dabd2d182f Mon Sep 17 00:00:00 2001 From: noorus Date: Tue, 4 Feb 2014 14:08:06 +0200 Subject: [PATCH] Added support for Logitech LEDs --- include/nil.h | 25 ++++++++++- include/nilLogitech.h | 35 ++++++++++++++-- include/nilTypes.h | 9 ++++ nil.vcxproj | 6 ++- nil.vcxproj.filters | 6 +++ src/ExternalModule.cpp | 14 +++++++ src/LogitechGkeySDK.cpp | 28 ++++++++++--- src/LogitechLedSDK.cpp | 91 +++++++++++++++++++++++++++++++++++++++++ src/System.cpp | 11 +++-- 9 files changed, 209 insertions(+), 16 deletions(-) create mode 100644 src/ExternalModule.cpp create mode 100644 src/LogitechLedSDK.cpp diff --git a/include/nil.h b/include/nil.h index 619bc99..745395a 100644 --- a/include/nil.h +++ b/include/nil.h @@ -16,6 +16,7 @@ namespace nil { namespace Logitech { class GKeySDK; + class LedSDK; } //! \struct Button @@ -90,7 +91,7 @@ namespace nil { enum Type: int { Device_Keyboard = 0, //!< I'm a keyboard Device_Mouse, //!< I'm a mouse - Device_Controller //!< No, I'm a controller + Device_Controller //!< I'm a controller }; enum Status: int { Status_Disconnected = 0, //!< Disconnected but not forgotten @@ -390,6 +391,25 @@ namespace nil { typedef map RawMouseMap; typedef map RawKeyboardMap; + //! \class ExternalModule + //! Base class for an external, optional module supported by the system. + class ExternalModule { + protected: + HMODULE mModule; + bool mInitialized; + public: + enum InitReturn: unsigned int { + Initialization_OK = 0, + Initialization_ModuleNotFound, + Initialization_MissingExports, + Initialization_Unavailable + }; + ExternalModule(); + virtual InitReturn initialize() = 0; + virtual void shutdown() = 0; + virtual bool isInitialized() const; + }; + //! \class System //! The input system root. class System: public PnPListener, public RawListener { @@ -409,7 +429,8 @@ namespace nil { bool mInitializing; //!< Are we initializing? RawMouseMap mMouseMapping; //!< Mouse events mapping RawKeyboardMap mKeyboardMapping; //!< Keyboard events mapping - Logitech::GKeySDK* mLogitechGKeys; + Logitech::GKeySDK* mLogitechGKeys; //!< External module for Logitech G-Keys + Logitech::LedSDK* mLogitechLEDs; //!< External module for Logitech LEDs void initializeDevices(); void refreshDevices(); void identifyXInputDevices(); diff --git a/include/nilLogitech.h b/include/nilLogitech.h index e1a9722..1bca3f2 100644 --- a/include/nilLogitech.h +++ b/include/nilLogitech.h @@ -1,12 +1,13 @@ #pragma once #include #include +#include namespace nil { namespace Logitech { - // G-Key SDK + // G-Key SDK (1.02.004) typedef unsigned int GKey; @@ -25,9 +26,8 @@ namespace nil { typedef queue GKeyQueue; - class GKeySDK { + class GKeySDK: public ExternalModule { protected: - HMODULE mModule; struct Functions { fnLogiGkeyInit pfnLogiGkeyInit; fnLogiGkeyGetMouseButtonString pfnLogiGkeyGetMouseButtonString; @@ -42,10 +42,39 @@ namespace nil { static void __cdecl keyCallback( GkeyCode key, const wchar_t* name, void* context ); public: GKeySDK(); + virtual InitReturn initialize(); void update(); + virtual void shutdown(); ~GKeySDK(); }; + // LED SDK (1.01.005.1) + + typedef BOOL (*fnLogiLedInit)(); + typedef BOOL (*fnLogiLedSaveCurrentLighting)( int deviceType ); + typedef BOOL (*fnLogiLedSetLighting)( int deviceType, int redPercentage, int greenPercentage, int bluePercentage ); + typedef BOOL (*fnLogiLedRestoreLighting)( int deviceType ); + typedef void (*fnLogiLedShutdown)(); + + class LedSDK: public ExternalModule { + protected: + struct Functions { + fnLogiLedInit pfnLogiLedInit; + fnLogiLedSaveCurrentLighting pfnLogiLedSaveCurrentLighting; + fnLogiLedSetLighting pfnLogiLedSetLighting; + fnLogiLedRestoreLighting pfnLogiLedRestoreLighting; + fnLogiLedShutdown pfnLogiLedShutdown; + Functions(); + } mFunctions; + bool mSavedOriginal; + public: + LedSDK(); + virtual InitReturn initialize(); + void setLighting( const Color& color ); + virtual void shutdown(); + ~LedSDK(); + }; + } } \ No newline at end of file diff --git a/include/nilTypes.h b/include/nilTypes.h index 262797b..ac5e8e3 100644 --- a/include/nilTypes.h +++ b/include/nilTypes.h @@ -91,6 +91,15 @@ namespace nil { const static Vector3i ZERO; }; + //! \struct Color + //! A color value. + struct Color { + public: + Real r; //!< Red color component amount in {0..1} + Real g; //!< Green color component amount in {0..1} + Real b; //!< Blue color component amount in {0..1} + }; + //! \struct Vector2f //! Two-dimensional floating point vector. struct Vector2f { diff --git a/nil.vcxproj b/nil.vcxproj index 456c2c9..6963872 100644 --- a/nil.vcxproj +++ b/nil.vcxproj @@ -97,7 +97,7 @@ Level3 Disabled - include;external\LogitechGkeySDK_1.02.004\Include;%(AdditionalIncludeDirectories) + include;external\LogitechGkeySDK_1.02.004\Include;external\LogitechLEDSDK_1.01.005.1\Include;%(AdditionalIncludeDirectories) false true @@ -131,7 +131,7 @@ MaxSpeed true true - include;external\LogitechGkeySDK_1.02.004\Include;%(AdditionalIncludeDirectories) + include;external\LogitechGkeySDK_1.02.004\Include;external\LogitechLEDSDK_1.01.005.1\Include;%(AdditionalIncludeDirectories) false None AnySuitable @@ -167,10 +167,12 @@ + + diff --git a/nil.vcxproj.filters b/nil.vcxproj.filters index 32a2d5e..7998b26 100644 --- a/nil.vcxproj.filters +++ b/nil.vcxproj.filters @@ -101,5 +101,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/src/ExternalModule.cpp b/src/ExternalModule.cpp new file mode 100644 index 0000000..c636cd0 --- /dev/null +++ b/src/ExternalModule.cpp @@ -0,0 +1,14 @@ +#include "nil.h" + +namespace nil { + + ExternalModule::ExternalModule(): mModule( NULL ), mInitialized( false ) + { + } + + bool ExternalModule::isInitialized() const + { + return mInitialized; + } + +} \ No newline at end of file diff --git a/src/LogitechGkeySDK.cpp b/src/LogitechGkeySDK.cpp index 98bbeae..fab9686 100644 --- a/src/LogitechGkeySDK.cpp +++ b/src/LogitechGkeySDK.cpp @@ -32,15 +32,18 @@ namespace nil { { } - GKeySDK::GKeySDK(): mModule( NULL ) + GKeySDK::GKeySDK(): ExternalModule() { InitializeSRWLock( &mLock ); mListeners.push_back( &gDummyGKeyListener ); + } + GKeySDK::InitReturn GKeySDK::initialize() + { mModule = LoadLibraryW( cLogitechGKeyModuleName ); if ( !mModule ) - NIL_EXCEPT_WINAPI( L"Couldn't load Logitech GKey module" ); + return Initialization_ModuleNotFound; NIL_LOAD_SDK_FUNC( LogiGkeyInit ); NIL_LOAD_SDK_FUNC( LogiGkeyGetMouseButtonString ); @@ -51,13 +54,17 @@ namespace nil { || !mFunctions.pfnLogiGkeyGetMouseButtonString || !mFunctions.pfnLogiGkeyGetKeyboardGkeyString || !mFunctions.pfnLogiGkeyShutdown ) - NIL_EXCEPT( L"Couldn't load Logitech GKey module" ); + return Initialization_MissingExports; mContext.gkeyContext = this; mContext.gkeyCallBack = keyCallback; if ( !mFunctions.pfnLogiGkeyInit( &mContext ) ) - NIL_EXCEPT( L"Couldn't initialize Logitech GKey module" ); + return Initialization_Unavailable; + + mInitialized = true; + + return Initialization_OK; } void GKeySDK::keyCallback( GkeyCode key, const wchar_t* name, void* context ) @@ -85,14 +92,23 @@ namespace nil { ReleaseSRWLockExclusive( &mLock ); } - GKeySDK::~GKeySDK() + void GKeySDK::shutdown() { + AcquireSRWLockExclusive( &mLock ); if ( mModule ) { - if ( mFunctions.pfnLogiGkeyShutdown ) + if ( mInitialized ) mFunctions.pfnLogiGkeyShutdown(); FreeLibrary( mModule ); + mModule = NULL; } + mInitialized = false; + ReleaseSRWLockExclusive( &mLock ); + } + + GKeySDK::~GKeySDK() + { + shutdown(); } } diff --git a/src/LogitechLedSDK.cpp b/src/LogitechLedSDK.cpp new file mode 100644 index 0000000..1e8fe7c --- /dev/null +++ b/src/LogitechLedSDK.cpp @@ -0,0 +1,91 @@ +#include "nil.h" +#include "nilLogitech.h" +#include "nilUtil.h" + +# define NIL_LOAD_SDK_FUNC(x) mFunctions.pfn##x##=(fn##x##)GetProcAddress(mModule,#x) + +namespace nil { + + namespace Logitech { + + const wchar_t* cLogitechLedModuleName = L"LogitechLed.dll"; + + LedSDK::Functions::Functions(): + pfnLogiLedInit( nullptr ), + pfnLogiLedSaveCurrentLighting( nullptr ), + pfnLogiLedSetLighting( nullptr ), + pfnLogiLedRestoreLighting( nullptr ), + pfnLogiLedShutdown( nullptr ) + { + } + + LedSDK::LedSDK(): ExternalModule(), mSavedOriginal( false ) + { + // + } + + LedSDK::InitReturn LedSDK::initialize() + { + mModule = LoadLibraryW( cLogitechLedModuleName ); + if ( !mModule ) + return Initialization_ModuleNotFound; + + NIL_LOAD_SDK_FUNC( LogiLedInit ); + NIL_LOAD_SDK_FUNC( LogiLedSaveCurrentLighting ); + NIL_LOAD_SDK_FUNC( LogiLedSetLighting ); + NIL_LOAD_SDK_FUNC( LogiLedRestoreLighting ); + NIL_LOAD_SDK_FUNC( LogiLedShutdown ); + + if ( !mFunctions.pfnLogiLedInit + || !mFunctions.pfnLogiLedSaveCurrentLighting + || !mFunctions.pfnLogiLedSetLighting + || !mFunctions.pfnLogiLedRestoreLighting + || !mFunctions.pfnLogiLedShutdown ) + return Initialization_MissingExports; + + if ( !mFunctions.pfnLogiLedInit() ) + return Initialization_Unavailable; + + if ( mFunctions.pfnLogiLedSaveCurrentLighting( LOGITECH_LED_ALL ) ) + mSavedOriginal = true; + + mInitialized = true; + + return Initialization_OK; + } + + void LedSDK::setLighting( const Color& color ) + { + if ( !mInitialized ) + return; + + int r = (int)( color.r * 100.0f ); + int g = (int)( color.g * 100.0f ); + int b = (int)( color.b * 100.0f ); + + mFunctions.pfnLogiLedSetLighting( LOGITECH_LED_ALL, r, g, b ); + } + + void LedSDK::shutdown() + { + if ( mModule ) + { + if ( mSavedOriginal ) + mFunctions.pfnLogiLedRestoreLighting( LOGITECH_LED_ALL ); + if ( mInitialized ) + mFunctions.pfnLogiLedShutdown(); + FreeLibrary( mModule ); + mModule = NULL; + } + mInitialized = false; + mSavedOriginal = false; + } + + LedSDK::~LedSDK() + { + shutdown(); + } + + } + +} \ No newline at end of file diff --git a/src/System.cpp b/src/System.cpp index a3f40b7..0ec1359 100644 --- a/src/System.cpp +++ b/src/System.cpp @@ -7,13 +7,14 @@ namespace nil { System::System( HINSTANCE instance, HWND window ): mWindow( window ), mInstance( instance ), mDirectInput( nullptr ), mMonitor( nullptr ), mIDPool( 0 ), mInitializing( true ), mHIDManager( nullptr ), - mLogitechGKeys( nullptr ) + mLogitechGKeys( nullptr ), mLogitechLEDs( nullptr ) { // Validate the passes window handle if ( !IsWindow( mWindow ) ) NIL_EXCEPT( L"Window handle is invalid" ); mLogitechGKeys = new Logitech::GKeySDK(); + mLogitechLEDs = new Logitech::LedSDK(); // Create DirectInput instance auto hr = DirectInput8Create( mInstance, DIRECTINPUT_VERSION, @@ -273,14 +274,17 @@ namespace nil { // Run PnP & raw events if there are any mMonitor->update(); - // First make sure that we disconnect failed devices + // Make sure that we disconnect failed devices, + // and update the rest for ( Device* device : mDevices ) if ( device->isDisconnectFlagged() ) device->onDisconnect(); else device->update(); - mLogitechGKeys->update(); + // Run queued G-key events if using the SDK + if ( mLogitechGKeys->isInitialized() ) + mLogitechGKeys->update(); } System::~System() @@ -291,6 +295,7 @@ namespace nil { SAFE_DELETE( mHIDManager ); SAFE_DELETE( mMonitor ); SAFE_RELEASE( mDirectInput ); + SAFE_DELETE( mLogitechLEDs ); SAFE_DELETE( mLogitechGKeys ); }