diff --git a/configure.ac b/configure.ac index 081cb2be..7445ffc2 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,19 @@ PKG_CHECK_MODULES([DBUS], [dbus-1]) AC_CHECK_LIB(gthread-2.0, g_thread_init) +# Thunder COM-RPC plugin support +AC_ARG_ENABLE([thunder-plugin], + AS_HELP_STRING([--enable-thunder-plugin], [Enable Thunder COM-RPC plugin support (default: no)]), + [enable_thunder_plugin=$enableval], + [enable_thunder_plugin=no]) + +AM_CONDITIONAL([USE_THUNDER_PLUGIN], [test "x$enable_thunder_plugin" = "xyes"]) + +AS_IF([test "x$enable_thunder_plugin" = "xyes"], + [AC_DEFINE([USE_WPE_THUNDER_PLUGIN], [1], [Define to 1 to enable Thunder COM-RPC plugin support]) + AC_MSG_NOTICE([Thunder COM-RPC plugin support enabled])], + [AC_MSG_NOTICE([Thunder COM-RPC plugin support disabled])]) + # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_PID_T AC_TYPE_SIZE_T diff --git a/cov_build.sh b/cov_build.sh index 22e8d7d4..1f1a6463 100644 --- a/cov_build.sh +++ b/cov_build.sh @@ -66,8 +66,10 @@ cd ${RDK_SOURCE_PATH} export STANDALONE_BUILD_ENABLED=y export DS_MGRS=$WORKDIR +export USE_WPE_THUNDER_PLUGIN=y + find $WORKDIR -iname "*.o" -exec rm -v {} \; find $WORKDIR -iname "*.so*" -exec rm -v {} \; echo "##### Triggering make" -make CFLAGS+='-fPIC -DDSMGR_LOGGER_ENABLED=ON -DRDK_DSHAL_NAME=\"libdshal.so\" -I${DS_IF_PATH}/include -I${DS_HAL_PATH} -I${DS_MGRS}/stubs -I${IARMBUS_PATH}/core -I${IARMBUS_PATH}/core/include -I${IARM_MGRS}/sysmgr/include -I${DS_MGRS}/ds/include -I${DS_MGRS}/rpc/include -I${POWER_IF_PATH}/include/ -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I${IARM_MGRS}/mfr/include/ -I${IARM_MGRS}/mfr/common -I${DEEPSLEEP_IF_PATH}/include -I${IARM_MGRS}/hal/include -I${IARM_MGRS}/power -I${IARM_MGRS}/power/include' LDFLAGS="-L/usr/lib/x86_64-linux-gnu/ -L/usr/local/include -lglib-2.0 -lIARMBus -lWPEFrameworkPowerController -ldshal" \ No newline at end of file +make CFLAGS+='-fPIC -DDSMGR_LOGGER_ENABLED=ON -DRDK_DSHAL_NAME=\"libdshal.so\" -I${DS_IF_PATH}/include -I${DS_HAL_PATH} -I${DS_MGRS}/stubs -I${IARMBUS_PATH}/core -I${IARMBUS_PATH}/core/include -I${IARM_MGRS}/sysmgr/include -I${DS_MGRS}/ds/include -I${DS_MGRS}/rpc/include -I${POWER_IF_PATH}/include/ -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I${IARM_MGRS}/mfr/include/ -I${IARM_MGRS}/mfr/common -I${DEEPSLEEP_IF_PATH}/include -I${IARM_MGRS}/hal/include -I${IARM_MGRS}/power -I${IARM_MGRS}/power/include' LDFLAGS="-L/usr/lib/x86_64-linux-gnu/ -L/usr/local/include -lglib-2.0 -lIARMBus -lWPEFrameworkPowerController -ldshal" diff --git a/rpc/cli/Makefile b/rpc/cli/Makefile index ab24c14f..7b2575ee 100644 --- a/rpc/cli/Makefile +++ b/rpc/cli/Makefile @@ -21,8 +21,20 @@ CFLAGS += -g -fPIC -D_REENTRANT -Wall LIBNAME := dshalcli LIBNAMEFULL := lib$(LIBNAME).so INSTALL := $(PWD)/install -OBJS := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) -OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) + +# Conditional compilation: Thunder vs IARM +ifdef USE_WPE_THUNDER_PLUGIN + # Thunder mode - use dsFPD-com.cpp, exclude dsFPD.c + OBJS := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) + OBJS += $(patsubst %.c,%.o,$(filter-out dsFPD.c,$(wildcard *.c))) +else + # IARM mode - use dsFPD.c, exclude dsFPD-com.cpp + OBJS := $(patsubst %.cpp,%.o,$(filter-out dsFPD-com.cpp,$(wildcard *.cpp))) + OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) +endif + +#OBJS := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) +#OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) INCLUDE := -I$(PWD) \ -I$(PWD)/hal/include \ -I$(PWD)/rpc/include @@ -31,13 +43,19 @@ INCLUDE += $(HAL_INCLUDE) CFLAGS += $(INCLUDE) +# Conditional linking flags +ifdef USE_WPE_THUNDER_PLUGIN + LDLIBS := -lWPEFrameworkCore -lWPEFrameworkCOM +else + LDLIBS := -lIARMBus +endif all: install @echo "Build Finished...." library: $(OBJS) @echo "Building $(LIBNAMEFULL) ...." - $(CXX) $(OBJS) $(CFLAGS) -lIARMBus -shared -o $(LIBNAMEFULL) + $(CXX) $(OBJS) $(CFLAGS) $(LDLIBS) -shared -o $(LIBNAMEFULL) %.o: %.cpp @echo "Building $@ ...." diff --git a/rpc/cli/Makefile.am b/rpc/cli/Makefile.am index fe48bb37..27f50c1b 100644 --- a/rpc/cli/Makefile.am +++ b/rpc/cli/Makefile.am @@ -28,4 +28,15 @@ INCLUDE_FILES = -I=$(includedir)/rdk/halif/ds-hal \ lib_LTLIBRARIES = libdshalcli.la libdshalcli_la_CPPFLAGS = $(INCLUDE_FILES) libdshalcli_la_CFLAGS = -g -fPIC -D_REENTRANT -Wall -libdshalcli_la_SOURCES = dsAudio.c dsclientlogger.c dsDisplay.c dsFPD.c dsHost.cpp dsVideoDevice.c dsVideoPort.c + +# Conditional compilation for Thunder COM-RPC +if USE_THUNDER_PLUGIN + FPD_SOURCE = dsFPD-com.cpp + THUNDER_LIBS = -lWPEFrameworkCore -lWPEFrameworkCOM +else + FPD_SOURCE = dsFPD.c + THUNDER_LIBS = +endif + +libdshalcli_la_SOURCES = dsAudio.c dsclientlogger.c dsDisplay.c $(FPD_SOURCE) dsHost.cpp dsVideoDevice.c dsVideoPort.c +libdshalcli_la_LIBADD = $(THUNDER_LIBS) diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp new file mode 100644 index 00000000..53631e05 --- /dev/null +++ b/rpc/cli/dsFPD-com.cpp @@ -0,0 +1,760 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/** +* @defgroup devicesettings +* @{ +* @defgroup rpc +* @{ +**/ + +#ifdef USE_WPE_THUNDER_PLUGIN + +#include +#include +#include +#include + +#include "dsFPD.h" +#include "dsError.h" +#include "dsclientlogger.h" + +// Thunder COM-RPC includes +#ifndef MODULE_NAME +#define MODULE_NAME DeviceSettings_FPD_Client +#endif + +#include +#include +#include +#include + +using namespace WPEFramework; + +// Thunder callsign for DeviceSettings plugin +static constexpr const TCHAR callSign[] = _T("org.rdk.DeviceSettings"); + +/** + * @brief DeviceSettingsFPD class manages Thunder COM-RPC connection for FPD + */ +class DeviceSettingsFPD : public RPC::SmartInterfaceType { +private: + using BaseClass = RPC::SmartInterfaceType; + + Exchange::IDeviceSettingsFPD* _fpdInterface; + + static DeviceSettingsFPD* _instance; + static Core::CriticalSection _apiLock; + + bool _connected; + bool _shutdown; + + DeviceSettingsFPD() + : BaseClass() + , _fpdInterface(nullptr) + , _connected(false) + , _shutdown(false) + { + (void)Connect(); + } + + ~DeviceSettingsFPD() + { + _shutdown = true; + BaseClass::Close(Core::infinite); + } + + virtual void Operational(const bool upAndRunning) override + { + _apiLock.Lock(); + + if (upAndRunning) { + // Communicator opened && DeviceSettings is Activated + if (nullptr == _fpdInterface) { + _fpdInterface = BaseClass::Interface(); + if (_fpdInterface != nullptr) { + printf("[dsFPD-com] Successfully established COM-RPC connection with DeviceSettings plugin\n"); + } else { + fprintf(stderr, "[dsFPD-com] Failed to get interface - plugin implementation may have failed to load\n"); + } + } + } else { + // DeviceSettings is Deactivated || Communicator closed + if (nullptr != _fpdInterface) { + _fpdInterface->Release(); + _fpdInterface = nullptr; + } + } + _apiLock.Unlock(); + } + + inline bool IsActivatedLocked() const + { + return (nullptr != _fpdInterface); + } + + inline bool isConnected() const + { + return _connected; + } + +public: + bool IsOperational() const + { + _apiLock.Lock(); + bool result = (isConnected() && (nullptr != _fpdInterface)); + _apiLock.Unlock(); + return result; + } + + bool WaitForOperational(uint32_t timeoutMs = 5000) const + { + const uint32_t pollIntervalMs = 100; + uint32_t elapsedMs = 0; + + while (elapsedMs < timeoutMs) { + if (IsOperational()) { + return true; + } + std::this_thread::sleep_for(std::chrono::milliseconds(pollIntervalMs)); + elapsedMs += pollIntervalMs; + } + return false; + } + + uint32_t Connect() + { + uint32_t status = Core::ERROR_NONE; + + _apiLock.Lock(); + + if (!isConnected()) { + printf("[dsFPD-com] Attempting to connect to Thunder with callsign: %s\n", callSign); + uint32_t res = BaseClass::Open(RPC::CommunicationTimeOut, BaseClass::Connector(), callSign); + if (Core::ERROR_NONE == res) { + _connected = true; + printf("[dsFPD-com] Successfully opened RPC connection to Thunder\n"); + } else { + fprintf(stderr, "[dsFPD-com] Failed to open RPC connection, error: %u. Is Thunder running?\n", res); + status = Core::ERROR_UNAVAILABLE; + } + } + + if (nullptr == _fpdInterface) { + status = Core::ERROR_NOT_EXIST; + printf("[dsFPD-com] DeviceSettings plugin not yet operational\n"); + } + + _apiLock.Unlock(); + + return status; + } + + uint32_t Disconnect() + { + uint32_t status = Core::ERROR_GENERAL; + bool close = false; + + _apiLock.Lock(); + + if (isConnected()) { + close = true; + _connected = false; + } + + _apiLock.Unlock(); + + if (close) { + status = BaseClass::Close(Core::infinite); + } + + return status; + } + + static void Init() + { + _apiLock.Lock(); + if (nullptr == _instance) { + _instance = new DeviceSettingsFPD(); + } + _apiLock.Unlock(); + } + + static void Term() + { + _apiLock.Lock(); + if (nullptr != _instance) { + delete _instance; + _instance = nullptr; + } + _apiLock.Unlock(); + } + + static DeviceSettingsFPD* Instance() + { + return _instance; + } + + // FPD API implementations + // Note: Thunder interface doesn't have FPDInit/FPDTerm/SetFPDText methods + + Core::hresult SetFPDTime(const Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat, + const uint32_t minutes, const uint32_t seconds) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDTime(timeFormat, minutes, seconds); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult SetFPDScroll(const uint32_t scrollHoldOnDur, const uint32_t horzScrollIterations, + const uint32_t vertScrollIterations) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDScroll(scrollHoldOnDur, horzScrollIterations, vertScrollIterations); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult SetFPDBlink(const Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + const uint32_t blinkDuration, const uint32_t blinkIterations) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDBlink(indicator, blinkDuration, blinkIterations); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult GetFPDBrightness(const Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + uint32_t& brightness) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->GetFPDBrightness(indicator, brightness); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult SetFPDBrightness(const Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + const uint32_t brightness, const bool persist) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDBrightness(indicator, brightness, persist); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult GetFPDTextBrightness(const Exchange::IDeviceSettingsFPD::FPDTextDisplay indicator, + uint32_t& brightness) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->GetFPDTextBrightness(indicator, brightness); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult SetFPDTextBrightness(const Exchange::IDeviceSettingsFPD::FPDTextDisplay indicator, + const uint32_t brightness) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDTextBrightness(indicator, brightness); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult GetFPDColor(const Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + uint32_t& color) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->GetFPDColor(indicator, color); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult SetFPDColor(const Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + const uint32_t color) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDColor(indicator, color); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult EnableFPDClockDisplay(const bool enable) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->EnableFPDClockDisplay(enable); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult SetFPDState(const Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + const Exchange::IDeviceSettingsFPD::FPDState state) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDState(indicator, state); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult GetFPDState(const Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + Exchange::IDeviceSettingsFPD::FPDState& state) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->GetFPDState(indicator, state); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult GetFPDTimeFormat(Exchange::IDeviceSettingsFPD::FPDTimeFormat& timeFormat) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->GetFPDTimeFormat(timeFormat); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult SetFPDTimeFormat(const Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDTimeFormat(timeFormat); + } + _apiLock.Unlock(); + return result; + } + + Core::hresult SetFPDMode(const Exchange::IDeviceSettingsFPD::FPDMode mode) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDMode(mode); + } + _apiLock.Unlock(); + return result; + } +}; + +// Static member initialization +DeviceSettingsFPD* DeviceSettingsFPD::_instance = nullptr; +Core::CriticalSection DeviceSettingsFPD::_apiLock; + +/** + * @brief Convert Thunder error code to dsError_t + */ +static dsError_t ConvertThunderError(uint32_t thunderError) +{ + if (thunderError == Core::ERROR_NONE) { + return dsERR_NONE; + } else if (thunderError == Core::ERROR_UNAVAILABLE) { + return dsERR_OPERATION_NOT_SUPPORTED; + } else if (thunderError == Core::ERROR_BAD_REQUEST) { + return dsERR_INVALID_PARAM; + } else { + return dsERR_GENERAL; + } +} + +// C API implementations using Thunder COM-RPC + +extern "C" { + +// Forward declarations +dsError_t dsSetFPDBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t eBrightness, bool toPersist); +dsError_t dsSetFPDColor(dsFPDIndicator_t eIndicator, dsFPDColor_t eColor, bool toPersist); + +dsError_t dsFPInit(void) +{ + printf("<<<<< Front Panel is initialized in Thunder Mode >>>>>>>>\r\n"); + + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance) { + DeviceSettingsFPD::Init(); + instance = DeviceSettingsFPD::Instance(); + } + + if (!instance) { + fprintf(stderr, "[dsFPD-com] Failed to create DeviceSettingsFPD instance\n"); + return dsERR_GENERAL; + } + + // Wait for plugin to become operational + if (!instance->WaitForOperational(5000)) { + fprintf(stderr, "[dsFPD-com] DeviceSettings plugin not operational after 5 seconds\n"); + return dsERR_GENERAL; + } + + // Thunder interface doesn't have explicit Init method - connection is sufficient + return dsERR_NONE; +} + +dsError_t dsFPTerm(void) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance) { + return dsERR_GENERAL; + } + + // Thunder interface doesn't have explicit Term method + // Terminate instance + DeviceSettingsFPD::Term(); + + return dsERR_NONE; +} + +dsError_t dsSetFPText(const char* pszChars) +{ + if (pszChars == NULL) { + fprintf(stderr, "[dsFPD-com] Invalid parameter: pszChars is NULL\n"); + return dsERR_INVALID_PARAM; + } + + // Thunder interface doesn't support text display + fprintf(stderr, "[dsFPD-com] SetFPText not supported in Thunder mode\n"); + return dsERR_OPERATION_NOT_SUPPORTED; +} + +dsError_t dsSetFPTime(dsFPDTimeFormat_t eTime, const unsigned int uHour, const unsigned int uMinutes) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat = + static_cast(eTime); + + // Note: Interface expects minutes and seconds, but API provides hour and minutes + // Converting: treating uMinutes as seconds for interface compatibility + uint32_t result = instance->SetFPDTime(timeFormat, uHour, uMinutes); + return ConvertThunderError(result); +} + +dsError_t dsSetFPScroll(unsigned int nScrollHoldOnDur, unsigned int nHorzScrollIterations, unsigned int nVertScrollIterations) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + uint32_t result = instance->SetFPDScroll(nScrollHoldOnDur, nHorzScrollIterations, nVertScrollIterations); + return ConvertThunderError(result); +} + +dsError_t dsSetFPBlink(dsFPDIndicator_t eIndicator, unsigned int nBlinkDuration, unsigned int nBlinkIterations) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); + + uint32_t result = instance->SetFPDBlink(indicator, nBlinkDuration, nBlinkIterations); + return ConvertThunderError(result); +} + +dsError_t dsGetFPBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t *pBrightness) +{ + if (pBrightness == NULL) { + fprintf(stderr, "[dsFPD-com] Invalid parameter: pBrightness is NULL\n"); + return dsERR_INVALID_PARAM; + } + + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); + + uint32_t brightness = 0; + uint32_t result = instance->GetFPDBrightness(indicator, brightness); + + if (result == Core::ERROR_NONE) { + *pBrightness = static_cast(brightness); + } + + return ConvertThunderError(result); +} + +dsError_t dsGetFPDBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t *pBrightness, bool persist) +{ + // Note: persist parameter may not be used in GET operation for Thunder + return dsGetFPBrightness(eIndicator, pBrightness); +} + +dsError_t dsSetFPBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t eBrightness) +{ + return dsSetFPDBrightness(eIndicator, eBrightness, true); +} + +dsError_t dsSetFPDBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t eBrightness, bool toPersist) +{ + if (eIndicator >= dsFPD_INDICATOR_MAX || eBrightness > 100) { + fprintf(stderr, "[dsFPD-com] Invalid parameter\n"); + return dsERR_INVALID_PARAM; + } + + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); + + uint32_t result = instance->SetFPDBrightness(indicator, static_cast(eBrightness), toPersist); + return ConvertThunderError(result); +} + +dsError_t dsGetFPTextBrightness(dsFPDTextDisplay_t eIndicator, dsFPDBrightness_t *pBrightness) +{ + if (pBrightness == NULL) { + fprintf(stderr, "[dsFPD-com] Invalid parameter: pBrightness is NULL\n"); + return dsERR_INVALID_PARAM; + } + + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDTextDisplay indicator = + static_cast(eIndicator); + + uint32_t brightness = 0; + uint32_t result = instance->GetFPDTextBrightness(indicator, brightness); + + if (result == Core::ERROR_NONE) { + *pBrightness = static_cast(brightness); + } + + return ConvertThunderError(result); +} + +dsError_t dsSetFPTextBrightness(dsFPDTextDisplay_t eIndicator, dsFPDBrightness_t eBrightness) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDTextDisplay indicator = + static_cast(eIndicator); + + uint32_t result = instance->SetFPDTextBrightness(indicator, static_cast(eBrightness)); + return ConvertThunderError(result); +} + +dsError_t dsGetFPColor(dsFPDIndicator_t eIndicator, dsFPDColor_t *pColor) +{ + if (pColor == NULL) { + fprintf(stderr, "[dsFPD-com] Invalid parameter: pColor is NULL\n"); + return dsERR_INVALID_PARAM; + } + + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); + + uint32_t color = 0; + uint32_t result = instance->GetFPDColor(indicator, color); + + if (result == Core::ERROR_NONE) { + *pColor = static_cast(color); + } + + return ConvertThunderError(result); +} + +dsError_t dsSetFPColor(dsFPDIndicator_t eIndicator, dsFPDColor_t eColor) +{ + return dsSetFPDColor(eIndicator, eColor, true); +} + +dsError_t dsSetFPDColor(dsFPDIndicator_t eIndicator, dsFPDColor_t eColor, bool toPersist) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); + + // Thunder interface doesn't support persist flag - ignore it + uint32_t result = instance->SetFPDColor(indicator, static_cast(eColor)); + return ConvertThunderError(result); +} + +dsError_t dsFPEnableCLockDisplay(int enable) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + uint32_t result = instance->EnableFPDClockDisplay(enable != 0); + return ConvertThunderError(result); +} + +dsError_t dsSetFPState(dsFPDIndicator_t eIndicator, dsFPDState_t state) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); + Exchange::IDeviceSettingsFPD::FPDState fpdState = + static_cast(state); + + uint32_t result = instance->SetFPDState(indicator, fpdState); + return ConvertThunderError(result); +} + +dsError_t dsGetFPState(dsFPDIndicator_t eIndicator, dsFPDState_t* state) +{ + if (state == NULL) { + fprintf(stderr, "[dsFPD-com] Invalid parameter: state is NULL\n"); + return dsERR_INVALID_PARAM; + } + + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); + + Exchange::IDeviceSettingsFPD::FPDState fpdState; + uint32_t result = instance->GetFPDState(indicator, fpdState); + + if (result == Core::ERROR_NONE) { + *state = static_cast(fpdState); + } + + return ConvertThunderError(result); +} + +dsError_t dsGetFPTimeFormat(dsFPDTimeFormat_t *pTimeFormat) +{ + if (pTimeFormat == NULL) { + fprintf(stderr, "[dsFPD-com] Invalid parameter: pTimeFormat is NULL\n"); + return dsERR_INVALID_PARAM; + } + + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat; + uint32_t result = instance->GetFPDTimeFormat(timeFormat); + + if (result == Core::ERROR_NONE) { + *pTimeFormat = static_cast(timeFormat); + } + + return ConvertThunderError(result); +} + +dsError_t dsSetFPTimeFormat(dsFPDTimeFormat_t eTimeFormat) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat = + static_cast(eTimeFormat); + + uint32_t result = instance->SetFPDTimeFormat(timeFormat); + return ConvertThunderError(result); +} + +dsError_t dsSetFPDMode(dsFPDMode_t eMode) +{ + DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); + if (!instance || !instance->IsOperational()) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD::FPDMode mode = + static_cast(eMode); + + uint32_t result = instance->SetFPDMode(mode); + return ConvertThunderError(result); +} + +} // extern "C" + +#endif // USE_WPE_THUNDER_PLUGIN + +/** @} */ +/** @} */