From 3324427cea6207b88d5278ef792c92f8c5436379 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Tue, 27 Jan 2026 18:23:26 +0000 Subject: [PATCH 01/23] RDKEMW-9659 Implement DeviceSettings client library for FPD in rpc/cli --- configure.ac | 13 + rpc/cli/Makefile | 20 +- rpc/cli/Makefile.am | 13 +- rpc/cli/dsFPD-com.cpp | 758 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 802 insertions(+), 2 deletions(-) create mode 100644 rpc/cli/dsFPD-com.cpp 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/rpc/cli/Makefile b/rpc/cli/Makefile index ab24c14f..06f2b963 100644 --- a/rpc/cli/Makefile +++ b/rpc/cli/Makefile @@ -21,6 +21,18 @@ CFLAGS += -g -fPIC -D_REENTRANT -Wall LIBNAME := dshalcli LIBNAMEFULL := lib$(LIBNAME).so INSTALL := $(PWD)/install + +# 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) \ @@ -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..3f7f5183 --- /dev/null +++ b/rpc/cli/dsFPD-com.cpp @@ -0,0 +1,758 @@ +/* + * 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 DeviceSettingsManager plugin +static constexpr const TCHAR callSign[] = _T("org.rdk.DeviceSettingsManager"); + +/** + * @brief DeviceSettingsFPD class manages Thunder COM-RPC connection for FPD + */ +class DeviceSettingsFPD : public RPC::SmartInterfaceType { +private: + using BaseClass = RPC::SmartInterfaceType; + + Exchange::IDeviceSettingsManagerFPD* _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 && DeviceSettingsManager is Activated + if (nullptr == _fpdInterface) { + _fpdInterface = BaseClass::Interface(); + if (_fpdInterface != nullptr) { + printf("[dsFPD-com] Successfully established COM-RPC connection with DeviceSettingsManager plugin\n"); + } else { + fprintf(stderr, "[dsFPD-com] Failed to get interface - plugin implementation may have failed to load\n"); + } + } + } else { + // DeviceSettingsManager 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] DeviceSettingsManager 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::IDeviceSettingsManagerFPD::FPDTimeFormat timeFormat, + const uint32_t hour, const uint32_t minutes) + { + Core::hresult result = Core::ERROR_UNAVAILABLE; + _apiLock.Lock(); + if (_fpdInterface) { + result = _fpdInterface->SetFPDTime(timeFormat, hour, minutes); + } + _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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::FPDIndicator indicator, + const Exchange::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::FPDIndicator indicator, + Exchange::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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] DeviceSettingsManager 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::IDeviceSettingsManagerFPD::FPDTimeFormat timeFormat = + static_cast(eTime); + + 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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::FPDIndicator indicator = + static_cast(eIndicator); + Exchange::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::FPDIndicator indicator = + static_cast(eIndicator); + + Exchange::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::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::IDeviceSettingsManagerFPD::FPDMode mode = + static_cast(eMode); + + uint32_t result = instance->SetFPDMode(mode); + return ConvertThunderError(result); +} + +} // extern "C" + +#endif // USE_WPE_THUNDER_PLUGIN + +/** @} */ +/** @} */ From b6e760cf82ebf3486298a6b5ca2364978207532d Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Fri, 30 Jan 2026 16:50:14 +0000 Subject: [PATCH 02/23] Modified the dsFPD-com.cpp code based on latest DeviceSettings plugin and Interface changes --- rpc/cli/dsFPD-com.cpp | 114 +++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp index 3f7f5183..53631e05 100644 --- a/rpc/cli/dsFPD-com.cpp +++ b/rpc/cli/dsFPD-com.cpp @@ -43,21 +43,21 @@ #include #include #include -#include +#include using namespace WPEFramework; -// Thunder callsign for DeviceSettingsManager plugin -static constexpr const TCHAR callSign[] = _T("org.rdk.DeviceSettingsManager"); +// 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 { +class DeviceSettingsFPD : public RPC::SmartInterfaceType { private: - using BaseClass = RPC::SmartInterfaceType; + using BaseClass = RPC::SmartInterfaceType; - Exchange::IDeviceSettingsManagerFPD* _fpdInterface; + Exchange::IDeviceSettingsFPD* _fpdInterface; static DeviceSettingsFPD* _instance; static Core::CriticalSection _apiLock; @@ -85,17 +85,17 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeRelease(); _fpdInterface = nullptr; @@ -158,7 +158,7 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeSetFPDTime(timeFormat, hour, minutes); + result = _fpdInterface->SetFPDTime(timeFormat, minutes, seconds); } _apiLock.Unlock(); return result; @@ -238,7 +238,7 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeWaitForOperational(5000)) { - fprintf(stderr, "[dsFPD-com] DeviceSettingsManager plugin not operational after 5 seconds\n"); + fprintf(stderr, "[dsFPD-com] DeviceSettings plugin not operational after 5 seconds\n"); return dsERR_GENERAL; } @@ -477,9 +477,11 @@ dsError_t dsSetFPTime(dsFPDTimeFormat_t eTime, const unsigned int uHour, const u return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDTimeFormat timeFormat = - static_cast(eTime); + 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); } @@ -502,8 +504,8 @@ dsError_t dsSetFPBlink(dsFPDIndicator_t eIndicator, unsigned int nBlinkDuration, return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDIndicator indicator = - static_cast(eIndicator); + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); uint32_t result = instance->SetFPDBlink(indicator, nBlinkDuration, nBlinkIterations); return ConvertThunderError(result); @@ -521,8 +523,8 @@ dsError_t dsGetFPBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t *pBri return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDIndicator indicator = - static_cast(eIndicator); + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); uint32_t brightness = 0; uint32_t result = instance->GetFPDBrightness(indicator, brightness); @@ -557,8 +559,8 @@ dsError_t dsSetFPDBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t eBri return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDIndicator indicator = - static_cast(eIndicator); + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); uint32_t result = instance->SetFPDBrightness(indicator, static_cast(eBrightness), toPersist); return ConvertThunderError(result); @@ -576,8 +578,8 @@ dsError_t dsGetFPTextBrightness(dsFPDTextDisplay_t eIndicator, dsFPDBrightness_t return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDTextDisplay indicator = - static_cast(eIndicator); + Exchange::IDeviceSettingsFPD::FPDTextDisplay indicator = + static_cast(eIndicator); uint32_t brightness = 0; uint32_t result = instance->GetFPDTextBrightness(indicator, brightness); @@ -596,8 +598,8 @@ dsError_t dsSetFPTextBrightness(dsFPDTextDisplay_t eIndicator, dsFPDBrightness_t return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDTextDisplay indicator = - static_cast(eIndicator); + Exchange::IDeviceSettingsFPD::FPDTextDisplay indicator = + static_cast(eIndicator); uint32_t result = instance->SetFPDTextBrightness(indicator, static_cast(eBrightness)); return ConvertThunderError(result); @@ -615,8 +617,8 @@ dsError_t dsGetFPColor(dsFPDIndicator_t eIndicator, dsFPDColor_t *pColor) return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDIndicator indicator = - static_cast(eIndicator); + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); uint32_t color = 0; uint32_t result = instance->GetFPDColor(indicator, color); @@ -640,8 +642,8 @@ dsError_t dsSetFPDColor(dsFPDIndicator_t eIndicator, dsFPDColor_t eColor, bool t return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDIndicator indicator = - static_cast(eIndicator); + 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)); @@ -666,10 +668,10 @@ dsError_t dsSetFPState(dsFPDIndicator_t eIndicator, dsFPDState_t state) return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDIndicator indicator = - static_cast(eIndicator); - Exchange::IDeviceSettingsManagerFPD::FPDState fpdState = - static_cast(state); + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); + Exchange::IDeviceSettingsFPD::FPDState fpdState = + static_cast(state); uint32_t result = instance->SetFPDState(indicator, fpdState); return ConvertThunderError(result); @@ -687,10 +689,10 @@ dsError_t dsGetFPState(dsFPDIndicator_t eIndicator, dsFPDState_t* state) return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDIndicator indicator = - static_cast(eIndicator); + Exchange::IDeviceSettingsFPD::FPDIndicator indicator = + static_cast(eIndicator); - Exchange::IDeviceSettingsManagerFPD::FPDState fpdState; + Exchange::IDeviceSettingsFPD::FPDState fpdState; uint32_t result = instance->GetFPDState(indicator, fpdState); if (result == Core::ERROR_NONE) { @@ -712,7 +714,7 @@ dsError_t dsGetFPTimeFormat(dsFPDTimeFormat_t *pTimeFormat) return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDTimeFormat timeFormat; + Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat; uint32_t result = instance->GetFPDTimeFormat(timeFormat); if (result == Core::ERROR_NONE) { @@ -729,8 +731,8 @@ dsError_t dsSetFPTimeFormat(dsFPDTimeFormat_t eTimeFormat) return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDTimeFormat timeFormat = - static_cast(eTimeFormat); + Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat = + static_cast(eTimeFormat); uint32_t result = instance->SetFPDTimeFormat(timeFormat); return ConvertThunderError(result); @@ -743,8 +745,8 @@ dsError_t dsSetFPDMode(dsFPDMode_t eMode) return dsERR_GENERAL; } - Exchange::IDeviceSettingsManagerFPD::FPDMode mode = - static_cast(eMode); + Exchange::IDeviceSettingsFPD::FPDMode mode = + static_cast(eMode); uint32_t result = instance->SetFPDMode(mode); return ConvertThunderError(result); From fdc41051567c374991e65d68683865aed78d75fb Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Mon, 2 Feb 2026 11:27:44 +0000 Subject: [PATCH 03/23] Modified the rpc/cliMakefile with conditionally exclude dsFPD.c when Thunder is enabled. --- rpc/cli/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/cli/Makefile b/rpc/cli/Makefile index 06f2b963..7b2575ee 100644 --- a/rpc/cli/Makefile +++ b/rpc/cli/Makefile @@ -33,8 +33,8 @@ else OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) endif -OBJS := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) -OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) +#OBJS := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) +#OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) INCLUDE := -I$(PWD) \ -I$(PWD)/hal/include \ -I$(PWD)/rpc/include From 034e5db7c0a293816ddf68a64ca891a496d4d8ef Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Wed, 4 Feb 2026 08:18:32 +0000 Subject: [PATCH 04/23] Added export USE_WPE_THUNDER_PLUGIN=y in cov_build.sh --- cov_build.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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" From 3ed996d60b0b55cb584ae4815a4092382976e01e Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Fri, 6 Feb 2026 12:25:33 +0000 Subject: [PATCH 05/23] Added the DSCliLibStandaloneApp.cpp file for validate the FPD functionalities from Standalone application --- Makefile.am | 12 + sample/DSCliLibStandaloneApp.cpp | 762 +++++++++++++++++++++++++++++++ sample/Makefile | 24 +- 3 files changed, 795 insertions(+), 3 deletions(-) create mode 100644 sample/DSCliLibStandaloneApp.cpp diff --git a/Makefile.am b/Makefile.am index 22cfac37..d7945d96 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,3 +38,15 @@ package_ipk: rm -rf $(IPK_GEN_PATH)/data.tar.gz rm -rf $(IPK_GEN_PATH)/control.tar.gz rm -rf $(IPK_GEN_STAGING_DIR) + +# DSApp - Device Settings Test Application +.PHONY: dsapp dsapp-clean + +dsapp: + @echo "Building DSApp..." + $(MAKE) -C sample dsapp + @echo "DSApp executable: $(abs_top_builddir)/DSApp" + +dsapp-clean: + @echo "Cleaning DSApp..." + $(MAKE) -C sample dsapp-clean diff --git a/sample/DSCliLibStandaloneApp.cpp b/sample/DSCliLibStandaloneApp.cpp new file mode 100644 index 00000000..ed512166 --- /dev/null +++ b/sample/DSCliLibStandaloneApp.cpp @@ -0,0 +1,762 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// RDK specific includes - libds.so API +#include "manager.hpp" // Device Settings Manager from libds.so +#include "host.hpp" // Host class from libds.so +#include "frontPanelIndicator.hpp" // FrontPanelIndicator class from libds.so +#include "frontPanelTextDisplay.hpp" // FrontPanelTextDisplay class from libds.so +// #include "libIBus.h" // Uncomment if using IARM Bus +// #include "libIBusDaemon.h" // Uncomment if using IARM Bus daemon + +using namespace std; +using namespace device; // For libds.so classes + +// RDK/Yocto specific constants +#define MAX_DEBUG_LOG_BUFF_SIZE 8192 +#define DEVICE_SETTINGS_ERROR_NONE 0 +#define DEVICE_SETTINGS_ERROR_GENERAL 1 +#define DEVICE_SETTINGS_ERROR_UNAVAILABLE 2 +#define DEVICE_SETTINGS_ERROR_NOT_EXIST 43 + +// Define logging macros +#define LOGI(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__) +#define LOGE(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__) +#define LOGD(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__) + +// Global variables +static pthread_mutex_t gCurlInitMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t gDSAppMutex = PTHREAD_MUTEX_INITIALIZER; +CURLSH* mCurlShared = nullptr; +char* gDebugPrintBuffer = nullptr; + +// RDK specific globals +static bool gAppInitialized = false; +static bool gSignalHandlersSet = false; + +// Function declarations (libds.so functions) +void libds_Initialize(); +void libds_Terminate(); +int setup_signals(); +int breakpad_ExceptionHandler(); +void cleanup_resources(); + +// Menu system functions +void showMainMenu(); +void handleFPDModule(); +void handleAudioPortsModule(); +void handleVideoPortsModule(); +void handleHDMIInModule(); +void handleCompositeInModule(); +int getUserChoice(); +void clearScreen(); + + +int main(int argc, char **argv) +{ + // Initialize syslog for RDK environment + openlog("DSApp", LOG_PID | LOG_CONS, LOG_DAEMON); + + printf("\n=== DeviceSettings Interactive Test Application ===\n"); + printf("Build: %s %s\n", __DATE__, __TIME__); + + // Parse command line arguments + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -h, --help Show this help message\n"); + printf(" --version Show version information\n"); + return 0; + } else if (strcmp(argv[i], "--version") == 0) { + printf("DSApp version 1.0.0 (RDK/Yocto build)\n"); + return 0; + } + } + + // Set up signal handlers early + if (setup_signals() != 0) { + LOGE("Failed to setup signal handlers"); + return -1; + } + + // Allocate debug buffer with error checking + gDebugPrintBuffer = new(std::nothrow) char[MAX_DEBUG_LOG_BUFF_SIZE]; + if (!gDebugPrintBuffer) { + LOGE("Failed to allocate debug buffer of size %d", MAX_DEBUG_LOG_BUFF_SIZE); + return -1; + } + memset(gDebugPrintBuffer, 0, MAX_DEBUG_LOG_BUFF_SIZE); + + // Initialize curl for network operations + CURLcode curl_result = curl_global_init(CURL_GLOBAL_ALL); + if (curl_result != CURLE_OK) { + LOGE("Failed to initialize curl: %s", curl_easy_strerror(curl_result)); + cleanup_resources(); + return -1; + } + + // Initialize breakpad for crash reporting + if (breakpad_ExceptionHandler() != 0) { + LOGE("Failed to initialize exception handler"); + // Continue anyway, not critical + } + + // Initialize libds.so (Device Settings library) + printf("\nInitializing libds.so (Device Settings library)...\n"); + libds_Initialize(); + printf("libds.so initialized successfully!\n"); + + // Set application as initialized + pthread_mutex_lock(&gDSAppMutex); + gAppInitialized = true; + pthread_mutex_unlock(&gDSAppMutex); + + // Main interactive menu loop + int result = 0; + try { + showMainMenu(); + printf("\nApplication completed successfully\n"); + } catch (const std::exception& e) { + LOGE("Application exception: %s", e.what()); + result = -1; + } catch (...) { + LOGE("Unknown application exception"); + result = -1; + } + + // Cleanup before exit + cleanup_resources(); + + printf("\nDevice Settings Application exiting with code %d\n", result); + closelog(); + return result; +} + +// Initialize libds.so Device Settings library +void libds_Initialize() +{ + try { + LOGI("Initializing Device Settings Manager from libds.so..."); + + // Initialize the Device Settings Manager + // This will internally call dsFPInit() and other init functions from libdshalcli.so + device::Manager::Initialize(); + + LOGI("Device Settings Manager initialized successfully"); + } catch (const std::exception& e) { + LOGE("Failed to initialize Device Settings Manager: %s", e.what()); + throw; + } +} + +// Terminate libds.so Device Settings library +void libds_Terminate() +{ + try { + LOGI("Terminating Device Settings Manager from libds.so..."); + device::Manager::DeInitialize(); + LOGI("Device Settings Manager terminated successfully"); + } catch (const std::exception& e) { + LOGE("Error during Device Settings Manager termination: %s", e.what()); + } +} + +// Signal handler for graceful shutdown +static void signal_handler(int signum) { + const char* signal_name = "UNKNOWN"; + switch (signum) { + case SIGTERM: signal_name = "SIGTERM"; break; + case SIGINT: signal_name = "SIGINT"; break; + case SIGHUP: signal_name = "SIGHUP"; break; + case SIGUSR1: signal_name = "SIGUSR1"; break; + case SIGUSR2: signal_name = "SIGUSR2"; break; + } + + syslog(LOG_INFO, "[DSApp] Received signal %s (%d), initiating graceful shutdown", signal_name, signum); + + // Mark application as not initialized to trigger cleanup + pthread_mutex_lock(&gDSAppMutex); + gAppInitialized = false; + pthread_mutex_unlock(&gDSAppMutex); + + // Cleanup and exit + cleanup_resources(); + closelog(); + exit(0); +} + +int setup_signals() { + LOGI("Setting up signal handlers for RDK environment..."); + + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + // Handle common termination signals + if (sigaction(SIGTERM, &sa, nullptr) == -1) { + LOGE("Failed to set SIGTERM handler: %s", strerror(errno)); + return -1; + } + + if (sigaction(SIGINT, &sa, nullptr) == -1) { + LOGE("Failed to set SIGINT handler: %s", strerror(errno)); + return -1; + } + + if (sigaction(SIGHUP, &sa, nullptr) == -1) { + LOGE("Failed to set SIGHUP handler: %s", strerror(errno)); + return -1; + } + + // Handle user-defined signals for debugging + if (sigaction(SIGUSR1, &sa, nullptr) == -1) { + LOGE("Failed to set SIGUSR1 handler: %s", strerror(errno)); + return -1; + } + + if (sigaction(SIGUSR2, &sa, nullptr) == -1) { + LOGE("Failed to set SIGUSR2 handler: %s", strerror(errno)); + return -1; + } + + // Ignore SIGPIPE to handle broken pipe gracefully + signal(SIGPIPE, SIG_IGN); + + gSignalHandlersSet = true; + LOGI("Signal handlers configured successfully"); + return 0; +} + +int breakpad_ExceptionHandler() { + LOGI("Initializing crash reporting for RDK environment..."); + + // Set core dump parameters for RDK debugging + struct rlimit core_limit; + core_limit.rlim_cur = RLIM_INFINITY; + core_limit.rlim_max = RLIM_INFINITY; + + if (setrlimit(RLIMIT_CORE, &core_limit) != 0) { + LOGE("Failed to set core dump limit: %s", strerror(errno)); + } else { + LOGI("Core dump enabled for crash analysis"); + } + + // Set up crash dump directory (typical RDK location) + const char* crash_dir = "/opt/logs/crashes"; + if (access(crash_dir, W_OK) == 0) { + LOGI("Crash dumps will be written to: %s", crash_dir); + } else { + LOGD("Crash directory %s not accessible, using default location", crash_dir); + } + + // TODO: Initialize actual breakpad/crashpad when available + // For now, rely on system core dumps and signal handlers + + LOGI("Crash reporting initialization complete"); + return 0; +} + +// DeviceSettings_Init() is now implemented in device_settings.cpp + +// DeviceSettings_IsOperational() is now implemented in device_settings.cpp + +// DeviceSettings_Connect() is now implemented in device_settings.cpp + +void cleanup_resources() { + LOGI("Cleaning up application resources..."); + + // Mark application as shutting down + pthread_mutex_lock(&gDSAppMutex); + gAppInitialized = false; + pthread_mutex_unlock(&gDSAppMutex); + + // Clean up curl resources + if (mCurlShared) { + curl_share_cleanup(mCurlShared); + mCurlShared = nullptr; + LOGD("CURL shared handle cleaned up"); + } + + curl_global_cleanup(); + LOGD("CURL global cleanup completed"); + + // Free debug buffer + if (gDebugPrintBuffer) { + delete[] gDebugPrintBuffer; + gDebugPrintBuffer = nullptr; + LOGD("Debug buffer freed"); + } + + // Clean up RDK-specific resources + LOGD("Terminating libds.so Device Settings..."); + libds_Terminate(); // Call libds.so cleanup + + // TODO: Add IARM Bus cleanup if used + // IARM_Bus_Disconnect(); + // IARM_Bus_Term(); + + // Destroy mutexes + pthread_mutex_destroy(&gDSAppMutex); + pthread_mutex_destroy(&gCurlInitMutex); + LOGD("Mutexes destroyed"); + + LOGI("Resource cleanup complete"); +} + +// Menu system implementation +void clearScreen() { + printf("\033[2J\033[H"); // ANSI escape codes to clear screen +} + +int getUserChoice() { + int choice; + printf("\nEnter your choice: "); + if (scanf("%d", &choice) != 1) { + // Clear input buffer on invalid input + int c; + while ((c = getchar()) != '\n' && c != EOF); + return -1; + } + return choice; +} + +void showMainMenu() { + int choice; + + do { + clearScreen(); + printf("\n=== DeviceSettings Module Test Menu ===\n"); + printf("1. FPD (Front Panel Display)\n"); + printf("2. Audio Ports\n"); + printf("3. Video Ports\n"); + printf("4. HDMI Input\n"); + printf("5. Composite Input\n"); + printf("0. Exit\n"); + printf("========================================\n"); + + choice = getUserChoice(); + + switch (choice) { + case 1: + handleFPDModule(); + break; + case 2: + handleAudioPortsModule(); + break; + case 3: + handleVideoPortsModule(); + break; + case 4: + handleHDMIInModule(); + break; + case 5: + handleCompositeInModule(); + break; + case 0: + printf("\nExiting...\n"); + break; + default: + printf("\nInvalid choice! Please try again.\n"); + printf("Press Enter to continue..."); + getchar(); // consume newline + getchar(); // wait for Enter + break; + } + } while (choice != 0); +} + +void handleFPDModule() { + int choice; + + do { + clearScreen(); + printf("\n=== FPD (Front Panel Display) Module ===\n"); + printf("Using libds.so → libdshalcli.so → COM-RPC → DeviceSettings plugin\n"); + printf("1. GetFPDBrightness (Power LED)\n"); + printf("2. SetFPDBrightness (Power LED)\n"); + printf("3. GetFPDState (Power LED)\n"); + printf("4. SetFPDState (Power LED)\n"); + printf("5. GetFPDColor (Power LED)\n"); + printf("6. SetFPDColor (Power LED)\n"); + printf("7. Set Blink (Power LED)\n"); + printf("8. Test All Indicators\n"); + printf("0. Back to Main Menu\n"); + printf("=========================================\n"); + + choice = getUserChoice(); + + switch (choice) { + case 1: { + try { + printf("\nCalling libds.so FrontPanelIndicator::getBrightness()...\n"); + + // Get the Power LED indicator from libds.so + FrontPanelIndicator& powerLED = FrontPanelIndicator::getInstance(FrontPanelIndicator::kPower); + + // Get brightness - this will call dsGetFPDBrightness from libdshalcli.so + int brightness = powerLED.getBrightness(); + + printf("SUCCESS: Power LED Brightness: %d\n", brightness); + } catch (const std::exception& e) { + printf("ERROR: %s\n", e.what()); + } + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + case 2: { + int brightness; + printf("\nEnter brightness level (0-100): "); + if (scanf("%d", &brightness) == 1) { + try { + printf("Calling libds.so FrontPanelIndicator::setBrightness(%d)...\n", brightness); + + // Get the Power LED indicator from libds.so + FrontPanelIndicator& powerLED = FrontPanelIndicator::getInstance(FrontPanelIndicator::kPower); + + // Set brightness - this will call dsSetFPDBrightness from libdshalcli.so + powerLED.setBrightness(brightness, true); + + printf("SUCCESS: Power LED brightness set to %d\n", brightness); + } catch (const std::exception& e) { + printf("ERROR: %s\n", e.what()); + } + } else { + printf("Invalid input!\n"); + } + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + case 3: { + try { + printf("\nCalling libds.so FrontPanelIndicator::getState()...\n"); + + // Get the Power LED indicator from libds.so + FrontPanelIndicator& powerLED = FrontPanelIndicator::getInstance(FrontPanelIndicator::kPower); + + // Get state - this will call dsGetFPDState from libdshalcli.so + bool state = powerLED.getState(); + + printf("SUCCESS: Power LED State: %s\n", state ? "ON" : "OFF"); + } catch (const std::exception& e) { + printf("ERROR: %s\n", e.what()); + } + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + case 4: { + int state; + printf("\nEnter FPD state (0=Off, 1=On): "); + if (scanf("%d", &state) == 1) { + try { + printf("Calling libds.so FrontPanelIndicator::setState(%d)...\n", state); + + // Get the Power LED indicator from libds.so + FrontPanelIndicator& powerLED = FrontPanelIndicator::getInstance(FrontPanelIndicator::kPower); + + // Set state - this will call dsSetFPDState from libdshalcli.so + powerLED.setState(state != 0); + + printf("SUCCESS: Power LED state set to %s\n", state ? "ON" : "OFF"); + } catch (const std::exception& e) { + printf("ERROR: %s\n", e.what()); + } + } else { + printf("Invalid input!\n"); + } + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + case 5: { + try { + printf("\nCalling libds.so FrontPanelIndicator::getColor()...\n"); + + // Get the Power LED indicator from libds.so + FrontPanelIndicator& powerLED = FrontPanelIndicator::getInstance(FrontPanelIndicator::kPower); + + // Get color - this will call dsGetFPColor from libdshalcli.so + uint32_t color = powerLED.getColor(); + + printf("SUCCESS: Power LED Color: 0x%08X\n", color); + } catch (const std::exception& e) { + printf("ERROR: %s\n", e.what()); + } + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + case 6: { + unsigned int color; + printf("\nEnter FPD color (hex, e.g., 0xFF0000 for red): 0x"); + if (scanf("%x", &color) == 1) { + try { + printf("Calling libds.so FrontPanelIndicator::setColor(0x%08X)...\n", color); + + // Get the Power LED indicator from libds.so + FrontPanelIndicator& powerLED = FrontPanelIndicator::getInstance(FrontPanelIndicator::kPower); + + // Set color - this will call dsSetFPDColor from libdshalcli.so + powerLED.setColor(color, true); + + printf("SUCCESS: Power LED color set to 0x%08X\n", color); + } catch (const std::exception& e) { + printf("ERROR: %s\n", e.what()); + } + } else { + printf("Invalid input!\n"); + } + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + case 7: { + int interval, iterations; + printf("\nEnter blink interval (ms): "); + if (scanf("%d", &interval) != 1) { + printf("Invalid input!\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + printf("Enter blink iterations: "); + if (scanf("%d", &iterations) == 1) { + try { + printf("Calling libds.so FrontPanelIndicator::setBlink(%d, %d)...\n", interval, iterations); + + // Get the Power LED indicator from libds.so + FrontPanelIndicator& powerLED = FrontPanelIndicator::getInstance(FrontPanelIndicator::kPower); + + // Set blink - this will call dsSetFPBlink from libdshalcli.so + FrontPanelIndicator::Blink blink(interval, iterations); + powerLED.setBlink(blink); + + printf("SUCCESS: Power LED blink set (interval=%d ms, iterations=%d)\n", interval, iterations); + } catch (const std::exception& e) { + printf("ERROR: %s\n", e.what()); + } + } else { + printf("Invalid input!\n"); + } + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + case 8: { + printf("\nTesting all FPD indicators...\n"); + try { + const char* indicatorNames[] = {"Message", "Power", "Record", "Remote", "RFBypass"}; + int indicatorIds[] = { + FrontPanelIndicator::kMessage, + FrontPanelIndicator::kPower, + FrontPanelIndicator::kRecord, + FrontPanelIndicator::kRemote, + FrontPanelIndicator::kRFBypass + }; + + for (int i = 0; i < 5; i++) { + try { + FrontPanelIndicator& indicator = FrontPanelIndicator::getInstance(indicatorIds[i]); + int brightness = indicator.getBrightness(); + bool state = indicator.getState(); + printf(" %s LED: Brightness=%d, State=%s\n", + indicatorNames[i], brightness, state ? "ON" : "OFF"); + } catch (const std::exception& e) { + printf(" %s LED: ERROR - %s\n", indicatorNames[i], e.what()); + } + } + printf("Test completed!\n"); + } catch (const std::exception& e) { + printf("ERROR: %s\n", e.what()); + } + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + case 0: + printf("\nReturning to main menu...\n"); + break; + default: + printf("\nInvalid choice! Please try again.\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + } while (choice != 0); +} + +void handleAudioPortsModule() { + int choice; + + do { + clearScreen(); + printf("\n=== Audio Ports Module ===\n"); + printf("1. DeviceSettings_GetAudioPort\n"); + printf("2. DeviceSettings_SetAudioPort\n"); + printf("3. DeviceSettings_GetAudioFormat\n"); + printf("4. DeviceSettings_SetAudioFormat\n"); + printf("5. DeviceSettings_GetAudioCompression\n"); + printf("6. DeviceSettings_SetAudioCompression\n"); + printf("7. DeviceSettings_GetDialogEnhancement\n"); + printf("8. DeviceSettings_SetDialogEnhancement\n"); + printf("9. DeviceSettings_GetDolbyVolumeMode\n"); + printf("10. DeviceSettings_SetDolbyVolumeMode\n"); + printf("0. Back to Main Menu\n"); + printf("===============================\n"); + + choice = getUserChoice(); + + switch (choice) { + case 1: + printf("\nCalling DeviceSettings_GetAudioPort()...\n"); + // TODO: Add actual function call + printf("Function called successfully!\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + case 2: + printf("\nCalling DeviceSettings_SetAudioPort()...\n"); + // TODO: Add actual function call + printf("Function called successfully!\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + // Add more cases as needed + case 0: + printf("\nReturning to main menu...\n"); + break; + default: + printf("\nInvalid choice! Please try again.\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + } while (choice != 0); +} + +void handleVideoPortsModule() { + int choice; + + do { + clearScreen(); + printf("\n=== Video Ports Module ===\n"); + printf("1. DeviceSettings_GetVideoPort\n"); + printf("2. DeviceSettings_SetVideoPort\n"); + printf("3. DeviceSettings_GetVideoFormat\n"); + printf("4. DeviceSettings_SetVideoFormat\n"); + printf("5. DeviceSettings_GetVideoResolution\n"); + printf("6. DeviceSettings_SetVideoResolution\n"); + printf("7. DeviceSettings_GetVideoFrameRate\n"); + printf("8. DeviceSettings_SetVideoFrameRate\n"); + printf("0. Back to Main Menu\n"); + printf("===============================\n"); + + choice = getUserChoice(); + + switch (choice) { + case 1: + printf("\nCalling DeviceSettings_GetVideoPort()...\n"); + // TODO: Add actual function call + printf("Function called successfully!\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + // Add more cases as needed + case 0: + printf("\nReturning to main menu...\n"); + break; + default: + printf("\nInvalid choice! Please try again.\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + } while (choice != 0); +} + +void handleHDMIInModule() { + int choice; + + do { + clearScreen(); + printf("\n=== HDMI Input Module ===\n"); + printf("1. DeviceSettings_GetHDMIInput\n"); + printf("2. DeviceSettings_SetHDMIInput\n"); + printf("3. DeviceSettings_GetHDMIInputStatus\n"); + printf("4. DeviceSettings_GetHDMIInputSignalStatus\n"); + printf("0. Back to Main Menu\n"); + printf("==========================\n"); + + choice = getUserChoice(); + + switch (choice) { + case 1: + printf("\nCalling DeviceSettings_GetHDMIInput()...\n"); + // TODO: Add actual function call + printf("Function called successfully!\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + // Add more cases as needed + case 0: + printf("\nReturning to main menu...\n"); + break; + default: + printf("\nInvalid choice! Please try again.\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + } while (choice != 0); +} + +void handleCompositeInModule() { + int choice; + + do { + clearScreen(); + printf("\n=== Composite Input Module ===\n"); + printf("1. DeviceSettings_GetCompositeInput\n"); + printf("2. DeviceSettings_SetCompositeInput\n"); + printf("3. DeviceSettings_GetCompositeInputStatus\n"); + printf("0. Back to Main Menu\n"); + printf("===============================\n"); + + choice = getUserChoice(); + + switch (choice) { + case 1: + printf("\nCalling DeviceSettings_GetCompositeInput()...\n"); + // TODO: Add actual function call + printf("Function called successfully!\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + // Add more cases as needed + case 0: + printf("\nReturning to main menu...\n"); + break; + default: + printf("\nInvalid choice! Please try again.\n"); + printf("Press Enter to continue..."); + getchar(); getchar(); + break; + } + } while (choice != 0); +} \ No newline at end of file diff --git a/sample/Makefile b/sample/Makefile index 80b1a2dc..39eadf23 100644 --- a/sample/Makefile +++ b/sample/Makefile @@ -45,12 +45,13 @@ CFLAGS += -g -fPIC -D_REENTRANT -Wall $(INCLUDE) .PHONY: $(OUTPUT) -BINARIES := $(patsubst %.cpp,%,$(wildcard *.cpp)) +# Exclude DSCliLibStandaloneApp.cpp from the automatic build pattern +BINARIES := $(patsubst %.cpp,%,$(filter-out DSCliLibStandaloneApp.cpp,$(wildcard *.cpp))) UNINSTALL := $(patsubst %,$(PWD)/install/bin/%, $(BINARIES)) #all: $(BINARIES) install -all: $(BINARIES) - @echo "Build Finished...." +all: $(BINARIES) dsapp + @echo "Build Finished (including DSApp)...." #frontPanelTest: $(BINARIES): @@ -69,6 +70,23 @@ uninstall: clean: @echo "Cleaning the directory..." @$(RM) $(BINARIES) + @$(RM) DSApp + +# DSApp - Device Settings Test Application +.PHONY: dsapp dsapp-clean + +dsapp: + @if [ -f DSCliLibStandaloneApp.cpp ]; then \ + echo "Building DSApp..."; \ + $(CXX) $(CFLAGS) -std=c++11 DSCliLibStandaloneApp.cpp -o ../DSApp -L$(INSTALL)/lib -lds -ldshalcli -lcurl -lpthread $(LDFLAGS); \ + echo "DSApp built successfully at devicesettings/DSApp"; \ + else \ + echo "DSCliLibStandaloneApp.cpp not found, skipping DSApp build"; \ + fi + +dsapp-clean: + @echo "Cleaning DSApp..." + @$(RM) ../DSApp From d731afd11f87c85fdf8d2e8bd35826c626f45490 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Mon, 9 Feb 2026 02:42:11 +0000 Subject: [PATCH 06/23] Install DSApp standalone app into /usr/bin folder --- sample/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sample/Makefile b/sample/Makefile index 39eadf23..934d3dff 100644 --- a/sample/Makefile +++ b/sample/Makefile @@ -62,6 +62,10 @@ $(BINARIES): install: @echo "Copying the binaries to bin install folder..." @cp $(BINARIES) $(INSTALL)/bin + @if [ -f ../DSApp ]; then \ + echo "Installing DSApp to $(INSTALL)/bin/..."; \ + cp ../DSApp $(INSTALL)/bin/; \ + fi uninstall: @echo "Removing bin from install folder..." From b18f613e6043e7af68bf49ce58cbf9aebf4ea7e3 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Mon, 9 Feb 2026 10:15:38 +0000 Subject: [PATCH 07/23] Install the DSApp in install/bin path --- sample/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sample/Makefile b/sample/Makefile index 934d3dff..9b223800 100644 --- a/sample/Makefile +++ b/sample/Makefile @@ -50,8 +50,8 @@ BINARIES := $(patsubst %.cpp,%,$(filter-out DSCliLibStandaloneApp.cpp,$(wildc UNINSTALL := $(patsubst %,$(PWD)/install/bin/%, $(BINARIES)) #all: $(BINARIES) install -all: $(BINARIES) dsapp - @echo "Build Finished (including DSApp)...." +all: $(BINARIES) dsapp install + @echo "Build Finished and Installed (including DSApp) $(INSTALL)/bin/DSApp" #frontPanelTest: $(BINARIES): @@ -60,6 +60,8 @@ $(BINARIES): # @cp -f $@ $(INSTALL)/bin install: + @echo "INSTALL=$(INSTALL)" + @echo "DSApp install path: $(INSTALL)/bin/DSApp" @echo "Copying the binaries to bin install folder..." @cp $(BINARIES) $(INSTALL)/bin @if [ -f ../DSApp ]; then \ From e6d435d4c9e8338bf859e2efafac88d2239e0e82 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Mon, 9 Feb 2026 11:21:54 +0000 Subject: [PATCH 08/23] Resolved compilation error --- sample/Makefile | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sample/Makefile b/sample/Makefile index 9b223800..cc06a401 100644 --- a/sample/Makefile +++ b/sample/Makefile @@ -50,8 +50,8 @@ BINARIES := $(patsubst %.cpp,%,$(filter-out DSCliLibStandaloneApp.cpp,$(wildc UNINSTALL := $(patsubst %,$(PWD)/install/bin/%, $(BINARIES)) #all: $(BINARIES) install -all: $(BINARIES) dsapp install - @echo "Build Finished and Installed (including DSApp) $(INSTALL)/bin/DSApp" +all: $(BINARIES) dsapp + @echo "Build Finished and Installed (including DSApp) ..." #frontPanelTest: $(BINARIES): @@ -59,14 +59,21 @@ $(BINARIES): $(CXX) $(CFLAGS) $@.cpp -o $@ $(LDFLAGS) # @cp -f $@ $(INSTALL)/bin -install: +install: $(BINARIES) dsapp @echo "INSTALL=$(INSTALL)" @echo "DSApp install path: $(INSTALL)/bin/DSApp" + @mkdir -p $(INSTALL)/bin @echo "Copying the binaries to bin install folder..." - @cp $(BINARIES) $(INSTALL)/bin + @if [ -n "$(BINARIES)" ]; then \ + @cp $(BINARIES) $(INSTALL)/bin + else \ + echo "No sample BINARIES to install"; \ + fi @if [ -f ../DSApp ]; then \ echo "Installing DSApp to $(INSTALL)/bin/..."; \ cp ../DSApp $(INSTALL)/bin/; \ + else \ + echo "DSApp not found at ../DSApp (skipping)"; \ fi uninstall: From 9c65c2d30479aaf1633d829c811e098375a8f316 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Mon, 9 Feb 2026 14:06:11 +0000 Subject: [PATCH 09/23] Commentout libds.so initialization --- sample/DSCliLibStandaloneApp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sample/DSCliLibStandaloneApp.cpp b/sample/DSCliLibStandaloneApp.cpp index ed512166..3a465630 100644 --- a/sample/DSCliLibStandaloneApp.cpp +++ b/sample/DSCliLibStandaloneApp.cpp @@ -115,7 +115,7 @@ int main(int argc, char **argv) // Initialize libds.so (Device Settings library) printf("\nInitializing libds.so (Device Settings library)...\n"); - libds_Initialize(); +// libds_Initialize(); printf("libds.so initialized successfully!\n"); // Set application as initialized @@ -759,4 +759,4 @@ void handleCompositeInModule() { break; } } while (choice != 0); -} \ No newline at end of file +} From ddf584103d9fb09737783ec9397089df9ef8a51a Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Mon, 9 Feb 2026 15:53:12 +0000 Subject: [PATCH 10/23] Commentout libds common init device::Manager::Initialize(); and init FPD only --- sample/DSCliLibStandaloneApp.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sample/DSCliLibStandaloneApp.cpp b/sample/DSCliLibStandaloneApp.cpp index 3a465630..00a699df 100644 --- a/sample/DSCliLibStandaloneApp.cpp +++ b/sample/DSCliLibStandaloneApp.cpp @@ -15,6 +15,7 @@ // RDK specific includes - libds.so API #include "manager.hpp" // Device Settings Manager from libds.so #include "host.hpp" // Host class from libds.so +#include "frontPanelConfig.hpp" // FrontPanelConfig class from libds.so #include "frontPanelIndicator.hpp" // FrontPanelIndicator class from libds.so #include "frontPanelTextDisplay.hpp" // FrontPanelTextDisplay class from libds.so // #include "libIBus.h" // Uncomment if using IARM Bus @@ -44,6 +45,7 @@ char* gDebugPrintBuffer = nullptr; // RDK specific globals static bool gAppInitialized = false; static bool gSignalHandlersSet = false; +static device::List fpIndicators; // Function declarations (libds.so functions) void libds_Initialize(); @@ -115,7 +117,7 @@ int main(int argc, char **argv) // Initialize libds.so (Device Settings library) printf("\nInitializing libds.so (Device Settings library)...\n"); -// libds_Initialize(); + libds_Initialize(); printf("libds.so initialized successfully!\n"); // Set application as initialized @@ -152,7 +154,18 @@ void libds_Initialize() // Initialize the Device Settings Manager // This will internally call dsFPInit() and other init functions from libdshalcli.so - device::Manager::Initialize(); + // device::Manager::Initialize(); As of now FPD only communicate through COM-RPC + + LOGI("Initializing Front Panel from libds.so..."); + LOGI("Front panel init"); + fpIndicators = device::FrontPanelConfig::getInstance().getIndicators(); + + for (size_t i = 0; i < fpIndicators.size(); i++) { + std::string IndicatorName = fpIndicators.at(i).getName(); + LOGI("Initializing Front Panel Indicator: %s", IndicatorName.c_str()); + } + + LOGI("Device Settings FPD initialized successfully"); LOGI("Device Settings Manager initialized successfully"); } catch (const std::exception& e) { From 6a2a9058d79f765396f487134d2efaa3d1753dc3 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Fri, 13 Feb 2026 15:07:46 +0000 Subject: [PATCH 11/23] Modified the dsFPD-com.cpp thunder client code based on latest Master interface changes in Ids.h and IDeviceSettings.h file --- rpc/cli/dsFPD-com.cpp | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp index 53631e05..ec4bcb4f 100644 --- a/rpc/cli/dsFPD-com.cpp +++ b/rpc/cli/dsFPD-com.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include using namespace WPEFramework; @@ -52,11 +53,13 @@ static constexpr const TCHAR callSign[] = _T("org.rdk.DeviceSettings"); /** * @brief DeviceSettingsFPD class manages Thunder COM-RPC connection for FPD + * * Connects to main IDeviceSettings interface and queries for IDeviceSettingsFPD */ -class DeviceSettingsFPD : public RPC::SmartInterfaceType { +class DeviceSettingsFPD : public RPC::SmartInterfaceType { private: - using BaseClass = RPC::SmartInterfaceType; + using BaseClass = RPC::SmartInterfaceType; + Exchange::IDeviceSettings* _deviceSettings; Exchange::IDeviceSettingsFPD* _fpdInterface; static DeviceSettingsFPD* _instance; @@ -67,6 +70,7 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeQueryInterface(); + if (_fpdInterface != nullptr) { + printf("[dsFPD-com] Successfully established COM-RPC connection with DeviceSettings FPD interface\n"); + } else { + fprintf(stderr, "[dsFPD-com] Failed to get IDeviceSettingsFPD interface - plugin implementation may have failed to load\n"); + } } else { - fprintf(stderr, "[dsFPD-com] Failed to get interface - plugin implementation may have failed to load\n"); + fprintf(stderr, "[dsFPD-com] Failed to get IDeviceSettings interface - plugin may not be activated\n"); } } } else { @@ -100,6 +112,10 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeRelease(); _fpdInterface = nullptr; } + if (nullptr != _deviceSettings) { + _deviceSettings->Release(); + _deviceSettings = nullptr; + } } _apiLock.Unlock(); } @@ -156,7 +172,7 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceType Date: Mon, 16 Feb 2026 12:06:32 +0000 Subject: [PATCH 12/23] Added debug prints in dsFPD-com.cpp for FPInit failure --- rpc/cli/dsFPD-com.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp index ec4bcb4f..a35e9a9b 100644 --- a/rpc/cli/dsFPD-com.cpp +++ b/rpc/cli/dsFPD-com.cpp @@ -93,12 +93,12 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeQueryInterface(); if (_fpdInterface != nullptr) { - printf("[dsFPD-com] Successfully established COM-RPC connection with DeviceSettings FPD interface\n"); + printf("[dsFPD-com] Successfully established COM-RPC connection with DeviceSettings FPD interface [%p]\n", _fpdInterface); } else { fprintf(stderr, "[dsFPD-com] Failed to get IDeviceSettingsFPD interface - plugin implementation may have failed to load\n"); } @@ -172,9 +172,12 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeWaitForOperational(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; } From 51180b6d164b809db1b4a384b50cb3e7bc7687de Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Mon, 16 Feb 2026 14:53:17 +0000 Subject: [PATCH 13/23] Added debug prints in GetBrightness and SetBrightness APIs --- rpc/cli/dsFPD-com.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp index a35e9a9b..14c68abb 100644 --- a/rpc/cli/dsFPD-com.cpp +++ b/rpc/cli/dsFPD-com.cpp @@ -278,10 +278,12 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeGetFPDBrightness(indicator, brightness); } _apiLock.Unlock(); + fprintf(stdout, "[dsFPD-com] GetFPDBrightness result for indicator %d: %d\n", indicator, result); return result; } @@ -290,10 +292,12 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeSetFPDBrightness(indicator, brightness, persist); } _apiLock.Unlock(); + fprintf(stdout, "[dsFPD-com] SetFPDBrightness result for indicator %d: %d\n", indicator, result); return result; } @@ -541,17 +545,24 @@ dsError_t dsGetFPBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t *pBri fprintf(stderr, "[dsFPD-com] Invalid parameter: pBrightness is NULL\n"); return dsERR_INVALID_PARAM; } + + fprintf(stdout, "[dsFPD-com] dsGetFPBrightness called for indicator %d\n", eIndicator); DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); if (!instance || !instance->IsOperational()) { + fprintf(stderr, "[dsFPD-com] DeviceSettingsFPD instance not operational\n"); return dsERR_GENERAL; } Exchange::IDeviceSettingsFPD::FPDIndicator indicator = static_cast(eIndicator); + + fprintf(stdout, "[dsFPD-com] Getting FPD brightness for indicator %d\n", indicator); uint32_t brightness = 0; + fprintf(stdout, "[dsFPD-com] Calling GetFPDBrightness for indicator %d\n", indicator); uint32_t result = instance->GetFPDBrightness(indicator, brightness); + fprintf(stdout, "[dsFPD-com] GetFPDBrightness result for indicator %d: %d\n", indicator, result); if (result == Core::ERROR_NONE) { *pBrightness = static_cast(brightness); @@ -577,16 +588,19 @@ dsError_t dsSetFPDBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t eBri fprintf(stderr, "[dsFPD-com] Invalid parameter\n"); return dsERR_INVALID_PARAM; } - + fprintf(stdout, "[dsFPD-com] Setting FPD brightness for indicator %d\n", eIndicator); DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); if (!instance || !instance->IsOperational()) { + fprintf(stderr, "[dsFPD-com] DeviceSettingsFPD instance not operational\n"); return dsERR_GENERAL; } Exchange::IDeviceSettingsFPD::FPDIndicator indicator = static_cast(eIndicator); + fprintf(stdout, "[dsFPD-com] Setting FPD brightness for indicator %d to %d\n", indicator, eBrightness); uint32_t result = instance->SetFPDBrightness(indicator, static_cast(eBrightness), toPersist); + fprintf(stdout, "[dsFPD-com] SetFPDBrightness result for indicator %d: %d\n", indicator, result); return ConvertThunderError(result); } From a816846063325d064334c11d095b490f3e63b40f Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Tue, 17 Feb 2026 07:43:11 +0000 Subject: [PATCH 14/23] Added debug prints to print the Error code --- rpc/cli/dsFPD-com.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp index 14c68abb..51f63761 100644 --- a/rpc/cli/dsFPD-com.cpp +++ b/rpc/cli/dsFPD-com.cpp @@ -283,7 +283,7 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeGetFPDBrightness(indicator, brightness); } _apiLock.Unlock(); - fprintf(stdout, "[dsFPD-com] GetFPDBrightness result for indicator %d: %d\n", indicator, result); + fprintf(stdout, "[dsFPD-com] GetFPDBrightness result for indicator %d: 0x%08X (error code: %u)\n", indicator, static_cast(result), static_cast(result)); return result; } @@ -297,7 +297,7 @@ class DeviceSettingsFPD : public RPC::SmartInterfaceTypeSetFPDBrightness(indicator, brightness, persist); } _apiLock.Unlock(); - fprintf(stdout, "[dsFPD-com] SetFPDBrightness result for indicator %d: %d\n", indicator, result); + fprintf(stdout, "[dsFPD-com] SetFPDBrightness result for indicator %d: 0x%08X (error code: %u)\n", indicator, static_cast(result), static_cast(result)); return result; } From 53aa9f44670a3430b0b3d75302c851cb0333426f Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Wed, 18 Feb 2026 13:39:26 +0000 Subject: [PATCH 15/23] Added dsController-com.cpp and dsController-com.h file Modified the dsFPD-com.cpp file based on dsController-com.cpp and Makefile.am --- ds/include/dsController-com.h | 261 ++++++++++++ rpc/cli/Makefile.am | 2 +- rpc/cli/dsController-com.cpp | 577 ++++++++++++++++++++++++++ rpc/cli/dsController-com.h | 261 ++++++++++++ rpc/cli/dsFPD-com.cpp | 756 +++++++++++++--------------------- 5 files changed, 1389 insertions(+), 468 deletions(-) create mode 100644 ds/include/dsController-com.h create mode 100644 rpc/cli/dsController-com.cpp create mode 100644 rpc/cli/dsController-com.h diff --git a/ds/include/dsController-com.h b/ds/include/dsController-com.h new file mode 100644 index 00000000..40966b22 --- /dev/null +++ b/ds/include/dsController-com.h @@ -0,0 +1,261 @@ +/* + * 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. +*/ + +/** +* @file DeviceSettingsController.h +* @brief Central controller for all DeviceSettings COM-RPC connections +* +* This controller manages a single RPC connection to the Thunder DeviceSettings plugin +* and provides access to all component interfaces (FPD, HDMIIn, Audio, etc.) through +* QueryInterface on the main IDeviceSettings interface. +*/ + +#pragma once + +#ifndef USE_IARM + +#ifndef MODULE_NAME +#define MODULE_NAME DeviceSettings_Client +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace WPEFramework { + +/** + * @brief Component types supported by DeviceSettings + */ +enum class DeviceSettingsComponent : uint8_t { + FPD, + HDMIIn, + Audio, + Display, + VideoPort, + VideoDevice, + Host, + CompositeIn +}; + +/** + * @class DeviceSettingsController + * @brief Singleton controller managing all DeviceSettings component interfaces + * + * This class provides: + * - Single RPC connection to Thunder DeviceSettings plugin + * - Thread-safe access to all component interfaces + * - Automatic lifecycle management + * - Connection status monitoring + * - Reconnection support + */ +class DeviceSettingsController : public RPC::SmartInterfaceType { +private: + using BaseClass = RPC::SmartInterfaceType; + + // Main interface + Exchange::IDeviceSettings* _deviceSettings; + + // Component interfaces obtained via QueryInterface + Exchange::IDeviceSettingsFPD* _fpdInterface; + Exchange::IDeviceSettingsHDMIIn* _hdmiInInterface; + Exchange::IDeviceSettingsAudio* _audioInterface; + Exchange::IDeviceSettingsDisplay* _displayInterface; + Exchange::IDeviceSettingsVideoPort* _videoPortInterface; + Exchange::IDeviceSettingsVideoDevice* _videoDeviceInterface; + Exchange::IDeviceSettingsHost* _hostInterface; + Exchange::IDeviceSettingsCompositeIn* _compositeInInterface; + + // Singleton instance + static DeviceSettingsController* _instance; + static Core::CriticalSection _lock; + + // Connection state + bool _connected; + bool _shutdown; + + // Thunder callsign + static constexpr const TCHAR _callSign[] = _T("org.rdk.DeviceSettings"); + + // Connection retry thread management + static pthread_t _connectionThreadID; + static std::atomic _isConnecting; + static uint32_t _connectionRetryCount; + + #define DS_CONTROLLER_CONNECT_WAIT_TIME_MS 300000 // 300ms in microseconds + + // Helper methods + static void EstablishThunderConnection(); + static void* RetryThunderConnectionThread(void* arg); + static void FetchAndInitializeInterfaces(); + + /** + * @brief Private constructor for singleton pattern + */ + DeviceSettingsController(); + + /** + * @brief Private destructor + */ + ~DeviceSettingsController(); + + /** + * @brief Operational callback from SmartInterfaceType + * @param upAndRunning true if plugin is operational, false otherwise + */ + virtual void Operational(const bool upAndRunning) override; + + /** + * @brief Check if connected (without lock) + */ + inline bool isConnected() const { return _connected; } + + /** + * @brief Query and cache a component interface + * @tparam T Component interface type + * @param interfacePtr Reference to cached interface pointer + * @param componentName Name for logging + * @return true if interface obtained successfully + */ + template + bool QueryComponentInterface(T*& interfacePtr, const char* componentName); + +public: + // Delete copy constructor and assignment operator + DeviceSettingsController(const DeviceSettingsController&) = delete; + DeviceSettingsController& operator=(const DeviceSettingsController&) = delete; + + /** + * @brief Get singleton instance + * @return Pointer to singleton instance + */ + static DeviceSettingsController* GetInstance(); + + /** + * @brief Initialize the controller + * @return Core::ERROR_NONE on success, error code otherwise + */ + static uint32_t Initialize(); + + /** + * @brief Terminate the controller and release all resources + */ + static void Terminate(); + + /** + * @brief Connect to Thunder DeviceSettings plugin + * @return Core::ERROR_NONE on success, error code otherwise + */ + uint32_t Connect(); + + /** + * @brief Disconnect from Thunder DeviceSettings plugin + * @return Core::ERROR_NONE on success, error code otherwise + */ + uint32_t Disconnect(); + + /** + * @brief Check if the main interface is operational + * @return true if operational, false otherwise + */ + bool IsOperational() const; + + /** + * @brief Check if a specific component interface is available + * @param component Component type to check + * @return true if available, false otherwise + */ + bool IsComponentAvailable(DeviceSettingsComponent component) const; + + /** + * @brief Wait for the main interface to become operational + * @param timeoutMs Timeout in milliseconds + * @return true if operational within timeout, false otherwise + */ + bool WaitForOperational(uint32_t timeoutMs = 5000) const; + + /** + * @brief Wait for a specific component to become available + * @param component Component type to wait for + * @param timeoutMs Timeout in milliseconds + * @return true if available within timeout, false otherwise + */ + bool WaitForComponent(DeviceSettingsComponent component, uint32_t timeoutMs = 5000) const; + + /** + * @brief Get FPD component interface + * @return Pointer to IDeviceSettingsFPD interface or nullptr + */ + Exchange::IDeviceSettingsFPD* GetFPDInterface(); + + /** + * @brief Get HDMIIn component interface + * @return Pointer to IDeviceSettingsHDMIIn interface or nullptr + */ + Exchange::IDeviceSettingsHDMIIn* GetHDMIInInterface(); + + /** + * @brief Get Audio component interface + * @return Pointer to IDeviceSettingsAudio interface or nullptr + */ + Exchange::IDeviceSettingsAudio* GetAudioInterface(); + + /** + * @brief Get Display component interface + * @return Pointer to IDeviceSettingsDisplay interface or nullptr + */ + Exchange::IDeviceSettingsDisplay* GetDisplayInterface(); + + /** + * @brief Get VideoPort component interface + * @return Pointer to IDeviceSettingsVideoPort interface or nullptr + */ + Exchange::IDeviceSettingsVideoPort* GetVideoPortInterface(); + + /** + * @brief Get VideoDevice component interface + * @return Pointer to IDeviceSettingsVideoDevice interface or nullptr + */ + Exchange::IDeviceSettingsVideoDevice* GetVideoDeviceInterface(); + + /** + * @brief Get Host component interface + * @return Pointer to IDeviceSettingsHost interface or nullptr + */ + Exchange::IDeviceSettingsHost* GetHostInterface(); + + /** + * @brief Get CompositeIn component interface + * @return Pointer to IDeviceSettingsCompositeIn interface or nullptr + */ + Exchange::IDeviceSettingsCompositeIn* GetCompositeInInterface(); +}; + +} // namespace WPEFramework + +#endif // USE_IARM \ No newline at end of file diff --git a/rpc/cli/Makefile.am b/rpc/cli/Makefile.am index 27f50c1b..a02fb515 100644 --- a/rpc/cli/Makefile.am +++ b/rpc/cli/Makefile.am @@ -31,7 +31,7 @@ libdshalcli_la_CFLAGS = -g -fPIC -D_REENTRANT -Wall # Conditional compilation for Thunder COM-RPC if USE_THUNDER_PLUGIN - FPD_SOURCE = dsFPD-com.cpp + FPD_SOURCE = dsController-com.cpp dsFPD-com.cpp THUNDER_LIBS = -lWPEFrameworkCore -lWPEFrameworkCOM else FPD_SOURCE = dsFPD.c diff --git a/rpc/cli/dsController-com.cpp b/rpc/cli/dsController-com.cpp new file mode 100644 index 00000000..aa8bab13 --- /dev/null +++ b/rpc/cli/dsController-com.cpp @@ -0,0 +1,577 @@ +/* + * 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. +*/ + +/** +* @file dsController-com.cpp +* @brief Implementation of central controller for DeviceSettings COM-RPC connections +*/ + +#ifndef USE_IARM + +#include "DeviceSettingsController.h" +#include +#include +#include + +namespace WPEFramework { + +// Static member initialization +DeviceSettingsController* DeviceSettingsController::_instance = nullptr; +Core::CriticalSection DeviceSettingsController::_lock; + +// Define the static constexpr member +constexpr const TCHAR DeviceSettingsController::_callSign[]; + +pthread_t DeviceSettingsController::_connectionThreadID = 0; +std::atomic DeviceSettingsController::_isConnecting(false); +uint32_t DeviceSettingsController::_connectionRetryCount = 0; + +DeviceSettingsController::DeviceSettingsController() + : BaseClass() + , _deviceSettings(nullptr) + , _fpdInterface(nullptr) + , _hdmiInInterface(nullptr) + , _audioInterface(nullptr) + , _displayInterface(nullptr) + , _videoPortInterface(nullptr) + , _videoDeviceInterface(nullptr) + , _hostInterface(nullptr) + , _compositeInInterface(nullptr) + , _connected(false) + , _shutdown(false) +{ + printf("[DeviceSettingsController] Constructor called\n"); +} + +DeviceSettingsController::~DeviceSettingsController() +{ + printf("[DeviceSettingsController] Destructor called\n"); + _shutdown = true; + + // Release all component interfaces + _lock.Lock(); + + if (_compositeInInterface) { + _compositeInInterface->Release(); + _compositeInInterface = nullptr; + } + if (_hostInterface) { + _hostInterface->Release(); + _hostInterface = nullptr; + } + if (_videoDeviceInterface) { + _videoDeviceInterface->Release(); + _videoDeviceInterface = nullptr; + } + if (_videoPortInterface) { + _videoPortInterface->Release(); + _videoPortInterface = nullptr; + } + if (_displayInterface) { + _displayInterface->Release(); + _displayInterface = nullptr; + } + if (_audioInterface) { + _audioInterface->Release(); + _audioInterface = nullptr; + } + if (_hdmiInInterface) { + _hdmiInInterface->Release(); + _hdmiInInterface = nullptr; + } + if (_fpdInterface) { + _fpdInterface->Release(); + _fpdInterface = nullptr; + } + if (_deviceSettings) { + _deviceSettings->Release(); + _deviceSettings = nullptr; + } + + _lock.Unlock(); + + BaseClass::Close(Core::infinite); +} + +void DeviceSettingsController::Operational(const bool upAndRunning) +{ + _lock.Lock(); + + if (upAndRunning) { + printf("[DeviceSettingsController] Plugin is operational\n"); + + // Get main IDeviceSettings interface + if (nullptr == _deviceSettings) { + _deviceSettings = BaseClass::Interface(); + if (_deviceSettings != nullptr) { + printf("[DeviceSettingsController] Successfully obtained IDeviceSettings interface\n"); + } else { + fprintf(stderr, "[DeviceSettingsController] Failed to get IDeviceSettings interface\n"); + } + } + } else { + printf("[DeviceSettingsController] Plugin is not operational - releasing all interfaces\n"); + + // Release all component interfaces + if (_compositeInInterface) { + _compositeInInterface->Release(); + _compositeInInterface = nullptr; + } + if (_hostInterface) { + _hostInterface->Release(); + _hostInterface = nullptr; + } + if (_videoDeviceInterface) { + _videoDeviceInterface->Release(); + _videoDeviceInterface = nullptr; + } + if (_videoPortInterface) { + _videoPortInterface->Release(); + _videoPortInterface = nullptr; + } + if (_displayInterface) { + _displayInterface->Release(); + _displayInterface = nullptr; + } + if (_audioInterface) { + _audioInterface->Release(); + _audioInterface = nullptr; + } + if (_hdmiInInterface) { + _hdmiInInterface->Release(); + _hdmiInInterface = nullptr; + } + if (_fpdInterface) { + _fpdInterface->Release(); + _fpdInterface = nullptr; + } + if (_deviceSettings) { + _deviceSettings->Release(); + _deviceSettings = nullptr; + } + } + + _lock.Unlock(); +} + +template +bool DeviceSettingsController::QueryComponentInterface(T*& interfacePtr, const char* componentName) +{ + if (interfacePtr != nullptr) { + // Already cached + return true; + } + + if (_deviceSettings == nullptr) { + fprintf(stderr, "[DeviceSettingsController] Cannot query %s - main interface not available\n", componentName); + return false; + } + + interfacePtr = _deviceSettings->QueryInterface(); + if (interfacePtr != nullptr) { + printf("[DeviceSettingsController] Successfully obtained %s interface\n", componentName); + return true; + } else { + fprintf(stderr, "[DeviceSettingsController] Failed to get %s interface\n", componentName); + return false; + } +} + +DeviceSettingsController* DeviceSettingsController::GetInstance() +{ + return _instance; +} + +uint32_t DeviceSettingsController::Initialize() +{ + printf("[DeviceSettingsController] Initialize entry\n"); + _lock.Lock(); + + if (_instance != nullptr) { + printf("[DeviceSettingsController] Already initialized\n"); + _lock.Unlock(); + return Core::ERROR_NONE; + } + + // Create the controller instance (NOT connected yet) + _instance = new DeviceSettingsController(); + + if (_instance == nullptr) { + fprintf(stderr, "[DeviceSettingsController] Failed to create instance\n"); + _lock.Unlock(); + return Core::ERROR_GENERAL; + } + + _lock.Unlock(); + + // Start Thunder connection retry thread (non-blocking, like dsMgrPwrCtrlEstablishConnection) + printf("[DeviceSettingsController] Starting Thunder COM-RPC connection thread\n"); + EstablishThunderConnection(); + + return Core::ERROR_NONE; +} + +void DeviceSettingsController::Terminate() +{ + printf("[DeviceSettingsController] Terminate entry\n"); + + _lock.Lock(); + + if (_instance != nullptr) { + delete _instance; + _instance = nullptr; + printf("[DeviceSettingsController] Instance terminated\n"); + } + + _lock.Unlock(); + + // Note: Connection retry thread is detached and will exit on its own + // when it successfully connects or if the process is shutting down +} + +void DeviceSettingsController::EstablishThunderConnection() +{ + printf("[DeviceSettingsController] Entering EstablishThunderConnection\n"); + + if (_isConnecting.load()) { + printf("[DeviceSettingsController] Connection already in progress\n"); + return; + } + + _isConnecting = true; + _connectionRetryCount = 0; + + // Create detached thread for retry logic (matches dsMgrPwrCtrlEstablishConnection pattern) + if (pthread_create(&_connectionThreadID, NULL, RetryThunderConnectionThread, NULL) == 0) { + if (pthread_detach(_connectionThreadID) != 0) { + fprintf(stderr, "[DeviceSettingsController] Thread detach failed\n"); + _isConnecting = false; + } + else { + printf("[DeviceSettingsController] Connection retry thread started successfully\n"); + } + } + else { + fprintf(stderr, "[DeviceSettingsController] Thread creation failed\n"); + _isConnecting = false; + } +} + +void* DeviceSettingsController::RetryThunderConnectionThread(void* arg) +{ + printf("[DeviceSettingsController] RetryThunderConnectionThread entry\n"); + + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (controller == nullptr) { + fprintf(stderr, "[DeviceSettingsController] Controller instance is null\n"); + _isConnecting = false; + return arg; + } + + // Infinite retry loop (matches dsMgrPwrRetryEstablishConnThread pattern) + while (1) + { + _connectionRetryCount++; + + uint32_t result = controller->Connect(); + + if (result == Core::ERROR_NONE) { + printf("[DeviceSettingsController] Thunder connection SUCCESS after %u attempts\n", + _connectionRetryCount); + + // Post-connection initialization + FetchAndInitializeInterfaces(); + + _isConnecting = false; + printf("[DeviceSettingsController] RetryThunderConnectionThread completed successfully\n"); + break; + } + else { + if (_connectionRetryCount % 10 == 0) { // Log every 3 seconds + printf("[DeviceSettingsController] Connection attempt %u failed, retrying...\n", + _connectionRetryCount); + } + + // 300ms wait before retry (matches DSMGR_PWR_CNTRL_CONNECT_WAIT_TIME_MS) + usleep(DS_CONTROLLER_CONNECT_WAIT_TIME_MS); + } + } + + printf("[DeviceSettingsController] RetryThunderConnectionThread exit\n"); + return arg; +} + +void DeviceSettingsController::FetchAndInitializeInterfaces() +{ + printf("[DeviceSettingsController] FetchAndInitializeInterfaces entry\n"); + + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (controller == nullptr || !controller->IsOperational()) { + fprintf(stderr, "[DeviceSettingsController] Controller not operational\n"); + return; + } + + // Pre-query all component interfaces to verify availability + uint32_t loadedCount = 0; + + // Query each interface (lazy loading will cache them) + if (controller->GetFPDInterface() != nullptr) { + printf("[DeviceSettingsController] FPD interface available\n"); + loadedCount++; + } + + if (controller->GetAudioInterface() != nullptr) { + printf("[DeviceSettingsController] Audio interface available\n"); + loadedCount++; + } + + if (controller->GetDisplayInterface() != nullptr) { + printf("[DeviceSettingsController] Display interface available\n"); + loadedCount++; + } + + if (controller->GetVideoDeviceInterface() != nullptr) { + printf("[DeviceSettingsController] VideoDevice interface available\n"); + loadedCount++; + } + + if (controller->GetVideoPortInterface() != nullptr) { + printf("[DeviceSettingsController] VideoPort interface available\n"); + loadedCount++; + } + + if (controller->GetHostInterface() != nullptr) { + printf("[DeviceSettingsController] Host interface available\n"); + loadedCount++; + } + + if (controller->GetHDMIInInterface() != nullptr) { + printf("[DeviceSettingsController] HDMIIn interface available\n"); + loadedCount++; + } + + if (controller->GetCompositeInInterface() != nullptr) { + printf("[DeviceSettingsController] CompositeIn interface available\n"); + loadedCount++; + } + + printf("[DeviceSettingsController] Interface initialization complete: %u interfaces loaded\n", + loadedCount); +} + +uint32_t DeviceSettingsController::Connect() +{ + uint32_t status = Core::ERROR_NONE; + + _lock.Lock(); + + if (!isConnected()) { + printf("[DeviceSettingsController] 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("[DeviceSettingsController] Successfully opened RPC connection to Thunder\n"); + } else { + fprintf(stderr, "[DeviceSettingsController] Failed to open RPC connection, error: %u. Is Thunder running?\n", res); + status = Core::ERROR_UNAVAILABLE; + } + } + + if (nullptr == _deviceSettings) { + status = Core::ERROR_NOT_EXIST; + printf("[DeviceSettingsController] DeviceSettings plugin not yet operational\n"); + } + + _lock.Unlock(); + + return status; +} + +uint32_t DeviceSettingsController::Disconnect() +{ + uint32_t status = Core::ERROR_GENERAL; + bool close = false; + + _lock.Lock(); + + if (isConnected()) { + close = true; + _connected = false; + } + + _lock.Unlock(); + + if (close) { + status = BaseClass::Close(Core::infinite); + } + + return status; +} + +bool DeviceSettingsController::IsOperational() const +{ + _lock.Lock(); + bool result = (isConnected() && (_deviceSettings != nullptr)); + _lock.Unlock(); + return result; +} + +bool DeviceSettingsController::IsComponentAvailable(DeviceSettingsComponent component) const +{ + _lock.Lock(); + + bool available = false; + switch (component) { + case DeviceSettingsComponent::FPD: + available = (_fpdInterface != nullptr); + break; + case DeviceSettingsComponent::HDMIIn: + available = (_hdmiInInterface != nullptr); + break; + case DeviceSettingsComponent::Audio: + available = (_audioInterface != nullptr); + break; + case DeviceSettingsComponent::Display: + available = (_displayInterface != nullptr); + break; + case DeviceSettingsComponent::VideoPort: + available = (_videoPortInterface != nullptr); + break; + case DeviceSettingsComponent::VideoDevice: + available = (_videoDeviceInterface != nullptr); + break; + case DeviceSettingsComponent::Host: + available = (_hostInterface != nullptr); + break; + case DeviceSettingsComponent::CompositeIn: + available = (_compositeInInterface != nullptr); + break; + } + + _lock.Unlock(); + return available; +} + +bool DeviceSettingsController::WaitForOperational(uint32_t timeoutMs) 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; +} + +bool DeviceSettingsController::WaitForComponent(DeviceSettingsComponent component, uint32_t timeoutMs) const +{ + const uint32_t pollIntervalMs = 100; + uint32_t elapsedMs = 0; + + while (elapsedMs < timeoutMs) { + if (IsComponentAvailable(component)) { + return true; + } + std::this_thread::sleep_for(std::chrono::milliseconds(pollIntervalMs)); + elapsedMs += pollIntervalMs; + } + + return false; +} + +Exchange::IDeviceSettingsFPD* DeviceSettingsController::GetFPDInterface() +{ + _lock.Lock(); + QueryComponentInterface(_fpdInterface, "IDeviceSettingsFPD"); + Exchange::IDeviceSettingsFPD* result = _fpdInterface; + _lock.Unlock(); + return result; +} + +Exchange::IDeviceSettingsHDMIIn* DeviceSettingsController::GetHDMIInInterface() +{ + _lock.Lock(); + QueryComponentInterface(_hdmiInInterface, "IDeviceSettingsHDMIIn"); + Exchange::IDeviceSettingsHDMIIn* result = _hdmiInInterface; + _lock.Unlock(); + return result; +} + +Exchange::IDeviceSettingsAudio* DeviceSettingsController::GetAudioInterface() +{ + _lock.Lock(); + QueryComponentInterface(_audioInterface, "IDeviceSettingsAudio"); + Exchange::IDeviceSettingsAudio* result = _audioInterface; + _lock.Unlock(); + return result; +} + +Exchange::IDeviceSettingsDisplay* DeviceSettingsController::GetDisplayInterface() +{ + _lock.Lock(); + QueryComponentInterface(_displayInterface, "IDeviceSettingsDisplay"); + Exchange::IDeviceSettingsDisplay* result = _displayInterface; + _lock.Unlock(); + return result; +} + +Exchange::IDeviceSettingsVideoPort* DeviceSettingsController::GetVideoPortInterface() +{ + _lock.Lock(); + QueryComponentInterface(_videoPortInterface, "IDeviceSettingsVideoPort"); + Exchange::IDeviceSettingsVideoPort* result = _videoPortInterface; + _lock.Unlock(); + return result; +} + +Exchange::IDeviceSettingsVideoDevice* DeviceSettingsController::GetVideoDeviceInterface() +{ + _lock.Lock(); + QueryComponentInterface(_videoDeviceInterface, "IDeviceSettingsVideoDevice"); + Exchange::IDeviceSettingsVideoDevice* result = _videoDeviceInterface; + _lock.Unlock(); + return result; +} + +Exchange::IDeviceSettingsHost* DeviceSettingsController::GetHostInterface() +{ + _lock.Lock(); + QueryComponentInterface(_hostInterface, "IDeviceSettingsHost"); + Exchange::IDeviceSettingsHost* result = _hostInterface; + _lock.Unlock(); + return result; +} + +Exchange::IDeviceSettingsCompositeIn* DeviceSettingsController::GetCompositeInInterface() +{ + _lock.Lock(); + QueryComponentInterface(_compositeInInterface, "IDeviceSettingsCompositeIn"); + Exchange::IDeviceSettingsCompositeIn* result = _compositeInInterface; + _lock.Unlock(); + return result; +} + +} // namespace WPEFramework + +#endif // USE_IARM \ No newline at end of file diff --git a/rpc/cli/dsController-com.h b/rpc/cli/dsController-com.h new file mode 100644 index 00000000..40966b22 --- /dev/null +++ b/rpc/cli/dsController-com.h @@ -0,0 +1,261 @@ +/* + * 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. +*/ + +/** +* @file DeviceSettingsController.h +* @brief Central controller for all DeviceSettings COM-RPC connections +* +* This controller manages a single RPC connection to the Thunder DeviceSettings plugin +* and provides access to all component interfaces (FPD, HDMIIn, Audio, etc.) through +* QueryInterface on the main IDeviceSettings interface. +*/ + +#pragma once + +#ifndef USE_IARM + +#ifndef MODULE_NAME +#define MODULE_NAME DeviceSettings_Client +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace WPEFramework { + +/** + * @brief Component types supported by DeviceSettings + */ +enum class DeviceSettingsComponent : uint8_t { + FPD, + HDMIIn, + Audio, + Display, + VideoPort, + VideoDevice, + Host, + CompositeIn +}; + +/** + * @class DeviceSettingsController + * @brief Singleton controller managing all DeviceSettings component interfaces + * + * This class provides: + * - Single RPC connection to Thunder DeviceSettings plugin + * - Thread-safe access to all component interfaces + * - Automatic lifecycle management + * - Connection status monitoring + * - Reconnection support + */ +class DeviceSettingsController : public RPC::SmartInterfaceType { +private: + using BaseClass = RPC::SmartInterfaceType; + + // Main interface + Exchange::IDeviceSettings* _deviceSettings; + + // Component interfaces obtained via QueryInterface + Exchange::IDeviceSettingsFPD* _fpdInterface; + Exchange::IDeviceSettingsHDMIIn* _hdmiInInterface; + Exchange::IDeviceSettingsAudio* _audioInterface; + Exchange::IDeviceSettingsDisplay* _displayInterface; + Exchange::IDeviceSettingsVideoPort* _videoPortInterface; + Exchange::IDeviceSettingsVideoDevice* _videoDeviceInterface; + Exchange::IDeviceSettingsHost* _hostInterface; + Exchange::IDeviceSettingsCompositeIn* _compositeInInterface; + + // Singleton instance + static DeviceSettingsController* _instance; + static Core::CriticalSection _lock; + + // Connection state + bool _connected; + bool _shutdown; + + // Thunder callsign + static constexpr const TCHAR _callSign[] = _T("org.rdk.DeviceSettings"); + + // Connection retry thread management + static pthread_t _connectionThreadID; + static std::atomic _isConnecting; + static uint32_t _connectionRetryCount; + + #define DS_CONTROLLER_CONNECT_WAIT_TIME_MS 300000 // 300ms in microseconds + + // Helper methods + static void EstablishThunderConnection(); + static void* RetryThunderConnectionThread(void* arg); + static void FetchAndInitializeInterfaces(); + + /** + * @brief Private constructor for singleton pattern + */ + DeviceSettingsController(); + + /** + * @brief Private destructor + */ + ~DeviceSettingsController(); + + /** + * @brief Operational callback from SmartInterfaceType + * @param upAndRunning true if plugin is operational, false otherwise + */ + virtual void Operational(const bool upAndRunning) override; + + /** + * @brief Check if connected (without lock) + */ + inline bool isConnected() const { return _connected; } + + /** + * @brief Query and cache a component interface + * @tparam T Component interface type + * @param interfacePtr Reference to cached interface pointer + * @param componentName Name for logging + * @return true if interface obtained successfully + */ + template + bool QueryComponentInterface(T*& interfacePtr, const char* componentName); + +public: + // Delete copy constructor and assignment operator + DeviceSettingsController(const DeviceSettingsController&) = delete; + DeviceSettingsController& operator=(const DeviceSettingsController&) = delete; + + /** + * @brief Get singleton instance + * @return Pointer to singleton instance + */ + static DeviceSettingsController* GetInstance(); + + /** + * @brief Initialize the controller + * @return Core::ERROR_NONE on success, error code otherwise + */ + static uint32_t Initialize(); + + /** + * @brief Terminate the controller and release all resources + */ + static void Terminate(); + + /** + * @brief Connect to Thunder DeviceSettings plugin + * @return Core::ERROR_NONE on success, error code otherwise + */ + uint32_t Connect(); + + /** + * @brief Disconnect from Thunder DeviceSettings plugin + * @return Core::ERROR_NONE on success, error code otherwise + */ + uint32_t Disconnect(); + + /** + * @brief Check if the main interface is operational + * @return true if operational, false otherwise + */ + bool IsOperational() const; + + /** + * @brief Check if a specific component interface is available + * @param component Component type to check + * @return true if available, false otherwise + */ + bool IsComponentAvailable(DeviceSettingsComponent component) const; + + /** + * @brief Wait for the main interface to become operational + * @param timeoutMs Timeout in milliseconds + * @return true if operational within timeout, false otherwise + */ + bool WaitForOperational(uint32_t timeoutMs = 5000) const; + + /** + * @brief Wait for a specific component to become available + * @param component Component type to wait for + * @param timeoutMs Timeout in milliseconds + * @return true if available within timeout, false otherwise + */ + bool WaitForComponent(DeviceSettingsComponent component, uint32_t timeoutMs = 5000) const; + + /** + * @brief Get FPD component interface + * @return Pointer to IDeviceSettingsFPD interface or nullptr + */ + Exchange::IDeviceSettingsFPD* GetFPDInterface(); + + /** + * @brief Get HDMIIn component interface + * @return Pointer to IDeviceSettingsHDMIIn interface or nullptr + */ + Exchange::IDeviceSettingsHDMIIn* GetHDMIInInterface(); + + /** + * @brief Get Audio component interface + * @return Pointer to IDeviceSettingsAudio interface or nullptr + */ + Exchange::IDeviceSettingsAudio* GetAudioInterface(); + + /** + * @brief Get Display component interface + * @return Pointer to IDeviceSettingsDisplay interface or nullptr + */ + Exchange::IDeviceSettingsDisplay* GetDisplayInterface(); + + /** + * @brief Get VideoPort component interface + * @return Pointer to IDeviceSettingsVideoPort interface or nullptr + */ + Exchange::IDeviceSettingsVideoPort* GetVideoPortInterface(); + + /** + * @brief Get VideoDevice component interface + * @return Pointer to IDeviceSettingsVideoDevice interface or nullptr + */ + Exchange::IDeviceSettingsVideoDevice* GetVideoDeviceInterface(); + + /** + * @brief Get Host component interface + * @return Pointer to IDeviceSettingsHost interface or nullptr + */ + Exchange::IDeviceSettingsHost* GetHostInterface(); + + /** + * @brief Get CompositeIn component interface + * @return Pointer to IDeviceSettingsCompositeIn interface or nullptr + */ + Exchange::IDeviceSettingsCompositeIn* GetCompositeInInterface(); +}; + +} // namespace WPEFramework + +#endif // USE_IARM \ No newline at end of file diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp index 51f63761..422f334f 100644 --- a/rpc/cli/dsFPD-com.cpp +++ b/rpc/cli/dsFPD-com.cpp @@ -24,7 +24,7 @@ * @{ **/ -#ifdef USE_WPE_THUNDER_PLUGIN +#ifndef USE_IARM #include #include @@ -34,393 +34,12 @@ #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 -#include +#include "DeviceSettingsController.h" 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 - * * Connects to main IDeviceSettings interface and queries for IDeviceSettingsFPD - */ -class DeviceSettingsFPD : public RPC::SmartInterfaceType { -private: - using BaseClass = RPC::SmartInterfaceType; - - Exchange::IDeviceSettings* _deviceSettings; - Exchange::IDeviceSettingsFPD* _fpdInterface; - - static DeviceSettingsFPD* _instance; - static Core::CriticalSection _apiLock; - - bool _connected; - bool _shutdown; - - DeviceSettingsFPD() - : BaseClass() - , _deviceSettings(nullptr) - , _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 == _deviceSettings) { - _deviceSettings = BaseClass::Interface(); - if (_deviceSettings != nullptr) { - printf("[dsFPD-com] Successfully obtained IDeviceSettings interface [%p] \n", _deviceSettings); - - // Now QueryInterface to get IDeviceSettingsFPD from the aggregated implementation - _fpdInterface = _deviceSettings->QueryInterface(); - if (_fpdInterface != nullptr) { - printf("[dsFPD-com] Successfully established COM-RPC connection with DeviceSettings FPD interface [%p]\n", _fpdInterface); - } else { - fprintf(stderr, "[dsFPD-com] Failed to get IDeviceSettingsFPD interface - plugin implementation may have failed to load\n"); - } - } else { - fprintf(stderr, "[dsFPD-com] Failed to get IDeviceSettings interface - plugin may not be activated\n"); - } - } - } else { - // DeviceSettings is Deactivated || Communicator closed - if (nullptr != _fpdInterface) { - _fpdInterface->Release(); - _fpdInterface = nullptr; - } - if (nullptr != _deviceSettings) { - _deviceSettings->Release(); - _deviceSettings = 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 == _deviceSettings) { - status = Core::ERROR_NOT_EXIST; - printf("[dsFPD-com] DeviceSettings plugin not yet operational\n"); - if (nullptr == _fpdInterface) { - fprintf(stderr, "[dsFPD-com] IDeviceSettingsFPD interface not available - plugin may have failed to load\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) { - printf("[dsFPD-com] Initializing DeviceSettingsFPD instance\n"); - _instance = new DeviceSettingsFPD(); - printf("[dsFPD-com] DeviceSettingsFPD instance initialized [%p]\n", _instance); - } - _apiLock.Unlock(); - } - - static void Term() - { - _apiLock.Lock(); - if (nullptr != _instance) { - printf("[dsFPD-com] Terminating DeviceSettingsFPD instance\n"); - delete _instance; - _instance = nullptr; - } - _apiLock.Unlock(); - } - - static DeviceSettingsFPD* Instance() - { - printf("[dsFPD-com] Returning DeviceSettingsFPD instance [%p]\n", _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(); - fprintf(stdout, "[dsFPD-com] Getting FPD brightness for indicator %d\n", indicator); - if (_fpdInterface) { - result = _fpdInterface->GetFPDBrightness(indicator, brightness); - } - _apiLock.Unlock(); - fprintf(stdout, "[dsFPD-com] GetFPDBrightness result for indicator %d: 0x%08X (error code: %u)\n", indicator, static_cast(result), static_cast(result)); - 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(); - fprintf(stdout, "[dsFPD-com] Setting FPD brightness for indicator %d to %d\n", indicator, brightness); - if (_fpdInterface) { - result = _fpdInterface->SetFPDBrightness(indicator, brightness, persist); - } - _apiLock.Unlock(); - fprintf(stdout, "[dsFPD-com] SetFPDBrightness result for indicator %d: 0x%08X (error code: %u)\n", indicator, static_cast(result), static_cast(result)); - 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; +// Thread safety lock for FPD interface calls +static Core::CriticalSection _fpdLock; /** * @brief Convert Thunder error code to dsError_t @@ -438,6 +57,158 @@ static dsError_t ConvertThunderError(uint32_t thunderError) } } +/** + * @brief Thread-safe wrapper functions for FPD interface calls + */ +namespace FPDWrapper { + +inline uint32_t SetFPDTime(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat, + uint32_t hour, uint32_t minutes) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->SetFPDTime(timeFormat, hour, minutes); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t SetFPDScroll(Exchange::IDeviceSettingsFPD* fpdInterface, + uint32_t scrollHoldOnDur, uint32_t horzScrollIterations, + uint32_t vertScrollIterations) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->SetFPDScroll(scrollHoldOnDur, horzScrollIterations, vertScrollIterations); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t SetFPDBlink(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + uint32_t blinkDuration, uint32_t blinkIterations) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->SetFPDBlink(indicator, blinkDuration, blinkIterations); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t GetFPDBrightness(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + uint32_t& brightness) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->GetFPDBrightness(indicator, brightness); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t SetFPDBrightness(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + uint32_t brightness, bool persist) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->SetFPDBrightness(indicator, brightness, persist); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t GetFPDTextBrightness(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDTextDisplay indicator, + uint32_t& brightness) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->GetFPDTextBrightness(indicator, brightness); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t SetFPDTextBrightness(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDTextDisplay indicator, + uint32_t brightness) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->SetFPDTextBrightness(indicator, brightness); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t GetFPDColor(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + uint32_t& color) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->GetFPDColor(indicator, color); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t SetFPDColor(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + uint32_t color) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->SetFPDColor(indicator, color); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t EnableFPDClockDisplay(Exchange::IDeviceSettingsFPD* fpdInterface, bool enable) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->EnableFPDClockDisplay(enable); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t SetFPDState(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + Exchange::IDeviceSettingsFPD::FPDState state) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->SetFPDState(indicator, state); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t GetFPDState(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDIndicator indicator, + Exchange::IDeviceSettingsFPD::FPDState& state) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->GetFPDState(indicator, state); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t GetFPDTimeFormat(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDTimeFormat& timeFormat) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->GetFPDTimeFormat(timeFormat); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t SetFPDTimeFormat(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->SetFPDTimeFormat(timeFormat); + _fpdLock.Unlock(); + return result; +} + +inline uint32_t SetFPDMode(Exchange::IDeviceSettingsFPD* fpdInterface, + Exchange::IDeviceSettingsFPD::FPDMode mode) +{ + _fpdLock.Lock(); + uint32_t result = fpdInterface->SetFPDMode(mode); + _fpdLock.Unlock(); + return result; +} + +} // namespace FPDWrapper + // C API implementations using Thunder COM-RPC extern "C" { @@ -450,39 +221,27 @@ 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(); - printf("[dsFPD-com] DeviceSettingsFPD instance initialized [%p]\n", instance); - } - - if (!instance) { - fprintf(stderr, "[dsFPD-com] Failed to create DeviceSettingsFPD instance\n"); + //DeviceSettingsController is initialized by manager.cpp + // Just verify we have FPD interface access + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + fprintf(stderr, "[dsFPD-com] DeviceSettingsController not initialized\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"); + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { + fprintf(stderr, "[dsFPD-com] FPD interface not available\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(); - + // DeviceSettingsController cleanup handled by manager.cpp + // No component-specific cleanup needed return dsERR_NONE; } @@ -500,42 +259,55 @@ dsError_t dsSetFPText(const char* pszChars) dsError_t dsSetFPTime(dsFPDTimeFormat_t eTime, const unsigned int uHour, const unsigned int uMinutes) { - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { 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); + uint32_t result = FPDWrapper::SetFPDTime(fpdInterface, 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()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { return dsERR_GENERAL; } - uint32_t result = instance->SetFPDScroll(nScrollHoldOnDur, nHorzScrollIterations, nVertScrollIterations); + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { + return dsERR_GENERAL; + } + + uint32_t result = FPDWrapper::SetFPDScroll(fpdInterface, 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()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } Exchange::IDeviceSettingsFPD::FPDIndicator indicator = static_cast(eIndicator); - uint32_t result = instance->SetFPDBlink(indicator, nBlinkDuration, nBlinkIterations); + uint32_t result = FPDWrapper::SetFPDBlink(fpdInterface, indicator, nBlinkDuration, nBlinkIterations); return ConvertThunderError(result); } @@ -545,24 +317,22 @@ dsError_t dsGetFPBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t *pBri fprintf(stderr, "[dsFPD-com] Invalid parameter: pBrightness is NULL\n"); return dsERR_INVALID_PARAM; } - - fprintf(stdout, "[dsFPD-com] dsGetFPBrightness called for indicator %d\n", eIndicator); - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { - fprintf(stderr, "[dsFPD-com] DeviceSettingsFPD instance not operational\n"); + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } Exchange::IDeviceSettingsFPD::FPDIndicator indicator = static_cast(eIndicator); - - fprintf(stdout, "[dsFPD-com] Getting FPD brightness for indicator %d\n", indicator); uint32_t brightness = 0; - fprintf(stdout, "[dsFPD-com] Calling GetFPDBrightness for indicator %d\n", indicator); - uint32_t result = instance->GetFPDBrightness(indicator, brightness); - fprintf(stdout, "[dsFPD-com] GetFPDBrightness result for indicator %d: %d\n", indicator, result); + uint32_t result = FPDWrapper::GetFPDBrightness(fpdInterface, indicator, brightness); if (result == Core::ERROR_NONE) { *pBrightness = static_cast(brightness); @@ -588,19 +358,21 @@ dsError_t dsSetFPDBrightness(dsFPDIndicator_t eIndicator, dsFPDBrightness_t eBri fprintf(stderr, "[dsFPD-com] Invalid parameter\n"); return dsERR_INVALID_PARAM; } - fprintf(stdout, "[dsFPD-com] Setting FPD brightness for indicator %d\n", eIndicator); - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { - fprintf(stderr, "[dsFPD-com] DeviceSettingsFPD instance not operational\n"); + + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } Exchange::IDeviceSettingsFPD::FPDIndicator indicator = static_cast(eIndicator); - fprintf(stdout, "[dsFPD-com] Setting FPD brightness for indicator %d to %d\n", indicator, eBrightness); - uint32_t result = instance->SetFPDBrightness(indicator, static_cast(eBrightness), toPersist); - fprintf(stdout, "[dsFPD-com] SetFPDBrightness result for indicator %d: %d\n", indicator, result); + uint32_t result = FPDWrapper::SetFPDBrightness(fpdInterface, indicator, static_cast(eBrightness), toPersist); return ConvertThunderError(result); } @@ -611,8 +383,13 @@ dsError_t dsGetFPTextBrightness(dsFPDTextDisplay_t eIndicator, dsFPDBrightness_t return dsERR_INVALID_PARAM; } - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } @@ -620,7 +397,7 @@ dsError_t dsGetFPTextBrightness(dsFPDTextDisplay_t eIndicator, dsFPDBrightness_t static_cast(eIndicator); uint32_t brightness = 0; - uint32_t result = instance->GetFPDTextBrightness(indicator, brightness); + uint32_t result = FPDWrapper::GetFPDTextBrightness(fpdInterface, indicator, brightness); if (result == Core::ERROR_NONE) { *pBrightness = static_cast(brightness); @@ -631,15 +408,20 @@ dsError_t dsGetFPTextBrightness(dsFPDTextDisplay_t eIndicator, dsFPDBrightness_t dsError_t dsSetFPTextBrightness(dsFPDTextDisplay_t eIndicator, dsFPDBrightness_t eBrightness) { - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } Exchange::IDeviceSettingsFPD::FPDTextDisplay indicator = static_cast(eIndicator); - uint32_t result = instance->SetFPDTextBrightness(indicator, static_cast(eBrightness)); + uint32_t result = FPDWrapper::SetFPDTextBrightness(fpdInterface, indicator, static_cast(eBrightness)); return ConvertThunderError(result); } @@ -650,8 +432,13 @@ dsError_t dsGetFPColor(dsFPDIndicator_t eIndicator, dsFPDColor_t *pColor) return dsERR_INVALID_PARAM; } - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } @@ -659,7 +446,7 @@ dsError_t dsGetFPColor(dsFPDIndicator_t eIndicator, dsFPDColor_t *pColor) static_cast(eIndicator); uint32_t color = 0; - uint32_t result = instance->GetFPDColor(indicator, color); + uint32_t result = FPDWrapper::GetFPDColor(fpdInterface, indicator, color); if (result == Core::ERROR_NONE) { *pColor = static_cast(color); @@ -675,8 +462,13 @@ dsError_t dsSetFPColor(dsFPDIndicator_t eIndicator, dsFPDColor_t eColor) dsError_t dsSetFPDColor(dsFPDIndicator_t eIndicator, dsFPDColor_t eColor, bool toPersist) { - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } @@ -684,25 +476,35 @@ dsError_t dsSetFPDColor(dsFPDIndicator_t eIndicator, dsFPDColor_t eColor, bool t static_cast(eIndicator); // Thunder interface doesn't support persist flag - ignore it - uint32_t result = instance->SetFPDColor(indicator, static_cast(eColor)); + uint32_t result = FPDWrapper::SetFPDColor(fpdInterface, indicator, static_cast(eColor)); return ConvertThunderError(result); } dsError_t dsFPEnableCLockDisplay(int enable) { - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { return dsERR_GENERAL; } - uint32_t result = instance->EnableFPDClockDisplay(enable != 0); + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { + return dsERR_GENERAL; + } + + uint32_t result = FPDWrapper::EnableFPDClockDisplay(fpdInterface, enable != 0); return ConvertThunderError(result); } dsError_t dsSetFPState(dsFPDIndicator_t eIndicator, dsFPDState_t state) { - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } @@ -711,7 +513,7 @@ dsError_t dsSetFPState(dsFPDIndicator_t eIndicator, dsFPDState_t state) Exchange::IDeviceSettingsFPD::FPDState fpdState = static_cast(state); - uint32_t result = instance->SetFPDState(indicator, fpdState); + uint32_t result = FPDWrapper::SetFPDState(fpdInterface, indicator, fpdState); return ConvertThunderError(result); } @@ -722,8 +524,13 @@ dsError_t dsGetFPState(dsFPDIndicator_t eIndicator, dsFPDState_t* state) return dsERR_INVALID_PARAM; } - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } @@ -731,7 +538,7 @@ dsError_t dsGetFPState(dsFPDIndicator_t eIndicator, dsFPDState_t* state) static_cast(eIndicator); Exchange::IDeviceSettingsFPD::FPDState fpdState; - uint32_t result = instance->GetFPDState(indicator, fpdState); + uint32_t result = FPDWrapper::GetFPDState(fpdInterface, indicator, fpdState); if (result == Core::ERROR_NONE) { *state = static_cast(fpdState); @@ -747,13 +554,18 @@ dsError_t dsGetFPTimeFormat(dsFPDTimeFormat_t *pTimeFormat) return dsERR_INVALID_PARAM; } - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat; - uint32_t result = instance->GetFPDTimeFormat(timeFormat); + uint32_t result = FPDWrapper::GetFPDTimeFormat(fpdInterface, timeFormat); if (result == Core::ERROR_NONE) { *pTimeFormat = static_cast(timeFormat); @@ -764,35 +576,45 @@ dsError_t dsGetFPTimeFormat(dsFPDTimeFormat_t *pTimeFormat) dsError_t dsSetFPTimeFormat(dsFPDTimeFormat_t eTimeFormat) { - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } Exchange::IDeviceSettingsFPD::FPDTimeFormat timeFormat = static_cast(eTimeFormat); - uint32_t result = instance->SetFPDTimeFormat(timeFormat); + uint32_t result = FPDWrapper::SetFPDTimeFormat(fpdInterface, timeFormat); return ConvertThunderError(result); } dsError_t dsSetFPDMode(dsFPDMode_t eMode) { - DeviceSettingsFPD* instance = DeviceSettingsFPD::Instance(); - if (!instance || !instance->IsOperational()) { + DeviceSettingsController* controller = DeviceSettingsController::GetInstance(); + if (!controller) { + return dsERR_GENERAL; + } + + Exchange::IDeviceSettingsFPD* fpdInterface = controller->GetFPDInterface(); + if (!fpdInterface) { return dsERR_GENERAL; } Exchange::IDeviceSettingsFPD::FPDMode mode = static_cast(eMode); - uint32_t result = instance->SetFPDMode(mode); + uint32_t result = FPDWrapper::SetFPDMode(fpdInterface, mode); return ConvertThunderError(result); } } // extern "C" -#endif // USE_WPE_THUNDER_PLUGIN +#endif // USE_IARM /** @} */ /** @} */ From 6b55778a248129a5d9c06d52c4507845a984d1fe Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Wed, 18 Feb 2026 14:10:32 +0000 Subject: [PATCH 16/23] Resolved compilation error --- ds/manager.cpp | 13 +++++++++++++ rpc/cli/dsController-com.cpp | 4 ++-- rpc/cli/dsFPD-com.cpp | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/ds/manager.cpp b/ds/manager.cpp index f94b9da1..8d61978f 100644 --- a/ds/manager.cpp +++ b/ds/manager.cpp @@ -45,6 +45,10 @@ #include #include +#ifndef USE_IARM +#include "dsController-com.h" +#endif + /** * @file manager.cpp * @brief RDK Device Settings module is a cross-platform device for controlling the following hardware configurations: @@ -156,6 +160,15 @@ void Manager::Initialize() if (needInit) { dsError_t err = dsERR_GENERAL; + #ifndef USE_IARM + // For Thunder COM-RPC mode, initialize the DeviceSettingsController + if (WPEFramework::DeviceSettingsController::Initialize() != WPEFramework::Core::ERROR_NONE) { + fprintf(stderr, "[Manager] Failed to initialize DeviceSettingsController\n"); + throw std::runtime_error("DeviceSettingsController initialization failed"); + } + printf("[Manager] DeviceSettingsController initialized successfully\n"); + #endif + err = initializeFunctionWithRetry("dsDisplayInit", dsDisplayInit); CHECK_RET_VAL(err); diff --git a/rpc/cli/dsController-com.cpp b/rpc/cli/dsController-com.cpp index aa8bab13..a4ba41e2 100644 --- a/rpc/cli/dsController-com.cpp +++ b/rpc/cli/dsController-com.cpp @@ -24,7 +24,7 @@ #ifndef USE_IARM -#include "DeviceSettingsController.h" +#include "dsController-com.h" #include #include #include @@ -574,4 +574,4 @@ Exchange::IDeviceSettingsCompositeIn* DeviceSettingsController::GetCompositeInIn } // namespace WPEFramework -#endif // USE_IARM \ No newline at end of file +#endif // USE_IARM diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp index 422f334f..60a55a27 100644 --- a/rpc/cli/dsFPD-com.cpp +++ b/rpc/cli/dsFPD-com.cpp @@ -34,7 +34,7 @@ #include "dsFPD.h" #include "dsError.h" #include "dsclientlogger.h" -#include "DeviceSettingsController.h" +#include "dsController-com.h" using namespace WPEFramework; From 32bd65dc0da6d652df9c67135ca2acce6395e917 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Thu, 19 Feb 2026 06:44:54 +0000 Subject: [PATCH 17/23] Modified the flag USE_THUNDER_PLUGIN --- ds/manager.cpp | 2 +- rpc/cli/dsController-com.cpp | 49 +++++++++++++++++++++++------------- rpc/cli/dsController-com.h | 4 +-- rpc/cli/dsFPD-com.cpp | 4 +-- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/ds/manager.cpp b/ds/manager.cpp index 8d61978f..7b2f5ea4 100644 --- a/ds/manager.cpp +++ b/ds/manager.cpp @@ -160,7 +160,7 @@ void Manager::Initialize() if (needInit) { dsError_t err = dsERR_GENERAL; - #ifndef USE_IARM + #ifdef USE_THUNDER_PLUGIN // For Thunder COM-RPC mode, initialize the DeviceSettingsController if (WPEFramework::DeviceSettingsController::Initialize() != WPEFramework::Core::ERROR_NONE) { fprintf(stderr, "[Manager] Failed to initialize DeviceSettingsController\n"); diff --git a/rpc/cli/dsController-com.cpp b/rpc/cli/dsController-com.cpp index a4ba41e2..926259f0 100644 --- a/rpc/cli/dsController-com.cpp +++ b/rpc/cli/dsController-com.cpp @@ -22,7 +22,7 @@ * @brief Implementation of central controller for DeviceSettings COM-RPC connections */ -#ifndef USE_IARM +#ifdef USE_THUNDER_PLUGIN #include "dsController-com.h" #include @@ -46,13 +46,13 @@ DeviceSettingsController::DeviceSettingsController() : BaseClass() , _deviceSettings(nullptr) , _fpdInterface(nullptr) - , _hdmiInInterface(nullptr) - , _audioInterface(nullptr) - , _displayInterface(nullptr) - , _videoPortInterface(nullptr) - , _videoDeviceInterface(nullptr) - , _hostInterface(nullptr) - , _compositeInInterface(nullptr) +// , _hdmiInInterface(nullptr) +// , _audioInterface(nullptr) +// , _displayInterface(nullptr) +// , _videoPortInterface(nullptr) +// , _videoDeviceInterface(nullptr) +// , _hostInterface(nullptr) +// , _compositeInInterface(nullptr) , _connected(false) , _shutdown(false) { @@ -67,7 +67,7 @@ DeviceSettingsController::~DeviceSettingsController() // Release all component interfaces _lock.Lock(); - if (_compositeInInterface) { +/* if (_compositeInInterface) { _compositeInInterface->Release(); _compositeInInterface = nullptr; } @@ -95,6 +95,7 @@ DeviceSettingsController::~DeviceSettingsController() _hdmiInInterface->Release(); _hdmiInInterface = nullptr; } +*/ if (_fpdInterface) { _fpdInterface->Release(); _fpdInterface = nullptr; @@ -129,7 +130,7 @@ void DeviceSettingsController::Operational(const bool upAndRunning) printf("[DeviceSettingsController] Plugin is not operational - releasing all interfaces\n"); // Release all component interfaces - if (_compositeInInterface) { + /* if (_compositeInInterface) { _compositeInInterface->Release(); _compositeInInterface = nullptr; } @@ -157,6 +158,7 @@ void DeviceSettingsController::Operational(const bool upAndRunning) _hdmiInInterface->Release(); _hdmiInInterface = nullptr; } + */ if (_fpdInterface) { _fpdInterface->Release(); _fpdInterface = nullptr; @@ -336,7 +338,7 @@ void DeviceSettingsController::FetchAndInitializeInterfaces() loadedCount++; } - if (controller->GetAudioInterface() != nullptr) { +/* if (controller->GetAudioInterface() != nullptr) { printf("[DeviceSettingsController] Audio interface available\n"); loadedCount++; } @@ -370,7 +372,7 @@ void DeviceSettingsController::FetchAndInitializeInterfaces() printf("[DeviceSettingsController] CompositeIn interface available\n"); loadedCount++; } - +*/ printf("[DeviceSettingsController] Interface initialization complete: %u interfaces loaded\n", loadedCount); } @@ -441,7 +443,7 @@ bool DeviceSettingsController::IsComponentAvailable(DeviceSettingsComponent comp case DeviceSettingsComponent::FPD: available = (_fpdInterface != nullptr); break; - case DeviceSettingsComponent::HDMIIn: + /* case DeviceSettingsComponent::HDMIIn: available = (_hdmiInInterface != nullptr); break; case DeviceSettingsComponent::Audio: @@ -462,6 +464,7 @@ bool DeviceSettingsController::IsComponentAvailable(DeviceSettingsComponent comp case DeviceSettingsComponent::CompositeIn: available = (_compositeInInterface != nullptr); break; + */ } _lock.Unlock(); @@ -511,67 +514,77 @@ Exchange::IDeviceSettingsFPD* DeviceSettingsController::GetFPDInterface() Exchange::IDeviceSettingsHDMIIn* DeviceSettingsController::GetHDMIInInterface() { - _lock.Lock(); +/* _lock.Lock(); QueryComponentInterface(_hdmiInInterface, "IDeviceSettingsHDMIIn"); Exchange::IDeviceSettingsHDMIIn* result = _hdmiInInterface; _lock.Unlock(); return result; +*/ } Exchange::IDeviceSettingsAudio* DeviceSettingsController::GetAudioInterface() { - _lock.Lock(); +/* _lock.Lock(); QueryComponentInterface(_audioInterface, "IDeviceSettingsAudio"); Exchange::IDeviceSettingsAudio* result = _audioInterface; _lock.Unlock(); return result; +*/ } Exchange::IDeviceSettingsDisplay* DeviceSettingsController::GetDisplayInterface() { - _lock.Lock(); +/* _lock.Lock(); QueryComponentInterface(_displayInterface, "IDeviceSettingsDisplay"); Exchange::IDeviceSettingsDisplay* result = _displayInterface; _lock.Unlock(); return result; -} +*/} Exchange::IDeviceSettingsVideoPort* DeviceSettingsController::GetVideoPortInterface() { +/* _lock.Lock(); QueryComponentInterface(_videoPortInterface, "IDeviceSettingsVideoPort"); Exchange::IDeviceSettingsVideoPort* result = _videoPortInterface; _lock.Unlock(); return result; +*/ } Exchange::IDeviceSettingsVideoDevice* DeviceSettingsController::GetVideoDeviceInterface() { +/* _lock.Lock(); QueryComponentInterface(_videoDeviceInterface, "IDeviceSettingsVideoDevice"); Exchange::IDeviceSettingsVideoDevice* result = _videoDeviceInterface; _lock.Unlock(); return result; +*/ } Exchange::IDeviceSettingsHost* DeviceSettingsController::GetHostInterface() { +/* _lock.Lock(); QueryComponentInterface(_hostInterface, "IDeviceSettingsHost"); Exchange::IDeviceSettingsHost* result = _hostInterface; _lock.Unlock(); return result; +*/ } Exchange::IDeviceSettingsCompositeIn* DeviceSettingsController::GetCompositeInInterface() { +/* _lock.Lock(); QueryComponentInterface(_compositeInInterface, "IDeviceSettingsCompositeIn"); Exchange::IDeviceSettingsCompositeIn* result = _compositeInInterface; _lock.Unlock(); return result; +*/ } } // namespace WPEFramework -#endif // USE_IARM +#endif // USE_THUNDER_PLUGIN diff --git a/rpc/cli/dsController-com.h b/rpc/cli/dsController-com.h index 40966b22..deaf2eb4 100644 --- a/rpc/cli/dsController-com.h +++ b/rpc/cli/dsController-com.h @@ -28,7 +28,7 @@ #pragma once -#ifndef USE_IARM +#ifdef USE_THUNDER_PLUGIN #ifndef MODULE_NAME #define MODULE_NAME DeviceSettings_Client @@ -258,4 +258,4 @@ class DeviceSettingsController : public RPC::SmartInterfaceType #include @@ -614,7 +614,7 @@ dsError_t dsSetFPDMode(dsFPDMode_t eMode) } // extern "C" -#endif // USE_IARM +#endif // USE_THUNDER_PLUGIN /** @} */ /** @} */ From 4b4c3e71b8e1f7e9ff866b99d781b9fafafadd83 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Thu, 19 Feb 2026 06:47:50 +0000 Subject: [PATCH 18/23] Modified the USE_THUNDER_PLUGIN flag in manager.cpp and ds/include/dsController-com.h file --- ds/include/dsController-com.h | 4 ++-- ds/manager.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ds/include/dsController-com.h b/ds/include/dsController-com.h index 40966b22..deaf2eb4 100644 --- a/ds/include/dsController-com.h +++ b/ds/include/dsController-com.h @@ -28,7 +28,7 @@ #pragma once -#ifndef USE_IARM +#ifdef USE_THUNDER_PLUGIN #ifndef MODULE_NAME #define MODULE_NAME DeviceSettings_Client @@ -258,4 +258,4 @@ class DeviceSettingsController : public RPC::SmartInterfaceType #include -#ifndef USE_IARM +#ifdef USE_THUNDER_PLUGIN #include "dsController-com.h" #endif From cc261adfd26e04e13f05a197b75e4c3c08fda873 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Thu, 19 Feb 2026 07:32:30 +0000 Subject: [PATCH 19/23] Removed USE_THUNDER_PLUGIN flag from dsFPD-com.cpp file --- rpc/cli/dsFPD-com.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp index 696e02c2..2146a818 100644 --- a/rpc/cli/dsFPD-com.cpp +++ b/rpc/cli/dsFPD-com.cpp @@ -24,8 +24,6 @@ * @{ **/ -#ifdef USE_THUNDER_PLUGIN - #include #include #include @@ -614,7 +612,5 @@ dsError_t dsSetFPDMode(dsFPDMode_t eMode) } // extern "C" -#endif // USE_THUNDER_PLUGIN - /** @} */ /** @} */ From 673c305a469f9fceee0c3fbd8c53dae8fb4bc5d5 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Thu, 19 Feb 2026 10:26:54 +0000 Subject: [PATCH 20/23] Resolved linker error --- ds/Makefile.am | 2 ++ rpc/cli/Makefile | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ds/Makefile.am b/ds/Makefile.am index 90c9bea4..c8a8b2c4 100644 --- a/ds/Makefile.am +++ b/ds/Makefile.am @@ -63,3 +63,5 @@ libds_la_SOURCES = aspectRatio.cpp \ host.cpp \ manager.cpp \ videoDFC.cpp + +libds_la_LIBADD = ../rpc/cli/libdshalcli.la diff --git a/rpc/cli/Makefile b/rpc/cli/Makefile index 7b2575ee..e9448399 100644 --- a/rpc/cli/Makefile +++ b/rpc/cli/Makefile @@ -24,12 +24,12 @@ INSTALL := $(PWD)/install # Conditional compilation: Thunder vs IARM ifdef USE_WPE_THUNDER_PLUGIN - # Thunder mode - use dsFPD-com.cpp, exclude dsFPD.c + # Thunder mode - use dsFPD-com.cpp and dsController-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))) + # IARM mode - use dsFPD.c, exclude both dsFPD-com.cpp and dsController-com.cpp + OBJS := $(patsubst %.cpp,%.o,$(filter-out dsFPD-com.cpp dsController-com.cpp,$(wildcard *.cpp))) OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) endif From 8ae412d7f135eda15e46bab6927a727e1ce684a7 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Thu, 19 Feb 2026 10:46:22 +0000 Subject: [PATCH 21/23] Added the USE_THUNDER_PLUGIN flag in dsFPD-com.cpp file --- rpc/cli/dsFPD-com.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rpc/cli/dsFPD-com.cpp b/rpc/cli/dsFPD-com.cpp index 2146a818..696e02c2 100644 --- a/rpc/cli/dsFPD-com.cpp +++ b/rpc/cli/dsFPD-com.cpp @@ -24,6 +24,8 @@ * @{ **/ +#ifdef USE_THUNDER_PLUGIN + #include #include #include @@ -612,5 +614,7 @@ dsError_t dsSetFPDMode(dsFPDMode_t eMode) } // extern "C" +#endif // USE_THUNDER_PLUGIN + /** @} */ /** @} */ From 6201448d836eb8a2cebf9fa436d46f2c6f17680c Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Thu, 19 Feb 2026 11:54:17 +0000 Subject: [PATCH 22/23] Modified the Makefile for linker error --- ds/Makefile | 4 ++-- sample/Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ds/Makefile b/ds/Makefile index 3000c0f2..df057235 100644 --- a/ds/Makefile +++ b/ds/Makefile @@ -59,8 +59,8 @@ all: install library: $(OBJS) @echo "Building $(LIBNAMEFULL) ...." - $(CXX) $(OBJS) $(CFLAGS) $(DSHAL_LDFLAGS) -L$(INSTALL)/lib -lIARMBus -ldshalcli -shared -o $(LIBNAMEFULL) - $(CXX) $(OBJS) $(CFLAGS) -L$(INSTALL)/lib -lIARMBus -ldshalcli -shared -o $(LIBNAMECLI) + $(CXX) $(OBJS) $(CFLAGS) $(DSHAL_LDFLAGS) -L$(INSTALL)/lib -lIARMBus -Wl,--no-as-needed -ldshalcli -Wl,--as-needed -shared -o $(LIBNAMEFULL) + $(CXX) $(OBJS) $(CFLAGS) -L$(INSTALL)/lib -lIARMBus -Wl,--no-as-needed -ldshalcli -Wl,--as-needed -shared -o $(LIBNAMECLI) %.o: %.cpp @echo "Building $@ ...." diff --git a/sample/Makefile b/sample/Makefile index cc06a401..5bb61c31 100644 --- a/sample/Makefile +++ b/sample/Makefile @@ -91,7 +91,7 @@ clean: dsapp: @if [ -f DSCliLibStandaloneApp.cpp ]; then \ echo "Building DSApp..."; \ - $(CXX) $(CFLAGS) -std=c++11 DSCliLibStandaloneApp.cpp -o ../DSApp -L$(INSTALL)/lib -lds -ldshalcli -lcurl -lpthread $(LDFLAGS); \ + $(CXX) $(CFLAGS) -std=c++11 DSCliLibStandaloneApp.cpp -o ../DSApp -L$(INSTALL)/lib -lds -Wl,--no-as-needed -ldshalcli -Wl,--as-needed -lcurl -lpthread $(LDFLAGS); \ echo "DSApp built successfully at devicesettings/DSApp"; \ else \ echo "DSCliLibStandaloneApp.cpp not found, skipping DSApp build"; \ From b928216c7c5c138b10e78132101aed0bf2469453 Mon Sep 17 00:00:00 2001 From: Manimaran Renganathan Date: Fri, 20 Feb 2026 11:04:33 +0000 Subject: [PATCH 23/23] Modified the devicesettings module changes as compiled successfully in Local Dev VM --- configure.ac | 2 +- ds/include/dsController-com.h | 4 ++-- ds/manager.cpp | 4 ++-- rpc/cli/Makefile.am | 2 +- rpc/cli/dsController-com.cpp | 4 ++-- rpc/cli/dsController-com.h | 4 ++-- rpc/cli/dsFPD-com.cpp | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 7445ffc2..edf9676e 100644 --- a/configure.ac +++ b/configure.ac @@ -56,7 +56,7 @@ AC_ARG_ENABLE([thunder-plugin], [enable_thunder_plugin=$enableval], [enable_thunder_plugin=no]) -AM_CONDITIONAL([USE_THUNDER_PLUGIN], [test "x$enable_thunder_plugin" = "xyes"]) +AM_CONDITIONAL([USE_WPE_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]) diff --git a/ds/include/dsController-com.h b/ds/include/dsController-com.h index deaf2eb4..94bbe509 100644 --- a/ds/include/dsController-com.h +++ b/ds/include/dsController-com.h @@ -28,7 +28,7 @@ #pragma once -#ifdef USE_THUNDER_PLUGIN +#ifdef USE_WPE_THUNDER_PLUGIN #ifndef MODULE_NAME #define MODULE_NAME DeviceSettings_Client @@ -258,4 +258,4 @@ class DeviceSettingsController : public RPC::SmartInterfaceType #include -#ifdef USE_THUNDER_PLUGIN +#ifdef USE_WPE_THUNDER_PLUGIN #include "dsController-com.h" #endif @@ -160,7 +160,7 @@ void Manager::Initialize() if (needInit) { dsError_t err = dsERR_GENERAL; - #ifdef USE_THUNDER_PLUGIN + #ifdef USE_WPE_THUNDER_PLUGIN // For Thunder COM-RPC mode, initialize the DeviceSettingsController if (WPEFramework::DeviceSettingsController::Initialize() != WPEFramework::Core::ERROR_NONE) { fprintf(stderr, "[Manager] Failed to initialize DeviceSettingsController\n"); diff --git a/rpc/cli/Makefile.am b/rpc/cli/Makefile.am index a02fb515..5e240587 100644 --- a/rpc/cli/Makefile.am +++ b/rpc/cli/Makefile.am @@ -30,7 +30,7 @@ libdshalcli_la_CPPFLAGS = $(INCLUDE_FILES) libdshalcli_la_CFLAGS = -g -fPIC -D_REENTRANT -Wall # Conditional compilation for Thunder COM-RPC -if USE_THUNDER_PLUGIN +if USE_WPE_THUNDER_PLUGIN FPD_SOURCE = dsController-com.cpp dsFPD-com.cpp THUNDER_LIBS = -lWPEFrameworkCore -lWPEFrameworkCOM else diff --git a/rpc/cli/dsController-com.cpp b/rpc/cli/dsController-com.cpp index 926259f0..7c668c1a 100644 --- a/rpc/cli/dsController-com.cpp +++ b/rpc/cli/dsController-com.cpp @@ -22,7 +22,7 @@ * @brief Implementation of central controller for DeviceSettings COM-RPC connections */ -#ifdef USE_THUNDER_PLUGIN +#ifdef USE_WPE_THUNDER_PLUGIN #include "dsController-com.h" #include @@ -587,4 +587,4 @@ Exchange::IDeviceSettingsCompositeIn* DeviceSettingsController::GetCompositeInIn } // namespace WPEFramework -#endif // USE_THUNDER_PLUGIN +#endif // USE_WPE_THUNDER_PLUGIN diff --git a/rpc/cli/dsController-com.h b/rpc/cli/dsController-com.h index deaf2eb4..94bbe509 100644 --- a/rpc/cli/dsController-com.h +++ b/rpc/cli/dsController-com.h @@ -28,7 +28,7 @@ #pragma once -#ifdef USE_THUNDER_PLUGIN +#ifdef USE_WPE_THUNDER_PLUGIN #ifndef MODULE_NAME #define MODULE_NAME DeviceSettings_Client @@ -258,4 +258,4 @@ class DeviceSettingsController : public RPC::SmartInterfaceType #include @@ -614,7 +614,7 @@ dsError_t dsSetFPDMode(dsFPDMode_t eMode) } // extern "C" -#endif // USE_THUNDER_PLUGIN +#endif // USE_WPE_THUNDER_PLUGIN /** @} */ /** @} */