From 033454b563ff10b80e0487eff8c7cb921bb58b1f Mon Sep 17 00:00:00 2001 From: "neethu.arambilsunny@sky.uk" Date: Mon, 12 May 2025 17:16:01 +0100 Subject: [PATCH 01/52] RDKEMW-4116 : VRR Feature Middleware changes. --- AVInput/AVInput.cpp | 216 +++++++++++++++++++++++++++++++++++++++++++- AVInput/AVInput.h | 8 ++ 2 files changed, 222 insertions(+), 2 deletions(-) diff --git a/AVInput/AVInput.cpp b/AVInput/AVInput.cpp index 8c71c7a6..094c5f99 100644 --- a/AVInput/AVInput.cpp +++ b/AVInput/AVInput.cpp @@ -48,6 +48,8 @@ #define AVINPUT_METHOD_GET_EDID_VERSION "getEdidVersion" #define AVINPUT_METHOD_SET_EDID_ALLM_SUPPORT "setEdid2AllmSupport" #define AVINPUT_METHOD_GET_EDID_ALLM_SUPPORT "getEdid2AllmSupport" +#define AVINPUT_METHOD_SET_VRR_SUPPORT "setVRRSupport" +#define AVINPUT_METHOD_GET_VRR_SUPPORT "getVRRSupport" #define AVINPUT_METHOD_GET_HDMI_COMPATIBILITY_VERSION "getHdmiVersion" #define AVINPUT_METHOD_SET_MIXER_LEVELS "setMixerLevels" #define AVINPUT_METHOD_START_INPUT "startInput" @@ -156,7 +158,11 @@ void AVInput::InitializeIARM() IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, dsAVGameFeatureStatusEventHandler)); - IARM_CHECK(IARM_Bus_RegisterEventHandler( + IARM_CHECK(IARM_Bus_RegisterEventHandler( + IARM_BUS_DSMGR_NAME, + IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS, + dsAVGameFeatureStatusEventHandler)); + IARM_CHECK(IARM_Bus_RegisterEventHandler( IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, dsAVEventHandler)); @@ -198,6 +204,9 @@ void AVInput::DeinitializeIARM() IARM_CHECK(IARM_Bus_RemoveEventHandler( IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, dsAVGameFeatureStatusEventHandler)); + IARM_CHECK(IARM_Bus_RemoveEventHandler( + IARM_BUS_DSMGR_NAME, + IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS, dsAVGameFeatureStatusEventHandler)); IARM_CHECK(IARM_Bus_RemoveEventHandler( IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, dsAVEventHandler)); @@ -231,6 +240,8 @@ void AVInput::RegisterAll() Register(_T(AVINPUT_METHOD_SET_MIXER_LEVELS), &AVInput::setMixerLevels, this); Register(_T(AVINPUT_METHOD_SET_EDID_ALLM_SUPPORT), &AVInput::setEdid2AllmSupportWrapper, this); Register(_T(AVINPUT_METHOD_GET_EDID_ALLM_SUPPORT), &AVInput::getEdid2AllmSupportWrapper, this); + Register(_T(AVINPUT_METHOD_SET_VRR_SUPPORT), &AVInput::setVRRSupportWrapper, this); + Register(_T(AVINPUT_METHOD_GET_VRR_SUPPORT), &AVInput::getVRRSupportWrapper, this); Register(_T(AVINPUT_METHOD_GET_HDMI_COMPATIBILITY_VERSION), &AVInput::getHdmiVersionWrapper, this); Register(_T(AVINPUT_METHOD_START_INPUT), &AVInput::startInput, this); Register(_T(AVINPUT_METHOD_STOP_INPUT), &AVInput::stopInput, this); @@ -239,6 +250,7 @@ void AVInput::RegisterAll() Register(_T(AVINPUT_METHOD_GAME_FEATURE_STATUS), &AVInput::getGameFeatureStatusWrapper, this); m_primVolume = DEFAULT_PRIM_VOL_LEVEL; m_inputVolume = DEFAULT_INPUT_VOL_LEVEL; + m_currentVrrType = dsVRR_NONE; } void AVInput::UnregisterAll() @@ -251,6 +263,8 @@ void AVInput::UnregisterAll() Unregister(_T(AVINPUT_METHOD_READ_EDID)); Unregister(_T(AVINPUT_METHOD_READ_RAWSPD)); Unregister(_T(AVINPUT_METHOD_READ_SPD)); + Unregister(_T(AVINPUT_METHOD_SET_VRR_SUPPORT)); + Unregister(_T(AVINPUT_METHOD_GET_VRR_SUPPORT)); Unregister(_T(AVINPUT_METHOD_SET_EDID_VERSION)); Unregister(_T(AVINPUT_METHOD_GET_EDID_VERSION)); Unregister(_T(AVINPUT_METHOD_START_INPUT)); @@ -1001,6 +1015,28 @@ void AVInput::dsAVGameFeatureStatusEventHandler(const char *owner, IARM_EventId_ AVInput::_instance->AVInputALLMChange(hdmi_in_port, allm_mode); } + if (IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + int hdmi_in_port = eventData->data.hdmi_in_vrr_mode.port; + dsVRRType_t new_vrrType = eventData->data.hdmi_in_vrr_mode.vrr_type; + LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS event port: %d, VRR Type: %d", hdmi_in_port,new_vrrType); + + if(new_vrrType == dsVRR_NONE) + { + if(AVInput::_instance->m_currentVrrType != dsVRR_NONE){ + AVInput::_instance->AVInputVRRChange(hdmi_in_port, AVInput::_instance->m_currentVrrType, false); + } + } + else + { + if(AVInput::_instance->m_currentVrrType != dsVRR_NONE){ + AVInput::_instance->AVInputVRRChange(hdmi_in_port, AVInput::_instance->m_currentVrrType, false); + } + AVInput::_instance->AVInputVRRChange(hdmi_in_port, new_vrrType, true); + } + AVInput::_instance->m_currentVrrType = new_vrrType; + } } void AVInput::AVInputALLMChange( int port , bool allm_mode) @@ -1013,6 +1049,37 @@ void AVInput::AVInputALLMChange( int port , bool allm_mode) sendNotify(AVINPUT_EVENT_ON_GAME_FEATURE_STATUS_CHANGED, params); } +void AVInput::AVInputVRRChange( int port , dsVRRType_t vrr_type, bool vrr_mode) +{ + JsonObject params; + switch(vrr_type) + { + case dsVRR_HDMI_VRR: + params["id"] = port; + params["gameFeature"] = "VRR-HDMI"; + params["mode"] = vrr_mode; + break; + case dsVRR_AMD_FREESYNC: + params["id"] = port; + params["gameFeature"] = "VRR-FREESYNC"; + params["mode"] = vrr_mode; + break; + case dsVRR_AMD_FREESYNC_PREMIUM: + params["id"] = port; + params["gameFeature"] = "VRR-FREESYNC-PREMIUM"; + params["mode"] = vrr_mode; + break; + case dsVRR_AMD_FREESYNC_PREMIUM_PRO: + params["id"] = port; + params["gameFeature"] = "VRR-FREESYNC-PREMIUM-PRO"; + params["mode"] = vrr_mode; + break; + default: + break; + } + sendNotify(AVINPUT_EVENT_ON_GAME_FEATURE_STATUS_CHANGED, params); +} + uint32_t AVInput::getSupportedGameFeatures(const JsonObject& parameters, JsonObject& response) { LOGINFOMETHOD(); @@ -1067,9 +1134,49 @@ uint32_t AVInput::getGameFeatureStatusWrapper(const JsonObject& parameters, Json LOGWARN("AVInput::getGameFeatureStatusWrapper ALLM MODE:%d", allm); response["mode"] = allm; } + else if(strcmp (sGameFeature.c_str(), "VRR-HDMI") == 0) + { + bool hdmi_vrr = false; + dsVRRType_t vrrType; + getVRRStatus(portId, &vrrType); + if(vrrType == dsVRR_HDMI_VRR) + hdmi_vrr = true; + LOGWARN("AVInput::getGameFeatureStatusWrapper HDMI VRR MODE:%d", hdmi_vrr); + response["mode"] = hdmi_vrr; + } + else if(strcmp (sGameFeature.c_str(), "VRR-FREESYNC") == 0) + { + bool freesync = false; + dsVRRType_t vrrType; + getVRRStatus(portId, &vrrType); + if(vrrType == dsVRR_AMD_FREESYNC) + freesync = true; + LOGWARN("AVInput::getGameFeatureStatusWrapper FREESYNC MODE:%d", freesync); + response["mode"] = freesync; + } + else if(strcmp (sGameFeature.c_str(), "VRR-FREESYNC-PREMIUM") == 0) + { + bool freesync_premium = false; + dsVRRType_t vrrType; + getVRRStatus(portId, &vrrType); + if(vrrType == dsVRR_AMD_FREESYNC_PREMIUM) + freesync_premium = true; + LOGWARN("AVInput::getGameFeatureStatusWrapper FREESYNC PREMIUM MODE:%d", freesync_premium); + response["mode"] = freesync_premium; + } + else if(strcmp (sGameFeature.c_str(), "VRR-FREESYNC-PREMIUM-PRO") == 0) + { + bool freesync_premium_pro = false; + dsVRRType_t vrrType; + getVRRStatus(portId, &vrrType); + if(vrrType == dsVRR_AMD_FREESYNC_PREMIUM_PRO) + freesync_premium_pro = true; + LOGWARN("AVInput::getGameFeatureStatusWrapper FREESYNC PREMIUM PRO MODE:%d", freesync_premium_pro); + response["mode"] = freesync_premium_pro; + } else { - LOGWARN("AVInput::getGameFeatureStatusWrapper Mode is not supported. Supported mode: ALLM"); + LOGWARN("AVInput::getGameFeatureStatusWrapper Mode is not supported. Supported mode: ALLM, VRR-HDMI, VRR-FREESYNC-PREMIUM"); returnResponse(false); } returnResponse(true); @@ -1091,6 +1198,21 @@ bool AVInput::getALLMStatus(int iPort) return allm; } +void AVInput::getVRRStatus(int iPort, dsVRRType_t *vrrType) +{ + + try + { + device::HdmiInput::getInstance().getVRRStatus (iPort, vrrType); + LOGWARN("AVInput::getVRRStatus VRR TYPE: %d", *vrrType); + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); + } + +} + uint32_t AVInput::getRawSPDWrapper(const JsonObject& parameters, JsonObject& response) { LOGINFOMETHOD(); @@ -1363,6 +1485,96 @@ uint32_t AVInput::getEdid2AllmSupportWrapper(const JsonObject& parameters, JsonO } } +bool AVInput::getVRRSupport(int portId,bool *vrrSupportValue) +{ + bool ret = true; + try + { + device::HdmiInput::getInstance().getVRRSupport (portId, vrrSupportValue); + LOGINFO("AVInput - getVRRSupport:%d", *vrrSupportValue); + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(std::to_string(portId)); + ret = false; + } + return ret; +} + +uint32_t AVInput::getVRRSupportWrapper(const JsonObject& parameters, JsonObject& response) +{ + LOGINFOMETHOD(); + string sPortId = parameters["portId"].String(); + + int portId = 0; + bool vrrSupport = true; + returnIfParamNotFound(parameters, "portId"); + + try { + portId = stoi(sPortId); + }catch (const std::exception& err) { + LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); + returnResponse(false); + } + + bool result = getVRRSupport(portId, &vrrSupport); + if(result == true) + { + response["vrrSupport"] = vrrSupport; + returnResponse(true); + } + else + { + returnResponse(false); + } +} + +bool AVInput::setVRRSupport(int portId, bool vrrSupport) +{ + bool ret = true; + try + { + device::HdmiInput::getInstance().setVRRSupport (portId, vrrSupport); + LOGWARN("AVInput - vrrSupport:%d", vrrSupport); + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(std::to_string(portId)); + ret = false; + } + return ret; + +} + +uint32_t AVInput::setVRRSupportWrapper(const JsonObject& parameters, JsonObject& response) +{ + LOGINFOMETHOD(); + + returnIfParamNotFound(parameters, "portId"); + returnIfParamNotFound(parameters, "vrrSupport"); + + int portId = 0; + string sPortId = parameters["portId"].String(); + bool vrrSupport = parameters["vrrSupport"].Boolean(); + + try { + portId = stoi(sPortId); + }catch (const std::exception& err) { + LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); + returnResponse(false); + } + + bool result = setVRRSupport(portId, vrrSupport); + if(result == true) + { + returnResponse(true); + } + else + { + returnResponse(false); + } +} + uint32_t AVInput::setEdidVersionWrapper(const JsonObject& parameters, JsonObject& response) { LOGINFOMETHOD(); diff --git a/AVInput/AVInput.h b/AVInput/AVInput.h index 22b61827..470f1e2d 100644 --- a/AVInput/AVInput.h +++ b/AVInput/AVInput.h @@ -47,6 +47,8 @@ class AVInput: public PluginHost::IPlugin, public PluginHost::JSONRPC int m_primVolume; int m_inputVolume; //Player Volume + + dsVRRType_t m_currentVrrType; public: // IPlugin methods // ------------------------------------------------------------------------------------------------------- @@ -79,6 +81,8 @@ class AVInput: public PluginHost::IPlugin, public PluginHost::JSONRPC uint32_t getEdidVersionWrapper(const JsonObject& parameters, JsonObject& response); uint32_t setEdid2AllmSupportWrapper(const JsonObject& parameters, JsonObject& response); uint32_t getEdid2AllmSupportWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setVRRSupportWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getVRRSupportWrapper(const JsonObject& parameters, JsonObject& response); uint32_t startInput(const JsonObject& parameters, JsonObject& response); uint32_t stopInput(const JsonObject& parameters, JsonObject& response); uint32_t setVideoRectangleWrapper(const JsonObject& parameters, JsonObject& response); @@ -95,10 +99,14 @@ class AVInput: public PluginHost::IPlugin, public PluginHost::JSONRPC std::string getSPD(int iPort); int setEdidVersion(int iPort, int iEdidVer); int getEdidVersion(int iPort); + bool setVRRSupport(int portId, bool vrrSupport); + bool getVRRSupport(int portId, bool *vrrSupportValue); bool setVideoRectangle(int x, int y, int width, int height, int type); bool getALLMStatus(int iPort); + void getVRRStatus(int iPort, dsVRRType_t *vrrType); void AVInputHotplug(int input , int connect, int type); + void AVInputVRRChange( int port , dsVRRType_t vrr_type, bool vrr_mode); static void dsAVEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); void AVInputSignalChange( int port , int signalStatus, int type); From f42680c36704650095061d813fbb68f5c6064b70 Mon Sep 17 00:00:00 2001 From: neethuas379 Date: Mon, 26 May 2025 14:47:23 +0530 Subject: [PATCH 02/52] Update AVInput.h --- AVInput/AVInput.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AVInput/AVInput.h b/AVInput/AVInput.h index 470f1e2d..b6c86142 100644 --- a/AVInput/AVInput.h +++ b/AVInput/AVInput.h @@ -83,6 +83,7 @@ class AVInput: public PluginHost::IPlugin, public PluginHost::JSONRPC uint32_t getEdid2AllmSupportWrapper(const JsonObject& parameters, JsonObject& response); uint32_t setVRRSupportWrapper(const JsonObject& parameters, JsonObject& response); uint32_t getVRRSupportWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getVRRFrameRateWrapper(const JsonObject& parameters, JsonObject& response); uint32_t startInput(const JsonObject& parameters, JsonObject& response); uint32_t stopInput(const JsonObject& parameters, JsonObject& response); uint32_t setVideoRectangleWrapper(const JsonObject& parameters, JsonObject& response); @@ -103,7 +104,7 @@ class AVInput: public PluginHost::IPlugin, public PluginHost::JSONRPC bool getVRRSupport(int portId, bool *vrrSupportValue); bool setVideoRectangle(int x, int y, int width, int height, int type); bool getALLMStatus(int iPort); - void getVRRStatus(int iPort, dsVRRType_t *vrrType); + bool getVRRStatus(int iPort, dsHdmiInVrrStatus_t *vrrStatus); void AVInputHotplug(int input , int connect, int type); void AVInputVRRChange( int port , dsVRRType_t vrr_type, bool vrr_mode); From 78f58ffebdd7dc34588a2202722758881503600c Mon Sep 17 00:00:00 2001 From: neethuas379 Date: Mon, 26 May 2025 14:59:45 +0530 Subject: [PATCH 03/52] Update AVInput.cpp --- AVInput/AVInput.cpp | 68 +++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/AVInput/AVInput.cpp b/AVInput/AVInput.cpp index 094c5f99..a1e08ba1 100644 --- a/AVInput/AVInput.cpp +++ b/AVInput/AVInput.cpp @@ -50,6 +50,7 @@ #define AVINPUT_METHOD_GET_EDID_ALLM_SUPPORT "getEdid2AllmSupport" #define AVINPUT_METHOD_SET_VRR_SUPPORT "setVRRSupport" #define AVINPUT_METHOD_GET_VRR_SUPPORT "getVRRSupport" +#define AVINPUT_METHOD_GET_VRR_FRAME_RATE "getVRRFrameRate" #define AVINPUT_METHOD_GET_HDMI_COMPATIBILITY_VERSION "getHdmiVersion" #define AVINPUT_METHOD_SET_MIXER_LEVELS "setMixerLevels" #define AVINPUT_METHOD_START_INPUT "startInput" @@ -242,6 +243,7 @@ void AVInput::RegisterAll() Register(_T(AVINPUT_METHOD_GET_EDID_ALLM_SUPPORT), &AVInput::getEdid2AllmSupportWrapper, this); Register(_T(AVINPUT_METHOD_SET_VRR_SUPPORT), &AVInput::setVRRSupportWrapper, this); Register(_T(AVINPUT_METHOD_GET_VRR_SUPPORT), &AVInput::getVRRSupportWrapper, this); + Register(_T(AVINPUT_METHOD_GET_VRR_FRAME_RATE), &AVInput::getVRRFrameRateWrapper, this); Register(_T(AVINPUT_METHOD_GET_HDMI_COMPATIBILITY_VERSION), &AVInput::getHdmiVersionWrapper, this); Register(_T(AVINPUT_METHOD_START_INPUT), &AVInput::startInput, this); Register(_T(AVINPUT_METHOD_STOP_INPUT), &AVInput::stopInput, this); @@ -265,6 +267,7 @@ void AVInput::UnregisterAll() Unregister(_T(AVINPUT_METHOD_READ_SPD)); Unregister(_T(AVINPUT_METHOD_SET_VRR_SUPPORT)); Unregister(_T(AVINPUT_METHOD_GET_VRR_SUPPORT)); + Unregister(_T(AVINPUT_METHOD_GET_VRR_FRAME_RATE)); Unregister(_T(AVINPUT_METHOD_SET_EDID_VERSION)); Unregister(_T(AVINPUT_METHOD_GET_EDID_VERSION)); Unregister(_T(AVINPUT_METHOD_START_INPUT)); @@ -1137,9 +1140,9 @@ uint32_t AVInput::getGameFeatureStatusWrapper(const JsonObject& parameters, Json else if(strcmp (sGameFeature.c_str(), "VRR-HDMI") == 0) { bool hdmi_vrr = false; - dsVRRType_t vrrType; - getVRRStatus(portId, &vrrType); - if(vrrType == dsVRR_HDMI_VRR) + dsHdmiInVrrStatus_t vrrStatus; + getVRRStatus(portId, &vrrStatus); + if(vrrStatus.vrrType == dsVRR_HDMI_VRR) hdmi_vrr = true; LOGWARN("AVInput::getGameFeatureStatusWrapper HDMI VRR MODE:%d", hdmi_vrr); response["mode"] = hdmi_vrr; @@ -1147,9 +1150,9 @@ uint32_t AVInput::getGameFeatureStatusWrapper(const JsonObject& parameters, Json else if(strcmp (sGameFeature.c_str(), "VRR-FREESYNC") == 0) { bool freesync = false; - dsVRRType_t vrrType; - getVRRStatus(portId, &vrrType); - if(vrrType == dsVRR_AMD_FREESYNC) + dsHdmiInVrrStatus_t vrrStatus; + getVRRStatus(portId, &vrrStatus); + if(vrrStatus.vrrType == dsVRR_AMD_FREESYNC) freesync = true; LOGWARN("AVInput::getGameFeatureStatusWrapper FREESYNC MODE:%d", freesync); response["mode"] = freesync; @@ -1157,9 +1160,9 @@ uint32_t AVInput::getGameFeatureStatusWrapper(const JsonObject& parameters, Json else if(strcmp (sGameFeature.c_str(), "VRR-FREESYNC-PREMIUM") == 0) { bool freesync_premium = false; - dsVRRType_t vrrType; - getVRRStatus(portId, &vrrType); - if(vrrType == dsVRR_AMD_FREESYNC_PREMIUM) + dsHdmiInVrrStatus_t vrrStatus; + getVRRStatus(portId, &vrrStatus); + if(vrrStatus.vrrType == dsVRR_AMD_FREESYNC_PREMIUM) freesync_premium = true; LOGWARN("AVInput::getGameFeatureStatusWrapper FREESYNC PREMIUM MODE:%d", freesync_premium); response["mode"] = freesync_premium; @@ -1167,9 +1170,9 @@ uint32_t AVInput::getGameFeatureStatusWrapper(const JsonObject& parameters, Json else if(strcmp (sGameFeature.c_str(), "VRR-FREESYNC-PREMIUM-PRO") == 0) { bool freesync_premium_pro = false; - dsVRRType_t vrrType; - getVRRStatus(portId, &vrrType); - if(vrrType == dsVRR_AMD_FREESYNC_PREMIUM_PRO) + dsHdmiInVrrStatus_t vrrStatus; + getVRRStatus(portId, &vrrStatus); + if(vrrStatus.vrrType == dsVRR_AMD_FREESYNC_PREMIUM_PRO) freesync_premium_pro = true; LOGWARN("AVInput::getGameFeatureStatusWrapper FREESYNC PREMIUM PRO MODE:%d", freesync_premium_pro); response["mode"] = freesync_premium_pro; @@ -1198,19 +1201,20 @@ bool AVInput::getALLMStatus(int iPort) return allm; } -void AVInput::getVRRStatus(int iPort, dsVRRType_t *vrrType) +void AVInput::getVRRStatus(int iPort, dsHdmiInVrrStatus_t *vrrStatus) { - + bool ret = true; try { - device::HdmiInput::getInstance().getVRRStatus (iPort, vrrType); - LOGWARN("AVInput::getVRRStatus VRR TYPE: %d", *vrrType); + device::HdmiInput::getInstance().getVRRStatus (iPort, vrrStatus); + LOGWARN("AVInput::getVRRStatus VRR TYPE: %d, VRR FRAMERATE: %f", vrrStatus->vrrType,vrrStatus->vrrAmdfreesyncFramerate_Hz); } catch (const device::Exception& err) { LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); + ret = false; } - + return ret; } uint32_t AVInput::getRawSPDWrapper(const JsonObject& parameters, JsonObject& response) @@ -1504,11 +1508,11 @@ bool AVInput::getVRRSupport(int portId,bool *vrrSupportValue) uint32_t AVInput::getVRRSupportWrapper(const JsonObject& parameters, JsonObject& response) { LOGINFOMETHOD(); + returnIfParamNotFound(parameters, "portId"); string sPortId = parameters["portId"].String(); int portId = 0; bool vrrSupport = true; - returnIfParamNotFound(parameters, "portId"); try { portId = stoi(sPortId); @@ -1575,6 +1579,34 @@ uint32_t AVInput::setVRRSupportWrapper(const JsonObject& parameters, JsonObject& } } +uint32_t AVInput::getVRRFrameRateWrapper(const JsonObject& parameters, JsonObject& response) +{ + LOGINFOMETHOD(); + returnIfParamNotFound(parameters, "portId"); + string sPortId = parameters["portId"].String(); + + int portId = 0; + dsHdmiInVrrStatus_t vrrStatus; + + try { + portId = stoi(sPortId); + }catch (const std::exception& err) { + LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); + returnResponse(false); + } + + bool result = getVRRStatus(portId, &vrrStatus); + if(result == true) + { + response["currentVRRVideoFrameRate"] = vrrStatus.vrrAmdfreesyncFramerate_Hz; + returnResponse(true); + } + else + { + returnResponse(false); + } +} + uint32_t AVInput::setEdidVersionWrapper(const JsonObject& parameters, JsonObject& response) { LOGINFOMETHOD(); From eb4c50627cca28d866fe312fc4590cf4d3885cb3 Mon Sep 17 00:00:00 2001 From: neethuas379 Date: Mon, 26 May 2025 17:23:57 +0530 Subject: [PATCH 04/52] Update AVInput.cpp --- AVInput/AVInput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AVInput/AVInput.cpp b/AVInput/AVInput.cpp index a1e08ba1..9bd519eb 100644 --- a/AVInput/AVInput.cpp +++ b/AVInput/AVInput.cpp @@ -1201,7 +1201,7 @@ bool AVInput::getALLMStatus(int iPort) return allm; } -void AVInput::getVRRStatus(int iPort, dsHdmiInVrrStatus_t *vrrStatus) +bool AVInput::getVRRStatus(int iPort, dsHdmiInVrrStatus_t *vrrStatus) { bool ret = true; try From 49ba711a3583999761dabf4af5b235044a47724b Mon Sep 17 00:00:00 2001 From: neethuas379 Date: Tue, 10 Jun 2025 19:22:51 +0530 Subject: [PATCH 05/52] Update AVInput.cpp --- AVInput/AVInput.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/AVInput/AVInput.cpp b/AVInput/AVInput.cpp index 9bd519eb..0562267e 100644 --- a/AVInput/AVInput.cpp +++ b/AVInput/AVInput.cpp @@ -68,6 +68,12 @@ #define AVINPUT_EVENT_ON_GAME_FEATURE_STATUS_CHANGED "gameFeatureStatusUpdate" #define AVINPUT_EVENT_ON_AVI_CONTENT_TYPE_CHANGED "aviContentTypeUpdate" +#define STR_ALLM "ALLM" +#define VRR_TYPE_HDMI "VRR-HDMI" +#define VRR_TYPE_FREESYNC "VRR-FREESYNC" +#define VRR_TYPE_FREESYNC_PREMIUM "VRR-FREESYNC-PREMIUM" +#define VRR_TYPE_FREESYNC_PREMIUM_PRO "VRR-FREESYNC-PREMIUM-PRO" + static bool isAudioBalanceSet = false; static int planeType = 0; From dcee164f26692b92e7d7fadf9b36e1523cd84d69 Mon Sep 17 00:00:00 2001 From: neethuas379 Date: Tue, 10 Jun 2025 19:27:05 +0530 Subject: [PATCH 06/52] Update AVInput.cpp --- AVInput/AVInput.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/AVInput/AVInput.cpp b/AVInput/AVInput.cpp index 0562267e..ede81737 100644 --- a/AVInput/AVInput.cpp +++ b/AVInput/AVInput.cpp @@ -1052,7 +1052,7 @@ void AVInput::AVInputALLMChange( int port , bool allm_mode) { JsonObject params; params["id"] = port; - params["gameFeature"] = "ALLM"; + params["gameFeature"] = STR_ALLM; params["mode"] = allm_mode; sendNotify(AVINPUT_EVENT_ON_GAME_FEATURE_STATUS_CHANGED, params); @@ -1065,22 +1065,22 @@ void AVInput::AVInputVRRChange( int port , dsVRRType_t vrr_type, bool vrr_mode) { case dsVRR_HDMI_VRR: params["id"] = port; - params["gameFeature"] = "VRR-HDMI"; + params["gameFeature"] = VRR_TYPE_HDMI; params["mode"] = vrr_mode; break; case dsVRR_AMD_FREESYNC: params["id"] = port; - params["gameFeature"] = "VRR-FREESYNC"; + params["gameFeature"] = VRR_TYPE_FREESYNC; params["mode"] = vrr_mode; break; case dsVRR_AMD_FREESYNC_PREMIUM: params["id"] = port; - params["gameFeature"] = "VRR-FREESYNC-PREMIUM"; + params["gameFeature"] = VRR_TYPE_FREESYNC_PREMIUM; params["mode"] = vrr_mode; break; case dsVRR_AMD_FREESYNC_PREMIUM_PRO: params["id"] = port; - params["gameFeature"] = "VRR-FREESYNC-PREMIUM-PRO"; + params["gameFeature"] = VRR_TYPE_FREESYNC_PREMIUM_PRO; params["mode"] = vrr_mode; break; default: @@ -1137,13 +1137,13 @@ uint32_t AVInput::getGameFeatureStatusWrapper(const JsonObject& parameters, Json returnResponse(false); } - if (strcmp (sGameFeature.c_str(), "ALLM") == 0) + if (strcmp (sGameFeature.c_str(), STR_ALLM) == 0) { bool allm = getALLMStatus(portId); LOGWARN("AVInput::getGameFeatureStatusWrapper ALLM MODE:%d", allm); response["mode"] = allm; } - else if(strcmp (sGameFeature.c_str(), "VRR-HDMI") == 0) + else if(strcmp (sGameFeature.c_str(), VRR_TYPE_HDMI) == 0) { bool hdmi_vrr = false; dsHdmiInVrrStatus_t vrrStatus; @@ -1153,7 +1153,7 @@ uint32_t AVInput::getGameFeatureStatusWrapper(const JsonObject& parameters, Json LOGWARN("AVInput::getGameFeatureStatusWrapper HDMI VRR MODE:%d", hdmi_vrr); response["mode"] = hdmi_vrr; } - else if(strcmp (sGameFeature.c_str(), "VRR-FREESYNC") == 0) + else if(strcmp (sGameFeature.c_str(), VRR_TYPE_FREESYNC) == 0) { bool freesync = false; dsHdmiInVrrStatus_t vrrStatus; @@ -1163,7 +1163,7 @@ uint32_t AVInput::getGameFeatureStatusWrapper(const JsonObject& parameters, Json LOGWARN("AVInput::getGameFeatureStatusWrapper FREESYNC MODE:%d", freesync); response["mode"] = freesync; } - else if(strcmp (sGameFeature.c_str(), "VRR-FREESYNC-PREMIUM") == 0) + else if(strcmp (sGameFeature.c_str(), VRR_TYPE_FREESYNC_PREMIUM) == 0) { bool freesync_premium = false; dsHdmiInVrrStatus_t vrrStatus; @@ -1173,7 +1173,7 @@ uint32_t AVInput::getGameFeatureStatusWrapper(const JsonObject& parameters, Json LOGWARN("AVInput::getGameFeatureStatusWrapper FREESYNC PREMIUM MODE:%d", freesync_premium); response["mode"] = freesync_premium; } - else if(strcmp (sGameFeature.c_str(), "VRR-FREESYNC-PREMIUM-PRO") == 0) + else if(strcmp (sGameFeature.c_str(), VRR_TYPE_FREESYNC_PREMIUM_PRO) == 0) { bool freesync_premium_pro = false; dsHdmiInVrrStatus_t vrrStatus; From f7638f052616c77463c9c921aaa2d17b2ed5b5f0 Mon Sep 17 00:00:00 2001 From: aishwariya15 <75303024+aishwariya15@users.noreply.github.com> Date: Wed, 11 Jun 2025 21:57:39 +0530 Subject: [PATCH 07/52] RDKEMW-5124: Higher framerate support in Thunder (#134) --- AVInput/AVInput.cpp | 25 ++++++++++++++++++++++++- HdmiInput/HdmiInput.cpp | 25 ++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/AVInput/AVInput.cpp b/AVInput/AVInput.cpp index 8c71c7a6..fccde076 100644 --- a/AVInput/AVInput.cpp +++ b/AVInput/AVInput.cpp @@ -868,7 +868,30 @@ void AVInput::AVInputVideoModeUpdate( int port , dsVideoPortResolution_t resolut params["frameRateN"] = 60000; params["frameRateD"] = 1001; break; - + case dsVIDEO_FRAMERATE_100: + params["frameRateN"] = 100000; + params["frameRateD"] = 1000; + break; + case dsVIDEO_FRAMERATE_119dot88: + params["frameRateN"] = 120000; + params["frameRateD"] = 1001; + break; + case dsVIDEO_FRAMERATE_120: + params["frameRateN"] = 120000; + params["frameRateD"] = 1000; + break; + case dsVIDEO_FRAMERATE_200: + params["frameRateN"] = 200000; + params["frameRateD"] = 1000; + break; + case dsVIDEO_FRAMERATE_239dot76: + params["frameRateN"] = 240000; + params["frameRateD"] = 1001; + break; + case dsVIDEO_FRAMERATE_240: + params["frameRateN"] = 240000; + params["frameRateD"] = 100; + break; default: params["frameRateN"] = 60000; params["frameRateD"] = 1000; diff --git a/HdmiInput/HdmiInput.cpp b/HdmiInput/HdmiInput.cpp index e45efa09..ef53a03a 100644 --- a/HdmiInput/HdmiInput.cpp +++ b/HdmiInput/HdmiInput.cpp @@ -718,7 +718,30 @@ namespace WPEFramework params["frameRateN"] = 60000; params["frameRateD"] = 1001; break; - + case dsVIDEO_FRAMERATE_100: + params["frameRateN"] = 100000; + params["frameRateD"] = 1000; + break; + case dsVIDEO_FRAMERATE_119dot88: + params["frameRateN"] = 120000; + params["frameRateD"] = 1001; + break; + case dsVIDEO_FRAMERATE_120: + params["frameRateN"] = 120000; + params["frameRateD"] = 1000; + break; + case dsVIDEO_FRAMERATE_200: + params["frameRateN"] = 200000; + params["frameRateD"] = 1000; + break; + case dsVIDEO_FRAMERATE_239dot76: + params["frameRateN"] = 240000; + params["frameRateD"] = 1001; + break; + case dsVIDEO_FRAMERATE_240: + params["frameRateN"] = 240000; + params["frameRateD"] = 100; + break; default: params["frameRateN"] = 60000; params["frameRateD"] = 1000; From 6b11c5b379c1bfdfc533fc090d73245d4cfe264e Mon Sep 17 00:00:00 2001 From: apatel859 Date: Wed, 11 Jun 2025 16:39:37 +0000 Subject: [PATCH 08/52] 1.1.1 release change log updates --- CHANGELOG.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73149475..cfb49314 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,20 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.1.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.1.0...1.1.1) + +- RDKEMW-5124: Higher framerate support in Thunder [`#134`](https://github.com/rdkcentral/entservices-inputoutput/pull/134) +- RDK-57440: Enable HdcpProfile for contract test [`#132`](https://github.com/rdkcentral/entservices-inputoutput/pull/132) +- [RDKEMW-2711] RDKEMW-4232: Moving the L2 Test files to specific entservices for inputoutput repo [`#123`](https://github.com/rdkcentral/entservices-inputoutput/pull/123) +- RDKEMW-4196: Cleanup and remove pwrmgr references from workflows [`#126`](https://github.com/rdkcentral/entservices-inputoutput/pull/126) +- RDKEMW-4220: Fix wpeframework crash on reactivating plugin and powerstate change [`#104`](https://github.com/rdkcentral/entservices-inputoutput/pull/104) +- RDKEMW-4139: Coverity integration with Entservices-inputoutput repo [`#116`](https://github.com/rdkcentral/entservices-inputoutput/pull/116) +- Merge tag '1.1.0' into develop [`2ce89ed`](https://github.com/rdkcentral/entservices-inputoutput/commit/2ce89edb2c300ecc3275fab6673b48823578d053) + #### [1.1.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.0.12...1.1.0) +> 20 May 2025 + - RDK-52028 : Add CMS,WB,ALS to AVOutput (#6139) [`#23`](https://github.com/rdkcentral/entservices-inputoutput/pull/23) - [RDKEMW-2711] RDKEMW-4232: Moving the L2 Test files to entservices-inputoutput [`#107`](https://github.com/rdkcentral/entservices-inputoutput/pull/107) - [RDKEMW-2711] RDKEMW-3851: L1 - Move plugins Unit test to inputoutput repo [`#92`](https://github.com/rdkcentral/entservices-inputoutput/pull/92) @@ -14,6 +26,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - RDK-55554 : Gtest for HdmiCecSource and sink [`#78`](https://github.com/rdkcentral/entservices-inputoutput/pull/78) - RDK-55373:[RDKServices] Coverity integration with middleware componen… [`#96`](https://github.com/rdkcentral/entservices-inputoutput/pull/96) - RDK-55373:[RDKServices] Coverity integration with middleware component workflow [`#94`](https://github.com/rdkcentral/entservices-inputoutput/pull/94) +- 1.1.0 release changelog updates [`d6c91fa`](https://github.com/rdkcentral/entservices-inputoutput/commit/d6c91fa3fb9bda7e296ce9321921cc8882b2d50d) - Merge tag '1.0.12' into develop [`2019c9f`](https://github.com/rdkcentral/entservices-inputoutput/commit/2019c9f8d72eba911fe9030cf4476ce99c2127de) #### [1.0.12](https://github.com/rdkcentral/entservices-inputoutput/compare/1.0.11...1.0.12) @@ -74,10 +87,15 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Enabling workflow for L1 and L2 [`4049a2e`](https://github.com/rdkcentral/entservices-inputoutput/commit/4049a2eb188efede1c1547be50847d29ddcb9e03) - Merge tag '1.0.6' into develop [`f46b084`](https://github.com/rdkcentral/entservices-inputoutput/commit/f46b084ed21e61d89e20868eacdea4ba8198266d) -#### [1.0.6](https://github.com/rdkcentral/entservices-inputoutput/compare/1.0.5...1.0.6) +#### [1.0.6](https://github.com/rdkcentral/entservices-inputoutput/compare/1.0.6-RDK7.1...1.0.6) > 27 March 2025 +#### [1.0.6-RDK7.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.0.5...1.0.6-RDK7.1) + +> 22 May 2025 + +- RDKEMW-4220: Fix wpeframework crash on reactivating plugin and powerstate change [`#104`](https://github.com/rdkcentral/entservices-inputoutput/pull/104) - Removed Cec host header [`#35`](https://github.com/rdkcentral/entservices-inputoutput/pull/35) - 1.0.9 release change log updates [`8abd094`](https://github.com/rdkcentral/entservices-inputoutput/commit/8abd09439355af4041436e562c4590769b55bc0c) - Merge tag '1.0.5' into develop [`3b26eeb`](https://github.com/rdkcentral/entservices-inputoutput/commit/3b26eebfdf0e992e369e5cd3cdc981748c9cdb69) From 7cf1b00de11ca8277732026b9859bff4f7a329da Mon Sep 17 00:00:00 2001 From: Prathyushakothuru <142974139+Prathyushakothuru@users.noreply.github.com> Date: Thu, 12 Jun 2025 15:33:44 +0530 Subject: [PATCH 09/52] [RDKEMW-2711] RDKEMW-4650: Enabling the L1/L2 test in the Testframework (#130) * input output cmake changes * enable L2 test * test_foo execution * t_foo modifications * adding one more include * retrigger * change to develop * pointing to local branch * pointing to testframework branch * retrigger * modify test_foo * change the dummy test name * error in test_foo * removing one flag from cmake * enable AVOUTPUT * disable the plugin * retrigger * retrigger * remove duplicate * enable HDMI INPUT AND AV INPUT * cmake modification * pointing to develop * comment hdcp --- .github/workflows/L1-tests.yml | 38 ++++++++++++++++++++++-- .github/workflows/L2-tests.yml | 36 ++++++++++++++++++++-- Tests/L1Tests/CMakeLists.txt | 20 ++++++------- Tests/L1Tests/tests/test_HdcpProfile.cpp | 3 ++ Tests/L2Tests/CMakeLists.txt | 16 ++++------ Tests/L2Tests/tests/test_foo_IN.cpp | 10 +++++++ 6 files changed, 95 insertions(+), 28 deletions(-) create mode 100755 Tests/L2Tests/tests/test_foo_IN.cpp diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 259d11b7..9366eaa5 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -2,9 +2,9 @@ name: L1-tests on: push: - branches: [ main, develop, 'sprint/**', 'release/**', 'topic/RDK*' ] + branches: [ main, develop, 'sprint/**', 'release/**' ] pull_request: - branches: [ main, develop, 'sprint/**', 'release/**', 'topic/RDK*' ] + branches: [ main, develop, 'sprint/**', 'release/**' ] env: BUILD_TYPE: Debug @@ -121,6 +121,14 @@ jobs: with: path: entservices-inputoutput + - name: Checkout googletest + if: steps.cache.outputs.cache-hit != 'true' + uses: actions/checkout@v3 + with: + repository: google/googletest + path: googletest + ref: v1.15.0 + - name: Apply patches ThunderTools run: | cd $GITHUB_WORKSPACE/ThunderTools @@ -342,6 +350,22 @@ jobs: && cmake --install build/mocks + - name: Build googletest + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake -G Ninja + -S "$GITHUB_WORKSPACE/googletest" + -B build/googletest + -DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/install/usr" + -DCMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" + -DGENERIC_CMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" + -DBUILD_TYPE=Debug + -DBUILD_GMOCK=ON + && + cmake --build build/googletest -j8 + && + cmake --install build/googletest + - name: Build entservices-inputoutput run: > cmake -G Ninja @@ -368,6 +392,8 @@ jobs: -I $GITHUB_WORKSPACE/entservices-testframework/Tests -I $GITHUB_WORKSPACE/Thunder/Source -I $GITHUB_WORKSPACE/Thunder/Source/core + -I $GITHUB_WORKSPACE/install/usr/include + -I $GITHUB_WORKSPACE/install/usr/include/WPEFramework -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Iarm.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Rfc.h @@ -406,6 +432,8 @@ jobs: -DDS_FOUND=ON -DHAS_FRONT_PANEL=ON -DRDK_SERVICES_L1_TEST=ON + -DPLUGIN_AVINPUT=ON + -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON -DPLUGIN_HDMICECSINK=ON @@ -443,6 +471,8 @@ jobs: -I $GITHUB_WORKSPACE/entservices-testframework/Tests -I $GITHUB_WORKSPACE/Thunder/Source -I $GITHUB_WORKSPACE/Thunder/Source/core + -I $GITHUB_WORKSPACE/install/usr/include + -I $GITHUB_WORKSPACE/install/usr/include/WPEFramework -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Iarm.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Rfc.h @@ -459,7 +489,7 @@ jobs: -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/thunder/Communicator.h --coverage -Wall -Wno-unused-result -Wno-deprecated-declarations -Wno-error=format= - -Wl,-wrap,system -Wl,-wrap,popen -Wl,-wrap,syslog + -Wl,-wrap,system -Wl,-wrap,popen -Wl,-wrap,syslog -Wl,--no-as-needed -DENABLE_TELEMETRY_LOGGING -DUSE_IARMBUS -DENABLE_SYSTEM_GET_STORE_DEMO_LINK @@ -480,6 +510,8 @@ jobs: -DCMAKE_DISABLE_FIND_PACKAGE_CEC=ON -DCMAKE_BUILD_TYPE=Debug -DDS_FOUND=ON + -DPLUGIN_AVINPUT=ON + -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON -DPLUGIN_HDMICECSINK=ON diff --git a/.github/workflows/L2-tests.yml b/.github/workflows/L2-tests.yml index 7224e70b..4d1bd361 100755 --- a/.github/workflows/L2-tests.yml +++ b/.github/workflows/L2-tests.yml @@ -1,9 +1,10 @@ name: L2-tests -#enable the workflow incase of any plugin/testcase changes -#Add "Tests/L2Tests" subdirectory in CMakeLists.txt, when enabling L2Tests on: - workflow_dispatch: + push: + branches: [ main, develop, 'sprint/**', 'release/**' ] + pull_request: + branches: [ main, develop, 'sprint/**', 'release/**' ] env: BUILD_TYPE: Debug @@ -90,6 +91,14 @@ jobs: ref: develop token: ${{ secrets.RDKCM_RDKE }} + - name: Checkout googletest + if: steps.cache.outputs.cache-hit != 'true' + uses: actions/checkout@v3 + with: + repository: google/googletest + path: googletest + ref: v1.15.0 + - name: Apply patches ThunderTools run: | cd $GITHUB_WORKSPACE/ThunderTools @@ -248,6 +257,22 @@ jobs: && cmake --install build/mocks + - name: Build googletest + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake -G Ninja + -S "$GITHUB_WORKSPACE/googletest" + -B build/googletest + -DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/install/usr" + -DCMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" + -DGENERIC_CMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" + -DBUILD_TYPE=Debug + -DBUILD_GMOCK=ON + && + cmake --build build/googletest -j8 + && + cmake --install build/googletest + - name: Build entservices-inputoutput run: > cmake @@ -274,6 +299,8 @@ jobs: -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/iarmmgrs-hal -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices/proc + -I $GITHUB_WORKSPACE/install/usr/include + -I $GITHUB_WORKSPACE/install/usr/include/WPEFramework -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Iarm.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Rfc.h @@ -365,6 +392,8 @@ jobs: -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices/proc -I $GITHUB_WORKSPACE/entservices-deviceanddisplay/helpers + -I $GITHUB_WORKSPACE/install/usr/include + -I $GITHUB_WORKSPACE/install/usr/include/WPEFramework -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Iarm.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Rfc.h @@ -384,6 +413,7 @@ jobs: -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvSettingsODM.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvTypes.h -Werror -Wall -Wno-unused-result -Wno-deprecated-declarations -Wno-error=format= + -Wl,--no-as-needed -DUSE_IARMBUS -DRDK_SERVICE_L2_TEST -DDISABLE_SECURITY_TOKEN diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index 33773882..23762b08 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -19,7 +19,8 @@ cmake_minimum_required(VERSION 3.8) set(PLUGIN_NAME L1TestsIO) set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(${NAMESPACE}Plugins REQUIRED) @@ -27,16 +28,7 @@ set (TEST_SRC tests/test_UtilsFile.cpp ) -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/e39786088138f2749d64e9e90e0f9902daa77c40.zip -) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -FetchContent_MakeAvailable(googletest) - set (TEST_LIB - gmock_main ${NAMESPACE}Plugins::${NAMESPACE}Plugins ) @@ -136,6 +128,12 @@ add_plugin_test_ex(PLUGIN_AVINPUT tests/test_AVInput.cpp "${AVINPUT_INC}" "${NAM add_library(${MODULE_NAME} SHARED ${TEST_SRC}) +set_source_files_properties( + tests/test_HdmiCec2.cpp + tests/test_HdmiCecSource.cpp + tests/test_HdmiCecSink.cpp + PROPERTIES COMPILE_FLAGS "-fexceptions") + if (RDK_SERVICES_L1_TEST) find_library(TESTMOCKLIB_LIBRARIES NAMES L1TestMocklib) if (TESTMOCKLIB_LIBRARIES) @@ -148,7 +146,7 @@ endif (RDK_SERVICES_L1_TEST) include_directories(${TEST_INC}) -target_link_directories(${MODULE_NAME} PUBLIC ${CMAKE_INSTALL_PREFIX}/lib/wpeframework/plugins) +target_link_directories(${MODULE_NAME} PUBLIC ${CMAKE_INSTALL_PREFIX}/lib ${CMAKE_INSTALL_PREFIX}/lib/wpeframework/plugins) target_link_libraries(${MODULE_NAME} ${TEST_LIB}) diff --git a/Tests/L1Tests/tests/test_HdcpProfile.cpp b/Tests/L1Tests/tests/test_HdcpProfile.cpp index f0f6a06f..bec5f9b9 100755 --- a/Tests/L1Tests/tests/test_HdcpProfile.cpp +++ b/Tests/L1Tests/tests/test_HdcpProfile.cpp @@ -378,6 +378,8 @@ TEST_F(HDCPProfileDsTest, getSettopHDCPSupport_Hdcp_v2x) "\\}"))); } +#if 0 + TEST_F(HDCPProfileEventIarmTest, onDisplayConnectionChanged) { ASSERT_TRUE(dsHdmiEventHandler != nullptr); @@ -447,6 +449,7 @@ TEST_F(HDCPProfileEventIarmTest, onDisplayConnectionChanged) EVENT_UNSUBSCRIBE(0, _T("onDisplayConnectionChanged"), _T("client.events"), message); } +#endif TEST_F(HDCPProfileEventIarmTest, onHdmiOutputHDCPStatusEvent) { ASSERT_TRUE(dsHdmiEventHandler != nullptr); diff --git a/Tests/L2Tests/CMakeLists.txt b/Tests/L2Tests/CMakeLists.txt index 7e852330..41cc70f7 100755 --- a/Tests/L2Tests/CMakeLists.txt +++ b/Tests/L2Tests/CMakeLists.txt @@ -19,16 +19,10 @@ set(PLUGIN_NAME L2TestsIO) set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) set(THUNDER_PORT 9998) -#set(CMAKE_CXX_STANDARD 11) + find_package(${NAMESPACE}Plugins REQUIRED) -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/e39786088138f2749d64e9e90e0f9902daa77c40.zip -) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -FetchContent_MakeAvailable(googletest) +set(SRC_FILES tests/test_foo_IN.cpp) if(PLUGIN_AVOUTPUT) set(SRC_FILES ${SRC_FILES} tests/AVOutputTV_L2Test.cpp) @@ -37,7 +31,7 @@ endif() add_library(${MODULE_NAME} SHARED ${SRC_FILES}) set_target_properties(${MODULE_NAME} PROPERTIES - CXX_STANDARD 11 + CXX_STANDARD 14 CXX_STANDARD_REQUIRED YES) target_compile_definitions(${MODULE_NAME} @@ -45,8 +39,8 @@ target_compile_definitions(${MODULE_NAME} MODULE_NAME=Plugin_${PLUGIN_NAME} THUNDER_PORT="${THUNDER_PORT}") -target_compile_options(${MODULE_NAME} PRIVATE -Wno-error) -target_link_libraries(${MODULE_NAME} PRIVATE gmock_main ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +# target_compile_options(${MODULE_NAME} PRIVATE -Wno-error) +target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) if (NOT L2_TEST_OOP_RPC) find_library(TESTMOCKLIB_LIBRARIES NAMES TestMocklib) diff --git a/Tests/L2Tests/tests/test_foo_IN.cpp b/Tests/L2Tests/tests/test_foo_IN.cpp new file mode 100755 index 00000000..9ce95a52 --- /dev/null +++ b/Tests/L2Tests/tests/test_foo_IN.cpp @@ -0,0 +1,10 @@ +#include +#include + +class PrintTestIO : public ::testing::Test { +}; + +// Single test with print statement +TEST_F(PrintTestIO, BasicOutputIO) { + std::cout << "this is a print statement from inputoutput" << std::endl; +} \ No newline at end of file From a72ae3d9d06a5a4b1db7f0eca1df050a3627ba3e Mon Sep 17 00:00:00 2001 From: Kishoredarmaradje <157680313+Kishoredarmaradje@users.noreply.github.com> Date: Fri, 13 Jun 2025 18:34:59 +0530 Subject: [PATCH 10/52] topic/RDK-58099: HdmiCecSink syntax error (#142) --- HdmiCecSink/HdmiCecSink.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HdmiCecSink/HdmiCecSink.cpp b/HdmiCecSink/HdmiCecSink.cpp index 26aef24c..b5150cf8 100644 --- a/HdmiCecSink/HdmiCecSink.cpp +++ b/HdmiCecSink/HdmiCecSink.cpp @@ -2500,7 +2500,7 @@ namespace WPEFramework m_audioStatusReceived = false; m_audioStatusTimerStarted = false; LOGINFO("Audio device removed, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params) + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params); } _instance->deviceList[logicalAddress].m_isRequestRetry = 0; From 8986170c1956a7a678b78c142cd0430bae459c58 Mon Sep 17 00:00:00 2001 From: "neethu.arambilsunny@sky.uk" Date: Mon, 16 Jun 2025 15:17:00 +0100 Subject: [PATCH 11/52] Added L1Tests --- Tests/L1Tests/tests/test_AVInput.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Tests/L1Tests/tests/test_AVInput.cpp b/Tests/L1Tests/tests/test_AVInput.cpp index fae90a90..d5e12f58 100644 --- a/Tests/L1Tests/tests/test_AVInput.cpp +++ b/Tests/L1Tests/tests/test_AVInput.cpp @@ -72,6 +72,9 @@ TEST_F(AVInputTest, RegisteredMethods) EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("contentProtected"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEdid2AllmSupport"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEdid2AllmSupport"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVRRSupport"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVRRSupport"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVRRFrameRate"))); } TEST_F(AVInputTest, contentProtected) @@ -111,3 +114,21 @@ TEST_F(AVInputDsTest, setEdid2AllmSupport) EXPECT_EQ(response, string("{\"success\":true}")); } +TEST_F(AVInputDsTest, getVRRSupport) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVRRSupport"), _T("{\"portId\": \"0\",\"vrrSupport\":true}"), response)); + EXPECT_EQ(response, string("{\"vrrSupport\":true,\"success\":true}")); +} + +TEST_F(AVInputDsTest, setVRRSupport) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVRRSupport"), _T("{\"portId\": \"0\",\"vrrSupport\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputDsTest, getVRRFrameRate) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVRRFrameRate"), _T("{\"portId\": \"0\",\"currentVRRVideoFrameRate\":48.6}"), response)); + EXPECT_EQ(response, string("{\"currentVRRVideoFrameRate\":48.6,\"success\":true}")); +} + From 06cdde8f5f90883cd99f3092081ed60d436a7ff8 Mon Sep 17 00:00:00 2001 From: neethuas379 Date: Mon, 16 Jun 2025 22:28:41 +0530 Subject: [PATCH 12/52] Update test_AVInput.cpp --- Tests/L1Tests/tests/test_AVInput.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/L1Tests/tests/test_AVInput.cpp b/Tests/L1Tests/tests/test_AVInput.cpp index d5e12f58..a82e2d21 100644 --- a/Tests/L1Tests/tests/test_AVInput.cpp +++ b/Tests/L1Tests/tests/test_AVInput.cpp @@ -128,7 +128,7 @@ TEST_F(AVInputDsTest, setVRRSupport) TEST_F(AVInputDsTest, getVRRFrameRate) { - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVRRFrameRate"), _T("{\"portId\": \"0\",\"currentVRRVideoFrameRate\":48.6}"), response)); - EXPECT_EQ(response, string("{\"currentVRRVideoFrameRate\":48.6,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVRRFrameRate"), _T("{\"portId\": \"0\"}"), response)); + EXPECT_EQ(response, string("{\"currentVRRVideoFrameRate\":0,\"success\":true}")); } From 1c37f749067cb176609e6613cf23f401b170920b Mon Sep 17 00:00:00 2001 From: neethuas379 Date: Mon, 16 Jun 2025 22:30:57 +0530 Subject: [PATCH 13/52] Update AVInput.cpp --- AVInput/AVInput.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/AVInput/AVInput.cpp b/AVInput/AVInput.cpp index bee90af4..c7586702 100644 --- a/AVInput/AVInput.cpp +++ b/AVInput/AVInput.cpp @@ -1616,6 +1616,7 @@ uint32_t AVInput::getVRRFrameRateWrapper(const JsonObject& parameters, JsonObjec int portId = 0; dsHdmiInVrrStatus_t vrrStatus; + vrrStatus.vrrAmdfreesyncFramerate_Hz = 0; try { portId = stoi(sPortId); From 80c66cfd9e96e17b98eb219d2dc9a64210653829 Mon Sep 17 00:00:00 2001 From: agampa263 <133222558+agampa263@users.noreply.github.com> Date: Tue, 17 Jun 2025 19:57:40 +0530 Subject: [PATCH 14/52] RDKEMW-4135:Coverity integration with Entservices repo (#147) Reason for change: Updating build_dependencies.sh Test Procedure: Verify checks in github Risks: Low Signed-off-by:AkshayKumar_Gampa --- build_dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_dependencies.sh b/build_dependencies.sh index 92d10f7f..cbd25a7f 100644 --- a/build_dependencies.sh +++ b/build_dependencies.sh @@ -31,7 +31,7 @@ git clone --branch R4.4.3 https://github.com/rdkcentral/ThunderTools.git git clone --branch R4.4.1 https://github.com/rdkcentral/Thunder.git -git clone --branch main https://github.com/rdkcentral/entservices-apis.git +git clone --branch develop https://github.com/rdkcentral/entservices-apis.git git clone https://$GITHUB_TOKEN@github.com/rdkcentral/entservices-testframework.git From 1c94f606d197c0a361012043d0077c319d39736f Mon Sep 17 00:00:00 2001 From: siva aditya varma uppalapati Date: Tue, 17 Jun 2025 15:27:39 +0000 Subject: [PATCH 15/52] 1.2.0 release changelog updates --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfb49314..76faba4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,27 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.2.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.1.1...1.2.0) + +- RDKEMW-4135:Coverity integration with Entservices repo [`#147`](https://github.com/rdkcentral/entservices-inputoutput/pull/147) +- RDKEMW-4116 : VRR Feature Middleware changes. [`#103`](https://github.com/rdkcentral/entservices-inputoutput/pull/103) +- topic/RDK-58099: HdmiCecSink syntax error [`#142`](https://github.com/rdkcentral/entservices-inputoutput/pull/142) +- [RDKEMW-2711] RDKEMW-4650: Enabling the L1/L2 test in the Testframework [`#130`](https://github.com/rdkcentral/entservices-inputoutput/pull/130) +- Update AVInput.cpp [`78f58ff`](https://github.com/rdkcentral/entservices-inputoutput/commit/78f58ffebdd7dc34588a2202722758881503600c) +- Added L1Tests [`8986170`](https://github.com/rdkcentral/entservices-inputoutput/commit/8986170c1956a7a678b78c142cd0430bae459c58) +- Update AVInput.cpp [`dcee164`](https://github.com/rdkcentral/entservices-inputoutput/commit/dcee164f26692b92e7d7fadf9b36e1523cd84d69) + #### [1.1.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.1.0...1.1.1) +> 11 June 2025 + - RDKEMW-5124: Higher framerate support in Thunder [`#134`](https://github.com/rdkcentral/entservices-inputoutput/pull/134) - RDK-57440: Enable HdcpProfile for contract test [`#132`](https://github.com/rdkcentral/entservices-inputoutput/pull/132) - [RDKEMW-2711] RDKEMW-4232: Moving the L2 Test files to specific entservices for inputoutput repo [`#123`](https://github.com/rdkcentral/entservices-inputoutput/pull/123) - RDKEMW-4196: Cleanup and remove pwrmgr references from workflows [`#126`](https://github.com/rdkcentral/entservices-inputoutput/pull/126) - RDKEMW-4220: Fix wpeframework crash on reactivating plugin and powerstate change [`#104`](https://github.com/rdkcentral/entservices-inputoutput/pull/104) - RDKEMW-4139: Coverity integration with Entservices-inputoutput repo [`#116`](https://github.com/rdkcentral/entservices-inputoutput/pull/116) +- 1.1.1 release change log updates [`6b11c5b`](https://github.com/rdkcentral/entservices-inputoutput/commit/6b11c5b379c1bfdfc533fc090d73245d4cfe264e) - Merge tag '1.1.0' into develop [`2ce89ed`](https://github.com/rdkcentral/entservices-inputoutput/commit/2ce89edb2c300ecc3275fab6673b48823578d053) #### [1.1.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.0.12...1.1.0) From cf134e8fae9ecc65482b0d86769bc4cf9f1c0f3d Mon Sep 17 00:00:00 2001 From: Srikanth <107277821+srikanth-vv@users.noreply.github.com> Date: Wed, 18 Jun 2025 15:35:32 -0400 Subject: [PATCH 16/52] RDK-57440: Causing config issue for higher versions of cmake (#146) Reason for Change: Added for CT Test Procedure: Check for regressions Risks: Low Priority: P1 --- Tests/L2Tests/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Tests/L2Tests/CMakeLists.txt b/Tests/L2Tests/CMakeLists.txt index 41cc70f7..a142f79e 100755 --- a/Tests/L2Tests/CMakeLists.txt +++ b/Tests/L2Tests/CMakeLists.txt @@ -72,8 +72,3 @@ target_include_directories( ) install(TARGETS ${MODULE_NAME} DESTINATION lib) - -write_config(${PLUGIN_NAME}) - - - From f4a230f1270113d9f1ca50abce58633d15c5b99b Mon Sep 17 00:00:00 2001 From: hgfell683 <107510770+hgfell683@users.noreply.github.com> Date: Fri, 20 Jun 2025 15:29:28 +0000 Subject: [PATCH 17/52] Feature/rdkemw 1015 comrpc (#129) * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC * RDKEMW-1015 : HDMICEC SINK COMRPC --- .github/workflows/L1-tests.yml | 8 +- HdmiCecSink/CMakeLists.txt | 21 +- HdmiCecSink/HdmiCecSink.conf.in | 7 + HdmiCecSink/HdmiCecSink.config | 10 + HdmiCecSink/HdmiCecSink.cpp | 3535 +--------------- HdmiCecSink/HdmiCecSink.h | 886 +--- HdmiCecSink/HdmiCecSinkImplementation.cpp | 3581 +++++++++++++++++ HdmiCecSink/HdmiCecSinkImplementation.h | 755 ++++ HdmiCecSource/HdmiCecSourceImplementation.cpp | 6 +- HdmiCecSource/HdmiCecSourceImplementation.h | 4 +- Tests/L1Tests/CMakeLists.txt | 6 +- Tests/L1Tests/tests/test_HdmiCecSource.cpp | 2 +- 12 files changed, 4662 insertions(+), 4159 deletions(-) create mode 100644 HdmiCecSink/HdmiCecSinkImplementation.cpp create mode 100644 HdmiCecSink/HdmiCecSinkImplementation.h diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 9366eaa5..d5748acf 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -435,8 +435,8 @@ jobs: -DPLUGIN_AVINPUT=ON -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON - -DPLUGIN_HDMICECSOURCE=ON - -DPLUGIN_HDMICECSINK=ON + -DPLUGIN_HDMICECSOURCE=OFF + -DPLUGIN_HDMICECSINK=OFF -DUSE_THUNDER_R4=ON -DHIDE_NON_EXTERNAL_SYMBOLS=OFF && @@ -513,8 +513,8 @@ jobs: -DPLUGIN_AVINPUT=ON -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON - -DPLUGIN_HDMICECSOURCE=ON - -DPLUGIN_HDMICECSINK=ON + -DPLUGIN_HDMICECSOURCE=OFF + -DPLUGIN_HDMICECSINK=OFF -DRDK_SERVICES_L1_TEST=ON -DUSE_THUNDER_R4=ON -DHIDE_NON_EXTERNAL_SYMBOLS=OFF diff --git a/HdmiCecSink/CMakeLists.txt b/HdmiCecSink/CMakeLists.txt index b244641e..11e12e6f 100644 --- a/HdmiCecSink/CMakeLists.txt +++ b/HdmiCecSink/CMakeLists.txt @@ -16,6 +16,7 @@ # limitations under the License. set(PLUGIN_NAME HdmiCecSink) set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) +set(PLUGIN_IMPLEMENTATION ${MODULE_NAME}Implementation) set(PLUGIN_HDMICECSINK_STARTUPORDER "" CACHE STRING "To configure startup order of HdmiCecSink plugin") @@ -26,10 +27,18 @@ add_library(${MODULE_NAME} SHARED HdmiCecSink.cpp Module.cpp) +add_library(${PLUGIN_IMPLEMENTATION} SHARED + HdmiCecSinkImplementation.cpp + Module.cpp) + set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES) +set_target_properties(${PLUGIN_IMPLEMENTATION} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + target_compile_definitions(${MODULE_NAME} PRIVATE MODULE_NAME=Plugin_${PLUGIN_NAME}) find_package(DS) @@ -41,13 +50,23 @@ target_include_directories(${MODULE_NAME} PRIVATE ${CEC_INCLUDE_DIRS}) target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) set_source_files_properties(HdmiCecSink.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") + +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${CEC_INCLUDE_DIRS}) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${DS_INCLUDE_DIRS}) +set_source_files_properties(HdmiCecSinkImplementation.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") + target_link_libraries(${MODULE_NAME} PUBLIC ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${CEC_LIBRARIES} ${DS_LIBRARIES} ) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PUBLIC ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${CEC_LIBRARIES} ${DS_LIBRARIES} ) if (NOT RDK_SERVICES_L1_TEST) - target_compile_options(${MODULE_NAME} PRIVATE -Wno-error=deprecated) + target_compile_options(${PLUGIN_IMPLEMENTATION} PRIVATE -Wno-error=deprecated) endif () install(TARGETS ${MODULE_NAME} DESTINATION lib/${STORAGE_DIRECTORY}/plugins) +install(TARGETS ${PLUGIN_IMPLEMENTATION} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + write_config(${PLUGIN_NAME}) diff --git a/HdmiCecSink/HdmiCecSink.conf.in b/HdmiCecSink/HdmiCecSink.conf.in index de8e1cdf..646c4430 100644 --- a/HdmiCecSink/HdmiCecSink.conf.in +++ b/HdmiCecSink/HdmiCecSink.conf.in @@ -2,3 +2,10 @@ precondition = ["Platform"] callsign = "org.rdk.HdmiCecSink" autostart = "false" startuporder = "@PLUGIN_HDMICECSINK_STARTUPORDER@" + +configuration = JSON() +rootobject = JSON() + +rootobject.add("mode", "@PLUGIN_HDMICECSINK_MODE@") +rootobject.add("locator", "lib@PLUGIN_IMPLEMENTATION@.so") +configuration.add("root", rootobject) \ No newline at end of file diff --git a/HdmiCecSink/HdmiCecSink.config b/HdmiCecSink/HdmiCecSink.config index 13ed0788..7257c9e8 100644 --- a/HdmiCecSink/HdmiCecSink.config +++ b/HdmiCecSink/HdmiCecSink.config @@ -5,3 +5,13 @@ set (callsign "org.rdk.HdmiCecSink") if(PLUGIN_HDMICECSINK_STARTUPORDER) set (startuporder ${PLUGIN_HDMICECSINK_STARTUPORDER}) endif() + + +map() + key(root) + map() + kv(mode ${PLUGIN_HDMICECSOURCE_MODE}) + kv(locator lib${PLUGIN_IMPLEMENTATION}.so) + end() +end() +ans(configuration) diff --git a/HdmiCecSink/HdmiCecSink.cpp b/HdmiCecSink/HdmiCecSink.cpp index b5150cf8..a7e08588 100644 --- a/HdmiCecSink/HdmiCecSink.cpp +++ b/HdmiCecSink/HdmiCecSink.cpp @@ -19,159 +19,14 @@ #include "HdmiCecSink.h" -#include "ccec/Connection.hpp" -#include "ccec/CECFrame.hpp" -#include "ccec/MessageEncoder.hpp" -#include "host.hpp" -#include "UtilsgetRFCConfig.h" - -#include "dsMgr.h" -#include "dsRpc.h" -#include "dsDisplay.h" -#include "videoOutputPort.hpp" -#include "manager.hpp" -#include "websocket/URL.h" - #include "UtilsIarm.h" #include "UtilsJsonRpc.h" #include "UtilssyncPersistFile.h" #include "UtilsSearchRDKProfile.h" -#define HDMICECSINK_METHOD_SET_ENABLED "setEnabled" -#define HDMICECSINK_METHOD_GET_ENABLED "getEnabled" -#define HDMICECSINK_METHOD_OTP_SET_ENABLED "setOTPEnabled" -#define HDMICECSINK_METHOD_OTP_GET_ENABLED "getOTPEnabled" -#define HDMICECSINK_METHOD_SET_OSD_NAME "setOSDName" -#define HDMICECSINK_METHOD_GET_OSD_NAME "getOSDName" -#define HDMICECSINK_METHOD_SET_VENDOR_ID "setVendorId" -#define HDMICECSINK_METHOD_GET_VENDOR_ID "getVendorId" -#define HDMICECSINK_METHOD_PRINT_DEVICE_LIST "printDeviceList" -#define HDMICECSINK_METHOD_SET_ACTIVE_PATH "setActivePath" -#define HDMICECSINK_METHOD_SET_ROUTING_CHANGE "setRoutingChange" -#define HDMICECSINK_METHOD_GET_DEVICE_LIST "getDeviceList" -#define HDMICECSINK_METHOD_GET_ACTIVE_SOURCE "getActiveSource" -#define HDMICECSINK_METHOD_SET_ACTIVE_SOURCE "setActiveSource" -#define HDMICECSINK_METHOD_GET_ACTIVE_ROUTE "getActiveRoute" -#define HDMICECSINK_METHOD_SET_MENU_LANGUAGE "setMenuLanguage" -#define HDMICECSINK_METHOD_REQUEST_ACTIVE_SOURCE "requestActiveSource" -#define HDMICECSINK_METHOD_SETUP_ARC "setupARCRouting" -#define HDMICECSINK_METHOD_REQUEST_SHORT_AUDIO_DESCRIPTOR "requestShortAudioDescriptor" -#define HDMICECSINK_METHOD_SEND_STANDBY_MESSAGE "sendStandbyMessage" -#define HDMICECSINK_METHOD_SEND_AUDIO_DEVICE_POWER_ON "sendAudioDevicePowerOnMessage" -#define HDMICECSINK_METHOD_SEND_KEY_PRESS "sendKeyPressEvent" -#define HDMICECSINK_METHOD_SEND_USER_CONTROL_PRESSED "sendUserControlPressed" -#define HDMICECSINK_METHOD_SEND_USER_CONTROL_RELEASED "sendUserControlReleased" -#define HDMICECSINK_METHOD_SEND_GIVE_AUDIO_STATUS "sendGetAudioStatusMessage" -#define HDMICECSINK_METHOD_GET_AUDIO_DEVICE_CONNECTED_STATUS "getAudioDeviceConnectedStatus" -#define HDMICECSINK_METHOD_REQUEST_AUDIO_DEVICE_POWER_STATUS "requestAudioDevicePowerStatus" -#define HDMICECSINK_METHOD_SET_LATENCY_INFO "setLatencyInfo" - -#define TEST_ADD 0 -#define HDMICECSINK_REQUEST_MAX_RETRY 3 -#define HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS 2000 -#define HDMICECSINK_PING_INTERVAL_MS 10000 -#define HDMICECSINK_WAIT_FOR_HDMI_IN_MS 1000 -#define HDMICECSINK_REQUEST_INTERVAL_TIME_MS 500 -#define HDMICECSINK_NUMBER_TV_ADDR 2 -#define HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS (60 * 1000) -#define HDMISINK_ARC_START_STOP_MAX_WAIT_MS 4000 -#define HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS 500 - - -#define SAD_FMT_CODE_AC3 2 -#define SAD_FMT_CODE_ENHANCED_AC3 10 - -#define SYSTEM_AUDIO_MODE_ON 0x01 -#define SYSTEM_AUDIO_MODE_OFF 0x00 -#define AUDIO_DEVICE_POWERSTATE_OFF 1 - -#define DEFAULT_VIDEO_LATENCY 100 -#define DEFAULT_LATENCY_FLAGS 3 -#define DEFAULT_AUDIO_OUTPUT_DELAY 100 - -//Device Type is TV - Bit 7 is set to 1 -#define ALL_DEVICE_TYPES 128 - -//RC Profile of TV is 3 - Typical TV Remote -#define RC_PROFILE_TV 10 - -//Device Features supported by TV - ARC Tx -#define DEVICE_FEATURES_TV 4 #define TR181_HDMICECSINK_CEC_VERSION "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.HdmiCecSink.CECVersion" -enum { - DEVICE_POWER_STATE_ON = 0, - DEVICE_POWER_STATE_OFF = 1 -}; - - -enum { - HDMICECSINK_EVENT_ACTIVE_SOURCE_CHANGE = 1, - HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY, - HDMICECSINK_EVENT_TEXT_VIEW_ON_MSG, - HDMICECSINK_EVENT_IMAGE_VIEW_ON_MSG, - HDMICECSINK_EVENT_DEVICE_ADDED, - HDMICECSINK_EVENT_DEVICE_REMOVED, - HDMICECSINK_EVENT_DEVICE_INFO_UPDATED, - HDMICECSINK_EVENT_INACTIVE_SOURCE, - HDMICECSINK_EVENT_ARC_INITIATION_EVENT, - HDMICECSINK_EVENT_ARC_TERMINATION_EVENT, - HDMICECSINK_EVENT_SHORT_AUDIODESCRIPTOR_EVENT, - HDMICECSINK_EVENT_STANDBY_MSG_EVENT, - HDMICECSINK_EVENT_SYSTEM_AUDIO_MODE, - HDMICECSINK_EVENT_REPORT_AUDIO_STATUS, - HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS, - HDMICECSINK_EVENT_CEC_ENABLED, - HDMICECSINK_EVENT_AUDIO_DEVICE_POWER_STATUS, - HDMICECSINK_EVENT_FEATURE_ABORT_EVENT, -}; - -static const char *eventString[] = { - "None", - "onActiveSourceChange", - "onWakeupFromStandby", - "onTextViewOnMsg", - "onImageViewOnMsg", - "onDeviceAdded", - "onDeviceRemoved", - "onDeviceInfoUpdated", - "onInActiveSource", - "arcInitiationEvent", - "arcTerminationEvent", - "shortAudiodesciptorEvent", - "standbyMessageReceived", - "setSystemAudioModeEvent", - "reportAudioStatusEvent", - "reportAudioDeviceConnectedStatus", - "reportCecEnabledEvent", - "reportAudioDevicePowerStatus", - "reportFeatureAbortEvent" -}; - - -#define CEC_SETTING_ENABLED_FILE "/opt/persistent/ds/cecData_2.json" -#define CEC_SETTING_OTP_ENABLED "cecOTPEnabled" -#define CEC_SETTING_ENABLED "cecEnabled" -#define CEC_SETTING_OSD_NAME "cecOSDName" -#define CEC_SETTING_VENDOR_ID "cecVendorId" - -static std::vector defaultVendorId = {0x00,0x19,0xFB}; -static VendorID appVendorId = {defaultVendorId.at(0),defaultVendorId.at(1),defaultVendorId.at(2)}; -static VendorID lgVendorId = {0x00,0xE0,0x91}; -static PhysicalAddress physical_addr = {0x0F,0x0F,0x0F,0x0F}; -static LogicalAddress logicalAddress = 0xF; -static Language defaultLanguage = "eng"; -static OSDName osdName = "TV Box"; -static int32_t powerState = DEVICE_POWER_STATE_OFF; -static std::vector formatid = {0,0}; -static std::vector audioFormatCode = { SAD_FMT_CODE_ENHANCED_AC3,SAD_FMT_CODE_AC3 }; -static uint8_t numberofdescriptor = 2; -static int32_t HdmiArcPortID = -1; -static float cecVersion = 1.4; -static AllDeviceTypes allDevicetype = ALL_DEVICE_TYPES; -static std::vector rcProfile = {RC_PROFILE_TV}; -static std::vector deviceFeatures = {DEVICE_FEATURES_TV}; #define API_VERSION_NUMBER_MAJOR 1 #define API_VERSION_NUMBER_MINOR 3 @@ -179,7 +34,7 @@ static std::vector deviceFeatures = {DEVICE_FEATURES_TV}; namespace WPEFramework { - namespace { + namespace { static Plugin::Metadata metadata( // Version (Major, Minor, Patch) @@ -195,3365 +50,119 @@ namespace WPEFramework namespace Plugin { - SERVICE_REGISTRATION(HdmiCecSink, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - - HdmiCecSink* HdmiCecSink::_instance = nullptr; - static int libcecInitStatus = 0; - -//=========================================== HdmiCecSinkFrameListener ========================================= - void HdmiCecSinkFrameListener::notify(const CECFrame &in) const { - const uint8_t *buf = NULL; - char strBuffer[512] = {0}; - size_t len = 0; - - in.getBuffer(&buf, &len); - for (unsigned int i = 0; i < len; i++) { - snprintf(strBuffer + (i*3) , sizeof(strBuffer) - (i*3), "%02X ",(uint8_t) *(buf + i)); - } - LOGINFO(" >>>>> Received CEC Frame: :%s \n",strBuffer); - - MessageDecoder(processor).decode(in); - } - -//=========================================== HdmiCecSinkProcessor ========================================= - void HdmiCecSinkProcessor::process (const ActiveSource &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - HdmiCecSink::_instance->addDevice(header.from.toInt()); - HdmiCecSink::_instance->updateActiveSource(header.from.toInt(), msg); - } - void HdmiCecSinkProcessor::process (const InActiveSource &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: InActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - - HdmiCecSink::_instance->updateInActiveSource(header.from.toInt(), msg); - } - - void HdmiCecSinkProcessor::process (const ImageViewOn &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ImageViewOn from %s\n", header.from.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSink::_instance->addDevice(header.from.toInt()); - HdmiCecSink::_instance->updateImageViewOn(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const TextViewOn &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: TextViewOn\n"); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSink::_instance->addDevice(header.from.toInt()); - HdmiCecSink::_instance->updateTextViewOn(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const RequestActiveSource &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RequestActiveSource\n"); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - - HdmiCecSink::_instance->setActiveSource(true); - } - void HdmiCecSinkProcessor::process (const Standby &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Standby from %s\n", header.from.toString().c_str()); - HdmiCecSink::_instance->SendStandbyMsgEvent(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const GetCECVersion &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GetCECVersion sending CECVersion response \n"); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - if(cecVersion == 2.0) { - conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_2_0))); - } - else{ - conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_1_4))); - } - } - catch(...) - { - LOGWARN("Exception while sending CECVersion "); - } - } - void HdmiCecSinkProcessor::process (const CECVersion &msg, const Header &header) - { - bool updateStatus; - printHeader(header); - LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); - - HdmiCecSink::_instance->addDevice(header.from.toInt()); - updateStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isVersionUpdated; - LOGINFO("updateStatus %d\n",updateStatus); - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.version); - if(!updateStatus) - HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const SetMenuLanguage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const GiveOSDName &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveOSDName sending SetOSDName : %s\n",osdName.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - conn.sendToAsync(header.from, MessageEncoder().encode(SetOSDName(osdName))); - } - catch(...) - { - LOGWARN("Exception while sending SetOSDName"); - } - } - void HdmiCecSinkProcessor::process (const GivePhysicalAddress &msg, const Header &header) - { - LOGINFO("Command: GivePhysicalAddress\n"); - if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) - { - try - { - LOGINFO(" sending ReportPhysicalAddress response physical_addr :%s logicalAddress :%x \n",physical_addr.toString().c_str(), logicalAddress.toInt()); - conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ReportPhysicalAddress(physical_addr,logicalAddress.toInt())), 500); - } - catch(...) - { - LOGWARN("Exception while sending ReportPhysicalAddress "); - } - } - } - void HdmiCecSinkProcessor::process (const GiveDeviceVendorID &msg, const Header &header) - { - printHeader(header); - if(header.to == LogicalAddress(LogicalAddress::BROADCAST)){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n",appVendorId.toString().c_str()); - conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); - } - catch(...) - { - LOGWARN("Exception while sending DeviceVendorID"); - } - - } - void HdmiCecSinkProcessor::process (const SetOSDString &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetOSDString OSDString : %s\n",msg.osdString.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const SetOSDName &msg, const Header &header) - { - printHeader(header); - bool updateStatus ; - LOGINFO("Command: SetOSDName OSDName : %s\n",msg.osdName.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - - HdmiCecSink::_instance->addDevice(header.from.toInt()); - updateStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isOSDNameUpdated; - LOGINFO("updateStatus %d\n",updateStatus); - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.osdName); - if(HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && - HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_OSD_NAME) { - HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; - } - if(!updateStatus) - HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const RoutingChange &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RoutingChange From : %s To: %s \n",msg.from.toString().c_str(),msg.to.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const RoutingInformation &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RoutingInformation Routing Information to Sink : %s\n",msg.toSink.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const SetStreamPath &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetStreamPath Set Stream Path to Sink : %s\n",msg.toSink.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const GetMenuLanguage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GetMenuLanguage\n"); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSink::_instance->sendMenuLanguage(); - } - void HdmiCecSinkProcessor::process (const ReportPhysicalAddress &msg, const Header &header) - { - printHeader(header); - bool updateDeviceTypeStatus; - bool updatePAStatus; - LOGINFO("Command: ReportPhysicalAddress\n"); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - - if(!HdmiCecSink::_instance) - return; - HdmiCecSink::_instance->addDevice(header.from.toInt()); - updateDeviceTypeStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isDeviceTypeUpdated; - updatePAStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isPAUpdated; - LOGINFO("updateDeviceTypeStatus %d updatePAStatus %d \n",updateDeviceTypeStatus,updatePAStatus); - if(HdmiCecSink::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString() != msg.physicalAddress.toString() && updatePAStatus){ - updatePAStatus= false; - LOGINFO("There is a change in physical address from current PA %s to newly reported PA %s\n",HdmiCecSink::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString().c_str(),msg.physicalAddress.toString().c_str()); - } - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.physicalAddress); - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.deviceType); - if(HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && - HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_PHISICAL_ADDRESS) { - HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; - } - HdmiCecSink::_instance->updateDeviceChain(header.from, msg.physicalAddress); - if (!updateDeviceTypeStatus || !updatePAStatus) - HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const DeviceVendorID &msg, const Header &header) - { - bool updateStatus ; - printHeader(header); - LOGINFO("Command: DeviceVendorID VendorID : %s\n",msg.vendorId.toString().c_str()); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - - HdmiCecSink::_instance->addDevice(header.from.toInt()); - updateStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isVendorIDUpdated; - LOGINFO("updateStatus %d\n",updateStatus); - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.vendorId); - if (!updateStatus) - HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const GiveDevicePowerStatus &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveDevicePowerStatus sending powerState :%d \n",powerState); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - conn.sendTo(header.from, MessageEncoder().encode(ReportPowerStatus(PowerStatus(powerState)))); - } - catch(...) - { - LOGWARN("Exception while sending ReportPowerStatus"); - } - } - void HdmiCecSinkProcessor::process (const ReportPowerStatus &msg, const Header &header) - { - uint32_t oldPowerStatus,newPowerStatus; - printHeader(header); - LOGINFO("Command: ReportPowerStatus Power Status from:%s status : %s \n",header.from.toString().c_str(),msg.status.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - oldPowerStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); - HdmiCecSink::_instance->addDevice(header.from.toInt()); - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.status); - newPowerStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); - LOGINFO(" oldPowerStatus %d newpower status %d \n",oldPowerStatus,newPowerStatus); - if ((oldPowerStatus != newPowerStatus) ) - { - HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - - if((header.from.toInt() == LogicalAddress::AUDIO_SYSTEM) && (HdmiCecSink::_instance->m_audioDevicePowerStatusRequested)) { - HdmiCecSink::_instance->reportAudioDevicePowerStatusInfo(header.from.toInt(), newPowerStatus); - } - - } - void HdmiCecSinkProcessor::process (const FeatureAbort &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: FeatureAbort opcode=%s, Reason = %s\n", msg.feature.toString().c_str(), msg.reason.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - - if(header.from.toInt() < LogicalAddress::UNREGISTERED && - msg.reason.toInt() == AbortReason::UNRECOGNIZED_OPCODE) - { - switch(msg.feature.opCode()) - { - case GET_CEC_VERSION : - { - /* If we get a Feature abort for CEC Version then default to 1.4b */ - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(Version(Version::V_1_4)); - } - break; - case GIVE_DEVICE_VENDOR_ID : - { - /* If we get a Feature abort for CEC Version then default to 1.4b */ - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(VendorID((uint8_t *)"FA", 2)); - } - break; - - case GIVE_OSD_NAME : - { - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(OSDName("")); - } - break; - - case GIVE_DEVICE_POWER_STATUS : - { - HdmiCecSink::_instance->deviceList[header.from.toInt()].update(PowerStatus(PowerStatus::POWER_STATUS_FEATURE_ABORT)); - } - break; - } - - HdmiCecSink::_instance->deviceList[header.from.toInt()].m_featureAborts.push_back(msg); - } - - LogicalAddress logicaladdress = header.from.toInt(); - OpCode featureOpcode = msg.feature; - AbortReason abortReason = msg.reason; - - HdmiCecSink::_instance->reportFeatureAbortEvent(logicaladdress,featureOpcode,abortReason); - - if(msg.feature.opCode() == REQUEST_SHORT_AUDIO_DESCRIPTOR) - { - JsonArray audiodescriptor; - audiodescriptor.Add(0); - HdmiCecSink::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); - } - - } - void HdmiCecSinkProcessor::process (const Abort &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Abort\n"); - if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) - { - AbortReason reason = AbortReason::UNRECOGNIZED_OPCODE; - LogicalAddress logicaladdress =header.from.toInt(); - OpCode feature = msg.opCode(); - HdmiCecSink::_instance->sendFeatureAbort(logicaladdress, feature,reason); - } - else - { - LOGINFO("Command: Abort broadcast msg so ignore\n"); - } - } - void HdmiCecSinkProcessor::process (const Polling &msg, const Header &header) { - printHeader(header); - LOGINFO("Command: Polling\n"); - } - - void HdmiCecSinkProcessor::process (const InitiateArc &msg, const Header &header) - { - printHeader(header); - if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ - LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); - return; - } - PhysicalAddress physical_addr_invalid = {0x0F,0x0F,0x0F,0x0F}; - PhysicalAddress physical_addr_arc_port = {0x0F,0x0F,0x0F,0x0F}; - - LOGINFO("Command: INITIATE_ARC \n"); - if(!HdmiCecSink::_instance || HdmiArcPortID == -1) - return; - - if (HdmiArcPortID == 0 ) - physical_addr_arc_port = {0x01,0x00,0x00,0x00}; - if (HdmiArcPortID == 1 ) - physical_addr_arc_port = {0x02,0x00,0x00,0x00}; - if (HdmiArcPortID == 2 ) - physical_addr_arc_port = {0x03,0x00,0x00,0x00}; - - if( (HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_arc_port.toString()) || (HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_invalid.toString()) ) { - LOGINFO("Command: INITIATE_ARC InitiateArc success %s \n",HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); - HdmiCecSink::_instance->Process_InitiateArc(); - } else { - LOGINFO("Command: INITIATE_ARC InitiateArc ignore %s \n",HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); - } - } - void HdmiCecSinkProcessor::process (const TerminateArc &msg, const Header &header) - { - printHeader(header); - if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ - LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); - return; - } - if(!HdmiCecSink::_instance) - return; - HdmiCecSink::_instance->Process_TerminateArc(); - } - void HdmiCecSinkProcessor::process (const ReportShortAudioDescriptor &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ReportShortAudioDescriptor %s : %d \n",GetOpName(msg.opCode()),numberofdescriptor); - HdmiCecSink::_instance->Process_ShortAudioDescriptor_msg(msg); - } - - void HdmiCecSinkProcessor::process (const SetSystemAudioMode &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetSystemAudioMode %s audio status %d audio status is %s \n",GetOpName(msg.opCode()),msg.status.toInt(),msg.status.toString().c_str()); - HdmiCecSink::_instance->Process_SetSystemAudioMode_msg(msg); - } - void HdmiCecSinkProcessor::process (const ReportAudioStatus &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSink::_instance->Process_ReportAudioStatus_msg(msg); - } - void HdmiCecSinkProcessor::process (const GiveFeatures &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveFeatures \n"); - try - { - if(cecVersion == 2.0) { - conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST),MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures))); - } - } - catch(...) - { - LOGWARN("Exception while sending ReportFeatures"); - } - } - void HdmiCecSinkProcessor::process (const RequestCurrentLatency &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Request Current Latency :%s, physical address: %s",GetOpName(msg.opCode()),msg.physicaladdress.toString().c_str()); - - if(msg.physicaladdress.toString() == physical_addr.toString()) { - HdmiCecSink::_instance->setLatencyInfo(); - } - else { - LOGINFO("Physical Address does not match with TV's physical address"); - return; - } - } -//=========================================== HdmiCecSink ========================================= - - HdmiCecSink::HdmiCecSink() - : PluginHost::JSONRPC() - , _pwrMgrNotification(*this) - , _registeredEventHandlers(false) - { - LOGWARN("Initlaizing HdmiCecSink"); - } + SERVICE_REGISTRATION(HdmiCecSink, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - HdmiCecSink::~HdmiCecSink() - { - } const std::string HdmiCecSink::Initialize(PluginHost::IShell *service) { - InitializePowerManager(service); - profileType = searchRdkProfile(); - - if (profileType == STB || profileType == NOT_FOUND) - { - LOGINFO("Invalid profile type for TV \n"); - return (std::string("Not supported")); - } - - HdmiCecSink::_instance = this; - smConnection=NULL; - cecEnableStatus = false; - HdmiCecSink::_instance->m_numberOfDevices = 0; - m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; - m_currentActiveSource = -1; - m_isHdmiInConnected = false; - hdmiCecAudioDeviceConnected = false; - m_isAudioStatusInfoUpdated = false; - m_audioStatusReceived = false; - m_audioStatusTimerStarted = false; - m_audioDevicePowerStatusRequested = false; - m_pollNextState = POLL_THREAD_STATE_NONE; - m_pollThreadState = POLL_THREAD_STATE_NONE; - m_video_latency = DEFAULT_VIDEO_LATENCY; - m_latency_flags = DEFAULT_LATENCY_FLAGS ; - m_audio_output_delay = DEFAULT_AUDIO_OUTPUT_DELAY; - - Register(HDMICECSINK_METHOD_SET_ENABLED, &HdmiCecSink::setEnabledWrapper, this); - Register(HDMICECSINK_METHOD_GET_ENABLED, &HdmiCecSink::getEnabledWrapper, this); - Register(HDMICECSINK_METHOD_SET_OSD_NAME, &HdmiCecSink::setOSDNameWrapper, this); - Register(HDMICECSINK_METHOD_GET_OSD_NAME, &HdmiCecSink::getOSDNameWrapper, this); - Register(HDMICECSINK_METHOD_SET_VENDOR_ID, &HdmiCecSink::setVendorIdWrapper, this); - Register(HDMICECSINK_METHOD_GET_VENDOR_ID, &HdmiCecSink::getVendorIdWrapper, this); - Register(HDMICECSINK_METHOD_PRINT_DEVICE_LIST, &HdmiCecSink::printDeviceListWrapper, this); - Register(HDMICECSINK_METHOD_SET_ACTIVE_PATH, &HdmiCecSink::setActivePathWrapper, this); - Register(HDMICECSINK_METHOD_SET_ROUTING_CHANGE, &HdmiCecSink::setRoutingChangeWrapper, this); - Register(HDMICECSINK_METHOD_GET_DEVICE_LIST, &HdmiCecSink::getDeviceListWrapper, this); - Register(HDMICECSINK_METHOD_GET_ACTIVE_SOURCE, &HdmiCecSink::getActiveSourceWrapper, this); - Register(HDMICECSINK_METHOD_SET_ACTIVE_SOURCE, &HdmiCecSink::setActiveSourceWrapper, this); - Register(HDMICECSINK_METHOD_GET_ACTIVE_ROUTE, &HdmiCecSink::getActiveRouteWrapper, this); - Register(HDMICECSINK_METHOD_REQUEST_ACTIVE_SOURCE, &HdmiCecSink::requestActiveSourceWrapper, this); - Register(HDMICECSINK_METHOD_SETUP_ARC, &HdmiCecSink::setArcEnableDisableWrapper, this); - Register(HDMICECSINK_METHOD_SET_MENU_LANGUAGE, &HdmiCecSink::setMenuLanguageWrapper, this); - Register(HDMICECSINK_METHOD_REQUEST_SHORT_AUDIO_DESCRIPTOR, &HdmiCecSink::requestShortAudioDescriptorWrapper, this); - Register(HDMICECSINK_METHOD_SEND_STANDBY_MESSAGE, &HdmiCecSink::sendStandbyMessageWrapper, this); - Register(HDMICECSINK_METHOD_SEND_AUDIO_DEVICE_POWER_ON, &HdmiCecSink::sendAudioDevicePowerOnMsgWrapper, this); - Register(HDMICECSINK_METHOD_SEND_KEY_PRESS,&HdmiCecSink::sendRemoteKeyPressWrapper,this); - Register(HDMICECSINK_METHOD_SEND_USER_CONTROL_PRESSED,&HdmiCecSink::sendUserControlPressedWrapper,this); - Register(HDMICECSINK_METHOD_SEND_USER_CONTROL_RELEASED,&HdmiCecSink::sendUserControlReleasedWrapper,this); - Register(HDMICECSINK_METHOD_SEND_GIVE_AUDIO_STATUS,&HdmiCecSink::sendGiveAudioStatusWrapper,this); - Register(HDMICECSINK_METHOD_GET_AUDIO_DEVICE_CONNECTED_STATUS,&HdmiCecSink::getAudioDeviceConnectedStatusWrapper,this); - Register(HDMICECSINK_METHOD_REQUEST_AUDIO_DEVICE_POWER_STATUS,&HdmiCecSink::requestAudioDevicePowerStatusWrapper,this); - Register(HDMICECSINK_METHOD_SET_LATENCY_INFO, &HdmiCecSink::setLatencyInfoWrapper, this); - logicalAddressDeviceType = "None"; - logicalAddress = 0xFF; - // load persistence setting - loadSettings(); - - int err; - dsHdmiInGetNumberOfInputsParam_t hdmiInput; - InitializeIARM(); - m_sendKeyEventThreadExit = false; - m_sendKeyEventThread = std::thread(threadSendKeyEvent); - - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - m_semSignaltoArcRoutingThread.acquire(); - m_arcRoutingThread = std::thread(threadArcRouting); - - m_audioStatusDetectionTimer.connect( std::bind( &HdmiCecSink::audioStatusTimerFunction, this ) ); - m_audioStatusDetectionTimer.setSingleShot(true); - m_arcStartStopTimer.connect( std::bind( &HdmiCecSink::arcStartStopTimerFunction, this ) ); - m_arcStartStopTimer.setSingleShot(true); - // get power state: - Core::hresult res = Core::ERROR_GENERAL; - PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - - ASSERT (_powerManagerPlugin); - if (_powerManagerPlugin) { - res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); - if (Core::ERROR_NONE == res) { - powerState = (pwrStateCur == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) ? DEVICE_POWER_STATE_ON : DEVICE_POWER_STATE_OFF; - LOGINFO("Current state is PowerManagerPlugin: (%d) powerState :%d \n", pwrStateCur, powerState); - } - } - - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - IARM_BUS_DSMGR_API_dsHdmiInGetNumberOfInputs, - (void *)&hdmiInput, - sizeof(hdmiInput)); + profileType = searchRdkProfile(); - if (err == IARM_RESULT_SUCCESS && hdmiInput.result == dsERR_NONE) + if (profileType == STB || profileType == NOT_FOUND) { - LOGINFO("Number of Inputs [%d] \n", hdmiInput.numHdmiInputs ); - m_numofHdmiInput = hdmiInput.numHdmiInputs; - }else{ - LOGINFO("Not able to get Numebr of inputs so defaulting to 3 \n"); - m_numofHdmiInput = 3; - } - - LOGINFO("initalize inputs \n"); - - for (int i = 0; i < m_numofHdmiInput; i++){ - HdmiPortMap hdmiPort((uint8_t)i); - LOGINFO(" Add to vector [%d] \n", i); - hdmiInputs.push_back(hdmiPort); - } - - LOGINFO("Check the HDMI State \n"); - - CheckHdmiInState(); - if (cecSettingEnabled) - { - try - { - CECEnable(); - } - catch(...) - { - LOGWARN("Exception while enabling CEC settings .\r\n"); - } - } - getCecVersion(); - LOGINFO(" HdmiCecSink plugin Initialize completed \n"); - return (std::string()); - - } - - void HdmiCecSink::Deinitialize(PluginHost::IShell* /* service */) - { - if(_powerManagerPlugin) - { - _powerManagerPlugin->Unregister(_pwrMgrNotification.baseInterface()); - _powerManagerPlugin.Reset(); - } - _registeredEventHandlers = false; - - profileType = searchRdkProfile(); - - if (profileType == STB || profileType == NOT_FOUND) - { - LOGINFO("Invalid profile type for TV \n"); - return ; - } - - CECDisable(); - m_currentArcRoutingState = ARC_STATE_ARC_EXIT; - - m_semSignaltoArcRoutingThread.release(); - - try - { - if (m_arcRoutingThread.joinable()) - m_arcRoutingThread.join(); - } - catch(const std::system_error& e) - { - LOGERR("system_error exception in thread join %s", e.what()); - } - catch(const std::exception& e) - { - LOGERR("exception in thread join %s", e.what()); - } - - { - m_sendKeyEventThreadExit = true; - std::unique_lock lk(m_sendKeyEventMutex); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - } - - try - { - if (m_sendKeyEventThread.joinable()) - m_sendKeyEventThread.join(); - } - catch(const std::system_error& e) - { - LOGERR("system_error exception in thread join %s", e.what()); - } - catch(const std::exception& e) - { - LOGERR("exception in thread join %s", e.what()); - } - - HdmiCecSink::_instance = nullptr; - DeinitializeIARM(); - LOGWARN(" HdmiCecSink Deinitialize() Done"); - } - - const void HdmiCecSink::InitializeIARM() - { - if (Utils::IARM::init()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); + LOGINFO("Invalid profile type for TV \n"); + return (std::string("Not supported")); } - } - - void HdmiCecSink::DeinitializeIARM() - { - if (Utils::IARM::isConnected()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); - } - } - - void HdmiCecSink::InitializePowerManager(PluginHost::IShell *service) - { - _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) - .withIShell(service) - .withRetryIntervalMS(200) - .withRetryCount(25) - .createInterface(); - registerEventHandlers(); - } - void HdmiCecSink::registerEventHandlers() - { - ASSERT (_powerManagerPlugin); - if(!_registeredEventHandlers && _powerManagerPlugin) { - _registeredEventHandlers = true; - _powerManagerPlugin->Register(_pwrMgrNotification.baseInterface()); - } - } + string msg = ""; - void HdmiCecSink::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiCecSink::_instance) - return; + ASSERT(nullptr != service); + ASSERT(nullptr == _service); + ASSERT(nullptr == _hdmiCecSink); + ASSERT(0 == _connectionId); - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - bool isHdmiConnected = eventData->data.hdmi_in_connect.isPortConnected; - dsHdmiInPort_t portId = eventData->data.hdmi_in_connect.port; - LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG event port: %d data:%d \r\n",portId, isHdmiConnected); - HdmiCecSink::_instance->onHdmiHotPlug(portId,isHdmiConnected); - } - } - void HdmiCecSink::onPowerModeChanged(const PowerState currentState, const PowerState newState) - { - if(!HdmiCecSink::_instance) - return; + _service = service; + _service->AddRef(); + _service->Register(&_notification); + _hdmiCecSink = _service->Root(_connectionId, 5000, _T("HdmiCecSinkImplementation")); - LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", - currentState, newState); - LOGWARN(" m_logicalAddressAllocated 0x%x CEC enable status %d \n",_instance->m_logicalAddressAllocated,_instance->cecEnableStatus); - if(newState == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) + if(nullptr != _hdmiCecSink) { - powerState = DEVICE_POWER_STATE_ON; + _hdmiCecSink->Configure(service); + _hdmiCecSink->Register(&_notification); + Exchange::JHdmiCecSink::Register(*this, _hdmiCecSink); + LOGINFO("HdmiCecSink plugin is available. Successfully activated HdmiCecSink Plugin"); } else { - powerState = DEVICE_POWER_STATE_OFF; - if((_instance->m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_INITIATION) || (_instance->m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) - { - LOGINFO("%s: Stop ARC \n",__FUNCTION__); - _instance->stopArc(); + msg = "HdmiCecSink plugin is not available"; + LOGINFO("HdmiCecSink plugin is not available. Failed to activate HdmiCecSink Plugin"); } - } - if (_instance->cecEnableStatus) - { - if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED ) - { - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); - - if ( powerState != DEVICE_POWER_STATE_ON ) - { - /* reset the current active source when TV on going to standby */ - HdmiCecSink::_instance->m_currentActiveSource = -1; - } - /* Initiate a ping straight away */ - HdmiCecSink::_instance->m_pollNextState = POLL_THREAD_STATE_PING; - HdmiCecSink::_instance->m_ThreadExitCV.notify_one(); - } - } - else + if (0 != msg.length()) { - LOGWARN("CEC not Enabled\n"); + Deinitialize(service); } - } - - - void HdmiCecSink::sendStandbyMessage() - { - if(!HdmiCecSink::_instance) - return; - if(!(HdmiCecSink::_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(Standby()), 1000); - } - - void HdmiCecSink::onHdmiHotPlug(int portId , int connectStatus) - { - LOGINFO("onHdmiHotPlug Status : %d ", connectStatus); - if(!connectStatus) - { - LOGINFO(" removeDevice port: %d Logical address :%d \r\n",portId,hdmiInputs[portId].m_logicalAddr.toInt() ); - _instance->removeDevice(hdmiInputs[portId].m_logicalAddr.toInt()); - } - CheckHdmiInState(); - if(cecEnableStatus) { - LOGINFO("cecEnableStatus : %d Trigger CEC Ping !!! \n", cecEnableStatus); - m_pollNextState = POLL_THREAD_STATE_PING; - m_ThreadExitCV.notify_one(); - } - if( HdmiArcPortID >= 0 ) { - updateArcState(); - } - return; - } - void HdmiCecSink::updateArcState() - { - if ( m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED ) - { - if (!(hdmiInputs[HdmiArcPortID].m_isConnected)) - { - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - } - else - { - LOGINFO("updateArcState :not updating ARC state current arc state %d ",m_currentArcRoutingState); - } - } - } - void HdmiCecSink::arcStartStopTimerFunction() - { - JsonObject params; - - if (m_arcstarting) - { - LOGINFO("arcStartStopTimerFunction ARC start timer expired"); - LOGINFO("notify_device setting that Initiate ARC failed to get the ARC_STATE_ARC_INITIATED state\n"); - params["status"] = string("failure"); - sendNotify(eventString[HDMICECSINK_EVENT_ARC_INITIATION_EVENT], params); - } - else - { - LOGINFO("arcStartStopTimerFunction ARC stop timer expired"); - LOGINFO("notify_device setting that Terminate ARC failed to get the ARC_STATE_ARC_TERMINATED state\n"); - params["status"] = string("failure"); - sendNotify(eventString[HDMICECSINK_EVENT_ARC_TERMINATION_EVENT], params); - - - } - /* bring the state machine to the clean state for a new start */ - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - } - void HdmiCecSink::Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor) - { - JsonObject params; + // On success return empty, to indicate there is no error text. + return msg; + } - LOGINFO("Notify the DS "); - params["ShortAudioDescriptor"]= JsonValue(audiodescriptor); - sendNotify(eventString[HDMICECSINK_EVENT_SHORT_AUDIODESCRIPTOR_EVENT], params); - } - void HdmiCecSink::Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg) + void HdmiCecSink::Deinitialize(PluginHost::IShell* /* service */) { - uint8_t numberofdescriptor = msg.numberofdescriptor; - uint32_t descriptor =0; - JsonArray audiodescriptor; - - if (numberofdescriptor) - { - for( uint8_t i=0; i < numberofdescriptor; i++) - { - descriptor = msg.shortAudioDescriptor[i].getAudiodescriptor(); - - LOGINFO("descriptor%d 0x%x\n",i,descriptor); - audiodescriptor.Add(descriptor); - - } - } - else - { - audiodescriptor.Add(descriptor); - } - HdmiCecSink::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); - } + + profileType = searchRdkProfile(); - void HdmiCecSink::updateCurrentLatency(int videoLatency, bool lowLatencyMode,int audioOutputCompensated, int audioOutputDelay = 0) + if (profileType == STB || profileType == NOT_FOUND) { - uint8_t latencyFlags = 0; - latencyFlags = ((lowLatencyMode & 0x1) << 2) | (audioOutputCompensated & 0x3); - LOGINFO("Video Latency : %d , Low Latency Mode : %d ,Audio Output Compensated value : %d , Audio Output Delay : %d , Latency Flags: %d ", videoLatency, lowLatencyMode, audioOutputCompensated, audioOutputDelay, latencyFlags); - m_video_latency = (videoLatency/2) + 1; - m_latency_flags = latencyFlags; - m_audio_output_delay = (audioOutputDelay/2) + 1; - setLatencyInfo(); + LOGINFO("Invalid profile type for TV \n"); + return ; } - void HdmiCecSink::setLatencyInfo() - { - if(!HdmiCecSink::_instance) - return; - - if(!(_instance->smConnection)) - return; - - LOGINFO("Send Report Current Latency message \n"); - _instance->smConnection->sendTo(LogicalAddress::BROADCAST,MessageEncoder().encode(ReportCurrentLatency(physical_addr,m_video_latency,m_latency_flags,m_audio_output_delay))); - - } - - void HdmiCecSink::Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg) - { - JsonObject params; - if(!HdmiCecSink::_instance) - return; - - //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status - //SetSystemAudioMode message may come from AVR/Soundbar while CEC disable is in-progress - if ( cecSettingEnabled != true ) - { - LOGINFO("Process SetSystemAudioMode from Audio device: Cec is disabled-> EnableCEC first"); - return; - } - - if ( (msg.status.toInt() == SYSTEM_AUDIO_MODE_OFF) && (m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) - { - /* ie system audio mode off -> amplifier goign to standby but still ARC is in initiated state,stop ARC and - bring the ARC state machine to terminated state*/ - LOGINFO("system audio mode off message but arc is not in terminated state so stopping ARC"); - stopArc(); - - } - - params["audioMode"] = msg.status.toString().c_str(); - if (msg.status.toInt() == SYSTEM_AUDIO_MODE_ON) { - LOGINFO("panel power state is %s", powerState ? "Off" : "On"); - if (powerState == DEVICE_POWER_STATE_ON ) { - LOGINFO("Notifying system audio mode ON event"); - sendNotify(eventString[HDMICECSINK_EVENT_SYSTEM_AUDIO_MODE], params); - } else { - LOGINFO("Not notifying system audio mode ON event"); - } - } else { - LOGINFO("Notifying system audio Mode OFF event"); - sendNotify(eventString[HDMICECSINK_EVENT_SYSTEM_AUDIO_MODE], params); - } - } - void HdmiCecSink::Process_ReportAudioStatus_msg(const ReportAudioStatus msg) - { - JsonObject params; - if(!HdmiCecSink::_instance) - return; - if (m_audioStatusTimerStarted) - { - m_audioStatusReceived = true; - m_isAudioStatusInfoUpdated = true; - m_audioStatusTimerStarted = false; - if (m_audioStatusDetectionTimer.isActive()) - { - LOGINFO("AudioStatus received from the Audio Device and the timer is still active. So stopping the timer!\n"); - m_audioStatusDetectionTimer.stop(); - } - LOGINFO("AudioStatus received from the Audio Device. Updating the AudioStatus info! m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - } - LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); - params["muteStatus"] = msg.status.getAudioMuteStatus(); - params["volumeLevel"] = msg.status.getAudioVolume(); - sendNotify(eventString[HDMICECSINK_EVENT_REPORT_AUDIO_STATUS], params); - - } - void HdmiCecSink::sendKeyPressEvent(const int logicalAddress, int keyCode) - { - if(!(_instance->smConnection)) - return; - LOGINFO(" sendKeyPressEvent logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); - switch(keyCode) - { - case VOLUME_UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); - break; - case VOLUME_DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); - break; - case MUTE: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); - break; - case UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); - break; - case DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); - break; - case LEFT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); - break; - case RIGHT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); - break; - case SELECT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); - break; - case HOME: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); - break; - case BACK: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); - break; - case NUMBER_0: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); - break; - case NUMBER_1: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); - break; - case NUMBER_2: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); - break; - case NUMBER_3: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); - break; - case NUMBER_4: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); - break; - case NUMBER_5: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); - break; - case NUMBER_6: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); - break; - case NUMBER_7: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); - break; - case NUMBER_8: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); - break; - case NUMBER_9: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); - break; + bool enabled = false; + bool ret = false; + HdmiCecSink::_hdmiCecSink->GetEnabled(enabled,ret); - } - } + if(ret && enabled) + { + Exchange::IHdmiCecSink::HdmiCecSinkSuccess success; + HdmiCecSink::_hdmiCecSink->SetEnabled(false,success); + } - void HdmiCecSink::sendUserControlPressed(const int logicalAddress, int keyCode) - { - if(!(_instance->smConnection)) - return; - LOGINFO(" sendUserControlPressed logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); - switch(keyCode) - { - case VOLUME_UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); - break; - case VOLUME_DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); - break; - case MUTE: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); - break; - case UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); - break; - case DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); - break; - case LEFT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); - break; - case RIGHT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); - break; - case SELECT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); - break; - case HOME: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); - break; - case BACK: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); - break; - case NUMBER_0: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); - break; - case NUMBER_1: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); - break; - case NUMBER_2: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); - break; - case NUMBER_3: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); - break; - case NUMBER_4: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); - break; - case NUMBER_5: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); - break; - case NUMBER_6: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); - break; - case NUMBER_7: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); - break; - case NUMBER_8: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); - break; - case NUMBER_9: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); - break; + if(nullptr != _hdmiCecSink) + { + _hdmiCecSink->Unregister(&_notification); + Exchange::JHdmiCecSink::Unregister(*this); + _hdmiCecSink->Release(); + _hdmiCecSink = nullptr; - } + RPC::IRemoteConnection* connection = _service->RemoteConnection(_connectionId); + if (connection != nullptr) + { + try{ + connection->Terminate(); + } + catch(const std::exception& e) + { + std::string errorMessage = "Failed to terminate connection: "; + errorMessage += e.what(); + LOGWARN("%s",errorMessage.c_str()); } - void HdmiCecSink::sendKeyReleaseEvent(const int logicalAddress) - { - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); - - } - - void HdmiCecSink::sendUserControlReleased(const int logicalAddress) - { - if(!(_instance->smConnection)) - return; - LOGINFO(" User Control Released \n"); - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); - } - - void HdmiCecSink::sendDeviceUpdateInfo(const int logicalAddress) - { - JsonObject params; - params["logicalAddress"] = JsonValue(logicalAddress); - sendNotify(eventString[HDMICECSINK_EVENT_DEVICE_INFO_UPDATED], params); - } - void HdmiCecSink::systemAudioModeRequest() - { - if ( cecEnableStatus != true ) - { - LOGINFO("systemAudioModeRequest: Cec is disabled-> EnableCEC first"); - return; - } - - if(!HdmiCecSink::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO(" Send systemAudioModeRequest "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(SystemAudioModeRequest(physical_addr)), 1000); + connection->Release(); + } + } + _connectionId = 0; + _service->Unregister(&_notification); + _service->Release(); + _service = nullptr; + LOGINFO("HdmiCecSink plugin is deactivated. Successfully deactivated HdmiCecSink Plugin"); } - void HdmiCecSink::sendGiveAudioStatusMsg() - { - if(!HdmiCecSink::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO(" Send GiveAudioStatus "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(GiveAudioStatus()), 100); - } - void HdmiCecSink::reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus) + string HdmiCecSink::Information() const { - JsonObject params; - params["powerStatus"] = JsonValue(powerStatus); - LOGINFO("Panle power state is %s", powerState ? "Off" : "On"); - if (powerStatus != AUDIO_DEVICE_POWERSTATE_OFF) { - if (powerState == DEVICE_POWER_STATE_ON ) { - LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); - sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_POWER_STATUS], params); - } else { - LOGINFO("Not notifying audio device power state to DS"); - } - } else { - LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); - sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_POWER_STATUS], params); - } + return("This HdmiCecSink PLugin Facilitates the HDMI CEC Sink Control"); } - void HdmiCecSink::SendStandbyMsgEvent(const int logicalAddress) + void HdmiCecSink::Deactivated(RPC::IRemoteConnection* connection) { - JsonObject params; - if(!HdmiCecSink::_instance) - return; - params["logicalAddress"] = JsonValue(logicalAddress); - sendNotify(eventString[HDMICECSINK_EVENT_STANDBY_MSG_EVENT], params); - } - uint32_t HdmiCecSink::setEnabledWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - bool enabled = false; - - if (parameters.HasLabel("enabled")) - { - getBoolParameter("enabled", enabled); - } - else - { - returnResponse(false); - } - - setEnabled(enabled); - returnResponse(true); - } - - uint32_t HdmiCecSink::getEnabledWrapper(const JsonObject& parameters, JsonObject& response) - { - response["enabled"] = getEnabled(); - returnResponse(true); - } - - uint32_t HdmiCecSink::getAudioDeviceConnectedStatusWrapper(const JsonObject& parameters, JsonObject& response) - { - response["connected"] = getAudioDeviceConnectedStatus(); - returnResponse(true); - } - - uint32_t HdmiCecSink::requestAudioDevicePowerStatusWrapper(const JsonObject& parameters, JsonObject& response) - { - requestAudioDevicePowerStatus(); - returnResponse(true); - } - - uint32_t HdmiCecSink::getActiveSourceWrapper(const JsonObject& parameters, JsonObject& response) - { - char routeString[1024] = {'\0'}; - int length = 0; - std::stringstream temp; - - if ( HdmiCecSink::_instance->m_currentActiveSource != -1 ) - { - int n = HdmiCecSink::_instance->m_currentActiveSource; - response["available"] = true; - response["logicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt(); - response["physicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_physicalAddr.toString().c_str(); - response["deviceType"] = HdmiCecSink::_instance->deviceList[n].m_deviceType.toString().c_str(); - response["cecVersion"] = HdmiCecSink::_instance->deviceList[n].m_cecVersion.toString().c_str(); - response["osdName"] = HdmiCecSink::_instance->deviceList[n].m_osdName.toString().c_str(); - response["vendorID"] = HdmiCecSink::_instance->deviceList[n].m_vendorID.toString().c_str(); - response["powerStatus"] = HdmiCecSink::_instance->deviceList[n].m_powerStatus.toString().c_str(); - - if ( HdmiCecSink::_instance->deviceList[n].m_physicalAddr.getByteValue(0) != 0 ) - { - snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSink::_instance->deviceList[n].m_physicalAddr.getByteValue(0) - 1)); - } - else if ( HdmiCecSink::_instance->deviceList[n].m_physicalAddr.getByteValue(0) == 0 ) - { - snprintf(&routeString[length], sizeof(routeString) - length, "%s", "TV"); - } - - temp << (char *)routeString; - response["port"] = temp.str(); - - } - else - { - response["available"] = false; - } - - returnResponse(true); - } - - uint32_t HdmiCecSink::getDeviceListWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - response["numberofdevices"] = HdmiCecSink::_instance->m_numberOfDevices; - LOGINFO("getDeviceListWrapper m_numberOfDevices :%d \n", HdmiCecSink::_instance->m_numberOfDevices); - JsonArray deviceList; - - for (int n = 0; n <= LogicalAddress::UNREGISTERED; n++) - { - - if ( n != HdmiCecSink::_instance->m_logicalAddressAllocated && - HdmiCecSink::_instance->deviceList[n].m_isDevicePresent ) - { - JsonObject device; - - device["logicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt(); - device["physicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_physicalAddr.toString().c_str(); - device["deviceType"] = HdmiCecSink::_instance->deviceList[n].m_deviceType.toString().c_str(); - device["cecVersion"] = HdmiCecSink::_instance->deviceList[n].m_cecVersion.toString().c_str(); - device["osdName"] = HdmiCecSink::_instance->deviceList[n].m_osdName.toString().c_str(); - device["vendorID"] = HdmiCecSink::_instance->deviceList[n].m_vendorID.toString().c_str(); - device["powerStatus"] = HdmiCecSink::_instance->deviceList[n].m_powerStatus.toString().c_str(); - int hdmiPortNumber = -1; - LOGINFO("getDeviceListWrapper m_numofHdmiInput:%d looking for Logical Address :%d \n", m_numofHdmiInput, HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt()); - for (int i=0; i < m_numofHdmiInput; i++) - { - LOGINFO("getDeviceListWrapper connected : %d, portid:%d LA: %d \n", hdmiInputs[i].m_isConnected, hdmiInputs[i].m_portID, hdmiInputs[i].m_logicalAddr.toInt()); - if(hdmiInputs[i].m_isConnected && hdmiInputs[i].m_logicalAddr.toInt() == HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt()) - { - hdmiPortNumber = hdmiInputs[i].m_portID; - LOGINFO("got portid :%d break \n", hdmiPortNumber); - break; - } - } - device["portNumber"] = hdmiPortNumber; - deviceList.Add(device); - } - } - - response["deviceList"] = deviceList; - - returnResponse(true); - } - - - uint32_t HdmiCecSink::setOSDNameWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - if (parameters.HasLabel("name")) - { - std::string osd = parameters["name"].String(); - LOGINFO("setOSDNameWrapper osdName: %s",osd.c_str()); - osdName = osd.c_str(); - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_OSD_NAME, JsonValue(osd.c_str())); - } - else + if (connection->Id() == _connectionId) { - returnResponse(false); + ASSERT(_service != nullptr); + Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE)); } - returnResponse(true); - } - - uint32_t HdmiCecSink::getOSDNameWrapper(const JsonObject& parameters, JsonObject& response) - { - response["name"] = osdName.toString(); - LOGINFO("getOSDNameWrapper osdName : %s \n",osdName.toString().c_str()); - returnResponse(true); } - uint32_t HdmiCecSink::printDeviceListWrapper(const JsonObject& parameters, JsonObject& response) - { - printDeviceList(); - response["printed"] = true; - returnResponse(true); - } - - uint32_t HdmiCecSink::setActiveSourceWrapper(const JsonObject& parameters, JsonObject& response) - { - setActiveSource(false); - returnResponse(true); - } - - uint32_t HdmiCecSink::setActivePathWrapper(const JsonObject& parameters, JsonObject& response) - { - if (parameters.HasLabel("activePath")) - { - std::string id = parameters["activePath"].String(); - PhysicalAddress phy_addr = PhysicalAddress(id); - - LOGINFO("Addr = %s, length = %zu", id.c_str(), id.length()); - - setStreamPath(phy_addr); - returnResponse(true); - } - else - { - returnResponse(false); - } - } - - uint32_t HdmiCecSink::getActiveRouteWrapper(const JsonObject& parameters, JsonObject& response) - { - std::vector route; - char routeString[1024] = {'\0'}; - int length = 0; - JsonArray pathList; - std::stringstream temp; - - if (HdmiCecSink::_instance->m_currentActiveSource != -1 && - HdmiCecSink::_instance->m_currentActiveSource != HdmiCecSink::_instance->m_logicalAddressAllocated ) - { - HdmiCecSink::_instance->getActiveRoute(LogicalAddress(HdmiCecSink::_instance->m_currentActiveSource), route); - - if (route.size()) - { - response["available"] = true; - response["length"] = route.size(); - - for (unsigned int i=0; i < route.size(); i++) - { - if ( route[i] != LogicalAddress::UNREGISTERED ) - { - JsonObject device; - - device["logicalAddress"] = HdmiCecSink::_instance->deviceList[route[i]].m_logicalAddress.toInt(); - device["physicalAddress"] = HdmiCecSink::_instance->deviceList[route[i]].m_physicalAddr.toString().c_str(); - device["deviceType"] = HdmiCecSink::_instance->deviceList[route[i]].m_deviceType.toString().c_str(); - device["osdName"] = HdmiCecSink::_instance->deviceList[route[i]].m_osdName.toString().c_str(); - device["vendorID"] = HdmiCecSink::_instance->deviceList[route[i]].m_vendorID.toString().c_str(); - - pathList.Add(device); - - snprintf(&routeString[length], sizeof(routeString) - length, "%s", _instance->deviceList[route[i]].m_logicalAddress.toString().c_str()); - length += _instance->deviceList[route[i]].m_logicalAddress.toString().length(); - snprintf(&routeString[length], sizeof(routeString) - length, "(%s", _instance->deviceList[route[i]].m_osdName.toString().c_str()); - length += _instance->deviceList[route[i]].m_osdName.toString().length(); - snprintf(&routeString[length], sizeof(routeString) - length, "%s", ")-->"); - length += strlen(")-->"); - if( i + 1 == route.size() ) - { - snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSink::_instance->deviceList[route[i]].m_physicalAddr.getByteValue(0) - 1)); - } - } - } - - response["pathList"] = pathList; - temp << (char *)routeString; - response["ActiveRoute"] = temp.str(); - LOGINFO("ActiveRoute = [%s]", routeString); - } - - } - else if ( HdmiCecSink::_instance->m_currentActiveSource == HdmiCecSink::_instance->m_logicalAddressAllocated ) - { - response["available"] = true; - response["ActiveRoute"] = "TV"; - } - else - { - response["available"] = false; - } - - returnResponse(true); - } - - uint32_t HdmiCecSink::requestActiveSourceWrapper(const JsonObject& parameters, JsonObject& response) - { - requestActiveSource(); - returnResponse(true); - } - - uint32_t HdmiCecSink::setRoutingChangeWrapper(const JsonObject& parameters, JsonObject& response) - { - std::string oldPortID; - std::string newPortID; - - returnIfParamNotFound(parameters, "oldPort"); - returnIfParamNotFound(parameters, "newPort"); - - oldPortID = parameters["oldPort"].String(); - newPortID = parameters["newPort"].String(); - - - if ((oldPortID.find("HDMI",0) != std::string::npos || - oldPortID.find("TV",0) != std::string::npos ) && - ( newPortID.find("HDMI", 0) != std::string::npos || - newPortID.find("TV", 0) != std::string::npos )) - { - setRoutingChange(oldPortID, newPortID); - returnResponse(true); - } - else - { - returnResponse(false); - } - } - - - uint32_t HdmiCecSink::setMenuLanguageWrapper(const JsonObject& parameters, JsonObject& response) - { - std::string lang; - - returnIfParamNotFound(parameters, "language"); - - lang = parameters["language"].String(); - - setCurrentLanguage(Language(lang.data())); - sendMenuLanguage(); - returnResponse(true); - } - - - uint32_t HdmiCecSink::setVendorIdWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - if (parameters.HasLabel("vendorid")) - { - std::string id = parameters["vendorid"].String(); - unsigned int vendorID = 0x00; - try - { - vendorID = stoi(id,NULL,16); - } - catch (...) - { - LOGWARN("Exception in setVendorIdWrapper set default value\n"); - vendorID = 0x0019FB; - } - appVendorId = {(uint8_t)(vendorID >> 16 & 0xff),(uint8_t)(vendorID>> 8 & 0xff),(uint8_t) (vendorID & 0xff)}; - LOGINFO("appVendorId : %s vendorID :%x \n",appVendorId.toString().c_str(), vendorID ); - - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_VENDOR_ID, JsonValue(vendorID)); - } - else - { - returnResponse(false); - } - returnResponse(true); - } - uint32_t HdmiCecSink::setArcEnableDisableWrapper(const JsonObject& parameters, JsonObject& response) - { - - bool enabled = false; - - if (parameters.HasLabel("enabled")) - { - getBoolParameter("enabled", enabled); - } - else - { - returnResponse(false); - } - if(enabled) - { - startArc(); - } - else - { - stopArc(); - - } - - returnResponse(true); - } - uint32_t HdmiCecSink::getVendorIdWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFO("getVendorIdWrapper appVendorId : %s \n",appVendorId.toString().c_str()); - response["vendorid"] = appVendorId.toString() ; - returnResponse(true); - } - - uint32_t HdmiCecSink::requestShortAudioDescriptorWrapper(const JsonObject& parameters, JsonObject& response) - { - requestShortaudioDescriptor(); - returnResponse(true); - } - uint32_t HdmiCecSink::sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response) - { - sendStandbyMessage(); - returnResponse(true); - } - - uint32_t HdmiCecSink::sendAudioDevicePowerOnMsgWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFO("%s invoked. \n",__FUNCTION__); - systemAudioModeRequest(); - returnResponse(true); - } - uint32_t HdmiCecSink::sendRemoteKeyPressWrapper(const JsonObject& parameters, JsonObject& response) - { - returnIfParamNotFound(parameters, "logicalAddress"); - returnIfParamNotFound(parameters, "keyCode"); - string logicalAddress = parameters["logicalAddress"].String(); - string keyCode = parameters["keyCode"].String(); - SendKeyInfo keyInfo; - keyInfo.logicalAddr = stoi(logicalAddress); - keyInfo.keyCode = stoi(keyCode); - keyInfo.UserControl = "sendKeyPressEvent"; - std::unique_lock lk(m_sendKeyEventMutex); - m_SendKeyQueue.push(keyInfo); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - LOGINFO("Post send key press event to queue size:%zu \n",m_SendKeyQueue.size()); - returnResponse(true); - } - - uint32_t HdmiCecSink::sendUserControlPressedWrapper(const JsonObject& parameters, JsonObject& response) - { - returnIfParamNotFound(parameters, "logicalAddress"); - returnIfParamNotFound(parameters, "keyCode"); - string logicalAddress = parameters["logicalAddress"].String(); - string keyCode = parameters["keyCode"].String(); - SendKeyInfo keyInfo; - keyInfo.logicalAddr = stoi(logicalAddress); - keyInfo.keyCode = stoi(keyCode); - keyInfo.UserControl = "sendUserControlPressed"; - std::unique_lock lk(m_sendKeyEventMutex); - m_SendKeyQueue.push(keyInfo); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - LOGINFO("User control pressed, queue size:%zu \n",m_SendKeyQueue.size()); - returnResponse(true); - } - - uint32_t HdmiCecSink::sendUserControlReleasedWrapper(const JsonObject& parameters, JsonObject& response) - { - returnIfParamNotFound(parameters, "logicalAddress"); - string logicalAddress = parameters["logicalAddress"].String(); - SendKeyInfo keyInfo; - keyInfo.logicalAddr = stoi(logicalAddress); - keyInfo.keyCode = 0; - keyInfo.UserControl = "sendUserControlReleased"; - std::unique_lock lk(m_sendKeyEventMutex); - m_SendKeyQueue.push(keyInfo); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - LOGINFO("User Control Released, queue size:%zu \n",m_SendKeyQueue.size()); - returnResponse(true); - } - - uint32_t HdmiCecSink::sendGiveAudioStatusWrapper(const JsonObject& parameters, JsonObject& response) - { - sendGiveAudioStatusMsg(); - returnResponse(true); - } - uint32_t HdmiCecSink::setLatencyInfoWrapper(const JsonObject& parameters, JsonObject& response) - { - int video_latency,audio_output_compensated,audio_output_delay; - bool low_latency_mode; - - returnIfParamNotFound(parameters, "videoLatency"); - returnIfParamNotFound(parameters, "lowLatencyMode"); - returnIfParamNotFound(parameters, "audioOutputCompensated"); - returnIfParamNotFound(parameters, "audioOutputDelay"); - video_latency = stoi(parameters["videoLatency"].String()); - low_latency_mode = stoi(parameters["lowLatencyMode"].String()); - audio_output_compensated = stoi(parameters["audioOutputCompensated"].String()); - audio_output_delay = stoi(parameters["audioOutputDelay"].String()); - - updateCurrentLatency(video_latency, low_latency_mode,audio_output_compensated, audio_output_delay); - returnResponse(true); - } - bool HdmiCecSink::loadSettings() - { - Core::File file; - file = CEC_SETTING_ENABLED_FILE; - - if( file.Open()) - { - JsonObject parameters; - parameters.IElement::FromFile(file); - bool isConfigAdded = false; - - if( parameters.HasLabel(CEC_SETTING_ENABLED)) - { - getBoolParameter(CEC_SETTING_ENABLED, cecSettingEnabled); - LOGINFO("CEC_SETTING_ENABLED present value:%d",cecSettingEnabled); - } - else - { - parameters[CEC_SETTING_ENABLED] = true; - cecSettingEnabled = true; - isConfigAdded = true; - LOGINFO("CEC_SETTING_ENABLED not present set dafult true:\n "); - } - - if( parameters.HasLabel(CEC_SETTING_OTP_ENABLED)) - { - getBoolParameter(CEC_SETTING_OTP_ENABLED, cecOTPSettingEnabled); - LOGINFO("CEC_SETTING_OTP_ENABLED present value :%d",cecOTPSettingEnabled); - } - else - { - parameters[CEC_SETTING_OTP_ENABLED] = true; - cecOTPSettingEnabled = true; - isConfigAdded = true; - LOGINFO("CEC_SETTING_OTP_ENABLED not present set dafult true:\n "); - } - if( parameters.HasLabel(CEC_SETTING_OSD_NAME)) - { - std::string osd_name; - getStringParameter(CEC_SETTING_OSD_NAME, osd_name); - osdName = osd_name.c_str(); - LOGINFO("CEC_SETTING_OSD_NAME present osd_name :%s",osdName.toString().c_str()); - } - else - { - parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); - LOGINFO("CEC_SETTING_OSD_NMAE not present set dafult value :%s\n ",osdName.toString().c_str()); - isConfigAdded = true; - } - unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); - if( parameters.HasLabel(CEC_SETTING_VENDOR_ID)) - { - getNumberParameter(CEC_SETTING_VENDOR_ID, vendorId); - LOGINFO("CEC_SETTING_VENDOR_ID present :%x ",vendorId); - } - else - { - LOGINFO("CEC_SETTING_VENDOR_ID not present set dafult value :%x \n ",vendorId); - parameters[CEC_SETTING_VENDOR_ID] = vendorId; - isConfigAdded = true; - } - - appVendorId = {(uint8_t)(vendorId >> 16 & 0xff),(uint8_t)(vendorId >> 8 & 0xff),(uint8_t) (vendorId & 0xff)}; - LOGINFO("appVendorId : %s vendorId :%x \n",appVendorId.toString().c_str(), vendorId ); - - if(isConfigAdded) - { - LOGINFO("isConfigAdded true so update file:\n "); - file.Destroy(); - file.Create(); - parameters.IElement::ToFile(file); - - } - - file.Close(); - } - else - { - LOGINFO("CEC_SETTING_ENABLED_FILE file not present create with default settings "); - file.Open(false); - if (!file.IsOpen()) - file.Create(); - - JsonObject parameters; - unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); - parameters[CEC_SETTING_ENABLED] = true; - parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); - parameters[CEC_SETTING_VENDOR_ID] = vendorId; - - cecSettingEnabled = true; - cecOTPSettingEnabled = true; - parameters.IElement::ToFile(file); - - file.Close(); - - } - - return cecSettingEnabled; - } - - void HdmiCecSink::setEnabled(bool enabled) - { - LOGINFO("Entered setEnabled: %d cecSettingEnabled :%d ",enabled, cecSettingEnabled); - - if (cecSettingEnabled != enabled) - { - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_ENABLED, JsonValue(enabled)); - cecSettingEnabled = enabled; - } - if(true == enabled) - { - CECEnable(); - } - else - { - CECDisable(); - } - return; - } - - void HdmiCecSink::updateImageViewOn(const int logicalAddress) - { - JsonObject params; - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || - logicalAddress == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress].m_isDevicePresent && - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) - - { - /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ - sendNotify(eventString[HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY], params); - } - - sendNotify(eventString[HDMICECSINK_EVENT_IMAGE_VIEW_ON_MSG], params); - } - - void HdmiCecSink::updateTextViewOn(const int logicalAddress) - { - JsonObject params; - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || - logicalAddress == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress].m_isDevicePresent && - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) - { - /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ - sendNotify(eventString[HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY], params); - } - - sendNotify(eventString[HDMICECSINK_EVENT_TEXT_VIEW_ON_MSG], params); - } - - - void HdmiCecSink::updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr) - { - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && - logicalAddress.toInt() != _instance->m_logicalAddressAllocated) - { - for (int i=0; i < m_numofHdmiInput; i++) - { - LOGINFO(" addr = %d, portID = %d", phy_addr.getByteValue(0), hdmiInputs[i].m_portID); - if (phy_addr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { - hdmiInputs[i].addChild(logicalAddress, phy_addr); - } - } - } - } - - void HdmiCecSink::getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route) - { - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || - logicalAddress.toInt() == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && - logicalAddress.toInt() != _instance->m_logicalAddressAllocated && - _instance->deviceList[logicalAddress.toInt()].m_isActiveSource ) - { - route.clear(); - for (int i=0; i < m_numofHdmiInput; i++) - { - LOGINFO("physicalAddress = [%d], portID = %d", _instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0), hdmiInputs[i].m_portID); - if (_instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { - hdmiInputs[i].getRoute(_instance->deviceList[logicalAddress.toInt()].m_physicalAddr, route); - } - } - } - else { - LOGERR("Not in correct state to Find Route"); - } - } - - - void HdmiCecSink::CheckHdmiInState() - { - int err; - bool isAnyPortConnected = false; - - dsHdmiInGetStatusParam_t params; - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - IARM_BUS_DSMGR_API_dsHdmiInGetStatus, - (void *)¶ms, - sizeof(params)); - - if(err == IARM_RESULT_SUCCESS && params.result == dsERR_NONE ) - { - for( int i = 0; i < m_numofHdmiInput; i++ ) - { - LOGINFO("Is HDMI In Port [%d] connected [%d] \n",i, params.status.isPortConnected[i]); - if ( params.status.isPortConnected[i] ) - { - isAnyPortConnected = true; - } - - LOGINFO("update Port Status [%d] \n", i); - hdmiInputs[i].update(params.status.isPortConnected[i]); - } - } - - if ( isAnyPortConnected ) { - m_isHdmiInConnected = true; - } else { - m_isHdmiInConnected = false; - } - } - - void HdmiCecSink::requestActiveSource() - { - if(!HdmiCecSink::_instance) - return; - - if(!(_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress::BROADCAST, - MessageEncoder().encode(RequestActiveSource()), 500); - } - - void HdmiCecSink::setActiveSource(bool isResponse) - { - if(!HdmiCecSink::_instance) - return; - - if(!(_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (isResponse && (_instance->m_currentActiveSource != _instance->m_logicalAddressAllocated) ) - { - LOGWARN("TV is not current Active Source"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress::BROADCAST, - MessageEncoder().encode(ActiveSource(_instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr)), 500); - _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; - } - - void HdmiCecSink::setCurrentLanguage(const Language &lang) - { - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = lang; - } - - void HdmiCecSink::sendMenuLanguage() - { - Language lang = ""; - if(!HdmiCecSink::_instance) - return; - - if(!(_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - lang = _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage; - - _instance->smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(SetMenuLanguage(lang)), 100); - } - - void HdmiCecSink::updateInActiveSource(const int logical_address, const InActiveSource &source ) - { - JsonObject params; - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if( logical_address != _instance->m_logicalAddressAllocated ) - { - _instance->deviceList[logical_address].m_isActiveSource = false; - - if ( _instance->m_currentActiveSource == logical_address ) - { - _instance->m_currentActiveSource = -1; - } - - params["logicalAddress"] = JsonValue(logical_address); - params["phsicalAddress"] = source.physicalAddress.toString().c_str(); - sendNotify(eventString[HDMICECSINK_EVENT_INACTIVE_SOURCE], params); - } - } - - void HdmiCecSink::updateActiveSource(const int logical_address, const ActiveSource &source ) - { - JsonObject params; - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if( logical_address != _instance->m_logicalAddressAllocated ) - { - if ( _instance->m_currentActiveSource != -1 ) - { - _instance->deviceList[_instance->m_currentActiveSource].m_isActiveSource = false; - } - - _instance->deviceList[logical_address].m_isActiveSource = true; - _instance->deviceList[logical_address].update(source.physicalAddress); - _instance->m_currentActiveSource = logical_address; - - if (_instance->deviceList[logical_address].m_isDevicePresent && - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) - { - /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ - sendNotify(eventString[HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY], params); - } - - params["logicalAddress"] = JsonValue(logical_address); - params["physicalAddress"] = _instance->deviceList[logical_address].m_physicalAddr.toString().c_str(); - sendNotify(eventString[HDMICECSINK_EVENT_ACTIVE_SOURCE_CHANGE], params); - } - } - - void HdmiCecSink::requestShortaudioDescriptor() - { - if ( cecEnableStatus != true ) - { - LOGINFO("requestShortaudioDescriptor: cec is disabled-> EnableCEC first"); - return; - } - - if(!HdmiCecSink::_instance) - return; - - if(!(_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - LOGINFO(" Send requestShortAudioDescriptor Message "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestShortAudioDescriptor(formatid,audioFormatCode,numberofdescriptor)), 1000); - - } - - void HdmiCecSink::requestAudioDevicePowerStatus() - { - if ( cecEnableStatus != true ) - { - LOGWARN("cec is disabled-> EnableCEC first"); - return; - } - - if(!HdmiCecSink::_instance) - return; - - if(!(_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - LOGINFO(" Send GiveDevicePowerStatus Message to Audio system in the network \n"); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM, MessageEncoder().encode(GiveDevicePowerStatus()), 500); - - m_audioDevicePowerStatusRequested = true; - } - - void HdmiCecSink::sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason) - { - - if(!HdmiCecSink::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO(" Sending FeatureAbort to %s for opcode %s with reason %s ",logicalAddress.toString().c_str(),feature.toString().c_str(),reason.toString().c_str()); - _instance->smConnection->sendTo(logicalAddress, MessageEncoder().encode(FeatureAbort(feature,reason)), 500); - } - - void HdmiCecSink::reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode featureOpcode, const AbortReason abortReason) - { - LOGINFO(" Notifying the UI FeatureAbort from the %s for the opcode %s with the reason %s ",logicalAddress.toString().c_str(),featureOpcode.toString().c_str(),abortReason.toString().c_str()); - JsonObject params; - params["LogicalAddress"] = logicalAddress.toInt(); - params["opcode"] = featureOpcode.opCode(); - params["FeatureAbortReason"] = abortReason.toInt(); - sendNotify(eventString[HDMICECSINK_EVENT_FEATURE_ABORT_EVENT], params); - } - - void HdmiCecSink::pingDevices(std::vector &connected , std::vector &disconnected) - { - int i; - - if(!HdmiCecSink::_instance) - return; - if(!(_instance->smConnection)) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { - if ( i != _instance->m_logicalAddressAllocated ) - { - //LOGWARN("PING for 0x%x \r\n",i); - try { - _instance->smConnection->ping(LogicalAddress(_instance->m_logicalAddressAllocated), LogicalAddress(i), Throw_e()); - } - catch(CECNoAckException &e) - { - if ( _instance->deviceList[i].m_isDevicePresent ) { - disconnected.push_back(i); - } - //LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); - usleep(50000); - continue; - } - catch(Exception &e) - { - LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); - usleep(50000); - continue; - } - - /* If we get ACK, then the device is present in the network*/ - if ( !_instance->deviceList[i].m_isDevicePresent ) - { - connected.push_back(i); - //LOGWARN("Ping success, added device: 0x%x \r\n", i); - } - usleep(50000); - } - } - } - - int HdmiCecSink::requestType( const int logicalAddress ) { - int requestType = CECDeviceParams::REQUEST_NONE; - - if ( !_instance->deviceList[logicalAddress].m_isPAUpdated || !_instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) { - requestType = CECDeviceParams::REQUEST_PHISICAL_ADDRESS; - }else if ( !_instance->deviceList[logicalAddress].m_isOSDNameUpdated ) { - requestType = CECDeviceParams::REQUEST_OSD_NAME; - }else if ( !_instance->deviceList[logicalAddress].m_isVersionUpdated ) { - requestType = CECDeviceParams::REQUEST_CEC_VERSION; - }else if ( !_instance->deviceList[logicalAddress].m_isVendorIDUpdated ) { - requestType = CECDeviceParams::REQUEST_DEVICE_VENDOR_ID; - }else if ( !_instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) { - requestType = CECDeviceParams::REQUEST_POWER_STATUS; - } - - return requestType; - } - - void HdmiCecSink::printDeviceList() { - int i; - - if(!HdmiCecSink::_instance) - return; - - for(i=0; i< 16; i++) - { - if (HdmiCecSink::_instance->deviceList[i].m_isDevicePresent) { - LOGWARN("------ Device ID = %d--------", i); - HdmiCecSink::_instance->deviceList[i].printVariable(); - LOGWARN("-----------------------------"); - } - } - } - - void HdmiCecSink::setStreamPath( const PhysicalAddress &physical_addr) { - - if(!HdmiCecSink::_instance) - return; - - if(!(_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(SetStreamPath(physical_addr)), 500); - } - - void HdmiCecSink::setRoutingChange(const std::string &from, const std::string &to) { - PhysicalAddress oldPhyAddr = {0xF,0xF,0xF,0xF}; - PhysicalAddress newPhyAddr = {0xF,0xF,0xF,0xF}; - int oldPortID = -1; - int newPortID = -1; - - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - if( from.find("TV",0) != std::string::npos ) - { - oldPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; - _instance->m_currentActiveSource = -1; - } - else - { - oldPortID = stoi(from.substr(4,1),NULL,16); - if ( oldPortID < _instance->m_numofHdmiInput ) - { - oldPhyAddr = _instance->hdmiInputs[oldPortID].m_physicalAddr; - } - else - { - LOGERR("Invalid HDMI Old Port ID"); - return; - } - } - - if( to.find("TV",0) != std::string::npos ) - { - newPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; - /*set active source as TV */ - _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; - } - else - { - newPortID = stoi(to.substr(4,1),NULL,16); - - if ( newPortID < _instance->m_numofHdmiInput ) - { - newPhyAddr = _instance->hdmiInputs[newPortID].m_physicalAddr; - } - else - { - LOGERR("Invalid HDMI New Port ID"); - return; - } - } - - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(RoutingChange(oldPhyAddr, newPhyAddr)), 500); - } - - void HdmiCecSink::addDevice(const int logicalAddress) { - JsonObject params; - - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if ( !HdmiCecSink::_instance->deviceList[logicalAddress].m_isDevicePresent ) - { - HdmiCecSink::_instance->deviceList[logicalAddress].m_isDevicePresent = true; - HdmiCecSink::_instance->deviceList[logicalAddress].m_logicalAddress = LogicalAddress(logicalAddress); - HdmiCecSink::_instance->m_numberOfDevices++; - HdmiCecSink::_instance->m_pollNextState = POLL_THREAD_STATE_INFO; - - if(logicalAddress == 0x5) - { - LOGINFO(" logicalAddress =%d , Audio device detected, Notify Device Settings", logicalAddress ); - params["status"] = string("success"); - params["audioDeviceConnected"] = string("true"); - hdmiCecAudioDeviceConnected = true; - sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params); - } - - sendNotify(eventString[HDMICECSINK_EVENT_DEVICE_ADDED], JsonObject()); - } - } - - void HdmiCecSink::removeDevice(const int logicalAddress) { - JsonObject params; - - if(!HdmiCecSink::_instance) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress].m_isDevicePresent) - { - _instance->m_numberOfDevices--; - - for (int i=0; i < m_numofHdmiInput; i++) - { - if (_instance->deviceList[logicalAddress].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { - hdmiInputs[i].removeChild(_instance->deviceList[logicalAddress].m_physicalAddr); - hdmiInputs[i].update(LogicalAddress(LogicalAddress::UNREGISTERED)); - } - } - - if(logicalAddress == 0x5) - { - LOGINFO(" logicalAddress =%d , Audio device removed, Notify Device Settings", logicalAddress ); - params["status"] = string("success"); - params["audioDeviceConnected"] = string("false"); - hdmiCecAudioDeviceConnected = false; - if (m_audioStatusDetectionTimer.isActive()){ - m_audioStatusDetectionTimer.stop(); - } - m_isAudioStatusInfoUpdated = false; - m_audioStatusReceived = false; - m_audioStatusTimerStarted = false; - LOGINFO("Audio device removed, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params); - } - - _instance->deviceList[logicalAddress].m_isRequestRetry = 0; - _instance->deviceList[logicalAddress].clear(); - sendNotify(eventString[HDMICECSINK_EVENT_DEVICE_REMOVED], JsonObject()); - } - } - - void HdmiCecSink::request(const int logicalAddress) { - int requestType; - - if(!HdmiCecSink::_instance) - return; - if(!(_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - requestType = _instance->requestType(logicalAddress); - _instance->deviceList[logicalAddress].m_isRequested = requestType; - - switch (requestType) - { - case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GivePhysicalAddress()), 200); - } - break; - - case CECDeviceParams::REQUEST_CEC_VERSION : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GetCECVersion()), 100); - } - break; - - case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDeviceVendorID()), 100); - } - break; - - case CECDeviceParams::REQUEST_OSD_NAME : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveOSDName()), 500); - } - break; - - case CECDeviceParams::REQUEST_POWER_STATUS : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDevicePowerStatus()), 100); - } - break; - default: - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - break; - } - - _instance->deviceList[logicalAddress].m_requestTime = std::chrono::system_clock::now(); - LOGINFO("request type %d", _instance->deviceList[logicalAddress].m_isRequested); - } - - int HdmiCecSink::requestStatus(const int logicalAddress) { - std::chrono::duration elapsed; - bool isElapsed = false; - - if(!HdmiCecSink::_instance) - return -1; - - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ) { - LOGERR("Logical Address NOT Allocated Or its not valid"); - return -1; - } - - switch ( _instance->deviceList[logicalAddress].m_isRequested ) { - case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : - { - if( _instance->deviceList[logicalAddress].m_isPAUpdated && - _instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_CEC_VERSION : - { - if( _instance->deviceList[logicalAddress].m_isVersionUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : - { - if( _instance->deviceList[logicalAddress].m_isVendorIDUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_OSD_NAME : - { - if( _instance->deviceList[logicalAddress].m_isOSDNameUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_POWER_STATUS : - { - if( _instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - default: - break; - } - - if ( _instance->deviceList[logicalAddress].m_isRequested != CECDeviceParams::REQUEST_NONE ) - { - elapsed = std::chrono::system_clock::now() - _instance->deviceList[logicalAddress].m_requestTime; - - if ( elapsed.count() > HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS ) - { - LOGINFO("request elapsed "); - isElapsed = true; - } - } - - if (isElapsed) - { - /* For some request it should be retry, like report physical address etc for other we can have default values */ - switch( _instance->deviceList[logicalAddress].m_isRequested ) - { - case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : - { - LOGINFO("Retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); - /* Update with Invalid Physical Address */ - if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) - { - LOGINFO("Max retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); - _instance->deviceList[logicalAddress].update(PhysicalAddress(0xF,0xF,0xF,0xF)); - _instance->deviceList[logicalAddress].update(DeviceType(DeviceType::RESERVED)); - _instance->deviceList[logicalAddress].m_isRequestRetry = 0; - } - } - break; - - case CECDeviceParams::REQUEST_CEC_VERSION : - { - /*Defaulting to 1.4*/ - _instance->deviceList[logicalAddress].update(Version(Version::V_1_4)); - } - break; - - case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : - { - _instance->deviceList[logicalAddress].update(VendorID(0,0,0)); - } - break; - - case CECDeviceParams::REQUEST_OSD_NAME : - { - if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) - { - LOGINFO("Max retry for REQUEST_OSD_NAME = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); - _instance->deviceList[logicalAddress].update(OSDName("")); - _instance->deviceList[logicalAddress].m_isRequestRetry = 0; - } - } - break; - - case CECDeviceParams::REQUEST_POWER_STATUS : - { - _instance->deviceList[logicalAddress].update(PowerStatus(PowerStatus::POWER_STATUS_NOT_KNOWN)); - } - break; - default: - break; - } - - - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - - if( _instance->deviceList[logicalAddress].m_isRequested == CECDeviceParams::REQUEST_NONE) - { - LOGINFO("Request Done"); - return CECDeviceParams::REQUEST_DONE; - } - - //LOGINFO("Request NOT Done"); - return CECDeviceParams::REQUEST_NOT_DONE; - } - - void HdmiCecSink::threadRun() - { - std::vector connected; - std::vector disconnected; - int logicalAddressRequested = LogicalAddress::UNREGISTERED + TEST_ADD; - bool isExit = false; - - if(!HdmiCecSink::_instance) - return; - - if(!(_instance->smConnection)) - return; - LOGINFO("Entering ThreadRun: _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); - _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; - - while(1) - { - - if (_instance->m_pollThreadExit || isExit ){ - LOGWARN("Thread Exits _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); - break; - } - - if ( _instance->m_pollNextState != POLL_THREAD_STATE_NONE ) - { - _instance->m_pollThreadState = _instance->m_pollNextState; - _instance->m_pollNextState = POLL_THREAD_STATE_NONE; - } - - switch (_instance->m_pollThreadState) { - - case POLL_THREAD_STATE_POLL : - { - //LOGINFO("POLL_THREAD_STATE_POLL"); - _instance->allocateLogicalAddress(DeviceType::TV); - if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED) - { - try{ - - logicalAddress = LogicalAddress(_instance->m_logicalAddressAllocated); - LibCCEC::getInstance().addLogicalAddress(logicalAddress); - _instance->smConnection->setSource(logicalAddress); - _instance->m_numberOfDevices = 0; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType = DeviceType::TV; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_isDevicePresent = true; - _instance->deviceList[_instance->m_logicalAddressAllocated].update(physical_addr); - _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_1_4; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_vendorID = appVendorId; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); - _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = defaultLanguage; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_osdName = osdName.toString().c_str(); - if(cecVersion == 2.0) { - _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_2_0; - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), - MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures)), 500); - } - _instance->smConnection->addFrameListener(_instance->msgFrameListener); - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), - MessageEncoder().encode(ReportPhysicalAddress(physical_addr, _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType)), 100); - - _instance->m_sleepTime = 0; - _instance->m_pollThreadState = POLL_THREAD_STATE_PING; - } - catch(InvalidStateException &e){ - LOGWARN("InvalidStateException caught while allocated logical address. %s", e.what()); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - catch(IOException &e){ - LOGWARN("IOException caught while allocated logical address. %s", e.what()); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - catch(...){ - LOGWARN("Exception caught while allocated logical address."); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - } - else - { - LOGINFO("Not able allocate Logical Address for TV"); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - } - break; - - case POLL_THREAD_STATE_PING : - { - //LOGINFO("POLL_THREAD_STATE_PING"); - _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; - connected.clear(); - disconnected.clear(); - _instance->pingDevices(connected, disconnected); - - if ( disconnected.size() ){ - for( unsigned int i=0; i< disconnected.size(); i++ ) - { - LOGWARN("Disconnected Devices [%zu]", disconnected.size()); - _instance->removeDevice(disconnected[i]); - } - } - - if (connected.size()) { - LOGWARN("Connected Devices [%zu]", connected.size()); - for( unsigned int i=0; i< connected.size(); i++ ) - { - _instance->addDevice(connected[i]); - /* If new device is connected, then try to aquire the information */ - _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; - _instance->m_sleepTime = 0; - } - } - else - { - for(int i=0;im_logicalAddressAllocated && - _instance->deviceList[i].m_isDevicePresent && - !_instance->deviceList[i].isAllUpdated() ) - { - _instance->m_pollNextState = POLL_THREAD_STATE_INFO; - _instance->m_sleepTime = 0; - } - } - /* Check for any update required */ - _instance->m_pollThreadState = POLL_THREAD_STATE_UPDATE; - _instance->m_sleepTime = 0; - } - } - break; - - case POLL_THREAD_STATE_INFO : - { - //LOGINFO("POLL_THREAD_STATE_INFO"); - - if ( logicalAddressRequested == LogicalAddress::UNREGISTERED + TEST_ADD ) - { - int i = 0; - for(;im_logicalAddressAllocated && - _instance->deviceList[i].m_isDevicePresent && - !_instance->deviceList[i].isAllUpdated() ) - { - //LOGINFO("POLL_THREAD_STATE_INFO -> request for %d", i); - logicalAddressRequested = i; - _instance->request(logicalAddressRequested); - _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; - break; - } - } - - if ( i == LogicalAddress::UNREGISTERED) - { - /*So there is no update required, try to ping after some seconds*/ - _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; - _instance->m_sleepTime = 0; - //LOGINFO("POLL_THREAD_STATE_INFO -> state change to Ping", i); - } - } - else - { - /*So there is request sent for logical address, so wait and check the status */ - if ( _instance->requestStatus(logicalAddressRequested) == CECDeviceParams::REQUEST_DONE ) - { - logicalAddressRequested = LogicalAddress::UNREGISTERED; - } - else - { - _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; - } - } - } - break; - - /* updating the power status and if required we can add other information later*/ - case POLL_THREAD_STATE_UPDATE : - { - //LOGINFO("POLL_THREAD_STATE_UPDATE"); - - for(int i=0;im_logicalAddressAllocated && - _instance->deviceList[i].m_isDevicePresent && - _instance->deviceList[i].m_isPowerStatusUpdated ) - { - std::chrono::duration elapsed = std::chrono::system_clock::now() - _instance->deviceList[i].m_lastPowerUpdateTime; - - if ( elapsed.count() > HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS ) - { - _instance->deviceList[i].m_isPowerStatusUpdated = false; - _instance->m_pollNextState = POLL_THREAD_STATE_INFO; - _instance->m_sleepTime = 0; - } - } - } - - _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; - _instance->m_sleepTime = 0; - } - break; - - case POLL_THREAD_STATE_IDLE : - { - //LOGINFO("POLL_THREAD_STATE_IDLE"); - _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; - _instance->m_pollThreadState = POLL_THREAD_STATE_PING; - } - break; - - case POLL_THREAD_STATE_WAIT : - { - /* Wait for Hdmi is connected, in case it disconnected */ - //LOGINFO("19Aug2020-[01] -> POLL_THREAD_STATE_WAIT"); - _instance->m_sleepTime = HDMICECSINK_WAIT_FOR_HDMI_IN_MS; - - if ( _instance->m_isHdmiInConnected == true ) - { - _instance->m_pollThreadState = POLL_THREAD_STATE_POLL; - } - } - break; - - case POLL_THREAD_STATE_EXIT : - { - isExit = true; - _instance->m_sleepTime = 0; - } - break; - } - - std::unique_lock lk(_instance->m_pollExitMutex); - if ( _instance->m_ThreadExitCV.wait_for(lk, std::chrono::milliseconds(_instance->m_sleepTime)) == std::cv_status::timeout ) - continue; - else - LOGINFO("Thread is going to Exit m_pollThreadExit %d\n", _instance->m_pollThreadExit ); - - } - } - - void HdmiCecSink::allocateLAforTV() - { - bool gotLogicalAddress = false; - int addr = LogicalAddress::TV; - int i, j; - if (!(_instance->smConnection)) - return; - - for (i = 0; i< HDMICECSINK_NUMBER_TV_ADDR; i++) - { - /* poll for TV logical address - retry 5 times*/ - for (j = 0; j < 5; j++) - { - try { - smConnection->poll(LogicalAddress(addr), Throw_e()); - } - catch(CECNoAckException &e ) - { - LOGWARN("Poll caught %s \r\n",e.what()); - gotLogicalAddress = true; - break; - } - catch(Exception &e) - { - LOGWARN("Poll caught %s \r\n",e.what()); - usleep(250000); - } - } - if (gotLogicalAddress) - { - break; - } - addr = LogicalAddress::SPECIFIC_USE; - } - - if ( gotLogicalAddress ) - { - m_logicalAddressAllocated = addr; - } - else - { - m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; - } - - LOGWARN("Logical Address for TV 0x%x \r\n",m_logicalAddressAllocated); - } - - void HdmiCecSink::allocateLogicalAddress(int deviceType) - { - if( deviceType == DeviceType::TV ) - { - allocateLAforTV(); - } - } - - void HdmiCecSink::CECEnable(void) - { - std::lock_guard lock(m_enableMutex); - JsonObject params; - LOGINFO("Entered CECEnable"); - if (cecEnableStatus) - { - LOGWARN("CEC Already Enabled"); - return; - } - - if(0 == libcecInitStatus) - { - try - { - LibCCEC::getInstance().init("HdmiCecSink"); - } - catch(InvalidStateException &e){ - LOGWARN("InvalidStateException caught in LibCCEC::init %s", e.what()); - } - catch(IOException &e){ - LOGWARN("IOException caught in LibCCEC::init %s", e.what()); - } - catch(...){ - LOGWARN("Exception caught in LibCCEC::init"); - } - } - libcecInitStatus++; - - //Acquire CEC Addresses - getPhysicalAddress(); - - smConnection = new Connection(LogicalAddress::UNREGISTERED,false,"ServiceManager::Connection::"); - smConnection->open(); - allocateLogicalAddress(DeviceType::TV); - LOGINFO("logical address allocalted: %x \n",m_logicalAddressAllocated); - if ( m_logicalAddressAllocated != LogicalAddress::UNREGISTERED && smConnection) - { - logicalAddress = LogicalAddress(m_logicalAddressAllocated); - LOGINFO(" add logical address %x \n",m_logicalAddressAllocated); - LibCCEC::getInstance().addLogicalAddress(logicalAddress); - smConnection->setSource(logicalAddress); - } - msgProcessor = new HdmiCecSinkProcessor(*smConnection); - msgFrameListener = new HdmiCecSinkFrameListener(*msgProcessor); - if(smConnection) - { - LOGWARN("Start Thread %p", smConnection ); - m_pollThreadState = POLL_THREAD_STATE_POLL; - m_pollNextState = POLL_THREAD_STATE_NONE; - m_pollThreadExit = false; - m_pollThread = std::thread(threadRun); - } - cecEnableStatus = true; - - params["cecEnable"] = string("true"); - sendNotify(eventString[HDMICECSINK_EVENT_CEC_ENABLED], params); - - return; - } - - void HdmiCecSink::CECDisable(void) - { - std::lock_guard lock(m_enableMutex); - JsonObject params; - LOGINFO("Entered CECDisable "); - if(!cecEnableStatus) - { - LOGWARN("CEC Already Disabled "); - return; - } - - if(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) - { - stopArc(); - while(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) - { - usleep(500000); - } - } - - LOGINFO(" CECDisable ARC stopped "); - cecEnableStatus = false; - if (smConnection != NULL) - { - LOGWARN("Stop Thread %p", smConnection ); - m_pollThreadExit = true; - m_ThreadExitCV.notify_one(); - - try - { - if (m_pollThread.joinable()) - { - LOGWARN("Join Thread %p", smConnection ); - m_pollThread.join(); - } - } - catch(const std::system_error& e) - { - LOGERR("system_error exception in thread join %s", e.what()); - } - catch(const std::exception& e) - { - LOGERR("exception in thread join %s", e.what()); - } - - m_pollThreadState = POLL_THREAD_STATE_NONE; - m_pollNextState = POLL_THREAD_STATE_NONE; - - LOGWARN("Deleted Thread %p", smConnection ); - - smConnection->close(); - delete smConnection; - smConnection = NULL; - } - - m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - if (m_audioStatusDetectionTimer.isActive()){ - m_audioStatusDetectionTimer.stop(); - } - m_isAudioStatusInfoUpdated = false; - m_audioStatusReceived = false; - m_audioStatusTimerStarted = false; - LOGINFO("CEC Disabled, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - - - for(int i=0; i< 16; i++) - { - if (_instance->deviceList[i].m_isDevicePresent) - { - _instance->deviceList[i].clear(); - } - } - - if(1 == libcecInitStatus) - { - try - { - LibCCEC::getInstance().term(); - } - catch(InvalidStateException &e){ - LOGWARN("InvalidStateException caught in LibCCEC::term %s", e.what()); - } - catch(IOException &e){ - LOGWARN("IOException caught in LibCCEC::term %s", e.what()); - } - catch(...){ - LOGWARN("Exception caught in LibCCEC::term"); - } - } - - libcecInitStatus--; - LOGWARN("CEC Disabled %d",libcecInitStatus); - - params["cecEnable"] = string("false"); - sendNotify(eventString[HDMICECSINK_EVENT_CEC_ENABLED], params); - - return; - } - - - void HdmiCecSink::getPhysicalAddress() - { - LOGINFO("Entered getPhysicalAddress "); - - uint32_t physAddress = 0x0F0F0F0F; - - try { - LibCCEC::getInstance().getPhysicalAddress(&physAddress); - physical_addr = {(uint8_t)((physAddress >> 24) & 0xFF),(uint8_t)((physAddress >> 16) & 0xFF),(uint8_t) ((physAddress >> 8) & 0xFF),(uint8_t)((physAddress) & 0xFF)}; - LOGINFO("getPhysicalAddress: physicalAddress: %s ", physical_addr.toString().c_str()); - } - catch (const std::exception& e) - { - LOGWARN("exception caught from getPhysicalAddress"); - } - return; - } - - bool HdmiCecSink::getEnabled() - { - - - LOGINFO("getEnabled :%d ",cecEnableStatus); - if(true == cecEnableStatus) - return true; - else - return false; - } - - bool HdmiCecSink::getAudioDeviceConnectedStatus() - { - LOGINFO("getAudioDeviceConnectedStatus :%d ", hdmiCecAudioDeviceConnected); - if(true == hdmiCecAudioDeviceConnected) - return true; - else - return false; - } - //Arc Routing related functions - void HdmiCecSink::startArc() - { - if ( cecEnableStatus != true ) - { - LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); - return; - } - if(!HdmiCecSink::_instance) - return; - - LOGINFO("Current ARC State : %d\n", m_currentArcRoutingState); - - _instance->requestArcInitiation(); - - // start initiate ARC timer 3 sec - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - m_arcstarting = true; - m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); - - } - void HdmiCecSink::requestArcInitiation() - { - { - std::lock_guard lock(m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_INITIATION; - } - LOGINFO("requestArcInitiation release sem"); - _instance->m_semSignaltoArcRoutingThread.release(); - - } - void HdmiCecSink::stopArc() - { - if ( cecEnableStatus != true ) - { - LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); - return; - } - if(!HdmiCecSink::_instance) - return; - if(m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_TERMINATION || m_currentArcRoutingState == ARC_STATE_ARC_TERMINATED) - { - LOGINFO("ARC is either Termination in progress or already Terminated"); - return; - } - - _instance->requestArcTermination(); - /* start a timer for 3 sec to get the desired ARC_STATE_ARC_TERMINATED */ - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - /* m_arcstarting = true means starting the ARC start timer ,false means ARC stopping timer*/ - m_arcstarting = false; - m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); - - - } - void HdmiCecSink::requestArcTermination() - { - { - std::lock_guard lock(m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_TERMINATION; - } - LOGINFO("requestArcTermination release sem"); - _instance->m_semSignaltoArcRoutingThread.release(); - - } - - void HdmiCecSink::Process_InitiateArc() - { - JsonObject params; - - LOGINFO("Command: INITIATE_ARC \n"); - - if(!HdmiCecSink::_instance) - return; - - //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status - //Initiate ARC message may come from AVR/Soundbar while CEC disable is in-progress - if ( cecSettingEnabled != true ) - { - LOGINFO("Process InitiateArc from Audio device: Cec is disabled-> EnableCEC first"); - return; - } - - LOGINFO("Got : INITIATE_ARC and current Arcstate is %d\n",_instance->m_currentArcRoutingState); - - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - if (powerState == DEVICE_POWER_STATE_ON ) { - LOGINFO("Notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); - { - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - _instance->m_currentArcRoutingState = ARC_STATE_ARC_INITIATED; - } - _instance->m_semSignaltoArcRoutingThread.release(); - LOGINFO("Got : ARC_INITIATED and notify Device setting"); - params["status"] = string("success"); - sendNotify(eventString[HDMICECSINK_EVENT_ARC_INITIATION_EVENT], params); - } else { - LOGINFO("Not notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); - } - - } - void HdmiCecSink::Process_TerminateArc() - { - JsonObject params; - - LOGINFO("Command: TERMINATE_ARC current arc state %d \n",HdmiCecSink::_instance->m_currentArcRoutingState); - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - { - std::lock_guard lock(m_arcRoutingStateMutex); - HdmiCecSink::_instance->m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - } - _instance->m_semSignaltoArcRoutingThread.release(); - - // trigger callback to Device setting informing to TERMINATE_ARC - LOGINFO("Got : ARC_TERMINATED and notify Device setting"); - params["status"] = string("success"); - sendNotify(eventString[HDMICECSINK_EVENT_ARC_TERMINATION_EVENT], params); - } - - void HdmiCecSink::threadSendKeyEvent() - { - if(!HdmiCecSink::_instance) - return; - - SendKeyInfo keyInfo = {-1,-1}; - - while(!_instance->m_sendKeyEventThreadExit) - { - keyInfo.logicalAddr = -1; - keyInfo.keyCode = -1; - { - // Wait for a message to be added to the queue - std::unique_lock lk(_instance->m_sendKeyEventMutex); - _instance->m_sendKeyCV.wait(lk, []{return (_instance->m_sendKeyEventThreadRun == true);}); - } - - if (_instance->m_sendKeyEventThreadExit == true) - { - LOGINFO(" threadSendKeyEvent Exiting"); - _instance->m_sendKeyEventThreadRun = false; - break; - } - - if (_instance->m_SendKeyQueue.empty()) { - _instance->m_sendKeyEventThreadRun = false; - continue; - } - - keyInfo = _instance->m_SendKeyQueue.front(); - _instance->m_SendKeyQueue.pop(); - - if(keyInfo.UserControl == "sendUserControlPressed" ) - { - LOGINFO("sendUserControlPressed : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); - _instance->sendUserControlPressed(keyInfo.logicalAddr,keyInfo.keyCode); - } - else if(keyInfo.UserControl == "sendUserControlReleased") - { - LOGINFO("sendUserControlReleased : logical addr:0x%x queue size :%zu \n",keyInfo.logicalAddr,_instance->m_SendKeyQueue.size()); - _instance->sendUserControlReleased(keyInfo.logicalAddr); - } - else - { - LOGINFO("sendKeyPressEvent : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); - _instance->sendKeyPressEvent(keyInfo.logicalAddr,keyInfo.keyCode); - _instance->sendKeyReleaseEvent(keyInfo.logicalAddr); - } - - if((_instance->m_SendKeyQueue.size()<=1 || (_instance->m_SendKeyQueue.size() % 2 == 0)) && ((keyInfo.keyCode == VOLUME_UP) || (keyInfo.keyCode == VOLUME_DOWN) || (keyInfo.keyCode == MUTE)) ) - { - if(keyInfo.keyCode == MUTE) - { - _instance->sendGiveAudioStatusMsg(); - } - else - { - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ",_instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); - if (!_instance->m_isAudioStatusInfoUpdated) - { - if ( !(_instance->m_audioStatusDetectionTimer.isActive())) - { - LOGINFO("Audio status info not updated. Starting the Timer!"); - _instance->m_audioStatusTimerStarted = true; - _instance->m_audioStatusDetectionTimer.start((HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS)); - } - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", _instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); - } - else - { - if (!_instance->m_audioStatusReceived){ - _instance->sendGiveAudioStatusMsg(); - } - } - } - } - - }//while(!_instance->m_sendKeyEventThreadExit) - }//threadSendKeyEvent - - void HdmiCecSink::audioStatusTimerFunction() - { - m_audioStatusTimerStarted = false; - m_isAudioStatusInfoUpdated = true; - LOGINFO("Timer Expired. Requesting the AudioStatus since not received.\n"); - sendGiveAudioStatusMsg(); - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - } - - void HdmiCecSink::threadArcRouting() - { - bool isExit = false; - uint32_t currentArcRoutingState; - - if(!HdmiCecSink::_instance) - return; - - LOGINFO("Running threadArcRouting"); - _instance->getHdmiArcPortID(); - - while(1) - { - - _instance->m_semSignaltoArcRoutingThread.acquire(); - - - - { - LOGINFO(" threadArcRouting Got semaphore"); - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - - currentArcRoutingState = _instance->m_currentArcRoutingState; - - LOGINFO(" threadArcRouting Got Sem arc state %d",currentArcRoutingState); - } - - switch (currentArcRoutingState) - { - - case ARC_STATE_REQUEST_ARC_INITIATION : - { - - _instance->systemAudioModeRequest(); - _instance->Send_Request_Arc_Initiation_Message(); - - } - break; - case ARC_STATE_ARC_INITIATED : - { - _instance->Send_Report_Arc_Initiated_Message(); - } - break; - case ARC_STATE_REQUEST_ARC_TERMINATION : - { - - _instance->Send_Request_Arc_Termination_Message(); - - } - break; - case ARC_STATE_ARC_TERMINATED : - { - _instance->Send_Report_Arc_Terminated_Message(); - } - break; - case ARC_STATE_ARC_EXIT : - { - isExit = true; - } - break; - } - - if (isExit == true) - { - LOGINFO(" threadArcRouting EXITing"); - break; - } - }//while(1) - }//threadArcRouting - - void HdmiCecSink::Send_Request_Arc_Initiation_Message() - { - if(!HdmiCecSink::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO(" Send_Request_Arc_Initiation_Message "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcInitiation()), 1000); - - } - void HdmiCecSink::Send_Report_Arc_Initiated_Message() - { - if(!HdmiCecSink::_instance) - return; - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcInitiation()), 1000); - - } - void HdmiCecSink::Send_Request_Arc_Termination_Message() - { - - if(!HdmiCecSink::_instance) - return; - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcTermination()), 1000); - } - - void HdmiCecSink::Send_Report_Arc_Terminated_Message() - { - if(!HdmiCecSink::_instance) - return; - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcTermination()), 1000); - - } - - void HdmiCecSink::getHdmiArcPortID() - { - int err; - dsGetHDMIARCPortIdParam_t param; - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, - (void *)¶m, - sizeof(param)); - if (IARM_RESULT_SUCCESS == err) - { - LOGINFO("HDMI ARC port ID HdmiArcPortID=[%d] \n", param.portId); - HdmiArcPortID = param.portId; - } - } - - void HdmiCecSink::getCecVersion() - { - RFC_ParamData_t param = {0}; - WDMP_STATUS status = getRFCParameter((char*)"thunderapi", TR181_HDMICECSINK_CEC_VERSION, ¶m); - if(WDMP_SUCCESS == status && param.type == WDMP_STRING) { - LOGINFO("CEC Version from RFC = [%s] \n", param.value); - cecVersion = atof(param.value); - } - else { - LOGINFO("Error while fetching CEC Version from RFC "); - } - } - } // namespace Plugin } // namespace WPEFrameworklk diff --git a/HdmiCecSink/HdmiCecSink.h b/HdmiCecSink/HdmiCecSink.h index 418fb134..e0f61176 100644 --- a/HdmiCecSink/HdmiCecSink.h +++ b/HdmiCecSink/HdmiCecSink.h @@ -20,456 +20,27 @@ #pragma once #include -#include "ccec/FrameListener.hpp" -#include "ccec/Connection.hpp" +#include +#include -#include "libIARM.h" -#include "ccec/Assert.hpp" -#include "ccec/Messages.hpp" -#include "ccec/MessageDecoder.hpp" -#include "ccec/MessageProcessor.hpp" +#include #undef Assert // this define from Connection.hpp conflicts with WPEFramework #include "Module.h" -#include "tptimer.h" -#include -#include -#include -#include -#include "UtilsLogging.h" -#include -#include "PowerManagerInterface.h" +#include "UtilsBIT.h" +#include "UtilsThreadRAII.h" -using namespace WPEFramework; -using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; -using ThermalTemperature = WPEFramework::Exchange::IPowerManager::ThermalTemperature; +#include +#include +#include +using namespace WPEFramework; namespace WPEFramework { namespace Plugin { - class HdmiCecSinkFrameListener : public FrameListener - { - public: - HdmiCecSinkFrameListener(MessageProcessor &processor) : processor(processor) {} - void notify(const CECFrame &in) const; - ~HdmiCecSinkFrameListener() {} - private: - MessageProcessor &processor; - }; - - class HdmiCecSinkProcessor : public MessageProcessor - { - public: - HdmiCecSinkProcessor(Connection &conn) : conn(conn) {} - void process (const ActiveSource &msg, const Header &header); - void process (const InActiveSource &msg, const Header &header); - void process (const ImageViewOn &msg, const Header &header); - void process (const TextViewOn &msg, const Header &header); - void process (const RequestActiveSource &msg, const Header &header); - void process (const Standby &msg, const Header &header); - void process (const GetCECVersion &msg, const Header &header); - void process (const CECVersion &msg, const Header &header); - void process (const SetMenuLanguage &msg, const Header &header); - void process (const GiveOSDName &msg, const Header &header); - void process (const GivePhysicalAddress &msg, const Header &header); - void process (const GiveDeviceVendorID &msg, const Header &header); - void process (const SetOSDString &msg, const Header &header); - void process (const SetOSDName &msg, const Header &header); - void process (const RoutingChange &msg, const Header &header); - void process (const RoutingInformation &msg, const Header &header); - void process (const SetStreamPath &msg, const Header &header); - void process (const GetMenuLanguage &msg, const Header &header); - void process (const ReportPhysicalAddress &msg, const Header &header); - void process (const DeviceVendorID &msg, const Header &header); - void process (const GiveDevicePowerStatus &msg, const Header &header); - void process (const ReportPowerStatus &msg, const Header &header); - void process (const FeatureAbort &msg, const Header &header); - void process (const Abort &msg, const Header &header); - void process (const Polling &msg, const Header &header); - void process (const InitiateArc &msg, const Header &header); - void process (const TerminateArc &msg, const Header &header); - void process (const ReportShortAudioDescriptor &msg, const Header &header); - void process (const SetSystemAudioMode &msg, const Header &header); - void process (const ReportAudioStatus &msg, const Header &header); - void process (const GiveFeatures &msg, const Header &header); - void process (const RequestCurrentLatency &msg, const Header &header); - private: - Connection conn; - void printHeader(const Header &header) - { - printf("Header : From : %s \n", header.from.toString().c_str()); - printf("Header : to : %s \n", header.to.toString().c_str()); - } - - }; - - class CECDeviceParams { - public: - - enum { - REQUEST_NONE = 0, - REQUEST_PHISICAL_ADDRESS = 1, - REQUEST_CEC_VERSION, - REQUEST_DEVICE_VENDOR_ID, - REQUEST_POWER_STATUS, - REQUEST_OSD_NAME, - }; - - enum { - REQUEST_DONE = 0, - REQUEST_NOT_DONE, - REQUEST_TIME_ELAPSED, - }; - - DeviceType m_deviceType; - LogicalAddress m_logicalAddress; - PhysicalAddress m_physicalAddr; - Version m_cecVersion; - VendorID m_vendorID; - OSDName m_osdName; - PowerStatus m_powerStatus; - bool m_isDevicePresent; - bool m_isDeviceDisconnected; - Language m_currentLanguage; - bool m_isActiveSource; - bool m_isDeviceTypeUpdated; - bool m_isPAUpdated; - bool m_isVersionUpdated; - bool m_isOSDNameUpdated; - bool m_isVendorIDUpdated; - bool m_isPowerStatusUpdated; - int m_isRequested; - int m_isRequestRetry; - std::chrono::system_clock::time_point m_requestTime; - std::vector m_featureAborts; - std::chrono::system_clock::time_point m_lastPowerUpdateTime; - - CECDeviceParams() - : m_deviceType(0), m_logicalAddress(0),m_physicalAddr(0x0f,0x0f,0x0f,0x0f),m_cecVersion(0),m_vendorID(0,0,0),m_osdName(""),m_powerStatus(0),m_currentLanguage("") - { - m_isDevicePresent = false; - m_isActiveSource = false; - m_isPAUpdated = false; - m_isVersionUpdated = false; - m_isOSDNameUpdated = false; - m_isVendorIDUpdated = false; - m_isPowerStatusUpdated = false; - m_isDeviceDisconnected = false; - m_isDeviceTypeUpdated = false; - m_isRequestRetry = 0; - } - - void clear( ) - { - m_deviceType = 0; - m_logicalAddress = 0; - m_physicalAddr = PhysicalAddress(0x0f,0x0f,0x0f,0x0f); - m_cecVersion = 0; - m_vendorID = VendorID(0,0,0); - m_osdName = ""; - m_powerStatus = 0; - m_currentLanguage = ""; - m_isDevicePresent = false; - m_isActiveSource = false; - m_isPAUpdated = false; - m_isVersionUpdated = false; - m_isOSDNameUpdated = false; - m_isVendorIDUpdated = false; - m_isPowerStatusUpdated = false; - m_isDeviceDisconnected = false; - m_isDeviceTypeUpdated = false; - } - - void printVariable() - { - LOGWARN("Device LogicalAddress %s", m_logicalAddress.toString().c_str()); - LOGWARN("Device Type %s", m_deviceType.toString().c_str()); - LOGWARN("Device Present %d", m_isDevicePresent); - LOGWARN("Active Source %d", m_isActiveSource); - LOGWARN("PA Updated %d", m_isPAUpdated); - LOGWARN("Version Updated %d", m_isVersionUpdated); - LOGWARN("OSDName Updated %d", m_isOSDNameUpdated); - LOGWARN("PowerStatus Updated %d", m_isPowerStatusUpdated); - LOGWARN("VendorID Updated %d", m_isPowerStatusUpdated); - LOGWARN("CEC Version : %s", m_cecVersion.toString().c_str()); - LOGWARN("Vendor ID : %s", m_vendorID.toString().c_str()); - LOGWARN("PhisicalAddress : %s", m_physicalAddr.toString().c_str()); - LOGWARN("OSDName : %s", m_osdName.toString().c_str()); - LOGWARN("Power Status : %s", m_powerStatus.toString().c_str()); - LOGWARN("Language : %s", m_currentLanguage.toString().c_str()); - } - - bool isAllUpdated() { - if( !m_isPAUpdated - || !m_isVersionUpdated - || !m_isOSDNameUpdated - || !m_isVendorIDUpdated - || !m_isPowerStatusUpdated - || !m_isDeviceTypeUpdated ){ - return false; - } - return true; - } - - void update( const DeviceType &deviceType ) { - m_deviceType = deviceType; - m_isDeviceTypeUpdated = true; - } - - void update( const PhysicalAddress &physical_addr ) { - m_physicalAddr = physical_addr; - m_isPAUpdated = true; - } - - void update ( const VendorID &vendorId) { - m_vendorID = vendorId; - m_isVendorIDUpdated = true; - } - - void update ( const Version &version ) { - m_cecVersion = version; - m_isVersionUpdated = true; - } - - void update ( const OSDName &osdName ) { - m_osdName = osdName; - m_isOSDNameUpdated = true; - } - - void update ( const PowerStatus &status ) { - m_powerStatus = status; - m_isPowerStatusUpdated = true; - m_lastPowerUpdateTime = std::chrono::system_clock::now(); - } - }; - - class DeviceNode { - public: - uint8_t m_childsLogicalAddr[LogicalAddress::UNREGISTERED]; - - DeviceNode() { - int i; - for (i = 0; i < LogicalAddress::UNREGISTERED; i++ ) - { - m_childsLogicalAddr[i] = LogicalAddress::UNREGISTERED; - } - } - - } ; - typedef struct sendKeyInfo - { - int logicalAddr; - int keyCode; - string UserControl; - }SendKeyInfo; - - class HdmiPortMap { - public: - uint8_t m_portID; - bool m_isConnected; - LogicalAddress m_logicalAddr; - PhysicalAddress m_physicalAddr; - DeviceNode m_deviceChain[3]; - - HdmiPortMap(uint8_t portID) : m_portID(portID), - m_logicalAddr(LogicalAddress::UNREGISTERED), - m_physicalAddr(portID+1,0,0,0) - { - m_isConnected = false; - } - - void update(bool isConnected) - { - m_isConnected = isConnected; - } - - void update( const LogicalAddress &addr ) - { - m_logicalAddr = addr; - } - - void addChild( const LogicalAddress &logical_addr, const PhysicalAddress &physical_addr ) - { - LOGINFO(" logicalAddr = %d, phisicalAddr = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); - - if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED && - m_logicalAddr.toInt() != logical_addr.toInt() ) - { - LOGINFO(" update own logicalAddr = %d, new devcie logicalAddress = %d", m_logicalAddr.toInt(), logical_addr.toInt() ); - /* check matching with this port's physical address */ - if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && - physical_addr.getByteValue(1) != 0 ) - { - if ( physical_addr.getByteValue(3) != 0 ) - { - m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = logical_addr.toInt(); - } - else if ( physical_addr.getByteValue(2) != 0 ) - { - m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = logical_addr.toInt(); - } - else if ( physical_addr.getByteValue(1) != 0 ) - { - m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = logical_addr.toInt(); - } - } - } - else if ( physical_addr == m_physicalAddr ) - { - update(logical_addr); - LOGINFO(" update own logicalAddr = %d", m_logicalAddr.toInt()); - } - } - - void removeChild( PhysicalAddress &physical_addr ) - { - if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) - { - /* check matching with this port's physical address */ - if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && - physical_addr.getByteValue(1) != 0 ) - { - if ( physical_addr.getByteValue(3) != 0 ) - { - m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = LogicalAddress::UNREGISTERED; - } - else if ( physical_addr.getByteValue(2) != 0 ) - { - m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = LogicalAddress::UNREGISTERED; - } - else if ( physical_addr.getByteValue(1) != 0 ) - { - m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = LogicalAddress::UNREGISTERED; - } - } - } - } - - void getRoute( PhysicalAddress &physical_addr, std::vector & route ) - { - LOGINFO(" logicalAddr = %d, phsical = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); - - if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) - { - LOGINFO(" search for logicalAddr = %d", m_logicalAddr.toInt()); - /* check matching with this port's physical address */ - if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && - physical_addr.getByteValue(1) != 0 ) - { - if ( physical_addr.getByteValue(3) != 0 ) - { - route.push_back(m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1]); - } - - if ( physical_addr.getByteValue(2) != 0 ) - { - route.push_back(m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1]); - } - - if ( physical_addr.getByteValue(1) != 0 ) - { - route.push_back(m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1]); - } - - route.push_back(m_logicalAddr.toInt()); - } - else - { - route.push_back(m_logicalAddr.toInt()); - LOGINFO("logicalAddr = %d, physical = %s", m_logicalAddr.toInt(), m_physicalAddr.toString().c_str()); - } - } - } - }; - - class binary_semaphore { - - public: - - explicit binary_semaphore(int init_count = count_max) - - : count_(init_count) {} - - - - // P-operation / acquire - - void wait() - - { - - std::unique_lock lk(m_); - - cv_.wait(lk, [=]{ return 0 < count_; }); - - --count_; - - } - - bool try_wait() - - { - - std::lock_guard lk(m_); - - if (0 < count_) { - - --count_; - - return true; - - } else { - - return false; - - } - - } - - // V-operation / release - - void signal() - - { - - std::lock_guard lk(m_); - - if (count_ < count_max) { - - ++count_; - - cv_.notify_one(); - - } - - } - - - - // Lockable requirements - - void acquire() { wait(); } - - bool try_lock() { return try_wait(); } - - void release() { signal(); } - - - -private: - - static const int count_max = 1; - - int count_; - - std::mutex m_; - - std::condition_variable cv_; - -}; // This is a server for a JSONRPC communication channel. // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. @@ -484,262 +55,211 @@ namespace WPEFramework { // will receive a JSONRPC message as a notification, in case this method is called. class HdmiCecSink : public PluginHost::IPlugin, public PluginHost::JSONRPC { - enum { - POLL_THREAD_STATE_NONE, - POLL_THREAD_STATE_IDLE, - POLL_THREAD_STATE_POLL, - POLL_THREAD_STATE_PING, - POLL_THREAD_STATE_INFO, - POLL_THREAD_STATE_WAIT, - POLL_THREAD_STATE_CLEAN, - POLL_THREAD_STATE_UPDATE, - POLL_THREAD_STATE_EXIT, - }; - enum { - ARC_STATE_REQUEST_ARC_INITIATION, - ARC_STATE_ARC_INITIATED, - ARC_STATE_REQUEST_ARC_TERMINATION, - ARC_STATE_ARC_TERMINATED, - ARC_STATE_ARC_EXIT - }; - enum { - VOLUME_UP = 0x41, - VOLUME_DOWN = 0x42, - MUTE = 0x43, - UP = 0x01, - DOWN = 0x02, - LEFT = 0x03, - RIGHT = 0x04, - SELECT = 0x00, - HOME = 0x09, - BACK = 0x0D, - NUMBER_0 = 0x20, - NUMBER_1 = 0x21, - NUMBER_2 = 0x22, - NUMBER_3 = 0x23, - NUMBER_4 = 0x24, - NUMBER_5 = 0x25, - NUMBER_6 = 0x26, - NUMBER_7 = 0x27, - NUMBER_8 = 0x28, - NUMBER_9 = 0x29 - }; - public: - HdmiCecSink(); - virtual ~HdmiCecSink(); - virtual const string Initialize(PluginHost::IShell* shell) override; - virtual void Deinitialize(PluginHost::IShell* service) override; - virtual string Information() const override { return {}; } - static HdmiCecSink* _instance; - CECDeviceParams deviceList[16]; - std::vector hdmiInputs; - int m_currentActiveSource; - void updateInActiveSource(const int logical_address, const InActiveSource &source ); - void updateActiveSource(const int logical_address, const ActiveSource &source ); - void updateTextViewOn(const int logicalAddress); - void updateImageViewOn(const int logicalAddress); - void updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr); - void getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route); - void removeDevice(const int logicalAddress); - void addDevice(const int logicalAddress); - void printDeviceList(); - void setStreamPath( const PhysicalAddress &physical_addr); - void setRoutingChange(const std::string &from, const std::string &to); - void sendStandbyMessage(); - void setCurrentLanguage(const Language &lang); - void sendMenuLanguage(); - void setActiveSource(bool isResponse); - void requestActiveSource(); - void startArc(); - void stopArc(); - void Process_InitiateArc(); - void Process_TerminateArc(); - void updateArcState(); - void requestShortaudioDescriptor(); - void Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor); - void Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg); - void Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg); - void sendDeviceUpdateInfo(const int logicalAddress); - void sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); - void reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); - void systemAudioModeRequest(); - void SendStandbyMsgEvent(const int logicalAddress); - void requestAudioDevicePowerStatus(); - void reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus); - void updateCurrentLatency(int videoLatency, bool lowLatencyMode, int audioOutputCompensated, int audioOutputDelay); - void setLatencyInfo(); - void Process_ReportAudioStatus_msg(const ReportAudioStatus msg); - void sendKeyPressEvent(const int logicalAddress, int keyCode); - void sendKeyReleaseEvent(const int logicalAddress); - void sendUserControlPressed(const int logicalAddress, int keyCode); - void sendUserControlReleased(const int logicalAddress); - void onPowerModeChanged(const PowerState currentState, const PowerState newState); - void registerEventHandlers(); - void sendGiveAudioStatusMsg(); - void getHdmiArcPortID(); - int m_numberOfDevices; /* Number of connected devices othethan own device */ - bool m_audioDevicePowerStatusRequested; - - BEGIN_INTERFACE_MAP(HdmiCecSink) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - END_INTERFACE_MAP - - private: - class PowerManagerNotification : public Exchange::IPowerManager::IModeChangedNotification { private: - PowerManagerNotification(const PowerManagerNotification&) = delete; - PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; + class Notification : public RPC::IRemoteConnection::INotification, + public Exchange::IHdmiCecSink::INotification + { + private: + Notification() = delete; + Notification(const Notification&) = delete; + Notification& operator=(const Notification&) = delete; + + public: + explicit Notification(HdmiCecSink* parent) + : _parent(*parent) + { + ASSERT(parent != nullptr); + } + + virtual ~Notification() + { + } + + BEGIN_INTERFACE_MAP(Notification) + INTERFACE_ENTRY(Exchange::IHdmiCecSink::INotification) + INTERFACE_ENTRY(RPC::IRemoteConnection::INotification) + END_INTERFACE_MAP + + void Activated(RPC::IRemoteConnection*) override + { + } + + void Deactivated(RPC::IRemoteConnection *connection) override + { + _parent.Deactivated(connection); + } + + void ArcInitiationEvent(const string success) override + { + LOGINFO("ArcInitiationEvent"); + LOGINFO("success: %s", success.c_str()); + Exchange::JHdmiCecSink::Event::ArcInitiationEvent(_parent, success); + } + + void ArcTerminationEvent(const string success) override + { + LOGINFO("ArcTerminationEvent"); + LOGINFO("success: %s", success.c_str()); + Exchange::JHdmiCecSink::Event::ArcTerminationEvent(_parent, success); + } + + void OnActiveSourceChange(const int logicalAddress, const string physicalAddress) override + { + LOGINFO("OnActiveSourceChange"); + LOGINFO("logicalAddress: %d, physicalAddress: %s", logicalAddress, physicalAddress.c_str()); + Exchange::JHdmiCecSink::Event::OnActiveSourceChange(_parent, logicalAddress, physicalAddress); + } + + void OnDeviceAdded(const int logicalAddress) override + { + LOGINFO("OnDeviceAdded"); + LOGINFO("logicalAddress: %d", logicalAddress); + Exchange::JHdmiCecSink::Event::OnDeviceAdded(_parent, logicalAddress); + } + + void OnDeviceInfoUpdated(const int logicalAddress) override + { + LOGINFO("OnDeviceInfoUpdated"); + LOGINFO("logicalAddress: %d", logicalAddress); + Exchange::JHdmiCecSink::Event::OnDeviceInfoUpdated(_parent, logicalAddress); + } + + void OnDeviceRemoved(const int logicalAddress) override + { + LOGINFO("OnDeviceRemoved"); + LOGINFO("logicalAddress: %d", logicalAddress); + Exchange::JHdmiCecSink::Event::OnDeviceRemoved(_parent, logicalAddress); + } + + void OnImageViewOnMsg(const int logicalAddress) override + { + LOGINFO("OnImageViewOnMsg"); + LOGINFO("logicalAddress: %d", logicalAddress); + Exchange::JHdmiCecSink::Event::OnImageViewOnMsg(_parent, logicalAddress); + } + + void OnInActiveSource(const int logicalAddress, const string physicalAddress) override + { + LOGINFO("OnInActiveSource"); + LOGINFO("logicalAddress: %d, physicalAddress: %s", logicalAddress, physicalAddress.c_str()); + Exchange::JHdmiCecSink::Event::OnInActiveSource(_parent, logicalAddress, physicalAddress); + } + + void OnTextViewOnMsg(const int logicalAddress) override + { + LOGINFO("OnTextViewOnMsg"); + LOGINFO("logicalAddress: %d", logicalAddress); + Exchange::JHdmiCecSink::Event::OnTextViewOnMsg(_parent, logicalAddress); + } + + void OnWakeupFromStandby(const int logicalAddress) override + { + LOGINFO("OnWakeupFromStandby"); + LOGINFO("logicalAddress: %d", logicalAddress); + Exchange::JHdmiCecSink::Event::OnWakeupFromStandby(_parent, logicalAddress); + } + + void ReportAudioDeviceConnectedStatus(const string status, const string audioDeviceConnected) override + { + LOGINFO("ReportAudioDeviceConnectedStatus"); + LOGINFO("status: %s, audioDeviceConnected: %s", status.c_str(), audioDeviceConnected.c_str()); + Exchange::JHdmiCecSink::Event::ReportAudioDeviceConnectedStatus(_parent, status, audioDeviceConnected); + } + + void ReportAudioStatusEvent(const int muteStatus, const int volumeLevel) override + { + LOGINFO("ReportAudioStatusEvent"); + LOGINFO("muteStatus: %d, volumeLevel: %d", muteStatus, volumeLevel); + Exchange::JHdmiCecSink::Event::ReportAudioStatusEvent(_parent, muteStatus, volumeLevel); + } + + void ReportFeatureAbortEvent(const int logicalAddress, const int opcode, const int FeatureAbortReason) override + { + LOGINFO("ReportFeatureAbortEvent"); + LOGINFO("logicalAddress: %d, opcode: %d, FeatureAbortReason: %d", logicalAddress, opcode, FeatureAbortReason); + Exchange::JHdmiCecSink::Event::ReportFeatureAbortEvent(_parent, logicalAddress, opcode, FeatureAbortReason); + } + + void ReportCecEnabledEvent(const string cecEnable) override + { + LOGINFO("ReportCecEnabledEvent"); + LOGINFO("cecEnable: %s", cecEnable.c_str()); + Exchange::JHdmiCecSink::Event::ReportCecEnabledEvent(_parent, cecEnable); + } + + void SetSystemAudioModeEvent(const string audioMode) override + { + LOGINFO("SetSystemAudioModeEvent"); + LOGINFO("audioMode: %s", audioMode.c_str()); + Exchange::JHdmiCecSink::Event::SetSystemAudioModeEvent(_parent, audioMode); + } + + void ShortAudiodescriptorEvent(const string& jsonresponse) override + { + LOGINFO("ShortAudiodescriptorEvent"); + Exchange::JHdmiCecSink::Event::ShortAudiodescriptorEvent(_parent, jsonresponse); + } + + void StandbyMessageReceived(const int logicalAddress) override + { + LOGINFO("StandbyMessageReceived"); + LOGINFO("logicalAddress: %d", logicalAddress); + Exchange::JHdmiCecSink::Event::StandbyMessageReceived(_parent, logicalAddress); + } + + void ReportAudioDevicePowerStatus(const int powerStatus) override + { + LOGINFO("ReportAudioDevicePowerStatus"); + LOGINFO("powerStatus: %d", powerStatus); + Exchange::JHdmiCecSink::Event::ReportAudioDevicePowerStatus(_parent, powerStatus); + } + + private: + HdmiCecSink &_parent; + + }; public: - explicit PowerManagerNotification(HdmiCecSink& parent) - : _parent(parent) + // We do not allow this plugin to be copied !! + HdmiCecSink(const HdmiCecSink&) = delete; + HdmiCecSink& operator=(const HdmiCecSink&) = delete; + + HdmiCecSink() + : PluginHost::IPlugin() + , PluginHost::JSONRPC() + , _service(nullptr) + , _notification(this) + , _hdmiCecSink(nullptr) + , _connectionId(0) { - } - ~PowerManagerNotification() override = default; - public: - void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override - { - _parent.onPowerModeChanged(currentState, newState); } - - template - T* baseInterface() + virtual ~HdmiCecSink() { - static_assert(std::is_base_of(), "base type mismatch"); - return static_cast(this); + } - - BEGIN_INTERFACE_MAP(PowerManagerNotification) - INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) + + BEGIN_INTERFACE_MAP(HdmiCecSink) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + INTERFACE_AGGREGATE(Exchange::IHdmiCecSink, _hdmiCecSink) END_INTERFACE_MAP + // IPlugin methods + // ------------------------------------------------------------------------------------------------------- + const string Initialize(PluginHost::IShell* service) override; + void Deinitialize(PluginHost::IShell* service) override; + string Information() const override; + //Begin methods + + private: + void Deactivated(RPC::IRemoteConnection* connection); + private: - HdmiCecSink& _parent; - }; - // We do not allow this plugin to be copied !! - HdmiCecSink(const HdmiCecSink&) = delete; - HdmiCecSink& operator=(const HdmiCecSink&) = delete; - - //Begin methods - uint32_t setEnabledWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getEnabledWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setOSDNameWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getOSDNameWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setVendorIdWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getVendorIdWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t printDeviceListWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setActivePathWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setRoutingChangeWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getDeviceListWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getActiveSourceWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setActiveSourceWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getActiveRouteWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t requestActiveSourceWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setArcEnableDisableWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setMenuLanguageWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t requestShortAudioDescriptorWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t sendAudioDevicePowerOnMsgWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t sendRemoteKeyPressWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t sendUserControlPressedWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t sendUserControlReleasedWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t sendGiveAudioStatusWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getAudioDeviceConnectedStatusWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t requestAudioDevicePowerStatusWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setLatencyInfoWrapper(const JsonObject& parameters, JsonObject& response); - void InitializePowerManager(PluginHost::IShell *service); - //End methods - std::string logicalAddressDeviceType; - bool cecSettingEnabled; - bool cecOTPSettingEnabled; - bool cecEnableStatus; - bool hdmiCecAudioDeviceConnected; - bool m_isHdmiInConnected; - int m_numofHdmiInput; - uint8_t m_deviceType; - int m_logicalAddressAllocated; - std::thread m_pollThread; - uint32_t m_pollThreadState; - uint32_t m_pollNextState; - bool m_pollThreadExit; - uint32_t m_sleepTime; - std::mutex m_pollExitMutex; - std::mutex m_enableMutex; - /* Send Key event related */ - bool m_sendKeyEventThreadExit; - bool m_sendKeyEventThreadRun; - bool m_isAudioStatusInfoUpdated; - bool m_audioStatusReceived; - bool m_audioStatusTimerStarted; - std::thread m_sendKeyEventThread; - std::mutex m_sendKeyEventMutex; - std::queue m_SendKeyQueue; - std::condition_variable m_sendKeyCV; - std::condition_variable m_ThreadExitCV; - - /* DALS - Latency Values */ - uint8_t m_video_latency; - uint8_t m_latency_flags; - uint8_t m_audio_output_delay; - - /* ARC related */ - std::thread m_arcRoutingThread; - uint32_t m_currentArcRoutingState; - std::mutex m_arcRoutingStateMutex; - binary_semaphore m_semSignaltoArcRoutingThread; - bool m_arcstarting; - TpTimer m_arcStartStopTimer; - TpTimer m_audioStatusDetectionTimer; - - Connection *smConnection; - std::vector m_connectedDevices; - HdmiCecSinkProcessor *msgProcessor; - HdmiCecSinkFrameListener *msgFrameListener; - PowerManagerInterfaceRef _powerManagerPlugin; - Core::Sink _pwrMgrNotification; - bool _registeredEventHandlers; - const void InitializeIARM(); - void DeinitializeIARM(); - void allocateLogicalAddress(int deviceType); - void allocateLAforTV(); - void pingDevices(std::vector &connected , std::vector &disconnected); - void CheckHdmiInState(); - void request(const int logicalAddress); - int requestType(const int logicalAddress); - int requestStatus(const int logicalAddress); - static void threadRun(); - void cecMonitoringThread(); - static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - void onHdmiHotPlug(int portId, int connectStatus); - bool loadSettings(); - void persistSettings(bool enableStatus); - void persistOTPSettings(bool enableStatus); - void persistOSDName(const char *name); - void persistVendorId(unsigned int vendorID); - void setEnabled(bool enabled); - bool getEnabled(); - bool getAudioDeviceConnectedStatus(); - void CECEnable(void); - void CECDisable(void); - void getPhysicalAddress(); - void getLogicalAddress(); - void cecAddressesChanged(int changeStatus); - - // Arc functions - - static void threadSendKeyEvent(); - static void threadArcRouting(); - void requestArcInitiation(); - void requestArcTermination(); - void Send_Request_Arc_Initiation_Message(); - void Send_Report_Arc_Initiated_Message(); - void Send_Request_Arc_Termination_Message(); - void Send_Report_Arc_Terminated_Message(); - void arcStartStopTimerFunction(); - void audioStatusTimerFunction(); - void getCecVersion(); + PluginHost::IShell* _service{}; + Core::Sink _notification; + Exchange::IHdmiCecSink* _hdmiCecSink; + uint32_t _connectionId; }; } // namespace Plugin } // namespace WPEFramework diff --git a/HdmiCecSink/HdmiCecSinkImplementation.cpp b/HdmiCecSink/HdmiCecSinkImplementation.cpp new file mode 100644 index 00000000..7363bb76 --- /dev/null +++ b/HdmiCecSink/HdmiCecSinkImplementation.cpp @@ -0,0 +1,3581 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2019 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. +**/ + +#include "HdmiCecSinkImplementation.h" + +#include "ccec/Connection.hpp" +#include "ccec/CECFrame.hpp" +#include "ccec/MessageEncoder.hpp" +#include "host.hpp" +#include "UtilsgetRFCConfig.h" + +#include "dsMgr.h" +#include "dsRpc.h" +#include "dsDisplay.h" +#include "videoOutputPort.hpp" +#include "manager.hpp" +#include "websocket/URL.h" + +#include "UtilsIarm.h" +#include "UtilsJsonRpc.h" +#include "UtilssyncPersistFile.h" +#include "UtilsSearchRDKProfile.h" + +#define TEST_ADD 0 +#define HDMICECSINK_REQUEST_MAX_RETRY 3 +#define HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS 2000 +#define HDMICECSINK_PING_INTERVAL_MS 10000 +#define HDMICECSINK_WAIT_FOR_HDMI_IN_MS 1000 +#define HDMICECSINK_REQUEST_INTERVAL_TIME_MS 500 +#define HDMICECSINK_NUMBER_TV_ADDR 2 +#define HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS (60 * 1000) +#define HDMISINK_ARC_START_STOP_MAX_WAIT_MS 4000 +#define HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS 500 + + +#define SAD_FMT_CODE_AC3 2 +#define SAD_FMT_CODE_ENHANCED_AC3 10 + +#define SYSTEM_AUDIO_MODE_ON 0x01 +#define SYSTEM_AUDIO_MODE_OFF 0x00 +#define AUDIO_DEVICE_POWERSTATE_OFF 1 + +#define DEFAULT_VIDEO_LATENCY 100 +#define DEFAULT_LATENCY_FLAGS 3 +#define DEFAULT_AUDIO_OUTPUT_DELAY 100 + +//Device Type is TV - Bit 7 is set to 1 +#define ALL_DEVICE_TYPES 128 + +//RC Profile of TV is 3 - Typical TV Remote +#define RC_PROFILE_TV 10 + +//Device Features supported by TV - ARC Tx +#define DEVICE_FEATURES_TV 4 + +#define TR181_HDMICECSINK_CEC_VERSION "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.HdmiCecSink.CECVersion" + + +#define CEC_SETTING_ENABLED_FILE "/opt/persistent/ds/cecData_2.json" +#define CEC_SETTING_OTP_ENABLED "cecOTPEnabled" +#define CEC_SETTING_ENABLED "cecEnabled" +#define CEC_SETTING_OSD_NAME "cecOSDName" +#define CEC_SETTING_VENDOR_ID "cecVendorId" + +enum { + DEVICE_POWER_STATE_ON = 0, + DEVICE_POWER_STATE_OFF = 1 +}; + +static std::vector defaultVendorId = {0x00,0x19,0xFB}; +static VendorID appVendorId = {defaultVendorId.at(0),defaultVendorId.at(1),defaultVendorId.at(2)}; +static VendorID lgVendorId = {0x00,0xE0,0x91}; +static PhysicalAddress physical_addr = {0x0F,0x0F,0x0F,0x0F}; +static LogicalAddress logicalAddress = 0xF; +static Language defaultLanguage = "eng"; +static OSDName osdName = "TV Box"; +static int32_t powerState = DEVICE_POWER_STATE_OFF; +static std::vector formatid = {0,0}; +static std::vector audioFormatCode = { SAD_FMT_CODE_ENHANCED_AC3,SAD_FMT_CODE_AC3 }; +static uint8_t numberofdescriptor = 2; +static int32_t HdmiArcPortID = -1; +static float cecVersion = 1.4; +static AllDeviceTypes allDevicetype = ALL_DEVICE_TYPES; +static std::vector rcProfile = {RC_PROFILE_TV}; +static std::vector deviceFeatures = {DEVICE_FEATURES_TV}; + +#define API_VERSION_NUMBER_MAJOR 1 +#define API_VERSION_NUMBER_MINOR 3 +#define API_VERSION_NUMBER_PATCH 7 + +using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; + +namespace WPEFramework +{ + + namespace Plugin + { + SERVICE_REGISTRATION(HdmiCecSinkImplementation, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + + HdmiCecSinkImplementation* HdmiCecSinkImplementation::_instance = nullptr; + static int libcecInitStatus = 0; + +//=========================================== HdmiCecSinkFrameListener ========================================= + void HdmiCecSinkFrameListener::notify(const CECFrame &in) const { + const uint8_t *buf = NULL; + char strBuffer[512] = {0}; + size_t len = 0; + + in.getBuffer(&buf, &len); + for (unsigned int i = 0; i < len; i++) { + snprintf(strBuffer + (i*3) , sizeof(strBuffer) - (i*3), "%02X ",(uint8_t) *(buf + i)); + } + LOGINFO(" >>>>> Received CEC Frame: :%s \n",strBuffer); + + MessageDecoder(processor).decode(in); + } + +//=========================================== HdmiCecSinkProcessor ========================================= + void HdmiCecSinkProcessor::process (const ActiveSource &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); + HdmiCecSinkImplementation::_instance->updateActiveSource(header.from.toInt(), msg); + } + void HdmiCecSinkProcessor::process (const InActiveSource &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: InActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + + HdmiCecSinkImplementation::_instance->updateInActiveSource(header.from.toInt(), msg); + } + + void HdmiCecSinkProcessor::process (const ImageViewOn &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ImageViewOn from %s\n", header.from.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); + HdmiCecSinkImplementation::_instance->updateImageViewOn(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const TextViewOn &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: TextViewOn\n"); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); + HdmiCecSinkImplementation::_instance->updateTextViewOn(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const RequestActiveSourceMessage &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RequestActiveSource\n"); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + + HdmiCecSinkImplementation::_instance->setActiveSource(true); + } + void HdmiCecSinkProcessor::process (const Standby &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Standby from %s\n", header.from.toString().c_str()); + HdmiCecSinkImplementation::_instance->SendStandbyMsgEvent(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const GetCECVersion &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GetCECVersion sending CECVersion response \n"); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + if(cecVersion == 2.0) { + conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_2_0))); + } + else{ + conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_1_4))); + } + } + catch(...) + { + LOGWARN("Exception while sending CECVersion "); + } + } + void HdmiCecSinkProcessor::process (const CECVersion &msg, const Header &header) + { + bool updateStatus; + printHeader(header); + LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); + + HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); + updateStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isVersionUpdated; + LOGINFO("updateStatus %d\n",updateStatus); + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.version); + if(!updateStatus) + HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const SetMenuLanguageMessage &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const GiveOSDName &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveOSDName sending SetOSDName : %s\n",osdName.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + conn.sendToAsync(header.from, MessageEncoder().encode(SetOSDName(osdName))); + } + catch(...) + { + LOGWARN("Exception while sending SetOSDName"); + } + } + void HdmiCecSinkProcessor::process (const GivePhysicalAddress &msg, const Header &header) + { + LOGINFO("Command: GivePhysicalAddress\n"); + if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) + { + try + { + LOGINFO(" sending ReportPhysicalAddress response physical_addr :%s logicalAddress :%x \n",physical_addr.toString().c_str(), logicalAddress.toInt()); + conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ReportPhysicalAddress(physical_addr,logicalAddress.toInt())), 500); + } + catch(...) + { + LOGWARN("Exception while sending ReportPhysicalAddress "); + } + } + } + void HdmiCecSinkProcessor::process (const GiveDeviceVendorID &msg, const Header &header) + { + printHeader(header); + if(header.to == LogicalAddress(LogicalAddress::BROADCAST)){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n",appVendorId.toString().c_str()); + conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); + } + catch(...) + { + LOGWARN("Exception while sending DeviceVendorID"); + } + + } + void HdmiCecSinkProcessor::process (const SetOSDString &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetOSDString OSDString : %s\n",msg.osdString.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const SetOSDName &msg, const Header &header) + { + printHeader(header); + bool updateStatus ; + LOGINFO("Command: SetOSDName OSDName : %s\n",msg.osdName.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + + HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); + updateStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isOSDNameUpdated; + LOGINFO("updateStatus %d\n",updateStatus); + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.osdName); + if(HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_OSD_NAME) { + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; + } + if(!updateStatus) + HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const RoutingChange &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RoutingChange From : %s To: %s \n",msg.from.toString().c_str(),msg.to.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const RoutingInformation &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RoutingInformation Routing Information to Sink : %s\n",msg.toSink.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const SetStreamPath &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetStreamPath Set Stream Path to Sink : %s\n",msg.toSink.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const GetMenuLanguage &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GetMenuLanguage\n"); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSinkImplementation::_instance->sendMenuLanguage(); + } + void HdmiCecSinkProcessor::process (const ReportPhysicalAddress &msg, const Header &header) + { + printHeader(header); + bool updateDeviceTypeStatus; + bool updatePAStatus; + LOGINFO("Command: ReportPhysicalAddress\n"); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + + if(!HdmiCecSinkImplementation::_instance) + return; + HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); + updateDeviceTypeStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isDeviceTypeUpdated; + updatePAStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isPAUpdated; + LOGINFO("updateDeviceTypeStatus %d updatePAStatus %d \n",updateDeviceTypeStatus,updatePAStatus); + if(HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString() != msg.physicalAddress.toString() && updatePAStatus){ + updatePAStatus= false; + LOGINFO("There is a change in physical address from current PA %s to newly reported PA %s\n",HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString().c_str(),msg.physicalAddress.toString().c_str()); + } + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.physicalAddress); + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.deviceType); + if(HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_PHISICAL_ADDRESS) { + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; + } + HdmiCecSinkImplementation::_instance->updateDeviceChain(header.from, msg.physicalAddress); + if (!updateDeviceTypeStatus || !updatePAStatus) + HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const DeviceVendorID &msg, const Header &header) + { + bool updateStatus ; + printHeader(header); + LOGINFO("Command: DeviceVendorID VendorID : %s\n",msg.vendorId.toString().c_str()); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + + HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); + updateStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isVendorIDUpdated; + LOGINFO("updateStatus %d\n",updateStatus); + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.vendorId); + if (!updateStatus) + HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const GiveDevicePowerStatus &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveDevicePowerStatus sending powerState :%d \n",powerState); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + conn.sendTo(header.from, MessageEncoder().encode(ReportPowerStatus(PowerStatus(powerState)))); + } + catch(...) + { + LOGWARN("Exception while sending ReportPowerStatus"); + } + } + void HdmiCecSinkProcessor::process (const ReportPowerStatus &msg, const Header &header) + { + uint32_t oldPowerStatus,newPowerStatus; + printHeader(header); + LOGINFO("Command: ReportPowerStatus Power Status from:%s status : %s \n",header.from.toString().c_str(),msg.status.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + oldPowerStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); + HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.status); + newPowerStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); + LOGINFO(" oldPowerStatus %d newpower status %d \n",oldPowerStatus,newPowerStatus); + if ((oldPowerStatus != newPowerStatus) ) + { + HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + + if((header.from.toInt() == LogicalAddress::AUDIO_SYSTEM) && (HdmiCecSinkImplementation::_instance->m_audioDevicePowerStatusRequested)) { + HdmiCecSinkImplementation::_instance->reportAudioDevicePowerStatusInfo(header.from.toInt(), newPowerStatus); + } + + } + void HdmiCecSinkProcessor::process (const FeatureAbort &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: FeatureAbort opcode=%s, Reason = %s\n", msg.feature.toString().c_str(), msg.reason.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + + if(header.from.toInt() < LogicalAddress::UNREGISTERED && + msg.reason.toInt() == AbortReason::UNRECOGNIZED_OPCODE) + { + switch(msg.feature.opCode()) + { + case GET_CEC_VERSION : + { + /* If we get a Feature abort for CEC Version then default to 1.4b */ + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(Version(Version::V_1_4)); + } + break; + case GIVE_DEVICE_VENDOR_ID : + { + /* If we get a Feature abort for CEC Version then default to 1.4b */ + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(VendorID((uint8_t *)"FA", 2)); + } + break; + + case GIVE_OSD_NAME : + { + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(OSDName("")); + } + break; + + case GIVE_DEVICE_POWER_STATUS : + { + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(PowerStatus(PowerStatus::POWER_STATUS_FEATURE_ABORT)); + } + break; + } + + HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_featureAborts.push_back(msg); + } + + LogicalAddress logicaladdress = header.from.toInt(); + OpCode featureOpcode = msg.feature; + AbortReason abortReason = msg.reason; + + HdmiCecSinkImplementation::_instance->reportFeatureAbortEvent(logicaladdress,featureOpcode,abortReason); + + if(msg.feature.opCode() == REQUEST_SHORT_AUDIO_DESCRIPTOR) + { + JsonArray audiodescriptor; + audiodescriptor.Add(0); + HdmiCecSinkImplementation::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); + } + + } + void HdmiCecSinkProcessor::process (const Abort &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Abort\n"); + if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) + { + AbortReason reason = AbortReason::UNRECOGNIZED_OPCODE; + LogicalAddress logicaladdress =header.from.toInt(); + OpCode feature = msg.opCode(); + HdmiCecSinkImplementation::_instance->sendFeatureAbort(logicaladdress, feature,reason); + } + else + { + LOGINFO("Command: Abort broadcast msg so ignore\n"); + } + } + void HdmiCecSinkProcessor::process (const Polling &msg, const Header &header) { + printHeader(header); + LOGINFO("Command: Polling\n"); + } + + void HdmiCecSinkProcessor::process (const InitiateArc &msg, const Header &header) + { + printHeader(header); + if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ + LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); + return; + } + PhysicalAddress physical_addr_invalid = {0x0F,0x0F,0x0F,0x0F}; + PhysicalAddress physical_addr_arc_port = {0x0F,0x0F,0x0F,0x0F}; + + LOGINFO("Command: INITIATE_ARC \n"); + if(!HdmiCecSinkImplementation::_instance || HdmiArcPortID == -1) + return; + + if (HdmiArcPortID == 0 ) + physical_addr_arc_port = {0x01,0x00,0x00,0x00}; + if (HdmiArcPortID == 1 ) + physical_addr_arc_port = {0x02,0x00,0x00,0x00}; + if (HdmiArcPortID == 2 ) + physical_addr_arc_port = {0x03,0x00,0x00,0x00}; + + if( (HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_arc_port.toString()) || (HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_invalid.toString()) ) { + LOGINFO("Command: INITIATE_ARC InitiateArc success %s \n",HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); + HdmiCecSinkImplementation::_instance->Process_InitiateArc(); + } else { + LOGINFO("Command: INITIATE_ARC InitiateArc ignore %s \n",HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); + } + } + void HdmiCecSinkProcessor::process (const TerminateArc &msg, const Header &header) + { + printHeader(header); + if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ + LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); + return; + } + if(!HdmiCecSinkImplementation::_instance) + return; + HdmiCecSinkImplementation::_instance->Process_TerminateArc(); + } + void HdmiCecSinkProcessor::process (const ReportShortAudioDescriptor &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ReportShortAudioDescriptor %s : %d \n",GetOpName(msg.opCode()),numberofdescriptor); + HdmiCecSinkImplementation::_instance->Process_ShortAudioDescriptor_msg(msg); + } + + void HdmiCecSinkProcessor::process (const SetSystemAudioMode &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetSystemAudioMode %s audio status %d audio status is %s \n",GetOpName(msg.opCode()),msg.status.toInt(),msg.status.toString().c_str()); + HdmiCecSinkImplementation::_instance->Process_SetSystemAudioMode_msg(msg); + } + void HdmiCecSinkProcessor::process (const ReportAudioStatus &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSinkImplementation::_instance->Process_ReportAudioStatus_msg(msg); + } + void HdmiCecSinkProcessor::process (const GiveFeatures &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveFeatures \n"); + try + { + if(cecVersion == 2.0) { + conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST),MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures))); + } + } + catch(...) + { + LOGWARN("Exception while sending ReportFeatures"); + } + } + void HdmiCecSinkProcessor::process (const RequestCurrentLatency &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Request Current Latency :%s, physical address: %s",GetOpName(msg.opCode()),msg.physicaladdress.toString().c_str()); + + if(msg.physicaladdress.toString() == physical_addr.toString()) { + HdmiCecSinkImplementation::_instance->setLatencyInfo(); + } + else { + LOGINFO("Physical Address does not match with TV's physical address"); + return; + } + } +//=========================================== HdmiCecSinkImplementation ========================================= + + HdmiCecSinkImplementation::HdmiCecSinkImplementation() + : _pwrMgrNotification(*this) + , _registeredEventHandlers(false) + { + LOGWARN("Initlaizing HdmiCecSinkImplementation"); + } + + HdmiCecSinkImplementation::~HdmiCecSinkImplementation() + { + if(_powerManagerPlugin) + { + _powerManagerPlugin->Unregister(_pwrMgrNotification.baseInterface()); + _powerManagerPlugin.Reset(); + } + _registeredEventHandlers = false; + + profileType = searchRdkProfile(); + + if (profileType == STB || profileType == NOT_FOUND) + { + LOGINFO("Invalid profile type for TV \n"); + return ; + } + + CECDisable(); + m_currentArcRoutingState = ARC_STATE_ARC_EXIT; + + m_semSignaltoArcRoutingThread.release(); + + try + { + if (m_arcRoutingThread.joinable()) + m_arcRoutingThread.join(); + } + catch(const std::system_error& e) + { + LOGERR("system_error exception in thread join %s", e.what()); + } + catch(const std::exception& e) + { + LOGERR("exception in thread join %s", e.what()); + } + + { + m_sendKeyEventThreadExit = true; + std::unique_lock lk(m_sendKeyEventMutex); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + } + + try + { + if (m_sendKeyEventThread.joinable()) + m_sendKeyEventThread.join(); + } + catch(const std::system_error& e) + { + LOGERR("system_error exception in thread join %s", e.what()); + } + catch(const std::exception& e) + { + LOGERR("exception in thread join %s", e.what()); + } + + HdmiCecSinkImplementation::_instance = nullptr; + DeinitializeIARM(); + } + + Core::hresult HdmiCecSinkImplementation::Configure(PluginHost::IShell *service) + { + InitializePowerManager(service); + profileType = searchRdkProfile(); + + HdmiCecSinkImplementation::_instance = this; + smConnection=NULL; + cecEnableStatus = false; + HdmiCecSinkImplementation::_instance->m_numberOfDevices = 0; + m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; + m_currentActiveSource = -1; + m_isHdmiInConnected = false; + hdmiCecAudioDeviceConnected = false; + m_isAudioStatusInfoUpdated = false; + m_audioStatusReceived = false; + m_audioStatusTimerStarted = false; + m_audioDevicePowerStatusRequested = false; + m_pollNextState = POLL_THREAD_STATE_NONE; + m_pollThreadState = POLL_THREAD_STATE_NONE; + m_video_latency = DEFAULT_VIDEO_LATENCY; + m_latency_flags = DEFAULT_LATENCY_FLAGS ; + m_audio_output_delay = DEFAULT_AUDIO_OUTPUT_DELAY; + + logicalAddressDeviceType = "None"; + logicalAddress = 0xFF; + // load persistence setting + loadSettings(); + + int err; + dsHdmiInGetNumberOfInputsParam_t hdmiInput; + InitializeIARM(); + m_sendKeyEventThreadExit = false; + m_sendKeyEventThread = std::thread(threadSendKeyEvent); + + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + m_semSignaltoArcRoutingThread.acquire(); + m_arcRoutingThread = std::thread(threadArcRouting); + + m_audioStatusDetectionTimer.connect( std::bind( &HdmiCecSinkImplementation::audioStatusTimerFunction, this ) ); + m_audioStatusDetectionTimer.setSingleShot(true); + m_arcStartStopTimer.connect( std::bind( &HdmiCecSinkImplementation::arcStartStopTimerFunction, this ) ); + m_arcStartStopTimer.setSingleShot(true); + + // get power state: + uint32_t res = Core::ERROR_GENERAL; + PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + + ASSERT (_powerManagerPlugin); + if (_powerManagerPlugin) { + res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); + if (Core::ERROR_NONE == res) { + powerState = (pwrStateCur == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) ? DEVICE_POWER_STATE_ON : DEVICE_POWER_STATE_OFF; + LOGINFO("Current state is PowerManagerPlugin: (%d) powerState :%d \n", pwrStateCur, powerState); + } + } + + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + IARM_BUS_DSMGR_API_dsHdmiInGetNumberOfInputs, + (void *)&hdmiInput, + sizeof(hdmiInput)); + + if (err == IARM_RESULT_SUCCESS && hdmiInput.result == dsERR_NONE) + { + LOGINFO("Number of Inputs [%d] \n", hdmiInput.numHdmiInputs ); + m_numofHdmiInput = hdmiInput.numHdmiInputs; + }else{ + LOGINFO("Not able to get Numebr of inputs so defaulting to 3 \n"); + m_numofHdmiInput = 3; + } + + LOGINFO("initalize inputs \n"); + + for (int i = 0; i < m_numofHdmiInput; i++){ + HdmiPortMap hdmiPort((uint8_t)i); + LOGINFO(" Add to vector [%d] \n", i); + hdmiInputs.push_back(hdmiPort); + } + + LOGINFO("Check the HDMI State \n"); + + CheckHdmiInState(); + if (cecSettingEnabled) + { + try + { + CECEnable(); + } + catch(...) + { + LOGWARN("Exception while enabling CEC settings .\r\n"); + } + } + getCecVersion(); + LOGINFO(" HdmiCecSinkImplementation plugin Initialize completed \n"); + return Core::ERROR_NONE; + + } + + Core::hresult HdmiCecSinkImplementation::Register(Exchange::IHdmiCecSink::INotification* notification) + { + LOGINFO("Register"); + if(notification != nullptr){ + _adminLock.Lock(); + if(std::find(_hdmiCecSinkNotifications.begin(), _hdmiCecSinkNotifications.end(), notification) == _hdmiCecSinkNotifications.end()) + { + _hdmiCecSinkNotifications.push_back(notification); + notification->AddRef(); + } + else + { + LOGERR("Same notification is registered already"); + } + _adminLock.Unlock(); + } + + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::Unregister(Exchange::IHdmiCecSink::INotification* notification) + { + LOGINFO("Unregister"); + if(notification != nullptr){ + _adminLock.Lock(); + std::list::iterator index = std::find(_hdmiCecSinkNotifications.begin(), _hdmiCecSinkNotifications.end(), notification); + if(index != _hdmiCecSinkNotifications.end()) + { + (*index)->Release(); + _hdmiCecSinkNotifications.erase(index); + } + else + { + LOGERR("Notification is not registered"); + } + _adminLock.Unlock(); + } + + return Core::ERROR_NONE; + } + + + const void HdmiCecSinkImplementation::InitializeIARM() + { + if (Utils::IARM::init()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); + } + } + + void HdmiCecSinkImplementation::DeinitializeIARM() + { + if (Utils::IARM::isConnected()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); + } + } + + void HdmiCecSinkImplementation::InitializePowerManager(PluginHost::IShell *service) + { + _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) + .withIShell(service) + .withRetryIntervalMS(200) + .withRetryCount(25) + .createInterface(); + registerEventHandlers(); + } + void HdmiCecSinkImplementation::registerEventHandlers() + { + ASSERT (_powerManagerPlugin); + + if(!_registeredEventHandlers && _powerManagerPlugin) { + _registeredEventHandlers = true; + _powerManagerPlugin->Register(_pwrMgrNotification.baseInterface()); + } + } + + void HdmiCecSinkImplementation::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if (IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + bool isHdmiConnected = eventData->data.hdmi_in_connect.isPortConnected; + dsHdmiInPort_t portId = eventData->data.hdmi_in_connect.port; + LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG event port: %d data:%d \r\n",portId, isHdmiConnected); + HdmiCecSinkImplementation::_instance->onHdmiHotPlug(portId,isHdmiConnected); + } + } + + void HdmiCecSinkImplementation::onPowerModeChanged(const PowerState ¤tState, const PowerState &newState) + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", + currentState, newState); + LOGWARN(" m_logicalAddressAllocated 0x%x CEC enable status %d \n",_instance->m_logicalAddressAllocated,_instance->cecEnableStatus); + if(newState == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) + { + powerState = DEVICE_POWER_STATE_ON; + } + else + { + powerState = DEVICE_POWER_STATE_OFF; + if((_instance->m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_INITIATION) || (_instance->m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) + { + LOGINFO("%s: Stop ARC \n",__FUNCTION__); + _instance->stopArc(); + } + + } + if (_instance->cecEnableStatus) + { + if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED ) + { + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); + + if ( powerState != DEVICE_POWER_STATE_ON ) + { + /* reset the current active source when TV on going to standby */ + HdmiCecSinkImplementation::_instance->m_currentActiveSource = -1; + } + /* Initiate a ping straight away */ + HdmiCecSinkImplementation::_instance->m_pollNextState = POLL_THREAD_STATE_PING; + HdmiCecSinkImplementation::_instance->m_ThreadExitCV.notify_one(); + } + } + else + { + LOGWARN("CEC not Enabled\n"); + } + } + + + void HdmiCecSinkImplementation::sendStandbyMessage() + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + if(!(HdmiCecSinkImplementation::_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(Standby()), 1000); + } + + void HdmiCecSinkImplementation::onHdmiHotPlug(int portId , int connectStatus) + { + LOGINFO("onHdmiHotPlug Status : %d ", connectStatus); + if(!connectStatus) + { + LOGINFO(" removeDevice port: %d Logical address :%d \r\n",portId,hdmiInputs[portId].m_logicalAddr.toInt() ); + _instance->removeDevice(hdmiInputs[portId].m_logicalAddr.toInt()); + } + CheckHdmiInState(); + + if(cecEnableStatus) { + LOGINFO("cecEnableStatus : %d Trigger CEC Ping !!! \n", cecEnableStatus); + m_pollNextState = POLL_THREAD_STATE_PING; + m_ThreadExitCV.notify_one(); + } + if( HdmiArcPortID >= 0 ) { + updateArcState(); + } + return; + } + void HdmiCecSinkImplementation::updateArcState() + { + if ( m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED ) + { + if (!(hdmiInputs[HdmiArcPortID].m_isConnected)) + { + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + } + else + { + LOGINFO("updateArcState :not updating ARC state current arc state %d ",m_currentArcRoutingState); + } + } + } + void HdmiCecSinkImplementation::arcStartStopTimerFunction() + { + JsonObject params; + + if (m_arcstarting) + { + LOGINFO("arcStartStopTimerFunction ARC start timer expired"); + LOGINFO("notify_device setting that Initiate ARC failed to get the ARC_STATE_ARC_INITIATED state\n"); + params["status"] = string("failure"); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ArcInitiationEvent("failure"); + index++; + } + } + else + { + LOGINFO("arcStartStopTimerFunction ARC stop timer expired"); + LOGINFO("notify_device setting that Terminate ARC failed to get the ARC_STATE_ARC_TERMINATED state\n"); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ArcTerminationEvent("failure"); + index++; + } + } + /* bring the state machine to the clean state for a new start */ + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + } + void HdmiCecSinkImplementation::Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor) + { + + LOGINFO("Notify the DS "); + string shortAudioDescriptors; + + if (!audiodescriptor.ToString(shortAudioDescriptors)) { + LOGERR("Failed to stringify JsonArray"); + } + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ShortAudiodescriptorEvent(shortAudioDescriptors); + index++; + } + } + + void HdmiCecSinkImplementation::Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg) + { + uint8_t numberofdescriptor = msg.numberofdescriptor; + uint32_t descriptor =0; + JsonArray audiodescriptor; + + if (numberofdescriptor) + { + for( uint8_t i=0; i < numberofdescriptor; i++) + { + descriptor = msg.shortAudioDescriptor[i].getAudiodescriptor(); + + LOGINFO("descriptor%d 0x%x\n",i,descriptor); + audiodescriptor.Add(descriptor); + + } + } + else + { + audiodescriptor.Add(descriptor); + } + HdmiCecSinkImplementation::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); + } + + void HdmiCecSinkImplementation::updateCurrentLatency(int videoLatency, bool lowLatencyMode,int audioOutputCompensated, int audioOutputDelay = 0) + { + uint8_t latencyFlags = 0; + latencyFlags = ((lowLatencyMode & 0x1) << 2) | (audioOutputCompensated & 0x3); + LOGINFO("Video Latency : %d , Low Latency Mode : %d ,Audio Output Compensated value : %d , Audio Output Delay : %d , Latency Flags: %d ", videoLatency, lowLatencyMode, audioOutputCompensated, audioOutputDelay, latencyFlags); + m_video_latency = (videoLatency/2) + 1; + m_latency_flags = latencyFlags; + m_audio_output_delay = (audioOutputDelay/2) + 1; + setLatencyInfo(); + } + + void HdmiCecSinkImplementation::setLatencyInfo() + { + if(!HdmiCecSinkImplementation::_instance) + return; + + if(!(_instance->smConnection)) + return; + + LOGINFO("Send Report Current Latency message \n"); + _instance->smConnection->sendTo(LogicalAddress::BROADCAST,MessageEncoder().encode(ReportCurrentLatency(physical_addr,m_video_latency,m_latency_flags,m_audio_output_delay))); + + } + + void HdmiCecSinkImplementation::Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg) + { + if(!HdmiCecSinkImplementation::_instance) + return; + + //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status + //SetSystemAudioMode message may come from AVR/Soundbar while CEC disable is in-progress + if ( cecSettingEnabled != true ) + { + LOGINFO("Process SetSystemAudioMode from Audio device: Cec is disabled-> EnableCEC first"); + return; + } + + if ( (msg.status.toInt() == SYSTEM_AUDIO_MODE_OFF) && (m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) + { + /* ie system audio mode off -> amplifier goign to standby but still ARC is in initiated state,stop ARC and + bring the ARC state machine to terminated state*/ + LOGINFO("system audio mode off message but arc is not in terminated state so stopping ARC"); + stopArc(); + + } + + if (msg.status.toInt() == SYSTEM_AUDIO_MODE_ON) { + LOGINFO("panel power state is %s", powerState ? "Off" : "On"); + if (powerState == DEVICE_POWER_STATE_ON ) { + LOGINFO("Notifying system audio mode ON event"); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->SetSystemAudioModeEvent(msg.status.toString()); + index++; + } + } else { + LOGINFO("Not notifying system audio mode ON event"); + } + } else { + LOGINFO("Notifying system audio Mode OFF event"); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->SetSystemAudioModeEvent(msg.status.toString()); + index++; + } + } + } + void HdmiCecSinkImplementation::Process_ReportAudioStatus_msg(const ReportAudioStatus msg) + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + if (m_audioStatusTimerStarted) + { + m_audioStatusReceived = true; + m_isAudioStatusInfoUpdated = true; + m_audioStatusTimerStarted = false; + if (m_audioStatusDetectionTimer.isActive()) + { + LOGINFO("AudioStatus received from the Audio Device and the timer is still active. So stopping the timer!\n"); + m_audioStatusDetectionTimer.stop(); + } + LOGINFO("AudioStatus received from the Audio Device. Updating the AudioStatus info! m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + } + LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ReportAudioStatusEvent(msg.status.getAudioMuteStatus(), msg.status.getAudioVolume()); + index++; + } + + } + void HdmiCecSinkImplementation::sendKeyPressEvent(const int logicalAddress, int keyCode) + { + if(!(_instance->smConnection)) + return; + LOGINFO(" sendKeyPressEvent logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); + switch(keyCode) + { + case VOLUME_UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); + break; + case VOLUME_DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); + break; + case MUTE: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); + break; + case UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); + break; + case DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); + break; + case LEFT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); + break; + case RIGHT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); + break; + case SELECT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); + break; + case HOME: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); + break; + case BACK: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); + break; + case NUMBER_0: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); + break; + case NUMBER_1: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); + break; + case NUMBER_2: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); + break; + case NUMBER_3: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); + break; + case NUMBER_4: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); + break; + case NUMBER_5: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); + break; + case NUMBER_6: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); + break; + case NUMBER_7: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); + break; + case NUMBER_8: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); + break; + case NUMBER_9: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); + break; + + } + } + + void HdmiCecSinkImplementation::sendUserControlPressed(const int logicalAddress, int keyCode) + { + if(!(_instance->smConnection)) + return; + LOGINFO(" sendUserControlPressed logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); + switch(keyCode) + { + case VOLUME_UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); + break; + case VOLUME_DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); + break; + case MUTE: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); + break; + case UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); + break; + case DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); + break; + case LEFT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); + break; + case RIGHT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); + break; + case SELECT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); + break; + case HOME: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); + break; + case BACK: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); + break; + case NUMBER_0: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); + break; + case NUMBER_1: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); + break; + case NUMBER_2: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); + break; + case NUMBER_3: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); + break; + case NUMBER_4: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); + break; + case NUMBER_5: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); + break; + case NUMBER_6: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); + break; + case NUMBER_7: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); + break; + case NUMBER_8: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); + break; + case NUMBER_9: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); + break; + + } + } + + void HdmiCecSinkImplementation::sendKeyReleaseEvent(const int logicalAddress) + { + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); + + } + + void HdmiCecSinkImplementation::sendUserControlReleased(const int logicalAddress) + { + if(!(_instance->smConnection)) + return; + LOGINFO(" User Control Released \n"); + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); + } + + void HdmiCecSinkImplementation::sendDeviceUpdateInfo(const int logicalAddress) + { + LOGINFO("Send Device Update Info \n"); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnDeviceInfoUpdated(logicalAddress); + index++; + } + } + void HdmiCecSinkImplementation::systemAudioModeRequest() + { + if ( cecEnableStatus != true ) + { + LOGINFO("systemAudioModeRequest: Cec is disabled-> EnableCEC first"); + return; + } + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + if(!(_instance->smConnection)) + { + return; + } + LOGINFO(" Send systemAudioModeRequest "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(SystemAudioModeRequest(physical_addr)), 1000); + + } + void HdmiCecSinkImplementation::sendGiveAudioStatusMsg() + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + if(!(_instance->smConnection)) + { + return; + } + LOGINFO(" Send GiveAudioStatus "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(GiveAudioStatus()), 100); + + } + void HdmiCecSinkImplementation::reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus) + { + JsonObject params; + params["powerStatus"] = JsonValue(powerStatus); + LOGINFO("Panle power state is %s", powerState ? "Off" : "On"); + if (powerStatus != AUDIO_DEVICE_POWERSTATE_OFF) { + if (powerState == DEVICE_POWER_STATE_ON ) { + LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ReportAudioDevicePowerStatus(powerStatus); + index++; + } + } else { + LOGINFO("Not notifying audio device power state to DS"); + } + } else { + LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ReportAudioDevicePowerStatus(powerStatus); + index++; + } + } + } + + void HdmiCecSinkImplementation::SendStandbyMsgEvent(const int logicalAddress) + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->StandbyMessageReceived(logicalAddress); + index++; + } + + } + Core::hresult HdmiCecSinkImplementation::SetEnabled(const bool &enabled, HdmiCecSinkSuccess &success) + { + + setEnabled(enabled); + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::GetEnabled(bool &enabled, bool &success) + { + enabled = getEnabled(); + success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::GetAudioDeviceConnectedStatus(bool &connected, bool &success) + { + connected = getAudioDeviceConnectedStatus(); + success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::GetActiveSource(bool &available, uint8_t &logicalAddress, string &physicalAddress, string &deviceType, string &cecVersion, string &osdName, string &vendorID, string &powerStatus, string &port, bool &success) + { + char routeString[1024] = {'\0'}; + int length = 0; + std::stringstream temp; + + if ( HdmiCecSinkImplementation::_instance->m_currentActiveSource != -1 ) + { + int n = HdmiCecSinkImplementation::_instance->m_currentActiveSource; + available = true; + logicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt(); + physicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.toString().c_str(); + deviceType = HdmiCecSinkImplementation::_instance->deviceList[n].m_deviceType.toString().c_str(); + cecVersion = HdmiCecSinkImplementation::_instance->deviceList[n].m_cecVersion.toString().c_str(); + osdName = HdmiCecSinkImplementation::_instance->deviceList[n].m_osdName.toString().c_str(); + vendorID = HdmiCecSinkImplementation::_instance->deviceList[n].m_vendorID.toString().c_str(); + powerStatus = HdmiCecSinkImplementation::_instance->deviceList[n].m_powerStatus.toString().c_str(); + + + if ( HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.getByteValue(0) != 0 ) + { + snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.getByteValue(0) - 1)); + } + else if ( HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.getByteValue(0) == 0 ) + { + snprintf(&routeString[length], sizeof(routeString) - length, "%s", "TV"); + } + + temp << (char *)routeString; + port = temp.str(); + + } + else + { + available = false; + } + + success = true; + return Core::ERROR_NONE; + + } + + Core::hresult HdmiCecSinkImplementation::GetDeviceList(uint32_t &numberofdevices, IHdmiCecSinkDeviceListIterator*& deviceList, bool &success) + { + + numberofdevices = HdmiCecSinkImplementation::_instance->m_numberOfDevices; + LOGINFO("getDeviceList m_numberOfDevices :%d \n", HdmiCecSinkImplementation::_instance->m_numberOfDevices); + std::vector localDevices; + Exchange::IHdmiCecSink::HdmiCecSinkDevices actual_hdmicecdevices = {0}; + + for (int n = 0; n <= LogicalAddress::UNREGISTERED; n++) + { + + if ( n != HdmiCecSinkImplementation::_instance->m_logicalAddressAllocated && + HdmiCecSinkImplementation::_instance->deviceList[n].m_isDevicePresent ) + { + + actual_hdmicecdevices.logicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt(); + actual_hdmicecdevices.physicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.toString().c_str(); + actual_hdmicecdevices.deviceType = HdmiCecSinkImplementation::_instance->deviceList[n].m_deviceType.toString().c_str(); + actual_hdmicecdevices.cecVersion = HdmiCecSinkImplementation::_instance->deviceList[n].m_cecVersion.toString().c_str(); + actual_hdmicecdevices.osdName = HdmiCecSinkImplementation::_instance->deviceList[n].m_osdName.toString().c_str(); + actual_hdmicecdevices.vendorID = HdmiCecSinkImplementation::_instance->deviceList[n].m_vendorID.toString().c_str(); + actual_hdmicecdevices.powerStatus = HdmiCecSinkImplementation::_instance->deviceList[n].m_powerStatus.toString().c_str(); + int hdmiPortNumber = -1; + LOGINFO("getDeviceList m_numofHdmiInput:%d looking for Logical Address :%d \n", m_numofHdmiInput, HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt()); + for (int i=0; i < m_numofHdmiInput; i++) + { + LOGINFO("getDeviceList connected : %d, portid:%d LA: %d \n", hdmiInputs[i].m_isConnected, hdmiInputs[i].m_portID, hdmiInputs[i].m_logicalAddr.toInt()); + if(hdmiInputs[i].m_isConnected && hdmiInputs[i].m_logicalAddr.toInt() == HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt()) + { + hdmiPortNumber = hdmiInputs[i].m_portID; + LOGINFO("got portid :%d break \n", hdmiPortNumber); + break; + } + } + actual_hdmicecdevices.powerStatus = hdmiPortNumber; + localDevices.push_back(actual_hdmicecdevices); + } + } + + deviceList = (Core::Service>::Create(localDevices)); + success = true; + return Core::ERROR_NONE; + } + + + Core::hresult HdmiCecSinkImplementation::SetOSDName(const string &name, HdmiCecSinkSuccess &success) + { + + LOGINFO("SetOSDName osdName: %s",name.c_str()); + osdName = name.c_str(); + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_OSD_NAME, JsonValue(name.c_str())); + + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::GetOSDName(string &name, bool &success) + { + name = osdName.toString(); + LOGINFO("GetOSDName osdName : %s \n",osdName.toString().c_str()); + success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::PrintDeviceList(bool &printed, bool &success) + { + printDeviceList(); + printed = true; + success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::SetActiveSource(HdmiCecSinkSuccess &success) + { + setActiveSource(false); + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::SetActivePath(const string &activePath, HdmiCecSinkSuccess &success) + { + string activePathStr = activePath; + PhysicalAddress phy_addr = PhysicalAddress(activePathStr); + LOGINFO("Addr = %s, length = %zu", activePathStr.c_str(), activePathStr.length()); + setStreamPath(phy_addr); + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::GetActiveRoute(bool &available, uint8_t &length, IHdmiCecSinkActivePathIterator*& pathList, string &ActiveRoute, bool &success) + { + std::vector route; + char routeString[1024] = {'\0'}; + std::vector paths; + std::stringstream temp; + + if (HdmiCecSinkImplementation::_instance->m_currentActiveSource != -1 && + HdmiCecSinkImplementation::_instance->m_currentActiveSource != HdmiCecSinkImplementation::_instance->m_logicalAddressAllocated ) + { + HdmiCecSinkImplementation::_instance->getActiveRoute(LogicalAddress(HdmiCecSinkImplementation::_instance->m_currentActiveSource), route); + + if (route.size()) + { + available = true; + length = route.size(); + + for (unsigned int i=0; i < route.size(); i++) + { + if ( route[i] != LogicalAddress::UNREGISTERED ) + { + Exchange::IHdmiCecSink::HdmiCecSinkActivePath device; + + device.logicalAddress = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_logicalAddress.toInt(); + device.physicalAddress = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_physicalAddr.toString().c_str(); + device.deviceType = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_deviceType.toString().c_str(); + device.vendorID = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_osdName.toString().c_str(); + device.osdName = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_vendorID.toString().c_str(); + + paths.push_back(device); + + snprintf(&routeString[length], sizeof(routeString) - length, "%s", _instance->deviceList[route[i]].m_logicalAddress.toString().c_str()); + length += _instance->deviceList[route[i]].m_logicalAddress.toString().length(); + snprintf(&routeString[length], sizeof(routeString) - length, "(%s", _instance->deviceList[route[i]].m_osdName.toString().c_str()); + length += _instance->deviceList[route[i]].m_osdName.toString().length(); + snprintf(&routeString[length], sizeof(routeString) - length, "%s", ")-->"); + length += strlen(")-->"); + if( i + 1 == route.size() ) + { + snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_physicalAddr.getByteValue(0) - 1)); + } + } + } + + pathList = (Core::Service>::Create(paths)); + temp << (char *)routeString; + ActiveRoute = temp.str(); + LOGINFO("ActiveRoute = [%s]", routeString); + } + else{ + available = false; + } + + } + else if ( HdmiCecSinkImplementation::_instance->m_currentActiveSource == HdmiCecSinkImplementation::_instance->m_logicalAddressAllocated ) + { + available = true; + ActiveRoute = "TV"; + } + else + { + available = false; + } + + success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::RequestActiveSource(HdmiCecSinkSuccess &success) + { + requestActiveSource(); + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::SetRoutingChange(const string &oldPort, const string &newPort, HdmiCecSinkSuccess &success) + { + if ((oldPort.find("HDMI",0) != std::string::npos || + oldPort.find("TV",0) != std::string::npos ) && + (newPort.find("HDMI", 0) != std::string::npos || + newPort.find("TV", 0) != std::string::npos )) + { + setRoutingChange(oldPort, newPort); + success.success = true; + } + else + { + success.success = false; + } + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::SetMenuLanguage(const string &language, HdmiCecSinkSuccess &success) + { + std::string lang; + + lang = language; + + setCurrentLanguage(Language(lang.data())); + success.success = true; + + return Core::ERROR_NONE; + + } + + + Core::hresult HdmiCecSinkImplementation::SetVendorId(const string &vendorId, HdmiCecSinkSuccess &success) + { + + unsigned int vendorID = 0x00; + try + { + vendorID = stoi(vendorId,NULL,16); + } + catch (...) + { + LOGWARN("Exception in setVendorId set default value\n"); + vendorID = 0x0019FB; + } + appVendorId = {(uint8_t)(vendorID >> 16 & 0xff),(uint8_t)(vendorID>> 8 & 0xff),(uint8_t) (vendorID & 0xff)}; + LOGINFO("appVendorId : %s vendorID :%x \n",appVendorId.toString().c_str(), vendorID ); + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_VENDOR_ID, JsonValue(vendorID)); + + success.success = true; + return Core::ERROR_NONE; + } + Core::hresult HdmiCecSinkImplementation::SetupARCRouting(const bool &enabled, HdmiCecSinkSuccess &success) + { + if(enabled) + { + startArc(); + } + else + { + stopArc(); + } + + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::GetVendorId(string &vendorid, bool &success) + { + LOGINFO("GetVendorId appVendorId : %s \n",appVendorId.toString().c_str()); + vendorid = appVendorId.toString() ; + success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::RequestShortAudioDescriptor(HdmiCecSinkSuccess &success) + { + requestShortaudioDescriptor(); + success.success = true; + return Core::ERROR_NONE; + } + Core::hresult HdmiCecSinkImplementation::SendStandbyMessage(HdmiCecSinkSuccess &success) + { + sendStandbyMessage(); + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::SendAudioDevicePowerOnMessage(HdmiCecSinkSuccess &success) + { + LOGINFO("%s invoked. \n",__FUNCTION__); + systemAudioModeRequest(); + success.success = true; + return Core::ERROR_NONE; + } + Core::hresult HdmiCecSinkImplementation::SendKeyPressEvent(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) + { + SendKeyInfo keyInfo; + + keyInfo.logicalAddr = logicalAddress; + keyInfo.keyCode = keyCode; + keyInfo.UserControl = "sendKeyPressEvent"; + std::unique_lock lk(m_sendKeyEventMutex); + m_SendKeyQueue.push(keyInfo); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + LOGINFO("Post send key press event to queue size:%zu \n",m_SendKeyQueue.size()); + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::SendUserControlPressed(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) + { + + SendKeyInfo keyInfo; + keyInfo.logicalAddr = logicalAddress; + keyInfo.keyCode = keyCode; + keyInfo.UserControl = "sendUserControlPressed"; + std::unique_lock lk(m_sendKeyEventMutex); + m_SendKeyQueue.push(keyInfo); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + LOGINFO("User control pressed, queue size:%zu \n",m_SendKeyQueue.size()); + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::SendUserControlReleased(const uint32_t &logicalAddress, HdmiCecSinkSuccess &success) + { + SendKeyInfo keyInfo; + keyInfo.logicalAddr = logicalAddress; + keyInfo.keyCode = 0; + keyInfo.UserControl = "sendUserControlReleased"; + std::unique_lock lk(m_sendKeyEventMutex); + m_SendKeyQueue.push(keyInfo); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + LOGINFO("User Control Released, queue size:%zu \n",m_SendKeyQueue.size()); + success.success = true; + return Core::ERROR_NONE; + } + + Core::hresult HdmiCecSinkImplementation::SendGetAudioStatusMessage(HdmiCecSinkSuccess &success) + { + sendGiveAudioStatusMsg(); + success.success = true; + return Core::ERROR_NONE; + } + Core::hresult HdmiCecSinkImplementation::SetLatencyInfo(const string &videoLatency, const string &lowLatencyMode, const string &audioOutputCompensated, const string &audioOutputDelay, HdmiCecSinkSuccess &success) + { + int video_latency,audio_output_compensated,audio_output_delay; + bool low_latency_mode; + + LOGINFO("SetLatencyInfo videoLatency : %s lowLatencyMode : %s audioOutputCompensated : %s audioOutputDelay : %s \n",videoLatency.c_str(),lowLatencyMode.c_str(),audioOutputCompensated.c_str(),audioOutputDelay.c_str()); + video_latency = stoi(videoLatency); + low_latency_mode = stoi(lowLatencyMode); + audio_output_compensated = stoi(audioOutputCompensated); + audio_output_delay = stoi(audioOutputDelay); + + updateCurrentLatency(video_latency, low_latency_mode,audio_output_compensated, audio_output_delay); + success.success = true; + return Core::ERROR_NONE; + } + bool HdmiCecSinkImplementation::loadSettings() + { + Core::File file; + file = CEC_SETTING_ENABLED_FILE; + + if( file.Open()) + { + JsonObject parameters; + parameters.IElement::FromFile(file); + bool isConfigAdded = false; + + if( parameters.HasLabel(CEC_SETTING_ENABLED)) + { + getBoolParameter(CEC_SETTING_ENABLED, cecSettingEnabled); + LOGINFO("CEC_SETTING_ENABLED present value:%d",cecSettingEnabled); + } + else + { + parameters[CEC_SETTING_ENABLED] = true; + cecSettingEnabled = true; + isConfigAdded = true; + LOGINFO("CEC_SETTING_ENABLED not present set dafult true:\n "); + } + + if( parameters.HasLabel(CEC_SETTING_OTP_ENABLED)) + { + getBoolParameter(CEC_SETTING_OTP_ENABLED, cecOTPSettingEnabled); + LOGINFO("CEC_SETTING_OTP_ENABLED present value :%d",cecOTPSettingEnabled); + } + else + { + parameters[CEC_SETTING_OTP_ENABLED] = true; + cecOTPSettingEnabled = true; + isConfigAdded = true; + LOGINFO("CEC_SETTING_OTP_ENABLED not present set dafult true:\n "); + } + if( parameters.HasLabel(CEC_SETTING_OSD_NAME)) + { + std::string osd_name; + getStringParameter(CEC_SETTING_OSD_NAME, osd_name); + osdName = osd_name.c_str(); + LOGINFO("CEC_SETTING_OSD_NAME present osd_name :%s",osdName.toString().c_str()); + } + else + { + parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); + LOGINFO("CEC_SETTING_OSD_NMAE not present set dafult value :%s\n ",osdName.toString().c_str()); + isConfigAdded = true; + } + unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); + if( parameters.HasLabel(CEC_SETTING_VENDOR_ID)) + { + getNumberParameter(CEC_SETTING_VENDOR_ID, vendorId); + LOGINFO("CEC_SETTING_VENDOR_ID present :%x ",vendorId); + } + else + { + LOGINFO("CEC_SETTING_VENDOR_ID not present set dafult value :%x \n ",vendorId); + parameters[CEC_SETTING_VENDOR_ID] = vendorId; + isConfigAdded = true; + } + + appVendorId = {(uint8_t)(vendorId >> 16 & 0xff),(uint8_t)(vendorId >> 8 & 0xff),(uint8_t) (vendorId & 0xff)}; + LOGINFO("appVendorId : %s vendorId :%x \n",appVendorId.toString().c_str(), vendorId ); + + if(isConfigAdded) + { + LOGINFO("isConfigAdded true so update file:\n "); + file.Destroy(); + file.Create(); + parameters.IElement::ToFile(file); + + } + + file.Close(); + } + else + { + LOGINFO("CEC_SETTING_ENABLED_FILE file not present create with default settings "); + file.Open(false); + if (!file.IsOpen()) + file.Create(); + + JsonObject parameters; + unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); + parameters[CEC_SETTING_ENABLED] = true; + parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); + parameters[CEC_SETTING_VENDOR_ID] = vendorId; + + cecSettingEnabled = true; + cecOTPSettingEnabled = true; + parameters.IElement::ToFile(file); + + file.Close(); + + } + + return cecSettingEnabled; + } + + void HdmiCecSinkImplementation::setEnabled(bool enabled) + { + LOGINFO("Entered setEnabled: %d cecSettingEnabled :%d ",enabled, cecSettingEnabled); + + if (cecSettingEnabled != enabled) + { + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_ENABLED, JsonValue(enabled)); + cecSettingEnabled = enabled; + } + if(true == enabled) + { + CECEnable(); + } + else + { + CECDisable(); + } + return; + } + + void HdmiCecSinkImplementation::updateImageViewOn(const int logicalAddress) + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || + logicalAddress == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress].m_isDevicePresent && + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) + { + /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnWakeupFromStandby(logicalAddress); + index++; + } + } + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnInActiveSource(logicalAddress, _instance->deviceList[logicalAddress].m_physicalAddr.toString()); + index++; + } + } + + void HdmiCecSinkImplementation::updateTextViewOn(const int logicalAddress) + { + JsonObject params; + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || + logicalAddress == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress].m_isDevicePresent && + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) + { + /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnWakeupFromStandby(logicalAddress); + index++; + } + } + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnTextViewOnMsg(logicalAddress); + index++; + } + } + + + void HdmiCecSinkImplementation::updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr) + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && + logicalAddress.toInt() != _instance->m_logicalAddressAllocated) + { + for (int i=0; i < m_numofHdmiInput; i++) + { + LOGINFO(" addr = %d, portID = %d", phy_addr.getByteValue(0), hdmiInputs[i].m_portID); + if (phy_addr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { + hdmiInputs[i].addChild(logicalAddress, phy_addr); + } + } + } + } + + void HdmiCecSinkImplementation::getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route) + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || + logicalAddress.toInt() == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && + logicalAddress.toInt() != _instance->m_logicalAddressAllocated && + _instance->deviceList[logicalAddress.toInt()].m_isActiveSource ) + { + route.clear(); + for (int i=0; i < m_numofHdmiInput; i++) + { + LOGINFO("physicalAddress = [%d], portID = %d", _instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0), hdmiInputs[i].m_portID); + if (_instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { + hdmiInputs[i].getRoute(_instance->deviceList[logicalAddress.toInt()].m_physicalAddr, route); + } + } + } + else { + LOGERR("Not in correct state to Find Route"); + } + } + + + void HdmiCecSinkImplementation::CheckHdmiInState() + { + int err; + bool isAnyPortConnected = false; + + dsHdmiInGetStatusParam_t params; + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + IARM_BUS_DSMGR_API_dsHdmiInGetStatus, + (void *)¶ms, + sizeof(params)); + + if(err == IARM_RESULT_SUCCESS && params.result == dsERR_NONE ) + { + for( int i = 0; i < m_numofHdmiInput; i++ ) + { + LOGINFO("Is HDMI In Port [%d] connected [%d] \n",i, params.status.isPortConnected[i]); + if ( params.status.isPortConnected[i] ) + { + isAnyPortConnected = true; + } + + LOGINFO("update Port Status [%d] \n", i); + hdmiInputs[i].update(params.status.isPortConnected[i]); + } + } + + if ( isAnyPortConnected ) { + m_isHdmiInConnected = true; + } else { + m_isHdmiInConnected = false; + } + } + + void HdmiCecSinkImplementation::requestActiveSource() + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if(!(_instance->smConnection)) + { + return; + } + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + + _instance->smConnection->sendTo(LogicalAddress::BROADCAST, + MessageEncoder().encode(RequestActiveSourceMessage()), 500); + } + + void HdmiCecSinkImplementation::setActiveSource(bool isResponse) + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if(!(_instance->smConnection)) + { + return; + } + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (isResponse && (_instance->m_currentActiveSource != _instance->m_logicalAddressAllocated) ) + { + LOGWARN("TV is not current Active Source"); + return; + } + + _instance->smConnection->sendTo(LogicalAddress::BROADCAST, + MessageEncoder().encode(ActiveSource(_instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr)), 500); + _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; + } + + void HdmiCecSinkImplementation::setCurrentLanguage(const Language &lang) + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = lang; + } + + void HdmiCecSinkImplementation::sendMenuLanguage() + { + Language lang = ""; + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if(!(_instance->smConnection)) + { + return; + } + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + lang = _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage; + + _instance->smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(SetMenuLanguageMessage(lang)), 100); + } + + void HdmiCecSinkImplementation::updateInActiveSource(const int logical_address, const InActiveSource &source ) + { + JsonObject params; + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if( logical_address != _instance->m_logicalAddressAllocated ) + { + _instance->deviceList[logical_address].m_isActiveSource = false; + + if ( _instance->m_currentActiveSource == logical_address ) + { + _instance->m_currentActiveSource = -1; + } + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnInActiveSource(logical_address, source.physicalAddress.toString()); + index++; + } + } + } + + void HdmiCecSinkImplementation::updateActiveSource(const int logical_address, const ActiveSource &source ) + { + JsonObject params; + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if( logical_address != _instance->m_logicalAddressAllocated ) + { + if ( _instance->m_currentActiveSource != -1 ) + { + _instance->deviceList[_instance->m_currentActiveSource].m_isActiveSource = false; + } + + _instance->deviceList[logical_address].m_isActiveSource = true; + _instance->deviceList[logical_address].update(source.physicalAddress); + _instance->m_currentActiveSource = logical_address; + + if (_instance->deviceList[logical_address].m_isDevicePresent && + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) + { + /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnWakeupFromStandby(logical_address); + index++; + } + } + + string physicalAddress = _instance->deviceList[logical_address].m_physicalAddr.toString().c_str(); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnActiveSourceChange(logical_address, physicalAddress); + index++; + } + } + } + + void HdmiCecSinkImplementation::requestShortaudioDescriptor() + { + if ( cecEnableStatus != true ) + { + LOGINFO("requestShortaudioDescriptor: cec is disabled-> EnableCEC first"); + return; + } + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if(!(_instance->smConnection)) + { + return; + } + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + LOGINFO(" Send requestShortAudioDescriptor Message "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestShortAudioDescriptorMessage(formatid,audioFormatCode,numberofdescriptor)), 1000); + + } + + void HdmiCecSinkImplementation::requestAudioDevicePowerStatus() + { + if ( cecEnableStatus != true ) + { + LOGWARN("cec is disabled-> EnableCEC first"); + return; + } + + if(!HdmiCecSinkImplementation::_instance) + return; + + if(!(_instance->smConnection)) + { + return; + } + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + LOGINFO(" Send GiveDevicePowerStatus Message to Audio system in the network \n"); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM, MessageEncoder().encode(GiveDevicePowerStatus()), 500); + + m_audioDevicePowerStatusRequested = true; + } + + void HdmiCecSinkImplementation::sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason) + { + + if(!HdmiCecSinkImplementation::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Sending FeatureAbort to %s for opcode %s with reason %s ",logicalAddress.toString().c_str(),feature.toString().c_str(),reason.toString().c_str()); + _instance->smConnection->sendTo(logicalAddress, MessageEncoder().encode(FeatureAbort(feature,reason)), 500); + } + + void HdmiCecSinkImplementation::reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode featureOpcode, const AbortReason abortReason) + { + LOGINFO(" Notifying the UI FeatureAbort from the %s for the opcode %s with the reason %s ",logicalAddress.toString().c_str(),featureOpcode.toString().c_str(),abortReason.toString().c_str()); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ReportFeatureAbortEvent(logicalAddress.toInt(), featureOpcode.opCode(), abortReason.toInt()); + index++; + } + } + + void HdmiCecSinkImplementation::pingDevices(std::vector &connected , std::vector &disconnected) + { + int i; + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + if(!(_instance->smConnection)) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { + if ( i != _instance->m_logicalAddressAllocated ) + { + //LOGWARN("PING for 0x%x \r\n",i); + try { + _instance->smConnection->ping(LogicalAddress(_instance->m_logicalAddressAllocated), LogicalAddress(i), Throw_e()); + } + catch(CECNoAckException &e) + { + if ( _instance->deviceList[i].m_isDevicePresent ) { + disconnected.push_back(i); + } + //LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); + usleep(50000); + continue; + } + catch(Exception &e) + { + LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); + usleep(50000); + continue; + } + + /* If we get ACK, then the device is present in the network*/ + if ( !_instance->deviceList[i].m_isDevicePresent ) + { + connected.push_back(i); + //LOGWARN("Ping success, added device: 0x%x \r\n", i); + } + usleep(50000); + } + } + } + + int HdmiCecSinkImplementation::requestType( const int logicalAddress ) { + int requestType = CECDeviceParams::REQUEST_NONE; + + if ( !_instance->deviceList[logicalAddress].m_isPAUpdated || !_instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) { + requestType = CECDeviceParams::REQUEST_PHISICAL_ADDRESS; + }else if ( !_instance->deviceList[logicalAddress].m_isOSDNameUpdated ) { + requestType = CECDeviceParams::REQUEST_OSD_NAME; + }else if ( !_instance->deviceList[logicalAddress].m_isVersionUpdated ) { + requestType = CECDeviceParams::REQUEST_CEC_VERSION; + }else if ( !_instance->deviceList[logicalAddress].m_isVendorIDUpdated ) { + requestType = CECDeviceParams::REQUEST_DEVICE_VENDOR_ID; + }else if ( !_instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) { + requestType = CECDeviceParams::REQUEST_POWER_STATUS; + } + + return requestType; + } + + void HdmiCecSinkImplementation::printDeviceList() { + int i; + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + for(i=0; i< 16; i++) + { + if (HdmiCecSinkImplementation::_instance->deviceList[i].m_isDevicePresent) { + LOGWARN("------ Device ID = %d--------", i); + HdmiCecSinkImplementation::_instance->deviceList[i].printVariable(); + LOGWARN("-----------------------------"); + } + } + } + + void HdmiCecSinkImplementation::setStreamPath( const PhysicalAddress &physical_addr) { + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if(!(_instance->smConnection)) + { + return; + } + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(SetStreamPath(physical_addr)), 500); + } + + void HdmiCecSinkImplementation::setRoutingChange(const std::string &from, const std::string &to) { + PhysicalAddress oldPhyAddr = {0xF,0xF,0xF,0xF}; + PhysicalAddress newPhyAddr = {0xF,0xF,0xF,0xF}; + int oldPortID = -1; + int newPortID = -1; + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + if( from.find("TV",0) != std::string::npos ) + { + oldPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; + _instance->m_currentActiveSource = -1; + } + else + { + oldPortID = stoi(from.substr(4,1),NULL,16); + if ( oldPortID < _instance->m_numofHdmiInput ) + { + oldPhyAddr = _instance->hdmiInputs[oldPortID].m_physicalAddr; + } + else + { + LOGERR("Invalid HDMI Old Port ID"); + return; + } + } + + if( to.find("TV",0) != std::string::npos ) + { + newPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; + /*set active source as TV */ + _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; + } + else + { + newPortID = stoi(to.substr(4,1),NULL,16); + + if ( newPortID < _instance->m_numofHdmiInput ) + { + newPhyAddr = _instance->hdmiInputs[newPortID].m_physicalAddr; + } + else + { + LOGERR("Invalid HDMI New Port ID"); + return; + } + } + + if(!(_instance->smConnection)) + { + return; + } + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(RoutingChange(oldPhyAddr, newPhyAddr)), 500); + } + + void HdmiCecSinkImplementation::addDevice(const int logicalAddress) { + JsonObject params; + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if ( !HdmiCecSinkImplementation::_instance->deviceList[logicalAddress].m_isDevicePresent ) + { + HdmiCecSinkImplementation::_instance->deviceList[logicalAddress].m_isDevicePresent = true; + HdmiCecSinkImplementation::_instance->deviceList[logicalAddress].m_logicalAddress = LogicalAddress(logicalAddress); + HdmiCecSinkImplementation::_instance->m_numberOfDevices++; + HdmiCecSinkImplementation::_instance->m_pollNextState = POLL_THREAD_STATE_INFO; + + if(logicalAddress == 0x5) + { + LOGINFO(" logicalAddress =%d , Audio device detected, Notify Device Settings", logicalAddress ); + hdmiCecAudioDeviceConnected = true; + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ReportAudioDeviceConnectedStatus("success", "true"); + index++; + } + } + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnDeviceAdded(logicalAddress); + index++; + } + } + } + + void HdmiCecSinkImplementation::removeDevice(const int logicalAddress) { + JsonObject params; + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress].m_isDevicePresent) + { + _instance->m_numberOfDevices--; + + for (int i=0; i < m_numofHdmiInput; i++) + { + if (_instance->deviceList[logicalAddress].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { + hdmiInputs[i].removeChild(_instance->deviceList[logicalAddress].m_physicalAddr); + hdmiInputs[i].update(LogicalAddress(LogicalAddress::UNREGISTERED)); + } + } + + if(logicalAddress == 0x5) + { + LOGINFO(" logicalAddress =%d , Audio device removed, Notify Device Settings", logicalAddress ); + + hdmiCecAudioDeviceConnected = false; + if (m_audioStatusDetectionTimer.isActive()){ + m_audioStatusDetectionTimer.stop(); + } + m_isAudioStatusInfoUpdated = false; + m_audioStatusReceived = false; + m_audioStatusTimerStarted = false; + LOGINFO("Audio device removed, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ReportAudioDeviceConnectedStatus("success", "false"); + index++; + } + } + + _instance->deviceList[logicalAddress].m_isRequestRetry = 0; + _instance->deviceList[logicalAddress].clear(); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->OnDeviceRemoved(logicalAddress); + index++; + } + } + } + + void HdmiCecSinkImplementation::request(const int logicalAddress) { + int requestType; + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + if(!(_instance->smConnection)) + { + return; + } + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + requestType = _instance->requestType(logicalAddress); + _instance->deviceList[logicalAddress].m_isRequested = requestType; + + switch (requestType) + { + case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GivePhysicalAddress()), 200); + } + break; + + case CECDeviceParams::REQUEST_CEC_VERSION : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GetCECVersion()), 100); + } + break; + + case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDeviceVendorID()), 100); + } + break; + + case CECDeviceParams::REQUEST_OSD_NAME : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveOSDName()), 500); + } + break; + + case CECDeviceParams::REQUEST_POWER_STATUS : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDevicePowerStatus()), 100); + } + break; + default: + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + break; + } + + _instance->deviceList[logicalAddress].m_requestTime = std::chrono::system_clock::now(); + LOGINFO("request type %d", _instance->deviceList[logicalAddress].m_isRequested); + } + + int HdmiCecSinkImplementation::requestStatus(const int logicalAddress) { + std::chrono::duration elapsed; + bool isElapsed = false; + + if(!HdmiCecSinkImplementation::_instance) + return -1; + + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ) { + LOGERR("Logical Address NOT Allocated Or its not valid"); + return -1; + } + + switch ( _instance->deviceList[logicalAddress].m_isRequested ) { + case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : + { + if( _instance->deviceList[logicalAddress].m_isPAUpdated && + _instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_CEC_VERSION : + { + if( _instance->deviceList[logicalAddress].m_isVersionUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : + { + if( _instance->deviceList[logicalAddress].m_isVendorIDUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_OSD_NAME : + { + if( _instance->deviceList[logicalAddress].m_isOSDNameUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_POWER_STATUS : + { + if( _instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + default: + break; + } + + if ( _instance->deviceList[logicalAddress].m_isRequested != CECDeviceParams::REQUEST_NONE ) + { + elapsed = std::chrono::system_clock::now() - _instance->deviceList[logicalAddress].m_requestTime; + + if ( elapsed.count() > HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS ) + { + LOGINFO("request elapsed "); + isElapsed = true; + } + } + + if (isElapsed) + { + /* For some request it should be retry, like report physical address etc for other we can have default values */ + switch( _instance->deviceList[logicalAddress].m_isRequested ) + { + case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : + { + LOGINFO("Retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); + /* Update with Invalid Physical Address */ + if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) + { + LOGINFO("Max retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); + _instance->deviceList[logicalAddress].update(PhysicalAddress(0xF,0xF,0xF,0xF)); + _instance->deviceList[logicalAddress].update(DeviceType(DeviceType::RESERVED)); + _instance->deviceList[logicalAddress].m_isRequestRetry = 0; + } + } + break; + + case CECDeviceParams::REQUEST_CEC_VERSION : + { + /*Defaulting to 1.4*/ + _instance->deviceList[logicalAddress].update(Version(Version::V_1_4)); + } + break; + + case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : + { + _instance->deviceList[logicalAddress].update(VendorID(0,0,0)); + } + break; + + case CECDeviceParams::REQUEST_OSD_NAME : + { + if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) + { + LOGINFO("Max retry for REQUEST_OSD_NAME = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); + _instance->deviceList[logicalAddress].update(OSDName("")); + _instance->deviceList[logicalAddress].m_isRequestRetry = 0; + } + } + break; + + case CECDeviceParams::REQUEST_POWER_STATUS : + { + _instance->deviceList[logicalAddress].update(PowerStatus(PowerStatus::POWER_STATUS_NOT_KNOWN)); + } + break; + default: + break; + } + + + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + + if( _instance->deviceList[logicalAddress].m_isRequested == CECDeviceParams::REQUEST_NONE) + { + LOGINFO("Request Done"); + return CECDeviceParams::REQUEST_DONE; + } + + //LOGINFO("Request NOT Done"); + return CECDeviceParams::REQUEST_NOT_DONE; + } + + void HdmiCecSinkImplementation::threadRun() + { + std::vector connected; + std::vector disconnected; + int logicalAddressRequested = LogicalAddress::UNREGISTERED + TEST_ADD; + bool isExit = false; + + if(!HdmiCecSinkImplementation::_instance) + return; + + if(!(_instance->smConnection)) + return; + LOGINFO("Entering ThreadRun: _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); + _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; + + while(1) + { + + if (_instance->m_pollThreadExit || isExit ){ + LOGWARN("Thread Exits _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); + break; + } + + if ( _instance->m_pollNextState != POLL_THREAD_STATE_NONE ) + { + _instance->m_pollThreadState = _instance->m_pollNextState; + _instance->m_pollNextState = POLL_THREAD_STATE_NONE; + } + + switch (_instance->m_pollThreadState) { + + case POLL_THREAD_STATE_POLL : + { + //LOGINFO("POLL_THREAD_STATE_POLL"); + _instance->allocateLogicalAddress(DeviceType::TV); + if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED) + { + try{ + + logicalAddress = LogicalAddress(_instance->m_logicalAddressAllocated); + LibCCEC::getInstance().addLogicalAddress(logicalAddress); + _instance->smConnection->setSource(logicalAddress); + _instance->m_numberOfDevices = 0; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType = DeviceType::TV; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_isDevicePresent = true; + _instance->deviceList[_instance->m_logicalAddressAllocated].update(physical_addr); + _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_1_4; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_vendorID = appVendorId; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); + _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = defaultLanguage; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_osdName = osdName.toString().c_str(); + if(cecVersion == 2.0) { + _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_2_0; + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), + MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures)), 500); + } + _instance->smConnection->addFrameListener(_instance->msgFrameListener); + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), + MessageEncoder().encode(ReportPhysicalAddress(physical_addr, _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType)), 100); + + _instance->m_sleepTime = 0; + _instance->m_pollThreadState = POLL_THREAD_STATE_PING; + } + catch(InvalidStateException &e){ + LOGWARN("InvalidStateException caught while allocated logical address. %s", e.what()); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + catch(IOException &e){ + LOGWARN("IOException caught while allocated logical address. %s", e.what()); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + catch(...){ + LOGWARN("Exception caught while allocated logical address."); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + } + else + { + LOGINFO("Not able allocate Logical Address for TV"); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + } + break; + + case POLL_THREAD_STATE_PING : + { + //LOGINFO("POLL_THREAD_STATE_PING"); + _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; + connected.clear(); + disconnected.clear(); + _instance->pingDevices(connected, disconnected); + + if ( disconnected.size() ){ + for( unsigned int i=0; i< disconnected.size(); i++ ) + { + LOGWARN("Disconnected Devices [%zu]", disconnected.size()); + _instance->removeDevice(disconnected[i]); + } + } + + if (connected.size()) { + LOGWARN("Connected Devices [%zu]", connected.size()); + for( unsigned int i=0; i< connected.size(); i++ ) + { + _instance->addDevice(connected[i]); + /* If new device is connected, then try to aquire the information */ + _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; + _instance->m_sleepTime = 0; + } + } + else + { + for(int i=0;im_logicalAddressAllocated && + _instance->deviceList[i].m_isDevicePresent && + !_instance->deviceList[i].isAllUpdated() ) + { + _instance->m_pollNextState = POLL_THREAD_STATE_INFO; + _instance->m_sleepTime = 0; + } + } + /* Check for any update required */ + _instance->m_pollThreadState = POLL_THREAD_STATE_UPDATE; + _instance->m_sleepTime = 0; + } + } + break; + + case POLL_THREAD_STATE_INFO : + { + //LOGINFO("POLL_THREAD_STATE_INFO"); + + if ( logicalAddressRequested == LogicalAddress::UNREGISTERED + TEST_ADD ) + { + int i = 0; + for(;im_logicalAddressAllocated && + _instance->deviceList[i].m_isDevicePresent && + !_instance->deviceList[i].isAllUpdated() ) + { + //LOGINFO("POLL_THREAD_STATE_INFO -> request for %d", i); + logicalAddressRequested = i; + _instance->request(logicalAddressRequested); + _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; + break; + } + } + + if ( i == LogicalAddress::UNREGISTERED) + { + /*So there is no update required, try to ping after some seconds*/ + _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; + _instance->m_sleepTime = 0; + //LOGINFO("POLL_THREAD_STATE_INFO -> state change to Ping", i); + } + } + else + { + /*So there is request sent for logical address, so wait and check the status */ + if ( _instance->requestStatus(logicalAddressRequested) == CECDeviceParams::REQUEST_DONE ) + { + logicalAddressRequested = LogicalAddress::UNREGISTERED; + } + else + { + _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; + } + } + } + break; + + /* updating the power status and if required we can add other information later*/ + case POLL_THREAD_STATE_UPDATE : + { + //LOGINFO("POLL_THREAD_STATE_UPDATE"); + + for(int i=0;im_logicalAddressAllocated && + _instance->deviceList[i].m_isDevicePresent && + _instance->deviceList[i].m_isPowerStatusUpdated ) + { + std::chrono::duration elapsed = std::chrono::system_clock::now() - _instance->deviceList[i].m_lastPowerUpdateTime; + + if ( elapsed.count() > HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS ) + { + _instance->deviceList[i].m_isPowerStatusUpdated = false; + _instance->m_pollNextState = POLL_THREAD_STATE_INFO; + _instance->m_sleepTime = 0; + } + } + } + + _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; + _instance->m_sleepTime = 0; + } + break; + + case POLL_THREAD_STATE_IDLE : + { + //LOGINFO("POLL_THREAD_STATE_IDLE"); + _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; + _instance->m_pollThreadState = POLL_THREAD_STATE_PING; + } + break; + + case POLL_THREAD_STATE_WAIT : + { + /* Wait for Hdmi is connected, in case it disconnected */ + //LOGINFO("19Aug2020-[01] -> POLL_THREAD_STATE_WAIT"); + _instance->m_sleepTime = HDMICECSINK_WAIT_FOR_HDMI_IN_MS; + + if ( _instance->m_isHdmiInConnected == true ) + { + _instance->m_pollThreadState = POLL_THREAD_STATE_POLL; + } + } + break; + + case POLL_THREAD_STATE_EXIT : + { + isExit = true; + _instance->m_sleepTime = 0; + } + break; + } + + std::unique_lock lk(_instance->m_pollExitMutex); + if ( _instance->m_ThreadExitCV.wait_for(lk, std::chrono::milliseconds(_instance->m_sleepTime)) == std::cv_status::timeout ) + continue; + else + LOGINFO("Thread is going to Exit m_pollThreadExit %d\n", _instance->m_pollThreadExit ); + + } + } + + void HdmiCecSinkImplementation::allocateLAforTV() + { + bool gotLogicalAddress = false; + int addr = LogicalAddress::TV; + int i, j; + if (!(_instance->smConnection)) + return; + + for (i = 0; i< HDMICECSINK_NUMBER_TV_ADDR; i++) + { + /* poll for TV logical address - retry 5 times*/ + for (j = 0; j < 5; j++) + { + try { + smConnection->poll(LogicalAddress(addr), Throw_e()); + } + catch(CECNoAckException &e ) + { + LOGWARN("Poll caught %s \r\n",e.what()); + gotLogicalAddress = true; + break; + } + catch(Exception &e) + { + LOGWARN("Poll caught %s \r\n",e.what()); + usleep(250000); + } + } + if (gotLogicalAddress) + { + break; + } + addr = LogicalAddress::SPECIFIC_USE; + } + + if ( gotLogicalAddress ) + { + m_logicalAddressAllocated = addr; + } + else + { + m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; + } + + LOGWARN("Logical Address for TV 0x%x \r\n",m_logicalAddressAllocated); + } + + void HdmiCecSinkImplementation::allocateLogicalAddress(int deviceType) + { + if( deviceType == DeviceType::TV ) + { + allocateLAforTV(); + } + } + + void HdmiCecSinkImplementation::CECEnable(void) + { + std::lock_guard lock(m_enableMutex); + JsonObject params; + LOGINFO("Entered CECEnable"); + if (cecEnableStatus) + { + LOGWARN("CEC Already Enabled"); + return; + } + + if(0 == libcecInitStatus) + { + try + { + LibCCEC::getInstance().init("HdmiCecSinkImplementation"); + } + catch(InvalidStateException &e){ + LOGWARN("InvalidStateException caught in LibCCEC::init %s", e.what()); + } + catch(IOException &e){ + LOGWARN("IOException caught in LibCCEC::init %s", e.what()); + } + catch(...){ + LOGWARN("Exception caught in LibCCEC::init"); + } + } + libcecInitStatus++; + + //Acquire CEC Addresses + _instance->getPhysicalAddress(); + + smConnection = new Connection(LogicalAddress::UNREGISTERED,false,"ServiceManager::Connection::"); + smConnection->open(); + allocateLogicalAddress(DeviceType::TV); + LOGINFO("logical address allocalted: %x \n",m_logicalAddressAllocated); + if ( m_logicalAddressAllocated != LogicalAddress::UNREGISTERED && smConnection) + { + logicalAddress = LogicalAddress(m_logicalAddressAllocated); + LOGINFO(" add logical address %x \n",m_logicalAddressAllocated); + LibCCEC::getInstance().addLogicalAddress(logicalAddress); + smConnection->setSource(logicalAddress); + } + msgProcessor = new HdmiCecSinkProcessor(*smConnection); + msgFrameListener = new HdmiCecSinkFrameListener(*msgProcessor); + if(smConnection) + { + LOGWARN("Start Thread %p", smConnection ); + m_pollThreadState = POLL_THREAD_STATE_POLL; + m_pollNextState = POLL_THREAD_STATE_NONE; + m_pollThreadExit = false; + m_pollThread = std::thread(threadRun); + } + cecEnableStatus = true; + + params["cecEnable"] = string("true"); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ReportCecEnabledEvent("true"); + index++; + } + + return; + } + + void HdmiCecSinkImplementation::CECDisable(void) + { + std::lock_guard lock(m_enableMutex); + JsonObject params; + LOGINFO("Entered CECDisable "); + if(!cecEnableStatus) + { + LOGWARN("CEC Already Disabled "); + return; + } + + if(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) + { + stopArc(); + while(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) + { + usleep(500000); + } + } + + LOGINFO(" CECDisable ARC stopped "); + cecEnableStatus = false; + if (smConnection != NULL) + { + LOGWARN("Stop Thread %p", smConnection ); + m_pollThreadExit = true; + m_ThreadExitCV.notify_one(); + + try + { + if (m_pollThread.joinable()) + { + LOGWARN("Join Thread %p", smConnection ); + m_pollThread.join(); + } + } + catch(const std::system_error& e) + { + LOGERR("system_error exception in thread join %s", e.what()); + } + catch(const std::exception& e) + { + LOGERR("exception in thread join %s", e.what()); + } + + m_pollThreadState = POLL_THREAD_STATE_NONE; + m_pollNextState = POLL_THREAD_STATE_NONE; + + LOGWARN("Deleted Thread %p", smConnection ); + + smConnection->close(); + delete smConnection; + smConnection = NULL; + } + + m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + if (m_audioStatusDetectionTimer.isActive()){ + m_audioStatusDetectionTimer.stop(); + } + m_isAudioStatusInfoUpdated = false; + m_audioStatusReceived = false; + m_audioStatusTimerStarted = false; + LOGINFO("CEC Disabled, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + + for(int i=0; i< 16; i++) + { + if (_instance->deviceList[i].m_isDevicePresent) + { + _instance->deviceList[i].clear(); + } + } + + if(1 == libcecInitStatus) + { + try + { + LibCCEC::getInstance().term(); + } + catch(InvalidStateException &e){ + LOGWARN("InvalidStateException caught in LibCCEC::term %s", e.what()); + } + catch(IOException &e){ + LOGWARN("IOException caught in LibCCEC::term %s", e.what()); + } + catch(...){ + LOGWARN("Exception caught in LibCCEC::term"); + } + + libcecInitStatus--; + LOGWARN("CEC Disabled %d",libcecInitStatus); + + params["cecEnable"] = string("false"); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ReportCecEnabledEvent("false"); + index++; + } + } + return; + } + + + void HdmiCecSinkImplementation::getPhysicalAddress() + { + LOGINFO("Entered getPhysicalAddress "); + + uint32_t physAddress = 0x0F0F0F0F; + + try { + LibCCEC::getInstance().getPhysicalAddress(&physAddress); + physical_addr = {(uint8_t)((physAddress >> 24) & 0xFF),(uint8_t)((physAddress >> 16) & 0xFF),(uint8_t) ((physAddress >> 8) & 0xFF),(uint8_t)((physAddress) & 0xFF)}; + LOGINFO("getPhysicalAddress: physicalAddress: %s ", physical_addr.toString().c_str()); + } + catch (const std::exception& e) + { + LOGWARN("exception caught from getPhysicalAddress"); + } + return; + } + + bool HdmiCecSinkImplementation::getEnabled() + { + + + LOGINFO("getEnabled :%d ",cecEnableStatus); + if(true == cecEnableStatus) + return true; + else + return false; + } + + bool HdmiCecSinkImplementation::getAudioDeviceConnectedStatus() + { + LOGINFO("getAudioDeviceConnectedStatus :%d ", hdmiCecAudioDeviceConnected); + if(true == hdmiCecAudioDeviceConnected) + return true; + else + return false; + } + //Arc Routing related functions + void HdmiCecSinkImplementation::startArc() + { + if ( cecEnableStatus != true ) + { + LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); + return; + } + if(!HdmiCecSinkImplementation::_instance) + return; + + LOGINFO("Current ARC State : %d\n", m_currentArcRoutingState); + + _instance->requestArcInitiation(); + + // start initiate ARC timer 3 sec + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + m_arcstarting = true; + m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); + + } + void HdmiCecSinkImplementation::requestArcInitiation() + { + { + std::lock_guard lock(m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_INITIATION; + } + LOGINFO("requestArcInitiation release sem"); + _instance->m_semSignaltoArcRoutingThread.release(); + + } + void HdmiCecSinkImplementation::stopArc() + { + if ( cecEnableStatus != true ) + { + LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); + return; + } + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + if(m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_TERMINATION || m_currentArcRoutingState == ARC_STATE_ARC_TERMINATED) + { + LOGINFO("ARC is either Termination in progress or already Terminated"); + return; + } + + _instance->requestArcTermination(); + /* start a timer for 3 sec to get the desired ARC_STATE_ARC_TERMINATED */ + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + /* m_arcstarting = true means starting the ARC start timer ,false means ARC stopping timer*/ + m_arcstarting = false; + m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); + + + } + void HdmiCecSinkImplementation::requestArcTermination() + { + { + std::lock_guard lock(m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_TERMINATION; + } + LOGINFO("requestArcTermination release sem"); + _instance->m_semSignaltoArcRoutingThread.release(); + + } + + void HdmiCecSinkImplementation::Process_InitiateArc() + { + JsonObject params; + + LOGINFO("Command: INITIATE_ARC \n"); + + if(!HdmiCecSinkImplementation::_instance) + return; + + //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status + //Initiate ARC message may come from AVR/Soundbar while CEC disable is in-progress + if ( cecSettingEnabled != true ) + { + LOGINFO("Process InitiateArc from Audio device: Cec is disabled-> EnableCEC first"); + return; + } + + LOGINFO("Got : INITIATE_ARC and current Arcstate is %d\n",_instance->m_currentArcRoutingState); + + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + if (powerState == DEVICE_POWER_STATE_ON ) { + LOGINFO("Notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + _instance->m_currentArcRoutingState = ARC_STATE_ARC_INITIATED; + + _instance->m_semSignaltoArcRoutingThread.release(); + LOGINFO("Got : ARC_INITIATED and notify Device setting"); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ArcInitiationEvent("success"); + index++; + } + } else { + LOGINFO("Not notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); + } + + } + void HdmiCecSinkImplementation::Process_TerminateArc() + { + JsonObject params; + + LOGINFO("Command: TERMINATE_ARC current arc state %d \n",HdmiCecSinkImplementation::_instance->m_currentArcRoutingState); + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + std::lock_guard lock(m_arcRoutingStateMutex); + HdmiCecSinkImplementation::_instance->m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + _instance->m_semSignaltoArcRoutingThread.release(); + + // trigger callback to Device setting informing to TERMINATE_ARC + LOGINFO("Got : ARC_TERMINATED and notify Device setting"); + std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); + while (index != _hdmiCecSinkNotifications.end()) { + (*index)->ArcTerminationEvent("success"); + index++; + } + } + + void HdmiCecSinkImplementation::threadSendKeyEvent() + { + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + SendKeyInfo keyInfo = {-1,-1}; + + while(!_instance->m_sendKeyEventThreadExit) + { + keyInfo.logicalAddr = -1; + keyInfo.keyCode = -1; + { + // Wait for a message to be added to the queue + std::unique_lock lk(_instance->m_sendKeyEventMutex); + _instance->m_sendKeyCV.wait(lk, []{return (_instance->m_sendKeyEventThreadRun == true);}); + } + + if (_instance->m_sendKeyEventThreadExit == true) + { + LOGINFO(" threadSendKeyEvent Exiting"); + _instance->m_sendKeyEventThreadRun = false; + break; + } + + if (_instance->m_SendKeyQueue.empty()) { + _instance->m_sendKeyEventThreadRun = false; + continue; + } + + keyInfo = _instance->m_SendKeyQueue.front(); + _instance->m_SendKeyQueue.pop(); + + if(keyInfo.UserControl == "sendUserControlPressed" ) + { + LOGINFO("sendUserControlPressed : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); + _instance->sendUserControlPressed(keyInfo.logicalAddr,keyInfo.keyCode); + } + else if(keyInfo.UserControl == "sendUserControlReleased") + { + LOGINFO("sendUserControlReleased : logical addr:0x%x queue size :%zu \n",keyInfo.logicalAddr,_instance->m_SendKeyQueue.size()); + _instance->sendUserControlReleased(keyInfo.logicalAddr); + } + else + { + LOGINFO("sendKeyPressEvent : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); + _instance->sendKeyPressEvent(keyInfo.logicalAddr,keyInfo.keyCode); + _instance->sendKeyReleaseEvent(keyInfo.logicalAddr); + } + + if((_instance->m_SendKeyQueue.size()<=1 || (_instance->m_SendKeyQueue.size() % 2 == 0)) && ((keyInfo.keyCode == VOLUME_UP) || (keyInfo.keyCode == VOLUME_DOWN) || (keyInfo.keyCode == MUTE)) ) + { + if(keyInfo.keyCode == MUTE) + { + _instance->sendGiveAudioStatusMsg(); + } + else + { + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ",_instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); + if (!_instance->m_isAudioStatusInfoUpdated) + { + if ( !(_instance->m_audioStatusDetectionTimer.isActive())) + { + LOGINFO("Audio status info not updated. Starting the Timer!"); + _instance->m_audioStatusTimerStarted = true; + _instance->m_audioStatusDetectionTimer.start((HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS)); + } + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", _instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); + } + else + { + if (!_instance->m_audioStatusReceived){ + _instance->sendGiveAudioStatusMsg(); + } + } + } + } + }//while(!_instance->m_sendKeyEventThreadExit) + }//threadSendKeyEvent + + void HdmiCecSinkImplementation::audioStatusTimerFunction() + { + m_audioStatusTimerStarted = false; + m_isAudioStatusInfoUpdated = true; + LOGINFO("Timer Expired. Requesting the AudioStatus since not received.\n"); + sendGiveAudioStatusMsg(); + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + } + + + void HdmiCecSinkImplementation::threadArcRouting() + { + bool isExit = false; + uint32_t currentArcRoutingState; + + if(!HdmiCecSinkImplementation::_instance) + { + return; + } + + LOGINFO("Running threadArcRouting"); + _instance->getHdmiArcPortID(); + + while(1) + { + + _instance->m_semSignaltoArcRoutingThread.acquire(); + + + + { + LOGINFO(" threadArcRouting Got semaphore"); + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + + currentArcRoutingState = _instance->m_currentArcRoutingState; + + LOGINFO(" threadArcRouting Got Sem arc state %d",currentArcRoutingState); + } + + switch (currentArcRoutingState) + { + + case ARC_STATE_REQUEST_ARC_INITIATION : + { + + _instance->systemAudioModeRequest(); + _instance->Send_Request_Arc_Initiation_Message(); + + } + break; + case ARC_STATE_ARC_INITIATED : + { + _instance->Send_Report_Arc_Initiated_Message(); + } + break; + case ARC_STATE_REQUEST_ARC_TERMINATION : + { + + _instance->Send_Request_Arc_Termination_Message(); + + } + break; + case ARC_STATE_ARC_TERMINATED : + { + _instance->Send_Report_Arc_Terminated_Message(); + } + break; + case ARC_STATE_ARC_EXIT : + { + isExit = true; + } + break; + } + + if (isExit == true) + { + LOGINFO(" threadArcRouting EXITing"); + break; + } + }//while(1) + }//threadArcRouting + + void HdmiCecSinkImplementation::Send_Request_Arc_Initiation_Message() + { + if(!HdmiCecSinkImplementation::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Send_Request_Arc_Initiation_Message "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcInitiation()), 1000); + + } + void HdmiCecSinkImplementation::Send_Report_Arc_Initiated_Message() + { + if(!HdmiCecSinkImplementation::_instance) + return; + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcInitiation()), 1000); + + } + void HdmiCecSinkImplementation::Send_Request_Arc_Termination_Message() + { + + if(!HdmiCecSinkImplementation::_instance) + return; + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcTermination()), 1000); + } + + void HdmiCecSinkImplementation::Send_Report_Arc_Terminated_Message() + { + if(!HdmiCecSinkImplementation::_instance) + return; + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcTermination()), 1000); + + } + + void HdmiCecSinkImplementation::getHdmiArcPortID() + { + int err; + dsGetHDMIARCPortIdParam_t param; + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, + (void *)¶m, + sizeof(param)); + if (IARM_RESULT_SUCCESS == err) + { + LOGINFO("HDMI ARC port ID HdmiArcPortID=[%d] \n", param.portId); + HdmiArcPortID = param.portId; + } + } + + void HdmiCecSinkImplementation::getCecVersion() + { + RFC_ParamData_t param = {0}; + WDMP_STATUS status = getRFCParameter((char*)"thunderapi", TR181_HDMICECSINK_CEC_VERSION, ¶m); + if(WDMP_SUCCESS == status && param.type == WDMP_STRING) { + LOGINFO("CEC Version from RFC = [%s] \n", param.value); + cecVersion = atof(param.value); + } + else { + LOGINFO("Error while fetching CEC Version from RFC "); + } + } + + } // namespace Plugin +} // namespace WPEFrameworklk diff --git a/HdmiCecSink/HdmiCecSinkImplementation.h b/HdmiCecSink/HdmiCecSinkImplementation.h new file mode 100644 index 00000000..c9d91c11 --- /dev/null +++ b/HdmiCecSink/HdmiCecSinkImplementation.h @@ -0,0 +1,755 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2019 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. +**/ + +#pragma once + +#include +#include "ccec/FrameListener.hpp" +#include "ccec/Connection.hpp" + +#include "libIARM.h" +#include "ccec/Assert.hpp" +#include "ccec/Messages.hpp" +#include "ccec/MessageDecoder.hpp" +#include "ccec/MessageProcessor.hpp" + +#undef Assert // this define from Connection.hpp conflicts with WPEFramework + +#include "Module.h" +#include "tptimer.h" +#include +#include +#include +#include + +#include "UtilsLogging.h" +#include +#include "PowerManagerInterface.h" +#include + +using namespace WPEFramework; +using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; +using ThermalTemperature = WPEFramework::Exchange::IPowerManager::ThermalTemperature; + + +namespace WPEFramework { + + namespace Plugin { + class HdmiCecSinkFrameListener : public FrameListener + { + public: + HdmiCecSinkFrameListener(MessageProcessor &processor) : processor(processor) {} + void notify(const CECFrame &in) const; + ~HdmiCecSinkFrameListener() {} + private: + MessageProcessor &processor; + }; + + class HdmiCecSinkProcessor : public MessageProcessor + { + public: + HdmiCecSinkProcessor(Connection &conn) : conn(conn) {} + void process (const ActiveSource &msg, const Header &header); + void process (const InActiveSource &msg, const Header &header); + void process (const ImageViewOn &msg, const Header &header); + void process (const TextViewOn &msg, const Header &header); + void process (const RequestActiveSourceMessage &msg, const Header &header); + void process (const Standby &msg, const Header &header); + void process (const GetCECVersion &msg, const Header &header); + void process (const CECVersion &msg, const Header &header); + void process (const SetMenuLanguageMessage &msg, const Header &header); + void process (const GiveOSDName &msg, const Header &header); + void process (const GivePhysicalAddress &msg, const Header &header); + void process (const GiveDeviceVendorID &msg, const Header &header); + void process (const SetOSDString &msg, const Header &header); + void process (const SetOSDName &msg, const Header &header); + void process (const RoutingChange &msg, const Header &header); + void process (const RoutingInformation &msg, const Header &header); + void process (const SetStreamPath &msg, const Header &header); + void process (const GetMenuLanguage &msg, const Header &header); + void process (const ReportPhysicalAddress &msg, const Header &header); + void process (const DeviceVendorID &msg, const Header &header); + void process (const GiveDevicePowerStatus &msg, const Header &header); + void process (const ReportPowerStatus &msg, const Header &header); + void process (const FeatureAbort &msg, const Header &header); + void process (const Abort &msg, const Header &header); + void process (const Polling &msg, const Header &header); + void process (const InitiateArc &msg, const Header &header); + void process (const TerminateArc &msg, const Header &header); + void process (const ReportShortAudioDescriptor &msg, const Header &header); + void process (const SetSystemAudioMode &msg, const Header &header); + void process (const ReportAudioStatus &msg, const Header &header); + void process (const GiveFeatures &msg, const Header &header); + void process (const RequestCurrentLatency &msg, const Header &header); + private: + Connection conn; + void printHeader(const Header &header) + { + printf("Header : From : %s \n", header.from.toString().c_str()); + printf("Header : to : %s \n", header.to.toString().c_str()); + } + + }; + + class CECDeviceParams { + public: + + enum { + REQUEST_NONE = 0, + REQUEST_PHISICAL_ADDRESS = 1, + REQUEST_CEC_VERSION, + REQUEST_DEVICE_VENDOR_ID, + REQUEST_POWER_STATUS, + REQUEST_OSD_NAME, + }; + + enum { + REQUEST_DONE = 0, + REQUEST_NOT_DONE, + REQUEST_TIME_ELAPSED, + }; + + DeviceType m_deviceType; + LogicalAddress m_logicalAddress; + PhysicalAddress m_physicalAddr; + Version m_cecVersion; + VendorID m_vendorID; + OSDName m_osdName; + PowerStatus m_powerStatus; + bool m_isDevicePresent; + bool m_isDeviceDisconnected; + Language m_currentLanguage; + bool m_isActiveSource; + bool m_isDeviceTypeUpdated; + bool m_isPAUpdated; + bool m_isVersionUpdated; + bool m_isOSDNameUpdated; + bool m_isVendorIDUpdated; + bool m_isPowerStatusUpdated; + int m_isRequested; + int m_isRequestRetry; + std::chrono::system_clock::time_point m_requestTime; + std::vector m_featureAborts; + std::chrono::system_clock::time_point m_lastPowerUpdateTime; + + CECDeviceParams() + : m_deviceType(0), m_logicalAddress(0),m_physicalAddr(0x0f,0x0f,0x0f,0x0f),m_cecVersion(0),m_vendorID(0,0,0),m_osdName(""),m_powerStatus(0),m_currentLanguage("") + { + m_isDevicePresent = false; + m_isActiveSource = false; + m_isPAUpdated = false; + m_isVersionUpdated = false; + m_isOSDNameUpdated = false; + m_isVendorIDUpdated = false; + m_isPowerStatusUpdated = false; + m_isDeviceDisconnected = false; + m_isDeviceTypeUpdated = false; + m_isRequestRetry = 0; + } + + void clear( ) + { + m_deviceType = 0; + m_logicalAddress = 0; + m_physicalAddr = PhysicalAddress(0x0f,0x0f,0x0f,0x0f); + m_cecVersion = 0; + m_vendorID = VendorID(0,0,0); + m_osdName = ""; + m_powerStatus = 0; + m_currentLanguage = ""; + m_isDevicePresent = false; + m_isActiveSource = false; + m_isPAUpdated = false; + m_isVersionUpdated = false; + m_isOSDNameUpdated = false; + m_isVendorIDUpdated = false; + m_isPowerStatusUpdated = false; + m_isDeviceDisconnected = false; + m_isDeviceTypeUpdated = false; + } + + void printVariable() + { + LOGWARN("Device LogicalAddress %s", m_logicalAddress.toString().c_str()); + LOGWARN("Device Type %s", m_deviceType.toString().c_str()); + LOGWARN("Device Present %d", m_isDevicePresent); + LOGWARN("Active Source %d", m_isActiveSource); + LOGWARN("PA Updated %d", m_isPAUpdated); + LOGWARN("Version Updated %d", m_isVersionUpdated); + LOGWARN("OSDName Updated %d", m_isOSDNameUpdated); + LOGWARN("PowerStatus Updated %d", m_isPowerStatusUpdated); + LOGWARN("VendorID Updated %d", m_isPowerStatusUpdated); + LOGWARN("CEC Version : %s", m_cecVersion.toString().c_str()); + LOGWARN("Vendor ID : %s", m_vendorID.toString().c_str()); + LOGWARN("PhisicalAddress : %s", m_physicalAddr.toString().c_str()); + LOGWARN("OSDName : %s", m_osdName.toString().c_str()); + LOGWARN("Power Status : %s", m_powerStatus.toString().c_str()); + LOGWARN("Language : %s", m_currentLanguage.toString().c_str()); + } + + bool isAllUpdated() { + if( !m_isPAUpdated + || !m_isVersionUpdated + || !m_isOSDNameUpdated + || !m_isVendorIDUpdated + || !m_isPowerStatusUpdated + || !m_isDeviceTypeUpdated ){ + return false; + } + return true; + } + + void update( const DeviceType &deviceType ) { + m_deviceType = deviceType; + m_isDeviceTypeUpdated = true; + } + + void update( const PhysicalAddress &physical_addr ) { + m_physicalAddr = physical_addr; + m_isPAUpdated = true; + } + + void update ( const VendorID &vendorId) { + m_vendorID = vendorId; + m_isVendorIDUpdated = true; + } + + void update ( const Version &version ) { + m_cecVersion = version; + m_isVersionUpdated = true; + } + + void update ( const OSDName &osdName ) { + m_osdName = osdName; + m_isOSDNameUpdated = true; + } + + void update ( const PowerStatus &status ) { + m_powerStatus = status; + m_isPowerStatusUpdated = true; + m_lastPowerUpdateTime = std::chrono::system_clock::now(); + } + }; + + class DeviceNode { + public: + uint8_t m_childsLogicalAddr[LogicalAddress::UNREGISTERED]; + + DeviceNode() { + int i; + for (i = 0; i < LogicalAddress::UNREGISTERED; i++ ) + { + m_childsLogicalAddr[i] = LogicalAddress::UNREGISTERED; + } + } + + } ; + typedef struct sendKeyInfo + { + int logicalAddr; + int keyCode; + string UserControl; + }SendKeyInfo; + + class HdmiPortMap { + public: + uint8_t m_portID; + bool m_isConnected; + LogicalAddress m_logicalAddr; + PhysicalAddress m_physicalAddr; + DeviceNode m_deviceChain[3]; + + HdmiPortMap(uint8_t portID) : m_portID(portID), + m_logicalAddr(LogicalAddress::UNREGISTERED), + m_physicalAddr(portID+1,0,0,0) + { + m_isConnected = false; + } + + void update(bool isConnected) + { + m_isConnected = isConnected; + } + + void update( const LogicalAddress &addr ) + { + m_logicalAddr = addr; + } + + void addChild( const LogicalAddress &logical_addr, const PhysicalAddress &physical_addr ) + { + LOGINFO(" logicalAddr = %d, phisicalAddr = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); + + if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED && + m_logicalAddr.toInt() != logical_addr.toInt() ) + { + LOGINFO(" update own logicalAddr = %d, new devcie logicalAddress = %d", m_logicalAddr.toInt(), logical_addr.toInt() ); + /* check matching with this port's physical address */ + if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && + physical_addr.getByteValue(1) != 0 ) + { + if ( physical_addr.getByteValue(3) != 0 ) + { + m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = logical_addr.toInt(); + } + else if ( physical_addr.getByteValue(2) != 0 ) + { + m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = logical_addr.toInt(); + } + else if ( physical_addr.getByteValue(1) != 0 ) + { + m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = logical_addr.toInt(); + } + } + } + else if ( physical_addr == m_physicalAddr ) + { + update(logical_addr); + LOGINFO(" update own logicalAddr = %d", m_logicalAddr.toInt()); + } + } + + void removeChild( PhysicalAddress &physical_addr ) + { + if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) + { + /* check matching with this port's physical address */ + if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && + physical_addr.getByteValue(1) != 0 ) + { + if ( physical_addr.getByteValue(3) != 0 ) + { + m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = LogicalAddress::UNREGISTERED; + } + else if ( physical_addr.getByteValue(2) != 0 ) + { + m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = LogicalAddress::UNREGISTERED; + } + else if ( physical_addr.getByteValue(1) != 0 ) + { + m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = LogicalAddress::UNREGISTERED; + } + } + } + } + + void getRoute( PhysicalAddress &physical_addr, std::vector & route ) + { + LOGINFO(" logicalAddr = %d, phsical = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); + + if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) + { + LOGINFO(" search for logicalAddr = %d", m_logicalAddr.toInt()); + /* check matching with this port's physical address */ + if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && + physical_addr.getByteValue(1) != 0 ) + { + if ( physical_addr.getByteValue(3) != 0 ) + { + route.push_back(m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1]); + } + + if ( physical_addr.getByteValue(2) != 0 ) + { + route.push_back(m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1]); + } + + if ( physical_addr.getByteValue(1) != 0 ) + { + route.push_back(m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1]); + } + + route.push_back(m_logicalAddr.toInt()); + } + else + { + route.push_back(m_logicalAddr.toInt()); + LOGINFO("logicalAddr = %d, physical = %s", m_logicalAddr.toInt(), m_physicalAddr.toString().c_str()); + } + } + } + }; + + class binary_semaphore { + + public: + + explicit binary_semaphore(int init_count = count_max) + + : count_(init_count) {} + + + + // P-operation / acquire + + void wait() + + { + + std::unique_lock lk(m_); + + cv_.wait(lk, [=]{ return 0 < count_; }); + + --count_; + + } + + bool try_wait() + + { + + std::lock_guard lk(m_); + + if (0 < count_) { + + --count_; + + return true; + + } else { + + return false; + + } + + } + + // V-operation / release + + void signal() + + { + + std::lock_guard lk(m_); + + if (count_ < count_max) { + + ++count_; + + cv_.notify_one(); + + } + + } + + + + // Lockable requirements + + void acquire() { wait(); } + + bool try_lock() { return try_wait(); } + + void release() { signal(); } + + + +private: + + static const int count_max = 1; + + int count_; + + std::mutex m_; + + std::condition_variable cv_; + +}; + // This is a server for a JSONRPC communication channel. + // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. + // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. + // This realization of this interface implements, by default, the following methods on this plugin + // - exists + // - register + // - unregister + // Any other methood to be handled by this plugin can be added can be added by using the + // templated methods Register on the PluginHost::JSONRPC class. + // As the registration/unregistration of notifications is realized by the class PluginHost::JSONRPC, + // this class exposes a public method called, Notify(), using this methods, all subscribed clients + // will receive a JSONRPC message as a notification, in case this method is called. + class HdmiCecSinkImplementation : public Exchange::IHdmiCecSink { + + enum { + POLL_THREAD_STATE_NONE, + POLL_THREAD_STATE_IDLE, + POLL_THREAD_STATE_POLL, + POLL_THREAD_STATE_PING, + POLL_THREAD_STATE_INFO, + POLL_THREAD_STATE_WAIT, + POLL_THREAD_STATE_CLEAN, + POLL_THREAD_STATE_UPDATE, + POLL_THREAD_STATE_EXIT, + }; + enum { + ARC_STATE_REQUEST_ARC_INITIATION, + ARC_STATE_ARC_INITIATED, + ARC_STATE_REQUEST_ARC_TERMINATION, + ARC_STATE_ARC_TERMINATED, + ARC_STATE_ARC_EXIT + }; + enum { + VOLUME_UP = 0x41, + VOLUME_DOWN = 0x42, + MUTE = 0x43, + UP = 0x01, + DOWN = 0x02, + LEFT = 0x03, + RIGHT = 0x04, + SELECT = 0x00, + HOME = 0x09, + BACK = 0x0D, + NUMBER_0 = 0x20, + NUMBER_1 = 0x21, + NUMBER_2 = 0x22, + NUMBER_3 = 0x23, + NUMBER_4 = 0x24, + NUMBER_5 = 0x25, + NUMBER_6 = 0x26, + NUMBER_7 = 0x27, + NUMBER_8 = 0x28, + NUMBER_9 = 0x29 + }; + public: + HdmiCecSinkImplementation(); + virtual ~HdmiCecSinkImplementation(); + static HdmiCecSinkImplementation* _instance; + CECDeviceParams deviceList[16]; + std::vector hdmiInputs; + int m_currentActiveSource; + void updateInActiveSource(const int logical_address, const InActiveSource &source ); + void updateActiveSource(const int logical_address, const ActiveSource &source ); + void updateTextViewOn(const int logicalAddress); + void updateImageViewOn(const int logicalAddress); + void updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr); + void getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route); + void removeDevice(const int logicalAddress); + void addDevice(const int logicalAddress); + void printDeviceList(); + void setStreamPath( const PhysicalAddress &physical_addr); + void setRoutingChange(const std::string &from, const std::string &to); + void sendStandbyMessage(); + void setCurrentLanguage(const Language &lang); + void sendMenuLanguage(); + void setActiveSource(bool isResponse); + void requestActiveSource(); + void startArc(); + void stopArc(); + void Process_InitiateArc(); + void Process_TerminateArc(); + void updateArcState(); + void requestShortaudioDescriptor(); + void Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor); + void Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg); + void Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg); + void sendDeviceUpdateInfo(const int logicalAddress); + void sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); + void reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); + void systemAudioModeRequest(); + void SendStandbyMsgEvent(const int logicalAddress); + void requestAudioDevicePowerStatus(); + void reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus); + void updateCurrentLatency(int videoLatency, bool lowLatencyMode, int audioOutputCompensated, int audioOutputDelay); + void setLatencyInfo(); + void Process_ReportAudioStatus_msg(const ReportAudioStatus msg); + void sendKeyPressEvent(const int logicalAddress, int keyCode); + void sendKeyReleaseEvent(const int logicalAddress); + void sendUserControlPressed(const int logicalAddress, int keyCode); + void sendUserControlReleased(const int logicalAddress); + void sendGiveAudioStatusMsg(); + void onPowerModeChanged(const PowerState ¤tState, const PowerState &newState); + void registerEventHandlers(); + void getHdmiArcPortID(); + int m_numberOfDevices; /* Number of connected devices othethan own device */ + bool m_audioDevicePowerStatusRequested; + + BEGIN_INTERFACE_MAP(HdmiCecSinkImplementation) + INTERFACE_ENTRY(Exchange::IHdmiCecSink) + END_INTERFACE_MAP + + private: + class PowerManagerNotification : public Exchange::IPowerManager::IModeChangedNotification { + private: + PowerManagerNotification(const PowerManagerNotification&) = delete; + PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; + + public: + explicit PowerManagerNotification(HdmiCecSinkImplementation& parent) + : _parent(parent) + { + } + ~PowerManagerNotification() override = default; + + public: + void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override + { + _parent.onPowerModeChanged(currentState, newState); + } + + template + T* baseInterface() + { + static_assert(std::is_base_of(), "base type mismatch"); + return static_cast(this); + } + + BEGIN_INTERFACE_MAP(PowerManagerNotification) + INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) + END_INTERFACE_MAP + + private: + HdmiCecSinkImplementation& _parent; + + }; + // We do not allow this plugin to be copied !! + HdmiCecSinkImplementation(const HdmiCecSinkImplementation&) = delete; + HdmiCecSinkImplementation& operator=(const HdmiCecSinkImplementation&) = delete; + //Begin methods + void InitializePowerManager(PluginHost::IShell *service); + //End methods + std::string logicalAddressDeviceType; + bool cecSettingEnabled; + bool cecOTPSettingEnabled; + bool cecEnableStatus; + bool hdmiCecAudioDeviceConnected; + bool m_isHdmiInConnected; + int m_numofHdmiInput; + uint8_t m_deviceType; + int m_logicalAddressAllocated; + std::thread m_pollThread; + uint32_t m_pollThreadState; + uint32_t m_pollNextState; + bool m_pollThreadExit; + uint32_t m_sleepTime; + std::mutex m_pollExitMutex; + std::mutex m_enableMutex; + /* Send Key event related */ + bool m_sendKeyEventThreadExit; + bool m_sendKeyEventThreadRun; + bool m_isAudioStatusInfoUpdated; + bool m_audioStatusReceived; + bool m_audioStatusTimerStarted; + std::thread m_sendKeyEventThread; + std::mutex m_sendKeyEventMutex; + std::queue m_SendKeyQueue; + std::condition_variable m_sendKeyCV; + std::condition_variable m_ThreadExitCV; + + /* DALS - Latency Values */ + uint8_t m_video_latency; + uint8_t m_latency_flags; + uint8_t m_audio_output_delay; + + /* ARC related */ + std::thread m_arcRoutingThread; + uint32_t m_currentArcRoutingState; + std::mutex m_arcRoutingStateMutex; + binary_semaphore m_semSignaltoArcRoutingThread; + bool m_arcstarting; + TpTimer m_arcStartStopTimer; + TpTimer m_audioStatusDetectionTimer; + + Connection *smConnection; + std::vector m_connectedDevices; + HdmiCecSinkProcessor *msgProcessor; + HdmiCecSinkFrameListener *msgFrameListener; + PowerManagerInterfaceRef _powerManagerPlugin; + Core::Sink _pwrMgrNotification; + bool _registeredEventHandlers; + const void InitializeIARM(); + void DeinitializeIARM(); + void allocateLogicalAddress(int deviceType); + void allocateLAforTV(); + void pingDevices(std::vector &connected , std::vector &disconnected); + void CheckHdmiInState(); + void request(const int logicalAddress); + int requestType(const int logicalAddress); + int requestStatus(const int logicalAddress); + static void threadRun(); + void cecMonitoringThread(); + static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + void onHdmiHotPlug(int portId, int connectStatus); + bool loadSettings(); + void persistSettings(bool enableStatus); + void persistOTPSettings(bool enableStatus); + void persistOSDName(const char *name); + void persistVendorId(unsigned int vendorID); + void setEnabled(bool enabled); + bool getEnabled(); + bool getAudioDeviceConnectedStatus(); + void CECEnable(void); + void CECDisable(void); + void getPhysicalAddress(); + void getLogicalAddress(); + void cecAddressesChanged(int changeStatus); + + // Arc functions + + static void threadSendKeyEvent(); + static void threadArcRouting(); + void requestArcInitiation(); + void requestArcTermination(); + void Send_Request_Arc_Initiation_Message(); + void Send_Report_Arc_Initiated_Message(); + void Send_Request_Arc_Termination_Message(); + void Send_Report_Arc_Terminated_Message(); + void arcStartStopTimerFunction(); + void audioStatusTimerFunction(); + void getCecVersion(); + + + public: + Core::hresult GetActiveRoute(bool &available, uint8_t &length, IHdmiCecSinkActivePathIterator*& pathList, string &ActiveRoute, bool &success) override; + Core::hresult GetActiveSource(bool &available, uint8_t &logicalAddress, string &physicalAddress, string &deviceType, string &cecVersion, string &osdName, string &vendorID, string &powerStatus, string &port, bool &success) override; + Core::hresult GetAudioDeviceConnectedStatus(bool &connected, bool &success) override; + Core::hresult GetDeviceList(uint32_t &numberofdevices, IHdmiCecSinkDeviceListIterator*& deviceList, bool &success) override; + Core::hresult GetEnabled(bool &enabled, bool &success) override; + Core::hresult GetOSDName(string &name, bool &success) override; + Core::hresult GetVendorId(string &vendorid, bool &success) override; + Core::hresult PrintDeviceList(bool &printed, bool &success) override; + Core::hresult RequestActiveSource(HdmiCecSinkSuccess &success) override; + Core::hresult RequestShortAudioDescriptor(HdmiCecSinkSuccess &success) override; + Core::hresult SendAudioDevicePowerOnMessage(HdmiCecSinkSuccess &success) override; + Core::hresult SendGetAudioStatusMessage(HdmiCecSinkSuccess &success) override; + Core::hresult SendKeyPressEvent(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) override; + Core::hresult SendUserControlPressed(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) override; + Core::hresult SendUserControlReleased(const uint32_t &logicalAddress, HdmiCecSinkSuccess &success) override; + Core::hresult SendStandbyMessage(HdmiCecSinkSuccess &success) override; + Core::hresult SetActivePath(const string &activePath, HdmiCecSinkSuccess &success) override; + Core::hresult SetActiveSource(HdmiCecSinkSuccess &success) override; + Core::hresult SetEnabled(const bool &enabled, HdmiCecSinkSuccess &success) override; + Core::hresult SetOSDName(const string &name, HdmiCecSinkSuccess &success) override; + Core::hresult SetRoutingChange(const string &oldPort, const string &newPort, HdmiCecSinkSuccess &success) override; + Core::hresult SetupARCRouting(const bool &enabled, HdmiCecSinkSuccess &success) override; + Core::hresult SetVendorId(const string &vendorId, HdmiCecSinkSuccess &success) override; + Core::hresult SetLatencyInfo(const string &videoLatency, const string &lowLatencyMode, const string &audioOutputCompensated, const string &audioOutputDelay, HdmiCecSinkSuccess &success) override; + Core::hresult Configure(PluginHost::IShell* service) override; + Core::hresult Register(Exchange::IHdmiCecSink::INotification *notification) override; + Core::hresult Unregister(Exchange::IHdmiCecSink::INotification *notification) override; + Core::hresult SetMenuLanguage(const string &language, HdmiCecSinkSuccess &success) override; + + private: + std::list _hdmiCecSinkNotifications; + mutable Core::CriticalSection _adminLock; + }; + } // namespace Plugin +} // namespace WPEFramework + + + + diff --git a/HdmiCecSource/HdmiCecSourceImplementation.cpp b/HdmiCecSource/HdmiCecSourceImplementation.cpp index 4a4e3e64..1086f6ac 100644 --- a/HdmiCecSource/HdmiCecSourceImplementation.cpp +++ b/HdmiCecSource/HdmiCecSourceImplementation.cpp @@ -135,7 +135,7 @@ namespace WPEFramework LOGINFO("Command: TextViewOn\n"); HdmiCecSourceImplementation::_instance->addDevice(header.from.toInt()); } - void HdmiCecSourceProcessor::process (const RequestActiveSource &msg, const Header &header) + void HdmiCecSourceProcessor::process (const RequestActiveSourceMessage &msg, const Header &header) { printHeader(header); LOGINFO("Command: RequestActiveSource\n"); @@ -178,7 +178,7 @@ namespace WPEFramework LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); HdmiCecSourceImplementation::_instance->addDevice(header.from.toInt()); } - void HdmiCecSourceProcessor::process (const SetMenuLanguage &msg, const Header &header) + void HdmiCecSourceProcessor::process (const SetMenuLanguageMessage &msg, const Header &header) { printHeader(header); LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); @@ -1031,7 +1031,7 @@ namespace WPEFramework LOGINFO("Command: sending GiveDevicePowerStatus \r\n"); smConnection->sendTo(LogicalAddress::TV, MessageEncoder().encode(GiveDevicePowerStatus())); LOGINFO("Command: sending request active Source isDeviceActiveSource is set to false\r\n"); - smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(RequestActiveSource())); + smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(RequestActiveSourceMessage())); isDeviceActiveSource = false; LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n", \ (isLGTvConnected)?lgVendorId.toString().c_str():appVendorId.toString().c_str()); diff --git a/HdmiCecSource/HdmiCecSourceImplementation.h b/HdmiCecSource/HdmiCecSourceImplementation.h index 6239dab5..d0494a18 100644 --- a/HdmiCecSource/HdmiCecSourceImplementation.h +++ b/HdmiCecSource/HdmiCecSourceImplementation.h @@ -68,11 +68,11 @@ namespace WPEFramework { void process (const InActiveSource &msg, const Header &header); void process (const ImageViewOn &msg, const Header &header); void process (const TextViewOn &msg, const Header &header); - void process (const RequestActiveSource &msg, const Header &header); + void process (const RequestActiveSourceMessage &msg, const Header &header); void process (const Standby &msg, const Header &header); void process (const GetCECVersion &msg, const Header &header); void process (const CECVersion &msg, const Header &header); - void process (const SetMenuLanguage &msg, const Header &header); + void process (const SetMenuLanguageMessage &msg, const Header &header); void process (const GiveOSDName &msg, const Header &header); void process (const GivePhysicalAddress &msg, const Header &header); void process (const GiveDeviceVendorID &msg, const Header &header); diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index 23762b08..406598ac 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -114,8 +114,10 @@ add_plugin_test_ex(PLUGIN_HDMIINPUT tests/test_HdmiInput.cpp "${HDMIINPUT_INC}" add_plugin_test_ex(PLUGIN_HDMICEC2 tests/test_HdmiCec2.cpp "../../HdmiCec_2" "${NAMESPACE}HdmiCec_2") # PLUGIN_HDMICECSINK -set (HDMICECSINK_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiCecSink ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) -add_plugin_test_ex(PLUGIN_HDMICECSINK tests/test_HdmiCecSink.cpp "${HDMICECSINK_INC}" "${NAMESPACE}HdmiCecSink") +set (HDMICECSINK_INC ${CMAKE_SINK_DIR}/../entservices-inputoutput/HdmiCecSink ${CMAKE_SINK_DIR}/../entservices-inputoutput/helpers) +set (HDMICECSINK_LIBS ${NAMESPACE}HdmiCecSink ${NAMESPACE}HdmiCecSinkImplementation) +add_plugin_test_ex(PLUGIN_HDMICECSINK tests/test_HdmiCecSink.cpp "${HDMICECSINK_INC}" "${HDMICECSINK_LIBS}") + # PLUGIN_HDMICECSOURCE set (HDMICECSOURCE_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiCecSource ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) diff --git a/Tests/L1Tests/tests/test_HdmiCecSource.cpp b/Tests/L1Tests/tests/test_HdmiCecSource.cpp index 3ae56adb..a298e038 100755 --- a/Tests/L1Tests/tests/test_HdmiCecSource.cpp +++ b/Tests/L1Tests/tests/test_HdmiCecSource.cpp @@ -989,7 +989,7 @@ TEST_F(HdmiCecSourceInitializedEventTest, requestActiveSourceProccess){ Header header; header.from = LogicalAddress(1); //specifies with logicalAddress in the deviceList we're using - RequestActiveSource requestActiveSource; + RequestActiveSourceMessage requestActiveSource; Plugin::HdmiCecSourceProcessor proc(Connection::getInstance()); From cc4f36979ba5a25a4ae96005b7e2c6dce1523044 Mon Sep 17 00:00:00 2001 From: svemur170 Date: Fri, 20 Jun 2025 15:32:30 +0000 Subject: [PATCH 18/52] RDK-57440 - Changelog updates for 1.3.0 Signed-off-by: svemur170 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76faba4a..7ad3be23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,16 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.3.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.2.0...1.3.0) + +- Feature/rdkemw 1015 comrpc [`#129`](https://github.com/rdkcentral/entservices-inputoutput/pull/129) +- RDK-57440: Causing config issue for higher versions of cmake [`#146`](https://github.com/rdkcentral/entservices-inputoutput/pull/146) +- Merge tag '1.2.0' into develop [`7b1dccc`](https://github.com/rdkcentral/entservices-inputoutput/commit/7b1dccc6d7bbba3fdf649c900ad15996e6424a27) + #### [1.2.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.1.1...1.2.0) +> 17 June 2025 + - RDKEMW-4135:Coverity integration with Entservices repo [`#147`](https://github.com/rdkcentral/entservices-inputoutput/pull/147) - RDKEMW-4116 : VRR Feature Middleware changes. [`#103`](https://github.com/rdkcentral/entservices-inputoutput/pull/103) - topic/RDK-58099: HdmiCecSink syntax error [`#142`](https://github.com/rdkcentral/entservices-inputoutput/pull/142) From 343ef1cc5f1902d8250bc31dc5458f67141a1111 Mon Sep 17 00:00:00 2001 From: hgfell683 <107510770+hgfell683@users.noreply.github.com> Date: Mon, 23 Jun 2025 19:23:35 +0000 Subject: [PATCH 19/52] RDKEMW-1015 - Update gtest (#155) * RDKEMW-1015 - Update gtest * RDKEMW-1015 - Update gtest * RDKEMW-1015 - Update gtest * RDKEMW-1015 - Update gtest * RDKEMW-1015 - Update gtest * RDKEMW-1015 - Update gtest * RDKEMW-1015 - Update gtest * RDKEMW-1015 - Update gtest --- .github/workflows/L1-tests.yml | 4 ++-- Tests/L1Tests/CMakeLists.txt | 3 +-- Tests/L1Tests/tests/test_HdmiCecSink.cpp | 3 +++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index d5748acf..0aaf227c 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -435,7 +435,7 @@ jobs: -DPLUGIN_AVINPUT=ON -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON - -DPLUGIN_HDMICECSOURCE=OFF + -DPLUGIN_HDMICECSOURCE=ON -DPLUGIN_HDMICECSINK=OFF -DUSE_THUNDER_R4=ON -DHIDE_NON_EXTERNAL_SYMBOLS=OFF @@ -513,7 +513,7 @@ jobs: -DPLUGIN_AVINPUT=ON -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON - -DPLUGIN_HDMICECSOURCE=OFF + -DPLUGIN_HDMICECSOURCE=ON -DPLUGIN_HDMICECSINK=OFF -DRDK_SERVICES_L1_TEST=ON -DUSE_THUNDER_R4=ON diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index 406598ac..2550627b 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -114,11 +114,10 @@ add_plugin_test_ex(PLUGIN_HDMIINPUT tests/test_HdmiInput.cpp "${HDMIINPUT_INC}" add_plugin_test_ex(PLUGIN_HDMICEC2 tests/test_HdmiCec2.cpp "../../HdmiCec_2" "${NAMESPACE}HdmiCec_2") # PLUGIN_HDMICECSINK -set (HDMICECSINK_INC ${CMAKE_SINK_DIR}/../entservices-inputoutput/HdmiCecSink ${CMAKE_SINK_DIR}/../entservices-inputoutput/helpers) +set (HDMICECSINK_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiCecSink ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) set (HDMICECSINK_LIBS ${NAMESPACE}HdmiCecSink ${NAMESPACE}HdmiCecSinkImplementation) add_plugin_test_ex(PLUGIN_HDMICECSINK tests/test_HdmiCecSink.cpp "${HDMICECSINK_INC}" "${HDMICECSINK_LIBS}") - # PLUGIN_HDMICECSOURCE set (HDMICECSOURCE_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiCecSource ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) set (HDMICECSOURCE_LIBS ${NAMESPACE}HdmiCecSource ${NAMESPACE}HdmiCecSourceImplementation) diff --git a/Tests/L1Tests/tests/test_HdmiCecSink.cpp b/Tests/L1Tests/tests/test_HdmiCecSink.cpp index 2f570df1..38631077 100755 --- a/Tests/L1Tests/tests/test_HdmiCecSink.cpp +++ b/Tests/L1Tests/tests/test_HdmiCecSink.cpp @@ -22,6 +22,9 @@ #include #include + +#include "HdmiCecSinkImplementation.h" +#include "HdmiCecSinkMock.h" #include "HdmiCecSink.h" #include "FactoriesImplementation.h" #include "IarmBusMock.h" From 04bad692808674b04222bf90aa505a05da0dfec2 Mon Sep 17 00:00:00 2001 From: arjunbinu <51983664+arjunbinu@users.noreply.github.com> Date: Thu, 26 Jun 2025 21:56:45 +0100 Subject: [PATCH 20/52] RDKEMW-5512: Implement a fix for the SaveTVDimmingMode failure (#157) Co-authored-by: benjaminqcox --- AVOutput/AVOutputTVHelper.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index 7e3b28c5..cc401a7a 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -321,13 +321,13 @@ namespace Plugin { { tvDimmingMode_t index = tvDimmingMode_MAX; - if(mode.compare("local") == 0 ) { + if(mode.compare("Local") == 0 ) { index=tvDimmingMode_Local; } - else if(mode.compare("fixed") == 0 ) { + else if(mode.compare("Fixed") == 0 ) { index=tvDimmingMode_Fixed; } - else if(mode.compare("global") == 0 ) { + else if(mode.compare("Global") == 0 ) { index=tvDimmingMode_Global; } else { @@ -1514,13 +1514,13 @@ namespace Plugin { return 0; } else if( forParam.compare("DimmingMode") == 0 ) { - if (strncmp(param.value, "fixed", strlen(param.value))==0) { + if (strncmp(param.value, "Fixed", strlen(param.value))==0) { value=tvDimmingMode_Fixed; } - else if (strncmp(param.value, "local", strlen(param.value))==0) { + else if (strncmp(param.value, "Local", strlen(param.value))==0) { value=tvDimmingMode_Local; } - else if (strncmp(param.value, "global", strlen(param.value))==0) { + else if (strncmp(param.value, "Global", strlen(param.value))==0) { value=tvDimmingMode_Global; } return 0; @@ -1683,9 +1683,9 @@ namespace Plugin { void AVOutputTV::getDimmingModeStringFromEnum(int value, std::string &toStore) { const char *color_temp_string[] = { - [tvDimmingMode_Fixed] = "fixed", - [tvDimmingMode_Local] = "local", - [tvDimmingMode_Global] = "global", + [tvDimmingMode_Fixed] = "Fixed", + [tvDimmingMode_Local] = "Local", + [tvDimmingMode_Global] = "Global", }; toStore.clear(); toStore+=color_temp_string[value]; From 88527cedd22c2ca3d58c8b625ed9f90ba1128066 Mon Sep 17 00:00:00 2001 From: akanda200_comcast Date: Thu, 26 Jun 2025 16:59:41 -0400 Subject: [PATCH 21/52] 1.3.1 release changelog updates --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ad3be23..83faa0b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.3.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.0...1.3.1) + +- RDKEMW-5512: Implement a fix for the SaveTVDimmingMode failure [`#157`](https://github.com/rdkcentral/entservices-inputoutput/pull/157) +- RDKEMW-1015 - Update gtest [`#155`](https://github.com/rdkcentral/entservices-inputoutput/pull/155) +- Merge tag '1.3.0' into develop [`2499e0b`](https://github.com/rdkcentral/entservices-inputoutput/commit/2499e0b71c2fbb9e9a303a342fbc4965da5b52c9) + #### [1.3.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.2.0...1.3.0) +> 20 June 2025 + - Feature/rdkemw 1015 comrpc [`#129`](https://github.com/rdkcentral/entservices-inputoutput/pull/129) - RDK-57440: Causing config issue for higher versions of cmake [`#146`](https://github.com/rdkcentral/entservices-inputoutput/pull/146) +- RDK-57440 - Changelog updates for 1.3.0 [`cc4f369`](https://github.com/rdkcentral/entservices-inputoutput/commit/cc4f36979ba5a25a4ae96005b7e2c6dce1523044) - Merge tag '1.2.0' into develop [`7b1dccc`](https://github.com/rdkcentral/entservices-inputoutput/commit/7b1dccc6d7bbba3fdf649c900ad15996e6424a27) #### [1.2.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.1.1...1.2.0) From dbf065a32e9b6d2239236bc9255ef5764470f800 Mon Sep 17 00:00:00 2001 From: arjunbinu <51983664+arjunbinu@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:17:56 +0100 Subject: [PATCH 22/52] RDKEMW-5510: Integrate the ODM Phase 2 middleware changes into RDKE (#160) * RDKEMW-5510: Integrate the ODM Phase 2 middleware changes into RDKE * RDKEMW-5510: Updated CHANGELOG --- AVOutput/AVOutputTV.cpp | 20 +++++--- AVOutput/AVOutputTV.h | 5 -- AVOutput/AVOutputTVHelper.cpp | 87 ++++------------------------------- AVOutput/CHANGELOG.md | 8 ++++ 4 files changed, 30 insertions(+), 90 deletions(-) diff --git a/AVOutput/AVOutputTV.cpp b/AVOutput/AVOutputTV.cpp index e95b81e7..3f0e8e59 100644 --- a/AVOutput/AVOutputTV.cpp +++ b/AVOutput/AVOutputTV.cpp @@ -2203,14 +2203,17 @@ namespace Plugin { uint32_t AVOutputTV::getSupportedDolbyVisionModes(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); - tvDolbyMode_t dvModes[tvMode_Max]; - tvDolbyMode_t *dvModesPtr = dvModes; // Pointer to statically allocated tvDolbyMode_t array + tvDolbyMode_t dvModes[tvMode_Max] = { tvDolbyMode_Invalid }; + tvDolbyMode_t *dvModesPtr[tvMode_Max] = { 0 }; unsigned short totalAvailable = 0; - + for (int i = 0; i < tvMode_Max; i++) + { + dvModesPtr[i] = &dvModes[i]; + } // Set an initial value to indicate the mode type dvModes[0] = tvDolbyMode_Dark; - tvError_t ret = GetTVSupportedDolbyVisionModes(&dvModesPtr, &totalAvailable); + tvError_t ret = GetTVSupportedDolbyVisionModes(dvModesPtr, &totalAvailable); if(ret != tvERROR_NONE) { returnResponse(false); } @@ -2423,9 +2426,14 @@ namespace Plugin { uint32_t AVOutputTV::getSupportedPictureModes(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); - pic_modes_t *pictureModes; + pic_modes_t pictureModes[PIC_MODES_SUPPORTED_MAX]; + pic_modes_t *pictureModesPtr[PIC_MODES_SUPPORTED_MAX]={0}; unsigned short totalAvailable = 0; - tvError_t ret = GetTVSupportedPictureModes(&pictureModes,&totalAvailable); + for (int i = 0; i < PIC_MODES_SUPPORTED_MAX; i++) + { + pictureModesPtr[i] = &pictureModes[i]; + } + tvError_t ret = GetTVSupportedPictureModes(pictureModesPtr,&totalAvailable); if(ret != tvERROR_NONE) { returnResponse(false); } diff --git a/AVOutput/AVOutputTV.h b/AVOutput/AVOutputTV.h index 5e493068..612aebf8 100644 --- a/AVOutput/AVOutputTV.h +++ b/AVOutput/AVOutputTV.h @@ -27,7 +27,6 @@ #include "tvTypes.h" #include "tvSettings.h" -#include "tvSettingsExtODM.h" #include #include "Module.h" #include "tvError.h" @@ -270,7 +269,6 @@ class AVOutputTV : public AVOutputBase { private: - tvContentFormatType_t getContentFormatIndex(tvVideoHDRFormat_t formatToConvert); int getPictureModeIndex(std::string pqmode); int getSourceIndex(std::string source); int getFormatIndex(std::string format); @@ -308,7 +306,6 @@ class AVOutputTV : public AVOutputBase { string convertSourceIndexToString(int source); string convertVideoFormatToString(int format); string convertPictureIndexToString(int pqmode); - tvContentFormatType_t convertFormatStringToTVContentFormat(const char *format); //std::string convertSourceIndexToString(int sourceIndex); //std::string convertVideoFormatToString( int formatIndex ); void convertUserScaleBacklightToDriverScale(int format,int * params); @@ -340,10 +337,8 @@ class AVOutputTV : public AVOutputBase { int getLocalparam( std::string forParam,paramIndex_t indexInfo,int & value,tvPQParameterIndex_t pqParamIndex,bool sync=false); tvDataComponentColor_t getComponentColorEnum(std::string colorName); - int getDolbyParams(tvContentFormatType_t format, std::string &s, std::string source = ""); tvError_t getParamsCaps(std::string param, capVectors_t &vecInfo); int GetPanelID(char *panelid); - int ConvertHDRFormatToContentFormat(tvhdr_type_t hdrFormat); int ReadCapablitiesFromConf(std::string param, capDetails_t& info); void getDimmingModeStringFromEnum(int value, std::string &toStore); void getColorTempStringFromEnum(int value, std::string &toStore); diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index cc401a7a..527569a9 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -32,36 +32,6 @@ static bool m_isDalsEnabled = false; namespace WPEFramework { namespace Plugin { - tvContentFormatType_t AVOutputTV::getContentFormatIndex(tvVideoHDRFormat_t formatToConvert) - { - /* default to SDR always*/ - tvContentFormatType_t ret = tvContentFormatType_NONE; - switch(formatToConvert) { - case tvVideoHDRFormat_HLG: - ret = tvContentFormatType_HLG; - break; - - case tvVideoHDRFormat_HDR10: - ret = tvContentFormatType_HDR10; - break; - - case tvVideoHDRFormat_HDR10PLUS: - ret = tvContentFormatType_HDR10PLUS; - break; - - case tvVideoHDRFormat_DV: - ret = tvContentFormatType_DOVI; - break; - - case tvVideoHDRFormat_SDR: - case tvVideoHDRFormat_NONE: - default: - ret = tvContentFormatType_SDR; - break; - } - return ret; - } - int AVOutputTV::getPictureModeIndex(std::string pqparam) { int index = -1; @@ -265,14 +235,19 @@ namespace Plugin { int AVOutputTV::getDolbyModeIndex(const char * dolbyMode) { int mode = 0; - tvDolbyMode_t dolbyModes[tvMode_Max]; - tvDolbyMode_t *dolbyModesPtr = dolbyModes; // Pointer to statically allocated tvDolbyMode_t array + tvDolbyMode_t dolbyModes[tvMode_Max] = { tvDolbyMode_Invalid }; + tvDolbyMode_t *dolbyModesPtr[tvMode_Max] = { 0 }; unsigned short totalAvailable = 0; + for (int i = 0; i < tvMode_Max; i++) + { + dolbyModesPtr[i] = &dolbyModes[i]; + } + // Set an initial value to indicate the mode type dolbyModes[0] = tvDolbyMode_Dark; - tvError_t ret = GetTVSupportedDolbyVisionModes(&dolbyModesPtr, &totalAvailable); + tvError_t ret = GetTVSupportedDolbyVisionModes(dolbyModesPtr, &totalAvailable); if (ret == tvERROR_NONE) { for (int count = 0; count < totalAvailable; count++) { if(strncasecmp(dolbyMode, getDolbyModeStringFromEnum(dolbyModes[count]).c_str(), strlen(dolbyMode))==0) { @@ -925,26 +900,6 @@ namespace Plugin { return ret; } - tvContentFormatType_t AVOutputTV::convertFormatStringToTVContentFormat(const char *format) - { - tvContentFormatType_t ret = tvContentFormatType_SDR; - - if( strncmp(format,"sdr",strlen(format)) == 0 || strncmp(format,"SDR",strlen(format)) == 0 ) { - ret = tvContentFormatType_SDR; - } - else if( strncmp(format,"hdr10",strlen(format)) == 0 || strncmp(format,"HDR10",strlen(format))==0 ) { - ret = tvContentFormatType_HDR10; - } - else if( strncmp(format,"hlg",strlen(format)) == 0 || strncmp(format,"HLG",strlen(format)) == 0 ) { - ret = tvContentFormatType_HLG; - } - else if( strncmp(format,"dolby",strlen(format)) == 0 || strncmp(format,"DOLBY",strlen(format)) == 0 ) { - ret=tvContentFormatType_DOVI; - } - - return ret; - } - tvError_t AVOutputTV::updateAVoutputTVParamToHAL(std::string forParam, paramIndex_t indexInfo, int value,bool setNotDelete) { tvError_t ret = tvERROR_NONE; @@ -1654,32 +1609,6 @@ namespace Plugin { return 0; } - int AVOutputTV::ConvertHDRFormatToContentFormat(tvhdr_type_t hdrFormat) - { - int ret=tvContentFormatType_SDR; - switch(hdrFormat) - { - case HDR_TYPE_SDR: - ret=tvContentFormatType_SDR; - break; - case HDR_TYPE_HDR10: - ret=tvContentFormatType_HDR10; - break; - case HDR_TYPE_HDR10PLUS: - ret=tvContentFormatType_HDR10PLUS; - break; - case HDR_TYPE_DOVI: - ret=tvContentFormatType_DOVI; - break; - case HDR_TYPE_HLG: - ret=tvContentFormatType_HLG; - break; - default: - break; - } - return ret; - } - void AVOutputTV::getDimmingModeStringFromEnum(int value, std::string &toStore) { const char *color_temp_string[] = { diff --git a/AVOutput/CHANGELOG.md b/AVOutput/CHANGELOG.md index a3afa122..e5f68a0f 100644 --- a/AVOutput/CHANGELOG.md +++ b/AVOutput/CHANGELOG.md @@ -14,6 +14,14 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.1.2] - 2025-07-01 +### Fixed +- Phase2 ODM + +## [1.1.1] - 2025-06-26 +### Fixed +- Fixed dimmingMode failures + ## [1.1.0] - 2025-03-14 ### Added - Add additional features on AVOutput From a70cf9a4229cfcc4f468cdd49064708f8bfd65aa Mon Sep 17 00:00:00 2001 From: svemur170 Date: Tue, 1 Jul 2025 16:26:41 +0000 Subject: [PATCH 23/52] RDKEMW-5510 - Changelog updates for 1.3.2 Signed-off-by: svemur170 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83faa0b3..6d0c412b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,18 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.3.2](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.1...1.3.2) + +- RDKEMW-5510: Integrate the ODM Phase 2 middleware changes into RDKE [`#160`](https://github.com/rdkcentral/entservices-inputoutput/pull/160) +- Merge tag '1.3.1' into develop [`8083548`](https://github.com/rdkcentral/entservices-inputoutput/commit/808354842ca703cbcd49d04ee6ceeca5911d1653) + #### [1.3.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.0...1.3.1) +> 26 June 2025 + - RDKEMW-5512: Implement a fix for the SaveTVDimmingMode failure [`#157`](https://github.com/rdkcentral/entservices-inputoutput/pull/157) - RDKEMW-1015 - Update gtest [`#155`](https://github.com/rdkcentral/entservices-inputoutput/pull/155) +- 1.3.1 release changelog updates [`88527ce`](https://github.com/rdkcentral/entservices-inputoutput/commit/88527cedd22c2ca3d58c8b625ed9f90ba1128066) - Merge tag '1.3.0' into develop [`2499e0b`](https://github.com/rdkcentral/entservices-inputoutput/commit/2499e0b71c2fbb9e9a303a342fbc4965da5b52c9) #### [1.3.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.2.0...1.3.0) From 375a96e3be25b8d9198d5a95942630dca4ea26ab Mon Sep 17 00:00:00 2001 From: Sankalp Maneshwar Date: Mon, 7 Jul 2025 20:43:20 +0530 Subject: [PATCH 24/52] RDK-42386 : Improve Unit Tests Coverage for AVInput Plugin (#164) * RDK-42386 : Improve Unit Tests Coverage for AVInput Plugin Reason for change: Adding L1 test cases for code coverage improvements. Test Procedure: Run L1test to verify Risks: Medium Signed-off-by: Sankalp * Update test_AVInput.cpp Added negative Test fixtures for all the APIs * Update test_AVInput.cpp * Update test_AVInput.cpp * Update test_AVInput.cpp * Update test_AVInput.cpp * Update test_AVInput.cpp * Update test_AVInput.cpp --------- Signed-off-by: Sankalp Co-authored-by: Sankalp --- Tests/L1Tests/tests/test_AVInput.cpp | 1847 +++++++++++++++++++++++++- 1 file changed, 1837 insertions(+), 10 deletions(-) diff --git a/Tests/L1Tests/tests/test_AVInput.cpp b/Tests/L1Tests/tests/test_AVInput.cpp index a82e2d21..0d0be6bd 100644 --- a/Tests/L1Tests/tests/test_AVInput.cpp +++ b/Tests/L1Tests/tests/test_AVInput.cpp @@ -21,7 +21,12 @@ #include "AVInput.h" +#include "CompositeInputMock.h" +#include "FactoriesImplementation.h" #include "HdmiInputMock.h" +#include "HostMock.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" #include "ThunderPortability.h" using namespace WPEFramework; @@ -46,13 +51,27 @@ class AVInputTest : public ::testing::Test { class AVInputDsTest : public AVInputTest { protected: - HdmiInputImplMock *p_hdmiInputImplMock = nullptr ; + HdmiInputImplMock* p_hdmiInputImplMock = nullptr; + CompositeInputImplMock* p_compositeInputImplMock = nullptr; + HostImplMock* p_HostImplMock = nullptr; + IARM_EventHandler_t dsAVGameFeatureStatusEventHandler; + IARM_EventHandler_t dsAVEventHandler; + IARM_EventHandler_t dsAVSignalStatusEventHandler; + IARM_EventHandler_t dsAVStatusEventHandler; + IARM_EventHandler_t dsAVVideoModeEventHandler; + IARM_EventHandler_t dsAviContentTypeEventHandler; AVInputDsTest() : AVInputTest() { p_hdmiInputImplMock = new NiceMock ; device::HdmiInput::setImpl(p_hdmiInputImplMock); + + p_compositeInputImplMock = new NiceMock; + device::CompositeInput::setImpl(p_compositeInputImplMock); + + p_HostImplMock = new NiceMock; + device::Host::setImpl(p_HostImplMock); } virtual ~AVInputDsTest() override { @@ -62,19 +81,1799 @@ class AVInputDsTest : public AVInputTest { delete p_hdmiInputImplMock; p_hdmiInputImplMock = nullptr; } + + device::CompositeInput::setImpl(nullptr); + if (p_compositeInputImplMock != nullptr) { + delete p_compositeInputImplMock; + p_compositeInputImplMock = nullptr; + } + + device::Host::setImpl(nullptr); + if (p_HostImplMock != nullptr) { + delete p_HostImplMock; + p_HostImplMock = nullptr; + } } }; -TEST_F(AVInputTest, RegisteredMethods) +class AVInputInit : public AVInputDsTest { +protected: + IarmBusImplMock* p_iarmBusImplMock = nullptr; + NiceMock factoriesImplementation; + PLUGINHOST_DISPATCHER* dispatcher; + NiceMock service; + Core::JSONRPC::Message message; + + AVInputInit() + : AVInputDsTest() + { + p_iarmBusImplMock = new NiceMock; + IarmBus::setImpl(p_iarmBusImplMock); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG)) { + EXPECT_TRUE(handler != nullptr); + dsAVEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsAVStatusEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsAVSignalStatusEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE)) { + EXPECT_TRUE(handler != nullptr); + dsAVVideoModeEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsAVGameFeatureStatusEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsAVGameFeatureStatusEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG)) { + EXPECT_TRUE(handler != nullptr); + dsAVEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsAVSignalStatusEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsAVStatusEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE)) { + EXPECT_TRUE(handler != nullptr); + dsAVVideoModeEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE)) { + EXPECT_TRUE(handler != nullptr); + dsAviContentTypeEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + PluginHost::IFactories::Assign(&factoriesImplementation); + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + } + + virtual ~AVInputInit() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + PluginHost::IFactories::Assign(nullptr); + + plugin->Deinitialize(&service); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } +}; + +TEST_F(AVInputTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("numberOfInputs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("currentVideoMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("contentProtected"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEdid2AllmSupport"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEdid2AllmSupport"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVRRSupport"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVRRSupport"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVRRFrameRate"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getInputDevices"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("writeEDID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("readEDID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getRawSPD"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSPD"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEdidVersion"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEdidVersion"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHdmiVersion"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setMixerLevels"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startInput"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopInput"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVideoRectangle"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSupportedGameFeatures"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getGameFeatureStatus"))); +} + +TEST_F(AVInputInit, getInputDevices) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getNumberOfInputs()) + .WillOnce(::testing::Return(1)); + EXPECT_CALL(*p_compositeInputImplMock, getNumberOfInputs()) + .WillOnce(::testing::Return(1)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInputDevices"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"devices\":[{\"id\":0,\"connected\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\"},{\"id\":0,\"connected\":false,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\"}],\"success\":true}")); +} + +TEST_F(AVInputInit, getInputDevices_HDMI) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getNumberOfInputs()) + .WillOnce(::testing::Return(1)); + EXPECT_CALL(*p_hdmiInputImplMock, isPortConnected(::testing::_)) + .WillOnce(::testing::Return(true)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInputDevices"), _T("{\"typeOfInput\": \"HDMI\"}"), response)); + EXPECT_EQ(response, string("{\"devices\":[{\"id\":0,\"connected\":true,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\"}],\"success\":true}")); +} + +TEST_F(AVInputInit, getInputDevices_COMPOSITE) +{ + EXPECT_CALL(*p_compositeInputImplMock, getNumberOfInputs()) + .WillOnce(::testing::Return(1)); + EXPECT_CALL(*p_compositeInputImplMock, isPortConnected(::testing::_)) + .WillOnce(::testing::Return(true)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInputDevices"), _T("{\"typeOfInput\": \"COMPOSITE\"}"), response)); + EXPECT_EQ(response, string("{\"devices\":[{\"id\":0,\"connected\":true,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\"}],\"success\":true}")); +} + +TEST_F(AVInputInit, getInputDevices_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getInputDevices"), _T("{\"typeOfInput\": \"Test\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, writeEDID) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("writeEDID"), _T("{\"portId\": \"1\",\"message\":\"Test\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, writeEDID_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("writeEDID"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, readEDID) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getEDIDBytesInfo(::testing::_, ::testing::_)) + .WillOnce([](int port, std::vector& edid) { + EXPECT_EQ(port, 1); + edid = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("readEDID"), _T("{\"portId\": \"1\"}"), response)); + EXPECT_EQ(response, string("{\"EDID\":\"AP\\/\\/\\/\\/\\/\\/\\/w==\",\"success\":true}")); +} + +TEST_F(AVInputInit, readEDIDFailure) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getEDIDBytesInfo(::testing::_, ::testing::_)) + .WillOnce([](int port, std::vector& edid) { + edid = {}; + }); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("readEDID"), _T("{\"portId\": \"1\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, readEDID_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("readEDID"), _T("{\"portId\": \"test\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, getRawSPD) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_, ::testing::_)) + .WillOnce([](int port, std::vector& data) { + data = { 0x53, 0x50, 0x44, 0x00 }; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getRawSPD"), _T("{\"portId\": \"1\"}"), response)); + EXPECT_EQ(response, string("{\"HDMISPD\":\"U1BEAA\",\"success\":true}")); +} + +TEST_F(AVInputInit, getRawSPD_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getRawSPD"), _T("{\"portId\": \"test\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, getSPD) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_, ::testing::_)) + .WillOnce([](int port, std::vector& data) { + data = { 0x53, 0x50, 0x44, 0x00 }; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSPD"), _T("{\"portId\": \"1\"}"), response)); + EXPECT_EQ(response, string("{\"HDMISPD\":\"Packet Type:53,Version:80,Length:68,vendor name:wn,product des:,source info:00\",\"success\":true}")); +} + +TEST_F(AVInputInit, getSPD_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getSPD"), _T("{\"portId\": \"test\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, setEdidVersion) +{ + EXPECT_CALL(*p_hdmiInputImplMock, setEdidVersion(::testing::_, ::testing::_)) + .WillOnce([](int port, int edidVersion) { + EXPECT_EQ(port, 1); + EXPECT_EQ(edidVersion, 0); + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"1\", \"edidVersion\":\"HDMI1.4\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, setEdidVersion_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"test\", \"edidVersion\":\"test\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, getEdidVersion1) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getEdidVersion(::testing::_, ::testing::_)) + .WillOnce([](int port, int* edidVersion) { + EXPECT_EQ(port, 0); + *edidVersion = 0; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"0\"}"), response)); + EXPECT_EQ(response, string("{\"edidVersion\":\"HDMI1.4\",\"success\":true}")); +} + +TEST_F(AVInputInit, getEdidVersion2) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getEdidVersion(::testing::_, ::testing::_)) + .WillOnce([](int port, int* edidVersion) { + EXPECT_EQ(port, 1); + *edidVersion = 1; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"1\"}"), response)); + EXPECT_EQ(response, string("{\"edidVersion\":\"HDMI2.0\",\"success\":true}")); +} + +TEST_F(AVInputInit, getEdidVersion_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"test\"}}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, getHdmiVersion) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getHdmiVersion(::testing::_, ::testing::_)) + .WillOnce([](int port, dsHdmiMaxCapabilityVersion_t* capVersion) { + if (capVersion) { + *capVersion = HDMI_COMPATIBILITY_VERSION_21; + } + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHdmiVersion"), _T("{\"portId\": \"1\"}"), response)); + EXPECT_EQ(response, string("{\"HdmiCapabilityVersion\":\"2.1\",\"success\":true}")); +} + +TEST_F(AVInputInit, getHdmiVersion_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getHdmiVersion"), _T("{\"portId\": \"test\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, setMixerLevels) +{ + EXPECT_CALL(*p_HostImplMock, setAudioMixerLevels(dsAUDIO_INPUT_PRIMARY, ::testing::_)) + .WillOnce([](dsAudioInput_t input, int volume) { + EXPECT_EQ(input, dsAUDIO_INPUT_PRIMARY); + EXPECT_EQ(volume, 50); + }); + + EXPECT_CALL(*p_HostImplMock, setAudioMixerLevels(dsAUDIO_INPUT_SYSTEM, ::testing::_)) + .WillOnce([](dsAudioInput_t input, int volume) { + EXPECT_EQ(input, dsAUDIO_INPUT_SYSTEM); + EXPECT_EQ(volume, 30); + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setMixerLevels"), _T("{\"primaryVolume\": 50 ,\"inputVolume\":30}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, setMixerLevelsErrorCase) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setMixerLevels"), _T("{\"primaryVolume\": 110 ,\"inputVolume\":110}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, startInput_HDMI) +{ + EXPECT_CALL(*p_hdmiInputImplMock, selectPort(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce([](int8_t Port, bool audioMix, int videoPlane, bool topMost) { + EXPECT_EQ(Port, 1); + EXPECT_EQ(audioMix, true); + EXPECT_EQ(videoPlane, 1); + EXPECT_EQ(topMost, true); + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startInput"), _T("{\"portId\": 1 ,\"typeOfInput\":\"HDMI\", \"requestAudioMix\": true, \"plane\" : 1, \"topMost\" : true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, startInput_COMPOSITE) +{ + EXPECT_CALL(*p_compositeInputImplMock, selectPort(::testing::_)) + .WillOnce([](int8_t Port) { + EXPECT_EQ(Port, 2); + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startInput"), _T("{\"portId\": 2 ,\"typeOfInput\":\"COMPOSITE\", \"requestAudioMix\": true, \"plane\" : 1, \"topMost\" : true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, startInput_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("startInput"), _T("{\"portId\": \"test\" ,\"typeOfInput\":\"HDMI\", \"requestAudioMix\": true, \"plane\" : 1, \"topMost\" : true}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, stopInput_HDMI) +{ + EXPECT_CALL(*p_hdmiInputImplMock, selectPort(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce([](int8_t Port, bool audioMix, int videoPlane, bool topMost) { + EXPECT_EQ(Port, -1); + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopInput"), _T("{\"typeOfInput\":\"HDMI\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, stopInput_COMPOSITE) +{ + EXPECT_CALL(*p_compositeInputImplMock, selectPort(::testing::_)) + .WillOnce([](int8_t Port) { + EXPECT_EQ(Port, -1); + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopInput"), _T("{\"typeOfInput\":\"COMPOSITE\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, stopInput_COMPOSITE_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopInput"), _T("{\"typeOfInput\":\"DP\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, setVideoRectangle_HDMI) +{ + EXPECT_CALL(*p_hdmiInputImplMock, scaleVideo(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce([](int32_t x, int32_t y, int32_t width, int32_t height) { + EXPECT_EQ(x, 0); + EXPECT_EQ(y, 0); + EXPECT_EQ(width, 3840); + EXPECT_EQ(height, 2160); + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\" : 0, \"y\" : 0, \"w\" : 3840, \"h\" : 2160 ,\"typeOfInput\":\"HDMI\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, setVideoRectangle_COMPOSITE) +{ + EXPECT_CALL(*p_compositeInputImplMock, scaleVideo(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce([](int32_t x, int32_t y, int32_t width, int32_t height) { + EXPECT_EQ(x, 0); + EXPECT_EQ(y, 0); + EXPECT_EQ(width, 720); + EXPECT_EQ(height, 480); + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\" : 0, \"y\" : 0, \"w\" : 720, \"h\" : 480 ,\"typeOfInput\":\"COMPOSITE\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(AVInputInit, setVideoRectangle_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\" : 0, \"y\" : 0, \"w\" : 720, \"h\" : 480 ,\"typeOfInput\":\"DP\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, getSupportedGameFeatures) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getSupportedGameFeatures(::testing::_)) + .WillOnce([](std::vector& featureList) { + featureList = { "ALLM", "VRR", "QMS" }; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSupportedGameFeatures"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"supportedGameFeatures\":[\"ALLM\",\"VRR\",\"QMS\"],\"success\":true}")); +} + +TEST_F(AVInputInit, getSupportedGameFeatures_ErrorCase) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getSupportedGameFeatures(::testing::_)) + .WillOnce([](std::vector& featureList) { + featureList = {}; + }); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getSupportedGameFeatures"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, getGameFeatureStatus_ALLM) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_, ::testing::_)) + .WillOnce([](int iHdmiPort, bool* allmStatus) { + EXPECT_EQ(iHdmiPort, 1); + *allmStatus = true; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getGameFeatureStatus"), _T("{\"portId\" : 1, \"gameFeature\" : \"ALLM\"}"), response)); + EXPECT_EQ(response, string("{\"mode\":true,\"success\":true}")); +} + +TEST_F(AVInputInit, getGameFeatureStatus_VRR_HDMI) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getVRRStatus(::testing::_, ::testing::_)) + .WillOnce([](int iHdmiPort, dsHdmiInVrrStatus_t* vrrStatus) { + ASSERT_NE(vrrStatus, nullptr); + vrrStatus->vrrType = dsVRR_HDMI_VRR; + vrrStatus->vrrAmdfreesyncFramerate_Hz = 90.00; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getGameFeatureStatus"), _T("{\"portId\" : 1, \"gameFeature\" : \"VRR-HDMI\"}"), response)); + EXPECT_EQ(response, string("{\"mode\":true,\"success\":true}")); +} + +TEST_F(AVInputInit, getGameFeatureStatus_VRR_FREESYNC) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getVRRStatus(::testing::_, ::testing::_)) + .WillOnce([](int iHdmiPort, dsHdmiInVrrStatus_t* vrrStatus) { + ASSERT_NE(vrrStatus, nullptr); + vrrStatus->vrrType = dsVRR_AMD_FREESYNC; + vrrStatus->vrrAmdfreesyncFramerate_Hz = 100.00; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getGameFeatureStatus"), _T("{\"portId\" : 1, \"gameFeature\" : \"VRR-FREESYNC\"}"), response)); + EXPECT_EQ(response, string("{\"mode\":true,\"success\":true}")); +} + +TEST_F(AVInputInit, getGameFeatureStatus_VRR_FREESYNC_PREMIUM) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getVRRStatus(::testing::_, ::testing::_)) + .WillOnce([](int iHdmiPort, dsHdmiInVrrStatus_t* vrrStatus) { + ASSERT_NE(vrrStatus, nullptr); + vrrStatus->vrrType = dsVRR_AMD_FREESYNC_PREMIUM; + vrrStatus->vrrAmdfreesyncFramerate_Hz = 120.00; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getGameFeatureStatus"), _T("{\"portId\" : 1, \"gameFeature\" : \"VRR-FREESYNC-PREMIUM\"}"), response)); + EXPECT_EQ(response, string("{\"mode\":true,\"success\":true}")); +} + +TEST_F(AVInputInit, getGameFeatureStatus_VRR_FREESYNC_PREMIUM_PRO) +{ + EXPECT_CALL(*p_hdmiInputImplMock, getVRRStatus(::testing::_, ::testing::_)) + .WillOnce([](int iHdmiPort, dsHdmiInVrrStatus_t* vrrStatus) { + ASSERT_NE(vrrStatus, nullptr); + vrrStatus->vrrType = dsVRR_AMD_FREESYNC_PREMIUM_PRO; + vrrStatus->vrrAmdfreesyncFramerate_Hz = 144.00; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getGameFeatureStatus"), _T("{\"portId\" : 1, \"gameFeature\" : \"VRR-FREESYNC-PREMIUM-PRO\"}"), response)); + EXPECT_EQ(response, string("{\"mode\":true,\"success\":true}")); +} + +TEST_F(AVInputInit, getGameFeatureStatus_InvalidParameters) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getGameFeatureStatus"), _T("{\"portId\" : \"test\", \"gameFeature\" : \"VRR-FREESYNC-PREMIUM-PRO\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(AVInputInit, onDevicesChangedHDMI) +{ + Core::Event onDevicesChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onDevicesChanged\",\"params\":{\"devices\":[]}}"); + + onDevicesChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onDevicesChanged"), _T("org.rdk.AVInput"), message); + + ASSERT_TRUE(dsAVEventHandler != nullptr); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_connect.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_connect.isPortConnected = true; + dsAVEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onDevicesChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onDevicesChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onDevicesChangedCOMPOSITE) +{ + Core::Event onDevicesChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onDevicesChanged\",\"params\":{\"devices\":[]}}"); + + onDevicesChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onDevicesChanged"), _T("org.rdk.AVInput"), message); + + ASSERT_TRUE(dsAVEventHandler != nullptr); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_connect.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_connect.isPortConnected = true; + dsAVEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onDevicesChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onDevicesChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedStableHDMI) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, + "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"stableSignal\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_STABLE; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedNoSignalHDMI) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, + "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"noSignal\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_NOSIGNAL; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedUnstableHDMI) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, + "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"unstableSignal\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_UNSTABLE; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedNotSupportedHDMI) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"notSupportedSignal\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_NOTSUPPORTED; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedDefaultHDMI) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"none\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_MAX; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedStableCOMPOSITE) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"stableSignal\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_STABLE; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedNoSignalCOMPOSITE) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"noSignal\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_NOSIGNAL; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedUnstableCOMPOSITE) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"unstableSignal\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_UNSTABLE; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedNotSupportedCOMPOSITE) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"notSupportedSignal\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_NOTSUPPORTED; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onSignalChangedDefaultCOMPOSITE) +{ + Core::Event onSignalChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"none\"}}"); + + onSignalChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_MAX; + dsAVSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSignalChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onInputStatusChangeOn_HDMI) +{ + Core::Event onInputStatusChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"started\",\"plane\":1}}"); + + onInputStatusChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onInputStatusChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startInput"), _T("{\"portId\": \"0\" , \"typeOfInput\":\"HDMI\", \"requestAudioMix\": true, \"plane\" : 1, \"topMost\" : true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_status.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_status.isPresented = true; + dsAVStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onInputStatusChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onInputStatusChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onInputStatusChangeOff_HDMI) +{ + Core::Event onInputStatusChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"stopped\",\"plane\":-1}}"); + + onInputStatusChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onInputStatusChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopInput"), _T("{\"typeOfInput\":\"HDMI\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_status.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_status.isPresented = false; + + dsAVStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onInputStatusChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onInputStatusChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onInputStatusChangeOn_COMPOSITE) +{ + Core::Event onInputStatusChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"started\",\"plane\":1}}"); + + onInputStatusChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onInputStatusChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startInput"), _T("{\"portId\": \"0\" , \"typeOfInput\":\"COMPOSITE\", \"requestAudioMix\": true, \"plane\" : 1, \"topMost\" : true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_status.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_status.isPresented = true; + dsAVStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onInputStatusChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onInputStatusChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, onInputStatusChangeOff_COMPOSITE) +{ + Core::Event onInputStatusChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"stopped\",\"plane\":-1}}"); + + onInputStatusChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onInputStatusChanged"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopInput"), _T("{\"typeOfInput\":\"COMPOSITE\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_status.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_status.isPresented = false; + dsAVStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onInputStatusChanged.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("onInputStatusChanged"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, hdmiGameFeatureStatusUpdate) +{ + Core::Event gameFeatureStatusUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.gameFeatureStatusUpdate\",\"params\":{\"id\":0,\"gameFeature\":\"ALLM\",\"mode\":true}}"); + + gameFeatureStatusUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_allm_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_allm_mode.allm_mode = true; + dsAVGameFeatureStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, gameFeatureStatusUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, hdmiGameFeatureStatusUpdate_HDMI_VRR) +{ + Core::Event gameFeatureStatusUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.gameFeatureStatusUpdate\",\"params\":{\"id\":0,\"gameFeature\":\"VRR-HDMI\",\"mode\":true}}"); + + gameFeatureStatusUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_vrr_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_vrr_mode.vrr_type = dsVRR_HDMI_VRR; + dsAVGameFeatureStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, gameFeatureStatusUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, hdmiGameFeatureStatusUpdate_AMD_FREESYNC) { - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("numberOfInputs"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("currentVideoMode"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("contentProtected"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEdid2AllmSupport"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEdid2AllmSupport"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVRRSupport"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVRRSupport"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVRRFrameRate"))); + Core::Event gameFeatureStatusUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.gameFeatureStatusUpdate\",\"params\":{\"id\":0,\"gameFeature\":\"VRR-FREESYNC\",\"mode\":true}}"); + + gameFeatureStatusUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_vrr_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_vrr_mode.vrr_type = dsVRR_AMD_FREESYNC; + dsAVGameFeatureStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, gameFeatureStatusUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, hdmiGameFeatureStatusUpdate_AMD_FREESYNC_PREMIUM) +{ + Core::Event gameFeatureStatusUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.gameFeatureStatusUpdate\",\"params\":{\"id\":0,\"gameFeature\":\"VRR-FREESYNC-PREMIUM\",\"mode\":true}}"); + + gameFeatureStatusUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_vrr_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_vrr_mode.vrr_type = dsVRR_AMD_FREESYNC_PREMIUM; + dsAVGameFeatureStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, gameFeatureStatusUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, hdmiGameFeatureStatusUpdate_AMD_FREESYNC_PREMIUM_PRO) +{ + Core::Event gameFeatureStatusUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.gameFeatureStatusUpdate\",\"params\":{\"id\":0,\"gameFeature\":\"VRR-FREESYNC-PREMIUM-PRO\",\"mode\":true}}"); + + gameFeatureStatusUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_vrr_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_vrr_mode.vrr_type = dsVRR_AMD_FREESYNC_PREMIUM_PRO; + dsAVGameFeatureStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, gameFeatureStatusUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("gameFeatureStatusUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate1_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":1920,\"height\":1080,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":60000,\"frameRateD\":1001}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1920x1080; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_59dot94; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate2_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":720,\"height\":480,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":24000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x480; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_24; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate3_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":720,\"height\":576,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":25000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x576; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_25; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate4_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":3840,\"height\":2160,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":30000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_3840x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_30; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate5_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":4096,\"height\":2160,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":50000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_50; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate6_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":4096,\"height\":2160,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":60000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_60; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate7_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":4096,\"height\":2160,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":24000,\"frameRateD\":1001}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_23dot98; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate8_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":4096,\"height\":2160,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":30000,\"frameRateD\":1001}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_29dot97; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate9_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":1280,\"height\":720,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":30000,\"frameRateD\":1001}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_29dot97; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate10_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":1280,\"height\":720,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":100000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_100; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate11_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":1280,\"height\":720,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":120000,\"frameRateD\":1001}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_119dot88; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate12_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":1280,\"height\":720,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":120000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_120; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate13_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":1280,\"height\":720,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":200000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_200; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate14_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":1280,\"height\":720,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":240000,\"frameRateD\":1001}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_239dot76; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdate15_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":1280,\"height\":720,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":240000,\"frameRateD\":100}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_240; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdateDefault_HDMI) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":1920,\"height\":1080,\"progressive\":false,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":60000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_MAX; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_MAX; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + + +TEST_F(AVInputInit, videoStreamInfoUpdate1_COMPOSITE) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":720,\"height\":480,\"progressive\":false,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":24000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_video_mode.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x480; + eventData.data.composite_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_24; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + + +TEST_F(AVInputInit, videoStreamInfoUpdate2_COMPOSITE) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":720,\"height\":576,\"progressive\":false,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":25000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_video_mode.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x576; + eventData.data.composite_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_25; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, videoStreamInfoUpdateDefault_COMPOSITE) +{ + Core::Event videoStreamInfoUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"width\":720,\"height\":576,\"progressive\":false,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"frameRateN\":60000,\"frameRateD\":1000}}"); + + videoStreamInfoUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_video_mode.port = dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_MAX; + eventData.data.composite_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_MAX; + dsAVVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, videoStreamInfoUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("org.rdk.AVInput"), message); +} + +TEST_F(AVInputInit, aviContentTypeUpdate_HDMI) +{ + Core::Event aviContentTypeUpdate(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,"{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.AVInput.aviContentTypeUpdate\",\"params\":{\"id\":0,\"aviContentType\":0}}"); + + aviContentTypeUpdate.SetEvent(); + + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("aviContentTypeUpdate"), _T("org.rdk.AVInput"), message); + ASSERT_TRUE(dsAVSignalStatusEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_content_type.port = dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_content_type.aviContentType = dsAVICONTENT_TYPE_GRAPHICS; + dsAviContentTypeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, aviContentTypeUpdate.Lock()); + + EVENT_UNSUBSCRIBE(0, _T("aviContentTypeUpdate"), _T("org.rdk.AVInput"), message); } TEST_F(AVInputTest, contentProtected) @@ -107,6 +1906,11 @@ TEST_F(AVInputDsTest, getEdid2AllmSupport) EXPECT_EQ(response, string("{\"allmSupport\":true,\"success\":true}")); } +TEST_F(AVInputDsTest, getEdid2AllmSupport_ErrorCase) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getEdid2AllmSupport"), _T("{\"portId\": \"test\",\"allmSupport\":true}"), response)); + EXPECT_EQ(response, string("")); +} TEST_F(AVInputDsTest, setEdid2AllmSupport) { @@ -114,21 +1918,44 @@ TEST_F(AVInputDsTest, setEdid2AllmSupport) EXPECT_EQ(response, string("{\"success\":true}")); } +TEST_F(AVInputDsTest, setEdid2AllmSupport_ErrorCase) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setEdid2AllmSupport"), _T("{\"portId\": \"test\",\"allmSupport\":true}"), response)); + EXPECT_EQ(response, string("")); +} + TEST_F(AVInputDsTest, getVRRSupport) { EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVRRSupport"), _T("{\"portId\": \"0\",\"vrrSupport\":true}"), response)); EXPECT_EQ(response, string("{\"vrrSupport\":true,\"success\":true}")); } +TEST_F(AVInputDsTest, getVRRSupport_ErrorCase) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getVRRSupport"), _T("{\"portId\": \"test\",\"vrrSupport\":true}"), response)); + EXPECT_EQ(response, string("")); +} + TEST_F(AVInputDsTest, setVRRSupport) { EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVRRSupport"), _T("{\"portId\": \"0\",\"vrrSupport\":true}"), response)); EXPECT_EQ(response, string("{\"success\":true}")); } +TEST_F(AVInputDsTest, setVRRSupport_ErrorCase) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setVRRSupport"), _T("{\"portId\": \"test\",\"vrrSupport\":true}"), response)); + EXPECT_EQ(response, string("")); +} + TEST_F(AVInputDsTest, getVRRFrameRate) { EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVRRFrameRate"), _T("{\"portId\": \"0\"}"), response)); EXPECT_EQ(response, string("{\"currentVRRVideoFrameRate\":0,\"success\":true}")); } +TEST_F(AVInputDsTest, getVRRFrameRate_ErrorCase) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getVRRFrameRate"), _T("{\"portId\": \"test\"}"), response)); + EXPECT_EQ(response, string("")); +} From 391cad6448a26e013fd5ae8c22f4bb4a0a0fc22f Mon Sep 17 00:00:00 2001 From: Prathyushakothuru <142974139+Prathyushakothuru@users.noreply.github.com> Date: Wed, 9 Jul 2025 17:01:56 +0530 Subject: [PATCH 25/52] cmake cleanup (#151) * Update CMakeLists.txt * Update test_HdcpProfile.cpp * Update L1-tests.yml * Update L2-tests.yml * Update L1-tests.yml * yml changes * adding header * fixing coverage error * Update L2-tests.yml * cleaning up unwanted header files * adding dummy macro * add plugin macro in testframeowrk build job * Update L2-tests.yml * Update L2-tests.yml * Update L2-tests.yml * Update L2-tests.yml * Update L2-tests.yml * Update CMakeLists.txt * changing the branch name to develop * Update CMakeLists.txt --------- Co-authored-by: PriyaPesala <116076033+PriyaPesala@users.noreply.github.com> --- .github/workflows/L1-tests.yml | 36 ++++++++------- .github/workflows/L2-tests.yml | 58 +++++++++--------------- Tests/L1Tests/CMakeLists.txt | 10 ---- Tests/L1Tests/tests/test_HdcpProfile.cpp | 2 - 4 files changed, 41 insertions(+), 65 deletions(-) diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 0aaf227c..209ff45f 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -288,6 +288,24 @@ jobs: if: ${{ matrix.compiler == 'gcc' && matrix.coverage == 'with-coverage' && !env.ACT }} run: echo "TOOLCHAIN_FILE=$GITHUB_WORKSPACE/entservices-testframework/Tests/gcc-with-coverage.cmake" >> $GITHUB_ENV + - name: Build googletest + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake -G Ninja + -S "$GITHUB_WORKSPACE/googletest" + -B build/googletest + -DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/install/usr" + -DCMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" + -DGENERIC_CMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" + -DBUILD_TYPE=Debug + -DBUILD_GMOCK=ON + -DBUILD_SHARED_LIBS=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + && + cmake --build build/googletest -j8 + && + cmake --install build/googletest + - name: Build mocks run: > cmake @@ -317,8 +335,10 @@ jobs: -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/ccec/drivers -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/network -I $GITHUB_WORKSPACE/entservices-testframework/Tests + -I $GITHUB_WORKSPACE/entservices-inputoutput/helpers -I $GITHUB_WORKSPACE/Thunder/Source -I $GITHUB_WORKSPACE/Thunder/Source/core + -I $GITHUB_WORKSPACE/install/usr/include -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Iarm.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Rfc.h @@ -350,22 +370,6 @@ jobs: && cmake --install build/mocks - - name: Build googletest - if: steps.cache.outputs.cache-hit != 'true' - run: > - cmake -G Ninja - -S "$GITHUB_WORKSPACE/googletest" - -B build/googletest - -DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/install/usr" - -DCMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" - -DGENERIC_CMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" - -DBUILD_TYPE=Debug - -DBUILD_GMOCK=ON - && - cmake --build build/googletest -j8 - && - cmake --install build/googletest - - name: Build entservices-inputoutput run: > cmake -G Ninja diff --git a/.github/workflows/L2-tests.yml b/.github/workflows/L2-tests.yml index 4d1bd361..c8a13eb5 100755 --- a/.github/workflows/L2-tests.yml +++ b/.github/workflows/L2-tests.yml @@ -240,23 +240,6 @@ jobs: if: ${{ matrix.compiler == 'gcc' && matrix.coverage == 'with-coverage' && !env.ACT }} run: echo "TOOLCHAIN_FILE=$GITHUB_WORKSPACE/entservices-testframework/Tests/gcc-with-coverage.cmake" >> $GITHUB_ENV - - name: Build mocks - run: > - cmake - -S "$GITHUB_WORKSPACE/entservices-testframework/Tests/mocks" - -B build/mocks - -DBUILD_SHARED_LIBS=ON - -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" - -DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/install/usr" - -DCMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - -DCMAKE_CXX_FLAGS=" - -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers" - && - cmake --build build/mocks -j8 - && - cmake --install build/mocks - - name: Build googletest if: steps.cache.outputs.cache-hit != 'true' run: > @@ -268,11 +251,31 @@ jobs: -DGENERIC_CMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" -DBUILD_TYPE=Debug -DBUILD_GMOCK=ON + -DBUILD_SHARED_LIBS=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON && cmake --build build/googletest -j8 && cmake --install build/googletest + - name: Build mocks + run: > + cmake + -S "$GITHUB_WORKSPACE/entservices-testframework/Tests/mocks" + -B build/mocks + -DBUILD_SHARED_LIBS=ON + -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" + -DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/install/usr" + -DCMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake" + -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + -DCMAKE_CXX_FLAGS=" + -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers + -I $GITHUB_WORKSPACE/install/usr/include" + && + cmake --build build/mocks -j8 + && + cmake --install build/mocks + - name: Build entservices-inputoutput run: > cmake @@ -319,26 +322,7 @@ jobs: -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvSettingsExtODM.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvSettingsODM.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvTypes.h - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/videoOutputPortType.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/videoOutputPortConfig.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/videoResolution.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/sleepMode.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/frontPanelConfig.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/frontPanelTextDisplay.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/audioOutputPortType.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/frontPanelConfig.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/frontPanelTextDisplay.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/manager.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/audioOutputPortConfig.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/iarmbus/iarmUtil.h - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemaudioplatform.h - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/list.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/dsDisplay.h - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/AudioStereoMode.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/VideoDFC.hpp - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/dsRpc.h - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/dsError.h - -include $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds/dsUtl.h + -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/essos-resmgr.h -Werror -Wall -Wno-unused-result -Wno-deprecated-declarations -Wno-error=format= -DUSE_IARMBUS -DRDK_SERVICE_L2_TEST diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index 2550627b..acab058e 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -135,16 +135,6 @@ set_source_files_properties( tests/test_HdmiCecSink.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") -if (RDK_SERVICES_L1_TEST) - find_library(TESTMOCKLIB_LIBRARIES NAMES L1TestMocklib) - if (TESTMOCKLIB_LIBRARIES) - message ("Found mock libraries ${TESTMOCKLIB_LIBRARIES} library") - target_link_libraries(${MODULE_NAME} ${TESTMOCKLIB_LIBRARIES}) - else (TESTMOCKLIB_LIBRARIES) - message ("Require ${TESTMOCKLIB_LIBRARIES} library") - endif (TESTMOCKLIB_LIBRARIES) -endif (RDK_SERVICES_L1_TEST) - include_directories(${TEST_INC}) target_link_directories(${MODULE_NAME} PUBLIC ${CMAKE_INSTALL_PREFIX}/lib ${CMAKE_INSTALL_PREFIX}/lib/wpeframework/plugins) diff --git a/Tests/L1Tests/tests/test_HdcpProfile.cpp b/Tests/L1Tests/tests/test_HdcpProfile.cpp index bec5f9b9..c474adea 100755 --- a/Tests/L1Tests/tests/test_HdcpProfile.cpp +++ b/Tests/L1Tests/tests/test_HdcpProfile.cpp @@ -378,7 +378,6 @@ TEST_F(HDCPProfileDsTest, getSettopHDCPSupport_Hdcp_v2x) "\\}"))); } -#if 0 TEST_F(HDCPProfileEventIarmTest, onDisplayConnectionChanged) { @@ -449,7 +448,6 @@ TEST_F(HDCPProfileEventIarmTest, onDisplayConnectionChanged) EVENT_UNSUBSCRIBE(0, _T("onDisplayConnectionChanged"), _T("client.events"), message); } -#endif TEST_F(HDCPProfileEventIarmTest, onHdmiOutputHDCPStatusEvent) { ASSERT_TRUE(dsHdmiEventHandler != nullptr); From 10fc7fd85c9856b71ef105e79baff1ea13d99a4d Mon Sep 17 00:00:00 2001 From: tabbas651 <74683978+tabbas651@users.noreply.github.com> Date: Thu, 10 Jul 2025 12:46:22 -0400 Subject: [PATCH 26/52] RDKEMW-3750 : Upgrade Thunder to Version R4.4.3 (#133) * RDKEMW-3750 : Upgrade Thunder to Version R4.4.3 Reason for change: AddRef return type got changed in R4.4.3 , modified the changes in RustAdapter pligin Test Procedure: please referred ticket descriptions Risks: Medium Priority: P1 Signed-off-by: Thamim Razith * Removed the AddRef and release which not in use --------- Signed-off-by: Thamim Razith --- AVOutput/AVOutput.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/AVOutput/AVOutput.h b/AVOutput/AVOutput.h index fb260ada..13536705 100644 --- a/AVOutput/AVOutput.h +++ b/AVOutput/AVOutput.h @@ -60,8 +60,6 @@ namespace Plugin { const std::string Initialize(PluginHost::IShell* service); void Deinitialize(PluginHost::IShell* service); virtual string Information() const override { return {}; } - virtual void AddRef() const { } - virtual uint32_t Release() const {return 0; } BEGIN_INTERFACE_MAP(AVOutput) INTERFACE_ENTRY(PluginHost::IPlugin) INTERFACE_ENTRY(PluginHost::IDispatcher) From ced52871e5f60487165bf417af781f3f72e10bfa Mon Sep 17 00:00:00 2001 From: svemur170 Date: Thu, 10 Jul 2025 17:01:20 +0000 Subject: [PATCH 27/52] RDKEMW-3750 - Changelog updates for 1.3.3 Signed-off-by: svemur170 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d0c412b..7de554a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.3.3](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.2...1.3.3) + +- RDKEMW-3750 : Upgrade Thunder to Version R4.4.3 [`#133`](https://github.com/rdkcentral/entservices-inputoutput/pull/133) +- cmake cleanup [`#151`](https://github.com/rdkcentral/entservices-inputoutput/pull/151) +- RDK-42386 : Improve Unit Tests Coverage for AVInput Plugin [`#164`](https://github.com/rdkcentral/entservices-inputoutput/pull/164) +- Merge tag '1.3.2' into develop [`dab1c4a`](https://github.com/rdkcentral/entservices-inputoutput/commit/dab1c4ab82e2983b04d66bdb975a546a79efc47f) + #### [1.3.2](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.1...1.3.2) +> 1 July 2025 + - RDKEMW-5510: Integrate the ODM Phase 2 middleware changes into RDKE [`#160`](https://github.com/rdkcentral/entservices-inputoutput/pull/160) +- RDKEMW-5510 - Changelog updates for 1.3.2 [`a70cf9a`](https://github.com/rdkcentral/entservices-inputoutput/commit/a70cf9a4229cfcc4f468cdd49064708f8bfd65aa) - Merge tag '1.3.1' into develop [`8083548`](https://github.com/rdkcentral/entservices-inputoutput/commit/808354842ca703cbcd49d04ee6ceeca5911d1653) #### [1.3.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.0...1.3.1) From 9b9658482e2acbe4f27c72ba99abdb0106612b58 Mon Sep 17 00:00:00 2001 From: Yuvaramachandran Gurusamy <123441336+yuvaramachandran-gurusamy@users.noreply.github.com> Date: Wed, 23 Jul 2025 01:02:10 +0530 Subject: [PATCH 28/52] RDKEMW-6279: Revert of HdmiCecSink comrpc changes (#129) (#199) This reverts commit f4a230f1270113d9f1ca50abce58633d15c5b99b. Signed-off-by: yuvaramachandran_gurusamy --- .github/workflows/L1-tests.yml | 4 +- HdmiCecSink/CMakeLists.txt | 21 +- HdmiCecSink/HdmiCecSink.conf.in | 7 - HdmiCecSink/HdmiCecSink.config | 10 - HdmiCecSink/HdmiCecSink.cpp | 3535 +++++++++++++++- HdmiCecSink/HdmiCecSink.h | 886 +++- HdmiCecSink/HdmiCecSinkImplementation.cpp | 3581 ----------------- HdmiCecSink/HdmiCecSinkImplementation.h | 755 ---- HdmiCecSource/HdmiCecSourceImplementation.cpp | 6 +- HdmiCecSource/HdmiCecSourceImplementation.h | 4 +- Tests/L1Tests/CMakeLists.txt | 3 +- Tests/L1Tests/tests/test_HdmiCecSource.cpp | 2 +- 12 files changed, 4156 insertions(+), 4658 deletions(-) delete mode 100644 HdmiCecSink/HdmiCecSinkImplementation.cpp delete mode 100644 HdmiCecSink/HdmiCecSinkImplementation.h diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 209ff45f..6121092a 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -440,7 +440,7 @@ jobs: -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON - -DPLUGIN_HDMICECSINK=OFF + -DPLUGIN_HDMICECSINK=ON -DUSE_THUNDER_R4=ON -DHIDE_NON_EXTERNAL_SYMBOLS=OFF && @@ -518,7 +518,7 @@ jobs: -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON - -DPLUGIN_HDMICECSINK=OFF + -DPLUGIN_HDMICECSINK=ON -DRDK_SERVICES_L1_TEST=ON -DUSE_THUNDER_R4=ON -DHIDE_NON_EXTERNAL_SYMBOLS=OFF diff --git a/HdmiCecSink/CMakeLists.txt b/HdmiCecSink/CMakeLists.txt index 11e12e6f..b244641e 100644 --- a/HdmiCecSink/CMakeLists.txt +++ b/HdmiCecSink/CMakeLists.txt @@ -16,7 +16,6 @@ # limitations under the License. set(PLUGIN_NAME HdmiCecSink) set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) -set(PLUGIN_IMPLEMENTATION ${MODULE_NAME}Implementation) set(PLUGIN_HDMICECSINK_STARTUPORDER "" CACHE STRING "To configure startup order of HdmiCecSink plugin") @@ -27,18 +26,10 @@ add_library(${MODULE_NAME} SHARED HdmiCecSink.cpp Module.cpp) -add_library(${PLUGIN_IMPLEMENTATION} SHARED - HdmiCecSinkImplementation.cpp - Module.cpp) - set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES) -set_target_properties(${PLUGIN_IMPLEMENTATION} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES) - target_compile_definitions(${MODULE_NAME} PRIVATE MODULE_NAME=Plugin_${PLUGIN_NAME}) find_package(DS) @@ -50,23 +41,13 @@ target_include_directories(${MODULE_NAME} PRIVATE ${CEC_INCLUDE_DIRS}) target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) set_source_files_properties(HdmiCecSink.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") - -target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) -target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${CEC_INCLUDE_DIRS}) -target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${DS_INCLUDE_DIRS}) -set_source_files_properties(HdmiCecSinkImplementation.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") - target_link_libraries(${MODULE_NAME} PUBLIC ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${CEC_LIBRARIES} ${DS_LIBRARIES} ) -target_link_libraries(${PLUGIN_IMPLEMENTATION} PUBLIC ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${CEC_LIBRARIES} ${DS_LIBRARIES} ) if (NOT RDK_SERVICES_L1_TEST) - target_compile_options(${PLUGIN_IMPLEMENTATION} PRIVATE -Wno-error=deprecated) + target_compile_options(${MODULE_NAME} PRIVATE -Wno-error=deprecated) endif () install(TARGETS ${MODULE_NAME} DESTINATION lib/${STORAGE_DIRECTORY}/plugins) -install(TARGETS ${PLUGIN_IMPLEMENTATION} - DESTINATION lib/${STORAGE_DIRECTORY}/plugins) - write_config(${PLUGIN_NAME}) diff --git a/HdmiCecSink/HdmiCecSink.conf.in b/HdmiCecSink/HdmiCecSink.conf.in index 646c4430..de8e1cdf 100644 --- a/HdmiCecSink/HdmiCecSink.conf.in +++ b/HdmiCecSink/HdmiCecSink.conf.in @@ -2,10 +2,3 @@ precondition = ["Platform"] callsign = "org.rdk.HdmiCecSink" autostart = "false" startuporder = "@PLUGIN_HDMICECSINK_STARTUPORDER@" - -configuration = JSON() -rootobject = JSON() - -rootobject.add("mode", "@PLUGIN_HDMICECSINK_MODE@") -rootobject.add("locator", "lib@PLUGIN_IMPLEMENTATION@.so") -configuration.add("root", rootobject) \ No newline at end of file diff --git a/HdmiCecSink/HdmiCecSink.config b/HdmiCecSink/HdmiCecSink.config index 7257c9e8..13ed0788 100644 --- a/HdmiCecSink/HdmiCecSink.config +++ b/HdmiCecSink/HdmiCecSink.config @@ -5,13 +5,3 @@ set (callsign "org.rdk.HdmiCecSink") if(PLUGIN_HDMICECSINK_STARTUPORDER) set (startuporder ${PLUGIN_HDMICECSINK_STARTUPORDER}) endif() - - -map() - key(root) - map() - kv(mode ${PLUGIN_HDMICECSOURCE_MODE}) - kv(locator lib${PLUGIN_IMPLEMENTATION}.so) - end() -end() -ans(configuration) diff --git a/HdmiCecSink/HdmiCecSink.cpp b/HdmiCecSink/HdmiCecSink.cpp index a7e08588..b5150cf8 100644 --- a/HdmiCecSink/HdmiCecSink.cpp +++ b/HdmiCecSink/HdmiCecSink.cpp @@ -19,14 +19,159 @@ #include "HdmiCecSink.h" +#include "ccec/Connection.hpp" +#include "ccec/CECFrame.hpp" +#include "ccec/MessageEncoder.hpp" +#include "host.hpp" +#include "UtilsgetRFCConfig.h" + +#include "dsMgr.h" +#include "dsRpc.h" +#include "dsDisplay.h" +#include "videoOutputPort.hpp" +#include "manager.hpp" +#include "websocket/URL.h" + #include "UtilsIarm.h" #include "UtilsJsonRpc.h" #include "UtilssyncPersistFile.h" #include "UtilsSearchRDKProfile.h" +#define HDMICECSINK_METHOD_SET_ENABLED "setEnabled" +#define HDMICECSINK_METHOD_GET_ENABLED "getEnabled" +#define HDMICECSINK_METHOD_OTP_SET_ENABLED "setOTPEnabled" +#define HDMICECSINK_METHOD_OTP_GET_ENABLED "getOTPEnabled" +#define HDMICECSINK_METHOD_SET_OSD_NAME "setOSDName" +#define HDMICECSINK_METHOD_GET_OSD_NAME "getOSDName" +#define HDMICECSINK_METHOD_SET_VENDOR_ID "setVendorId" +#define HDMICECSINK_METHOD_GET_VENDOR_ID "getVendorId" +#define HDMICECSINK_METHOD_PRINT_DEVICE_LIST "printDeviceList" +#define HDMICECSINK_METHOD_SET_ACTIVE_PATH "setActivePath" +#define HDMICECSINK_METHOD_SET_ROUTING_CHANGE "setRoutingChange" +#define HDMICECSINK_METHOD_GET_DEVICE_LIST "getDeviceList" +#define HDMICECSINK_METHOD_GET_ACTIVE_SOURCE "getActiveSource" +#define HDMICECSINK_METHOD_SET_ACTIVE_SOURCE "setActiveSource" +#define HDMICECSINK_METHOD_GET_ACTIVE_ROUTE "getActiveRoute" +#define HDMICECSINK_METHOD_SET_MENU_LANGUAGE "setMenuLanguage" +#define HDMICECSINK_METHOD_REQUEST_ACTIVE_SOURCE "requestActiveSource" +#define HDMICECSINK_METHOD_SETUP_ARC "setupARCRouting" +#define HDMICECSINK_METHOD_REQUEST_SHORT_AUDIO_DESCRIPTOR "requestShortAudioDescriptor" +#define HDMICECSINK_METHOD_SEND_STANDBY_MESSAGE "sendStandbyMessage" +#define HDMICECSINK_METHOD_SEND_AUDIO_DEVICE_POWER_ON "sendAudioDevicePowerOnMessage" +#define HDMICECSINK_METHOD_SEND_KEY_PRESS "sendKeyPressEvent" +#define HDMICECSINK_METHOD_SEND_USER_CONTROL_PRESSED "sendUserControlPressed" +#define HDMICECSINK_METHOD_SEND_USER_CONTROL_RELEASED "sendUserControlReleased" +#define HDMICECSINK_METHOD_SEND_GIVE_AUDIO_STATUS "sendGetAudioStatusMessage" +#define HDMICECSINK_METHOD_GET_AUDIO_DEVICE_CONNECTED_STATUS "getAudioDeviceConnectedStatus" +#define HDMICECSINK_METHOD_REQUEST_AUDIO_DEVICE_POWER_STATUS "requestAudioDevicePowerStatus" +#define HDMICECSINK_METHOD_SET_LATENCY_INFO "setLatencyInfo" + +#define TEST_ADD 0 +#define HDMICECSINK_REQUEST_MAX_RETRY 3 +#define HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS 2000 +#define HDMICECSINK_PING_INTERVAL_MS 10000 +#define HDMICECSINK_WAIT_FOR_HDMI_IN_MS 1000 +#define HDMICECSINK_REQUEST_INTERVAL_TIME_MS 500 +#define HDMICECSINK_NUMBER_TV_ADDR 2 +#define HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS (60 * 1000) +#define HDMISINK_ARC_START_STOP_MAX_WAIT_MS 4000 +#define HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS 500 + + +#define SAD_FMT_CODE_AC3 2 +#define SAD_FMT_CODE_ENHANCED_AC3 10 + +#define SYSTEM_AUDIO_MODE_ON 0x01 +#define SYSTEM_AUDIO_MODE_OFF 0x00 +#define AUDIO_DEVICE_POWERSTATE_OFF 1 + +#define DEFAULT_VIDEO_LATENCY 100 +#define DEFAULT_LATENCY_FLAGS 3 +#define DEFAULT_AUDIO_OUTPUT_DELAY 100 + +//Device Type is TV - Bit 7 is set to 1 +#define ALL_DEVICE_TYPES 128 + +//RC Profile of TV is 3 - Typical TV Remote +#define RC_PROFILE_TV 10 + +//Device Features supported by TV - ARC Tx +#define DEVICE_FEATURES_TV 4 #define TR181_HDMICECSINK_CEC_VERSION "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.HdmiCecSink.CECVersion" +enum { + DEVICE_POWER_STATE_ON = 0, + DEVICE_POWER_STATE_OFF = 1 +}; + + +enum { + HDMICECSINK_EVENT_ACTIVE_SOURCE_CHANGE = 1, + HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY, + HDMICECSINK_EVENT_TEXT_VIEW_ON_MSG, + HDMICECSINK_EVENT_IMAGE_VIEW_ON_MSG, + HDMICECSINK_EVENT_DEVICE_ADDED, + HDMICECSINK_EVENT_DEVICE_REMOVED, + HDMICECSINK_EVENT_DEVICE_INFO_UPDATED, + HDMICECSINK_EVENT_INACTIVE_SOURCE, + HDMICECSINK_EVENT_ARC_INITIATION_EVENT, + HDMICECSINK_EVENT_ARC_TERMINATION_EVENT, + HDMICECSINK_EVENT_SHORT_AUDIODESCRIPTOR_EVENT, + HDMICECSINK_EVENT_STANDBY_MSG_EVENT, + HDMICECSINK_EVENT_SYSTEM_AUDIO_MODE, + HDMICECSINK_EVENT_REPORT_AUDIO_STATUS, + HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS, + HDMICECSINK_EVENT_CEC_ENABLED, + HDMICECSINK_EVENT_AUDIO_DEVICE_POWER_STATUS, + HDMICECSINK_EVENT_FEATURE_ABORT_EVENT, +}; + +static const char *eventString[] = { + "None", + "onActiveSourceChange", + "onWakeupFromStandby", + "onTextViewOnMsg", + "onImageViewOnMsg", + "onDeviceAdded", + "onDeviceRemoved", + "onDeviceInfoUpdated", + "onInActiveSource", + "arcInitiationEvent", + "arcTerminationEvent", + "shortAudiodesciptorEvent", + "standbyMessageReceived", + "setSystemAudioModeEvent", + "reportAudioStatusEvent", + "reportAudioDeviceConnectedStatus", + "reportCecEnabledEvent", + "reportAudioDevicePowerStatus", + "reportFeatureAbortEvent" +}; + + +#define CEC_SETTING_ENABLED_FILE "/opt/persistent/ds/cecData_2.json" +#define CEC_SETTING_OTP_ENABLED "cecOTPEnabled" +#define CEC_SETTING_ENABLED "cecEnabled" +#define CEC_SETTING_OSD_NAME "cecOSDName" +#define CEC_SETTING_VENDOR_ID "cecVendorId" + +static std::vector defaultVendorId = {0x00,0x19,0xFB}; +static VendorID appVendorId = {defaultVendorId.at(0),defaultVendorId.at(1),defaultVendorId.at(2)}; +static VendorID lgVendorId = {0x00,0xE0,0x91}; +static PhysicalAddress physical_addr = {0x0F,0x0F,0x0F,0x0F}; +static LogicalAddress logicalAddress = 0xF; +static Language defaultLanguage = "eng"; +static OSDName osdName = "TV Box"; +static int32_t powerState = DEVICE_POWER_STATE_OFF; +static std::vector formatid = {0,0}; +static std::vector audioFormatCode = { SAD_FMT_CODE_ENHANCED_AC3,SAD_FMT_CODE_AC3 }; +static uint8_t numberofdescriptor = 2; +static int32_t HdmiArcPortID = -1; +static float cecVersion = 1.4; +static AllDeviceTypes allDevicetype = ALL_DEVICE_TYPES; +static std::vector rcProfile = {RC_PROFILE_TV}; +static std::vector deviceFeatures = {DEVICE_FEATURES_TV}; #define API_VERSION_NUMBER_MAJOR 1 #define API_VERSION_NUMBER_MINOR 3 @@ -34,7 +179,7 @@ namespace WPEFramework { - namespace { + namespace { static Plugin::Metadata metadata( // Version (Major, Minor, Patch) @@ -50,119 +195,3365 @@ namespace WPEFramework namespace Plugin { - SERVICE_REGISTRATION(HdmiCecSink, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + SERVICE_REGISTRATION(HdmiCecSink, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + + HdmiCecSink* HdmiCecSink::_instance = nullptr; + static int libcecInitStatus = 0; + +//=========================================== HdmiCecSinkFrameListener ========================================= + void HdmiCecSinkFrameListener::notify(const CECFrame &in) const { + const uint8_t *buf = NULL; + char strBuffer[512] = {0}; + size_t len = 0; + + in.getBuffer(&buf, &len); + for (unsigned int i = 0; i < len; i++) { + snprintf(strBuffer + (i*3) , sizeof(strBuffer) - (i*3), "%02X ",(uint8_t) *(buf + i)); + } + LOGINFO(" >>>>> Received CEC Frame: :%s \n",strBuffer); + + MessageDecoder(processor).decode(in); + } + +//=========================================== HdmiCecSinkProcessor ========================================= + void HdmiCecSinkProcessor::process (const ActiveSource &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + HdmiCecSink::_instance->addDevice(header.from.toInt()); + HdmiCecSink::_instance->updateActiveSource(header.from.toInt(), msg); + } + void HdmiCecSinkProcessor::process (const InActiveSource &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: InActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + + HdmiCecSink::_instance->updateInActiveSource(header.from.toInt(), msg); + } + + void HdmiCecSinkProcessor::process (const ImageViewOn &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ImageViewOn from %s\n", header.from.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSink::_instance->addDevice(header.from.toInt()); + HdmiCecSink::_instance->updateImageViewOn(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const TextViewOn &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: TextViewOn\n"); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSink::_instance->addDevice(header.from.toInt()); + HdmiCecSink::_instance->updateTextViewOn(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const RequestActiveSource &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RequestActiveSource\n"); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + + HdmiCecSink::_instance->setActiveSource(true); + } + void HdmiCecSinkProcessor::process (const Standby &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Standby from %s\n", header.from.toString().c_str()); + HdmiCecSink::_instance->SendStandbyMsgEvent(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const GetCECVersion &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GetCECVersion sending CECVersion response \n"); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + if(cecVersion == 2.0) { + conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_2_0))); + } + else{ + conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_1_4))); + } + } + catch(...) + { + LOGWARN("Exception while sending CECVersion "); + } + } + void HdmiCecSinkProcessor::process (const CECVersion &msg, const Header &header) + { + bool updateStatus; + printHeader(header); + LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); + + HdmiCecSink::_instance->addDevice(header.from.toInt()); + updateStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isVersionUpdated; + LOGINFO("updateStatus %d\n",updateStatus); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.version); + if(!updateStatus) + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const SetMenuLanguage &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const GiveOSDName &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveOSDName sending SetOSDName : %s\n",osdName.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + conn.sendToAsync(header.from, MessageEncoder().encode(SetOSDName(osdName))); + } + catch(...) + { + LOGWARN("Exception while sending SetOSDName"); + } + } + void HdmiCecSinkProcessor::process (const GivePhysicalAddress &msg, const Header &header) + { + LOGINFO("Command: GivePhysicalAddress\n"); + if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) + { + try + { + LOGINFO(" sending ReportPhysicalAddress response physical_addr :%s logicalAddress :%x \n",physical_addr.toString().c_str(), logicalAddress.toInt()); + conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ReportPhysicalAddress(physical_addr,logicalAddress.toInt())), 500); + } + catch(...) + { + LOGWARN("Exception while sending ReportPhysicalAddress "); + } + } + } + void HdmiCecSinkProcessor::process (const GiveDeviceVendorID &msg, const Header &header) + { + printHeader(header); + if(header.to == LogicalAddress(LogicalAddress::BROADCAST)){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n",appVendorId.toString().c_str()); + conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); + } + catch(...) + { + LOGWARN("Exception while sending DeviceVendorID"); + } + + } + void HdmiCecSinkProcessor::process (const SetOSDString &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetOSDString OSDString : %s\n",msg.osdString.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const SetOSDName &msg, const Header &header) + { + printHeader(header); + bool updateStatus ; + LOGINFO("Command: SetOSDName OSDName : %s\n",msg.osdName.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + + HdmiCecSink::_instance->addDevice(header.from.toInt()); + updateStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isOSDNameUpdated; + LOGINFO("updateStatus %d\n",updateStatus); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.osdName); + if(HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_OSD_NAME) { + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; + } + if(!updateStatus) + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const RoutingChange &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RoutingChange From : %s To: %s \n",msg.from.toString().c_str(),msg.to.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const RoutingInformation &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RoutingInformation Routing Information to Sink : %s\n",msg.toSink.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const SetStreamPath &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetStreamPath Set Stream Path to Sink : %s\n",msg.toSink.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const GetMenuLanguage &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GetMenuLanguage\n"); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSink::_instance->sendMenuLanguage(); + } + void HdmiCecSinkProcessor::process (const ReportPhysicalAddress &msg, const Header &header) + { + printHeader(header); + bool updateDeviceTypeStatus; + bool updatePAStatus; + LOGINFO("Command: ReportPhysicalAddress\n"); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + + if(!HdmiCecSink::_instance) + return; + HdmiCecSink::_instance->addDevice(header.from.toInt()); + updateDeviceTypeStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isDeviceTypeUpdated; + updatePAStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isPAUpdated; + LOGINFO("updateDeviceTypeStatus %d updatePAStatus %d \n",updateDeviceTypeStatus,updatePAStatus); + if(HdmiCecSink::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString() != msg.physicalAddress.toString() && updatePAStatus){ + updatePAStatus= false; + LOGINFO("There is a change in physical address from current PA %s to newly reported PA %s\n",HdmiCecSink::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString().c_str(),msg.physicalAddress.toString().c_str()); + } + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.physicalAddress); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.deviceType); + if(HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_PHISICAL_ADDRESS) { + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; + } + HdmiCecSink::_instance->updateDeviceChain(header.from, msg.physicalAddress); + if (!updateDeviceTypeStatus || !updatePAStatus) + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const DeviceVendorID &msg, const Header &header) + { + bool updateStatus ; + printHeader(header); + LOGINFO("Command: DeviceVendorID VendorID : %s\n",msg.vendorId.toString().c_str()); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + + HdmiCecSink::_instance->addDevice(header.from.toInt()); + updateStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isVendorIDUpdated; + LOGINFO("updateStatus %d\n",updateStatus); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.vendorId); + if (!updateStatus) + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const GiveDevicePowerStatus &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveDevicePowerStatus sending powerState :%d \n",powerState); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + conn.sendTo(header.from, MessageEncoder().encode(ReportPowerStatus(PowerStatus(powerState)))); + } + catch(...) + { + LOGWARN("Exception while sending ReportPowerStatus"); + } + } + void HdmiCecSinkProcessor::process (const ReportPowerStatus &msg, const Header &header) + { + uint32_t oldPowerStatus,newPowerStatus; + printHeader(header); + LOGINFO("Command: ReportPowerStatus Power Status from:%s status : %s \n",header.from.toString().c_str(),msg.status.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + oldPowerStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); + HdmiCecSink::_instance->addDevice(header.from.toInt()); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.status); + newPowerStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); + LOGINFO(" oldPowerStatus %d newpower status %d \n",oldPowerStatus,newPowerStatus); + if ((oldPowerStatus != newPowerStatus) ) + { + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + + if((header.from.toInt() == LogicalAddress::AUDIO_SYSTEM) && (HdmiCecSink::_instance->m_audioDevicePowerStatusRequested)) { + HdmiCecSink::_instance->reportAudioDevicePowerStatusInfo(header.from.toInt(), newPowerStatus); + } + + } + void HdmiCecSinkProcessor::process (const FeatureAbort &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: FeatureAbort opcode=%s, Reason = %s\n", msg.feature.toString().c_str(), msg.reason.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + + if(header.from.toInt() < LogicalAddress::UNREGISTERED && + msg.reason.toInt() == AbortReason::UNRECOGNIZED_OPCODE) + { + switch(msg.feature.opCode()) + { + case GET_CEC_VERSION : + { + /* If we get a Feature abort for CEC Version then default to 1.4b */ + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(Version(Version::V_1_4)); + } + break; + case GIVE_DEVICE_VENDOR_ID : + { + /* If we get a Feature abort for CEC Version then default to 1.4b */ + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(VendorID((uint8_t *)"FA", 2)); + } + break; + + case GIVE_OSD_NAME : + { + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(OSDName("")); + } + break; + + case GIVE_DEVICE_POWER_STATUS : + { + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(PowerStatus(PowerStatus::POWER_STATUS_FEATURE_ABORT)); + } + break; + } + + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_featureAborts.push_back(msg); + } + + LogicalAddress logicaladdress = header.from.toInt(); + OpCode featureOpcode = msg.feature; + AbortReason abortReason = msg.reason; + + HdmiCecSink::_instance->reportFeatureAbortEvent(logicaladdress,featureOpcode,abortReason); + + if(msg.feature.opCode() == REQUEST_SHORT_AUDIO_DESCRIPTOR) + { + JsonArray audiodescriptor; + audiodescriptor.Add(0); + HdmiCecSink::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); + } + + } + void HdmiCecSinkProcessor::process (const Abort &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Abort\n"); + if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) + { + AbortReason reason = AbortReason::UNRECOGNIZED_OPCODE; + LogicalAddress logicaladdress =header.from.toInt(); + OpCode feature = msg.opCode(); + HdmiCecSink::_instance->sendFeatureAbort(logicaladdress, feature,reason); + } + else + { + LOGINFO("Command: Abort broadcast msg so ignore\n"); + } + } + void HdmiCecSinkProcessor::process (const Polling &msg, const Header &header) { + printHeader(header); + LOGINFO("Command: Polling\n"); + } + + void HdmiCecSinkProcessor::process (const InitiateArc &msg, const Header &header) + { + printHeader(header); + if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ + LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); + return; + } + PhysicalAddress physical_addr_invalid = {0x0F,0x0F,0x0F,0x0F}; + PhysicalAddress physical_addr_arc_port = {0x0F,0x0F,0x0F,0x0F}; + + LOGINFO("Command: INITIATE_ARC \n"); + if(!HdmiCecSink::_instance || HdmiArcPortID == -1) + return; + + if (HdmiArcPortID == 0 ) + physical_addr_arc_port = {0x01,0x00,0x00,0x00}; + if (HdmiArcPortID == 1 ) + physical_addr_arc_port = {0x02,0x00,0x00,0x00}; + if (HdmiArcPortID == 2 ) + physical_addr_arc_port = {0x03,0x00,0x00,0x00}; + + if( (HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_arc_port.toString()) || (HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_invalid.toString()) ) { + LOGINFO("Command: INITIATE_ARC InitiateArc success %s \n",HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); + HdmiCecSink::_instance->Process_InitiateArc(); + } else { + LOGINFO("Command: INITIATE_ARC InitiateArc ignore %s \n",HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); + } + } + void HdmiCecSinkProcessor::process (const TerminateArc &msg, const Header &header) + { + printHeader(header); + if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ + LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); + return; + } + if(!HdmiCecSink::_instance) + return; + HdmiCecSink::_instance->Process_TerminateArc(); + } + void HdmiCecSinkProcessor::process (const ReportShortAudioDescriptor &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ReportShortAudioDescriptor %s : %d \n",GetOpName(msg.opCode()),numberofdescriptor); + HdmiCecSink::_instance->Process_ShortAudioDescriptor_msg(msg); + } + + void HdmiCecSinkProcessor::process (const SetSystemAudioMode &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetSystemAudioMode %s audio status %d audio status is %s \n",GetOpName(msg.opCode()),msg.status.toInt(),msg.status.toString().c_str()); + HdmiCecSink::_instance->Process_SetSystemAudioMode_msg(msg); + } + void HdmiCecSinkProcessor::process (const ReportAudioStatus &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSink::_instance->Process_ReportAudioStatus_msg(msg); + } + void HdmiCecSinkProcessor::process (const GiveFeatures &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveFeatures \n"); + try + { + if(cecVersion == 2.0) { + conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST),MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures))); + } + } + catch(...) + { + LOGWARN("Exception while sending ReportFeatures"); + } + } + void HdmiCecSinkProcessor::process (const RequestCurrentLatency &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Request Current Latency :%s, physical address: %s",GetOpName(msg.opCode()),msg.physicaladdress.toString().c_str()); + + if(msg.physicaladdress.toString() == physical_addr.toString()) { + HdmiCecSink::_instance->setLatencyInfo(); + } + else { + LOGINFO("Physical Address does not match with TV's physical address"); + return; + } + } +//=========================================== HdmiCecSink ========================================= + + HdmiCecSink::HdmiCecSink() + : PluginHost::JSONRPC() + , _pwrMgrNotification(*this) + , _registeredEventHandlers(false) + { + LOGWARN("Initlaizing HdmiCecSink"); + } + HdmiCecSink::~HdmiCecSink() + { + } const std::string HdmiCecSink::Initialize(PluginHost::IShell *service) { - profileType = searchRdkProfile(); + InitializePowerManager(service); + profileType = searchRdkProfile(); + + if (profileType == STB || profileType == NOT_FOUND) + { + LOGINFO("Invalid profile type for TV \n"); + return (std::string("Not supported")); + } + + HdmiCecSink::_instance = this; + smConnection=NULL; + cecEnableStatus = false; + HdmiCecSink::_instance->m_numberOfDevices = 0; + m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; + m_currentActiveSource = -1; + m_isHdmiInConnected = false; + hdmiCecAudioDeviceConnected = false; + m_isAudioStatusInfoUpdated = false; + m_audioStatusReceived = false; + m_audioStatusTimerStarted = false; + m_audioDevicePowerStatusRequested = false; + m_pollNextState = POLL_THREAD_STATE_NONE; + m_pollThreadState = POLL_THREAD_STATE_NONE; + m_video_latency = DEFAULT_VIDEO_LATENCY; + m_latency_flags = DEFAULT_LATENCY_FLAGS ; + m_audio_output_delay = DEFAULT_AUDIO_OUTPUT_DELAY; + + Register(HDMICECSINK_METHOD_SET_ENABLED, &HdmiCecSink::setEnabledWrapper, this); + Register(HDMICECSINK_METHOD_GET_ENABLED, &HdmiCecSink::getEnabledWrapper, this); + Register(HDMICECSINK_METHOD_SET_OSD_NAME, &HdmiCecSink::setOSDNameWrapper, this); + Register(HDMICECSINK_METHOD_GET_OSD_NAME, &HdmiCecSink::getOSDNameWrapper, this); + Register(HDMICECSINK_METHOD_SET_VENDOR_ID, &HdmiCecSink::setVendorIdWrapper, this); + Register(HDMICECSINK_METHOD_GET_VENDOR_ID, &HdmiCecSink::getVendorIdWrapper, this); + Register(HDMICECSINK_METHOD_PRINT_DEVICE_LIST, &HdmiCecSink::printDeviceListWrapper, this); + Register(HDMICECSINK_METHOD_SET_ACTIVE_PATH, &HdmiCecSink::setActivePathWrapper, this); + Register(HDMICECSINK_METHOD_SET_ROUTING_CHANGE, &HdmiCecSink::setRoutingChangeWrapper, this); + Register(HDMICECSINK_METHOD_GET_DEVICE_LIST, &HdmiCecSink::getDeviceListWrapper, this); + Register(HDMICECSINK_METHOD_GET_ACTIVE_SOURCE, &HdmiCecSink::getActiveSourceWrapper, this); + Register(HDMICECSINK_METHOD_SET_ACTIVE_SOURCE, &HdmiCecSink::setActiveSourceWrapper, this); + Register(HDMICECSINK_METHOD_GET_ACTIVE_ROUTE, &HdmiCecSink::getActiveRouteWrapper, this); + Register(HDMICECSINK_METHOD_REQUEST_ACTIVE_SOURCE, &HdmiCecSink::requestActiveSourceWrapper, this); + Register(HDMICECSINK_METHOD_SETUP_ARC, &HdmiCecSink::setArcEnableDisableWrapper, this); + Register(HDMICECSINK_METHOD_SET_MENU_LANGUAGE, &HdmiCecSink::setMenuLanguageWrapper, this); + Register(HDMICECSINK_METHOD_REQUEST_SHORT_AUDIO_DESCRIPTOR, &HdmiCecSink::requestShortAudioDescriptorWrapper, this); + Register(HDMICECSINK_METHOD_SEND_STANDBY_MESSAGE, &HdmiCecSink::sendStandbyMessageWrapper, this); + Register(HDMICECSINK_METHOD_SEND_AUDIO_DEVICE_POWER_ON, &HdmiCecSink::sendAudioDevicePowerOnMsgWrapper, this); + Register(HDMICECSINK_METHOD_SEND_KEY_PRESS,&HdmiCecSink::sendRemoteKeyPressWrapper,this); + Register(HDMICECSINK_METHOD_SEND_USER_CONTROL_PRESSED,&HdmiCecSink::sendUserControlPressedWrapper,this); + Register(HDMICECSINK_METHOD_SEND_USER_CONTROL_RELEASED,&HdmiCecSink::sendUserControlReleasedWrapper,this); + Register(HDMICECSINK_METHOD_SEND_GIVE_AUDIO_STATUS,&HdmiCecSink::sendGiveAudioStatusWrapper,this); + Register(HDMICECSINK_METHOD_GET_AUDIO_DEVICE_CONNECTED_STATUS,&HdmiCecSink::getAudioDeviceConnectedStatusWrapper,this); + Register(HDMICECSINK_METHOD_REQUEST_AUDIO_DEVICE_POWER_STATUS,&HdmiCecSink::requestAudioDevicePowerStatusWrapper,this); + Register(HDMICECSINK_METHOD_SET_LATENCY_INFO, &HdmiCecSink::setLatencyInfoWrapper, this); + logicalAddressDeviceType = "None"; + logicalAddress = 0xFF; + // load persistence setting + loadSettings(); + + int err; + dsHdmiInGetNumberOfInputsParam_t hdmiInput; + InitializeIARM(); + m_sendKeyEventThreadExit = false; + m_sendKeyEventThread = std::thread(threadSendKeyEvent); + + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + m_semSignaltoArcRoutingThread.acquire(); + m_arcRoutingThread = std::thread(threadArcRouting); + + m_audioStatusDetectionTimer.connect( std::bind( &HdmiCecSink::audioStatusTimerFunction, this ) ); + m_audioStatusDetectionTimer.setSingleShot(true); + m_arcStartStopTimer.connect( std::bind( &HdmiCecSink::arcStartStopTimerFunction, this ) ); + m_arcStartStopTimer.setSingleShot(true); + // get power state: + Core::hresult res = Core::ERROR_GENERAL; + PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + + ASSERT (_powerManagerPlugin); + if (_powerManagerPlugin) { + res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); + if (Core::ERROR_NONE == res) { + powerState = (pwrStateCur == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) ? DEVICE_POWER_STATE_ON : DEVICE_POWER_STATE_OFF; + LOGINFO("Current state is PowerManagerPlugin: (%d) powerState :%d \n", pwrStateCur, powerState); + } + } + + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + IARM_BUS_DSMGR_API_dsHdmiInGetNumberOfInputs, + (void *)&hdmiInput, + sizeof(hdmiInput)); - if (profileType == STB || profileType == NOT_FOUND) + if (err == IARM_RESULT_SUCCESS && hdmiInput.result == dsERR_NONE) { - LOGINFO("Invalid profile type for TV \n"); - return (std::string("Not supported")); + LOGINFO("Number of Inputs [%d] \n", hdmiInput.numHdmiInputs ); + m_numofHdmiInput = hdmiInput.numHdmiInputs; + }else{ + LOGINFO("Not able to get Numebr of inputs so defaulting to 3 \n"); + m_numofHdmiInput = 3; + } + + LOGINFO("initalize inputs \n"); + + for (int i = 0; i < m_numofHdmiInput; i++){ + HdmiPortMap hdmiPort((uint8_t)i); + LOGINFO(" Add to vector [%d] \n", i); + hdmiInputs.push_back(hdmiPort); + } + + LOGINFO("Check the HDMI State \n"); + + CheckHdmiInState(); + if (cecSettingEnabled) + { + try + { + CECEnable(); + } + catch(...) + { + LOGWARN("Exception while enabling CEC settings .\r\n"); + } + } + getCecVersion(); + LOGINFO(" HdmiCecSink plugin Initialize completed \n"); + return (std::string()); + + } + + void HdmiCecSink::Deinitialize(PluginHost::IShell* /* service */) + { + if(_powerManagerPlugin) + { + _powerManagerPlugin->Unregister(_pwrMgrNotification.baseInterface()); + _powerManagerPlugin.Reset(); + } + _registeredEventHandlers = false; + + profileType = searchRdkProfile(); + + if (profileType == STB || profileType == NOT_FOUND) + { + LOGINFO("Invalid profile type for TV \n"); + return ; + } + + CECDisable(); + m_currentArcRoutingState = ARC_STATE_ARC_EXIT; + + m_semSignaltoArcRoutingThread.release(); + + try + { + if (m_arcRoutingThread.joinable()) + m_arcRoutingThread.join(); + } + catch(const std::system_error& e) + { + LOGERR("system_error exception in thread join %s", e.what()); + } + catch(const std::exception& e) + { + LOGERR("exception in thread join %s", e.what()); + } + + { + m_sendKeyEventThreadExit = true; + std::unique_lock lk(m_sendKeyEventMutex); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + } + + try + { + if (m_sendKeyEventThread.joinable()) + m_sendKeyEventThread.join(); + } + catch(const std::system_error& e) + { + LOGERR("system_error exception in thread join %s", e.what()); + } + catch(const std::exception& e) + { + LOGERR("exception in thread join %s", e.what()); + } + + HdmiCecSink::_instance = nullptr; + DeinitializeIARM(); + LOGWARN(" HdmiCecSink Deinitialize() Done"); + } + + const void HdmiCecSink::InitializeIARM() + { + if (Utils::IARM::init()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); } + } + + void HdmiCecSink::DeinitializeIARM() + { + if (Utils::IARM::isConnected()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); + } + } + + void HdmiCecSink::InitializePowerManager(PluginHost::IShell *service) + { + _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) + .withIShell(service) + .withRetryIntervalMS(200) + .withRetryCount(25) + .createInterface(); + registerEventHandlers(); + } + void HdmiCecSink::registerEventHandlers() + { + ASSERT (_powerManagerPlugin); - string msg = ""; + if(!_registeredEventHandlers && _powerManagerPlugin) { + _registeredEventHandlers = true; + _powerManagerPlugin->Register(_pwrMgrNotification.baseInterface()); + } + } - ASSERT(nullptr != service); - ASSERT(nullptr == _service); - ASSERT(nullptr == _hdmiCecSink); - ASSERT(0 == _connectionId); + void HdmiCecSink::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + if(!HdmiCecSink::_instance) + return; + if (IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + bool isHdmiConnected = eventData->data.hdmi_in_connect.isPortConnected; + dsHdmiInPort_t portId = eventData->data.hdmi_in_connect.port; + LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG event port: %d data:%d \r\n",portId, isHdmiConnected); + HdmiCecSink::_instance->onHdmiHotPlug(portId,isHdmiConnected); + } + } - _service = service; - _service->AddRef(); - _service->Register(&_notification); - _hdmiCecSink = _service->Root(_connectionId, 5000, _T("HdmiCecSinkImplementation")); + void HdmiCecSink::onPowerModeChanged(const PowerState currentState, const PowerState newState) + { + if(!HdmiCecSink::_instance) + return; - if(nullptr != _hdmiCecSink) + LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", + currentState, newState); + LOGWARN(" m_logicalAddressAllocated 0x%x CEC enable status %d \n",_instance->m_logicalAddressAllocated,_instance->cecEnableStatus); + if(newState == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) { - _hdmiCecSink->Configure(service); - _hdmiCecSink->Register(&_notification); - Exchange::JHdmiCecSink::Register(*this, _hdmiCecSink); - LOGINFO("HdmiCecSink plugin is available. Successfully activated HdmiCecSink Plugin"); + powerState = DEVICE_POWER_STATE_ON; } else { - msg = "HdmiCecSink plugin is not available"; - LOGINFO("HdmiCecSink plugin is not available. Failed to activate HdmiCecSink Plugin"); + powerState = DEVICE_POWER_STATE_OFF; + if((_instance->m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_INITIATION) || (_instance->m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) + { + LOGINFO("%s: Stop ARC \n",__FUNCTION__); + _instance->stopArc(); } - if (0 != msg.length()) + } + if (_instance->cecEnableStatus) + { + if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED ) + { + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); + + if ( powerState != DEVICE_POWER_STATE_ON ) + { + /* reset the current active source when TV on going to standby */ + HdmiCecSink::_instance->m_currentActiveSource = -1; + } + /* Initiate a ping straight away */ + HdmiCecSink::_instance->m_pollNextState = POLL_THREAD_STATE_PING; + HdmiCecSink::_instance->m_ThreadExitCV.notify_one(); + } + } + else { - Deinitialize(service); + LOGWARN("CEC not Enabled\n"); } + } - // On success return empty, to indicate there is no error text. - return msg; - } + void HdmiCecSink::sendStandbyMessage() + { + if(!HdmiCecSink::_instance) + return; + if(!(HdmiCecSink::_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } - void HdmiCecSink::Deinitialize(PluginHost::IShell* /* service */) + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(Standby()), 1000); + } + + void HdmiCecSink::onHdmiHotPlug(int portId , int connectStatus) + { + LOGINFO("onHdmiHotPlug Status : %d ", connectStatus); + if(!connectStatus) + { + LOGINFO(" removeDevice port: %d Logical address :%d \r\n",portId,hdmiInputs[portId].m_logicalAddr.toInt() ); + _instance->removeDevice(hdmiInputs[portId].m_logicalAddr.toInt()); + } + CheckHdmiInState(); + + if(cecEnableStatus) { + LOGINFO("cecEnableStatus : %d Trigger CEC Ping !!! \n", cecEnableStatus); + m_pollNextState = POLL_THREAD_STATE_PING; + m_ThreadExitCV.notify_one(); + } + if( HdmiArcPortID >= 0 ) { + updateArcState(); + } + return; + } + void HdmiCecSink::updateArcState() { - - profileType = searchRdkProfile(); + if ( m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED ) + { + if (!(hdmiInputs[HdmiArcPortID].m_isConnected)) + { + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + } + else + { + LOGINFO("updateArcState :not updating ARC state current arc state %d ",m_currentArcRoutingState); + } + } + } + void HdmiCecSink::arcStartStopTimerFunction() + { + JsonObject params; + + if (m_arcstarting) + { + LOGINFO("arcStartStopTimerFunction ARC start timer expired"); + LOGINFO("notify_device setting that Initiate ARC failed to get the ARC_STATE_ARC_INITIATED state\n"); + params["status"] = string("failure"); + sendNotify(eventString[HDMICECSINK_EVENT_ARC_INITIATION_EVENT], params); + } + else + { + LOGINFO("arcStartStopTimerFunction ARC stop timer expired"); + LOGINFO("notify_device setting that Terminate ARC failed to get the ARC_STATE_ARC_TERMINATED state\n"); + params["status"] = string("failure"); + sendNotify(eventString[HDMICECSINK_EVENT_ARC_TERMINATION_EVENT], params); + + + } + /* bring the state machine to the clean state for a new start */ + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + } + void HdmiCecSink::Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor) + { + JsonObject params; + + LOGINFO("Notify the DS "); + params["ShortAudioDescriptor"]= JsonValue(audiodescriptor); + sendNotify(eventString[HDMICECSINK_EVENT_SHORT_AUDIODESCRIPTOR_EVENT], params); + } + + void HdmiCecSink::Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg) + { + uint8_t numberofdescriptor = msg.numberofdescriptor; + uint32_t descriptor =0; + JsonArray audiodescriptor; + + if (numberofdescriptor) + { + for( uint8_t i=0; i < numberofdescriptor; i++) + { + descriptor = msg.shortAudioDescriptor[i].getAudiodescriptor(); + + LOGINFO("descriptor%d 0x%x\n",i,descriptor); + audiodescriptor.Add(descriptor); + + } + } + else + { + audiodescriptor.Add(descriptor); + } + HdmiCecSink::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); + } - if (profileType == STB || profileType == NOT_FOUND) + void HdmiCecSink::updateCurrentLatency(int videoLatency, bool lowLatencyMode,int audioOutputCompensated, int audioOutputDelay = 0) { - LOGINFO("Invalid profile type for TV \n"); - return ; + uint8_t latencyFlags = 0; + latencyFlags = ((lowLatencyMode & 0x1) << 2) | (audioOutputCompensated & 0x3); + LOGINFO("Video Latency : %d , Low Latency Mode : %d ,Audio Output Compensated value : %d , Audio Output Delay : %d , Latency Flags: %d ", videoLatency, lowLatencyMode, audioOutputCompensated, audioOutputDelay, latencyFlags); + m_video_latency = (videoLatency/2) + 1; + m_latency_flags = latencyFlags; + m_audio_output_delay = (audioOutputDelay/2) + 1; + setLatencyInfo(); } - bool enabled = false; - bool ret = false; - HdmiCecSink::_hdmiCecSink->GetEnabled(enabled,ret); + void HdmiCecSink::setLatencyInfo() + { + if(!HdmiCecSink::_instance) + return; - if(ret && enabled) - { - Exchange::IHdmiCecSink::HdmiCecSinkSuccess success; - HdmiCecSink::_hdmiCecSink->SetEnabled(false,success); - } + if(!(_instance->smConnection)) + return; - if(nullptr != _hdmiCecSink) - { - _hdmiCecSink->Unregister(&_notification); - Exchange::JHdmiCecSink::Unregister(*this); - _hdmiCecSink->Release(); - _hdmiCecSink = nullptr; + LOGINFO("Send Report Current Latency message \n"); + _instance->smConnection->sendTo(LogicalAddress::BROADCAST,MessageEncoder().encode(ReportCurrentLatency(physical_addr,m_video_latency,m_latency_flags,m_audio_output_delay))); - RPC::IRemoteConnection* connection = _service->RemoteConnection(_connectionId); - if (connection != nullptr) - { - try{ - connection->Terminate(); - } - catch(const std::exception& e) - { - std::string errorMessage = "Failed to terminate connection: "; - errorMessage += e.what(); - LOGWARN("%s",errorMessage.c_str()); + } + + void HdmiCecSink::Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status + //SetSystemAudioMode message may come from AVR/Soundbar while CEC disable is in-progress + if ( cecSettingEnabled != true ) + { + LOGINFO("Process SetSystemAudioMode from Audio device: Cec is disabled-> EnableCEC first"); + return; + } + + if ( (msg.status.toInt() == SYSTEM_AUDIO_MODE_OFF) && (m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) + { + /* ie system audio mode off -> amplifier goign to standby but still ARC is in initiated state,stop ARC and + bring the ARC state machine to terminated state*/ + LOGINFO("system audio mode off message but arc is not in terminated state so stopping ARC"); + stopArc(); + + } + + params["audioMode"] = msg.status.toString().c_str(); + if (msg.status.toInt() == SYSTEM_AUDIO_MODE_ON) { + LOGINFO("panel power state is %s", powerState ? "Off" : "On"); + if (powerState == DEVICE_POWER_STATE_ON ) { + LOGINFO("Notifying system audio mode ON event"); + sendNotify(eventString[HDMICECSINK_EVENT_SYSTEM_AUDIO_MODE], params); + } else { + LOGINFO("Not notifying system audio mode ON event"); + } + } else { + LOGINFO("Notifying system audio Mode OFF event"); + sendNotify(eventString[HDMICECSINK_EVENT_SYSTEM_AUDIO_MODE], params); + } + } + void HdmiCecSink::Process_ReportAudioStatus_msg(const ReportAudioStatus msg) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + if (m_audioStatusTimerStarted) + { + m_audioStatusReceived = true; + m_isAudioStatusInfoUpdated = true; + m_audioStatusTimerStarted = false; + if (m_audioStatusDetectionTimer.isActive()) + { + LOGINFO("AudioStatus received from the Audio Device and the timer is still active. So stopping the timer!\n"); + m_audioStatusDetectionTimer.stop(); + } + LOGINFO("AudioStatus received from the Audio Device. Updating the AudioStatus info! m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + } + LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); + params["muteStatus"] = msg.status.getAudioMuteStatus(); + params["volumeLevel"] = msg.status.getAudioVolume(); + sendNotify(eventString[HDMICECSINK_EVENT_REPORT_AUDIO_STATUS], params); + + } + void HdmiCecSink::sendKeyPressEvent(const int logicalAddress, int keyCode) + { + if(!(_instance->smConnection)) + return; + LOGINFO(" sendKeyPressEvent logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); + switch(keyCode) + { + case VOLUME_UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); + break; + case VOLUME_DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); + break; + case MUTE: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); + break; + case UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); + break; + case DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); + break; + case LEFT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); + break; + case RIGHT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); + break; + case SELECT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); + break; + case HOME: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); + break; + case BACK: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); + break; + case NUMBER_0: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); + break; + case NUMBER_1: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); + break; + case NUMBER_2: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); + break; + case NUMBER_3: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); + break; + case NUMBER_4: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); + break; + case NUMBER_5: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); + break; + case NUMBER_6: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); + break; + case NUMBER_7: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); + break; + case NUMBER_8: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); + break; + case NUMBER_9: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); + break; + + } + } + + void HdmiCecSink::sendUserControlPressed(const int logicalAddress, int keyCode) + { + if(!(_instance->smConnection)) + return; + LOGINFO(" sendUserControlPressed logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); + switch(keyCode) + { + case VOLUME_UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); + break; + case VOLUME_DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); + break; + case MUTE: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); + break; + case UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); + break; + case DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); + break; + case LEFT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); + break; + case RIGHT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); + break; + case SELECT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); + break; + case HOME: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); + break; + case BACK: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); + break; + case NUMBER_0: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); + break; + case NUMBER_1: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); + break; + case NUMBER_2: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); + break; + case NUMBER_3: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); + break; + case NUMBER_4: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); + break; + case NUMBER_5: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); + break; + case NUMBER_6: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); + break; + case NUMBER_7: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); + break; + case NUMBER_8: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); + break; + case NUMBER_9: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); + break; + + } } - connection->Release(); - } - } + void HdmiCecSink::sendKeyReleaseEvent(const int logicalAddress) + { + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); + + } + + void HdmiCecSink::sendUserControlReleased(const int logicalAddress) + { + if(!(_instance->smConnection)) + return; + LOGINFO(" User Control Released \n"); + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); + } + + void HdmiCecSink::sendDeviceUpdateInfo(const int logicalAddress) + { + JsonObject params; + params["logicalAddress"] = JsonValue(logicalAddress); + sendNotify(eventString[HDMICECSINK_EVENT_DEVICE_INFO_UPDATED], params); + } + void HdmiCecSink::systemAudioModeRequest() + { + if ( cecEnableStatus != true ) + { + LOGINFO("systemAudioModeRequest: Cec is disabled-> EnableCEC first"); + return; + } + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Send systemAudioModeRequest "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(SystemAudioModeRequest(physical_addr)), 1000); - _connectionId = 0; - _service->Unregister(&_notification); - _service->Release(); - _service = nullptr; - LOGINFO("HdmiCecSink plugin is deactivated. Successfully deactivated HdmiCecSink Plugin"); } + void HdmiCecSink::sendGiveAudioStatusMsg() + { + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Send GiveAudioStatus "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(GiveAudioStatus()), 100); - string HdmiCecSink::Information() const + } + void HdmiCecSink::reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus) { - return("This HdmiCecSink PLugin Facilitates the HDMI CEC Sink Control"); + JsonObject params; + params["powerStatus"] = JsonValue(powerStatus); + LOGINFO("Panle power state is %s", powerState ? "Off" : "On"); + if (powerStatus != AUDIO_DEVICE_POWERSTATE_OFF) { + if (powerState == DEVICE_POWER_STATE_ON ) { + LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_POWER_STATUS], params); + } else { + LOGINFO("Not notifying audio device power state to DS"); + } + } else { + LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_POWER_STATUS], params); + } } - void HdmiCecSink::Deactivated(RPC::IRemoteConnection* connection) + void HdmiCecSink::SendStandbyMsgEvent(const int logicalAddress) { - if (connection->Id() == _connectionId) + JsonObject params; + if(!HdmiCecSink::_instance) + return; + params["logicalAddress"] = JsonValue(logicalAddress); + sendNotify(eventString[HDMICECSINK_EVENT_STANDBY_MSG_EVENT], params); + } + uint32_t HdmiCecSink::setEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + bool enabled = false; + + if (parameters.HasLabel("enabled")) + { + getBoolParameter("enabled", enabled); + } + else + { + returnResponse(false); + } + + setEnabled(enabled); + returnResponse(true); + } + + uint32_t HdmiCecSink::getEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + response["enabled"] = getEnabled(); + returnResponse(true); + } + + uint32_t HdmiCecSink::getAudioDeviceConnectedStatusWrapper(const JsonObject& parameters, JsonObject& response) + { + response["connected"] = getAudioDeviceConnectedStatus(); + returnResponse(true); + } + + uint32_t HdmiCecSink::requestAudioDevicePowerStatusWrapper(const JsonObject& parameters, JsonObject& response) + { + requestAudioDevicePowerStatus(); + returnResponse(true); + } + + uint32_t HdmiCecSink::getActiveSourceWrapper(const JsonObject& parameters, JsonObject& response) + { + char routeString[1024] = {'\0'}; + int length = 0; + std::stringstream temp; + + if ( HdmiCecSink::_instance->m_currentActiveSource != -1 ) + { + int n = HdmiCecSink::_instance->m_currentActiveSource; + response["available"] = true; + response["logicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt(); + response["physicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_physicalAddr.toString().c_str(); + response["deviceType"] = HdmiCecSink::_instance->deviceList[n].m_deviceType.toString().c_str(); + response["cecVersion"] = HdmiCecSink::_instance->deviceList[n].m_cecVersion.toString().c_str(); + response["osdName"] = HdmiCecSink::_instance->deviceList[n].m_osdName.toString().c_str(); + response["vendorID"] = HdmiCecSink::_instance->deviceList[n].m_vendorID.toString().c_str(); + response["powerStatus"] = HdmiCecSink::_instance->deviceList[n].m_powerStatus.toString().c_str(); + + if ( HdmiCecSink::_instance->deviceList[n].m_physicalAddr.getByteValue(0) != 0 ) + { + snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSink::_instance->deviceList[n].m_physicalAddr.getByteValue(0) - 1)); + } + else if ( HdmiCecSink::_instance->deviceList[n].m_physicalAddr.getByteValue(0) == 0 ) + { + snprintf(&routeString[length], sizeof(routeString) - length, "%s", "TV"); + } + + temp << (char *)routeString; + response["port"] = temp.str(); + + } + else + { + response["available"] = false; + } + + returnResponse(true); + } + + uint32_t HdmiCecSink::getDeviceListWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + response["numberofdevices"] = HdmiCecSink::_instance->m_numberOfDevices; + LOGINFO("getDeviceListWrapper m_numberOfDevices :%d \n", HdmiCecSink::_instance->m_numberOfDevices); + JsonArray deviceList; + + for (int n = 0; n <= LogicalAddress::UNREGISTERED; n++) + { + + if ( n != HdmiCecSink::_instance->m_logicalAddressAllocated && + HdmiCecSink::_instance->deviceList[n].m_isDevicePresent ) + { + JsonObject device; + + device["logicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt(); + device["physicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_physicalAddr.toString().c_str(); + device["deviceType"] = HdmiCecSink::_instance->deviceList[n].m_deviceType.toString().c_str(); + device["cecVersion"] = HdmiCecSink::_instance->deviceList[n].m_cecVersion.toString().c_str(); + device["osdName"] = HdmiCecSink::_instance->deviceList[n].m_osdName.toString().c_str(); + device["vendorID"] = HdmiCecSink::_instance->deviceList[n].m_vendorID.toString().c_str(); + device["powerStatus"] = HdmiCecSink::_instance->deviceList[n].m_powerStatus.toString().c_str(); + int hdmiPortNumber = -1; + LOGINFO("getDeviceListWrapper m_numofHdmiInput:%d looking for Logical Address :%d \n", m_numofHdmiInput, HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt()); + for (int i=0; i < m_numofHdmiInput; i++) + { + LOGINFO("getDeviceListWrapper connected : %d, portid:%d LA: %d \n", hdmiInputs[i].m_isConnected, hdmiInputs[i].m_portID, hdmiInputs[i].m_logicalAddr.toInt()); + if(hdmiInputs[i].m_isConnected && hdmiInputs[i].m_logicalAddr.toInt() == HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt()) + { + hdmiPortNumber = hdmiInputs[i].m_portID; + LOGINFO("got portid :%d break \n", hdmiPortNumber); + break; + } + } + device["portNumber"] = hdmiPortNumber; + deviceList.Add(device); + } + } + + response["deviceList"] = deviceList; + + returnResponse(true); + } + + + uint32_t HdmiCecSink::setOSDNameWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + if (parameters.HasLabel("name")) + { + std::string osd = parameters["name"].String(); + LOGINFO("setOSDNameWrapper osdName: %s",osd.c_str()); + osdName = osd.c_str(); + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_OSD_NAME, JsonValue(osd.c_str())); + } + else { - ASSERT(_service != nullptr); - Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE)); + returnResponse(false); } + returnResponse(true); + } + + uint32_t HdmiCecSink::getOSDNameWrapper(const JsonObject& parameters, JsonObject& response) + { + response["name"] = osdName.toString(); + LOGINFO("getOSDNameWrapper osdName : %s \n",osdName.toString().c_str()); + returnResponse(true); } + uint32_t HdmiCecSink::printDeviceListWrapper(const JsonObject& parameters, JsonObject& response) + { + printDeviceList(); + response["printed"] = true; + returnResponse(true); + } + + uint32_t HdmiCecSink::setActiveSourceWrapper(const JsonObject& parameters, JsonObject& response) + { + setActiveSource(false); + returnResponse(true); + } + + uint32_t HdmiCecSink::setActivePathWrapper(const JsonObject& parameters, JsonObject& response) + { + if (parameters.HasLabel("activePath")) + { + std::string id = parameters["activePath"].String(); + PhysicalAddress phy_addr = PhysicalAddress(id); + + LOGINFO("Addr = %s, length = %zu", id.c_str(), id.length()); + + setStreamPath(phy_addr); + returnResponse(true); + } + else + { + returnResponse(false); + } + } + + uint32_t HdmiCecSink::getActiveRouteWrapper(const JsonObject& parameters, JsonObject& response) + { + std::vector route; + char routeString[1024] = {'\0'}; + int length = 0; + JsonArray pathList; + std::stringstream temp; + + if (HdmiCecSink::_instance->m_currentActiveSource != -1 && + HdmiCecSink::_instance->m_currentActiveSource != HdmiCecSink::_instance->m_logicalAddressAllocated ) + { + HdmiCecSink::_instance->getActiveRoute(LogicalAddress(HdmiCecSink::_instance->m_currentActiveSource), route); + + if (route.size()) + { + response["available"] = true; + response["length"] = route.size(); + + for (unsigned int i=0; i < route.size(); i++) + { + if ( route[i] != LogicalAddress::UNREGISTERED ) + { + JsonObject device; + + device["logicalAddress"] = HdmiCecSink::_instance->deviceList[route[i]].m_logicalAddress.toInt(); + device["physicalAddress"] = HdmiCecSink::_instance->deviceList[route[i]].m_physicalAddr.toString().c_str(); + device["deviceType"] = HdmiCecSink::_instance->deviceList[route[i]].m_deviceType.toString().c_str(); + device["osdName"] = HdmiCecSink::_instance->deviceList[route[i]].m_osdName.toString().c_str(); + device["vendorID"] = HdmiCecSink::_instance->deviceList[route[i]].m_vendorID.toString().c_str(); + + pathList.Add(device); + + snprintf(&routeString[length], sizeof(routeString) - length, "%s", _instance->deviceList[route[i]].m_logicalAddress.toString().c_str()); + length += _instance->deviceList[route[i]].m_logicalAddress.toString().length(); + snprintf(&routeString[length], sizeof(routeString) - length, "(%s", _instance->deviceList[route[i]].m_osdName.toString().c_str()); + length += _instance->deviceList[route[i]].m_osdName.toString().length(); + snprintf(&routeString[length], sizeof(routeString) - length, "%s", ")-->"); + length += strlen(")-->"); + if( i + 1 == route.size() ) + { + snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSink::_instance->deviceList[route[i]].m_physicalAddr.getByteValue(0) - 1)); + } + } + } + + response["pathList"] = pathList; + temp << (char *)routeString; + response["ActiveRoute"] = temp.str(); + LOGINFO("ActiveRoute = [%s]", routeString); + } + + } + else if ( HdmiCecSink::_instance->m_currentActiveSource == HdmiCecSink::_instance->m_logicalAddressAllocated ) + { + response["available"] = true; + response["ActiveRoute"] = "TV"; + } + else + { + response["available"] = false; + } + + returnResponse(true); + } + + uint32_t HdmiCecSink::requestActiveSourceWrapper(const JsonObject& parameters, JsonObject& response) + { + requestActiveSource(); + returnResponse(true); + } + + uint32_t HdmiCecSink::setRoutingChangeWrapper(const JsonObject& parameters, JsonObject& response) + { + std::string oldPortID; + std::string newPortID; + + returnIfParamNotFound(parameters, "oldPort"); + returnIfParamNotFound(parameters, "newPort"); + + oldPortID = parameters["oldPort"].String(); + newPortID = parameters["newPort"].String(); + + + if ((oldPortID.find("HDMI",0) != std::string::npos || + oldPortID.find("TV",0) != std::string::npos ) && + ( newPortID.find("HDMI", 0) != std::string::npos || + newPortID.find("TV", 0) != std::string::npos )) + { + setRoutingChange(oldPortID, newPortID); + returnResponse(true); + } + else + { + returnResponse(false); + } + } + + + uint32_t HdmiCecSink::setMenuLanguageWrapper(const JsonObject& parameters, JsonObject& response) + { + std::string lang; + + returnIfParamNotFound(parameters, "language"); + + lang = parameters["language"].String(); + + setCurrentLanguage(Language(lang.data())); + sendMenuLanguage(); + returnResponse(true); + } + + + uint32_t HdmiCecSink::setVendorIdWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + if (parameters.HasLabel("vendorid")) + { + std::string id = parameters["vendorid"].String(); + unsigned int vendorID = 0x00; + try + { + vendorID = stoi(id,NULL,16); + } + catch (...) + { + LOGWARN("Exception in setVendorIdWrapper set default value\n"); + vendorID = 0x0019FB; + } + appVendorId = {(uint8_t)(vendorID >> 16 & 0xff),(uint8_t)(vendorID>> 8 & 0xff),(uint8_t) (vendorID & 0xff)}; + LOGINFO("appVendorId : %s vendorID :%x \n",appVendorId.toString().c_str(), vendorID ); + + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_VENDOR_ID, JsonValue(vendorID)); + } + else + { + returnResponse(false); + } + returnResponse(true); + } + uint32_t HdmiCecSink::setArcEnableDisableWrapper(const JsonObject& parameters, JsonObject& response) + { + + bool enabled = false; + + if (parameters.HasLabel("enabled")) + { + getBoolParameter("enabled", enabled); + } + else + { + returnResponse(false); + } + if(enabled) + { + startArc(); + } + else + { + stopArc(); + + } + + returnResponse(true); + } + uint32_t HdmiCecSink::getVendorIdWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("getVendorIdWrapper appVendorId : %s \n",appVendorId.toString().c_str()); + response["vendorid"] = appVendorId.toString() ; + returnResponse(true); + } + + uint32_t HdmiCecSink::requestShortAudioDescriptorWrapper(const JsonObject& parameters, JsonObject& response) + { + requestShortaudioDescriptor(); + returnResponse(true); + } + uint32_t HdmiCecSink::sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response) + { + sendStandbyMessage(); + returnResponse(true); + } + + uint32_t HdmiCecSink::sendAudioDevicePowerOnMsgWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("%s invoked. \n",__FUNCTION__); + systemAudioModeRequest(); + returnResponse(true); + } + uint32_t HdmiCecSink::sendRemoteKeyPressWrapper(const JsonObject& parameters, JsonObject& response) + { + returnIfParamNotFound(parameters, "logicalAddress"); + returnIfParamNotFound(parameters, "keyCode"); + string logicalAddress = parameters["logicalAddress"].String(); + string keyCode = parameters["keyCode"].String(); + SendKeyInfo keyInfo; + keyInfo.logicalAddr = stoi(logicalAddress); + keyInfo.keyCode = stoi(keyCode); + keyInfo.UserControl = "sendKeyPressEvent"; + std::unique_lock lk(m_sendKeyEventMutex); + m_SendKeyQueue.push(keyInfo); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + LOGINFO("Post send key press event to queue size:%zu \n",m_SendKeyQueue.size()); + returnResponse(true); + } + + uint32_t HdmiCecSink::sendUserControlPressedWrapper(const JsonObject& parameters, JsonObject& response) + { + returnIfParamNotFound(parameters, "logicalAddress"); + returnIfParamNotFound(parameters, "keyCode"); + string logicalAddress = parameters["logicalAddress"].String(); + string keyCode = parameters["keyCode"].String(); + SendKeyInfo keyInfo; + keyInfo.logicalAddr = stoi(logicalAddress); + keyInfo.keyCode = stoi(keyCode); + keyInfo.UserControl = "sendUserControlPressed"; + std::unique_lock lk(m_sendKeyEventMutex); + m_SendKeyQueue.push(keyInfo); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + LOGINFO("User control pressed, queue size:%zu \n",m_SendKeyQueue.size()); + returnResponse(true); + } + + uint32_t HdmiCecSink::sendUserControlReleasedWrapper(const JsonObject& parameters, JsonObject& response) + { + returnIfParamNotFound(parameters, "logicalAddress"); + string logicalAddress = parameters["logicalAddress"].String(); + SendKeyInfo keyInfo; + keyInfo.logicalAddr = stoi(logicalAddress); + keyInfo.keyCode = 0; + keyInfo.UserControl = "sendUserControlReleased"; + std::unique_lock lk(m_sendKeyEventMutex); + m_SendKeyQueue.push(keyInfo); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + LOGINFO("User Control Released, queue size:%zu \n",m_SendKeyQueue.size()); + returnResponse(true); + } + + uint32_t HdmiCecSink::sendGiveAudioStatusWrapper(const JsonObject& parameters, JsonObject& response) + { + sendGiveAudioStatusMsg(); + returnResponse(true); + } + uint32_t HdmiCecSink::setLatencyInfoWrapper(const JsonObject& parameters, JsonObject& response) + { + int video_latency,audio_output_compensated,audio_output_delay; + bool low_latency_mode; + + returnIfParamNotFound(parameters, "videoLatency"); + returnIfParamNotFound(parameters, "lowLatencyMode"); + returnIfParamNotFound(parameters, "audioOutputCompensated"); + returnIfParamNotFound(parameters, "audioOutputDelay"); + video_latency = stoi(parameters["videoLatency"].String()); + low_latency_mode = stoi(parameters["lowLatencyMode"].String()); + audio_output_compensated = stoi(parameters["audioOutputCompensated"].String()); + audio_output_delay = stoi(parameters["audioOutputDelay"].String()); + + updateCurrentLatency(video_latency, low_latency_mode,audio_output_compensated, audio_output_delay); + returnResponse(true); + } + bool HdmiCecSink::loadSettings() + { + Core::File file; + file = CEC_SETTING_ENABLED_FILE; + + if( file.Open()) + { + JsonObject parameters; + parameters.IElement::FromFile(file); + bool isConfigAdded = false; + + if( parameters.HasLabel(CEC_SETTING_ENABLED)) + { + getBoolParameter(CEC_SETTING_ENABLED, cecSettingEnabled); + LOGINFO("CEC_SETTING_ENABLED present value:%d",cecSettingEnabled); + } + else + { + parameters[CEC_SETTING_ENABLED] = true; + cecSettingEnabled = true; + isConfigAdded = true; + LOGINFO("CEC_SETTING_ENABLED not present set dafult true:\n "); + } + + if( parameters.HasLabel(CEC_SETTING_OTP_ENABLED)) + { + getBoolParameter(CEC_SETTING_OTP_ENABLED, cecOTPSettingEnabled); + LOGINFO("CEC_SETTING_OTP_ENABLED present value :%d",cecOTPSettingEnabled); + } + else + { + parameters[CEC_SETTING_OTP_ENABLED] = true; + cecOTPSettingEnabled = true; + isConfigAdded = true; + LOGINFO("CEC_SETTING_OTP_ENABLED not present set dafult true:\n "); + } + if( parameters.HasLabel(CEC_SETTING_OSD_NAME)) + { + std::string osd_name; + getStringParameter(CEC_SETTING_OSD_NAME, osd_name); + osdName = osd_name.c_str(); + LOGINFO("CEC_SETTING_OSD_NAME present osd_name :%s",osdName.toString().c_str()); + } + else + { + parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); + LOGINFO("CEC_SETTING_OSD_NMAE not present set dafult value :%s\n ",osdName.toString().c_str()); + isConfigAdded = true; + } + unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); + if( parameters.HasLabel(CEC_SETTING_VENDOR_ID)) + { + getNumberParameter(CEC_SETTING_VENDOR_ID, vendorId); + LOGINFO("CEC_SETTING_VENDOR_ID present :%x ",vendorId); + } + else + { + LOGINFO("CEC_SETTING_VENDOR_ID not present set dafult value :%x \n ",vendorId); + parameters[CEC_SETTING_VENDOR_ID] = vendorId; + isConfigAdded = true; + } + + appVendorId = {(uint8_t)(vendorId >> 16 & 0xff),(uint8_t)(vendorId >> 8 & 0xff),(uint8_t) (vendorId & 0xff)}; + LOGINFO("appVendorId : %s vendorId :%x \n",appVendorId.toString().c_str(), vendorId ); + + if(isConfigAdded) + { + LOGINFO("isConfigAdded true so update file:\n "); + file.Destroy(); + file.Create(); + parameters.IElement::ToFile(file); + + } + + file.Close(); + } + else + { + LOGINFO("CEC_SETTING_ENABLED_FILE file not present create with default settings "); + file.Open(false); + if (!file.IsOpen()) + file.Create(); + + JsonObject parameters; + unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); + parameters[CEC_SETTING_ENABLED] = true; + parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); + parameters[CEC_SETTING_VENDOR_ID] = vendorId; + + cecSettingEnabled = true; + cecOTPSettingEnabled = true; + parameters.IElement::ToFile(file); + + file.Close(); + + } + + return cecSettingEnabled; + } + + void HdmiCecSink::setEnabled(bool enabled) + { + LOGINFO("Entered setEnabled: %d cecSettingEnabled :%d ",enabled, cecSettingEnabled); + + if (cecSettingEnabled != enabled) + { + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_ENABLED, JsonValue(enabled)); + cecSettingEnabled = enabled; + } + if(true == enabled) + { + CECEnable(); + } + else + { + CECDisable(); + } + return; + } + + void HdmiCecSink::updateImageViewOn(const int logicalAddress) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || + logicalAddress == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress].m_isDevicePresent && + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) + + { + /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ + sendNotify(eventString[HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY], params); + } + + sendNotify(eventString[HDMICECSINK_EVENT_IMAGE_VIEW_ON_MSG], params); + } + + void HdmiCecSink::updateTextViewOn(const int logicalAddress) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || + logicalAddress == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress].m_isDevicePresent && + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) + { + /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ + sendNotify(eventString[HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY], params); + } + + sendNotify(eventString[HDMICECSINK_EVENT_TEXT_VIEW_ON_MSG], params); + } + + + void HdmiCecSink::updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr) + { + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && + logicalAddress.toInt() != _instance->m_logicalAddressAllocated) + { + for (int i=0; i < m_numofHdmiInput; i++) + { + LOGINFO(" addr = %d, portID = %d", phy_addr.getByteValue(0), hdmiInputs[i].m_portID); + if (phy_addr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { + hdmiInputs[i].addChild(logicalAddress, phy_addr); + } + } + } + } + + void HdmiCecSink::getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route) + { + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || + logicalAddress.toInt() == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && + logicalAddress.toInt() != _instance->m_logicalAddressAllocated && + _instance->deviceList[logicalAddress.toInt()].m_isActiveSource ) + { + route.clear(); + for (int i=0; i < m_numofHdmiInput; i++) + { + LOGINFO("physicalAddress = [%d], portID = %d", _instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0), hdmiInputs[i].m_portID); + if (_instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { + hdmiInputs[i].getRoute(_instance->deviceList[logicalAddress.toInt()].m_physicalAddr, route); + } + } + } + else { + LOGERR("Not in correct state to Find Route"); + } + } + + + void HdmiCecSink::CheckHdmiInState() + { + int err; + bool isAnyPortConnected = false; + + dsHdmiInGetStatusParam_t params; + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + IARM_BUS_DSMGR_API_dsHdmiInGetStatus, + (void *)¶ms, + sizeof(params)); + + if(err == IARM_RESULT_SUCCESS && params.result == dsERR_NONE ) + { + for( int i = 0; i < m_numofHdmiInput; i++ ) + { + LOGINFO("Is HDMI In Port [%d] connected [%d] \n",i, params.status.isPortConnected[i]); + if ( params.status.isPortConnected[i] ) + { + isAnyPortConnected = true; + } + + LOGINFO("update Port Status [%d] \n", i); + hdmiInputs[i].update(params.status.isPortConnected[i]); + } + } + + if ( isAnyPortConnected ) { + m_isHdmiInConnected = true; + } else { + m_isHdmiInConnected = false; + } + } + + void HdmiCecSink::requestActiveSource() + { + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + _instance->smConnection->sendTo(LogicalAddress::BROADCAST, + MessageEncoder().encode(RequestActiveSource()), 500); + } + + void HdmiCecSink::setActiveSource(bool isResponse) + { + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (isResponse && (_instance->m_currentActiveSource != _instance->m_logicalAddressAllocated) ) + { + LOGWARN("TV is not current Active Source"); + return; + } + + _instance->smConnection->sendTo(LogicalAddress::BROADCAST, + MessageEncoder().encode(ActiveSource(_instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr)), 500); + _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; + } + + void HdmiCecSink::setCurrentLanguage(const Language &lang) + { + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = lang; + } + + void HdmiCecSink::sendMenuLanguage() + { + Language lang = ""; + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + lang = _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage; + + _instance->smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(SetMenuLanguage(lang)), 100); + } + + void HdmiCecSink::updateInActiveSource(const int logical_address, const InActiveSource &source ) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if( logical_address != _instance->m_logicalAddressAllocated ) + { + _instance->deviceList[logical_address].m_isActiveSource = false; + + if ( _instance->m_currentActiveSource == logical_address ) + { + _instance->m_currentActiveSource = -1; + } + + params["logicalAddress"] = JsonValue(logical_address); + params["phsicalAddress"] = source.physicalAddress.toString().c_str(); + sendNotify(eventString[HDMICECSINK_EVENT_INACTIVE_SOURCE], params); + } + } + + void HdmiCecSink::updateActiveSource(const int logical_address, const ActiveSource &source ) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if( logical_address != _instance->m_logicalAddressAllocated ) + { + if ( _instance->m_currentActiveSource != -1 ) + { + _instance->deviceList[_instance->m_currentActiveSource].m_isActiveSource = false; + } + + _instance->deviceList[logical_address].m_isActiveSource = true; + _instance->deviceList[logical_address].update(source.physicalAddress); + _instance->m_currentActiveSource = logical_address; + + if (_instance->deviceList[logical_address].m_isDevicePresent && + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) + { + /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ + sendNotify(eventString[HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY], params); + } + + params["logicalAddress"] = JsonValue(logical_address); + params["physicalAddress"] = _instance->deviceList[logical_address].m_physicalAddr.toString().c_str(); + sendNotify(eventString[HDMICECSINK_EVENT_ACTIVE_SOURCE_CHANGE], params); + } + } + + void HdmiCecSink::requestShortaudioDescriptor() + { + if ( cecEnableStatus != true ) + { + LOGINFO("requestShortaudioDescriptor: cec is disabled-> EnableCEC first"); + return; + } + + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + LOGINFO(" Send requestShortAudioDescriptor Message "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestShortAudioDescriptor(formatid,audioFormatCode,numberofdescriptor)), 1000); + + } + + void HdmiCecSink::requestAudioDevicePowerStatus() + { + if ( cecEnableStatus != true ) + { + LOGWARN("cec is disabled-> EnableCEC first"); + return; + } + + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + LOGINFO(" Send GiveDevicePowerStatus Message to Audio system in the network \n"); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM, MessageEncoder().encode(GiveDevicePowerStatus()), 500); + + m_audioDevicePowerStatusRequested = true; + } + + void HdmiCecSink::sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason) + { + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Sending FeatureAbort to %s for opcode %s with reason %s ",logicalAddress.toString().c_str(),feature.toString().c_str(),reason.toString().c_str()); + _instance->smConnection->sendTo(logicalAddress, MessageEncoder().encode(FeatureAbort(feature,reason)), 500); + } + + void HdmiCecSink::reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode featureOpcode, const AbortReason abortReason) + { + LOGINFO(" Notifying the UI FeatureAbort from the %s for the opcode %s with the reason %s ",logicalAddress.toString().c_str(),featureOpcode.toString().c_str(),abortReason.toString().c_str()); + JsonObject params; + params["LogicalAddress"] = logicalAddress.toInt(); + params["opcode"] = featureOpcode.opCode(); + params["FeatureAbortReason"] = abortReason.toInt(); + sendNotify(eventString[HDMICECSINK_EVENT_FEATURE_ABORT_EVENT], params); + } + + void HdmiCecSink::pingDevices(std::vector &connected , std::vector &disconnected) + { + int i; + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { + if ( i != _instance->m_logicalAddressAllocated ) + { + //LOGWARN("PING for 0x%x \r\n",i); + try { + _instance->smConnection->ping(LogicalAddress(_instance->m_logicalAddressAllocated), LogicalAddress(i), Throw_e()); + } + catch(CECNoAckException &e) + { + if ( _instance->deviceList[i].m_isDevicePresent ) { + disconnected.push_back(i); + } + //LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); + usleep(50000); + continue; + } + catch(Exception &e) + { + LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); + usleep(50000); + continue; + } + + /* If we get ACK, then the device is present in the network*/ + if ( !_instance->deviceList[i].m_isDevicePresent ) + { + connected.push_back(i); + //LOGWARN("Ping success, added device: 0x%x \r\n", i); + } + usleep(50000); + } + } + } + + int HdmiCecSink::requestType( const int logicalAddress ) { + int requestType = CECDeviceParams::REQUEST_NONE; + + if ( !_instance->deviceList[logicalAddress].m_isPAUpdated || !_instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) { + requestType = CECDeviceParams::REQUEST_PHISICAL_ADDRESS; + }else if ( !_instance->deviceList[logicalAddress].m_isOSDNameUpdated ) { + requestType = CECDeviceParams::REQUEST_OSD_NAME; + }else if ( !_instance->deviceList[logicalAddress].m_isVersionUpdated ) { + requestType = CECDeviceParams::REQUEST_CEC_VERSION; + }else if ( !_instance->deviceList[logicalAddress].m_isVendorIDUpdated ) { + requestType = CECDeviceParams::REQUEST_DEVICE_VENDOR_ID; + }else if ( !_instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) { + requestType = CECDeviceParams::REQUEST_POWER_STATUS; + } + + return requestType; + } + + void HdmiCecSink::printDeviceList() { + int i; + + if(!HdmiCecSink::_instance) + return; + + for(i=0; i< 16; i++) + { + if (HdmiCecSink::_instance->deviceList[i].m_isDevicePresent) { + LOGWARN("------ Device ID = %d--------", i); + HdmiCecSink::_instance->deviceList[i].printVariable(); + LOGWARN("-----------------------------"); + } + } + } + + void HdmiCecSink::setStreamPath( const PhysicalAddress &physical_addr) { + + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(SetStreamPath(physical_addr)), 500); + } + + void HdmiCecSink::setRoutingChange(const std::string &from, const std::string &to) { + PhysicalAddress oldPhyAddr = {0xF,0xF,0xF,0xF}; + PhysicalAddress newPhyAddr = {0xF,0xF,0xF,0xF}; + int oldPortID = -1; + int newPortID = -1; + + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + if( from.find("TV",0) != std::string::npos ) + { + oldPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; + _instance->m_currentActiveSource = -1; + } + else + { + oldPortID = stoi(from.substr(4,1),NULL,16); + if ( oldPortID < _instance->m_numofHdmiInput ) + { + oldPhyAddr = _instance->hdmiInputs[oldPortID].m_physicalAddr; + } + else + { + LOGERR("Invalid HDMI Old Port ID"); + return; + } + } + + if( to.find("TV",0) != std::string::npos ) + { + newPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; + /*set active source as TV */ + _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; + } + else + { + newPortID = stoi(to.substr(4,1),NULL,16); + + if ( newPortID < _instance->m_numofHdmiInput ) + { + newPhyAddr = _instance->hdmiInputs[newPortID].m_physicalAddr; + } + else + { + LOGERR("Invalid HDMI New Port ID"); + return; + } + } + + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(RoutingChange(oldPhyAddr, newPhyAddr)), 500); + } + + void HdmiCecSink::addDevice(const int logicalAddress) { + JsonObject params; + + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if ( !HdmiCecSink::_instance->deviceList[logicalAddress].m_isDevicePresent ) + { + HdmiCecSink::_instance->deviceList[logicalAddress].m_isDevicePresent = true; + HdmiCecSink::_instance->deviceList[logicalAddress].m_logicalAddress = LogicalAddress(logicalAddress); + HdmiCecSink::_instance->m_numberOfDevices++; + HdmiCecSink::_instance->m_pollNextState = POLL_THREAD_STATE_INFO; + + if(logicalAddress == 0x5) + { + LOGINFO(" logicalAddress =%d , Audio device detected, Notify Device Settings", logicalAddress ); + params["status"] = string("success"); + params["audioDeviceConnected"] = string("true"); + hdmiCecAudioDeviceConnected = true; + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params); + } + + sendNotify(eventString[HDMICECSINK_EVENT_DEVICE_ADDED], JsonObject()); + } + } + + void HdmiCecSink::removeDevice(const int logicalAddress) { + JsonObject params; + + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress].m_isDevicePresent) + { + _instance->m_numberOfDevices--; + + for (int i=0; i < m_numofHdmiInput; i++) + { + if (_instance->deviceList[logicalAddress].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { + hdmiInputs[i].removeChild(_instance->deviceList[logicalAddress].m_physicalAddr); + hdmiInputs[i].update(LogicalAddress(LogicalAddress::UNREGISTERED)); + } + } + + if(logicalAddress == 0x5) + { + LOGINFO(" logicalAddress =%d , Audio device removed, Notify Device Settings", logicalAddress ); + params["status"] = string("success"); + params["audioDeviceConnected"] = string("false"); + hdmiCecAudioDeviceConnected = false; + if (m_audioStatusDetectionTimer.isActive()){ + m_audioStatusDetectionTimer.stop(); + } + m_isAudioStatusInfoUpdated = false; + m_audioStatusReceived = false; + m_audioStatusTimerStarted = false; + LOGINFO("Audio device removed, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params); + } + + _instance->deviceList[logicalAddress].m_isRequestRetry = 0; + _instance->deviceList[logicalAddress].clear(); + sendNotify(eventString[HDMICECSINK_EVENT_DEVICE_REMOVED], JsonObject()); + } + } + + void HdmiCecSink::request(const int logicalAddress) { + int requestType; + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + requestType = _instance->requestType(logicalAddress); + _instance->deviceList[logicalAddress].m_isRequested = requestType; + + switch (requestType) + { + case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GivePhysicalAddress()), 200); + } + break; + + case CECDeviceParams::REQUEST_CEC_VERSION : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GetCECVersion()), 100); + } + break; + + case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDeviceVendorID()), 100); + } + break; + + case CECDeviceParams::REQUEST_OSD_NAME : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveOSDName()), 500); + } + break; + + case CECDeviceParams::REQUEST_POWER_STATUS : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDevicePowerStatus()), 100); + } + break; + default: + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + break; + } + + _instance->deviceList[logicalAddress].m_requestTime = std::chrono::system_clock::now(); + LOGINFO("request type %d", _instance->deviceList[logicalAddress].m_isRequested); + } + + int HdmiCecSink::requestStatus(const int logicalAddress) { + std::chrono::duration elapsed; + bool isElapsed = false; + + if(!HdmiCecSink::_instance) + return -1; + + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ) { + LOGERR("Logical Address NOT Allocated Or its not valid"); + return -1; + } + + switch ( _instance->deviceList[logicalAddress].m_isRequested ) { + case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : + { + if( _instance->deviceList[logicalAddress].m_isPAUpdated && + _instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_CEC_VERSION : + { + if( _instance->deviceList[logicalAddress].m_isVersionUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : + { + if( _instance->deviceList[logicalAddress].m_isVendorIDUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_OSD_NAME : + { + if( _instance->deviceList[logicalAddress].m_isOSDNameUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_POWER_STATUS : + { + if( _instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + default: + break; + } + + if ( _instance->deviceList[logicalAddress].m_isRequested != CECDeviceParams::REQUEST_NONE ) + { + elapsed = std::chrono::system_clock::now() - _instance->deviceList[logicalAddress].m_requestTime; + + if ( elapsed.count() > HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS ) + { + LOGINFO("request elapsed "); + isElapsed = true; + } + } + + if (isElapsed) + { + /* For some request it should be retry, like report physical address etc for other we can have default values */ + switch( _instance->deviceList[logicalAddress].m_isRequested ) + { + case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : + { + LOGINFO("Retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); + /* Update with Invalid Physical Address */ + if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) + { + LOGINFO("Max retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); + _instance->deviceList[logicalAddress].update(PhysicalAddress(0xF,0xF,0xF,0xF)); + _instance->deviceList[logicalAddress].update(DeviceType(DeviceType::RESERVED)); + _instance->deviceList[logicalAddress].m_isRequestRetry = 0; + } + } + break; + + case CECDeviceParams::REQUEST_CEC_VERSION : + { + /*Defaulting to 1.4*/ + _instance->deviceList[logicalAddress].update(Version(Version::V_1_4)); + } + break; + + case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : + { + _instance->deviceList[logicalAddress].update(VendorID(0,0,0)); + } + break; + + case CECDeviceParams::REQUEST_OSD_NAME : + { + if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) + { + LOGINFO("Max retry for REQUEST_OSD_NAME = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); + _instance->deviceList[logicalAddress].update(OSDName("")); + _instance->deviceList[logicalAddress].m_isRequestRetry = 0; + } + } + break; + + case CECDeviceParams::REQUEST_POWER_STATUS : + { + _instance->deviceList[logicalAddress].update(PowerStatus(PowerStatus::POWER_STATUS_NOT_KNOWN)); + } + break; + default: + break; + } + + + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + + if( _instance->deviceList[logicalAddress].m_isRequested == CECDeviceParams::REQUEST_NONE) + { + LOGINFO("Request Done"); + return CECDeviceParams::REQUEST_DONE; + } + + //LOGINFO("Request NOT Done"); + return CECDeviceParams::REQUEST_NOT_DONE; + } + + void HdmiCecSink::threadRun() + { + std::vector connected; + std::vector disconnected; + int logicalAddressRequested = LogicalAddress::UNREGISTERED + TEST_ADD; + bool isExit = false; + + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + LOGINFO("Entering ThreadRun: _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); + _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; + + while(1) + { + + if (_instance->m_pollThreadExit || isExit ){ + LOGWARN("Thread Exits _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); + break; + } + + if ( _instance->m_pollNextState != POLL_THREAD_STATE_NONE ) + { + _instance->m_pollThreadState = _instance->m_pollNextState; + _instance->m_pollNextState = POLL_THREAD_STATE_NONE; + } + + switch (_instance->m_pollThreadState) { + + case POLL_THREAD_STATE_POLL : + { + //LOGINFO("POLL_THREAD_STATE_POLL"); + _instance->allocateLogicalAddress(DeviceType::TV); + if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED) + { + try{ + + logicalAddress = LogicalAddress(_instance->m_logicalAddressAllocated); + LibCCEC::getInstance().addLogicalAddress(logicalAddress); + _instance->smConnection->setSource(logicalAddress); + _instance->m_numberOfDevices = 0; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType = DeviceType::TV; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_isDevicePresent = true; + _instance->deviceList[_instance->m_logicalAddressAllocated].update(physical_addr); + _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_1_4; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_vendorID = appVendorId; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); + _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = defaultLanguage; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_osdName = osdName.toString().c_str(); + if(cecVersion == 2.0) { + _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_2_0; + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), + MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures)), 500); + } + _instance->smConnection->addFrameListener(_instance->msgFrameListener); + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), + MessageEncoder().encode(ReportPhysicalAddress(physical_addr, _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType)), 100); + + _instance->m_sleepTime = 0; + _instance->m_pollThreadState = POLL_THREAD_STATE_PING; + } + catch(InvalidStateException &e){ + LOGWARN("InvalidStateException caught while allocated logical address. %s", e.what()); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + catch(IOException &e){ + LOGWARN("IOException caught while allocated logical address. %s", e.what()); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + catch(...){ + LOGWARN("Exception caught while allocated logical address."); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + } + else + { + LOGINFO("Not able allocate Logical Address for TV"); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + } + break; + + case POLL_THREAD_STATE_PING : + { + //LOGINFO("POLL_THREAD_STATE_PING"); + _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; + connected.clear(); + disconnected.clear(); + _instance->pingDevices(connected, disconnected); + + if ( disconnected.size() ){ + for( unsigned int i=0; i< disconnected.size(); i++ ) + { + LOGWARN("Disconnected Devices [%zu]", disconnected.size()); + _instance->removeDevice(disconnected[i]); + } + } + + if (connected.size()) { + LOGWARN("Connected Devices [%zu]", connected.size()); + for( unsigned int i=0; i< connected.size(); i++ ) + { + _instance->addDevice(connected[i]); + /* If new device is connected, then try to aquire the information */ + _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; + _instance->m_sleepTime = 0; + } + } + else + { + for(int i=0;im_logicalAddressAllocated && + _instance->deviceList[i].m_isDevicePresent && + !_instance->deviceList[i].isAllUpdated() ) + { + _instance->m_pollNextState = POLL_THREAD_STATE_INFO; + _instance->m_sleepTime = 0; + } + } + /* Check for any update required */ + _instance->m_pollThreadState = POLL_THREAD_STATE_UPDATE; + _instance->m_sleepTime = 0; + } + } + break; + + case POLL_THREAD_STATE_INFO : + { + //LOGINFO("POLL_THREAD_STATE_INFO"); + + if ( logicalAddressRequested == LogicalAddress::UNREGISTERED + TEST_ADD ) + { + int i = 0; + for(;im_logicalAddressAllocated && + _instance->deviceList[i].m_isDevicePresent && + !_instance->deviceList[i].isAllUpdated() ) + { + //LOGINFO("POLL_THREAD_STATE_INFO -> request for %d", i); + logicalAddressRequested = i; + _instance->request(logicalAddressRequested); + _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; + break; + } + } + + if ( i == LogicalAddress::UNREGISTERED) + { + /*So there is no update required, try to ping after some seconds*/ + _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; + _instance->m_sleepTime = 0; + //LOGINFO("POLL_THREAD_STATE_INFO -> state change to Ping", i); + } + } + else + { + /*So there is request sent for logical address, so wait and check the status */ + if ( _instance->requestStatus(logicalAddressRequested) == CECDeviceParams::REQUEST_DONE ) + { + logicalAddressRequested = LogicalAddress::UNREGISTERED; + } + else + { + _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; + } + } + } + break; + + /* updating the power status and if required we can add other information later*/ + case POLL_THREAD_STATE_UPDATE : + { + //LOGINFO("POLL_THREAD_STATE_UPDATE"); + + for(int i=0;im_logicalAddressAllocated && + _instance->deviceList[i].m_isDevicePresent && + _instance->deviceList[i].m_isPowerStatusUpdated ) + { + std::chrono::duration elapsed = std::chrono::system_clock::now() - _instance->deviceList[i].m_lastPowerUpdateTime; + + if ( elapsed.count() > HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS ) + { + _instance->deviceList[i].m_isPowerStatusUpdated = false; + _instance->m_pollNextState = POLL_THREAD_STATE_INFO; + _instance->m_sleepTime = 0; + } + } + } + + _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; + _instance->m_sleepTime = 0; + } + break; + + case POLL_THREAD_STATE_IDLE : + { + //LOGINFO("POLL_THREAD_STATE_IDLE"); + _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; + _instance->m_pollThreadState = POLL_THREAD_STATE_PING; + } + break; + + case POLL_THREAD_STATE_WAIT : + { + /* Wait for Hdmi is connected, in case it disconnected */ + //LOGINFO("19Aug2020-[01] -> POLL_THREAD_STATE_WAIT"); + _instance->m_sleepTime = HDMICECSINK_WAIT_FOR_HDMI_IN_MS; + + if ( _instance->m_isHdmiInConnected == true ) + { + _instance->m_pollThreadState = POLL_THREAD_STATE_POLL; + } + } + break; + + case POLL_THREAD_STATE_EXIT : + { + isExit = true; + _instance->m_sleepTime = 0; + } + break; + } + + std::unique_lock lk(_instance->m_pollExitMutex); + if ( _instance->m_ThreadExitCV.wait_for(lk, std::chrono::milliseconds(_instance->m_sleepTime)) == std::cv_status::timeout ) + continue; + else + LOGINFO("Thread is going to Exit m_pollThreadExit %d\n", _instance->m_pollThreadExit ); + + } + } + + void HdmiCecSink::allocateLAforTV() + { + bool gotLogicalAddress = false; + int addr = LogicalAddress::TV; + int i, j; + if (!(_instance->smConnection)) + return; + + for (i = 0; i< HDMICECSINK_NUMBER_TV_ADDR; i++) + { + /* poll for TV logical address - retry 5 times*/ + for (j = 0; j < 5; j++) + { + try { + smConnection->poll(LogicalAddress(addr), Throw_e()); + } + catch(CECNoAckException &e ) + { + LOGWARN("Poll caught %s \r\n",e.what()); + gotLogicalAddress = true; + break; + } + catch(Exception &e) + { + LOGWARN("Poll caught %s \r\n",e.what()); + usleep(250000); + } + } + if (gotLogicalAddress) + { + break; + } + addr = LogicalAddress::SPECIFIC_USE; + } + + if ( gotLogicalAddress ) + { + m_logicalAddressAllocated = addr; + } + else + { + m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; + } + + LOGWARN("Logical Address for TV 0x%x \r\n",m_logicalAddressAllocated); + } + + void HdmiCecSink::allocateLogicalAddress(int deviceType) + { + if( deviceType == DeviceType::TV ) + { + allocateLAforTV(); + } + } + + void HdmiCecSink::CECEnable(void) + { + std::lock_guard lock(m_enableMutex); + JsonObject params; + LOGINFO("Entered CECEnable"); + if (cecEnableStatus) + { + LOGWARN("CEC Already Enabled"); + return; + } + + if(0 == libcecInitStatus) + { + try + { + LibCCEC::getInstance().init("HdmiCecSink"); + } + catch(InvalidStateException &e){ + LOGWARN("InvalidStateException caught in LibCCEC::init %s", e.what()); + } + catch(IOException &e){ + LOGWARN("IOException caught in LibCCEC::init %s", e.what()); + } + catch(...){ + LOGWARN("Exception caught in LibCCEC::init"); + } + } + libcecInitStatus++; + + //Acquire CEC Addresses + getPhysicalAddress(); + + smConnection = new Connection(LogicalAddress::UNREGISTERED,false,"ServiceManager::Connection::"); + smConnection->open(); + allocateLogicalAddress(DeviceType::TV); + LOGINFO("logical address allocalted: %x \n",m_logicalAddressAllocated); + if ( m_logicalAddressAllocated != LogicalAddress::UNREGISTERED && smConnection) + { + logicalAddress = LogicalAddress(m_logicalAddressAllocated); + LOGINFO(" add logical address %x \n",m_logicalAddressAllocated); + LibCCEC::getInstance().addLogicalAddress(logicalAddress); + smConnection->setSource(logicalAddress); + } + msgProcessor = new HdmiCecSinkProcessor(*smConnection); + msgFrameListener = new HdmiCecSinkFrameListener(*msgProcessor); + if(smConnection) + { + LOGWARN("Start Thread %p", smConnection ); + m_pollThreadState = POLL_THREAD_STATE_POLL; + m_pollNextState = POLL_THREAD_STATE_NONE; + m_pollThreadExit = false; + m_pollThread = std::thread(threadRun); + } + cecEnableStatus = true; + + params["cecEnable"] = string("true"); + sendNotify(eventString[HDMICECSINK_EVENT_CEC_ENABLED], params); + + return; + } + + void HdmiCecSink::CECDisable(void) + { + std::lock_guard lock(m_enableMutex); + JsonObject params; + LOGINFO("Entered CECDisable "); + if(!cecEnableStatus) + { + LOGWARN("CEC Already Disabled "); + return; + } + + if(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) + { + stopArc(); + while(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) + { + usleep(500000); + } + } + + LOGINFO(" CECDisable ARC stopped "); + cecEnableStatus = false; + if (smConnection != NULL) + { + LOGWARN("Stop Thread %p", smConnection ); + m_pollThreadExit = true; + m_ThreadExitCV.notify_one(); + + try + { + if (m_pollThread.joinable()) + { + LOGWARN("Join Thread %p", smConnection ); + m_pollThread.join(); + } + } + catch(const std::system_error& e) + { + LOGERR("system_error exception in thread join %s", e.what()); + } + catch(const std::exception& e) + { + LOGERR("exception in thread join %s", e.what()); + } + + m_pollThreadState = POLL_THREAD_STATE_NONE; + m_pollNextState = POLL_THREAD_STATE_NONE; + + LOGWARN("Deleted Thread %p", smConnection ); + + smConnection->close(); + delete smConnection; + smConnection = NULL; + } + + m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + if (m_audioStatusDetectionTimer.isActive()){ + m_audioStatusDetectionTimer.stop(); + } + m_isAudioStatusInfoUpdated = false; + m_audioStatusReceived = false; + m_audioStatusTimerStarted = false; + LOGINFO("CEC Disabled, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + + + for(int i=0; i< 16; i++) + { + if (_instance->deviceList[i].m_isDevicePresent) + { + _instance->deviceList[i].clear(); + } + } + + if(1 == libcecInitStatus) + { + try + { + LibCCEC::getInstance().term(); + } + catch(InvalidStateException &e){ + LOGWARN("InvalidStateException caught in LibCCEC::term %s", e.what()); + } + catch(IOException &e){ + LOGWARN("IOException caught in LibCCEC::term %s", e.what()); + } + catch(...){ + LOGWARN("Exception caught in LibCCEC::term"); + } + } + + libcecInitStatus--; + LOGWARN("CEC Disabled %d",libcecInitStatus); + + params["cecEnable"] = string("false"); + sendNotify(eventString[HDMICECSINK_EVENT_CEC_ENABLED], params); + + return; + } + + + void HdmiCecSink::getPhysicalAddress() + { + LOGINFO("Entered getPhysicalAddress "); + + uint32_t physAddress = 0x0F0F0F0F; + + try { + LibCCEC::getInstance().getPhysicalAddress(&physAddress); + physical_addr = {(uint8_t)((physAddress >> 24) & 0xFF),(uint8_t)((physAddress >> 16) & 0xFF),(uint8_t) ((physAddress >> 8) & 0xFF),(uint8_t)((physAddress) & 0xFF)}; + LOGINFO("getPhysicalAddress: physicalAddress: %s ", physical_addr.toString().c_str()); + } + catch (const std::exception& e) + { + LOGWARN("exception caught from getPhysicalAddress"); + } + return; + } + + bool HdmiCecSink::getEnabled() + { + + + LOGINFO("getEnabled :%d ",cecEnableStatus); + if(true == cecEnableStatus) + return true; + else + return false; + } + + bool HdmiCecSink::getAudioDeviceConnectedStatus() + { + LOGINFO("getAudioDeviceConnectedStatus :%d ", hdmiCecAudioDeviceConnected); + if(true == hdmiCecAudioDeviceConnected) + return true; + else + return false; + } + //Arc Routing related functions + void HdmiCecSink::startArc() + { + if ( cecEnableStatus != true ) + { + LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); + return; + } + if(!HdmiCecSink::_instance) + return; + + LOGINFO("Current ARC State : %d\n", m_currentArcRoutingState); + + _instance->requestArcInitiation(); + + // start initiate ARC timer 3 sec + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + m_arcstarting = true; + m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); + + } + void HdmiCecSink::requestArcInitiation() + { + { + std::lock_guard lock(m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_INITIATION; + } + LOGINFO("requestArcInitiation release sem"); + _instance->m_semSignaltoArcRoutingThread.release(); + + } + void HdmiCecSink::stopArc() + { + if ( cecEnableStatus != true ) + { + LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); + return; + } + if(!HdmiCecSink::_instance) + return; + if(m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_TERMINATION || m_currentArcRoutingState == ARC_STATE_ARC_TERMINATED) + { + LOGINFO("ARC is either Termination in progress or already Terminated"); + return; + } + + _instance->requestArcTermination(); + /* start a timer for 3 sec to get the desired ARC_STATE_ARC_TERMINATED */ + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + /* m_arcstarting = true means starting the ARC start timer ,false means ARC stopping timer*/ + m_arcstarting = false; + m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); + + + } + void HdmiCecSink::requestArcTermination() + { + { + std::lock_guard lock(m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_TERMINATION; + } + LOGINFO("requestArcTermination release sem"); + _instance->m_semSignaltoArcRoutingThread.release(); + + } + + void HdmiCecSink::Process_InitiateArc() + { + JsonObject params; + + LOGINFO("Command: INITIATE_ARC \n"); + + if(!HdmiCecSink::_instance) + return; + + //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status + //Initiate ARC message may come from AVR/Soundbar while CEC disable is in-progress + if ( cecSettingEnabled != true ) + { + LOGINFO("Process InitiateArc from Audio device: Cec is disabled-> EnableCEC first"); + return; + } + + LOGINFO("Got : INITIATE_ARC and current Arcstate is %d\n",_instance->m_currentArcRoutingState); + + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + if (powerState == DEVICE_POWER_STATE_ON ) { + LOGINFO("Notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); + { + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + _instance->m_currentArcRoutingState = ARC_STATE_ARC_INITIATED; + } + _instance->m_semSignaltoArcRoutingThread.release(); + LOGINFO("Got : ARC_INITIATED and notify Device setting"); + params["status"] = string("success"); + sendNotify(eventString[HDMICECSINK_EVENT_ARC_INITIATION_EVENT], params); + } else { + LOGINFO("Not notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); + } + + } + void HdmiCecSink::Process_TerminateArc() + { + JsonObject params; + + LOGINFO("Command: TERMINATE_ARC current arc state %d \n",HdmiCecSink::_instance->m_currentArcRoutingState); + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + { + std::lock_guard lock(m_arcRoutingStateMutex); + HdmiCecSink::_instance->m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + } + _instance->m_semSignaltoArcRoutingThread.release(); + + // trigger callback to Device setting informing to TERMINATE_ARC + LOGINFO("Got : ARC_TERMINATED and notify Device setting"); + params["status"] = string("success"); + sendNotify(eventString[HDMICECSINK_EVENT_ARC_TERMINATION_EVENT], params); + } + + void HdmiCecSink::threadSendKeyEvent() + { + if(!HdmiCecSink::_instance) + return; + + SendKeyInfo keyInfo = {-1,-1}; + + while(!_instance->m_sendKeyEventThreadExit) + { + keyInfo.logicalAddr = -1; + keyInfo.keyCode = -1; + { + // Wait for a message to be added to the queue + std::unique_lock lk(_instance->m_sendKeyEventMutex); + _instance->m_sendKeyCV.wait(lk, []{return (_instance->m_sendKeyEventThreadRun == true);}); + } + + if (_instance->m_sendKeyEventThreadExit == true) + { + LOGINFO(" threadSendKeyEvent Exiting"); + _instance->m_sendKeyEventThreadRun = false; + break; + } + + if (_instance->m_SendKeyQueue.empty()) { + _instance->m_sendKeyEventThreadRun = false; + continue; + } + + keyInfo = _instance->m_SendKeyQueue.front(); + _instance->m_SendKeyQueue.pop(); + + if(keyInfo.UserControl == "sendUserControlPressed" ) + { + LOGINFO("sendUserControlPressed : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); + _instance->sendUserControlPressed(keyInfo.logicalAddr,keyInfo.keyCode); + } + else if(keyInfo.UserControl == "sendUserControlReleased") + { + LOGINFO("sendUserControlReleased : logical addr:0x%x queue size :%zu \n",keyInfo.logicalAddr,_instance->m_SendKeyQueue.size()); + _instance->sendUserControlReleased(keyInfo.logicalAddr); + } + else + { + LOGINFO("sendKeyPressEvent : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); + _instance->sendKeyPressEvent(keyInfo.logicalAddr,keyInfo.keyCode); + _instance->sendKeyReleaseEvent(keyInfo.logicalAddr); + } + + if((_instance->m_SendKeyQueue.size()<=1 || (_instance->m_SendKeyQueue.size() % 2 == 0)) && ((keyInfo.keyCode == VOLUME_UP) || (keyInfo.keyCode == VOLUME_DOWN) || (keyInfo.keyCode == MUTE)) ) + { + if(keyInfo.keyCode == MUTE) + { + _instance->sendGiveAudioStatusMsg(); + } + else + { + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ",_instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); + if (!_instance->m_isAudioStatusInfoUpdated) + { + if ( !(_instance->m_audioStatusDetectionTimer.isActive())) + { + LOGINFO("Audio status info not updated. Starting the Timer!"); + _instance->m_audioStatusTimerStarted = true; + _instance->m_audioStatusDetectionTimer.start((HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS)); + } + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", _instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); + } + else + { + if (!_instance->m_audioStatusReceived){ + _instance->sendGiveAudioStatusMsg(); + } + } + } + } + + }//while(!_instance->m_sendKeyEventThreadExit) + }//threadSendKeyEvent + + void HdmiCecSink::audioStatusTimerFunction() + { + m_audioStatusTimerStarted = false; + m_isAudioStatusInfoUpdated = true; + LOGINFO("Timer Expired. Requesting the AudioStatus since not received.\n"); + sendGiveAudioStatusMsg(); + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + } + + void HdmiCecSink::threadArcRouting() + { + bool isExit = false; + uint32_t currentArcRoutingState; + + if(!HdmiCecSink::_instance) + return; + + LOGINFO("Running threadArcRouting"); + _instance->getHdmiArcPortID(); + + while(1) + { + + _instance->m_semSignaltoArcRoutingThread.acquire(); + + + + { + LOGINFO(" threadArcRouting Got semaphore"); + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + + currentArcRoutingState = _instance->m_currentArcRoutingState; + + LOGINFO(" threadArcRouting Got Sem arc state %d",currentArcRoutingState); + } + + switch (currentArcRoutingState) + { + + case ARC_STATE_REQUEST_ARC_INITIATION : + { + + _instance->systemAudioModeRequest(); + _instance->Send_Request_Arc_Initiation_Message(); + + } + break; + case ARC_STATE_ARC_INITIATED : + { + _instance->Send_Report_Arc_Initiated_Message(); + } + break; + case ARC_STATE_REQUEST_ARC_TERMINATION : + { + + _instance->Send_Request_Arc_Termination_Message(); + + } + break; + case ARC_STATE_ARC_TERMINATED : + { + _instance->Send_Report_Arc_Terminated_Message(); + } + break; + case ARC_STATE_ARC_EXIT : + { + isExit = true; + } + break; + } + + if (isExit == true) + { + LOGINFO(" threadArcRouting EXITing"); + break; + } + }//while(1) + }//threadArcRouting + + void HdmiCecSink::Send_Request_Arc_Initiation_Message() + { + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Send_Request_Arc_Initiation_Message "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcInitiation()), 1000); + + } + void HdmiCecSink::Send_Report_Arc_Initiated_Message() + { + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcInitiation()), 1000); + + } + void HdmiCecSink::Send_Request_Arc_Termination_Message() + { + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcTermination()), 1000); + } + + void HdmiCecSink::Send_Report_Arc_Terminated_Message() + { + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcTermination()), 1000); + + } + + void HdmiCecSink::getHdmiArcPortID() + { + int err; + dsGetHDMIARCPortIdParam_t param; + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, + (void *)¶m, + sizeof(param)); + if (IARM_RESULT_SUCCESS == err) + { + LOGINFO("HDMI ARC port ID HdmiArcPortID=[%d] \n", param.portId); + HdmiArcPortID = param.portId; + } + } + + void HdmiCecSink::getCecVersion() + { + RFC_ParamData_t param = {0}; + WDMP_STATUS status = getRFCParameter((char*)"thunderapi", TR181_HDMICECSINK_CEC_VERSION, ¶m); + if(WDMP_SUCCESS == status && param.type == WDMP_STRING) { + LOGINFO("CEC Version from RFC = [%s] \n", param.value); + cecVersion = atof(param.value); + } + else { + LOGINFO("Error while fetching CEC Version from RFC "); + } + } + } // namespace Plugin } // namespace WPEFrameworklk diff --git a/HdmiCecSink/HdmiCecSink.h b/HdmiCecSink/HdmiCecSink.h index e0f61176..418fb134 100644 --- a/HdmiCecSink/HdmiCecSink.h +++ b/HdmiCecSink/HdmiCecSink.h @@ -20,27 +20,456 @@ #pragma once #include -#include -#include +#include "ccec/FrameListener.hpp" +#include "ccec/Connection.hpp" -#include +#include "libIARM.h" +#include "ccec/Assert.hpp" +#include "ccec/Messages.hpp" +#include "ccec/MessageDecoder.hpp" +#include "ccec/MessageProcessor.hpp" #undef Assert // this define from Connection.hpp conflicts with WPEFramework #include "Module.h" +#include "tptimer.h" +#include +#include +#include +#include -#include "UtilsBIT.h" -#include "UtilsThreadRAII.h" - -#include -#include -#include +#include "UtilsLogging.h" +#include +#include "PowerManagerInterface.h" using namespace WPEFramework; +using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; +using ThermalTemperature = WPEFramework::Exchange::IPowerManager::ThermalTemperature; + namespace WPEFramework { namespace Plugin { + class HdmiCecSinkFrameListener : public FrameListener + { + public: + HdmiCecSinkFrameListener(MessageProcessor &processor) : processor(processor) {} + void notify(const CECFrame &in) const; + ~HdmiCecSinkFrameListener() {} + private: + MessageProcessor &processor; + }; + + class HdmiCecSinkProcessor : public MessageProcessor + { + public: + HdmiCecSinkProcessor(Connection &conn) : conn(conn) {} + void process (const ActiveSource &msg, const Header &header); + void process (const InActiveSource &msg, const Header &header); + void process (const ImageViewOn &msg, const Header &header); + void process (const TextViewOn &msg, const Header &header); + void process (const RequestActiveSource &msg, const Header &header); + void process (const Standby &msg, const Header &header); + void process (const GetCECVersion &msg, const Header &header); + void process (const CECVersion &msg, const Header &header); + void process (const SetMenuLanguage &msg, const Header &header); + void process (const GiveOSDName &msg, const Header &header); + void process (const GivePhysicalAddress &msg, const Header &header); + void process (const GiveDeviceVendorID &msg, const Header &header); + void process (const SetOSDString &msg, const Header &header); + void process (const SetOSDName &msg, const Header &header); + void process (const RoutingChange &msg, const Header &header); + void process (const RoutingInformation &msg, const Header &header); + void process (const SetStreamPath &msg, const Header &header); + void process (const GetMenuLanguage &msg, const Header &header); + void process (const ReportPhysicalAddress &msg, const Header &header); + void process (const DeviceVendorID &msg, const Header &header); + void process (const GiveDevicePowerStatus &msg, const Header &header); + void process (const ReportPowerStatus &msg, const Header &header); + void process (const FeatureAbort &msg, const Header &header); + void process (const Abort &msg, const Header &header); + void process (const Polling &msg, const Header &header); + void process (const InitiateArc &msg, const Header &header); + void process (const TerminateArc &msg, const Header &header); + void process (const ReportShortAudioDescriptor &msg, const Header &header); + void process (const SetSystemAudioMode &msg, const Header &header); + void process (const ReportAudioStatus &msg, const Header &header); + void process (const GiveFeatures &msg, const Header &header); + void process (const RequestCurrentLatency &msg, const Header &header); + private: + Connection conn; + void printHeader(const Header &header) + { + printf("Header : From : %s \n", header.from.toString().c_str()); + printf("Header : to : %s \n", header.to.toString().c_str()); + } + + }; + + class CECDeviceParams { + public: + + enum { + REQUEST_NONE = 0, + REQUEST_PHISICAL_ADDRESS = 1, + REQUEST_CEC_VERSION, + REQUEST_DEVICE_VENDOR_ID, + REQUEST_POWER_STATUS, + REQUEST_OSD_NAME, + }; + + enum { + REQUEST_DONE = 0, + REQUEST_NOT_DONE, + REQUEST_TIME_ELAPSED, + }; + + DeviceType m_deviceType; + LogicalAddress m_logicalAddress; + PhysicalAddress m_physicalAddr; + Version m_cecVersion; + VendorID m_vendorID; + OSDName m_osdName; + PowerStatus m_powerStatus; + bool m_isDevicePresent; + bool m_isDeviceDisconnected; + Language m_currentLanguage; + bool m_isActiveSource; + bool m_isDeviceTypeUpdated; + bool m_isPAUpdated; + bool m_isVersionUpdated; + bool m_isOSDNameUpdated; + bool m_isVendorIDUpdated; + bool m_isPowerStatusUpdated; + int m_isRequested; + int m_isRequestRetry; + std::chrono::system_clock::time_point m_requestTime; + std::vector m_featureAborts; + std::chrono::system_clock::time_point m_lastPowerUpdateTime; + + CECDeviceParams() + : m_deviceType(0), m_logicalAddress(0),m_physicalAddr(0x0f,0x0f,0x0f,0x0f),m_cecVersion(0),m_vendorID(0,0,0),m_osdName(""),m_powerStatus(0),m_currentLanguage("") + { + m_isDevicePresent = false; + m_isActiveSource = false; + m_isPAUpdated = false; + m_isVersionUpdated = false; + m_isOSDNameUpdated = false; + m_isVendorIDUpdated = false; + m_isPowerStatusUpdated = false; + m_isDeviceDisconnected = false; + m_isDeviceTypeUpdated = false; + m_isRequestRetry = 0; + } + + void clear( ) + { + m_deviceType = 0; + m_logicalAddress = 0; + m_physicalAddr = PhysicalAddress(0x0f,0x0f,0x0f,0x0f); + m_cecVersion = 0; + m_vendorID = VendorID(0,0,0); + m_osdName = ""; + m_powerStatus = 0; + m_currentLanguage = ""; + m_isDevicePresent = false; + m_isActiveSource = false; + m_isPAUpdated = false; + m_isVersionUpdated = false; + m_isOSDNameUpdated = false; + m_isVendorIDUpdated = false; + m_isPowerStatusUpdated = false; + m_isDeviceDisconnected = false; + m_isDeviceTypeUpdated = false; + } + + void printVariable() + { + LOGWARN("Device LogicalAddress %s", m_logicalAddress.toString().c_str()); + LOGWARN("Device Type %s", m_deviceType.toString().c_str()); + LOGWARN("Device Present %d", m_isDevicePresent); + LOGWARN("Active Source %d", m_isActiveSource); + LOGWARN("PA Updated %d", m_isPAUpdated); + LOGWARN("Version Updated %d", m_isVersionUpdated); + LOGWARN("OSDName Updated %d", m_isOSDNameUpdated); + LOGWARN("PowerStatus Updated %d", m_isPowerStatusUpdated); + LOGWARN("VendorID Updated %d", m_isPowerStatusUpdated); + LOGWARN("CEC Version : %s", m_cecVersion.toString().c_str()); + LOGWARN("Vendor ID : %s", m_vendorID.toString().c_str()); + LOGWARN("PhisicalAddress : %s", m_physicalAddr.toString().c_str()); + LOGWARN("OSDName : %s", m_osdName.toString().c_str()); + LOGWARN("Power Status : %s", m_powerStatus.toString().c_str()); + LOGWARN("Language : %s", m_currentLanguage.toString().c_str()); + } + + bool isAllUpdated() { + if( !m_isPAUpdated + || !m_isVersionUpdated + || !m_isOSDNameUpdated + || !m_isVendorIDUpdated + || !m_isPowerStatusUpdated + || !m_isDeviceTypeUpdated ){ + return false; + } + return true; + } + + void update( const DeviceType &deviceType ) { + m_deviceType = deviceType; + m_isDeviceTypeUpdated = true; + } + + void update( const PhysicalAddress &physical_addr ) { + m_physicalAddr = physical_addr; + m_isPAUpdated = true; + } + + void update ( const VendorID &vendorId) { + m_vendorID = vendorId; + m_isVendorIDUpdated = true; + } + + void update ( const Version &version ) { + m_cecVersion = version; + m_isVersionUpdated = true; + } + + void update ( const OSDName &osdName ) { + m_osdName = osdName; + m_isOSDNameUpdated = true; + } + + void update ( const PowerStatus &status ) { + m_powerStatus = status; + m_isPowerStatusUpdated = true; + m_lastPowerUpdateTime = std::chrono::system_clock::now(); + } + }; + + class DeviceNode { + public: + uint8_t m_childsLogicalAddr[LogicalAddress::UNREGISTERED]; + + DeviceNode() { + int i; + for (i = 0; i < LogicalAddress::UNREGISTERED; i++ ) + { + m_childsLogicalAddr[i] = LogicalAddress::UNREGISTERED; + } + } + + } ; + typedef struct sendKeyInfo + { + int logicalAddr; + int keyCode; + string UserControl; + }SendKeyInfo; + + class HdmiPortMap { + public: + uint8_t m_portID; + bool m_isConnected; + LogicalAddress m_logicalAddr; + PhysicalAddress m_physicalAddr; + DeviceNode m_deviceChain[3]; + + HdmiPortMap(uint8_t portID) : m_portID(portID), + m_logicalAddr(LogicalAddress::UNREGISTERED), + m_physicalAddr(portID+1,0,0,0) + { + m_isConnected = false; + } + + void update(bool isConnected) + { + m_isConnected = isConnected; + } + + void update( const LogicalAddress &addr ) + { + m_logicalAddr = addr; + } + + void addChild( const LogicalAddress &logical_addr, const PhysicalAddress &physical_addr ) + { + LOGINFO(" logicalAddr = %d, phisicalAddr = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); + + if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED && + m_logicalAddr.toInt() != logical_addr.toInt() ) + { + LOGINFO(" update own logicalAddr = %d, new devcie logicalAddress = %d", m_logicalAddr.toInt(), logical_addr.toInt() ); + /* check matching with this port's physical address */ + if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && + physical_addr.getByteValue(1) != 0 ) + { + if ( physical_addr.getByteValue(3) != 0 ) + { + m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = logical_addr.toInt(); + } + else if ( physical_addr.getByteValue(2) != 0 ) + { + m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = logical_addr.toInt(); + } + else if ( physical_addr.getByteValue(1) != 0 ) + { + m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = logical_addr.toInt(); + } + } + } + else if ( physical_addr == m_physicalAddr ) + { + update(logical_addr); + LOGINFO(" update own logicalAddr = %d", m_logicalAddr.toInt()); + } + } + + void removeChild( PhysicalAddress &physical_addr ) + { + if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) + { + /* check matching with this port's physical address */ + if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && + physical_addr.getByteValue(1) != 0 ) + { + if ( physical_addr.getByteValue(3) != 0 ) + { + m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = LogicalAddress::UNREGISTERED; + } + else if ( physical_addr.getByteValue(2) != 0 ) + { + m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = LogicalAddress::UNREGISTERED; + } + else if ( physical_addr.getByteValue(1) != 0 ) + { + m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = LogicalAddress::UNREGISTERED; + } + } + } + } + + void getRoute( PhysicalAddress &physical_addr, std::vector & route ) + { + LOGINFO(" logicalAddr = %d, phsical = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); + + if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) + { + LOGINFO(" search for logicalAddr = %d", m_logicalAddr.toInt()); + /* check matching with this port's physical address */ + if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && + physical_addr.getByteValue(1) != 0 ) + { + if ( physical_addr.getByteValue(3) != 0 ) + { + route.push_back(m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1]); + } + + if ( physical_addr.getByteValue(2) != 0 ) + { + route.push_back(m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1]); + } + + if ( physical_addr.getByteValue(1) != 0 ) + { + route.push_back(m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1]); + } + + route.push_back(m_logicalAddr.toInt()); + } + else + { + route.push_back(m_logicalAddr.toInt()); + LOGINFO("logicalAddr = %d, physical = %s", m_logicalAddr.toInt(), m_physicalAddr.toString().c_str()); + } + } + } + }; + + class binary_semaphore { + + public: + + explicit binary_semaphore(int init_count = count_max) + + : count_(init_count) {} + + + + // P-operation / acquire + + void wait() + + { + + std::unique_lock lk(m_); + + cv_.wait(lk, [=]{ return 0 < count_; }); + + --count_; + + } + + bool try_wait() + + { + + std::lock_guard lk(m_); + + if (0 < count_) { + + --count_; + + return true; + + } else { + + return false; + + } + + } + + // V-operation / release + + void signal() + + { + + std::lock_guard lk(m_); + + if (count_ < count_max) { + + ++count_; + + cv_.notify_one(); + + } + + } + + + + // Lockable requirements + + void acquire() { wait(); } + + bool try_lock() { return try_wait(); } + + void release() { signal(); } + + + +private: + + static const int count_max = 1; + + int count_; + + std::mutex m_; + + std::condition_variable cv_; + +}; // This is a server for a JSONRPC communication channel. // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. @@ -55,211 +484,262 @@ namespace WPEFramework { // will receive a JSONRPC message as a notification, in case this method is called. class HdmiCecSink : public PluginHost::IPlugin, public PluginHost::JSONRPC { + enum { + POLL_THREAD_STATE_NONE, + POLL_THREAD_STATE_IDLE, + POLL_THREAD_STATE_POLL, + POLL_THREAD_STATE_PING, + POLL_THREAD_STATE_INFO, + POLL_THREAD_STATE_WAIT, + POLL_THREAD_STATE_CLEAN, + POLL_THREAD_STATE_UPDATE, + POLL_THREAD_STATE_EXIT, + }; + enum { + ARC_STATE_REQUEST_ARC_INITIATION, + ARC_STATE_ARC_INITIATED, + ARC_STATE_REQUEST_ARC_TERMINATION, + ARC_STATE_ARC_TERMINATED, + ARC_STATE_ARC_EXIT + }; + enum { + VOLUME_UP = 0x41, + VOLUME_DOWN = 0x42, + MUTE = 0x43, + UP = 0x01, + DOWN = 0x02, + LEFT = 0x03, + RIGHT = 0x04, + SELECT = 0x00, + HOME = 0x09, + BACK = 0x0D, + NUMBER_0 = 0x20, + NUMBER_1 = 0x21, + NUMBER_2 = 0x22, + NUMBER_3 = 0x23, + NUMBER_4 = 0x24, + NUMBER_5 = 0x25, + NUMBER_6 = 0x26, + NUMBER_7 = 0x27, + NUMBER_8 = 0x28, + NUMBER_9 = 0x29 + }; + public: + HdmiCecSink(); + virtual ~HdmiCecSink(); + virtual const string Initialize(PluginHost::IShell* shell) override; + virtual void Deinitialize(PluginHost::IShell* service) override; + virtual string Information() const override { return {}; } + static HdmiCecSink* _instance; + CECDeviceParams deviceList[16]; + std::vector hdmiInputs; + int m_currentActiveSource; + void updateInActiveSource(const int logical_address, const InActiveSource &source ); + void updateActiveSource(const int logical_address, const ActiveSource &source ); + void updateTextViewOn(const int logicalAddress); + void updateImageViewOn(const int logicalAddress); + void updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr); + void getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route); + void removeDevice(const int logicalAddress); + void addDevice(const int logicalAddress); + void printDeviceList(); + void setStreamPath( const PhysicalAddress &physical_addr); + void setRoutingChange(const std::string &from, const std::string &to); + void sendStandbyMessage(); + void setCurrentLanguage(const Language &lang); + void sendMenuLanguage(); + void setActiveSource(bool isResponse); + void requestActiveSource(); + void startArc(); + void stopArc(); + void Process_InitiateArc(); + void Process_TerminateArc(); + void updateArcState(); + void requestShortaudioDescriptor(); + void Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor); + void Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg); + void Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg); + void sendDeviceUpdateInfo(const int logicalAddress); + void sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); + void reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); + void systemAudioModeRequest(); + void SendStandbyMsgEvent(const int logicalAddress); + void requestAudioDevicePowerStatus(); + void reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus); + void updateCurrentLatency(int videoLatency, bool lowLatencyMode, int audioOutputCompensated, int audioOutputDelay); + void setLatencyInfo(); + void Process_ReportAudioStatus_msg(const ReportAudioStatus msg); + void sendKeyPressEvent(const int logicalAddress, int keyCode); + void sendKeyReleaseEvent(const int logicalAddress); + void sendUserControlPressed(const int logicalAddress, int keyCode); + void sendUserControlReleased(const int logicalAddress); + void onPowerModeChanged(const PowerState currentState, const PowerState newState); + void registerEventHandlers(); + void sendGiveAudioStatusMsg(); + void getHdmiArcPortID(); + int m_numberOfDevices; /* Number of connected devices othethan own device */ + bool m_audioDevicePowerStatusRequested; + + BEGIN_INTERFACE_MAP(HdmiCecSink) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + END_INTERFACE_MAP + + private: + class PowerManagerNotification : public Exchange::IPowerManager::IModeChangedNotification { private: - class Notification : public RPC::IRemoteConnection::INotification, - public Exchange::IHdmiCecSink::INotification - { - private: - Notification() = delete; - Notification(const Notification&) = delete; - Notification& operator=(const Notification&) = delete; - - public: - explicit Notification(HdmiCecSink* parent) - : _parent(*parent) - { - ASSERT(parent != nullptr); - } - - virtual ~Notification() - { - } - - BEGIN_INTERFACE_MAP(Notification) - INTERFACE_ENTRY(Exchange::IHdmiCecSink::INotification) - INTERFACE_ENTRY(RPC::IRemoteConnection::INotification) - END_INTERFACE_MAP - - void Activated(RPC::IRemoteConnection*) override - { - } - - void Deactivated(RPC::IRemoteConnection *connection) override - { - _parent.Deactivated(connection); - } - - void ArcInitiationEvent(const string success) override - { - LOGINFO("ArcInitiationEvent"); - LOGINFO("success: %s", success.c_str()); - Exchange::JHdmiCecSink::Event::ArcInitiationEvent(_parent, success); - } - - void ArcTerminationEvent(const string success) override - { - LOGINFO("ArcTerminationEvent"); - LOGINFO("success: %s", success.c_str()); - Exchange::JHdmiCecSink::Event::ArcTerminationEvent(_parent, success); - } - - void OnActiveSourceChange(const int logicalAddress, const string physicalAddress) override - { - LOGINFO("OnActiveSourceChange"); - LOGINFO("logicalAddress: %d, physicalAddress: %s", logicalAddress, physicalAddress.c_str()); - Exchange::JHdmiCecSink::Event::OnActiveSourceChange(_parent, logicalAddress, physicalAddress); - } - - void OnDeviceAdded(const int logicalAddress) override - { - LOGINFO("OnDeviceAdded"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnDeviceAdded(_parent, logicalAddress); - } - - void OnDeviceInfoUpdated(const int logicalAddress) override - { - LOGINFO("OnDeviceInfoUpdated"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnDeviceInfoUpdated(_parent, logicalAddress); - } - - void OnDeviceRemoved(const int logicalAddress) override - { - LOGINFO("OnDeviceRemoved"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnDeviceRemoved(_parent, logicalAddress); - } - - void OnImageViewOnMsg(const int logicalAddress) override - { - LOGINFO("OnImageViewOnMsg"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnImageViewOnMsg(_parent, logicalAddress); - } - - void OnInActiveSource(const int logicalAddress, const string physicalAddress) override - { - LOGINFO("OnInActiveSource"); - LOGINFO("logicalAddress: %d, physicalAddress: %s", logicalAddress, physicalAddress.c_str()); - Exchange::JHdmiCecSink::Event::OnInActiveSource(_parent, logicalAddress, physicalAddress); - } - - void OnTextViewOnMsg(const int logicalAddress) override - { - LOGINFO("OnTextViewOnMsg"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnTextViewOnMsg(_parent, logicalAddress); - } - - void OnWakeupFromStandby(const int logicalAddress) override - { - LOGINFO("OnWakeupFromStandby"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnWakeupFromStandby(_parent, logicalAddress); - } - - void ReportAudioDeviceConnectedStatus(const string status, const string audioDeviceConnected) override - { - LOGINFO("ReportAudioDeviceConnectedStatus"); - LOGINFO("status: %s, audioDeviceConnected: %s", status.c_str(), audioDeviceConnected.c_str()); - Exchange::JHdmiCecSink::Event::ReportAudioDeviceConnectedStatus(_parent, status, audioDeviceConnected); - } - - void ReportAudioStatusEvent(const int muteStatus, const int volumeLevel) override - { - LOGINFO("ReportAudioStatusEvent"); - LOGINFO("muteStatus: %d, volumeLevel: %d", muteStatus, volumeLevel); - Exchange::JHdmiCecSink::Event::ReportAudioStatusEvent(_parent, muteStatus, volumeLevel); - } - - void ReportFeatureAbortEvent(const int logicalAddress, const int opcode, const int FeatureAbortReason) override - { - LOGINFO("ReportFeatureAbortEvent"); - LOGINFO("logicalAddress: %d, opcode: %d, FeatureAbortReason: %d", logicalAddress, opcode, FeatureAbortReason); - Exchange::JHdmiCecSink::Event::ReportFeatureAbortEvent(_parent, logicalAddress, opcode, FeatureAbortReason); - } - - void ReportCecEnabledEvent(const string cecEnable) override - { - LOGINFO("ReportCecEnabledEvent"); - LOGINFO("cecEnable: %s", cecEnable.c_str()); - Exchange::JHdmiCecSink::Event::ReportCecEnabledEvent(_parent, cecEnable); - } - - void SetSystemAudioModeEvent(const string audioMode) override - { - LOGINFO("SetSystemAudioModeEvent"); - LOGINFO("audioMode: %s", audioMode.c_str()); - Exchange::JHdmiCecSink::Event::SetSystemAudioModeEvent(_parent, audioMode); - } - - void ShortAudiodescriptorEvent(const string& jsonresponse) override - { - LOGINFO("ShortAudiodescriptorEvent"); - Exchange::JHdmiCecSink::Event::ShortAudiodescriptorEvent(_parent, jsonresponse); - } - - void StandbyMessageReceived(const int logicalAddress) override - { - LOGINFO("StandbyMessageReceived"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::StandbyMessageReceived(_parent, logicalAddress); - } - - void ReportAudioDevicePowerStatus(const int powerStatus) override - { - LOGINFO("ReportAudioDevicePowerStatus"); - LOGINFO("powerStatus: %d", powerStatus); - Exchange::JHdmiCecSink::Event::ReportAudioDevicePowerStatus(_parent, powerStatus); - } - - private: - HdmiCecSink &_parent; - - }; + PowerManagerNotification(const PowerManagerNotification&) = delete; + PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; public: - // We do not allow this plugin to be copied !! - HdmiCecSink(const HdmiCecSink&) = delete; - HdmiCecSink& operator=(const HdmiCecSink&) = delete; - - HdmiCecSink() - : PluginHost::IPlugin() - , PluginHost::JSONRPC() - , _service(nullptr) - , _notification(this) - , _hdmiCecSink(nullptr) - , _connectionId(0) + explicit PowerManagerNotification(HdmiCecSink& parent) + : _parent(parent) { - } - virtual ~HdmiCecSink() - { + ~PowerManagerNotification() override = default; + public: + void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override + { + _parent.onPowerModeChanged(currentState, newState); } - BEGIN_INTERFACE_MAP(HdmiCecSink) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - INTERFACE_AGGREGATE(Exchange::IHdmiCecSink, _hdmiCecSink) + template + T* baseInterface() + { + static_assert(std::is_base_of(), "base type mismatch"); + return static_cast(this); + } + + BEGIN_INTERFACE_MAP(PowerManagerNotification) + INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) END_INTERFACE_MAP - // IPlugin methods - // ------------------------------------------------------------------------------------------------------- - const string Initialize(PluginHost::IShell* service) override; - void Deinitialize(PluginHost::IShell* service) override; - string Information() const override; - //Begin methods - - private: - void Deactivated(RPC::IRemoteConnection* connection); - private: - PluginHost::IShell* _service{}; - Core::Sink _notification; - Exchange::IHdmiCecSink* _hdmiCecSink; - uint32_t _connectionId; + HdmiCecSink& _parent; + }; + // We do not allow this plugin to be copied !! + HdmiCecSink(const HdmiCecSink&) = delete; + HdmiCecSink& operator=(const HdmiCecSink&) = delete; + + //Begin methods + uint32_t setEnabledWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getEnabledWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setOSDNameWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getOSDNameWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setVendorIdWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getVendorIdWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t printDeviceListWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setActivePathWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setRoutingChangeWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getDeviceListWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getActiveSourceWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setActiveSourceWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getActiveRouteWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t requestActiveSourceWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setArcEnableDisableWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setMenuLanguageWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t requestShortAudioDescriptorWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendAudioDevicePowerOnMsgWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendRemoteKeyPressWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendUserControlPressedWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendUserControlReleasedWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendGiveAudioStatusWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getAudioDeviceConnectedStatusWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t requestAudioDevicePowerStatusWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setLatencyInfoWrapper(const JsonObject& parameters, JsonObject& response); + void InitializePowerManager(PluginHost::IShell *service); + //End methods + std::string logicalAddressDeviceType; + bool cecSettingEnabled; + bool cecOTPSettingEnabled; + bool cecEnableStatus; + bool hdmiCecAudioDeviceConnected; + bool m_isHdmiInConnected; + int m_numofHdmiInput; + uint8_t m_deviceType; + int m_logicalAddressAllocated; + std::thread m_pollThread; + uint32_t m_pollThreadState; + uint32_t m_pollNextState; + bool m_pollThreadExit; + uint32_t m_sleepTime; + std::mutex m_pollExitMutex; + std::mutex m_enableMutex; + /* Send Key event related */ + bool m_sendKeyEventThreadExit; + bool m_sendKeyEventThreadRun; + bool m_isAudioStatusInfoUpdated; + bool m_audioStatusReceived; + bool m_audioStatusTimerStarted; + std::thread m_sendKeyEventThread; + std::mutex m_sendKeyEventMutex; + std::queue m_SendKeyQueue; + std::condition_variable m_sendKeyCV; + std::condition_variable m_ThreadExitCV; + + /* DALS - Latency Values */ + uint8_t m_video_latency; + uint8_t m_latency_flags; + uint8_t m_audio_output_delay; + + /* ARC related */ + std::thread m_arcRoutingThread; + uint32_t m_currentArcRoutingState; + std::mutex m_arcRoutingStateMutex; + binary_semaphore m_semSignaltoArcRoutingThread; + bool m_arcstarting; + TpTimer m_arcStartStopTimer; + TpTimer m_audioStatusDetectionTimer; + + Connection *smConnection; + std::vector m_connectedDevices; + HdmiCecSinkProcessor *msgProcessor; + HdmiCecSinkFrameListener *msgFrameListener; + PowerManagerInterfaceRef _powerManagerPlugin; + Core::Sink _pwrMgrNotification; + bool _registeredEventHandlers; + const void InitializeIARM(); + void DeinitializeIARM(); + void allocateLogicalAddress(int deviceType); + void allocateLAforTV(); + void pingDevices(std::vector &connected , std::vector &disconnected); + void CheckHdmiInState(); + void request(const int logicalAddress); + int requestType(const int logicalAddress); + int requestStatus(const int logicalAddress); + static void threadRun(); + void cecMonitoringThread(); + static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + void onHdmiHotPlug(int portId, int connectStatus); + bool loadSettings(); + void persistSettings(bool enableStatus); + void persistOTPSettings(bool enableStatus); + void persistOSDName(const char *name); + void persistVendorId(unsigned int vendorID); + void setEnabled(bool enabled); + bool getEnabled(); + bool getAudioDeviceConnectedStatus(); + void CECEnable(void); + void CECDisable(void); + void getPhysicalAddress(); + void getLogicalAddress(); + void cecAddressesChanged(int changeStatus); + + // Arc functions + + static void threadSendKeyEvent(); + static void threadArcRouting(); + void requestArcInitiation(); + void requestArcTermination(); + void Send_Request_Arc_Initiation_Message(); + void Send_Report_Arc_Initiated_Message(); + void Send_Request_Arc_Termination_Message(); + void Send_Report_Arc_Terminated_Message(); + void arcStartStopTimerFunction(); + void audioStatusTimerFunction(); + void getCecVersion(); }; } // namespace Plugin } // namespace WPEFramework diff --git a/HdmiCecSink/HdmiCecSinkImplementation.cpp b/HdmiCecSink/HdmiCecSinkImplementation.cpp deleted file mode 100644 index 7363bb76..00000000 --- a/HdmiCecSink/HdmiCecSinkImplementation.cpp +++ /dev/null @@ -1,3581 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 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. -**/ - -#include "HdmiCecSinkImplementation.h" - -#include "ccec/Connection.hpp" -#include "ccec/CECFrame.hpp" -#include "ccec/MessageEncoder.hpp" -#include "host.hpp" -#include "UtilsgetRFCConfig.h" - -#include "dsMgr.h" -#include "dsRpc.h" -#include "dsDisplay.h" -#include "videoOutputPort.hpp" -#include "manager.hpp" -#include "websocket/URL.h" - -#include "UtilsIarm.h" -#include "UtilsJsonRpc.h" -#include "UtilssyncPersistFile.h" -#include "UtilsSearchRDKProfile.h" - -#define TEST_ADD 0 -#define HDMICECSINK_REQUEST_MAX_RETRY 3 -#define HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS 2000 -#define HDMICECSINK_PING_INTERVAL_MS 10000 -#define HDMICECSINK_WAIT_FOR_HDMI_IN_MS 1000 -#define HDMICECSINK_REQUEST_INTERVAL_TIME_MS 500 -#define HDMICECSINK_NUMBER_TV_ADDR 2 -#define HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS (60 * 1000) -#define HDMISINK_ARC_START_STOP_MAX_WAIT_MS 4000 -#define HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS 500 - - -#define SAD_FMT_CODE_AC3 2 -#define SAD_FMT_CODE_ENHANCED_AC3 10 - -#define SYSTEM_AUDIO_MODE_ON 0x01 -#define SYSTEM_AUDIO_MODE_OFF 0x00 -#define AUDIO_DEVICE_POWERSTATE_OFF 1 - -#define DEFAULT_VIDEO_LATENCY 100 -#define DEFAULT_LATENCY_FLAGS 3 -#define DEFAULT_AUDIO_OUTPUT_DELAY 100 - -//Device Type is TV - Bit 7 is set to 1 -#define ALL_DEVICE_TYPES 128 - -//RC Profile of TV is 3 - Typical TV Remote -#define RC_PROFILE_TV 10 - -//Device Features supported by TV - ARC Tx -#define DEVICE_FEATURES_TV 4 - -#define TR181_HDMICECSINK_CEC_VERSION "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.HdmiCecSink.CECVersion" - - -#define CEC_SETTING_ENABLED_FILE "/opt/persistent/ds/cecData_2.json" -#define CEC_SETTING_OTP_ENABLED "cecOTPEnabled" -#define CEC_SETTING_ENABLED "cecEnabled" -#define CEC_SETTING_OSD_NAME "cecOSDName" -#define CEC_SETTING_VENDOR_ID "cecVendorId" - -enum { - DEVICE_POWER_STATE_ON = 0, - DEVICE_POWER_STATE_OFF = 1 -}; - -static std::vector defaultVendorId = {0x00,0x19,0xFB}; -static VendorID appVendorId = {defaultVendorId.at(0),defaultVendorId.at(1),defaultVendorId.at(2)}; -static VendorID lgVendorId = {0x00,0xE0,0x91}; -static PhysicalAddress physical_addr = {0x0F,0x0F,0x0F,0x0F}; -static LogicalAddress logicalAddress = 0xF; -static Language defaultLanguage = "eng"; -static OSDName osdName = "TV Box"; -static int32_t powerState = DEVICE_POWER_STATE_OFF; -static std::vector formatid = {0,0}; -static std::vector audioFormatCode = { SAD_FMT_CODE_ENHANCED_AC3,SAD_FMT_CODE_AC3 }; -static uint8_t numberofdescriptor = 2; -static int32_t HdmiArcPortID = -1; -static float cecVersion = 1.4; -static AllDeviceTypes allDevicetype = ALL_DEVICE_TYPES; -static std::vector rcProfile = {RC_PROFILE_TV}; -static std::vector deviceFeatures = {DEVICE_FEATURES_TV}; - -#define API_VERSION_NUMBER_MAJOR 1 -#define API_VERSION_NUMBER_MINOR 3 -#define API_VERSION_NUMBER_PATCH 7 - -using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; - -namespace WPEFramework -{ - - namespace Plugin - { - SERVICE_REGISTRATION(HdmiCecSinkImplementation, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - - HdmiCecSinkImplementation* HdmiCecSinkImplementation::_instance = nullptr; - static int libcecInitStatus = 0; - -//=========================================== HdmiCecSinkFrameListener ========================================= - void HdmiCecSinkFrameListener::notify(const CECFrame &in) const { - const uint8_t *buf = NULL; - char strBuffer[512] = {0}; - size_t len = 0; - - in.getBuffer(&buf, &len); - for (unsigned int i = 0; i < len; i++) { - snprintf(strBuffer + (i*3) , sizeof(strBuffer) - (i*3), "%02X ",(uint8_t) *(buf + i)); - } - LOGINFO(" >>>>> Received CEC Frame: :%s \n",strBuffer); - - MessageDecoder(processor).decode(in); - } - -//=========================================== HdmiCecSinkProcessor ========================================= - void HdmiCecSinkProcessor::process (const ActiveSource &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - HdmiCecSinkImplementation::_instance->updateActiveSource(header.from.toInt(), msg); - } - void HdmiCecSinkProcessor::process (const InActiveSource &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: InActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - - HdmiCecSinkImplementation::_instance->updateInActiveSource(header.from.toInt(), msg); - } - - void HdmiCecSinkProcessor::process (const ImageViewOn &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ImageViewOn from %s\n", header.from.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - HdmiCecSinkImplementation::_instance->updateImageViewOn(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const TextViewOn &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: TextViewOn\n"); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - HdmiCecSinkImplementation::_instance->updateTextViewOn(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const RequestActiveSourceMessage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RequestActiveSource\n"); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - - HdmiCecSinkImplementation::_instance->setActiveSource(true); - } - void HdmiCecSinkProcessor::process (const Standby &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Standby from %s\n", header.from.toString().c_str()); - HdmiCecSinkImplementation::_instance->SendStandbyMsgEvent(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const GetCECVersion &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GetCECVersion sending CECVersion response \n"); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - if(cecVersion == 2.0) { - conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_2_0))); - } - else{ - conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_1_4))); - } - } - catch(...) - { - LOGWARN("Exception while sending CECVersion "); - } - } - void HdmiCecSinkProcessor::process (const CECVersion &msg, const Header &header) - { - bool updateStatus; - printHeader(header); - LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); - - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - updateStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isVersionUpdated; - LOGINFO("updateStatus %d\n",updateStatus); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.version); - if(!updateStatus) - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const SetMenuLanguageMessage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const GiveOSDName &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveOSDName sending SetOSDName : %s\n",osdName.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - conn.sendToAsync(header.from, MessageEncoder().encode(SetOSDName(osdName))); - } - catch(...) - { - LOGWARN("Exception while sending SetOSDName"); - } - } - void HdmiCecSinkProcessor::process (const GivePhysicalAddress &msg, const Header &header) - { - LOGINFO("Command: GivePhysicalAddress\n"); - if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) - { - try - { - LOGINFO(" sending ReportPhysicalAddress response physical_addr :%s logicalAddress :%x \n",physical_addr.toString().c_str(), logicalAddress.toInt()); - conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ReportPhysicalAddress(physical_addr,logicalAddress.toInt())), 500); - } - catch(...) - { - LOGWARN("Exception while sending ReportPhysicalAddress "); - } - } - } - void HdmiCecSinkProcessor::process (const GiveDeviceVendorID &msg, const Header &header) - { - printHeader(header); - if(header.to == LogicalAddress(LogicalAddress::BROADCAST)){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n",appVendorId.toString().c_str()); - conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); - } - catch(...) - { - LOGWARN("Exception while sending DeviceVendorID"); - } - - } - void HdmiCecSinkProcessor::process (const SetOSDString &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetOSDString OSDString : %s\n",msg.osdString.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const SetOSDName &msg, const Header &header) - { - printHeader(header); - bool updateStatus ; - LOGINFO("Command: SetOSDName OSDName : %s\n",msg.osdName.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - updateStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isOSDNameUpdated; - LOGINFO("updateStatus %d\n",updateStatus); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.osdName); - if(HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_OSD_NAME) { - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; - } - if(!updateStatus) - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const RoutingChange &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RoutingChange From : %s To: %s \n",msg.from.toString().c_str(),msg.to.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const RoutingInformation &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RoutingInformation Routing Information to Sink : %s\n",msg.toSink.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const SetStreamPath &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetStreamPath Set Stream Path to Sink : %s\n",msg.toSink.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const GetMenuLanguage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GetMenuLanguage\n"); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSinkImplementation::_instance->sendMenuLanguage(); - } - void HdmiCecSinkProcessor::process (const ReportPhysicalAddress &msg, const Header &header) - { - printHeader(header); - bool updateDeviceTypeStatus; - bool updatePAStatus; - LOGINFO("Command: ReportPhysicalAddress\n"); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - - if(!HdmiCecSinkImplementation::_instance) - return; - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - updateDeviceTypeStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isDeviceTypeUpdated; - updatePAStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isPAUpdated; - LOGINFO("updateDeviceTypeStatus %d updatePAStatus %d \n",updateDeviceTypeStatus,updatePAStatus); - if(HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString() != msg.physicalAddress.toString() && updatePAStatus){ - updatePAStatus= false; - LOGINFO("There is a change in physical address from current PA %s to newly reported PA %s\n",HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString().c_str(),msg.physicalAddress.toString().c_str()); - } - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.physicalAddress); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.deviceType); - if(HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_PHISICAL_ADDRESS) { - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; - } - HdmiCecSinkImplementation::_instance->updateDeviceChain(header.from, msg.physicalAddress); - if (!updateDeviceTypeStatus || !updatePAStatus) - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const DeviceVendorID &msg, const Header &header) - { - bool updateStatus ; - printHeader(header); - LOGINFO("Command: DeviceVendorID VendorID : %s\n",msg.vendorId.toString().c_str()); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - updateStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isVendorIDUpdated; - LOGINFO("updateStatus %d\n",updateStatus); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.vendorId); - if (!updateStatus) - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const GiveDevicePowerStatus &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveDevicePowerStatus sending powerState :%d \n",powerState); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - conn.sendTo(header.from, MessageEncoder().encode(ReportPowerStatus(PowerStatus(powerState)))); - } - catch(...) - { - LOGWARN("Exception while sending ReportPowerStatus"); - } - } - void HdmiCecSinkProcessor::process (const ReportPowerStatus &msg, const Header &header) - { - uint32_t oldPowerStatus,newPowerStatus; - printHeader(header); - LOGINFO("Command: ReportPowerStatus Power Status from:%s status : %s \n",header.from.toString().c_str(),msg.status.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - oldPowerStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.status); - newPowerStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); - LOGINFO(" oldPowerStatus %d newpower status %d \n",oldPowerStatus,newPowerStatus); - if ((oldPowerStatus != newPowerStatus) ) - { - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - - if((header.from.toInt() == LogicalAddress::AUDIO_SYSTEM) && (HdmiCecSinkImplementation::_instance->m_audioDevicePowerStatusRequested)) { - HdmiCecSinkImplementation::_instance->reportAudioDevicePowerStatusInfo(header.from.toInt(), newPowerStatus); - } - - } - void HdmiCecSinkProcessor::process (const FeatureAbort &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: FeatureAbort opcode=%s, Reason = %s\n", msg.feature.toString().c_str(), msg.reason.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - - if(header.from.toInt() < LogicalAddress::UNREGISTERED && - msg.reason.toInt() == AbortReason::UNRECOGNIZED_OPCODE) - { - switch(msg.feature.opCode()) - { - case GET_CEC_VERSION : - { - /* If we get a Feature abort for CEC Version then default to 1.4b */ - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(Version(Version::V_1_4)); - } - break; - case GIVE_DEVICE_VENDOR_ID : - { - /* If we get a Feature abort for CEC Version then default to 1.4b */ - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(VendorID((uint8_t *)"FA", 2)); - } - break; - - case GIVE_OSD_NAME : - { - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(OSDName("")); - } - break; - - case GIVE_DEVICE_POWER_STATUS : - { - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(PowerStatus(PowerStatus::POWER_STATUS_FEATURE_ABORT)); - } - break; - } - - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_featureAborts.push_back(msg); - } - - LogicalAddress logicaladdress = header.from.toInt(); - OpCode featureOpcode = msg.feature; - AbortReason abortReason = msg.reason; - - HdmiCecSinkImplementation::_instance->reportFeatureAbortEvent(logicaladdress,featureOpcode,abortReason); - - if(msg.feature.opCode() == REQUEST_SHORT_AUDIO_DESCRIPTOR) - { - JsonArray audiodescriptor; - audiodescriptor.Add(0); - HdmiCecSinkImplementation::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); - } - - } - void HdmiCecSinkProcessor::process (const Abort &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Abort\n"); - if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) - { - AbortReason reason = AbortReason::UNRECOGNIZED_OPCODE; - LogicalAddress logicaladdress =header.from.toInt(); - OpCode feature = msg.opCode(); - HdmiCecSinkImplementation::_instance->sendFeatureAbort(logicaladdress, feature,reason); - } - else - { - LOGINFO("Command: Abort broadcast msg so ignore\n"); - } - } - void HdmiCecSinkProcessor::process (const Polling &msg, const Header &header) { - printHeader(header); - LOGINFO("Command: Polling\n"); - } - - void HdmiCecSinkProcessor::process (const InitiateArc &msg, const Header &header) - { - printHeader(header); - if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ - LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); - return; - } - PhysicalAddress physical_addr_invalid = {0x0F,0x0F,0x0F,0x0F}; - PhysicalAddress physical_addr_arc_port = {0x0F,0x0F,0x0F,0x0F}; - - LOGINFO("Command: INITIATE_ARC \n"); - if(!HdmiCecSinkImplementation::_instance || HdmiArcPortID == -1) - return; - - if (HdmiArcPortID == 0 ) - physical_addr_arc_port = {0x01,0x00,0x00,0x00}; - if (HdmiArcPortID == 1 ) - physical_addr_arc_port = {0x02,0x00,0x00,0x00}; - if (HdmiArcPortID == 2 ) - physical_addr_arc_port = {0x03,0x00,0x00,0x00}; - - if( (HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_arc_port.toString()) || (HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_invalid.toString()) ) { - LOGINFO("Command: INITIATE_ARC InitiateArc success %s \n",HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); - HdmiCecSinkImplementation::_instance->Process_InitiateArc(); - } else { - LOGINFO("Command: INITIATE_ARC InitiateArc ignore %s \n",HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); - } - } - void HdmiCecSinkProcessor::process (const TerminateArc &msg, const Header &header) - { - printHeader(header); - if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ - LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); - return; - } - if(!HdmiCecSinkImplementation::_instance) - return; - HdmiCecSinkImplementation::_instance->Process_TerminateArc(); - } - void HdmiCecSinkProcessor::process (const ReportShortAudioDescriptor &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ReportShortAudioDescriptor %s : %d \n",GetOpName(msg.opCode()),numberofdescriptor); - HdmiCecSinkImplementation::_instance->Process_ShortAudioDescriptor_msg(msg); - } - - void HdmiCecSinkProcessor::process (const SetSystemAudioMode &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetSystemAudioMode %s audio status %d audio status is %s \n",GetOpName(msg.opCode()),msg.status.toInt(),msg.status.toString().c_str()); - HdmiCecSinkImplementation::_instance->Process_SetSystemAudioMode_msg(msg); - } - void HdmiCecSinkProcessor::process (const ReportAudioStatus &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSinkImplementation::_instance->Process_ReportAudioStatus_msg(msg); - } - void HdmiCecSinkProcessor::process (const GiveFeatures &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveFeatures \n"); - try - { - if(cecVersion == 2.0) { - conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST),MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures))); - } - } - catch(...) - { - LOGWARN("Exception while sending ReportFeatures"); - } - } - void HdmiCecSinkProcessor::process (const RequestCurrentLatency &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Request Current Latency :%s, physical address: %s",GetOpName(msg.opCode()),msg.physicaladdress.toString().c_str()); - - if(msg.physicaladdress.toString() == physical_addr.toString()) { - HdmiCecSinkImplementation::_instance->setLatencyInfo(); - } - else { - LOGINFO("Physical Address does not match with TV's physical address"); - return; - } - } -//=========================================== HdmiCecSinkImplementation ========================================= - - HdmiCecSinkImplementation::HdmiCecSinkImplementation() - : _pwrMgrNotification(*this) - , _registeredEventHandlers(false) - { - LOGWARN("Initlaizing HdmiCecSinkImplementation"); - } - - HdmiCecSinkImplementation::~HdmiCecSinkImplementation() - { - if(_powerManagerPlugin) - { - _powerManagerPlugin->Unregister(_pwrMgrNotification.baseInterface()); - _powerManagerPlugin.Reset(); - } - _registeredEventHandlers = false; - - profileType = searchRdkProfile(); - - if (profileType == STB || profileType == NOT_FOUND) - { - LOGINFO("Invalid profile type for TV \n"); - return ; - } - - CECDisable(); - m_currentArcRoutingState = ARC_STATE_ARC_EXIT; - - m_semSignaltoArcRoutingThread.release(); - - try - { - if (m_arcRoutingThread.joinable()) - m_arcRoutingThread.join(); - } - catch(const std::system_error& e) - { - LOGERR("system_error exception in thread join %s", e.what()); - } - catch(const std::exception& e) - { - LOGERR("exception in thread join %s", e.what()); - } - - { - m_sendKeyEventThreadExit = true; - std::unique_lock lk(m_sendKeyEventMutex); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - } - - try - { - if (m_sendKeyEventThread.joinable()) - m_sendKeyEventThread.join(); - } - catch(const std::system_error& e) - { - LOGERR("system_error exception in thread join %s", e.what()); - } - catch(const std::exception& e) - { - LOGERR("exception in thread join %s", e.what()); - } - - HdmiCecSinkImplementation::_instance = nullptr; - DeinitializeIARM(); - } - - Core::hresult HdmiCecSinkImplementation::Configure(PluginHost::IShell *service) - { - InitializePowerManager(service); - profileType = searchRdkProfile(); - - HdmiCecSinkImplementation::_instance = this; - smConnection=NULL; - cecEnableStatus = false; - HdmiCecSinkImplementation::_instance->m_numberOfDevices = 0; - m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; - m_currentActiveSource = -1; - m_isHdmiInConnected = false; - hdmiCecAudioDeviceConnected = false; - m_isAudioStatusInfoUpdated = false; - m_audioStatusReceived = false; - m_audioStatusTimerStarted = false; - m_audioDevicePowerStatusRequested = false; - m_pollNextState = POLL_THREAD_STATE_NONE; - m_pollThreadState = POLL_THREAD_STATE_NONE; - m_video_latency = DEFAULT_VIDEO_LATENCY; - m_latency_flags = DEFAULT_LATENCY_FLAGS ; - m_audio_output_delay = DEFAULT_AUDIO_OUTPUT_DELAY; - - logicalAddressDeviceType = "None"; - logicalAddress = 0xFF; - // load persistence setting - loadSettings(); - - int err; - dsHdmiInGetNumberOfInputsParam_t hdmiInput; - InitializeIARM(); - m_sendKeyEventThreadExit = false; - m_sendKeyEventThread = std::thread(threadSendKeyEvent); - - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - m_semSignaltoArcRoutingThread.acquire(); - m_arcRoutingThread = std::thread(threadArcRouting); - - m_audioStatusDetectionTimer.connect( std::bind( &HdmiCecSinkImplementation::audioStatusTimerFunction, this ) ); - m_audioStatusDetectionTimer.setSingleShot(true); - m_arcStartStopTimer.connect( std::bind( &HdmiCecSinkImplementation::arcStartStopTimerFunction, this ) ); - m_arcStartStopTimer.setSingleShot(true); - - // get power state: - uint32_t res = Core::ERROR_GENERAL; - PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - - ASSERT (_powerManagerPlugin); - if (_powerManagerPlugin) { - res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); - if (Core::ERROR_NONE == res) { - powerState = (pwrStateCur == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) ? DEVICE_POWER_STATE_ON : DEVICE_POWER_STATE_OFF; - LOGINFO("Current state is PowerManagerPlugin: (%d) powerState :%d \n", pwrStateCur, powerState); - } - } - - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - IARM_BUS_DSMGR_API_dsHdmiInGetNumberOfInputs, - (void *)&hdmiInput, - sizeof(hdmiInput)); - - if (err == IARM_RESULT_SUCCESS && hdmiInput.result == dsERR_NONE) - { - LOGINFO("Number of Inputs [%d] \n", hdmiInput.numHdmiInputs ); - m_numofHdmiInput = hdmiInput.numHdmiInputs; - }else{ - LOGINFO("Not able to get Numebr of inputs so defaulting to 3 \n"); - m_numofHdmiInput = 3; - } - - LOGINFO("initalize inputs \n"); - - for (int i = 0; i < m_numofHdmiInput; i++){ - HdmiPortMap hdmiPort((uint8_t)i); - LOGINFO(" Add to vector [%d] \n", i); - hdmiInputs.push_back(hdmiPort); - } - - LOGINFO("Check the HDMI State \n"); - - CheckHdmiInState(); - if (cecSettingEnabled) - { - try - { - CECEnable(); - } - catch(...) - { - LOGWARN("Exception while enabling CEC settings .\r\n"); - } - } - getCecVersion(); - LOGINFO(" HdmiCecSinkImplementation plugin Initialize completed \n"); - return Core::ERROR_NONE; - - } - - Core::hresult HdmiCecSinkImplementation::Register(Exchange::IHdmiCecSink::INotification* notification) - { - LOGINFO("Register"); - if(notification != nullptr){ - _adminLock.Lock(); - if(std::find(_hdmiCecSinkNotifications.begin(), _hdmiCecSinkNotifications.end(), notification) == _hdmiCecSinkNotifications.end()) - { - _hdmiCecSinkNotifications.push_back(notification); - notification->AddRef(); - } - else - { - LOGERR("Same notification is registered already"); - } - _adminLock.Unlock(); - } - - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::Unregister(Exchange::IHdmiCecSink::INotification* notification) - { - LOGINFO("Unregister"); - if(notification != nullptr){ - _adminLock.Lock(); - std::list::iterator index = std::find(_hdmiCecSinkNotifications.begin(), _hdmiCecSinkNotifications.end(), notification); - if(index != _hdmiCecSinkNotifications.end()) - { - (*index)->Release(); - _hdmiCecSinkNotifications.erase(index); - } - else - { - LOGERR("Notification is not registered"); - } - _adminLock.Unlock(); - } - - return Core::ERROR_NONE; - } - - - const void HdmiCecSinkImplementation::InitializeIARM() - { - if (Utils::IARM::init()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); - } - } - - void HdmiCecSinkImplementation::DeinitializeIARM() - { - if (Utils::IARM::isConnected()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); - } - } - - void HdmiCecSinkImplementation::InitializePowerManager(PluginHost::IShell *service) - { - _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) - .withIShell(service) - .withRetryIntervalMS(200) - .withRetryCount(25) - .createInterface(); - registerEventHandlers(); - } - void HdmiCecSinkImplementation::registerEventHandlers() - { - ASSERT (_powerManagerPlugin); - - if(!_registeredEventHandlers && _powerManagerPlugin) { - _registeredEventHandlers = true; - _powerManagerPlugin->Register(_pwrMgrNotification.baseInterface()); - } - } - - void HdmiCecSinkImplementation::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - bool isHdmiConnected = eventData->data.hdmi_in_connect.isPortConnected; - dsHdmiInPort_t portId = eventData->data.hdmi_in_connect.port; - LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG event port: %d data:%d \r\n",portId, isHdmiConnected); - HdmiCecSinkImplementation::_instance->onHdmiHotPlug(portId,isHdmiConnected); - } - } - - void HdmiCecSinkImplementation::onPowerModeChanged(const PowerState ¤tState, const PowerState &newState) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", - currentState, newState); - LOGWARN(" m_logicalAddressAllocated 0x%x CEC enable status %d \n",_instance->m_logicalAddressAllocated,_instance->cecEnableStatus); - if(newState == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) - { - powerState = DEVICE_POWER_STATE_ON; - } - else - { - powerState = DEVICE_POWER_STATE_OFF; - if((_instance->m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_INITIATION) || (_instance->m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) - { - LOGINFO("%s: Stop ARC \n",__FUNCTION__); - _instance->stopArc(); - } - - } - if (_instance->cecEnableStatus) - { - if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED ) - { - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); - - if ( powerState != DEVICE_POWER_STATE_ON ) - { - /* reset the current active source when TV on going to standby */ - HdmiCecSinkImplementation::_instance->m_currentActiveSource = -1; - } - /* Initiate a ping straight away */ - HdmiCecSinkImplementation::_instance->m_pollNextState = POLL_THREAD_STATE_PING; - HdmiCecSinkImplementation::_instance->m_ThreadExitCV.notify_one(); - } - } - else - { - LOGWARN("CEC not Enabled\n"); - } - } - - - void HdmiCecSinkImplementation::sendStandbyMessage() - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(HdmiCecSinkImplementation::_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(Standby()), 1000); - } - - void HdmiCecSinkImplementation::onHdmiHotPlug(int portId , int connectStatus) - { - LOGINFO("onHdmiHotPlug Status : %d ", connectStatus); - if(!connectStatus) - { - LOGINFO(" removeDevice port: %d Logical address :%d \r\n",portId,hdmiInputs[portId].m_logicalAddr.toInt() ); - _instance->removeDevice(hdmiInputs[portId].m_logicalAddr.toInt()); - } - CheckHdmiInState(); - - if(cecEnableStatus) { - LOGINFO("cecEnableStatus : %d Trigger CEC Ping !!! \n", cecEnableStatus); - m_pollNextState = POLL_THREAD_STATE_PING; - m_ThreadExitCV.notify_one(); - } - if( HdmiArcPortID >= 0 ) { - updateArcState(); - } - return; - } - void HdmiCecSinkImplementation::updateArcState() - { - if ( m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED ) - { - if (!(hdmiInputs[HdmiArcPortID].m_isConnected)) - { - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - } - else - { - LOGINFO("updateArcState :not updating ARC state current arc state %d ",m_currentArcRoutingState); - } - } - } - void HdmiCecSinkImplementation::arcStartStopTimerFunction() - { - JsonObject params; - - if (m_arcstarting) - { - LOGINFO("arcStartStopTimerFunction ARC start timer expired"); - LOGINFO("notify_device setting that Initiate ARC failed to get the ARC_STATE_ARC_INITIATED state\n"); - params["status"] = string("failure"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ArcInitiationEvent("failure"); - index++; - } - } - else - { - LOGINFO("arcStartStopTimerFunction ARC stop timer expired"); - LOGINFO("notify_device setting that Terminate ARC failed to get the ARC_STATE_ARC_TERMINATED state\n"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ArcTerminationEvent("failure"); - index++; - } - } - /* bring the state machine to the clean state for a new start */ - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - } - void HdmiCecSinkImplementation::Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor) - { - - LOGINFO("Notify the DS "); - string shortAudioDescriptors; - - if (!audiodescriptor.ToString(shortAudioDescriptors)) { - LOGERR("Failed to stringify JsonArray"); - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ShortAudiodescriptorEvent(shortAudioDescriptors); - index++; - } - } - - void HdmiCecSinkImplementation::Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg) - { - uint8_t numberofdescriptor = msg.numberofdescriptor; - uint32_t descriptor =0; - JsonArray audiodescriptor; - - if (numberofdescriptor) - { - for( uint8_t i=0; i < numberofdescriptor; i++) - { - descriptor = msg.shortAudioDescriptor[i].getAudiodescriptor(); - - LOGINFO("descriptor%d 0x%x\n",i,descriptor); - audiodescriptor.Add(descriptor); - - } - } - else - { - audiodescriptor.Add(descriptor); - } - HdmiCecSinkImplementation::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); - } - - void HdmiCecSinkImplementation::updateCurrentLatency(int videoLatency, bool lowLatencyMode,int audioOutputCompensated, int audioOutputDelay = 0) - { - uint8_t latencyFlags = 0; - latencyFlags = ((lowLatencyMode & 0x1) << 2) | (audioOutputCompensated & 0x3); - LOGINFO("Video Latency : %d , Low Latency Mode : %d ,Audio Output Compensated value : %d , Audio Output Delay : %d , Latency Flags: %d ", videoLatency, lowLatencyMode, audioOutputCompensated, audioOutputDelay, latencyFlags); - m_video_latency = (videoLatency/2) + 1; - m_latency_flags = latencyFlags; - m_audio_output_delay = (audioOutputDelay/2) + 1; - setLatencyInfo(); - } - - void HdmiCecSinkImplementation::setLatencyInfo() - { - if(!HdmiCecSinkImplementation::_instance) - return; - - if(!(_instance->smConnection)) - return; - - LOGINFO("Send Report Current Latency message \n"); - _instance->smConnection->sendTo(LogicalAddress::BROADCAST,MessageEncoder().encode(ReportCurrentLatency(physical_addr,m_video_latency,m_latency_flags,m_audio_output_delay))); - - } - - void HdmiCecSinkImplementation::Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg) - { - if(!HdmiCecSinkImplementation::_instance) - return; - - //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status - //SetSystemAudioMode message may come from AVR/Soundbar while CEC disable is in-progress - if ( cecSettingEnabled != true ) - { - LOGINFO("Process SetSystemAudioMode from Audio device: Cec is disabled-> EnableCEC first"); - return; - } - - if ( (msg.status.toInt() == SYSTEM_AUDIO_MODE_OFF) && (m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) - { - /* ie system audio mode off -> amplifier goign to standby but still ARC is in initiated state,stop ARC and - bring the ARC state machine to terminated state*/ - LOGINFO("system audio mode off message but arc is not in terminated state so stopping ARC"); - stopArc(); - - } - - if (msg.status.toInt() == SYSTEM_AUDIO_MODE_ON) { - LOGINFO("panel power state is %s", powerState ? "Off" : "On"); - if (powerState == DEVICE_POWER_STATE_ON ) { - LOGINFO("Notifying system audio mode ON event"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->SetSystemAudioModeEvent(msg.status.toString()); - index++; - } - } else { - LOGINFO("Not notifying system audio mode ON event"); - } - } else { - LOGINFO("Notifying system audio Mode OFF event"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->SetSystemAudioModeEvent(msg.status.toString()); - index++; - } - } - } - void HdmiCecSinkImplementation::Process_ReportAudioStatus_msg(const ReportAudioStatus msg) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if (m_audioStatusTimerStarted) - { - m_audioStatusReceived = true; - m_isAudioStatusInfoUpdated = true; - m_audioStatusTimerStarted = false; - if (m_audioStatusDetectionTimer.isActive()) - { - LOGINFO("AudioStatus received from the Audio Device and the timer is still active. So stopping the timer!\n"); - m_audioStatusDetectionTimer.stop(); - } - LOGINFO("AudioStatus received from the Audio Device. Updating the AudioStatus info! m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - } - LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioStatusEvent(msg.status.getAudioMuteStatus(), msg.status.getAudioVolume()); - index++; - } - - } - void HdmiCecSinkImplementation::sendKeyPressEvent(const int logicalAddress, int keyCode) - { - if(!(_instance->smConnection)) - return; - LOGINFO(" sendKeyPressEvent logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); - switch(keyCode) - { - case VOLUME_UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); - break; - case VOLUME_DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); - break; - case MUTE: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); - break; - case UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); - break; - case DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); - break; - case LEFT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); - break; - case RIGHT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); - break; - case SELECT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); - break; - case HOME: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); - break; - case BACK: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); - break; - case NUMBER_0: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); - break; - case NUMBER_1: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); - break; - case NUMBER_2: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); - break; - case NUMBER_3: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); - break; - case NUMBER_4: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); - break; - case NUMBER_5: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); - break; - case NUMBER_6: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); - break; - case NUMBER_7: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); - break; - case NUMBER_8: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); - break; - case NUMBER_9: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); - break; - - } - } - - void HdmiCecSinkImplementation::sendUserControlPressed(const int logicalAddress, int keyCode) - { - if(!(_instance->smConnection)) - return; - LOGINFO(" sendUserControlPressed logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); - switch(keyCode) - { - case VOLUME_UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); - break; - case VOLUME_DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); - break; - case MUTE: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); - break; - case UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); - break; - case DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); - break; - case LEFT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); - break; - case RIGHT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); - break; - case SELECT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); - break; - case HOME: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); - break; - case BACK: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); - break; - case NUMBER_0: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); - break; - case NUMBER_1: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); - break; - case NUMBER_2: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); - break; - case NUMBER_3: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); - break; - case NUMBER_4: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); - break; - case NUMBER_5: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); - break; - case NUMBER_6: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); - break; - case NUMBER_7: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); - break; - case NUMBER_8: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); - break; - case NUMBER_9: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); - break; - - } - } - - void HdmiCecSinkImplementation::sendKeyReleaseEvent(const int logicalAddress) - { - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); - - } - - void HdmiCecSinkImplementation::sendUserControlReleased(const int logicalAddress) - { - if(!(_instance->smConnection)) - return; - LOGINFO(" User Control Released \n"); - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); - } - - void HdmiCecSinkImplementation::sendDeviceUpdateInfo(const int logicalAddress) - { - LOGINFO("Send Device Update Info \n"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnDeviceInfoUpdated(logicalAddress); - index++; - } - } - void HdmiCecSinkImplementation::systemAudioModeRequest() - { - if ( cecEnableStatus != true ) - { - LOGINFO("systemAudioModeRequest: Cec is disabled-> EnableCEC first"); - return; - } - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(_instance->smConnection)) - { - return; - } - LOGINFO(" Send systemAudioModeRequest "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(SystemAudioModeRequest(physical_addr)), 1000); - - } - void HdmiCecSinkImplementation::sendGiveAudioStatusMsg() - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(_instance->smConnection)) - { - return; - } - LOGINFO(" Send GiveAudioStatus "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(GiveAudioStatus()), 100); - - } - void HdmiCecSinkImplementation::reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus) - { - JsonObject params; - params["powerStatus"] = JsonValue(powerStatus); - LOGINFO("Panle power state is %s", powerState ? "Off" : "On"); - if (powerStatus != AUDIO_DEVICE_POWERSTATE_OFF) { - if (powerState == DEVICE_POWER_STATE_ON ) { - LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioDevicePowerStatus(powerStatus); - index++; - } - } else { - LOGINFO("Not notifying audio device power state to DS"); - } - } else { - LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioDevicePowerStatus(powerStatus); - index++; - } - } - } - - void HdmiCecSinkImplementation::SendStandbyMsgEvent(const int logicalAddress) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->StandbyMessageReceived(logicalAddress); - index++; - } - - } - Core::hresult HdmiCecSinkImplementation::SetEnabled(const bool &enabled, HdmiCecSinkSuccess &success) - { - - setEnabled(enabled); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetEnabled(bool &enabled, bool &success) - { - enabled = getEnabled(); - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetAudioDeviceConnectedStatus(bool &connected, bool &success) - { - connected = getAudioDeviceConnectedStatus(); - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetActiveSource(bool &available, uint8_t &logicalAddress, string &physicalAddress, string &deviceType, string &cecVersion, string &osdName, string &vendorID, string &powerStatus, string &port, bool &success) - { - char routeString[1024] = {'\0'}; - int length = 0; - std::stringstream temp; - - if ( HdmiCecSinkImplementation::_instance->m_currentActiveSource != -1 ) - { - int n = HdmiCecSinkImplementation::_instance->m_currentActiveSource; - available = true; - logicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt(); - physicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.toString().c_str(); - deviceType = HdmiCecSinkImplementation::_instance->deviceList[n].m_deviceType.toString().c_str(); - cecVersion = HdmiCecSinkImplementation::_instance->deviceList[n].m_cecVersion.toString().c_str(); - osdName = HdmiCecSinkImplementation::_instance->deviceList[n].m_osdName.toString().c_str(); - vendorID = HdmiCecSinkImplementation::_instance->deviceList[n].m_vendorID.toString().c_str(); - powerStatus = HdmiCecSinkImplementation::_instance->deviceList[n].m_powerStatus.toString().c_str(); - - - if ( HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.getByteValue(0) != 0 ) - { - snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.getByteValue(0) - 1)); - } - else if ( HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.getByteValue(0) == 0 ) - { - snprintf(&routeString[length], sizeof(routeString) - length, "%s", "TV"); - } - - temp << (char *)routeString; - port = temp.str(); - - } - else - { - available = false; - } - - success = true; - return Core::ERROR_NONE; - - } - - Core::hresult HdmiCecSinkImplementation::GetDeviceList(uint32_t &numberofdevices, IHdmiCecSinkDeviceListIterator*& deviceList, bool &success) - { - - numberofdevices = HdmiCecSinkImplementation::_instance->m_numberOfDevices; - LOGINFO("getDeviceList m_numberOfDevices :%d \n", HdmiCecSinkImplementation::_instance->m_numberOfDevices); - std::vector localDevices; - Exchange::IHdmiCecSink::HdmiCecSinkDevices actual_hdmicecdevices = {0}; - - for (int n = 0; n <= LogicalAddress::UNREGISTERED; n++) - { - - if ( n != HdmiCecSinkImplementation::_instance->m_logicalAddressAllocated && - HdmiCecSinkImplementation::_instance->deviceList[n].m_isDevicePresent ) - { - - actual_hdmicecdevices.logicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt(); - actual_hdmicecdevices.physicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.toString().c_str(); - actual_hdmicecdevices.deviceType = HdmiCecSinkImplementation::_instance->deviceList[n].m_deviceType.toString().c_str(); - actual_hdmicecdevices.cecVersion = HdmiCecSinkImplementation::_instance->deviceList[n].m_cecVersion.toString().c_str(); - actual_hdmicecdevices.osdName = HdmiCecSinkImplementation::_instance->deviceList[n].m_osdName.toString().c_str(); - actual_hdmicecdevices.vendorID = HdmiCecSinkImplementation::_instance->deviceList[n].m_vendorID.toString().c_str(); - actual_hdmicecdevices.powerStatus = HdmiCecSinkImplementation::_instance->deviceList[n].m_powerStatus.toString().c_str(); - int hdmiPortNumber = -1; - LOGINFO("getDeviceList m_numofHdmiInput:%d looking for Logical Address :%d \n", m_numofHdmiInput, HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt()); - for (int i=0; i < m_numofHdmiInput; i++) - { - LOGINFO("getDeviceList connected : %d, portid:%d LA: %d \n", hdmiInputs[i].m_isConnected, hdmiInputs[i].m_portID, hdmiInputs[i].m_logicalAddr.toInt()); - if(hdmiInputs[i].m_isConnected && hdmiInputs[i].m_logicalAddr.toInt() == HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt()) - { - hdmiPortNumber = hdmiInputs[i].m_portID; - LOGINFO("got portid :%d break \n", hdmiPortNumber); - break; - } - } - actual_hdmicecdevices.powerStatus = hdmiPortNumber; - localDevices.push_back(actual_hdmicecdevices); - } - } - - deviceList = (Core::Service>::Create(localDevices)); - success = true; - return Core::ERROR_NONE; - } - - - Core::hresult HdmiCecSinkImplementation::SetOSDName(const string &name, HdmiCecSinkSuccess &success) - { - - LOGINFO("SetOSDName osdName: %s",name.c_str()); - osdName = name.c_str(); - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_OSD_NAME, JsonValue(name.c_str())); - - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetOSDName(string &name, bool &success) - { - name = osdName.toString(); - LOGINFO("GetOSDName osdName : %s \n",osdName.toString().c_str()); - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::PrintDeviceList(bool &printed, bool &success) - { - printDeviceList(); - printed = true; - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SetActiveSource(HdmiCecSinkSuccess &success) - { - setActiveSource(false); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SetActivePath(const string &activePath, HdmiCecSinkSuccess &success) - { - string activePathStr = activePath; - PhysicalAddress phy_addr = PhysicalAddress(activePathStr); - LOGINFO("Addr = %s, length = %zu", activePathStr.c_str(), activePathStr.length()); - setStreamPath(phy_addr); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetActiveRoute(bool &available, uint8_t &length, IHdmiCecSinkActivePathIterator*& pathList, string &ActiveRoute, bool &success) - { - std::vector route; - char routeString[1024] = {'\0'}; - std::vector paths; - std::stringstream temp; - - if (HdmiCecSinkImplementation::_instance->m_currentActiveSource != -1 && - HdmiCecSinkImplementation::_instance->m_currentActiveSource != HdmiCecSinkImplementation::_instance->m_logicalAddressAllocated ) - { - HdmiCecSinkImplementation::_instance->getActiveRoute(LogicalAddress(HdmiCecSinkImplementation::_instance->m_currentActiveSource), route); - - if (route.size()) - { - available = true; - length = route.size(); - - for (unsigned int i=0; i < route.size(); i++) - { - if ( route[i] != LogicalAddress::UNREGISTERED ) - { - Exchange::IHdmiCecSink::HdmiCecSinkActivePath device; - - device.logicalAddress = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_logicalAddress.toInt(); - device.physicalAddress = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_physicalAddr.toString().c_str(); - device.deviceType = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_deviceType.toString().c_str(); - device.vendorID = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_osdName.toString().c_str(); - device.osdName = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_vendorID.toString().c_str(); - - paths.push_back(device); - - snprintf(&routeString[length], sizeof(routeString) - length, "%s", _instance->deviceList[route[i]].m_logicalAddress.toString().c_str()); - length += _instance->deviceList[route[i]].m_logicalAddress.toString().length(); - snprintf(&routeString[length], sizeof(routeString) - length, "(%s", _instance->deviceList[route[i]].m_osdName.toString().c_str()); - length += _instance->deviceList[route[i]].m_osdName.toString().length(); - snprintf(&routeString[length], sizeof(routeString) - length, "%s", ")-->"); - length += strlen(")-->"); - if( i + 1 == route.size() ) - { - snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_physicalAddr.getByteValue(0) - 1)); - } - } - } - - pathList = (Core::Service>::Create(paths)); - temp << (char *)routeString; - ActiveRoute = temp.str(); - LOGINFO("ActiveRoute = [%s]", routeString); - } - else{ - available = false; - } - - } - else if ( HdmiCecSinkImplementation::_instance->m_currentActiveSource == HdmiCecSinkImplementation::_instance->m_logicalAddressAllocated ) - { - available = true; - ActiveRoute = "TV"; - } - else - { - available = false; - } - - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::RequestActiveSource(HdmiCecSinkSuccess &success) - { - requestActiveSource(); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SetRoutingChange(const string &oldPort, const string &newPort, HdmiCecSinkSuccess &success) - { - if ((oldPort.find("HDMI",0) != std::string::npos || - oldPort.find("TV",0) != std::string::npos ) && - (newPort.find("HDMI", 0) != std::string::npos || - newPort.find("TV", 0) != std::string::npos )) - { - setRoutingChange(oldPort, newPort); - success.success = true; - } - else - { - success.success = false; - } - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SetMenuLanguage(const string &language, HdmiCecSinkSuccess &success) - { - std::string lang; - - lang = language; - - setCurrentLanguage(Language(lang.data())); - success.success = true; - - return Core::ERROR_NONE; - - } - - - Core::hresult HdmiCecSinkImplementation::SetVendorId(const string &vendorId, HdmiCecSinkSuccess &success) - { - - unsigned int vendorID = 0x00; - try - { - vendorID = stoi(vendorId,NULL,16); - } - catch (...) - { - LOGWARN("Exception in setVendorId set default value\n"); - vendorID = 0x0019FB; - } - appVendorId = {(uint8_t)(vendorID >> 16 & 0xff),(uint8_t)(vendorID>> 8 & 0xff),(uint8_t) (vendorID & 0xff)}; - LOGINFO("appVendorId : %s vendorID :%x \n",appVendorId.toString().c_str(), vendorID ); - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_VENDOR_ID, JsonValue(vendorID)); - - success.success = true; - return Core::ERROR_NONE; - } - Core::hresult HdmiCecSinkImplementation::SetupARCRouting(const bool &enabled, HdmiCecSinkSuccess &success) - { - if(enabled) - { - startArc(); - } - else - { - stopArc(); - } - - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetVendorId(string &vendorid, bool &success) - { - LOGINFO("GetVendorId appVendorId : %s \n",appVendorId.toString().c_str()); - vendorid = appVendorId.toString() ; - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::RequestShortAudioDescriptor(HdmiCecSinkSuccess &success) - { - requestShortaudioDescriptor(); - success.success = true; - return Core::ERROR_NONE; - } - Core::hresult HdmiCecSinkImplementation::SendStandbyMessage(HdmiCecSinkSuccess &success) - { - sendStandbyMessage(); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SendAudioDevicePowerOnMessage(HdmiCecSinkSuccess &success) - { - LOGINFO("%s invoked. \n",__FUNCTION__); - systemAudioModeRequest(); - success.success = true; - return Core::ERROR_NONE; - } - Core::hresult HdmiCecSinkImplementation::SendKeyPressEvent(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) - { - SendKeyInfo keyInfo; - - keyInfo.logicalAddr = logicalAddress; - keyInfo.keyCode = keyCode; - keyInfo.UserControl = "sendKeyPressEvent"; - std::unique_lock lk(m_sendKeyEventMutex); - m_SendKeyQueue.push(keyInfo); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - LOGINFO("Post send key press event to queue size:%zu \n",m_SendKeyQueue.size()); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SendUserControlPressed(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) - { - - SendKeyInfo keyInfo; - keyInfo.logicalAddr = logicalAddress; - keyInfo.keyCode = keyCode; - keyInfo.UserControl = "sendUserControlPressed"; - std::unique_lock lk(m_sendKeyEventMutex); - m_SendKeyQueue.push(keyInfo); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - LOGINFO("User control pressed, queue size:%zu \n",m_SendKeyQueue.size()); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SendUserControlReleased(const uint32_t &logicalAddress, HdmiCecSinkSuccess &success) - { - SendKeyInfo keyInfo; - keyInfo.logicalAddr = logicalAddress; - keyInfo.keyCode = 0; - keyInfo.UserControl = "sendUserControlReleased"; - std::unique_lock lk(m_sendKeyEventMutex); - m_SendKeyQueue.push(keyInfo); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - LOGINFO("User Control Released, queue size:%zu \n",m_SendKeyQueue.size()); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SendGetAudioStatusMessage(HdmiCecSinkSuccess &success) - { - sendGiveAudioStatusMsg(); - success.success = true; - return Core::ERROR_NONE; - } - Core::hresult HdmiCecSinkImplementation::SetLatencyInfo(const string &videoLatency, const string &lowLatencyMode, const string &audioOutputCompensated, const string &audioOutputDelay, HdmiCecSinkSuccess &success) - { - int video_latency,audio_output_compensated,audio_output_delay; - bool low_latency_mode; - - LOGINFO("SetLatencyInfo videoLatency : %s lowLatencyMode : %s audioOutputCompensated : %s audioOutputDelay : %s \n",videoLatency.c_str(),lowLatencyMode.c_str(),audioOutputCompensated.c_str(),audioOutputDelay.c_str()); - video_latency = stoi(videoLatency); - low_latency_mode = stoi(lowLatencyMode); - audio_output_compensated = stoi(audioOutputCompensated); - audio_output_delay = stoi(audioOutputDelay); - - updateCurrentLatency(video_latency, low_latency_mode,audio_output_compensated, audio_output_delay); - success.success = true; - return Core::ERROR_NONE; - } - bool HdmiCecSinkImplementation::loadSettings() - { - Core::File file; - file = CEC_SETTING_ENABLED_FILE; - - if( file.Open()) - { - JsonObject parameters; - parameters.IElement::FromFile(file); - bool isConfigAdded = false; - - if( parameters.HasLabel(CEC_SETTING_ENABLED)) - { - getBoolParameter(CEC_SETTING_ENABLED, cecSettingEnabled); - LOGINFO("CEC_SETTING_ENABLED present value:%d",cecSettingEnabled); - } - else - { - parameters[CEC_SETTING_ENABLED] = true; - cecSettingEnabled = true; - isConfigAdded = true; - LOGINFO("CEC_SETTING_ENABLED not present set dafult true:\n "); - } - - if( parameters.HasLabel(CEC_SETTING_OTP_ENABLED)) - { - getBoolParameter(CEC_SETTING_OTP_ENABLED, cecOTPSettingEnabled); - LOGINFO("CEC_SETTING_OTP_ENABLED present value :%d",cecOTPSettingEnabled); - } - else - { - parameters[CEC_SETTING_OTP_ENABLED] = true; - cecOTPSettingEnabled = true; - isConfigAdded = true; - LOGINFO("CEC_SETTING_OTP_ENABLED not present set dafult true:\n "); - } - if( parameters.HasLabel(CEC_SETTING_OSD_NAME)) - { - std::string osd_name; - getStringParameter(CEC_SETTING_OSD_NAME, osd_name); - osdName = osd_name.c_str(); - LOGINFO("CEC_SETTING_OSD_NAME present osd_name :%s",osdName.toString().c_str()); - } - else - { - parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); - LOGINFO("CEC_SETTING_OSD_NMAE not present set dafult value :%s\n ",osdName.toString().c_str()); - isConfigAdded = true; - } - unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); - if( parameters.HasLabel(CEC_SETTING_VENDOR_ID)) - { - getNumberParameter(CEC_SETTING_VENDOR_ID, vendorId); - LOGINFO("CEC_SETTING_VENDOR_ID present :%x ",vendorId); - } - else - { - LOGINFO("CEC_SETTING_VENDOR_ID not present set dafult value :%x \n ",vendorId); - parameters[CEC_SETTING_VENDOR_ID] = vendorId; - isConfigAdded = true; - } - - appVendorId = {(uint8_t)(vendorId >> 16 & 0xff),(uint8_t)(vendorId >> 8 & 0xff),(uint8_t) (vendorId & 0xff)}; - LOGINFO("appVendorId : %s vendorId :%x \n",appVendorId.toString().c_str(), vendorId ); - - if(isConfigAdded) - { - LOGINFO("isConfigAdded true so update file:\n "); - file.Destroy(); - file.Create(); - parameters.IElement::ToFile(file); - - } - - file.Close(); - } - else - { - LOGINFO("CEC_SETTING_ENABLED_FILE file not present create with default settings "); - file.Open(false); - if (!file.IsOpen()) - file.Create(); - - JsonObject parameters; - unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); - parameters[CEC_SETTING_ENABLED] = true; - parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); - parameters[CEC_SETTING_VENDOR_ID] = vendorId; - - cecSettingEnabled = true; - cecOTPSettingEnabled = true; - parameters.IElement::ToFile(file); - - file.Close(); - - } - - return cecSettingEnabled; - } - - void HdmiCecSinkImplementation::setEnabled(bool enabled) - { - LOGINFO("Entered setEnabled: %d cecSettingEnabled :%d ",enabled, cecSettingEnabled); - - if (cecSettingEnabled != enabled) - { - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_ENABLED, JsonValue(enabled)); - cecSettingEnabled = enabled; - } - if(true == enabled) - { - CECEnable(); - } - else - { - CECDisable(); - } - return; - } - - void HdmiCecSinkImplementation::updateImageViewOn(const int logicalAddress) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || - logicalAddress == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress].m_isDevicePresent && - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) - { - /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnWakeupFromStandby(logicalAddress); - index++; - } - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnInActiveSource(logicalAddress, _instance->deviceList[logicalAddress].m_physicalAddr.toString()); - index++; - } - } - - void HdmiCecSinkImplementation::updateTextViewOn(const int logicalAddress) - { - JsonObject params; - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || - logicalAddress == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress].m_isDevicePresent && - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) - { - /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnWakeupFromStandby(logicalAddress); - index++; - } - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnTextViewOnMsg(logicalAddress); - index++; - } - } - - - void HdmiCecSinkImplementation::updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && - logicalAddress.toInt() != _instance->m_logicalAddressAllocated) - { - for (int i=0; i < m_numofHdmiInput; i++) - { - LOGINFO(" addr = %d, portID = %d", phy_addr.getByteValue(0), hdmiInputs[i].m_portID); - if (phy_addr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { - hdmiInputs[i].addChild(logicalAddress, phy_addr); - } - } - } - } - - void HdmiCecSinkImplementation::getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || - logicalAddress.toInt() == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && - logicalAddress.toInt() != _instance->m_logicalAddressAllocated && - _instance->deviceList[logicalAddress.toInt()].m_isActiveSource ) - { - route.clear(); - for (int i=0; i < m_numofHdmiInput; i++) - { - LOGINFO("physicalAddress = [%d], portID = %d", _instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0), hdmiInputs[i].m_portID); - if (_instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { - hdmiInputs[i].getRoute(_instance->deviceList[logicalAddress.toInt()].m_physicalAddr, route); - } - } - } - else { - LOGERR("Not in correct state to Find Route"); - } - } - - - void HdmiCecSinkImplementation::CheckHdmiInState() - { - int err; - bool isAnyPortConnected = false; - - dsHdmiInGetStatusParam_t params; - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - IARM_BUS_DSMGR_API_dsHdmiInGetStatus, - (void *)¶ms, - sizeof(params)); - - if(err == IARM_RESULT_SUCCESS && params.result == dsERR_NONE ) - { - for( int i = 0; i < m_numofHdmiInput; i++ ) - { - LOGINFO("Is HDMI In Port [%d] connected [%d] \n",i, params.status.isPortConnected[i]); - if ( params.status.isPortConnected[i] ) - { - isAnyPortConnected = true; - } - - LOGINFO("update Port Status [%d] \n", i); - hdmiInputs[i].update(params.status.isPortConnected[i]); - } - } - - if ( isAnyPortConnected ) { - m_isHdmiInConnected = true; - } else { - m_isHdmiInConnected = false; - } - } - - void HdmiCecSinkImplementation::requestActiveSource() - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - - _instance->smConnection->sendTo(LogicalAddress::BROADCAST, - MessageEncoder().encode(RequestActiveSourceMessage()), 500); - } - - void HdmiCecSinkImplementation::setActiveSource(bool isResponse) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (isResponse && (_instance->m_currentActiveSource != _instance->m_logicalAddressAllocated) ) - { - LOGWARN("TV is not current Active Source"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress::BROADCAST, - MessageEncoder().encode(ActiveSource(_instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr)), 500); - _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; - } - - void HdmiCecSinkImplementation::setCurrentLanguage(const Language &lang) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = lang; - } - - void HdmiCecSinkImplementation::sendMenuLanguage() - { - Language lang = ""; - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - lang = _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage; - - _instance->smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(SetMenuLanguageMessage(lang)), 100); - } - - void HdmiCecSinkImplementation::updateInActiveSource(const int logical_address, const InActiveSource &source ) - { - JsonObject params; - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if( logical_address != _instance->m_logicalAddressAllocated ) - { - _instance->deviceList[logical_address].m_isActiveSource = false; - - if ( _instance->m_currentActiveSource == logical_address ) - { - _instance->m_currentActiveSource = -1; - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnInActiveSource(logical_address, source.physicalAddress.toString()); - index++; - } - } - } - - void HdmiCecSinkImplementation::updateActiveSource(const int logical_address, const ActiveSource &source ) - { - JsonObject params; - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if( logical_address != _instance->m_logicalAddressAllocated ) - { - if ( _instance->m_currentActiveSource != -1 ) - { - _instance->deviceList[_instance->m_currentActiveSource].m_isActiveSource = false; - } - - _instance->deviceList[logical_address].m_isActiveSource = true; - _instance->deviceList[logical_address].update(source.physicalAddress); - _instance->m_currentActiveSource = logical_address; - - if (_instance->deviceList[logical_address].m_isDevicePresent && - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) - { - /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnWakeupFromStandby(logical_address); - index++; - } - } - - string physicalAddress = _instance->deviceList[logical_address].m_physicalAddr.toString().c_str(); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnActiveSourceChange(logical_address, physicalAddress); - index++; - } - } - } - - void HdmiCecSinkImplementation::requestShortaudioDescriptor() - { - if ( cecEnableStatus != true ) - { - LOGINFO("requestShortaudioDescriptor: cec is disabled-> EnableCEC first"); - return; - } - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - LOGINFO(" Send requestShortAudioDescriptor Message "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestShortAudioDescriptorMessage(formatid,audioFormatCode,numberofdescriptor)), 1000); - - } - - void HdmiCecSinkImplementation::requestAudioDevicePowerStatus() - { - if ( cecEnableStatus != true ) - { - LOGWARN("cec is disabled-> EnableCEC first"); - return; - } - - if(!HdmiCecSinkImplementation::_instance) - return; - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - LOGINFO(" Send GiveDevicePowerStatus Message to Audio system in the network \n"); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM, MessageEncoder().encode(GiveDevicePowerStatus()), 500); - - m_audioDevicePowerStatusRequested = true; - } - - void HdmiCecSinkImplementation::sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason) - { - - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO(" Sending FeatureAbort to %s for opcode %s with reason %s ",logicalAddress.toString().c_str(),feature.toString().c_str(),reason.toString().c_str()); - _instance->smConnection->sendTo(logicalAddress, MessageEncoder().encode(FeatureAbort(feature,reason)), 500); - } - - void HdmiCecSinkImplementation::reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode featureOpcode, const AbortReason abortReason) - { - LOGINFO(" Notifying the UI FeatureAbort from the %s for the opcode %s with the reason %s ",logicalAddress.toString().c_str(),featureOpcode.toString().c_str(),abortReason.toString().c_str()); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportFeatureAbortEvent(logicalAddress.toInt(), featureOpcode.opCode(), abortReason.toInt()); - index++; - } - } - - void HdmiCecSinkImplementation::pingDevices(std::vector &connected , std::vector &disconnected) - { - int i; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(_instance->smConnection)) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { - if ( i != _instance->m_logicalAddressAllocated ) - { - //LOGWARN("PING for 0x%x \r\n",i); - try { - _instance->smConnection->ping(LogicalAddress(_instance->m_logicalAddressAllocated), LogicalAddress(i), Throw_e()); - } - catch(CECNoAckException &e) - { - if ( _instance->deviceList[i].m_isDevicePresent ) { - disconnected.push_back(i); - } - //LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); - usleep(50000); - continue; - } - catch(Exception &e) - { - LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); - usleep(50000); - continue; - } - - /* If we get ACK, then the device is present in the network*/ - if ( !_instance->deviceList[i].m_isDevicePresent ) - { - connected.push_back(i); - //LOGWARN("Ping success, added device: 0x%x \r\n", i); - } - usleep(50000); - } - } - } - - int HdmiCecSinkImplementation::requestType( const int logicalAddress ) { - int requestType = CECDeviceParams::REQUEST_NONE; - - if ( !_instance->deviceList[logicalAddress].m_isPAUpdated || !_instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) { - requestType = CECDeviceParams::REQUEST_PHISICAL_ADDRESS; - }else if ( !_instance->deviceList[logicalAddress].m_isOSDNameUpdated ) { - requestType = CECDeviceParams::REQUEST_OSD_NAME; - }else if ( !_instance->deviceList[logicalAddress].m_isVersionUpdated ) { - requestType = CECDeviceParams::REQUEST_CEC_VERSION; - }else if ( !_instance->deviceList[logicalAddress].m_isVendorIDUpdated ) { - requestType = CECDeviceParams::REQUEST_DEVICE_VENDOR_ID; - }else if ( !_instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) { - requestType = CECDeviceParams::REQUEST_POWER_STATUS; - } - - return requestType; - } - - void HdmiCecSinkImplementation::printDeviceList() { - int i; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - for(i=0; i< 16; i++) - { - if (HdmiCecSinkImplementation::_instance->deviceList[i].m_isDevicePresent) { - LOGWARN("------ Device ID = %d--------", i); - HdmiCecSinkImplementation::_instance->deviceList[i].printVariable(); - LOGWARN("-----------------------------"); - } - } - } - - void HdmiCecSinkImplementation::setStreamPath( const PhysicalAddress &physical_addr) { - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(SetStreamPath(physical_addr)), 500); - } - - void HdmiCecSinkImplementation::setRoutingChange(const std::string &from, const std::string &to) { - PhysicalAddress oldPhyAddr = {0xF,0xF,0xF,0xF}; - PhysicalAddress newPhyAddr = {0xF,0xF,0xF,0xF}; - int oldPortID = -1; - int newPortID = -1; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - if( from.find("TV",0) != std::string::npos ) - { - oldPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; - _instance->m_currentActiveSource = -1; - } - else - { - oldPortID = stoi(from.substr(4,1),NULL,16); - if ( oldPortID < _instance->m_numofHdmiInput ) - { - oldPhyAddr = _instance->hdmiInputs[oldPortID].m_physicalAddr; - } - else - { - LOGERR("Invalid HDMI Old Port ID"); - return; - } - } - - if( to.find("TV",0) != std::string::npos ) - { - newPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; - /*set active source as TV */ - _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; - } - else - { - newPortID = stoi(to.substr(4,1),NULL,16); - - if ( newPortID < _instance->m_numofHdmiInput ) - { - newPhyAddr = _instance->hdmiInputs[newPortID].m_physicalAddr; - } - else - { - LOGERR("Invalid HDMI New Port ID"); - return; - } - } - - if(!(_instance->smConnection)) - { - return; - } - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(RoutingChange(oldPhyAddr, newPhyAddr)), 500); - } - - void HdmiCecSinkImplementation::addDevice(const int logicalAddress) { - JsonObject params; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if ( !HdmiCecSinkImplementation::_instance->deviceList[logicalAddress].m_isDevicePresent ) - { - HdmiCecSinkImplementation::_instance->deviceList[logicalAddress].m_isDevicePresent = true; - HdmiCecSinkImplementation::_instance->deviceList[logicalAddress].m_logicalAddress = LogicalAddress(logicalAddress); - HdmiCecSinkImplementation::_instance->m_numberOfDevices++; - HdmiCecSinkImplementation::_instance->m_pollNextState = POLL_THREAD_STATE_INFO; - - if(logicalAddress == 0x5) - { - LOGINFO(" logicalAddress =%d , Audio device detected, Notify Device Settings", logicalAddress ); - hdmiCecAudioDeviceConnected = true; - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioDeviceConnectedStatus("success", "true"); - index++; - } - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnDeviceAdded(logicalAddress); - index++; - } - } - } - - void HdmiCecSinkImplementation::removeDevice(const int logicalAddress) { - JsonObject params; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress].m_isDevicePresent) - { - _instance->m_numberOfDevices--; - - for (int i=0; i < m_numofHdmiInput; i++) - { - if (_instance->deviceList[logicalAddress].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { - hdmiInputs[i].removeChild(_instance->deviceList[logicalAddress].m_physicalAddr); - hdmiInputs[i].update(LogicalAddress(LogicalAddress::UNREGISTERED)); - } - } - - if(logicalAddress == 0x5) - { - LOGINFO(" logicalAddress =%d , Audio device removed, Notify Device Settings", logicalAddress ); - - hdmiCecAudioDeviceConnected = false; - if (m_audioStatusDetectionTimer.isActive()){ - m_audioStatusDetectionTimer.stop(); - } - m_isAudioStatusInfoUpdated = false; - m_audioStatusReceived = false; - m_audioStatusTimerStarted = false; - LOGINFO("Audio device removed, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioDeviceConnectedStatus("success", "false"); - index++; - } - } - - _instance->deviceList[logicalAddress].m_isRequestRetry = 0; - _instance->deviceList[logicalAddress].clear(); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnDeviceRemoved(logicalAddress); - index++; - } - } - } - - void HdmiCecSinkImplementation::request(const int logicalAddress) { - int requestType; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - requestType = _instance->requestType(logicalAddress); - _instance->deviceList[logicalAddress].m_isRequested = requestType; - - switch (requestType) - { - case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GivePhysicalAddress()), 200); - } - break; - - case CECDeviceParams::REQUEST_CEC_VERSION : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GetCECVersion()), 100); - } - break; - - case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDeviceVendorID()), 100); - } - break; - - case CECDeviceParams::REQUEST_OSD_NAME : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveOSDName()), 500); - } - break; - - case CECDeviceParams::REQUEST_POWER_STATUS : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDevicePowerStatus()), 100); - } - break; - default: - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - break; - } - - _instance->deviceList[logicalAddress].m_requestTime = std::chrono::system_clock::now(); - LOGINFO("request type %d", _instance->deviceList[logicalAddress].m_isRequested); - } - - int HdmiCecSinkImplementation::requestStatus(const int logicalAddress) { - std::chrono::duration elapsed; - bool isElapsed = false; - - if(!HdmiCecSinkImplementation::_instance) - return -1; - - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ) { - LOGERR("Logical Address NOT Allocated Or its not valid"); - return -1; - } - - switch ( _instance->deviceList[logicalAddress].m_isRequested ) { - case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : - { - if( _instance->deviceList[logicalAddress].m_isPAUpdated && - _instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_CEC_VERSION : - { - if( _instance->deviceList[logicalAddress].m_isVersionUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : - { - if( _instance->deviceList[logicalAddress].m_isVendorIDUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_OSD_NAME : - { - if( _instance->deviceList[logicalAddress].m_isOSDNameUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_POWER_STATUS : - { - if( _instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - default: - break; - } - - if ( _instance->deviceList[logicalAddress].m_isRequested != CECDeviceParams::REQUEST_NONE ) - { - elapsed = std::chrono::system_clock::now() - _instance->deviceList[logicalAddress].m_requestTime; - - if ( elapsed.count() > HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS ) - { - LOGINFO("request elapsed "); - isElapsed = true; - } - } - - if (isElapsed) - { - /* For some request it should be retry, like report physical address etc for other we can have default values */ - switch( _instance->deviceList[logicalAddress].m_isRequested ) - { - case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : - { - LOGINFO("Retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); - /* Update with Invalid Physical Address */ - if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) - { - LOGINFO("Max retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); - _instance->deviceList[logicalAddress].update(PhysicalAddress(0xF,0xF,0xF,0xF)); - _instance->deviceList[logicalAddress].update(DeviceType(DeviceType::RESERVED)); - _instance->deviceList[logicalAddress].m_isRequestRetry = 0; - } - } - break; - - case CECDeviceParams::REQUEST_CEC_VERSION : - { - /*Defaulting to 1.4*/ - _instance->deviceList[logicalAddress].update(Version(Version::V_1_4)); - } - break; - - case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : - { - _instance->deviceList[logicalAddress].update(VendorID(0,0,0)); - } - break; - - case CECDeviceParams::REQUEST_OSD_NAME : - { - if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) - { - LOGINFO("Max retry for REQUEST_OSD_NAME = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); - _instance->deviceList[logicalAddress].update(OSDName("")); - _instance->deviceList[logicalAddress].m_isRequestRetry = 0; - } - } - break; - - case CECDeviceParams::REQUEST_POWER_STATUS : - { - _instance->deviceList[logicalAddress].update(PowerStatus(PowerStatus::POWER_STATUS_NOT_KNOWN)); - } - break; - default: - break; - } - - - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - - if( _instance->deviceList[logicalAddress].m_isRequested == CECDeviceParams::REQUEST_NONE) - { - LOGINFO("Request Done"); - return CECDeviceParams::REQUEST_DONE; - } - - //LOGINFO("Request NOT Done"); - return CECDeviceParams::REQUEST_NOT_DONE; - } - - void HdmiCecSinkImplementation::threadRun() - { - std::vector connected; - std::vector disconnected; - int logicalAddressRequested = LogicalAddress::UNREGISTERED + TEST_ADD; - bool isExit = false; - - if(!HdmiCecSinkImplementation::_instance) - return; - - if(!(_instance->smConnection)) - return; - LOGINFO("Entering ThreadRun: _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); - _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; - - while(1) - { - - if (_instance->m_pollThreadExit || isExit ){ - LOGWARN("Thread Exits _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); - break; - } - - if ( _instance->m_pollNextState != POLL_THREAD_STATE_NONE ) - { - _instance->m_pollThreadState = _instance->m_pollNextState; - _instance->m_pollNextState = POLL_THREAD_STATE_NONE; - } - - switch (_instance->m_pollThreadState) { - - case POLL_THREAD_STATE_POLL : - { - //LOGINFO("POLL_THREAD_STATE_POLL"); - _instance->allocateLogicalAddress(DeviceType::TV); - if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED) - { - try{ - - logicalAddress = LogicalAddress(_instance->m_logicalAddressAllocated); - LibCCEC::getInstance().addLogicalAddress(logicalAddress); - _instance->smConnection->setSource(logicalAddress); - _instance->m_numberOfDevices = 0; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType = DeviceType::TV; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_isDevicePresent = true; - _instance->deviceList[_instance->m_logicalAddressAllocated].update(physical_addr); - _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_1_4; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_vendorID = appVendorId; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); - _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = defaultLanguage; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_osdName = osdName.toString().c_str(); - if(cecVersion == 2.0) { - _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_2_0; - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), - MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures)), 500); - } - _instance->smConnection->addFrameListener(_instance->msgFrameListener); - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), - MessageEncoder().encode(ReportPhysicalAddress(physical_addr, _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType)), 100); - - _instance->m_sleepTime = 0; - _instance->m_pollThreadState = POLL_THREAD_STATE_PING; - } - catch(InvalidStateException &e){ - LOGWARN("InvalidStateException caught while allocated logical address. %s", e.what()); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - catch(IOException &e){ - LOGWARN("IOException caught while allocated logical address. %s", e.what()); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - catch(...){ - LOGWARN("Exception caught while allocated logical address."); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - } - else - { - LOGINFO("Not able allocate Logical Address for TV"); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - } - break; - - case POLL_THREAD_STATE_PING : - { - //LOGINFO("POLL_THREAD_STATE_PING"); - _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; - connected.clear(); - disconnected.clear(); - _instance->pingDevices(connected, disconnected); - - if ( disconnected.size() ){ - for( unsigned int i=0; i< disconnected.size(); i++ ) - { - LOGWARN("Disconnected Devices [%zu]", disconnected.size()); - _instance->removeDevice(disconnected[i]); - } - } - - if (connected.size()) { - LOGWARN("Connected Devices [%zu]", connected.size()); - for( unsigned int i=0; i< connected.size(); i++ ) - { - _instance->addDevice(connected[i]); - /* If new device is connected, then try to aquire the information */ - _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; - _instance->m_sleepTime = 0; - } - } - else - { - for(int i=0;im_logicalAddressAllocated && - _instance->deviceList[i].m_isDevicePresent && - !_instance->deviceList[i].isAllUpdated() ) - { - _instance->m_pollNextState = POLL_THREAD_STATE_INFO; - _instance->m_sleepTime = 0; - } - } - /* Check for any update required */ - _instance->m_pollThreadState = POLL_THREAD_STATE_UPDATE; - _instance->m_sleepTime = 0; - } - } - break; - - case POLL_THREAD_STATE_INFO : - { - //LOGINFO("POLL_THREAD_STATE_INFO"); - - if ( logicalAddressRequested == LogicalAddress::UNREGISTERED + TEST_ADD ) - { - int i = 0; - for(;im_logicalAddressAllocated && - _instance->deviceList[i].m_isDevicePresent && - !_instance->deviceList[i].isAllUpdated() ) - { - //LOGINFO("POLL_THREAD_STATE_INFO -> request for %d", i); - logicalAddressRequested = i; - _instance->request(logicalAddressRequested); - _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; - break; - } - } - - if ( i == LogicalAddress::UNREGISTERED) - { - /*So there is no update required, try to ping after some seconds*/ - _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; - _instance->m_sleepTime = 0; - //LOGINFO("POLL_THREAD_STATE_INFO -> state change to Ping", i); - } - } - else - { - /*So there is request sent for logical address, so wait and check the status */ - if ( _instance->requestStatus(logicalAddressRequested) == CECDeviceParams::REQUEST_DONE ) - { - logicalAddressRequested = LogicalAddress::UNREGISTERED; - } - else - { - _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; - } - } - } - break; - - /* updating the power status and if required we can add other information later*/ - case POLL_THREAD_STATE_UPDATE : - { - //LOGINFO("POLL_THREAD_STATE_UPDATE"); - - for(int i=0;im_logicalAddressAllocated && - _instance->deviceList[i].m_isDevicePresent && - _instance->deviceList[i].m_isPowerStatusUpdated ) - { - std::chrono::duration elapsed = std::chrono::system_clock::now() - _instance->deviceList[i].m_lastPowerUpdateTime; - - if ( elapsed.count() > HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS ) - { - _instance->deviceList[i].m_isPowerStatusUpdated = false; - _instance->m_pollNextState = POLL_THREAD_STATE_INFO; - _instance->m_sleepTime = 0; - } - } - } - - _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; - _instance->m_sleepTime = 0; - } - break; - - case POLL_THREAD_STATE_IDLE : - { - //LOGINFO("POLL_THREAD_STATE_IDLE"); - _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; - _instance->m_pollThreadState = POLL_THREAD_STATE_PING; - } - break; - - case POLL_THREAD_STATE_WAIT : - { - /* Wait for Hdmi is connected, in case it disconnected */ - //LOGINFO("19Aug2020-[01] -> POLL_THREAD_STATE_WAIT"); - _instance->m_sleepTime = HDMICECSINK_WAIT_FOR_HDMI_IN_MS; - - if ( _instance->m_isHdmiInConnected == true ) - { - _instance->m_pollThreadState = POLL_THREAD_STATE_POLL; - } - } - break; - - case POLL_THREAD_STATE_EXIT : - { - isExit = true; - _instance->m_sleepTime = 0; - } - break; - } - - std::unique_lock lk(_instance->m_pollExitMutex); - if ( _instance->m_ThreadExitCV.wait_for(lk, std::chrono::milliseconds(_instance->m_sleepTime)) == std::cv_status::timeout ) - continue; - else - LOGINFO("Thread is going to Exit m_pollThreadExit %d\n", _instance->m_pollThreadExit ); - - } - } - - void HdmiCecSinkImplementation::allocateLAforTV() - { - bool gotLogicalAddress = false; - int addr = LogicalAddress::TV; - int i, j; - if (!(_instance->smConnection)) - return; - - for (i = 0; i< HDMICECSINK_NUMBER_TV_ADDR; i++) - { - /* poll for TV logical address - retry 5 times*/ - for (j = 0; j < 5; j++) - { - try { - smConnection->poll(LogicalAddress(addr), Throw_e()); - } - catch(CECNoAckException &e ) - { - LOGWARN("Poll caught %s \r\n",e.what()); - gotLogicalAddress = true; - break; - } - catch(Exception &e) - { - LOGWARN("Poll caught %s \r\n",e.what()); - usleep(250000); - } - } - if (gotLogicalAddress) - { - break; - } - addr = LogicalAddress::SPECIFIC_USE; - } - - if ( gotLogicalAddress ) - { - m_logicalAddressAllocated = addr; - } - else - { - m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; - } - - LOGWARN("Logical Address for TV 0x%x \r\n",m_logicalAddressAllocated); - } - - void HdmiCecSinkImplementation::allocateLogicalAddress(int deviceType) - { - if( deviceType == DeviceType::TV ) - { - allocateLAforTV(); - } - } - - void HdmiCecSinkImplementation::CECEnable(void) - { - std::lock_guard lock(m_enableMutex); - JsonObject params; - LOGINFO("Entered CECEnable"); - if (cecEnableStatus) - { - LOGWARN("CEC Already Enabled"); - return; - } - - if(0 == libcecInitStatus) - { - try - { - LibCCEC::getInstance().init("HdmiCecSinkImplementation"); - } - catch(InvalidStateException &e){ - LOGWARN("InvalidStateException caught in LibCCEC::init %s", e.what()); - } - catch(IOException &e){ - LOGWARN("IOException caught in LibCCEC::init %s", e.what()); - } - catch(...){ - LOGWARN("Exception caught in LibCCEC::init"); - } - } - libcecInitStatus++; - - //Acquire CEC Addresses - _instance->getPhysicalAddress(); - - smConnection = new Connection(LogicalAddress::UNREGISTERED,false,"ServiceManager::Connection::"); - smConnection->open(); - allocateLogicalAddress(DeviceType::TV); - LOGINFO("logical address allocalted: %x \n",m_logicalAddressAllocated); - if ( m_logicalAddressAllocated != LogicalAddress::UNREGISTERED && smConnection) - { - logicalAddress = LogicalAddress(m_logicalAddressAllocated); - LOGINFO(" add logical address %x \n",m_logicalAddressAllocated); - LibCCEC::getInstance().addLogicalAddress(logicalAddress); - smConnection->setSource(logicalAddress); - } - msgProcessor = new HdmiCecSinkProcessor(*smConnection); - msgFrameListener = new HdmiCecSinkFrameListener(*msgProcessor); - if(smConnection) - { - LOGWARN("Start Thread %p", smConnection ); - m_pollThreadState = POLL_THREAD_STATE_POLL; - m_pollNextState = POLL_THREAD_STATE_NONE; - m_pollThreadExit = false; - m_pollThread = std::thread(threadRun); - } - cecEnableStatus = true; - - params["cecEnable"] = string("true"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportCecEnabledEvent("true"); - index++; - } - - return; - } - - void HdmiCecSinkImplementation::CECDisable(void) - { - std::lock_guard lock(m_enableMutex); - JsonObject params; - LOGINFO("Entered CECDisable "); - if(!cecEnableStatus) - { - LOGWARN("CEC Already Disabled "); - return; - } - - if(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) - { - stopArc(); - while(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) - { - usleep(500000); - } - } - - LOGINFO(" CECDisable ARC stopped "); - cecEnableStatus = false; - if (smConnection != NULL) - { - LOGWARN("Stop Thread %p", smConnection ); - m_pollThreadExit = true; - m_ThreadExitCV.notify_one(); - - try - { - if (m_pollThread.joinable()) - { - LOGWARN("Join Thread %p", smConnection ); - m_pollThread.join(); - } - } - catch(const std::system_error& e) - { - LOGERR("system_error exception in thread join %s", e.what()); - } - catch(const std::exception& e) - { - LOGERR("exception in thread join %s", e.what()); - } - - m_pollThreadState = POLL_THREAD_STATE_NONE; - m_pollNextState = POLL_THREAD_STATE_NONE; - - LOGWARN("Deleted Thread %p", smConnection ); - - smConnection->close(); - delete smConnection; - smConnection = NULL; - } - - m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - if (m_audioStatusDetectionTimer.isActive()){ - m_audioStatusDetectionTimer.stop(); - } - m_isAudioStatusInfoUpdated = false; - m_audioStatusReceived = false; - m_audioStatusTimerStarted = false; - LOGINFO("CEC Disabled, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - - for(int i=0; i< 16; i++) - { - if (_instance->deviceList[i].m_isDevicePresent) - { - _instance->deviceList[i].clear(); - } - } - - if(1 == libcecInitStatus) - { - try - { - LibCCEC::getInstance().term(); - } - catch(InvalidStateException &e){ - LOGWARN("InvalidStateException caught in LibCCEC::term %s", e.what()); - } - catch(IOException &e){ - LOGWARN("IOException caught in LibCCEC::term %s", e.what()); - } - catch(...){ - LOGWARN("Exception caught in LibCCEC::term"); - } - - libcecInitStatus--; - LOGWARN("CEC Disabled %d",libcecInitStatus); - - params["cecEnable"] = string("false"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportCecEnabledEvent("false"); - index++; - } - } - return; - } - - - void HdmiCecSinkImplementation::getPhysicalAddress() - { - LOGINFO("Entered getPhysicalAddress "); - - uint32_t physAddress = 0x0F0F0F0F; - - try { - LibCCEC::getInstance().getPhysicalAddress(&physAddress); - physical_addr = {(uint8_t)((physAddress >> 24) & 0xFF),(uint8_t)((physAddress >> 16) & 0xFF),(uint8_t) ((physAddress >> 8) & 0xFF),(uint8_t)((physAddress) & 0xFF)}; - LOGINFO("getPhysicalAddress: physicalAddress: %s ", physical_addr.toString().c_str()); - } - catch (const std::exception& e) - { - LOGWARN("exception caught from getPhysicalAddress"); - } - return; - } - - bool HdmiCecSinkImplementation::getEnabled() - { - - - LOGINFO("getEnabled :%d ",cecEnableStatus); - if(true == cecEnableStatus) - return true; - else - return false; - } - - bool HdmiCecSinkImplementation::getAudioDeviceConnectedStatus() - { - LOGINFO("getAudioDeviceConnectedStatus :%d ", hdmiCecAudioDeviceConnected); - if(true == hdmiCecAudioDeviceConnected) - return true; - else - return false; - } - //Arc Routing related functions - void HdmiCecSinkImplementation::startArc() - { - if ( cecEnableStatus != true ) - { - LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); - return; - } - if(!HdmiCecSinkImplementation::_instance) - return; - - LOGINFO("Current ARC State : %d\n", m_currentArcRoutingState); - - _instance->requestArcInitiation(); - - // start initiate ARC timer 3 sec - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - m_arcstarting = true; - m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); - - } - void HdmiCecSinkImplementation::requestArcInitiation() - { - { - std::lock_guard lock(m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_INITIATION; - } - LOGINFO("requestArcInitiation release sem"); - _instance->m_semSignaltoArcRoutingThread.release(); - - } - void HdmiCecSinkImplementation::stopArc() - { - if ( cecEnableStatus != true ) - { - LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); - return; - } - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_TERMINATION || m_currentArcRoutingState == ARC_STATE_ARC_TERMINATED) - { - LOGINFO("ARC is either Termination in progress or already Terminated"); - return; - } - - _instance->requestArcTermination(); - /* start a timer for 3 sec to get the desired ARC_STATE_ARC_TERMINATED */ - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - /* m_arcstarting = true means starting the ARC start timer ,false means ARC stopping timer*/ - m_arcstarting = false; - m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); - - - } - void HdmiCecSinkImplementation::requestArcTermination() - { - { - std::lock_guard lock(m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_TERMINATION; - } - LOGINFO("requestArcTermination release sem"); - _instance->m_semSignaltoArcRoutingThread.release(); - - } - - void HdmiCecSinkImplementation::Process_InitiateArc() - { - JsonObject params; - - LOGINFO("Command: INITIATE_ARC \n"); - - if(!HdmiCecSinkImplementation::_instance) - return; - - //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status - //Initiate ARC message may come from AVR/Soundbar while CEC disable is in-progress - if ( cecSettingEnabled != true ) - { - LOGINFO("Process InitiateArc from Audio device: Cec is disabled-> EnableCEC first"); - return; - } - - LOGINFO("Got : INITIATE_ARC and current Arcstate is %d\n",_instance->m_currentArcRoutingState); - - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - if (powerState == DEVICE_POWER_STATE_ON ) { - LOGINFO("Notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - _instance->m_currentArcRoutingState = ARC_STATE_ARC_INITIATED; - - _instance->m_semSignaltoArcRoutingThread.release(); - LOGINFO("Got : ARC_INITIATED and notify Device setting"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ArcInitiationEvent("success"); - index++; - } - } else { - LOGINFO("Not notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); - } - - } - void HdmiCecSinkImplementation::Process_TerminateArc() - { - JsonObject params; - - LOGINFO("Command: TERMINATE_ARC current arc state %d \n",HdmiCecSinkImplementation::_instance->m_currentArcRoutingState); - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - std::lock_guard lock(m_arcRoutingStateMutex); - HdmiCecSinkImplementation::_instance->m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - _instance->m_semSignaltoArcRoutingThread.release(); - - // trigger callback to Device setting informing to TERMINATE_ARC - LOGINFO("Got : ARC_TERMINATED and notify Device setting"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ArcTerminationEvent("success"); - index++; - } - } - - void HdmiCecSinkImplementation::threadSendKeyEvent() - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - SendKeyInfo keyInfo = {-1,-1}; - - while(!_instance->m_sendKeyEventThreadExit) - { - keyInfo.logicalAddr = -1; - keyInfo.keyCode = -1; - { - // Wait for a message to be added to the queue - std::unique_lock lk(_instance->m_sendKeyEventMutex); - _instance->m_sendKeyCV.wait(lk, []{return (_instance->m_sendKeyEventThreadRun == true);}); - } - - if (_instance->m_sendKeyEventThreadExit == true) - { - LOGINFO(" threadSendKeyEvent Exiting"); - _instance->m_sendKeyEventThreadRun = false; - break; - } - - if (_instance->m_SendKeyQueue.empty()) { - _instance->m_sendKeyEventThreadRun = false; - continue; - } - - keyInfo = _instance->m_SendKeyQueue.front(); - _instance->m_SendKeyQueue.pop(); - - if(keyInfo.UserControl == "sendUserControlPressed" ) - { - LOGINFO("sendUserControlPressed : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); - _instance->sendUserControlPressed(keyInfo.logicalAddr,keyInfo.keyCode); - } - else if(keyInfo.UserControl == "sendUserControlReleased") - { - LOGINFO("sendUserControlReleased : logical addr:0x%x queue size :%zu \n",keyInfo.logicalAddr,_instance->m_SendKeyQueue.size()); - _instance->sendUserControlReleased(keyInfo.logicalAddr); - } - else - { - LOGINFO("sendKeyPressEvent : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); - _instance->sendKeyPressEvent(keyInfo.logicalAddr,keyInfo.keyCode); - _instance->sendKeyReleaseEvent(keyInfo.logicalAddr); - } - - if((_instance->m_SendKeyQueue.size()<=1 || (_instance->m_SendKeyQueue.size() % 2 == 0)) && ((keyInfo.keyCode == VOLUME_UP) || (keyInfo.keyCode == VOLUME_DOWN) || (keyInfo.keyCode == MUTE)) ) - { - if(keyInfo.keyCode == MUTE) - { - _instance->sendGiveAudioStatusMsg(); - } - else - { - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ",_instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); - if (!_instance->m_isAudioStatusInfoUpdated) - { - if ( !(_instance->m_audioStatusDetectionTimer.isActive())) - { - LOGINFO("Audio status info not updated. Starting the Timer!"); - _instance->m_audioStatusTimerStarted = true; - _instance->m_audioStatusDetectionTimer.start((HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS)); - } - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", _instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); - } - else - { - if (!_instance->m_audioStatusReceived){ - _instance->sendGiveAudioStatusMsg(); - } - } - } - } - }//while(!_instance->m_sendKeyEventThreadExit) - }//threadSendKeyEvent - - void HdmiCecSinkImplementation::audioStatusTimerFunction() - { - m_audioStatusTimerStarted = false; - m_isAudioStatusInfoUpdated = true; - LOGINFO("Timer Expired. Requesting the AudioStatus since not received.\n"); - sendGiveAudioStatusMsg(); - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - } - - - void HdmiCecSinkImplementation::threadArcRouting() - { - bool isExit = false; - uint32_t currentArcRoutingState; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - LOGINFO("Running threadArcRouting"); - _instance->getHdmiArcPortID(); - - while(1) - { - - _instance->m_semSignaltoArcRoutingThread.acquire(); - - - - { - LOGINFO(" threadArcRouting Got semaphore"); - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - - currentArcRoutingState = _instance->m_currentArcRoutingState; - - LOGINFO(" threadArcRouting Got Sem arc state %d",currentArcRoutingState); - } - - switch (currentArcRoutingState) - { - - case ARC_STATE_REQUEST_ARC_INITIATION : - { - - _instance->systemAudioModeRequest(); - _instance->Send_Request_Arc_Initiation_Message(); - - } - break; - case ARC_STATE_ARC_INITIATED : - { - _instance->Send_Report_Arc_Initiated_Message(); - } - break; - case ARC_STATE_REQUEST_ARC_TERMINATION : - { - - _instance->Send_Request_Arc_Termination_Message(); - - } - break; - case ARC_STATE_ARC_TERMINATED : - { - _instance->Send_Report_Arc_Terminated_Message(); - } - break; - case ARC_STATE_ARC_EXIT : - { - isExit = true; - } - break; - } - - if (isExit == true) - { - LOGINFO(" threadArcRouting EXITing"); - break; - } - }//while(1) - }//threadArcRouting - - void HdmiCecSinkImplementation::Send_Request_Arc_Initiation_Message() - { - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO(" Send_Request_Arc_Initiation_Message "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcInitiation()), 1000); - - } - void HdmiCecSinkImplementation::Send_Report_Arc_Initiated_Message() - { - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcInitiation()), 1000); - - } - void HdmiCecSinkImplementation::Send_Request_Arc_Termination_Message() - { - - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcTermination()), 1000); - } - - void HdmiCecSinkImplementation::Send_Report_Arc_Terminated_Message() - { - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcTermination()), 1000); - - } - - void HdmiCecSinkImplementation::getHdmiArcPortID() - { - int err; - dsGetHDMIARCPortIdParam_t param; - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, - (void *)¶m, - sizeof(param)); - if (IARM_RESULT_SUCCESS == err) - { - LOGINFO("HDMI ARC port ID HdmiArcPortID=[%d] \n", param.portId); - HdmiArcPortID = param.portId; - } - } - - void HdmiCecSinkImplementation::getCecVersion() - { - RFC_ParamData_t param = {0}; - WDMP_STATUS status = getRFCParameter((char*)"thunderapi", TR181_HDMICECSINK_CEC_VERSION, ¶m); - if(WDMP_SUCCESS == status && param.type == WDMP_STRING) { - LOGINFO("CEC Version from RFC = [%s] \n", param.value); - cecVersion = atof(param.value); - } - else { - LOGINFO("Error while fetching CEC Version from RFC "); - } - } - - } // namespace Plugin -} // namespace WPEFrameworklk diff --git a/HdmiCecSink/HdmiCecSinkImplementation.h b/HdmiCecSink/HdmiCecSinkImplementation.h deleted file mode 100644 index c9d91c11..00000000 --- a/HdmiCecSink/HdmiCecSinkImplementation.h +++ /dev/null @@ -1,755 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 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. -**/ - -#pragma once - -#include -#include "ccec/FrameListener.hpp" -#include "ccec/Connection.hpp" - -#include "libIARM.h" -#include "ccec/Assert.hpp" -#include "ccec/Messages.hpp" -#include "ccec/MessageDecoder.hpp" -#include "ccec/MessageProcessor.hpp" - -#undef Assert // this define from Connection.hpp conflicts with WPEFramework - -#include "Module.h" -#include "tptimer.h" -#include -#include -#include -#include - -#include "UtilsLogging.h" -#include -#include "PowerManagerInterface.h" -#include - -using namespace WPEFramework; -using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; -using ThermalTemperature = WPEFramework::Exchange::IPowerManager::ThermalTemperature; - - -namespace WPEFramework { - - namespace Plugin { - class HdmiCecSinkFrameListener : public FrameListener - { - public: - HdmiCecSinkFrameListener(MessageProcessor &processor) : processor(processor) {} - void notify(const CECFrame &in) const; - ~HdmiCecSinkFrameListener() {} - private: - MessageProcessor &processor; - }; - - class HdmiCecSinkProcessor : public MessageProcessor - { - public: - HdmiCecSinkProcessor(Connection &conn) : conn(conn) {} - void process (const ActiveSource &msg, const Header &header); - void process (const InActiveSource &msg, const Header &header); - void process (const ImageViewOn &msg, const Header &header); - void process (const TextViewOn &msg, const Header &header); - void process (const RequestActiveSourceMessage &msg, const Header &header); - void process (const Standby &msg, const Header &header); - void process (const GetCECVersion &msg, const Header &header); - void process (const CECVersion &msg, const Header &header); - void process (const SetMenuLanguageMessage &msg, const Header &header); - void process (const GiveOSDName &msg, const Header &header); - void process (const GivePhysicalAddress &msg, const Header &header); - void process (const GiveDeviceVendorID &msg, const Header &header); - void process (const SetOSDString &msg, const Header &header); - void process (const SetOSDName &msg, const Header &header); - void process (const RoutingChange &msg, const Header &header); - void process (const RoutingInformation &msg, const Header &header); - void process (const SetStreamPath &msg, const Header &header); - void process (const GetMenuLanguage &msg, const Header &header); - void process (const ReportPhysicalAddress &msg, const Header &header); - void process (const DeviceVendorID &msg, const Header &header); - void process (const GiveDevicePowerStatus &msg, const Header &header); - void process (const ReportPowerStatus &msg, const Header &header); - void process (const FeatureAbort &msg, const Header &header); - void process (const Abort &msg, const Header &header); - void process (const Polling &msg, const Header &header); - void process (const InitiateArc &msg, const Header &header); - void process (const TerminateArc &msg, const Header &header); - void process (const ReportShortAudioDescriptor &msg, const Header &header); - void process (const SetSystemAudioMode &msg, const Header &header); - void process (const ReportAudioStatus &msg, const Header &header); - void process (const GiveFeatures &msg, const Header &header); - void process (const RequestCurrentLatency &msg, const Header &header); - private: - Connection conn; - void printHeader(const Header &header) - { - printf("Header : From : %s \n", header.from.toString().c_str()); - printf("Header : to : %s \n", header.to.toString().c_str()); - } - - }; - - class CECDeviceParams { - public: - - enum { - REQUEST_NONE = 0, - REQUEST_PHISICAL_ADDRESS = 1, - REQUEST_CEC_VERSION, - REQUEST_DEVICE_VENDOR_ID, - REQUEST_POWER_STATUS, - REQUEST_OSD_NAME, - }; - - enum { - REQUEST_DONE = 0, - REQUEST_NOT_DONE, - REQUEST_TIME_ELAPSED, - }; - - DeviceType m_deviceType; - LogicalAddress m_logicalAddress; - PhysicalAddress m_physicalAddr; - Version m_cecVersion; - VendorID m_vendorID; - OSDName m_osdName; - PowerStatus m_powerStatus; - bool m_isDevicePresent; - bool m_isDeviceDisconnected; - Language m_currentLanguage; - bool m_isActiveSource; - bool m_isDeviceTypeUpdated; - bool m_isPAUpdated; - bool m_isVersionUpdated; - bool m_isOSDNameUpdated; - bool m_isVendorIDUpdated; - bool m_isPowerStatusUpdated; - int m_isRequested; - int m_isRequestRetry; - std::chrono::system_clock::time_point m_requestTime; - std::vector m_featureAborts; - std::chrono::system_clock::time_point m_lastPowerUpdateTime; - - CECDeviceParams() - : m_deviceType(0), m_logicalAddress(0),m_physicalAddr(0x0f,0x0f,0x0f,0x0f),m_cecVersion(0),m_vendorID(0,0,0),m_osdName(""),m_powerStatus(0),m_currentLanguage("") - { - m_isDevicePresent = false; - m_isActiveSource = false; - m_isPAUpdated = false; - m_isVersionUpdated = false; - m_isOSDNameUpdated = false; - m_isVendorIDUpdated = false; - m_isPowerStatusUpdated = false; - m_isDeviceDisconnected = false; - m_isDeviceTypeUpdated = false; - m_isRequestRetry = 0; - } - - void clear( ) - { - m_deviceType = 0; - m_logicalAddress = 0; - m_physicalAddr = PhysicalAddress(0x0f,0x0f,0x0f,0x0f); - m_cecVersion = 0; - m_vendorID = VendorID(0,0,0); - m_osdName = ""; - m_powerStatus = 0; - m_currentLanguage = ""; - m_isDevicePresent = false; - m_isActiveSource = false; - m_isPAUpdated = false; - m_isVersionUpdated = false; - m_isOSDNameUpdated = false; - m_isVendorIDUpdated = false; - m_isPowerStatusUpdated = false; - m_isDeviceDisconnected = false; - m_isDeviceTypeUpdated = false; - } - - void printVariable() - { - LOGWARN("Device LogicalAddress %s", m_logicalAddress.toString().c_str()); - LOGWARN("Device Type %s", m_deviceType.toString().c_str()); - LOGWARN("Device Present %d", m_isDevicePresent); - LOGWARN("Active Source %d", m_isActiveSource); - LOGWARN("PA Updated %d", m_isPAUpdated); - LOGWARN("Version Updated %d", m_isVersionUpdated); - LOGWARN("OSDName Updated %d", m_isOSDNameUpdated); - LOGWARN("PowerStatus Updated %d", m_isPowerStatusUpdated); - LOGWARN("VendorID Updated %d", m_isPowerStatusUpdated); - LOGWARN("CEC Version : %s", m_cecVersion.toString().c_str()); - LOGWARN("Vendor ID : %s", m_vendorID.toString().c_str()); - LOGWARN("PhisicalAddress : %s", m_physicalAddr.toString().c_str()); - LOGWARN("OSDName : %s", m_osdName.toString().c_str()); - LOGWARN("Power Status : %s", m_powerStatus.toString().c_str()); - LOGWARN("Language : %s", m_currentLanguage.toString().c_str()); - } - - bool isAllUpdated() { - if( !m_isPAUpdated - || !m_isVersionUpdated - || !m_isOSDNameUpdated - || !m_isVendorIDUpdated - || !m_isPowerStatusUpdated - || !m_isDeviceTypeUpdated ){ - return false; - } - return true; - } - - void update( const DeviceType &deviceType ) { - m_deviceType = deviceType; - m_isDeviceTypeUpdated = true; - } - - void update( const PhysicalAddress &physical_addr ) { - m_physicalAddr = physical_addr; - m_isPAUpdated = true; - } - - void update ( const VendorID &vendorId) { - m_vendorID = vendorId; - m_isVendorIDUpdated = true; - } - - void update ( const Version &version ) { - m_cecVersion = version; - m_isVersionUpdated = true; - } - - void update ( const OSDName &osdName ) { - m_osdName = osdName; - m_isOSDNameUpdated = true; - } - - void update ( const PowerStatus &status ) { - m_powerStatus = status; - m_isPowerStatusUpdated = true; - m_lastPowerUpdateTime = std::chrono::system_clock::now(); - } - }; - - class DeviceNode { - public: - uint8_t m_childsLogicalAddr[LogicalAddress::UNREGISTERED]; - - DeviceNode() { - int i; - for (i = 0; i < LogicalAddress::UNREGISTERED; i++ ) - { - m_childsLogicalAddr[i] = LogicalAddress::UNREGISTERED; - } - } - - } ; - typedef struct sendKeyInfo - { - int logicalAddr; - int keyCode; - string UserControl; - }SendKeyInfo; - - class HdmiPortMap { - public: - uint8_t m_portID; - bool m_isConnected; - LogicalAddress m_logicalAddr; - PhysicalAddress m_physicalAddr; - DeviceNode m_deviceChain[3]; - - HdmiPortMap(uint8_t portID) : m_portID(portID), - m_logicalAddr(LogicalAddress::UNREGISTERED), - m_physicalAddr(portID+1,0,0,0) - { - m_isConnected = false; - } - - void update(bool isConnected) - { - m_isConnected = isConnected; - } - - void update( const LogicalAddress &addr ) - { - m_logicalAddr = addr; - } - - void addChild( const LogicalAddress &logical_addr, const PhysicalAddress &physical_addr ) - { - LOGINFO(" logicalAddr = %d, phisicalAddr = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); - - if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED && - m_logicalAddr.toInt() != logical_addr.toInt() ) - { - LOGINFO(" update own logicalAddr = %d, new devcie logicalAddress = %d", m_logicalAddr.toInt(), logical_addr.toInt() ); - /* check matching with this port's physical address */ - if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && - physical_addr.getByteValue(1) != 0 ) - { - if ( physical_addr.getByteValue(3) != 0 ) - { - m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = logical_addr.toInt(); - } - else if ( physical_addr.getByteValue(2) != 0 ) - { - m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = logical_addr.toInt(); - } - else if ( physical_addr.getByteValue(1) != 0 ) - { - m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = logical_addr.toInt(); - } - } - } - else if ( physical_addr == m_physicalAddr ) - { - update(logical_addr); - LOGINFO(" update own logicalAddr = %d", m_logicalAddr.toInt()); - } - } - - void removeChild( PhysicalAddress &physical_addr ) - { - if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) - { - /* check matching with this port's physical address */ - if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && - physical_addr.getByteValue(1) != 0 ) - { - if ( physical_addr.getByteValue(3) != 0 ) - { - m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = LogicalAddress::UNREGISTERED; - } - else if ( physical_addr.getByteValue(2) != 0 ) - { - m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = LogicalAddress::UNREGISTERED; - } - else if ( physical_addr.getByteValue(1) != 0 ) - { - m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = LogicalAddress::UNREGISTERED; - } - } - } - } - - void getRoute( PhysicalAddress &physical_addr, std::vector & route ) - { - LOGINFO(" logicalAddr = %d, phsical = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); - - if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) - { - LOGINFO(" search for logicalAddr = %d", m_logicalAddr.toInt()); - /* check matching with this port's physical address */ - if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && - physical_addr.getByteValue(1) != 0 ) - { - if ( physical_addr.getByteValue(3) != 0 ) - { - route.push_back(m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1]); - } - - if ( physical_addr.getByteValue(2) != 0 ) - { - route.push_back(m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1]); - } - - if ( physical_addr.getByteValue(1) != 0 ) - { - route.push_back(m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1]); - } - - route.push_back(m_logicalAddr.toInt()); - } - else - { - route.push_back(m_logicalAddr.toInt()); - LOGINFO("logicalAddr = %d, physical = %s", m_logicalAddr.toInt(), m_physicalAddr.toString().c_str()); - } - } - } - }; - - class binary_semaphore { - - public: - - explicit binary_semaphore(int init_count = count_max) - - : count_(init_count) {} - - - - // P-operation / acquire - - void wait() - - { - - std::unique_lock lk(m_); - - cv_.wait(lk, [=]{ return 0 < count_; }); - - --count_; - - } - - bool try_wait() - - { - - std::lock_guard lk(m_); - - if (0 < count_) { - - --count_; - - return true; - - } else { - - return false; - - } - - } - - // V-operation / release - - void signal() - - { - - std::lock_guard lk(m_); - - if (count_ < count_max) { - - ++count_; - - cv_.notify_one(); - - } - - } - - - - // Lockable requirements - - void acquire() { wait(); } - - bool try_lock() { return try_wait(); } - - void release() { signal(); } - - - -private: - - static const int count_max = 1; - - int count_; - - std::mutex m_; - - std::condition_variable cv_; - -}; - // This is a server for a JSONRPC communication channel. - // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. - // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. - // This realization of this interface implements, by default, the following methods on this plugin - // - exists - // - register - // - unregister - // Any other methood to be handled by this plugin can be added can be added by using the - // templated methods Register on the PluginHost::JSONRPC class. - // As the registration/unregistration of notifications is realized by the class PluginHost::JSONRPC, - // this class exposes a public method called, Notify(), using this methods, all subscribed clients - // will receive a JSONRPC message as a notification, in case this method is called. - class HdmiCecSinkImplementation : public Exchange::IHdmiCecSink { - - enum { - POLL_THREAD_STATE_NONE, - POLL_THREAD_STATE_IDLE, - POLL_THREAD_STATE_POLL, - POLL_THREAD_STATE_PING, - POLL_THREAD_STATE_INFO, - POLL_THREAD_STATE_WAIT, - POLL_THREAD_STATE_CLEAN, - POLL_THREAD_STATE_UPDATE, - POLL_THREAD_STATE_EXIT, - }; - enum { - ARC_STATE_REQUEST_ARC_INITIATION, - ARC_STATE_ARC_INITIATED, - ARC_STATE_REQUEST_ARC_TERMINATION, - ARC_STATE_ARC_TERMINATED, - ARC_STATE_ARC_EXIT - }; - enum { - VOLUME_UP = 0x41, - VOLUME_DOWN = 0x42, - MUTE = 0x43, - UP = 0x01, - DOWN = 0x02, - LEFT = 0x03, - RIGHT = 0x04, - SELECT = 0x00, - HOME = 0x09, - BACK = 0x0D, - NUMBER_0 = 0x20, - NUMBER_1 = 0x21, - NUMBER_2 = 0x22, - NUMBER_3 = 0x23, - NUMBER_4 = 0x24, - NUMBER_5 = 0x25, - NUMBER_6 = 0x26, - NUMBER_7 = 0x27, - NUMBER_8 = 0x28, - NUMBER_9 = 0x29 - }; - public: - HdmiCecSinkImplementation(); - virtual ~HdmiCecSinkImplementation(); - static HdmiCecSinkImplementation* _instance; - CECDeviceParams deviceList[16]; - std::vector hdmiInputs; - int m_currentActiveSource; - void updateInActiveSource(const int logical_address, const InActiveSource &source ); - void updateActiveSource(const int logical_address, const ActiveSource &source ); - void updateTextViewOn(const int logicalAddress); - void updateImageViewOn(const int logicalAddress); - void updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr); - void getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route); - void removeDevice(const int logicalAddress); - void addDevice(const int logicalAddress); - void printDeviceList(); - void setStreamPath( const PhysicalAddress &physical_addr); - void setRoutingChange(const std::string &from, const std::string &to); - void sendStandbyMessage(); - void setCurrentLanguage(const Language &lang); - void sendMenuLanguage(); - void setActiveSource(bool isResponse); - void requestActiveSource(); - void startArc(); - void stopArc(); - void Process_InitiateArc(); - void Process_TerminateArc(); - void updateArcState(); - void requestShortaudioDescriptor(); - void Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor); - void Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg); - void Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg); - void sendDeviceUpdateInfo(const int logicalAddress); - void sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); - void reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); - void systemAudioModeRequest(); - void SendStandbyMsgEvent(const int logicalAddress); - void requestAudioDevicePowerStatus(); - void reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus); - void updateCurrentLatency(int videoLatency, bool lowLatencyMode, int audioOutputCompensated, int audioOutputDelay); - void setLatencyInfo(); - void Process_ReportAudioStatus_msg(const ReportAudioStatus msg); - void sendKeyPressEvent(const int logicalAddress, int keyCode); - void sendKeyReleaseEvent(const int logicalAddress); - void sendUserControlPressed(const int logicalAddress, int keyCode); - void sendUserControlReleased(const int logicalAddress); - void sendGiveAudioStatusMsg(); - void onPowerModeChanged(const PowerState ¤tState, const PowerState &newState); - void registerEventHandlers(); - void getHdmiArcPortID(); - int m_numberOfDevices; /* Number of connected devices othethan own device */ - bool m_audioDevicePowerStatusRequested; - - BEGIN_INTERFACE_MAP(HdmiCecSinkImplementation) - INTERFACE_ENTRY(Exchange::IHdmiCecSink) - END_INTERFACE_MAP - - private: - class PowerManagerNotification : public Exchange::IPowerManager::IModeChangedNotification { - private: - PowerManagerNotification(const PowerManagerNotification&) = delete; - PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; - - public: - explicit PowerManagerNotification(HdmiCecSinkImplementation& parent) - : _parent(parent) - { - } - ~PowerManagerNotification() override = default; - - public: - void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override - { - _parent.onPowerModeChanged(currentState, newState); - } - - template - T* baseInterface() - { - static_assert(std::is_base_of(), "base type mismatch"); - return static_cast(this); - } - - BEGIN_INTERFACE_MAP(PowerManagerNotification) - INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) - END_INTERFACE_MAP - - private: - HdmiCecSinkImplementation& _parent; - - }; - // We do not allow this plugin to be copied !! - HdmiCecSinkImplementation(const HdmiCecSinkImplementation&) = delete; - HdmiCecSinkImplementation& operator=(const HdmiCecSinkImplementation&) = delete; - //Begin methods - void InitializePowerManager(PluginHost::IShell *service); - //End methods - std::string logicalAddressDeviceType; - bool cecSettingEnabled; - bool cecOTPSettingEnabled; - bool cecEnableStatus; - bool hdmiCecAudioDeviceConnected; - bool m_isHdmiInConnected; - int m_numofHdmiInput; - uint8_t m_deviceType; - int m_logicalAddressAllocated; - std::thread m_pollThread; - uint32_t m_pollThreadState; - uint32_t m_pollNextState; - bool m_pollThreadExit; - uint32_t m_sleepTime; - std::mutex m_pollExitMutex; - std::mutex m_enableMutex; - /* Send Key event related */ - bool m_sendKeyEventThreadExit; - bool m_sendKeyEventThreadRun; - bool m_isAudioStatusInfoUpdated; - bool m_audioStatusReceived; - bool m_audioStatusTimerStarted; - std::thread m_sendKeyEventThread; - std::mutex m_sendKeyEventMutex; - std::queue m_SendKeyQueue; - std::condition_variable m_sendKeyCV; - std::condition_variable m_ThreadExitCV; - - /* DALS - Latency Values */ - uint8_t m_video_latency; - uint8_t m_latency_flags; - uint8_t m_audio_output_delay; - - /* ARC related */ - std::thread m_arcRoutingThread; - uint32_t m_currentArcRoutingState; - std::mutex m_arcRoutingStateMutex; - binary_semaphore m_semSignaltoArcRoutingThread; - bool m_arcstarting; - TpTimer m_arcStartStopTimer; - TpTimer m_audioStatusDetectionTimer; - - Connection *smConnection; - std::vector m_connectedDevices; - HdmiCecSinkProcessor *msgProcessor; - HdmiCecSinkFrameListener *msgFrameListener; - PowerManagerInterfaceRef _powerManagerPlugin; - Core::Sink _pwrMgrNotification; - bool _registeredEventHandlers; - const void InitializeIARM(); - void DeinitializeIARM(); - void allocateLogicalAddress(int deviceType); - void allocateLAforTV(); - void pingDevices(std::vector &connected , std::vector &disconnected); - void CheckHdmiInState(); - void request(const int logicalAddress); - int requestType(const int logicalAddress); - int requestStatus(const int logicalAddress); - static void threadRun(); - void cecMonitoringThread(); - static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - void onHdmiHotPlug(int portId, int connectStatus); - bool loadSettings(); - void persistSettings(bool enableStatus); - void persistOTPSettings(bool enableStatus); - void persistOSDName(const char *name); - void persistVendorId(unsigned int vendorID); - void setEnabled(bool enabled); - bool getEnabled(); - bool getAudioDeviceConnectedStatus(); - void CECEnable(void); - void CECDisable(void); - void getPhysicalAddress(); - void getLogicalAddress(); - void cecAddressesChanged(int changeStatus); - - // Arc functions - - static void threadSendKeyEvent(); - static void threadArcRouting(); - void requestArcInitiation(); - void requestArcTermination(); - void Send_Request_Arc_Initiation_Message(); - void Send_Report_Arc_Initiated_Message(); - void Send_Request_Arc_Termination_Message(); - void Send_Report_Arc_Terminated_Message(); - void arcStartStopTimerFunction(); - void audioStatusTimerFunction(); - void getCecVersion(); - - - public: - Core::hresult GetActiveRoute(bool &available, uint8_t &length, IHdmiCecSinkActivePathIterator*& pathList, string &ActiveRoute, bool &success) override; - Core::hresult GetActiveSource(bool &available, uint8_t &logicalAddress, string &physicalAddress, string &deviceType, string &cecVersion, string &osdName, string &vendorID, string &powerStatus, string &port, bool &success) override; - Core::hresult GetAudioDeviceConnectedStatus(bool &connected, bool &success) override; - Core::hresult GetDeviceList(uint32_t &numberofdevices, IHdmiCecSinkDeviceListIterator*& deviceList, bool &success) override; - Core::hresult GetEnabled(bool &enabled, bool &success) override; - Core::hresult GetOSDName(string &name, bool &success) override; - Core::hresult GetVendorId(string &vendorid, bool &success) override; - Core::hresult PrintDeviceList(bool &printed, bool &success) override; - Core::hresult RequestActiveSource(HdmiCecSinkSuccess &success) override; - Core::hresult RequestShortAudioDescriptor(HdmiCecSinkSuccess &success) override; - Core::hresult SendAudioDevicePowerOnMessage(HdmiCecSinkSuccess &success) override; - Core::hresult SendGetAudioStatusMessage(HdmiCecSinkSuccess &success) override; - Core::hresult SendKeyPressEvent(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) override; - Core::hresult SendUserControlPressed(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) override; - Core::hresult SendUserControlReleased(const uint32_t &logicalAddress, HdmiCecSinkSuccess &success) override; - Core::hresult SendStandbyMessage(HdmiCecSinkSuccess &success) override; - Core::hresult SetActivePath(const string &activePath, HdmiCecSinkSuccess &success) override; - Core::hresult SetActiveSource(HdmiCecSinkSuccess &success) override; - Core::hresult SetEnabled(const bool &enabled, HdmiCecSinkSuccess &success) override; - Core::hresult SetOSDName(const string &name, HdmiCecSinkSuccess &success) override; - Core::hresult SetRoutingChange(const string &oldPort, const string &newPort, HdmiCecSinkSuccess &success) override; - Core::hresult SetupARCRouting(const bool &enabled, HdmiCecSinkSuccess &success) override; - Core::hresult SetVendorId(const string &vendorId, HdmiCecSinkSuccess &success) override; - Core::hresult SetLatencyInfo(const string &videoLatency, const string &lowLatencyMode, const string &audioOutputCompensated, const string &audioOutputDelay, HdmiCecSinkSuccess &success) override; - Core::hresult Configure(PluginHost::IShell* service) override; - Core::hresult Register(Exchange::IHdmiCecSink::INotification *notification) override; - Core::hresult Unregister(Exchange::IHdmiCecSink::INotification *notification) override; - Core::hresult SetMenuLanguage(const string &language, HdmiCecSinkSuccess &success) override; - - private: - std::list _hdmiCecSinkNotifications; - mutable Core::CriticalSection _adminLock; - }; - } // namespace Plugin -} // namespace WPEFramework - - - - diff --git a/HdmiCecSource/HdmiCecSourceImplementation.cpp b/HdmiCecSource/HdmiCecSourceImplementation.cpp index 1086f6ac..4a4e3e64 100644 --- a/HdmiCecSource/HdmiCecSourceImplementation.cpp +++ b/HdmiCecSource/HdmiCecSourceImplementation.cpp @@ -135,7 +135,7 @@ namespace WPEFramework LOGINFO("Command: TextViewOn\n"); HdmiCecSourceImplementation::_instance->addDevice(header.from.toInt()); } - void HdmiCecSourceProcessor::process (const RequestActiveSourceMessage &msg, const Header &header) + void HdmiCecSourceProcessor::process (const RequestActiveSource &msg, const Header &header) { printHeader(header); LOGINFO("Command: RequestActiveSource\n"); @@ -178,7 +178,7 @@ namespace WPEFramework LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); HdmiCecSourceImplementation::_instance->addDevice(header.from.toInt()); } - void HdmiCecSourceProcessor::process (const SetMenuLanguageMessage &msg, const Header &header) + void HdmiCecSourceProcessor::process (const SetMenuLanguage &msg, const Header &header) { printHeader(header); LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); @@ -1031,7 +1031,7 @@ namespace WPEFramework LOGINFO("Command: sending GiveDevicePowerStatus \r\n"); smConnection->sendTo(LogicalAddress::TV, MessageEncoder().encode(GiveDevicePowerStatus())); LOGINFO("Command: sending request active Source isDeviceActiveSource is set to false\r\n"); - smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(RequestActiveSourceMessage())); + smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(RequestActiveSource())); isDeviceActiveSource = false; LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n", \ (isLGTvConnected)?lgVendorId.toString().c_str():appVendorId.toString().c_str()); diff --git a/HdmiCecSource/HdmiCecSourceImplementation.h b/HdmiCecSource/HdmiCecSourceImplementation.h index d0494a18..6239dab5 100644 --- a/HdmiCecSource/HdmiCecSourceImplementation.h +++ b/HdmiCecSource/HdmiCecSourceImplementation.h @@ -68,11 +68,11 @@ namespace WPEFramework { void process (const InActiveSource &msg, const Header &header); void process (const ImageViewOn &msg, const Header &header); void process (const TextViewOn &msg, const Header &header); - void process (const RequestActiveSourceMessage &msg, const Header &header); + void process (const RequestActiveSource &msg, const Header &header); void process (const Standby &msg, const Header &header); void process (const GetCECVersion &msg, const Header &header); void process (const CECVersion &msg, const Header &header); - void process (const SetMenuLanguageMessage &msg, const Header &header); + void process (const SetMenuLanguage &msg, const Header &header); void process (const GiveOSDName &msg, const Header &header); void process (const GivePhysicalAddress &msg, const Header &header); void process (const GiveDeviceVendorID &msg, const Header &header); diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index acab058e..ead1b3c2 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -115,8 +115,7 @@ add_plugin_test_ex(PLUGIN_HDMICEC2 tests/test_HdmiCec2.cpp "../../HdmiCec_2" "${ # PLUGIN_HDMICECSINK set (HDMICECSINK_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiCecSink ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) -set (HDMICECSINK_LIBS ${NAMESPACE}HdmiCecSink ${NAMESPACE}HdmiCecSinkImplementation) -add_plugin_test_ex(PLUGIN_HDMICECSINK tests/test_HdmiCecSink.cpp "${HDMICECSINK_INC}" "${HDMICECSINK_LIBS}") +add_plugin_test_ex(PLUGIN_HDMICECSINK tests/test_HdmiCecSink.cpp "${HDMICECSINK_INC}" "${NAMESPACE}HdmiCecSink") # PLUGIN_HDMICECSOURCE set (HDMICECSOURCE_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiCecSource ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) diff --git a/Tests/L1Tests/tests/test_HdmiCecSource.cpp b/Tests/L1Tests/tests/test_HdmiCecSource.cpp index a298e038..3ae56adb 100755 --- a/Tests/L1Tests/tests/test_HdmiCecSource.cpp +++ b/Tests/L1Tests/tests/test_HdmiCecSource.cpp @@ -989,7 +989,7 @@ TEST_F(HdmiCecSourceInitializedEventTest, requestActiveSourceProccess){ Header header; header.from = LogicalAddress(1); //specifies with logicalAddress in the deviceList we're using - RequestActiveSourceMessage requestActiveSource; + RequestActiveSource requestActiveSource; Plugin::HdmiCecSourceProcessor proc(Connection::getInstance()); From 8a6fd55be4c187be3c725d2ca6512720bd6c018b Mon Sep 17 00:00:00 2001 From: svemur170 Date: Tue, 22 Jul 2025 19:41:40 +0000 Subject: [PATCH 29/52] RDKEMW-6279 - Changelog updates for 1.3.4 Signed-off-by: svemur170 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7de554a7..1f24687d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.3.4](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.3...1.3.4) + +- RDKEMW-6279: Revert of HdmiCecSink comrpc changes (#129) [`#199`](https://github.com/rdkcentral/entservices-inputoutput/pull/199) +- Merge tag '1.3.3' into develop [`7abaec3`](https://github.com/rdkcentral/entservices-inputoutput/commit/7abaec32ed58c36ef05640ca9baaf8077b90a5d5) + #### [1.3.3](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.2...1.3.3) +> 10 July 2025 + - RDKEMW-3750 : Upgrade Thunder to Version R4.4.3 [`#133`](https://github.com/rdkcentral/entservices-inputoutput/pull/133) - cmake cleanup [`#151`](https://github.com/rdkcentral/entservices-inputoutput/pull/151) - RDK-42386 : Improve Unit Tests Coverage for AVInput Plugin [`#164`](https://github.com/rdkcentral/entservices-inputoutput/pull/164) +- RDKEMW-3750 - Changelog updates for 1.3.3 [`ced5287`](https://github.com/rdkcentral/entservices-inputoutput/commit/ced52871e5f60487165bf417af781f3f72e10bfa) - Merge tag '1.3.2' into develop [`dab1c4a`](https://github.com/rdkcentral/entservices-inputoutput/commit/dab1c4ab82e2983b04d66bdb975a546a79efc47f) #### [1.3.2](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.1...1.3.2) From 4b8146edce8360b845cc6446fcc414e9279d76b9 Mon Sep 17 00:00:00 2001 From: Yuvaramachandran Gurusamy <123441336+yuvaramachandran-gurusamy@users.noreply.github.com> Date: Wed, 23 Jul 2025 15:57:36 +0530 Subject: [PATCH 30/52] RDKEMW-6230: Retry logic used dsGetHDMIARCPortId in HdmiCecSink (#203) * RDKEMW-6230: Retry logic used dsGetHDMIARCPortId in HdmiCecSink Signed-off-by: yuvaramachandran_gurusamy * RDKEMW-6230: Fix L1 test build failure Signed-off-by: yuvaramachandran_gurusamy --------- Signed-off-by: yuvaramachandran_gurusamy --- HdmiCecSink/HdmiCecSink.cpp | 28 ++++++++++++++++-------- Tests/L1Tests/tests/test_HdmiCecSink.cpp | 2 -- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/HdmiCecSink/HdmiCecSink.cpp b/HdmiCecSink/HdmiCecSink.cpp index b5150cf8..ecb5415e 100644 --- a/HdmiCecSink/HdmiCecSink.cpp +++ b/HdmiCecSink/HdmiCecSink.cpp @@ -3531,15 +3531,25 @@ namespace WPEFramework { int err; dsGetHDMIARCPortIdParam_t param; - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, - (void *)¶m, - sizeof(param)); - if (IARM_RESULT_SUCCESS == err) - { - LOGINFO("HDMI ARC port ID HdmiArcPortID=[%d] \n", param.portId); - HdmiArcPortID = param.portId; - } + unsigned int retryCount = 1; + do { + usleep(50000); // Sleep for 50ms before retrying + param.portId = -1; // Initialize to an invalid port ID + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, + (void *)¶m, + sizeof(param)); + if (IARM_RESULT_SUCCESS == err) + { + LOGINFO("HDMI ARC port ID HdmiArcPortID[%d] on retry count[%d]", param.portId, retryCount); + HdmiArcPortID = param.portId; + break; + } + else + { + LOGWARN("IARM_Bus_Call failed with error[%d], retry count[%d]", err, retryCount); + } + } while(retryCount++ <= 6); } void HdmiCecSink::getCecVersion() diff --git a/Tests/L1Tests/tests/test_HdmiCecSink.cpp b/Tests/L1Tests/tests/test_HdmiCecSink.cpp index 38631077..22df165c 100755 --- a/Tests/L1Tests/tests/test_HdmiCecSink.cpp +++ b/Tests/L1Tests/tests/test_HdmiCecSink.cpp @@ -23,8 +23,6 @@ #include -#include "HdmiCecSinkImplementation.h" -#include "HdmiCecSinkMock.h" #include "HdmiCecSink.h" #include "FactoriesImplementation.h" #include "IarmBusMock.h" From b12cd97a05c2dc2b7915cfac28c998fb2277d349 Mon Sep 17 00:00:00 2001 From: siva aditya varma uppalapati Date: Wed, 23 Jul 2025 10:33:32 +0000 Subject: [PATCH 31/52] 1.3.5 release changelog updates --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f24687d..e60fb2bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,17 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.3.5](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.4...1.3.5) + +- RDKEMW-6230: Retry logic used dsGetHDMIARCPortId in HdmiCecSink [`#203`](https://github.com/rdkcentral/entservices-inputoutput/pull/203) +- Merge tag '1.3.4' into develop [`760ee0f`](https://github.com/rdkcentral/entservices-inputoutput/commit/760ee0f9da46e0b0ed2e2adb4523bfec85c5a927) + #### [1.3.4](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.3...1.3.4) +> 22 July 2025 + - RDKEMW-6279: Revert of HdmiCecSink comrpc changes (#129) [`#199`](https://github.com/rdkcentral/entservices-inputoutput/pull/199) +- RDKEMW-6279 - Changelog updates for 1.3.4 [`8a6fd55`](https://github.com/rdkcentral/entservices-inputoutput/commit/8a6fd55be4c187be3c725d2ca6512720bd6c018b) - Merge tag '1.3.3' into develop [`7abaec3`](https://github.com/rdkcentral/entservices-inputoutput/commit/7abaec32ed58c36ef05640ca9baaf8077b90a5d5) #### [1.3.3](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.2...1.3.3) From 7b417c62cb1d8daf4ede73b9ca1cf39bb43a66f3 Mon Sep 17 00:00:00 2001 From: Anju Raveendran Date: Tue, 22 Jul 2025 11:01:30 +0100 Subject: [PATCH 32/52] RDKEMW-6325: platfromSupport is missing from dimmingMode capabilities Reason For Change: platfromSupport is missing from getBacklightDimmingModeCaps Test procedure: Mentioned in the ticket Risks: Low Signed-off-by: anju.raveendran@sky.uk --- AVOutput/AVOutputTV.cpp | 14 ++++++++++++++ AVOutput/AVOutputTVHelper.cpp | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/AVOutput/AVOutputTV.cpp b/AVOutput/AVOutputTV.cpp index 3f0e8e59..b686669c 100644 --- a/AVOutput/AVOutputTV.cpp +++ b/AVOutput/AVOutputTV.cpp @@ -2016,6 +2016,10 @@ namespace Plugin { returnResponse(false); } + if (isPlatformSupport("DimmingMode") != 0) { + returnResponse(false); + } + if (getParamIndex("DimmingMode",inputInfo,indexInfo) == -1) { LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); returnResponse(false); @@ -2072,6 +2076,10 @@ namespace Plugin { returnResponse(false); } + if (isPlatformSupport("DimmingMode") != 0) { + returnResponse(false); + } + if( !isCapablityCheckPassed( "DimmingMode" , inputInfo )) { LOGERR("%s: CapablityCheck failed for DimmingMode\n", __FUNCTION__); returnResponse(false); @@ -2118,6 +2126,10 @@ namespace Plugin { returnResponse(false); } + if (isPlatformSupport("DimmingMode") != 0) { + returnResponse(false); + } + int retval= updateAVoutputTVParam("reset","DimmingMode", inputInfo,PQ_PARAM_DIMMINGMODE,dMode); if(retval != 0 ) { @@ -2171,6 +2183,8 @@ namespace Plugin { returnResponse(false); } else { + response["platformSupport"] = (info.isPlatformSupportVector[0].compare("true") == 0) ? true : false; + for (index = 0; index < info.rangeVector.size(); index++) { supportedDimmingModeArray.Add(info.rangeVector[index]); } diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index 527569a9..6fbcbab0 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -2302,7 +2302,7 @@ namespace Plugin { } - if ((param == "DolbyVisionMode") || (param == "Backlight") || (param == "CMS") || (param == "CustomWhiteBalance") || (param == "HDRMode") || (param == "BacklightControl")) { + if ((param == "DolbyVisionMode") || (param == "Backlight") || (param == "CMS") || (param == "CustomWhiteBalance") || (param == "HDRMode") || (param == "BacklightControl") || (param == "DimmingMode")) { configString = param + ".platformsupport"; info.isPlatformSupport = inFile.Get(configString); printf(" platformsupport : %s\n",info.isPlatformSupport.c_str() ); From 008fa89376b48570d81b21e87c53914da789931c Mon Sep 17 00:00:00 2001 From: PriyaPesala <116076033+PriyaPesala@users.noreply.github.com> Date: Thu, 24 Jul 2025 16:46:15 +0530 Subject: [PATCH 33/52] [RDKEMW-3513] PR action to run with latest change (#163) * [RDKEMW-3513] PR action to run with latest change * Modifying L1,L2 .yml * Modifying artifacts job name * resolving review comments * modifying testframework branch name to develop * pointing to develop * Update tests-trigger.yml --------- Co-authored-by: Prathyushakothuru <142974139+Prathyushakothuru@users.noreply.github.com> Co-authored-by: kprathyusha --- .github/workflows/L1-tests.yml | 16 +++++++++++----- .github/workflows/L2-tests.yml | 18 ++++++++++++------ .github/workflows/tests-trigger.yml | 21 +++++++++++++++++++++ 3 files changed, 44 insertions(+), 11 deletions(-) create mode 100755 .github/workflows/tests-trigger.yml diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 6121092a..f5dfb136 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -1,10 +1,10 @@ name: L1-tests on: - push: - branches: [ main, develop, 'sprint/**', 'release/**' ] - pull_request: - branches: [ main, develop, 'sprint/**', 'release/**' ] + workflow_call: + secrets: + RDKCM_RDKE: + required: true env: BUILD_TYPE: Debug @@ -66,6 +66,10 @@ jobs: python-version: '3.x' - run: pip install jsonref + - name: ACK External Trigger + run: | + echo "Message: External Trigger Received for L1 Tests" + - name: Set up CMake uses: jwlawson/actions-setup-cmake@v1.13 with: @@ -119,7 +123,9 @@ jobs: - name: Checkout entservices-inputoutput uses: actions/checkout@v3 with: + repository: rdkcentral/entservices-inputoutput path: entservices-inputoutput + ref: develop - name: Checkout googletest if: steps.cache.outputs.cache-hit != 'true' @@ -667,7 +673,7 @@ jobs: if: ${{ !env.ACT }} uses: actions/upload-artifact@v4 with: - name: artifacts + name: artifacts-L1-inputoutput path: | coverage/ valgrind_log diff --git a/.github/workflows/L2-tests.yml b/.github/workflows/L2-tests.yml index c8a13eb5..9dc033be 100755 --- a/.github/workflows/L2-tests.yml +++ b/.github/workflows/L2-tests.yml @@ -1,10 +1,10 @@ name: L2-tests on: - push: - branches: [ main, develop, 'sprint/**', 'release/**' ] - pull_request: - branches: [ main, develop, 'sprint/**', 'release/**' ] + workflow_call: + secrets: + RDKCM_RDKE: + required: true env: BUILD_TYPE: Debug @@ -36,6 +36,10 @@ jobs: python-version: '3.x' - run: pip install jsonref + - name: ACK External Trigger + run: | + echo "Message: External Trigger Received for L2 Tests" + - name: Set up CMake uses: jwlawson/actions-setup-cmake@v1.13 with: @@ -81,7 +85,9 @@ jobs: - name: Checkout entservices-inputoutput uses: actions/checkout@v3 with: + repository: rdkcentral/entservices-inputoutput path: entservices-inputoutput + ref: develop - name: Checkout entservices-testframework uses: actions/checkout@v3 @@ -375,7 +381,7 @@ jobs: -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/iarmmgrs-hal -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices/proc - -I $GITHUB_WORKSPACE/entservices-deviceanddisplay/helpers + -I $GITHUB_WORKSPACE/entservices-inputoutput/helpers -I $GITHUB_WORKSPACE/install/usr/include -I $GITHUB_WORKSPACE/install/usr/include/WPEFramework -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h @@ -581,7 +587,7 @@ jobs: if: ${{ !env.ACT }} uses: actions/upload-artifact@v4 with: - name: artifacts + name: artifacts-L2-inputoutput path: | coverage/ valgrind_log diff --git a/.github/workflows/tests-trigger.yml b/.github/workflows/tests-trigger.yml new file mode 100755 index 00000000..3aa84f0f --- /dev/null +++ b/.github/workflows/tests-trigger.yml @@ -0,0 +1,21 @@ +permissions: + contents: read +name: main-workflow + +on: + push: + branches: [ main, develop, 'sprint/**', 'release/**' ] + pull_request: + branches: [ main, develop, 'sprint/**', 'release/**' ] + +jobs: + trigger-L1: + uses: ./.github/workflows/L1-tests.yml + secrets: + RDKCM_RDKE: ${{ secrets.RDKCM_RDKE }} + + trigger-L2: + uses: ./.github/workflows/L2-tests.yml + secrets: + RDKCM_RDKE: ${{ secrets.RDKCM_RDKE }} + From cc6cb216e9e1a36cc8527db723046391676812f0 Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Thu, 24 Jul 2025 19:56:49 +0530 Subject: [PATCH 34/52] RDKEMW-2942 : Remove the HdmiInput plugin and replace its references with AVInput (#205) Co-authored-by: apatel859 <48992974+apatel859@users.noreply.github.com> --- .github/workflows/L1-tests.yml | 2 - CMakeLists.txt | 4 - HdmiInput/CHANGELOG.md | 27 - HdmiInput/CMakeLists.txt | 64 -- HdmiInput/HdmiInput.conf.in | 4 - HdmiInput/HdmiInput.config | 7 - HdmiInput/HdmiInput.cpp | 1454 ------------------------ HdmiInput/HdmiInput.h | 139 --- HdmiInput/Module.cpp | 22 - HdmiInput/Module.h | 29 - HdmiInput/README.md | 9 - HdmiInput/cmake/FindDS.cmake | 57 - HdmiInput/cmake/FindIARMBus.cmake | 44 - Tests/L1Tests/CMakeLists.txt | 3 - Tests/L1Tests/tests/test_HdmiInput.cpp | 861 -------------- 15 files changed, 2726 deletions(-) delete mode 100644 HdmiInput/CHANGELOG.md delete mode 100644 HdmiInput/CMakeLists.txt delete mode 100644 HdmiInput/HdmiInput.conf.in delete mode 100644 HdmiInput/HdmiInput.config delete mode 100644 HdmiInput/HdmiInput.cpp delete mode 100644 HdmiInput/HdmiInput.h delete mode 100644 HdmiInput/Module.cpp delete mode 100644 HdmiInput/Module.h delete mode 100644 HdmiInput/README.md delete mode 100644 HdmiInput/cmake/FindDS.cmake delete mode 100644 HdmiInput/cmake/FindIARMBus.cmake delete mode 100644 Tests/L1Tests/tests/test_HdmiInput.cpp diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index f5dfb136..0b5cfccd 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -443,7 +443,6 @@ jobs: -DHAS_FRONT_PANEL=ON -DRDK_SERVICES_L1_TEST=ON -DPLUGIN_AVINPUT=ON - -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON -DPLUGIN_HDMICECSINK=ON @@ -521,7 +520,6 @@ jobs: -DCMAKE_BUILD_TYPE=Debug -DDS_FOUND=ON -DPLUGIN_AVINPUT=ON - -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON -DPLUGIN_HDMICECSINK=ON diff --git a/CMakeLists.txt b/CMakeLists.txt index df70686a..6a222334 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,10 +64,6 @@ if(PLUGIN_HDCPPROFILE) add_subdirectory(HdcpProfile) endif() -if(PLUGIN_HDMIINPUT) - add_subdirectory(HdmiInput) -endif() - if(WPEFRAMEWORK_CREATE_IPKG_TARGETS) set(CPACK_GENERATOR "DEB") diff --git a/HdmiInput/CHANGELOG.md b/HdmiInput/CHANGELOG.md deleted file mode 100644 index 3e73c318..00000000 --- a/HdmiInput/CHANGELOG.md +++ /dev/null @@ -1,27 +0,0 @@ -# Changelog - -All notable changes to this RDK Service will be documented in this file. - -* Each RDK Service has a CHANGELOG file that contains all changes done so far. When version is updated, add a entry in the CHANGELOG.md at the top with user friendly information on what was changed with the new version. Please don't mention JIRA tickets in CHANGELOG. - -* Please Add entry in the CHANGELOG for each version change and indicate the type of change with these labels: - * **Added** for new features. - * **Changed** for changes in existing functionality. - * **Deprecated** for soon-to-be removed features. - * **Removed** for now removed features. - * **Fixed** for any bug fixes. - * **Security** in case of vulnerabilities. - -* Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. - -## [1.4.0] - 2025-02-17 -### Added -- Added support for Getting the Maximum HDMI Compatibility version for the given port. - -## [1.0.0] - 2025-02-17 -### Added -- Add CHANGELOG - -### Change -- Reset API version to 1.0.0 -- Change README to inform how to update changelog and API version diff --git a/HdmiInput/CMakeLists.txt b/HdmiInput/CMakeLists.txt deleted file mode 100644 index b5d667a4..00000000 --- a/HdmiInput/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -# If not stated otherwise in this file or this component's license file the -# following copyright and licenses apply: -# -# Copyright 2020 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. - -set(PLUGIN_NAME HdmiInput) -set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) - -set(PLUGIN_HDMIINPUT_STARTUPORDER "" CACHE STRING "To configure startup order of HdmiInput plugin") - -find_package(${NAMESPACE}Plugins REQUIRED) -if (USE_THUNDER_R4) - find_package(${NAMESPACE}COM REQUIRED) -else () - find_package(${NAMESPACE}Protocols REQUIRED) -endif (USE_THUNDER_R4) - -add_library(${MODULE_NAME} SHARED - HdmiInput.cpp - Module.cpp - ) - -set_target_properties(${MODULE_NAME} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES) - -target_compile_definitions(${MODULE_NAME} PRIVATE MODULE_NAME=Plugin_${PLUGIN_NAME}) - -target_include_directories(${MODULE_NAME} PRIVATE ../helpers) - -if (USE_THUNDER_R4) -target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}COM::${NAMESPACE}COM) -else () -target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Protocols::${NAMESPACE}Protocols) -endif (USE_THUNDER_R4) - - -find_package(DS) -find_package(IARMBus) - -target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) -target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) -target_include_directories(${MODULE_NAME} PRIVATE ../helpers) - -set_source_files_properties(HdmiInput.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") - -target_link_libraries(${MODULE_NAME} PUBLIC ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${DS_LIBRARIES} ) - -install(TARGETS ${MODULE_NAME} - DESTINATION lib/${STORAGE_DIRECTORY}/plugins) - -write_config(${PLUGIN_NAME}) diff --git a/HdmiInput/HdmiInput.conf.in b/HdmiInput/HdmiInput.conf.in deleted file mode 100644 index e16bde27..00000000 --- a/HdmiInput/HdmiInput.conf.in +++ /dev/null @@ -1,4 +0,0 @@ -precondition = ["Platform"] -callsign = "org.rdk.HdmiInput" -autostart = "false" -startuporder = "@PLUGIN_HDMIINPUT_STARTUPORDER@" diff --git a/HdmiInput/HdmiInput.config b/HdmiInput/HdmiInput.config deleted file mode 100644 index 2b918b14..00000000 --- a/HdmiInput/HdmiInput.config +++ /dev/null @@ -1,7 +0,0 @@ -set (autostart false) -set (preconditions Platform) -set (callsign "org.rdk.HdmiInput") - -if(PLUGIN_HDMIINPUT_STARTUPORDER) -set (startuporder ${PLUGIN_HDMIINPUT_STARTUPORDER}) -endif() diff --git a/HdmiInput/HdmiInput.cpp b/HdmiInput/HdmiInput.cpp deleted file mode 100644 index ef53a03a..00000000 --- a/HdmiInput/HdmiInput.cpp +++ /dev/null @@ -1,1454 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 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. -**/ - -#include "HdmiInput.h" -#include "UtilsJsonRpc.h" -#include "UtilsIarm.h" - -#include "hdmiIn.hpp" -#include "exception.hpp" -#include "dsUtl.h" -#include "dsError.h" -#include "dsMgr.h" -#include "host.hpp" - -#include -#include - -#define HDMI_HOT_PLUG_EVENT_CONNECTED 0 -#define HDMI_HOT_PLUG_EVENT_DISCONNECTED 1 - -#define HDMIINPUT_METHOD_GET_HDMI_INPUT_DEVICES "getHDMIInputDevices" -#define HDMIINPUT_METHOD_WRITE_EDID "writeEDID" -#define HDMIINPUT_METHOD_READ_EDID "readEDID" -#define HDMIINPUT_METHOD_READ_RAWHDMISPD "getRawHDMISPD" -#define HDMIINPUT_METHOD_READ_HDMISPD "getHDMISPD" -#define HDMIINPUT_METHOD_SET_EDID_VERSION "setEdidVersion" -#define HDMIINPUT_METHOD_GET_EDID_VERSION "getEdidVersion" -#define HDMIINPUT_METHOD_SET_MIXER_LEVELS "setMixerLevels" -#define HDMIINPUT_METHOD_START_HDMI_INPUT "startHdmiInput" -#define HDMIINPUT_METHOD_STOP_HDMI_INPUT "stopHdmiInput" -#define HDMIINPUT_METHOD_SCALE_HDMI_INPUT "setVideoRectangle" -#define HDMIINPUT_METHOD_SUPPORTED_GAME_FEATURES "getSupportedGameFeatures" -#define HDMIINPUT_METHOD_GAME_FEATURE_STATUS "getHdmiGameFeatureStatus" - -#define HDMIINPUT_EVENT_ON_DEVICES_CHANGED "onDevicesChanged" -#define HDMIINPUT_EVENT_ON_SIGNAL_CHANGED "onSignalChanged" -#define HDMIINPUT_EVENT_ON_STATUS_CHANGED "onInputStatusChanged" -#define HDMIINPUT_EVENT_ON_VIDEO_MODE_UPDATED "videoStreamInfoUpdate" -#define HDMIINPUT_EVENT_ON_GAME_FEATURE_STATUS_CHANGED "hdmiGameFeatureStatusUpdate" -#define HDMIINPUT_EVENT_ON_AVI_CONTENT_TYPE_CHANGED "hdmiContentTypeUpdate" -#define HDMIINPUT_METHOD_GET_LOW_LATENCY_MODE "getTVLowLatencyMode" -#define HDMIINPUT_METHOD_GET_AV_LATENCY "getAVLatency" -#define HDMIINPUT_METHOD_GET_HDMI_COMPATIBILITY_VERSION "getHdmiVersion" - -#define HDMICECSINK_CALLSIGN "org.rdk.HdmiCecSink" -#define HDMICECSINK_CALLSIGN_VER HDMICECSINK_CALLSIGN".1" -#define TVSETTINGS_CALLSIGN "org.rdk.tv.ControlSettings" -#define TVSETTINGS_CALLSIGN_VER TVSETTINGS_CALLSIGN".2" - -// TODO: remove this -#define registerMethod(...) for (uint8_t i = 1; GetHandler(i); i++) GetHandler(i)->Register(__VA_ARGS__) - -#define API_VERSION_NUMBER_MAJOR 1 -#define API_VERSION_NUMBER_MINOR 4 -#define API_VERSION_NUMBER_PATCH 0 - -static int audio_output_delay = 100; -static int video_latency = 20; -#define TVMGR_GAME_MODE_EVENT "gameModeEvent" -static bool lowLatencyMode = false; -#define SERVER_DETAILS "127.0.0.1:9998" -static int planeType = 0; -static bool isAudioBalanceSet = false; -using namespace std; - -namespace WPEFramework -{ - namespace { - - static Plugin::Metadata metadata( - // Version (Major, Minor, Patch) - API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH, - // Preconditions - {}, - // Terminations - {}, - // Controls - {} - ); - } - - namespace Plugin - { - SERVICE_REGISTRATION(HdmiInput, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - - HdmiInput* HdmiInput::_instance = nullptr; - - HdmiInput::HdmiInput() - : PluginHost::JSONRPC() - { - HdmiInput::_instance = this; - - m_tv_client = nullptr; - m_client = nullptr; - //InitializeIARM(); - - CreateHandler({2}); - - registerMethod(HDMIINPUT_METHOD_GET_HDMI_INPUT_DEVICES, &HdmiInput::getHDMIInputDevicesWrapper, this); - registerMethod(HDMIINPUT_METHOD_WRITE_EDID, &HdmiInput::writeEDIDWrapper, this); - registerMethod(HDMIINPUT_METHOD_READ_EDID, &HdmiInput::readEDIDWrapper, this); - registerMethod(HDMIINPUT_METHOD_READ_RAWHDMISPD, &HdmiInput::getRawHDMISPDWrapper, this); - registerMethod(HDMIINPUT_METHOD_READ_HDMISPD, &HdmiInput::getHDMISPDWrapper, this); - registerMethod(HDMIINPUT_METHOD_SET_EDID_VERSION, &HdmiInput::setEdidVersionWrapper, this); - registerMethod(HDMIINPUT_METHOD_GET_EDID_VERSION, &HdmiInput::getEdidVersionWrapper, this); - registerMethod(HDMIINPUT_METHOD_START_HDMI_INPUT, &HdmiInput::startHdmiInput, this); - registerMethod(HDMIINPUT_METHOD_STOP_HDMI_INPUT, &HdmiInput::stopHdmiInput, this); - registerMethod(HDMIINPUT_METHOD_SCALE_HDMI_INPUT, &HdmiInput::setVideoRectangleWrapper, this); - registerMethod(HDMIINPUT_METHOD_SET_MIXER_LEVELS, &HdmiInput::setMixerLevels, this); - registerMethod(HDMIINPUT_METHOD_SUPPORTED_GAME_FEATURES, &HdmiInput::getSupportedGameFeatures, this); - registerMethod(HDMIINPUT_METHOD_GAME_FEATURE_STATUS, &HdmiInput::getHdmiGameFeatureStatusWrapper, this); - registerMethod(HDMIINPUT_METHOD_GET_AV_LATENCY, &HdmiInput::getAVLatency, this); - registerMethod(HDMIINPUT_METHOD_GET_LOW_LATENCY_MODE, &HdmiInput::getTVLowLatencyMode, this); - registerMethod(HDMIINPUT_METHOD_GET_HDMI_COMPATIBILITY_VERSION, &HdmiInput::getHdmiVersionWrapper, this); - m_primVolume = DEFAULT_PRIM_VOL_LEVEL; - m_inputVolume = DEFAULT_INPUT_VOL_LEVEL; - } - - HdmiInput::~HdmiInput() - { - } - - const string HdmiInput::Initialize(PluginHost::IShell * service ) - { - LOGINFO("Entering HdmiInput::Initialize"); - ASSERT(service != nullptr); - ASSERT(m_service == nullptr); - - m_service = service; - m_service->AddRef(); - - HdmiInput::_instance = this; - InitializeIARM(); - - subscribeForTvMgrEvent("gameModeEvent"); - LOGINFO("Exiting HdmiInput::Initialize"); - return (string()); - } - - uint32_t HdmiInput::subscribeForTvMgrEvent(const char* eventName) - { - uint32_t err = Core::ERROR_NONE; - LOGINFO("Attempting to subscribe for event: %s\n", eventName); - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T(SERVER_DETAILS))); - if (nullptr == m_tv_client) { - getControlSettingsPlugin(); - if (nullptr == m_tv_client) { - LOGERR("JSONRPC: %s: client initialization failed", TVSETTINGS_CALLSIGN_VER); - err = Core::ERROR_UNAVAILABLE; - } - } - - if(err == Core::ERROR_NONE) { - /* Register handlers for Event reception. */ - if(strcmp(eventName, TVMGR_GAME_MODE_EVENT) == 0) { - err =m_tv_client->Subscribe(1000, eventName, &HdmiInput::onGameModeEventHandler, this); - } - else { - LOGERR("Failed to subscribe for %s with code %d", eventName, err); - } - } - return err; - } - - void setResponseArray(JsonObject& response, const char* key, const vector& items) - { - JsonArray arr; - for(auto& i : items) arr.Add(JsonValue(i)); - - response[key] = arr; - - string json; - response.ToString(json); - } - - void HdmiInput::Deinitialize(PluginHost::IShell* service ) - { - ASSERT(service == m_service); - m_service->Release(); - m_service = nullptr; - - HdmiInput::_instance = nullptr; - - DeinitializeIARM(); - } - - void HdmiInput::InitializeIARM() - { - if (Utils::IARM::init()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, dsHdmiSignalStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, dsHdmiStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, dsHdmiVideoModeEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, dsHdmiGameFeatureStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE, dsHdmiAviContentTypeEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_AV_LATENCY, dsHdmiAVLatencyEventHandler) ); - } - } - - void HdmiInput::DeinitializeIARM() - { - if (Utils::IARM::isConnected()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, dsHdmiSignalStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, dsHdmiStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, dsHdmiVideoModeEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, dsHdmiGameFeatureStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE,dsHdmiAviContentTypeEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_AV_LATENCY,dsHdmiAVLatencyEventHandler) ); - } - } - - uint32_t HdmiInput::startHdmiInput(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - - string sPortId = parameters["portId"].String(); - bool audioMix = parameters["requestAudioMix"].Boolean(); - int portId = 0; - bool topMostPlane = parameters["topMost"].Boolean(); - - //planeType = 0 - primary, 1 - secondary video plane type - planeType = 0; - try { - portId = stoi(sPortId); - if (parameters.HasLabel("plane")){ - string sPlaneType = parameters["plane"].String(); - planeType = stoi(sPlaneType); - if(!(planeType == 0 || planeType == 1))// planeType has to be primary(0) or secondary(1) - { - LOGWARN("planeType is invalid\n"); - returnResponse(false); - } - } - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - bool success = true; - try - { - device::HdmiInput::getInstance().selectPort(portId,audioMix,planeType,topMostPlane); - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(sPortId); - success = false; - } - returnResponse(success); - - } - - uint32_t HdmiInput::stopHdmiInput(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - bool success = true; - try - { - // Restoring the Audio Mixer Levels when the Input is stopped. - if (isAudioBalanceSet){ - device::Host::getInstance().setAudioMixerLevels(dsAUDIO_INPUT_PRIMARY,MAX_PRIM_VOL_LEVEL); - device::Host::getInstance().setAudioMixerLevels(dsAUDIO_INPUT_SYSTEM,DEFAULT_INPUT_VOL_LEVEL); - isAudioBalanceSet = false; - } - planeType = -1;// plane index when stopping hdmi input - device::HdmiInput::getInstance().selectPort(-1); - } - catch (const device::Exception& err) - { - LOGWARN("HdmiInputService::stopHdmiInput Failed"); - success = false; - } - returnResponse(success); - - } - uint32_t HdmiInput::setMixerLevels(const JsonObject& parameters, JsonObject& response) - { - returnIfParamNotFound(parameters, "primaryVolume"); - returnIfParamNotFound(parameters, "inputVolume"); - - int primVol = 0, inputVol = 0; - try { - primVol = parameters["primaryVolume"].Number(); - inputVol = parameters["inputVolume"].Number() ; - } catch(...) { - LOGERR("Incompatible params passed !!!\n"); - response["success"] = false; - returnResponse(false); - } - - if( (primVol >=0) && (inputVol >=0) ) { - m_primVolume = primVol; - m_inputVolume = inputVol; - } - else { - LOGERR("Incompatible params passed !!!\n"); - response["success"] = false; - returnResponse(false); - } - - if(m_primVolume > MAX_PRIM_VOL_LEVEL) { - LOGWARN("Primary Volume greater than limit. Set to MAX_PRIM_VOL_LEVEL(100) !!!\n"); - m_primVolume = MAX_PRIM_VOL_LEVEL; - } - if(m_inputVolume > DEFAULT_INPUT_VOL_LEVEL) { - LOGWARN("Input Volume greater than limit. Set to DEFAULT_INPUT_VOL_LEVEL(100) !!!\n"); - m_inputVolume = DEFAULT_INPUT_VOL_LEVEL; - } - LOGINFO("GLOBAL primary Volume=%d input Volume=%d \n",m_primVolume , m_inputVolume ); - - try{ - - device::Host::getInstance().setAudioMixerLevels(dsAUDIO_INPUT_PRIMARY,primVol); - device::Host::getInstance().setAudioMixerLevels(dsAUDIO_INPUT_SYSTEM,inputVol); - } - catch(...){ - LOGWARN("Not setting SoC volume !!!\n"); - returnResponse(false); - } - isAudioBalanceSet = true; - returnResponse(true); - } - - uint32_t HdmiInput::setVideoRectangleWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - bool result = true; - if (!parameters.HasLabel("x") && !parameters.HasLabel("y")) - { - result = false; - response["message"] = "please specif coordinates (x,y)"; - } - - if (!parameters.HasLabel("w") && !parameters.HasLabel("h")) - { - result = false; - response["message"] = "please specify window width and height (w,h)"; - } - - if (result) - { - int x = 0; - int y = 0; - int w = 0; - int h = 0; - - try - { - if (parameters.HasLabel("x")) - { - x = std::stoi(parameters["x"].String()); - } - if (parameters.HasLabel("y")) - { - y = std::stoi(parameters["y"].String()); - } - if (parameters.HasLabel("w")) - { - w = std::stoi(parameters["w"].String()); - } - if (parameters.HasLabel("h")) - { - h = std::stoi(parameters["h"].String()); - } - } - catch (const std::exception& err) { - LOGWARN("Invalid paramater X: %s,Y: %s, W: %s, H:%s ", parameters["x"].String().c_str(),parameters["y"].String().c_str(),parameters["w"].String().c_str(),parameters["h"].String().c_str()); - returnResponse(false); - } - - result = setVideoRectangle(x, y, w, h); - if (false == result) { - LOGWARN("HdmiInputService::setVideoRectangle Failed"); - response["message"] = "failed to set scale"; - } - } - - returnResponse(result); - - } - - bool HdmiInput::setVideoRectangle(int x, int y, int width, int height) - { - bool ret = true; - - try - { - device::HdmiInput::getInstance().scaleVideo(x, y, width, height); - } - catch (const device::Exception& err) - { - ret = false; - } - - return ret; - } - - uint32_t HdmiInput::getHDMIInputDevicesWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - response["devices"] = getHDMIInputDevices(); - - returnResponse(true); - } - - uint32_t HdmiInput::writeEDIDWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - int deviceId; - std::string message; - - if (parameters.HasLabel("deviceId") && parameters.HasLabel("message")) - { - getNumberParameter("deviceId", deviceId); - message = parameters["message"].String(); - } - else - { - LOGWARN("Required parameters are not passed"); - returnResponse(false); - } - - - writeEDID(deviceId, message); - returnResponse(true); - - } - - uint32_t HdmiInput::readEDIDWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - string sPortId = parameters.HasLabel("deviceId") ? parameters["deviceId"].String() : "0";; - int portId = 0; - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - string edid = readEDID (portId); - response["EDID"] = edid; - if (edid.empty()) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - JsonArray HdmiInput::getHDMIInputDevices() - { - JsonArray list; - try - { - int num = device::HdmiInput::getInstance().getNumberOfInputs(); - if (num > 0) { - int i = 0; - for (i = 0; i < num; i++) { - //Input ID is aleays 0-indexed, continuous number starting 0 - JsonObject hash; - hash["id"] = i; - std::stringstream locator; - locator << "hdmiin://localhost/deviceid/" << i; - hash["locator"] = locator.str(); - hash["connected"] = device::HdmiInput::getInstance().isPortConnected(i) ? "true" : "false"; - LOGWARN("HdmiInputService::getHDMIInputDevices id %d, locator=[%s], connected=[%s]", i, hash["locator"].String().c_str(), hash["connected"].String().c_str()); - list.Add(hash); - } - } - } - catch (const std::exception& e) { - LOGWARN("HdmiInputService::getHDMIInputDevices Failed"); - } - - return list; - } - - void HdmiInput::writeEDID(int deviceId, std::string message) - { - - } - - std::string HdmiInput::readEDID(int iPort) - { - vector edidVec({'u','n','k','n','o','w','n' }); - string edidbase64 = ""; - try - { - vector edidVec2; - device::HdmiInput::getInstance().getEDIDBytesInfo (iPort, edidVec2); - edidVec = edidVec2;//edidVec must be "unknown" unless we successfully get to this line - - //convert to base64 - uint16_t size = min(edidVec.size(), (size_t)numeric_limits::max()); - - LOGWARN("HdmiInput::readEDID size:%u edidVec.size:%d", size, (int)edidVec.size()); - - if(edidVec.size() > (size_t)numeric_limits::max()) { - LOGERR("Size too large to use ToString base64 wpe api"); - return edidbase64; - } - - Core::ToString((uint8_t*)&edidVec[0], size, true, edidbase64); - - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return edidbase64; - } - - /** - * @brief This function is used to translate HDMI input hotplug to - * deviceChanged event. - * - * @param[in] input Number of input port integer. - * @param[in] connection status of input port integer. - */ - void HdmiInput::hdmiInputHotplug( int input , int connect) - { - LOGWARN("hdmiInputHotplug [%d, %d]", input, connect); - - JsonObject params; - params["devices"] = getHDMIInputDevices(); - sendNotify(HDMIINPUT_EVENT_ON_DEVICES_CHANGED, params); - } - - /** - * @brief This function is used to translate HDMI input signal change to - * signalChanged event. - * - * @param[in] port HDMI In port id. - * @param[in] signalStatus signal status of HDMI In port. - */ - void HdmiInput::hdmiInputSignalChange( int port , int signalStatus) - { - LOGWARN("hdmiInputSignalStatus [%d, %d]", port, signalStatus); - - JsonObject params; - params["id"] = port; - std::stringstream locator; - locator << "hdmiin://localhost/deviceid/" << port; - params["locator"] = locator.str(); - - switch (signalStatus) { - case dsHDMI_IN_SIGNAL_STATUS_NOSIGNAL: - params["signalStatus"] = "noSignal"; - break; - - case dsHDMI_IN_SIGNAL_STATUS_UNSTABLE: - params["signalStatus"] = "unstableSignal"; - break; - - case dsHDMI_IN_SIGNAL_STATUS_NOTSUPPORTED: - params["signalStatus"] = "notSupportedSignal"; - break; - - case dsHDMI_IN_SIGNAL_STATUS_STABLE: - params["signalStatus"] = "stableSignal"; - break; - - default: - params["signalStatus"] = "none"; - break; - } - - sendNotify(HDMIINPUT_EVENT_ON_SIGNAL_CHANGED, params); - } - - /** - * @brief This function is used to translate HDMI input status change to - * inputStatusChanged event. - * - * @param[in] port HDMI In port id. - * @param[bool] isPresented HDMI In presentation started/stopped. - */ - void HdmiInput::hdmiInputStatusChange( int port , bool isPresented) - { - LOGWARN("hdmiInputStatus [%d, %d]", port, isPresented); - - JsonObject params; - params["id"] = port; - std::stringstream locator; - locator << "hdmiin://localhost/deviceid/" << port; - params["locator"] = locator.str(); - - if(isPresented) { - params["status"] = "started"; - } - else { - params["status"] = "stopped"; - } - params["plane"] = planeType; - sendNotify(HDMIINPUT_EVENT_ON_STATUS_CHANGED, params); - } - - /** - * @brief This function is used to translate HDMI input video mode change to - * videoStreamInfoUpdate event. - * - * @param[in] port HDMI In port id. - * @param[dsVideoPortResolution_t] video resolution data - */ - void HdmiInput::hdmiInputVideoModeUpdate( int port , dsVideoPortResolution_t resolution) - { - LOGWARN("hdmiInputVideoModeUpdate [%d]", port); - - JsonObject params; - params["id"] = port; - std::stringstream locator; - locator << "hdmiin://localhost/deviceid/" << port; - params["locator"] = locator.str(); - - switch(resolution.pixelResolution) { - case dsVIDEO_PIXELRES_720x480: - params["width"] = 720; - params["height"] = 480; - break; - - case dsVIDEO_PIXELRES_720x576: - params["width"] = 720; - params["height"] = 576; - break; - - case dsVIDEO_PIXELRES_1280x720: - params["width"] = 1280; - params["height"] = 720; - break; - - case dsVIDEO_PIXELRES_1920x1080: - params["width"] = 1920; - params["height"] = 1080; - break; - - case dsVIDEO_PIXELRES_3840x2160: - params["width"] = 3840; - params["height"] = 2160; - break; - - case dsVIDEO_PIXELRES_4096x2160: - params["width"] = 4096; - params["height"] = 2160; - break; - - default: - params["width"] = 1920; - params["height"] = 1080; - break; - } - - params["progressive"] = (!resolution.interlaced); - - switch(resolution.frameRate) { - case dsVIDEO_FRAMERATE_24: - params["frameRateN"] = 24000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_25: - params["frameRateN"] = 25000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_30: - params["frameRateN"] = 30000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_50: - params["frameRateN"] = 50000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_60: - params["frameRateN"] = 60000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_23dot98: - params["frameRateN"] = 24000; - params["frameRateD"] = 1001; - break; - - case dsVIDEO_FRAMERATE_29dot97: - params["frameRateN"] = 30000; - params["frameRateD"] = 1001; - break; - - case dsVIDEO_FRAMERATE_59dot94: - params["frameRateN"] = 60000; - params["frameRateD"] = 1001; - break; - case dsVIDEO_FRAMERATE_100: - params["frameRateN"] = 100000; - params["frameRateD"] = 1000; - break; - case dsVIDEO_FRAMERATE_119dot88: - params["frameRateN"] = 120000; - params["frameRateD"] = 1001; - break; - case dsVIDEO_FRAMERATE_120: - params["frameRateN"] = 120000; - params["frameRateD"] = 1000; - break; - case dsVIDEO_FRAMERATE_200: - params["frameRateN"] = 200000; - params["frameRateD"] = 1000; - break; - case dsVIDEO_FRAMERATE_239dot76: - params["frameRateN"] = 240000; - params["frameRateD"] = 1001; - break; - case dsVIDEO_FRAMERATE_240: - params["frameRateN"] = 240000; - params["frameRateD"] = 100; - break; - default: - params["frameRateN"] = 60000; - params["frameRateD"] = 1000; - break; - } - - sendNotify(HDMIINPUT_EVENT_ON_VIDEO_MODE_UPDATED, params); - } - - void HdmiInput::getHdmiCecSinkPlugin() - { - - if(m_client == nullptr) - { - LOGINFO("getting the hdmicecsink client\n"); - string token; - - // TODO: use interfaces and remove token - auto security = m_service->QueryInterfaceByCallsign("SecurityAgent"); - if (security != nullptr) { - string payload = "http://localhost"; - if (security->CreateToken( - static_cast(payload.length()), - reinterpret_cast(payload.c_str()), - token) - == Core::ERROR_NONE) { - LOGINFO("HdmiInput got security token\n"); - } - else { - LOGINFO("HdmiInput failed to get security token\n"); - } - security->Release(); - } - else { - LOGINFO("No security agent\n"); - } - - string query = "token=" + token; - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); - m_client = new WPEFramework::JSONRPC::LinkType(_T(HDMICECSINK_CALLSIGN_VER), (_T(HDMICECSINK_CALLSIGN_VER)), false, query); - LOGINFO("HdmiInput getHdmiCecSinkPlugin init m_client\n"); - } - } - - void HdmiInput::reportLatencyInfoToHdmiCecSink() - { - - PluginHost::IShell::state state; - if ((getServiceState(m_service, HDMICECSINK_CALLSIGN, state) == Core::ERROR_NONE) && (state == PluginHost::IShell::state::ACTIVATED)) { - LOGINFO("%s is active", HDMICECSINK_CALLSIGN); - - getHdmiCecSinkPlugin(); - if (!m_client) { - LOGERR("HdmiCecSink Initialisation failed\n"); - } - else { - JsonObject hdmiCecSinkResult; - JsonObject param; - - param["audioOutputDelay"] = std::to_string(audio_output_delay); - param["videoLatency"] = std::to_string(video_latency); - param["lowLatencyMode"] = std::to_string(lowLatencyMode); - param["audioOutputCompensated"] ="3";//hard-coded for now - LOGINFO("latency - Info: %d : %d, %d\n",audio_output_delay,video_latency,lowLatencyMode); - m_client->Invoke(2000, "setLatencyInfo", param, hdmiCecSinkResult); - if (!hdmiCecSinkResult["success"].Boolean()) { - LOGERR("HdmiCecSink Plugin returned error\n"); - } - } - } - else { - LOGERR("HdmiCecSink plugin not ready\n"); - } - - - } - void HdmiInput::dsHdmiAVLatencyEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_AV_LATENCY == eventId) - { - LOGINFO("received the latency mode change event in dsHdmiAVLatencyEventHandler\n"); - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - audio_output_delay = eventData->data.hdmi_in_av_latency.audio_output_delay; - video_latency= eventData->data.hdmi_in_av_latency.video_latency; - - // HdmiInput::_instance->hdmiInAVLatencyChange(audio_output_delay,video_latency); - LOGINFO("Latency Info Change occurs: AV Latencies -- Report to HdmiCecSink\n"); - HdmiInput::_instance->reportLatencyInfoToHdmiCecSink(); - } - } - - void HdmiInput::onGameModeEventHandler(const JsonObject& parameters) - { - LOGINFO("Entered in onGameModeEventHandler\n"); - lowLatencyMode = parameters["lowLatencyMode"].Boolean(); - LOGINFO("Low Latency Mode : %d\n", lowLatencyMode); - HdmiInput::_instance->reportLatencyInfoToHdmiCecSink(); - } - - void HdmiInput::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmiin_hotplug_port = eventData->data.hdmi_in_connect.port; - int hdmiin_hotplug_conn = eventData->data.hdmi_in_connect.isPortConnected; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG event data:%d", hdmiin_hotplug_port); - - HdmiInput::_instance->hdmiInputHotplug(hdmiin_hotplug_port, hdmiin_hotplug_conn ? HDMI_HOT_PLUG_EVENT_CONNECTED : HDMI_HOT_PLUG_EVENT_DISCONNECTED); - } - } - - void HdmiInput::dsHdmiSignalStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_sig_status.port; - int hdmi_in_signal_status = eventData->data.hdmi_in_sig_status.status; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS event port: %d, signal status: %d", hdmi_in_port,hdmi_in_signal_status); - - HdmiInput::_instance->hdmiInputSignalChange(hdmi_in_port, hdmi_in_signal_status); - - } - } - - void HdmiInput::dsHdmiStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_status.port; - bool hdmi_in_status = eventData->data.hdmi_in_status.isPresented; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS event port: %d, started: %d", hdmi_in_port,hdmi_in_status); - - HdmiInput::_instance->hdmiInputStatusChange(hdmi_in_port, hdmi_in_status); - - } - } - - void HdmiInput::dsHdmiVideoModeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_video_mode.port; - dsVideoPortResolution_t resolution = {}; - resolution.pixelResolution = eventData->data.hdmi_in_video_mode.resolution.pixelResolution; - resolution.interlaced = eventData->data.hdmi_in_video_mode.resolution.interlaced; - resolution.frameRate = eventData->data.hdmi_in_video_mode.resolution.frameRate; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE event port: %d, pixelResolution: %d, interlaced : %d, frameRate: %d \n", hdmi_in_port,resolution.pixelResolution, resolution.interlaced, resolution.frameRate); - - HdmiInput::_instance->hdmiInputVideoModeUpdate(hdmi_in_port, resolution); - - } - } - - void HdmiInput::dsHdmiGameFeatureStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_allm_mode.port; - bool allm_mode = eventData->data.hdmi_in_allm_mode.allm_mode; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS event port: %d, ALLM Mode: %d", hdmi_in_port,allm_mode); - - HdmiInput::_instance->hdmiInputALLMChange(hdmi_in_port, allm_mode); - } - } - - void HdmiInput::hdmiInputALLMChange( int port , bool allm_mode) - { - JsonObject params; - params["id"] = port; - params["gameFeature"] = "ALLM"; - params["mode"] = allm_mode; - - sendNotify(HDMIINPUT_EVENT_ON_GAME_FEATURE_STATUS_CHANGED, params); - } - - void HdmiInput::dsHdmiAviContentTypeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_content_type.port; - int avi_content_type = eventData->data.hdmi_in_content_type.aviContentType; - LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE event port: %d, Content Type : %d", hdmi_in_port,avi_content_type); - HdmiInput::_instance->hdmiInputAviContentTypeChange(hdmi_in_port, avi_content_type); - } - } - - void HdmiInput::hdmiInputAviContentTypeChange( int port , int content_type) - { - JsonObject params; - params["id"] = port; - params["aviContentType"] = content_type; - sendNotify(HDMIINPUT_EVENT_ON_AVI_CONTENT_TYPE_CHANGED, params); - } - - uint32_t HdmiInput::getSupportedGameFeatures(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - vector supportedFeatures; - try - { - device::HdmiInput::getInstance().getSupportedGameFeatures (supportedFeatures); - for (size_t i = 0; i < supportedFeatures.size(); i++) - { - LOGINFO("Supported Game Feature [%d]: %s\n",(int)i,supportedFeatures.at(i).c_str()); - } - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION0(); - } - - if (supportedFeatures.empty()) { - returnResponse(false); - } - else { - setResponseArray(response, "supportedGameFeatures", supportedFeatures); - returnResponse(true); - } - } - - uint32_t HdmiInput::getHdmiGameFeatureStatusWrapper(const JsonObject& parameters, JsonObject& response) - { - string sPortId = parameters["portId"].String(); - string sGameFeature = parameters["gameFeature"].String(); - int portId = 0; - - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - returnIfParamNotFound(parameters, "gameFeature"); - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - if (strcmp (sGameFeature.c_str(), "ALLM") == 0) - { - bool allm = getHdmiALLMStatus(portId); - LOGWARN("HdmiInput::getHdmiGameFeatureStatusWrapper ALLM MODE:%d", allm); - response["mode"] = allm; - } - else - { - LOGWARN("HdmiInput::getHdmiGameFeatureStatusWrapper Mode is not supported. Supported mode: ALLM"); - response["message"] = "Mode is not supported. Supported mode: ALLM"; - returnResponse(false); - } - returnResponse(true); - } - - bool HdmiInput::getHdmiALLMStatus(int iPort) - { - bool allm = false; - - try - { - device::HdmiInput::getInstance().getHdmiALLMStatus (iPort, &allm); - LOGWARN("HdmiInput::getHdmiALLMStatus ALLM MODE: %d", allm); - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return allm; - } - - uint32_t HdmiInput::getRawHDMISPDWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - - string sPortId = parameters["portId"].String(); - int portId = 0; - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - string spdInfo = getRawHDMISPD (portId); - response["HDMISPD"] = spdInfo; - if (spdInfo.empty()) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - uint32_t HdmiInput::getHDMISPDWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - - string sPortId = parameters["portId"].String(); - int portId = 0; - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - string spdInfo = getHDMISPD (portId); - response["HDMISPD"] = spdInfo; - if (spdInfo.empty()) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - std::string HdmiInput::getRawHDMISPD(int iPort) - { - LOGINFO("HdmiInput::getHDMISPDInfo"); - vector spdVect({'u','n','k','n','o','w','n' }); - std::string spdbase64 = ""; - try - { - LOGWARN("HdmiInput::getHDMISPDInfo"); - vector spdVect2; - device::HdmiInput::getInstance().getHDMISPDInfo(iPort, spdVect2); - spdVect = spdVect2;//edidVec must be "unknown" unless we successfully get to this line - - //convert to base64 - uint16_t size = min(spdVect.size(), (size_t)numeric_limits::max()); - - LOGWARN("HdmiInput::getHDMISPD size:%u spdVec.size:%d", size, (int)spdVect.size()); - - if(spdVect.size() > (size_t)numeric_limits::max()) { - LOGERR("Size too large to use ToString base64 wpe api"); - return spdbase64; - } - - LOGINFO("------------getHDMISPD: "); - for (unsigned int itr =0; itr < spdVect.size(); itr++) { - LOGINFO("%02X ", spdVect[itr]); - } - Core::ToString((uint8_t*)&spdVect[0], size, false, spdbase64); - - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return spdbase64; - } - - std::string HdmiInput::getHDMISPD(int iPort) - { - LOGINFO("HdmiInput::getHDMISPDInfo"); - vector spdVect({'u','n','k','n','o','w','n' }); - std::string spdbase64 = ""; - try - { - LOGWARN("HdmiInput::getHDMISPDInfo"); - vector spdVect2; - device::HdmiInput::getInstance().getHDMISPDInfo(iPort, spdVect2); - spdVect = spdVect2;//edidVec must be "unknown" unless we successfully get to this line - - //convert to base64 - uint16_t size = min(spdVect.size(), (size_t)numeric_limits::max()); - - LOGWARN("HdmiInput::getHDMISPD size:%u spdVec.size:%d", size, (int)spdVect.size()); - - if(spdVect.size() > (size_t)numeric_limits::max()) { - LOGERR("Size too large to use ToString base64 wpe api"); - return spdbase64; - } - - LOGINFO("------------getHDMISPD: "); - for (unsigned int itr =0; itr < spdVect.size(); itr++) { - LOGINFO("%02X ", spdVect[itr]); - } - if (spdVect.size() > 0) { - struct dsSpd_infoframe_st pre; - memcpy(&pre,spdVect.data(),sizeof(struct dsSpd_infoframe_st)); - - char str[200] = {0}; - snprintf(str, sizeof(str), "Packet Type:%02X,Version:%u,Length:%u,vendor name:%s,product des:%s,source info:%02X" -,pre.pkttype,pre.version,pre.length,pre.vendor_name,pre.product_des,pre.source_info); - spdbase64 = str; - } - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return spdbase64; - } - - uint32_t HdmiInput::setEdidVersionWrapper(const JsonObject& parameters, JsonObject& response) - { - int portId = 0; - - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - returnIfParamNotFound(parameters, "edidVersion"); - string sPortId = parameters["portId"].String(); - string sVersion = parameters["edidVersion"].String(); - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - int edidVer = -1; - if (strcmp (sVersion.c_str(), "HDMI1.4") == 0) { - edidVer = HDMI_EDID_VER_14; - } - else if (strcmp (sVersion.c_str(), "HDMI2.0") == 0) { - edidVer = HDMI_EDID_VER_20; - } - - if (edidVer < 0) { - returnResponse(false); - } - bool result = setEdidVersion (portId, edidVer); - if (result == false) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - uint32_t HdmiInput::getAVLatency(const JsonObject& parameters, JsonObject& response) - { - int audio_output_delay = 0; - int video_latency = 0; - - LOGINFO("calling HdmiInput::getHdmiDAL_AudioVideoLatency \n"); - try - { - device::HdmiInput::getInstance().getAVLatency(&audio_output_delay,&video_latency); - LOGINFO("HdmiInput::getHdmiDAL_AudioVideoLatency Audio Latency: %d, Video Latency: %d\n", audio_output_delay,video_latency); - response["AudioLatency"] = audio_output_delay; - response["VideoLatency"] = video_latency; - returnResponse(true); - } - catch(const device::Exception& err) - { - std::string api = "getHdmiDAL_AudioVideoLatency"; - LOG_DEVICE_EXCEPTION1(std::string(api)); - response["message"] = "Invalid response from getHdmiDAL_AudioVideoLatency"; - LOGINFO("ERROR:HdmiInput::getHdmiDAL_AudioVideoLatency Audio Latency: %d, Video Latency: %d\n", audio_output_delay,video_latency); - returnResponse(false); - } - - } - uint32_t HdmiInput::getHdmiVersionWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - string sPortId = parameters["portId"].String(); - int portId = 0; - - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - dsHdmiMaxCapabilityVersion_t hdmiCapVersion = HDMI_COMPATIBILITY_VERSION_14; - - try { - device::HdmiInput::getInstance().getHdmiVersion(portId, &(hdmiCapVersion)); - LOGWARN("HdmiInput::getHdmiVersion Hdmi Version:%d", hdmiCapVersion); - } - catch (const device::Exception& err) { - LOG_DEVICE_EXCEPTION1(std::to_string(portId)); - returnResponse(false); - } - - - switch ((int)hdmiCapVersion){ - case HDMI_COMPATIBILITY_VERSION_14: - response["HdmiCapabilityVersion"] = "1.4"; - break; - case HDMI_COMPATIBILITY_VERSION_20: - response["HdmiCapabilityVersion"] = "2.0"; - break; - case HDMI_COMPATIBILITY_VERSION_21: - response["HdmiCapabilityVersion"] = "2.1"; - break; - } - - - if(hdmiCapVersion == HDMI_COMPATIBILITY_VERSION_MAX) - { - returnResponse(false); - }else{ - returnResponse(true); - } - } - - uint32_t HdmiInput::getServiceState(PluginHost::IShell* shell, const string& callsign, PluginHost::IShell::state& state) - { - LOGINFO("entering getServiceState\n"); - uint32_t result; - auto interface = shell->QueryInterfaceByCallsign(callsign); - LOGINFO("received interface:\n"); - - if (interface == nullptr) { - result = Core::ERROR_UNAVAILABLE; - LOGINFO("no IShell\n"); - } - else { - result = Core::ERROR_NONE; - state = interface->State(); - LOGINFO("IShell state\n"); - interface->Release(); - } - LOGINFO("at the end of getSErviceState\n"); - return result; - } - - void HdmiInput::getControlSettingsPlugin() - { - LOGINFO("entering getControlSettingsPlugin\n"); - if(m_tv_client == nullptr) - { - LOGINFO("in if case\n"); - string token; - - // TODO: use interfaces and remove token - auto security = m_service->QueryInterfaceByCallsign("SecurityAgent"); - LOGINFO("received security code\n"); - if (security != nullptr) { - string payload = "http://localhost"; - if (security->CreateToken( - static_cast(payload.length()), - reinterpret_cast(payload.c_str()), - token) - == Core::ERROR_NONE) - { - LOGINFO("ControlSettings got security token\n"); - } - else { - LOGINFO("ControlSettings failed to get security token\n"); - } - security->Release(); - } - else { - LOGINFO("No security agent\n"); - } - - string query = "token=" + token; - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); - m_tv_client = new WPEFramework::JSONRPC::LinkType(_T(TVSETTINGS_CALLSIGN_VER), (_T(TVSETTINGS_CALLSIGN_VER)), false, query); - LOGINFO("HdmiInput getControlSettingsPlugin init m_tv_client\n"); - } - } - - uint32_t HdmiInput::getTVLowLatencyMode(const JsonObject& parameters, JsonObject& response) - { - PluginHost::IShell::state state; - LOGINFOMETHOD(); - if ((getServiceState(m_service, TVSETTINGS_CALLSIGN, state) == Core::ERROR_NONE) && (state == PluginHost::IShell::state::ACTIVATED)) - { - LOGINFO("%s is active", TVSETTINGS_CALLSIGN); - - getControlSettingsPlugin(); - if(!m_tv_client) - { - LOGERR("TV Settings Initialisation failed\n"); - } - else{ - - JsonObject result; - JsonObject param; - - - int llmode = 0; - m_tv_client->Invoke(2000, "getLowLatencyState", param, result); - - if(result["success"].Boolean()) - { - string value = result.HasLabel("lowLatencyState") ? result["lowLatencyState"].String() : ""; - llmode = stoi(value); - - LOGINFO("value of the result: %d\n",llmode); - - if(llmode){ - response["lowLatencyMode"] = true; - LOGINFO("Low Latency Mode is enabled\n"); - returnResponse(true); - } - else{ - response["lowLatencyMode"] = false; - LOGINFO("Low Latency Mode is disabled\n"); - returnResponse(true); - } - } - else{ - - LOGERR("control settings Plugin returned error\n"); - returnResponse(false); - - } - } - } - else - { - LOGERR("control settings Plugin not ready\n"); - returnResponse(false); - } - - returnResponse(true); - } - - int HdmiInput::setEdidVersion(int iPort, int iEdidVer) - { - bool ret = true; - try - { - device::HdmiInput::getInstance().setEdidVersion (iPort, iEdidVer); - LOGWARN("HdmiInput::setEdidVersion EDID Version:%d", iEdidVer); - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - ret = false; - } - return ret; - } - - uint32_t HdmiInput::getEdidVersionWrapper(const JsonObject& parameters, JsonObject& response) - { - string sPortId = parameters["portId"].String(); - int portId = 0; - - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - int edidVer = getEdidVersion (portId); - switch (edidVer) - { - case HDMI_EDID_VER_14: - response["edidVersion"] = "HDMI1.4"; - break; - case HDMI_EDID_VER_20: - response["edidVersion"] = "HDMI2.0"; - break; - } - - if (edidVer < 0) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - int HdmiInput::getEdidVersion(int iPort) - { - int edidVersion = -1; - - try - { - device::HdmiInput::getInstance().getEdidVersion (iPort, &edidVersion); - LOGWARN("HdmiInput::getEdidVersion EDID Version:%d", edidVersion); - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return edidVersion; - } - - } // namespace Plugin -} // namespace WPEFramework diff --git a/HdmiInput/HdmiInput.h b/HdmiInput/HdmiInput.h deleted file mode 100644 index ff93202e..00000000 --- a/HdmiInput/HdmiInput.h +++ /dev/null @@ -1,139 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 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. -**/ - -#pragma once - -#include "libIBus.h" - -#include "Module.h" -#include "dsTypes.h" - -#define DEFAULT_PRIM_VOL_LEVEL 25 -#define MAX_PRIM_VOL_LEVEL 100 -#define DEFAULT_INPUT_VOL_LEVEL 100 - -namespace WPEFramework { - - namespace Plugin { - - // This is a server for a JSONRPC communication channel. - // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. - // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. - // This realization of this interface implements, by default, the following methods on this plugin - // - exists - // - register - // - unregister - // Any other methood to be handled by this plugin can be added can be added by using the - // templated methods Register on the PluginHost::JSONRPC class. - // As the registration/unregistration of notifications is realized by the class PluginHost::JSONRPC, - // this class exposes a public method called, Notify(), using this methods, all subscribed clients - // will receive a JSONRPC message as a notification, in case this method is called. - class HdmiInput : public PluginHost::IPlugin, public PluginHost::JSONRPC { - private: - - // We do not allow this plugin to be copied !! - HdmiInput(const HdmiInput&) = delete; - HdmiInput& operator=(const HdmiInput&) = delete; - - void InitializeIARM(); - void DeinitializeIARM(); - int m_primVolume; - int m_inputVolume; //Player Volume - - //Begin methods - uint32_t getHDMIInputDevicesWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t writeEDIDWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t readEDIDWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getRawHDMISPDWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getHDMISPDWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setEdidVersionWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getEdidVersionWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t startHdmiInput(const JsonObject& parameters, JsonObject& response); - uint32_t stopHdmiInput(const JsonObject& parameters, JsonObject& response); - uint32_t setMixerLevels(const JsonObject& parameters, JsonObject& response); - uint32_t setVideoRectangleWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getSupportedGameFeatures(const JsonObject& parameters, JsonObject& response); - uint32_t getHdmiGameFeatureStatusWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getAVLatency(const JsonObject& parameters, JsonObject& response); - uint32_t getTVLowLatencyMode(const JsonObject& parameters, JsonObject& response); - uint32_t getHdmiVersionWrapper(const JsonObject& parameters, JsonObject& response); - //End methods - - JsonArray getHDMIInputDevices(); - void writeEDID(int deviceId, std::string message); - std::string readEDID(int iPort); - std::string getRawHDMISPD(int iPort); - std::string getHDMISPD(int iPort); - int setEdidVersion(int iPort, int iEdidVer); - int getEdidVersion(int iPort); - bool getHdmiALLMStatus(int iPort); - - bool setVideoRectangle(int x, int y, int width, int height); - - void getControlSettingsPlugin(); - void getHdmiCecSinkPlugin(void); - PluginHost::IShell* m_service = nullptr; - WPEFramework::JSONRPC::LinkType* m_client; - WPEFramework::JSONRPC::LinkType* m_tv_client; - std::vector m_clientRegisteredEventNames; - uint32_t getServiceState(PluginHost::IShell* shell, const string& callsign, PluginHost::IShell::state& state); - - void hdmiInputHotplug( int input , int connect); - static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputSignalChange( int port , int signalStatus); - static void dsHdmiSignalStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputStatusChange( int port , bool isPresented); - static void dsHdmiStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputVideoModeUpdate( int port , dsVideoPortResolution_t resolution); - static void dsHdmiVideoModeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputALLMChange( int port , bool allmMode); - static void dsHdmiGameFeatureStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputAviContentTypeChange(int port, int content_type); - static void dsHdmiAviContentTypeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInAVLatencyChange(int audio_output_delay,int video_latency); - static void dsHdmiAVLatencyEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void reportLatencyInfoToHdmiCecSink(); - void onGameModeEventHandler(const JsonObject& parameters); - uint32_t subscribeForTvMgrEvent(const char* eventName); - public: - HdmiInput(); - virtual ~HdmiInput(); - virtual const string Initialize(PluginHost::IShell* shell) override; - virtual void Deinitialize(PluginHost::IShell* service) override; - virtual string Information() const override { return {}; } - - void terminate(); - - BEGIN_INTERFACE_MAP(HdmiInput) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - END_INTERFACE_MAP - - public: - static HdmiInput* _instance; - }; - } // namespace Plugin -} // namespace WPEFramework diff --git a/HdmiInput/Module.cpp b/HdmiInput/Module.cpp deleted file mode 100644 index ce759b61..00000000 --- a/HdmiInput/Module.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 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. -**/ - -#include "Module.h" - -MODULE_NAME_DECLARATION(BUILD_REFERENCE) diff --git a/HdmiInput/Module.h b/HdmiInput/Module.h deleted file mode 100644 index 54e672c3..00000000 --- a/HdmiInput/Module.h +++ /dev/null @@ -1,29 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 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. -**/ - -#pragma once -#ifndef MODULE_NAME -#define MODULE_NAME Plugin_HdmiInput -#endif - -#include -#include - -#undef EXTERNAL -#define EXTERNAL diff --git a/HdmiInput/README.md b/HdmiInput/README.md deleted file mode 100644 index 998e3280..00000000 --- a/HdmiInput/README.md +++ /dev/null @@ -1,9 +0,0 @@ ------------------ -Build: - -bitbake wpeframework-service-plugins - ------------------ -Test: - -curl --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0","id":"3","method": "HdmiInput.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/HdmiInput/cmake/FindDS.cmake b/HdmiInput/cmake/FindDS.cmake deleted file mode 100644 index 926c02e0..00000000 --- a/HdmiInput/cmake/FindDS.cmake +++ /dev/null @@ -1,57 +0,0 @@ -# If not stated otherwise in this file or this component's license file the -# following copyright and licenses apply: -# -# Copyright 2020 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. - -# - Try to find Display Settings library -# Once done this will define -# DS_FOUND - System has DS -# DS_INCLUDE_DIRS - The DS include directories -# DS_LIBRARIES - The libraries needed to use DS -# DS_FLAGS - The flags needed to use DS -# - -find_package(PkgConfig) - -find_library(DS_LIBRARIES NAMES ds) -find_path(DS_INCLUDE_DIRS NAMES hdmiIn.hpp PATH_SUFFIXES rdk/ds) - -set(DS_LIBRARIES ${DS_LIBRARIES}) -set(DS_LIBRARIES ${DS_LIBRARIES} CACHE PATH "Path to DS library") -set(DS_INCLUDE_DIRS ${DS_INCLUDE_DIRS}) -set(DS_INCLUDE_DIRS ${DS_INCLUDE_DIRS} CACHE PATH "Path to DS include") - - -find_library(DS_LIBRARIES NAMES ds) -#find_library(DSHAL_LIBRARIES NAMES dshalcli) -#find_path(DS_INCLUDE_DIRS NAMES manager.hpp PATH_SUFFIXES rdk/ds) -find_path(DSHAL_INCLUDE_DIRS NAMES dsTypes.h PATH_SUFFIXES rdk/halif/ds-hal) -find_path(DSRPC_INCLUDE_DIRS NAMES dsMgr.h PATH_SUFFIXES rdk/ds-rpc) - -#set(DS_LIBRARIES ${DS_LIBRARIES} ${DSHAL_LIBRARIES}) -#set(DS_LIBRARIES ${DS_LIBRARIES} CACHE PATH "Path to DS library") -set(DS_INCLUDE_DIRS ${DS_INCLUDE_DIRS} ${DSHAL_INCLUDE_DIRS} ${DSRPC_INCLUDE_DIRS}) -#set(DS_INCLUDE_DIRS ${DS_INCLUDE_DIRS} CACHE PATH "Path to DS include") - - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(DS DEFAULT_MSG DS_INCLUDE_DIRS DS_LIBRARIES) - -mark_as_advanced( - DS_FOUND - DS_INCLUDE_DIRS - DS_LIBRARIES - DS_LIBRARY_DIRS - DS_FLAGS) diff --git a/HdmiInput/cmake/FindIARMBus.cmake b/HdmiInput/cmake/FindIARMBus.cmake deleted file mode 100644 index bc716bcd..00000000 --- a/HdmiInput/cmake/FindIARMBus.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# If not stated otherwise in this file or this component's license file the -# following copyright and licenses apply: -# -# Copyright 2020 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. - -# - Try to find IARMBus -# Once done this will define -# IARMBUS_FOUND - System has IARMBus -# IARMBUS_INCLUDE_DIRS - The IARMBus include directories -# IARMBUS_LIBRARIES - The libraries needed to use IARMBus -# IARMBUS_FLAGS - The flags needed to use IARMBus -# - -find_package(PkgConfig) - -find_library(IARMBUS_LIBRARIES NAMES IARMBus) -find_path(IARMIR_INCLUDE_DIRS NAMES sysMgr.h PATH_SUFFIXES rdk/iarmmgrs/sysmgr) - -set(IARMBUS_LIBRARIES ${IARMBUS_LIBRARIES} CACHE PATH "Path to IARMBus library") -set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${SYSMGR_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS../sysmgr} ) -set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${SYSMGR_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS../sysmgr} CACHE PATH "Path to IARMBus include") - - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(IARMBUS DEFAULT_MSG IARMBUS_INCLUDE_DIRS IARMBUS_LIBRARIES) - -mark_as_advanced( - IARMBUS_FOUND - IARMBUS_INCLUDE_DIRS - IARMBUS_LIBRARIES - IARMBUS_LIBRARY_DIRS - IARMBUS_FLAGS) diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index ead1b3c2..3d6639c9 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -106,9 +106,6 @@ set (HDCPPROFILE_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdcpProfile set (HDCPPROFILE_LIBS ${NAMESPACE}HdcpProfile ${NAMESPACE}HdcpProfileImplementation) add_plugin_test_ex(PLUGIN_HDCPPROFILE tests/test_HdcpProfile.cpp "${HDCPPROFILE_INC}" "${HDCPPROFILE_LIBS}") -# PLUGIN_HDMIINPUT -set (HDMIINPUT_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiInput ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) -add_plugin_test_ex(PLUGIN_HDMIINPUT tests/test_HdmiInput.cpp "${HDMIINPUT_INC}" "${NAMESPACE}HdmiInput") # PLUGIN_HDMICEC2 add_plugin_test_ex(PLUGIN_HDMICEC2 tests/test_HdmiCec2.cpp "../../HdmiCec_2" "${NAMESPACE}HdmiCec_2") diff --git a/Tests/L1Tests/tests/test_HdmiInput.cpp b/Tests/L1Tests/tests/test_HdmiInput.cpp deleted file mode 100644 index 9b0b1f66..00000000 --- a/Tests/L1Tests/tests/test_HdmiInput.cpp +++ /dev/null @@ -1,861 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2024 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. -**/ - -#include - -#include "HdmiInput.h" - -#include "FactoriesImplementation.h" - -#include "HdmiInputMock.h" -#include "IarmBusMock.h" -#include "ServiceMock.h" - -#include "dsMgr.h" -#include "ThunderPortability.h" - -using namespace WPEFramework; - -using ::testing::NiceMock; - -class HdmiInputTest : public ::testing::Test { -protected: - Core::ProxyType plugin; - Core::JSONRPC::Handler& handler; - Core::JSONRPC::Handler& handlerV2; - DECL_CORE_JSONRPC_CONX connection; - string response; - - HdmiInputTest() - : plugin(Core::ProxyType::Create()) - , handler(*(plugin)) - , handlerV2(*(plugin->GetHandler(2))) - , INIT_CONX(1, 0) - { - } - virtual ~HdmiInputTest() = default; -}; - -class HdmiInputDsTest : public HdmiInputTest { -protected: - HdmiInputImplMock *p_hdmiInputImplMock = nullptr ; - - HdmiInputDsTest() - : HdmiInputTest() - { - p_hdmiInputImplMock = new NiceMock ; - device::HdmiInput::setImpl(p_hdmiInputImplMock); - } - virtual ~HdmiInputDsTest() override - { - device::HdmiInput::setImpl(nullptr); - if (p_hdmiInputImplMock != nullptr) - { - delete p_hdmiInputImplMock; - p_hdmiInputImplMock = nullptr; - } - } -}; - -class HdmiInputInitializedTest : public HdmiInputTest { -protected: - IarmBusImplMock *p_iarmBusImplMock = nullptr ; - IARM_EventHandler_t dsHdmiEventHandler; - IARM_EventHandler_t dsHdmiStatusEventHandler; - IARM_EventHandler_t dsHdmiSignalStatusEventHandler; - IARM_EventHandler_t dsHdmiVideoModeEventHandler; - IARM_EventHandler_t dsHdmiGameFeatureStatusEventHandler; - - // NiceMock service; - ServiceMock service; - - HdmiInputInitializedTest() - : HdmiInputTest() - { - p_iarmBusImplMock = new NiceMock ; - IarmBus::setImpl(p_iarmBusImplMock); - - EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillRepeatedly(::testing::Invoke( - [&](const uint32_t, const string& name) -> void* { - return nullptr; - })); - ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) - .WillByDefault(::testing::Invoke( - [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiEventHandler = handler; - } - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiStatusEventHandler = handler; - } - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiSignalStatusEventHandler = handler; - } - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiVideoModeEventHandler = handler; - } - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiGameFeatureStatusEventHandler = handler; - } - return IARM_RESULT_SUCCESS; - })); - - EXPECT_EQ(string(""), plugin->Initialize(&service)); - } - virtual ~HdmiInputInitializedTest() override - { - plugin->Deinitialize(&service); - - IarmBus::setImpl(nullptr); - if (p_iarmBusImplMock != nullptr) - { - delete p_iarmBusImplMock; - p_iarmBusImplMock = nullptr; - } - } -}; - - -class HdmiInputInitializedEventTest : public HdmiInputInitializedTest { -protected: - NiceMock service; - NiceMock factoriesImplementation; - PLUGINHOST_DISPATCHER* dispatcher; - Core::JSONRPC::Message message; - - HdmiInputInitializedEventTest() - : HdmiInputInitializedTest() - { - PluginHost::IFactories::Assign(&factoriesImplementation); - - dispatcher = static_cast( - plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); - dispatcher->Activate(&service); - } - - virtual ~HdmiInputInitializedEventTest() override - { - dispatcher->Deactivate(); - dispatcher->Release(); - - PluginHost::IFactories::Assign(nullptr); - } -}; - -class HdmiInputInitializedEventDsTest : public HdmiInputInitializedEventTest { -protected: - HdmiInputImplMock *p_hdmiInputImplMock = nullptr ; - - HdmiInputInitializedEventDsTest() - : HdmiInputInitializedEventTest() - { - p_hdmiInputImplMock = new NiceMock ; - device::HdmiInput::setImpl(p_hdmiInputImplMock); - } - - virtual ~HdmiInputInitializedEventDsTest() override - { - device::HdmiInput::setImpl(nullptr); - if (p_hdmiInputImplMock != nullptr) - { - delete p_hdmiInputImplMock; - p_hdmiInputImplMock = nullptr; - } - } -}; - -TEST_F(HdmiInputTest, RegisteredMethods) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHDMIInputDevices"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("writeEDID"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("readEDID"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getRawHDMISPD"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getHDMISPD"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("setEdidVersion"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getEdidVersion"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startHdmiInput"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopHdmiInput"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVideoRectangle"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSupportedGameFeatures"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHdmiGameFeatureStatus"))); - - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getHDMIInputDevices"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("writeEDID"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("readEDID"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("startHdmiInput"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("stopHdmiInput"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("setVideoRectangle"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getSupportedGameFeatures"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getHdmiGameFeatureStatus"))); -} - -TEST_F(HdmiInputDsTest, getHDMIInputDevices) -{ - - ON_CALL(*p_hdmiInputImplMock, getNumberOfInputs()) - .WillByDefault(::testing::Return(1)); - ON_CALL(*p_hdmiInputImplMock, isPortConnected(::testing::_)) - .WillByDefault(::testing::Return(true)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHDMIInputDevices"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"devices\":[{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"connected\":\"true\"}],\"success\":true}")); -} - - -TEST_F(HdmiInputDsTest, writeEDIDEmpty) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("writeEDID"), _T("{\"message\": \"message\"}"), response)); - EXPECT_EQ(response, string("")); -} - - -TEST_F(HdmiInputDsTest, writeEDID) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("writeEDID"), _T("{\"deviceId\": 0, \"message\": \"message\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, writeEDIDInvalid) -{ - ON_CALL(*p_hdmiInputImplMock, getEDIDBytesInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector &edidVec2) { - edidVec2 = std::vector({ 't', 'e', 's', 't' }); - })); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("readEDID"), _T("{\"deviceId\": \"b\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, readEDID) -{ - ON_CALL(*p_hdmiInputImplMock, getEDIDBytesInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector &edidVec2) { - edidVec2 = std::vector({ 't', 'e', 's', 't' }); - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("readEDID"), _T("{\"deviceId\": 0}"), response)); - EXPECT_EQ(response, string("{\"EDID\":\"dGVzdA==\",\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, getRawHDMISPD) -{ - ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector& edidVec2) { - edidVec2 = { 't', 'e', 's', 't' }; - })); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getRawHDMISPD"), _T("{\"portId\":0}"), response)); - EXPECT_EQ(response, string("{\"HDMISPD\":\"dGVzdA\",\"success\":true}")); -} -TEST_F(HdmiInputDsTest, getRawHDMISPDInvalid) -{ - ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector& edidVec2) { - edidVec2 = { 't', 'e', 's', 't' }; - })); - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("getRawHDMISPD"), _T("{\"portId\":\"b\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, getHDMISPD) -{ - ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector& edidVec2) { - edidVec2 = {'0','1','2','n', 'p', '1','2','3','4','5','6','7',0,'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',0,'q','r'}; - })); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getHDMISPD"), _T("{\"portId\":0}"), response)); - EXPECT_EQ(response, string("{\"HDMISPD\":\"Packet Type:30,Version:49,Length:50,vendor name:1234567,product des:abcdefghijklmno,source info:71\",\"success\":true}")); -} -TEST_F(HdmiInputDsTest, getHDMISPDInvalid) -{ - ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector& edidVec2) { - edidVec2 = {'0','1','2','n', 'p', '0'}; - })); - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("getHDMISPD"), _T("{\"portId\":\"b\"}"), response)); - EXPECT_EQ(response, string("")); -} - - -TEST_F(HdmiInputDsTest, setEdidVersionInvalid) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"b\", \"edidVersion\":\"HDMI1.4\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, setEdidVersion14) -{ - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"0\", \"edidVersion\":\"HDMI1.4\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, setEdidVersion20) -{ - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"0\", \"edidVersion\":\"HDMI2.0\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} -TEST_F(HdmiInputDsTest, setEdidVersionEmpty) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"0\", \"edidVersion\":\"\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, getEdidVersionInvalid) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"b\", \"edidVersion\":\"HDMI1.4\"}"), response)); - EXPECT_EQ(response, string("")); -} -TEST_F(HdmiInputDsTest, getEdidVersionVer14) -{ - ON_CALL(*p_hdmiInputImplMock, getEdidVersion(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iPort, int *edidVersion) { - *edidVersion = 0; - })); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"0\"}"), response)); - EXPECT_EQ(response, string("{\"edidVersion\":\"HDMI1.4\",\"success\":true}")); -} -TEST_F(HdmiInputDsTest, getEdidVersionVer20) -{ - ON_CALL(*p_hdmiInputImplMock, getEdidVersion(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iPort, int *edidVersion) { - *edidVersion = 1; - })); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"0\"}"), response)); - EXPECT_EQ(response, string("{\"edidVersion\":\"HDMI2.0\",\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, startHdmiInputInvalid) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("startHdmiInput"), _T("{\"portId\": \"b\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, startHdmiInput) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startHdmiInput"), _T("{\"portId\": \"0\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - - -TEST_F(HdmiInputDsTest, stopHdmiInput) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopHdmiInput"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, setVideoRectangleInvalid) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\": \"b\",\"y\": 0,\"w\": 1920,\"h\": 1080}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, setVideoRectangle) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\": 0,\"y\": 0,\"w\": 1920,\"h\": 1080}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - - -TEST_F(HdmiInputDsTest, getSupportedGameFeatures) -{ - ON_CALL(*p_hdmiInputImplMock, getSupportedGameFeatures(::testing::_)) - .WillByDefault(::testing::Invoke( - [&](std::vector &supportedFeatures) { - supportedFeatures = {"ALLM"}; - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSupportedGameFeatures"), _T("{\"supportedGameFeatures\": \"ALLM\"}"), response)); - EXPECT_EQ(response, string("{\"supportedGameFeatures\":[\"ALLM\"],\"success\":true}")); -} - - -TEST_F(HdmiInputDsTest, getHdmiGameFeatureStatusInvalidPort) -{ - ON_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, bool *allm) { - *allm = true; - })); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getHdmiGameFeatureStatus"), _T("{\"portId\": \"b\",\"gameFeature\": \"ALLM\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, getHdmiGameFeatureStatus) -{ - ON_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, bool *allm) { - *allm = true; - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHdmiGameFeatureStatus"), _T("{\"portId\": \"0\",\"gameFeature\": \"ALLM\"}"), response)); - EXPECT_EQ(response, string("{\"mode\":true,\"success\":true}")); -} -TEST_F(HdmiInputDsTest, getHdmiGameFeatureStatusInvalidFeature) -{ - ON_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, bool *allm) { - *allm = true; - })); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getHdmiGameFeatureStatus"), _T("{\"portId\": \"0\",\"gameFeature\": \"Invalid\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputInitializedEventDsTest, onDevicesChanged) -{ - ASSERT_TRUE(dsHdmiEventHandler != nullptr); - ON_CALL(*p_hdmiInputImplMock, getNumberOfInputs()) - .WillByDefault(::testing::Return(1)); - ON_CALL(*p_hdmiInputImplMock, isPortConnected(::testing::_)) - .WillByDefault(::testing::Return(true)); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onDevicesChanged.onDevicesChanged\",\"params\":{\"devices\":[{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"connected\":\"true\"}]}}"))); - - return Core::ERROR_NONE; - })); - - - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_connect.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_connect.isPortConnected = true; - - EVENT_SUBSCRIBE(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); - - dsHdmiEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); -} - -TEST_F(HdmiInputInitializedEventDsTest, onInputStatusChangeOn) -{ - ASSERT_TRUE(dsHdmiStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onInputStatusChanged.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"started\",\"plane\":0}}"))); - return Core::ERROR_NONE; - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startHdmiInput"), _T("{\"portId\": \"0\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_status.isPresented = true; - - EVENT_SUBSCRIBE(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); - - dsHdmiStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onInputStatusChangeOff) -{ - ASSERT_TRUE(dsHdmiStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onInputStatusChanged.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"stopped\",\"plane\":-1}}"))); - return Core::ERROR_NONE; - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopHdmiInput"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_status.isPresented = false; - - EVENT_SUBSCRIBE(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); - - dsHdmiStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedStable) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"stableSignal\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_STABLE; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedNoSignal) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"noSignal\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_NOSIGNAL; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedUnstable) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"unstableSignal\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_UNSTABLE; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedNotSupported) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"notSupportedSignal\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_NOTSUPPORTED; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedDefault) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"none\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_MAX; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); -} - -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate1) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":1920,\"height\":1080,\"progressive\":false,\"frameRateN\":60000,\"frameRateD\":1001}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1920x1080; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_59dot94; - - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate2) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":720,\"height\":480,\"progressive\":false,\"frameRateN\":24000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x480; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_24; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate3) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":720,\"height\":576,\"progressive\":false,\"frameRateN\":25000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x576; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_25; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate4) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":3840,\"height\":2160,\"progressive\":false,\"frameRateN\":30000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_3840x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_30; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate5) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":50000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_50; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate6) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":60000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_60; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate7) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":24000,\"frameRateD\":1001}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_23dot98; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate8) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":30000,\"frameRateD\":1001}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_29dot97; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate9) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":1280,\"height\":720,\"progressive\":false,\"frameRateN\":30000,\"frameRateD\":1001}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_29dot97; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdateDefault) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":1920,\"height\":1080,\"progressive\":false,\"frameRateN\":60000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_MAX; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate= dsVIDEO_FRAMERATE_MAX; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, hdmiGameFeatureStatusUpdate) -{ - ASSERT_TRUE(dsHdmiGameFeatureStatusEventHandler != nullptr); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.hdmiGameFeatureStatusUpdate.hdmiGameFeatureStatusUpdate\",\"params\":{\"id\":0,\"gameFeature\":\"ALLM\",\"mode\":true}}"))); - - return Core::ERROR_NONE; - })); - - - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_allm_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_allm_mode.allm_mode = true; - EVENT_SUBSCRIBE(0, _T("hdmiGameFeatureStatusUpdate"), _T("client.events.hdmiGameFeatureStatusUpdate"), message); - - dsHdmiGameFeatureStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("hdmiGameFeatureStatusUpdate"), _T("client.events.hdmiGameFeatureStatusUpdate"), message); -} From b969871181dd194dd835750ec8eb908b66d34537 Mon Sep 17 00:00:00 2001 From: svemur170 Date: Mon, 28 Jul 2025 14:28:26 +0000 Subject: [PATCH 35/52] RDKTV-37015 - Changelog updates for 1.4.0 Signed-off-by: svemur170 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e60fb2bf..96b97f66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.4.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.5...1.4.0) + +- RDKEMW-2942 : Remove the HdmiInput plugin and replace its references with AVInput [`#205`](https://github.com/rdkcentral/entservices-inputoutput/pull/205) +- [RDKEMW-3513] PR action to run with latest change [`#163`](https://github.com/rdkcentral/entservices-inputoutput/pull/163) +- RDKEMW-6325: platfromSupport is missing from dimmingMode capabilities [`#198`](https://github.com/rdkcentral/entservices-inputoutput/pull/198) +- Merge tag '1.3.5' into develop [`024be52`](https://github.com/rdkcentral/entservices-inputoutput/commit/024be52d58d512b138b84aee9b12609e603d7110) + #### [1.3.5](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.4...1.3.5) +> 23 July 2025 + - RDKEMW-6230: Retry logic used dsGetHDMIARCPortId in HdmiCecSink [`#203`](https://github.com/rdkcentral/entservices-inputoutput/pull/203) +- 1.3.5 release changelog updates [`b12cd97`](https://github.com/rdkcentral/entservices-inputoutput/commit/b12cd97a05c2dc2b7915cfac28c998fb2277d349) - Merge tag '1.3.4' into develop [`760ee0f`](https://github.com/rdkcentral/entservices-inputoutput/commit/760ee0f9da46e0b0ed2e2adb4523bfec85c5a927) #### [1.3.4](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.3...1.3.4) From 71b85003456290ee18a71cecfdaacf97662a0158 Mon Sep 17 00:00:00 2001 From: PriyaPesala <116076033+PriyaPesala@users.noreply.github.com> Date: Wed, 30 Jul 2025 20:40:10 +0530 Subject: [PATCH 36/52] [RDKEMW-5410] RDKEMW-6572 : Compilation error was not reported for the PR branch (#211) * Reffering to current branch * For PR purpose added github.head_ref * Fixing copilot review comments * Adding description to caller_branch * Adding develop branch in ref * Modifying L1, L2 yml files * Modifying README in Tests folder * Modifying Branch to Trigger Source --- .github/workflows/L1-tests.yml | 13 +++++++ .github/workflows/L2-tests.yml | 13 +++++++ .github/workflows/tests-trigger.yml | 5 ++- Tests/README.md | 59 ++++++++++++++++------------- 4 files changed, 62 insertions(+), 28 deletions(-) diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 0b5cfccd..4f85ca8a 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -2,6 +2,11 @@ name: L1-tests on: workflow_call: + inputs: + caller_source: + description: "Specifies the source type (e.g., local or test framework) for the workflow." + required: true + type: string secrets: RDKCM_RDKE: required: true @@ -69,6 +74,7 @@ jobs: - name: ACK External Trigger run: | echo "Message: External Trigger Received for L1 Tests" + echo "Trigger Source: ${{ inputs.caller_source }}" - name: Set up CMake uses: jwlawson/actions-setup-cmake@v1.13 @@ -121,6 +127,13 @@ jobs: token: ${{ secrets.RDKCM_RDKE }} - name: Checkout entservices-inputoutput + if: ${{ inputs.caller_source == 'local' }} + uses: actions/checkout@v3 + with: + path: entservices-inputoutput + + - name: Checkout entservices-inputoutput-testframework + if: ${{ inputs.caller_source == 'testframework' }} uses: actions/checkout@v3 with: repository: rdkcentral/entservices-inputoutput diff --git a/.github/workflows/L2-tests.yml b/.github/workflows/L2-tests.yml index 9dc033be..70b3894a 100755 --- a/.github/workflows/L2-tests.yml +++ b/.github/workflows/L2-tests.yml @@ -2,6 +2,11 @@ name: L2-tests on: workflow_call: + inputs: + caller_source: + description: "Specifies the source type (e.g., local or test framework) for the workflow." + required: true + type: string secrets: RDKCM_RDKE: required: true @@ -39,6 +44,7 @@ jobs: - name: ACK External Trigger run: | echo "Message: External Trigger Received for L2 Tests" + echo "Trigger Source: ${{ inputs.caller_source }}" - name: Set up CMake uses: jwlawson/actions-setup-cmake@v1.13 @@ -83,6 +89,13 @@ jobs: ref: R4.4.3 - name: Checkout entservices-inputoutput + if: ${{ inputs.caller_source == 'local' }} + uses: actions/checkout@v3 + with: + path: entservices-inputoutput + + - name: Checkout entservices-inputoutput-testframework + if: ${{ inputs.caller_source == 'testframework' }} uses: actions/checkout@v3 with: repository: rdkcentral/entservices-inputoutput diff --git a/.github/workflows/tests-trigger.yml b/.github/workflows/tests-trigger.yml index 3aa84f0f..bb3de6af 100755 --- a/.github/workflows/tests-trigger.yml +++ b/.github/workflows/tests-trigger.yml @@ -11,11 +11,14 @@ on: jobs: trigger-L1: uses: ./.github/workflows/L1-tests.yml + with: + caller_source: local secrets: RDKCM_RDKE: ${{ secrets.RDKCM_RDKE }} trigger-L2: uses: ./.github/workflows/L2-tests.yml + with: + caller_source: local secrets: RDKCM_RDKE: ${{ secrets.RDKCM_RDKE }} - diff --git a/Tests/README.md b/Tests/README.md index 4b6eb4ac..48e14c27 100644 --- a/Tests/README.md +++ b/Tests/README.md @@ -6,30 +6,20 @@ Hence, any modifications/additions related to mocks should be commited to entser # Individual Repo Handling Each individual entservices-* repo was added with a .yml file to trigger L1, L2, L2-OOP test job in github workflow. This yml file triggers below mentioned build jobs in addition to regular build jobs (thunder, thunder tools & etc,). - +``` a/ Build mocks => To create TestMock Lib from all required mock relates stubs and copy to install/usr/lib path. b/ Build entservices- => To create Test Lib of .so type from all applicable test files which are enabled for plugin test. c/ Build entservices-testframework => To create L1/L2 executable by linking the plugins/test .so files. - +``` This ensures everything in-tact in repo level across multiple related plugins when there is a new change comes in. -# testframework Repo Handling -The entservices-testframework repo contains yml files corresponds to L1, L2 & L2-OOP to trigger test job in github workflow. - -This yml file triggers below mentioned build jobs in addition to regular build jobs (thunder, thunder tools & etc,). - -a/ Build mocks => To create TestMock Lib from all required mock relates stubs and copy to install/usr/lib path. -b/ Build entservices-* => Jobs to checkout/build all individual repo's plugin & test files which are enabled for plugin test and copy all required libs to install/usr/lib path. -c/ Build entservices-testframework => To create L1/L2 executable by linking the plugins/test .so files. - -This ensures everything in-tact across multiple repos when there is a new change comes either in mocks or test case or plugins. - ##### Steps to run L1, L2, L2-OOP test locally ##### +``` 1. checkout the entservices- to your working directory in your build machine. -example: git clone https://github.com/rdkcentral/entservices-testframework.git +example: git clone https://github.com/rdkcentral/entservices-deviceanddisplay.git 2. switch to entservices- directory -example: cd entservices-testframework +example: cd entservices-deviceanddisplay 3. check and ensure current working branch points to develop example: git branch @@ -37,18 +27,33 @@ example: git branch 4. Run below curl command to download act executable to your repo. example: curl -SL https://raw.githubusercontent.com/nektos/act/master/install.sh | bash -5. 5a/to run L1 test -example: ./bin/act -W .github/workflows/L1-tests.yml -s GITHUB_TOKEN= +5. Run L1, L2, L2-oop test +example: ./bin/act -W .github/workflows/tests-trigger.yml -s GITHUB_TOKEN= -5. 5b/to run L2 test -example: ./bin/act -W .github/workflows/L2-tests.yml -s GITHUB_TOKEN= - -5. 5c/to run L2 test OOP -example: ./bin/act -W .github/workflows/L2-tests-oop.yml -s GITHUB_TOKEN= +NOTE: By default test-trigger.yml will trigger all tests(L1, L2 and etc) parallely, if you want any one test alone to be triggered/verified then remove the other trigger rules from the tests-trigger.yml +``` +# testframework Repo Handling +tf-trigger.yml file of testframework repo will get loaded into github action whenever there is a pull or push happens. This file in-turn triggers all individual repos L1, L2, L2-oop tests. testframework repo test can run only in github workflow. -NOTES: -a/ If you face any secret token related error while run your yml, pls comment the below mentioned line +NOTE: +If you face any secret token related error while run your yml, pls comment the below mentioned line #token: ${{ secrets.RDKE_GITHUB_TOKEN }} -b/ Coverage Report of both L1 and L2 test are uploaded to artifacts server. -c/ For the case, which has modification in plugin and/or test files as well in entservices-testframework mock files, change the ref key of checkout job to point your own branch instead of develop, in both entservices-testframework and entservices-* repo and ensure L1, L2, L2-OOP test jobs are passing for your PR. -example: ref: feature/L1-test + +# Execution usecases where manual change required before triggering the test: +``` +a/ changes in testframework repo only: +Need to change ref pointer of "Checkout entservices-testframework" job in individual repo yml file, to point your current working branch of testframework and in tftrigger.yml of testframework repo need to change trigger branch name to your individual repo branch name instead of develop which is default. +example: +ref: topic/method_1 /* Checkout entservices-testframework job */ +uses: rdkcentral/entservices-deviceanddisplay/.github/workflows/L1-tests.yml@topic/method_1 /* tf-trigger.yml */ + +b/ changes in both testframework repo and invidual repo: +Changes mentioned in step (a) above + "Checkout entservices-deviceanddisplay-testframework" job in individual repo yml file, ref field to point your deviceanddisplay current working branch. +example: +ref: topic/method_1 /* Checkout entservices-testframework job */ +ref: topic/method_1 /* Checkout entservices-deviceanddisplay-testframework job */ +uses: rdkcentral/entservices-deviceanddisplay/.github/workflows/L1-tests.yml@topic/method_1 /* tf-trigger.yml */ + +c/ changes in individual entservices-* repo only +no changes required +``` From a927f061930711ea01a242abab1323b1f6124ffb Mon Sep 17 00:00:00 2001 From: neethuas379 Date: Thu, 31 Jul 2025 23:00:16 +0530 Subject: [PATCH 37/52] RDKEMW-6582: Improve the ARC volume logo smoothness during the Volume +/- press and hold scenario (#215) Co-authored-by: neethu.arambilsunny@sky.uk --- HdmiCecSink/HdmiCecSink.cpp | 33 ++++++++++++++++++++++++--------- HdmiCecSink/HdmiCecSink.h | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/HdmiCecSink/HdmiCecSink.cpp b/HdmiCecSink/HdmiCecSink.cpp index ecb5415e..a1ac6a75 100644 --- a/HdmiCecSink/HdmiCecSink.cpp +++ b/HdmiCecSink/HdmiCecSink.cpp @@ -75,7 +75,7 @@ #define HDMICECSINK_NUMBER_TV_ADDR 2 #define HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS (60 * 1000) #define HDMISINK_ARC_START_STOP_MAX_WAIT_MS 4000 -#define HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS 500 +#define HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS 2000 #define SAD_FMT_CODE_AC3 2 @@ -710,6 +710,7 @@ namespace WPEFramework m_isHdmiInConnected = false; hdmiCecAudioDeviceConnected = false; m_isAudioStatusInfoUpdated = false; + m_audioStatusRequestedCount = 0; m_audioStatusReceived = false; m_audioStatusTimerStarted = false; m_audioDevicePowerStatusRequested = false; @@ -1161,9 +1162,11 @@ namespace WPEFramework LOGINFO("AudioStatus received from the Audio Device and the timer is still active. So stopping the timer!\n"); m_audioStatusDetectionTimer.stop(); } - LOGINFO("AudioStatus received from the Audio Device. Updating the AudioStatus info! m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + LOGINFO("AudioStatus received from the Audio Device. Updating the AudioStatus info! m_isAudioStatusInfoUpdated :%d, m_audioStatusRequestedCount :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusRequestedCount,m_audioStatusReceived,m_audioStatusTimerStarted); } - LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); + if(m_audioStatusRequestedCount > 0) + m_audioStatusRequestedCount--; + LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); params["muteStatus"] = msg.status.getAudioMuteStatus(); params["volumeLevel"] = msg.status.getAudioVolume(); sendNotify(eventString[HDMICECSINK_EVENT_REPORT_AUDIO_STATUS], params); @@ -1355,7 +1358,15 @@ namespace WPEFramework return; if(!(_instance->smConnection)) return; + if (m_audioStatusDetectionTimer.isActive()) + { + LOGINFO("Stopping the Audio Status Timer!\n"); + m_audioStatusDetectionTimer.stop(); + m_audioStatusTimerStarted = false; + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ",m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + } LOGINFO(" Send GiveAudioStatus "); + m_audioStatusRequestedCount++; _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(GiveAudioStatus()), 100); } @@ -2497,10 +2508,11 @@ namespace WPEFramework m_audioStatusDetectionTimer.stop(); } m_isAudioStatusInfoUpdated = false; + m_audioStatusRequestedCount = 0; m_audioStatusReceived = false; m_audioStatusTimerStarted = false; - LOGINFO("Audio device removed, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params); + LOGINFO("Audio device removed, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusRequestedCount :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d", m_isAudioStatusInfoUpdated,m_audioStatusRequestedCount,m_audioStatusReceived,m_audioStatusTimerStarted); + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params); } _instance->deviceList[logicalAddress].m_isRequestRetry = 0; @@ -3121,10 +3133,10 @@ namespace WPEFramework m_audioStatusDetectionTimer.stop(); } m_isAudioStatusInfoUpdated = false; + m_audioStatusRequestedCount = 0; m_audioStatusReceived = false; m_audioStatusTimerStarted = false; - LOGINFO("CEC Disabled, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - + LOGINFO("CEC Disabled, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusRequestedCount :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusRequestedCount,m_audioStatusReceived,m_audioStatusTimerStarted); for(int i=0; i< 16; i++) { @@ -3361,6 +3373,8 @@ namespace WPEFramework keyInfo = _instance->m_SendKeyQueue.front(); _instance->m_SendKeyQueue.pop(); + if((keyInfo.logicalAddr != 0x5) || ((keyInfo.logicalAddr == 0x5) && (_instance->hdmiCecAudioDeviceConnected == true))) + { if(keyInfo.UserControl == "sendUserControlPressed" ) { LOGINFO("sendUserControlPressed : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); @@ -3380,16 +3394,16 @@ namespace WPEFramework if((_instance->m_SendKeyQueue.size()<=1 || (_instance->m_SendKeyQueue.size() % 2 == 0)) && ((keyInfo.keyCode == VOLUME_UP) || (keyInfo.keyCode == VOLUME_DOWN) || (keyInfo.keyCode == MUTE)) ) { + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusRequestedCount :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ",_instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusRequestedCount,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); if(keyInfo.keyCode == MUTE) { _instance->sendGiveAudioStatusMsg(); } else { - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ",_instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); if (!_instance->m_isAudioStatusInfoUpdated) { - if ( !(_instance->m_audioStatusDetectionTimer.isActive())) + if ((!(_instance->m_audioStatusDetectionTimer.isActive())) && (_instance->m_audioStatusRequestedCount == 0)) { LOGINFO("Audio status info not updated. Starting the Timer!"); _instance->m_audioStatusTimerStarted = true; @@ -3404,6 +3418,7 @@ namespace WPEFramework } } } + } } }//while(!_instance->m_sendKeyEventThreadExit) diff --git a/HdmiCecSink/HdmiCecSink.h b/HdmiCecSink/HdmiCecSink.h index 418fb134..2bc6d7c6 100644 --- a/HdmiCecSink/HdmiCecSink.h +++ b/HdmiCecSink/HdmiCecSink.h @@ -673,6 +673,7 @@ namespace WPEFramework { bool m_isAudioStatusInfoUpdated; bool m_audioStatusReceived; bool m_audioStatusTimerStarted; + int m_audioStatusRequestedCount; std::thread m_sendKeyEventThread; std::mutex m_sendKeyEventMutex; std::queue m_SendKeyQueue; From f6c7916aff03d41fb65e8b631f5c05f666ec92c6 Mon Sep 17 00:00:00 2001 From: apatel859 Date: Fri, 1 Aug 2025 14:39:21 +0000 Subject: [PATCH 38/52] 1.4.1 release change log updates --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96b97f66..2de216e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,20 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.4.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.0...1.4.1) + +- RDKEMW-6582: Improve the ARC volume logo smoothness during the Volume +/- press and hold scenario [`#215`](https://github.com/rdkcentral/entservices-inputoutput/pull/215) +- [RDKEMW-5410] RDKEMW-6572 : Compilation error was not reported for the PR branch [`#211`](https://github.com/rdkcentral/entservices-inputoutput/pull/211) +- Merge tag '1.4.0' into develop [`152ff74`](https://github.com/rdkcentral/entservices-inputoutput/commit/152ff74a4066cd3b6fc10800d1b3835fe7d3b543) + #### [1.4.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.5...1.4.0) +> 28 July 2025 + - RDKEMW-2942 : Remove the HdmiInput plugin and replace its references with AVInput [`#205`](https://github.com/rdkcentral/entservices-inputoutput/pull/205) - [RDKEMW-3513] PR action to run with latest change [`#163`](https://github.com/rdkcentral/entservices-inputoutput/pull/163) - RDKEMW-6325: platfromSupport is missing from dimmingMode capabilities [`#198`](https://github.com/rdkcentral/entservices-inputoutput/pull/198) +- RDKTV-37015 - Changelog updates for 1.4.0 [`b969871`](https://github.com/rdkcentral/entservices-inputoutput/commit/b969871181dd194dd835750ec8eb908b66d34537) - Merge tag '1.3.5' into develop [`024be52`](https://github.com/rdkcentral/entservices-inputoutput/commit/024be52d58d512b138b84aee9b12609e603d7110) #### [1.3.5](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.4...1.3.5) From e41f270f2e365c260878e4cd966ae92a7a318687 Mon Sep 17 00:00:00 2001 From: KaleeswaranGnanagurusamy <151117743+KaleeswaranGnanagurusamy@users.noreply.github.com> Date: Mon, 4 Aug 2025 20:38:04 +0530 Subject: [PATCH 39/52] RDKEMW-4708: Replacing IARM Power manager with Power Manager Plugin (#194) AddRef() is called within QueryInterface(). So, removed AddRef() Co-authored-by: apatel859 <48992974+apatel859@users.noreply.github.com> --- helpers/PluginInterfaceBuilder.h | 1 - 1 file changed, 1 deletion(-) diff --git a/helpers/PluginInterfaceBuilder.h b/helpers/PluginInterfaceBuilder.h index a10ad6a6..fdfc5edb 100755 --- a/helpers/PluginInterfaceBuilder.h +++ b/helpers/PluginInterfaceBuilder.h @@ -113,7 +113,6 @@ namespace Plugin { auto pluginInterface = controller->QueryInterfaceByCallsign(callsign.c_str()); if (pluginInterface) { - pluginInterface->AddRef(); LOGINFO("plugin interface succeed and retry count: %d",count); return pluginInterface; } From e2a57a710780328c582d3b62c5c559409c83e9f4 Mon Sep 17 00:00:00 2001 From: apatel859 Date: Mon, 4 Aug 2025 23:43:53 +0000 Subject: [PATCH 40/52] 1.4.2 release change log updates --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2de216e7..5b5817fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,18 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.4.2](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.1...1.4.2) + +- RDKEMW-4708: Replacing IARM Power manager with Power Manager Plugin [`#194`](https://github.com/rdkcentral/entservices-inputoutput/pull/194) +- Merge tag '1.4.1' into develop [`263272d`](https://github.com/rdkcentral/entservices-inputoutput/commit/263272d6c89623461ace94af863e746fda34f9c3) + #### [1.4.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.0...1.4.1) +> 1 August 2025 + - RDKEMW-6582: Improve the ARC volume logo smoothness during the Volume +/- press and hold scenario [`#215`](https://github.com/rdkcentral/entservices-inputoutput/pull/215) - [RDKEMW-5410] RDKEMW-6572 : Compilation error was not reported for the PR branch [`#211`](https://github.com/rdkcentral/entservices-inputoutput/pull/211) +- 1.4.1 release change log updates [`f6c7916`](https://github.com/rdkcentral/entservices-inputoutput/commit/f6c7916aff03d41fb65e8b631f5c05f666ec92c6) - Merge tag '1.4.0' into develop [`152ff74`](https://github.com/rdkcentral/entservices-inputoutput/commit/152ff74a4066cd3b6fc10800d1b3835fe7d3b543) #### [1.4.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.5...1.4.0) From 1659f19a627b84efdd76827d3c51b802935b7578 Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Wed, 6 Aug 2025 19:50:59 +0530 Subject: [PATCH 41/52] RDKEMW-4778 : Automate git flow merges to main branch for entservices repos (#209) * Create component-release.yml * Update component-release.yml * Update component-release.yml * RDKEMW-4778: Update component-release.yml --- .github/workflows/component-release.yml | 111 ++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 .github/workflows/component-release.yml diff --git a/.github/workflows/component-release.yml b/.github/workflows/component-release.yml new file mode 100644 index 00000000..541cb73b --- /dev/null +++ b/.github/workflows/component-release.yml @@ -0,0 +1,111 @@ +name: Component Release + +permissions: + contents: write + +on: + pull_request: + types: [closed] + branches: + - develop + +jobs: + release: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Git + run: | + git config --global user.name "GitHub Actions" + git config --global user.email "actions@github.com" + + - name: Install git-flow and auto-changelog + run: | + sudo apt-get update + sudo apt-get install -y git-flow + npm install -g auto-changelog + + - name: Clone the project and start release + run: | + set -e + git clone https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} project + cd project + git fetch --all + git checkout main || git checkout -b main origin/main + git checkout develop || git checkout -b develop origin/develop + + git config gitflow.branch.master main + git config gitflow.branch.develop develop + git config gitflow.prefix.feature feature/ + git config gitflow.prefix.bugfix bugfix/ + git config gitflow.prefix.release release/ + git config gitflow.prefix.hotfix hotfix/ + git config gitflow.prefix.support support/ + git config gitflow.prefix.versiontag '' + + echo "git config completed" + # Extract version from PR description + PR_DESC="${{ github.event.pull_request.body }}" + # Get top tag from CHANGELOG.md + TOP_TAG=$(grep -m 1 -oP '^#### \[\K[^\]]+' CHANGELOG.md) + if [[ -z "$TOP_TAG" ]]; then + echo "No version found in CHANGELOG.md!" + exit 1 + fi + # Validate TOP_TAG format (semantic versioning: major.minor.patch) + if [[ ! "$TOP_TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Invalid version format in CHANGELOG.md: $TOP_TAG. Expected format: major.minor.patch" + exit 1 + fi + IFS='.' read -r major minor patch <<< "$TOP_TAG" + VERSION_TYPE=$(echo "$PR_DESC" | grep -oiP 'version\s*:\s*\K(major|minor|patch)' | tr '[:upper:]' '[:lower:]') + if [[ -z "$VERSION_TYPE" ]]; then + echo "No version type found in PR description, defaulting to PATCH increment." + patch=$((patch + 1)) + elif [[ "$VERSION_TYPE" == "major" ]]; then + major=$((major + 1)) + minor=0 + patch=0 + elif [[ "$VERSION_TYPE" == "minor" ]]; then + minor=$((minor + 1)) + patch=0 + elif [[ "$VERSION_TYPE" == "patch" ]]; then + patch=$((patch + 1)) + else + echo "Invalid version type in PR description: $VERSION_TYPE" + exit 1 + fi + RELEASE_VERSION="$major.$minor.$patch" + echo "Using calculated version: $RELEASE_VERSION" + echo "RELEASE_VERSION=$RELEASE_VERSION" + echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV + # Check if tag already exists + if git rev-parse "refs/tags/$RELEASE_VERSION" >/dev/null 2>&1; then + echo "Tag $RELEASE_VERSION already exists. Skipping release." + exit 0 + fi + git flow release start $RELEASE_VERSION + auto-changelog -v $RELEASE_VERSION + git add CHANGELOG.md + git commit -m "$RELEASE_VERSION release changelog updates" + git flow release publish + + - name: Finish release and push (default git-flow messages) + run: | + set -e + cd project + git flow release finish -m "$RELEASE_VERSION release" $RELEASE_VERSION + git push origin main + git push origin --tags + git push origin develop + + - name: Cleanup tag if workflow fails + if: failure() + run: | + cd project + git tag -d $RELEASE_VERSION || true + git push origin :refs/tags/$RELEASE_VERSION || true From 9db7ba48bd2c1d6b45c7f575ae5bacec2b0f8308 Mon Sep 17 00:00:00 2001 From: Anbarasan Ravichandran Date: Fri, 18 Jul 2025 12:05:40 +0000 Subject: [PATCH 42/52] RDKEMW-6681: getDolbyVisionMode api fails to return "Dark/Bright" in response for AVOutput plugins. Reason for change: Added condition in getDolbyVisionMode() to return error for non DV content. Test Procedure: as per JIRA Risks: None Priority: P2 Signed-off-by: Anbarasan R --- AVOutput/AVOutputTV.cpp | 7 +++++++ AVOutput/CHANGELOG.md | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/AVOutput/AVOutputTV.cpp b/AVOutput/AVOutputTV.cpp index b686669c..7bdf3876 100644 --- a/AVOutput/AVOutputTV.cpp +++ b/AVOutput/AVOutputTV.cpp @@ -2252,6 +2252,7 @@ namespace Plugin { paramIndex_t indexInfo; int dolbyMode = 0; int err = 0; + tvVideoFormatType_t video_type = VIDEO_FORMAT_NONE; if (parsingGetInputArgument(parameters, "DolbyVisionMode",inputInfo) != 0) { LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); @@ -2262,6 +2263,12 @@ namespace Plugin { returnResponse(false); } + GetCurrentVideoFormat(&video_type); + if(video_type != VIDEO_FORMAT_DV) + { + LOGERR("%s: Invalid video format: %d \n", __FUNCTION__,video_type); + returnResponse(false); + } if (getParamIndex("DolbyVisionMode",inputInfo,indexInfo) == -1) { LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); diff --git a/AVOutput/CHANGELOG.md b/AVOutput/CHANGELOG.md index e5f68a0f..cf722532 100644 --- a/AVOutput/CHANGELOG.md +++ b/AVOutput/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.1.3] - 2025-08-08 +### Fixed +- Fixed getDolbyVisionMode() for non DV content + ## [1.1.2] - 2025-07-01 ### Fixed - Phase2 ODM From ef1583d9967693a1607839f41057fb2a8f0f3060 Mon Sep 17 00:00:00 2001 From: akanda200_comcast Date: Tue, 19 Aug 2025 07:56:12 -0400 Subject: [PATCH 43/52] 1.4.3 release changelog updates --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b5817fe..ba2f46f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.4.3](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.2...1.4.3) + +- RDKEMW-6681: getDolbyVisionMode api fails to return "Dark/Bright" in … [`#223`](https://github.com/rdkcentral/entservices-inputoutput/pull/223) +- RDKEMW-4778 : Automate git flow merges to main branch for entservices repos [`#209`](https://github.com/rdkcentral/entservices-inputoutput/pull/209) +- RDKEMW-6681: getDolbyVisionMode api fails to return "Dark/Bright" in response for AVOutput plugins. [`9db7ba4`](https://github.com/rdkcentral/entservices-inputoutput/commit/9db7ba48bd2c1d6b45c7f575ae5bacec2b0f8308) +- Merge tag '1.4.2' into develop [`be41736`](https://github.com/rdkcentral/entservices-inputoutput/commit/be41736e250601991249354d91777def97c17546) + #### [1.4.2](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.1...1.4.2) +> 4 August 2025 + - RDKEMW-4708: Replacing IARM Power manager with Power Manager Plugin [`#194`](https://github.com/rdkcentral/entservices-inputoutput/pull/194) +- 1.4.2 release change log updates [`e2a57a7`](https://github.com/rdkcentral/entservices-inputoutput/commit/e2a57a710780328c582d3b62c5c559409c83e9f4) - Merge tag '1.4.1' into develop [`263272d`](https://github.com/rdkcentral/entservices-inputoutput/commit/263272d6c89623461ace94af863e746fda34f9c3) #### [1.4.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.0...1.4.1) From a40b62d46d02ba94e94cfbfc585f809b9e5bb209 Mon Sep 17 00:00:00 2001 From: agampa263 <133222558+agampa263@users.noreply.github.com> Date: Fri, 29 Aug 2025 01:39:56 +0530 Subject: [PATCH 44/52] RDKEMW-6515: Scan and Fix coverity issues of Entservices and rdkservices-cpc (#234) Reason for change: Fix Coverity identified issues in ENTServices-Infra Repo Test Procedure: Regression testing on effected plugins Risks: Low Signed-off-by:AkshayKumar_Gampa AkshayKumar_Gampa@comcast.com --- HdmiCecSource/HdmiCecSourceImplementation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HdmiCecSource/HdmiCecSourceImplementation.h b/HdmiCecSource/HdmiCecSourceImplementation.h index 6239dab5..4a0abbd7 100644 --- a/HdmiCecSource/HdmiCecSourceImplementation.h +++ b/HdmiCecSource/HdmiCecSourceImplementation.h @@ -118,7 +118,7 @@ namespace WPEFramework { std::unique_lock lk; CECDeviceInfo_2() - : m_logicalAddress(0),m_vendorID(0,0,0),m_osdName("NA"), m_isOSDNameUpdated (false), m_isVendorIDUpdated (false) + : m_logicalAddress(0),m_vendorID(0,0,0),m_osdName("NA"), m_deviceInfoStatus(0), m_isOSDNameUpdated (false), m_isVendorIDUpdated (false) { BITMASK_CLEAR(m_deviceInfoStatus, 0xFFFF); //Clear all bits } From 78a5fb2aa9a81455869c52d3f77cf765bb9c497b Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Fri, 29 Aug 2025 16:57:35 +0530 Subject: [PATCH 45/52] Update component-release.yml (#242) --- .github/workflows/component-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/component-release.yml b/.github/workflows/component-release.yml index 541cb73b..4a26990e 100644 --- a/.github/workflows/component-release.yml +++ b/.github/workflows/component-release.yml @@ -32,7 +32,7 @@ jobs: - name: Clone the project and start release run: | set -e - git clone https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} project + git clone https://x-access-token:${{ secrets.RDKCM_RDKE }}@github.com/${{ github.repository }} project cd project git fetch --all git checkout main || git checkout -b main origin/main From feec135c1c56d36401582981b6dfcd11993358fb Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 1 Sep 2025 09:57:24 +0000 Subject: [PATCH 46/52] 1.4.4 release changelog updates --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba2f46f5..e276ad21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,20 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.4.4](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.3...1.4.4) + +- Update component-release.yml [`#242`](https://github.com/rdkcentral/entservices-inputoutput/pull/242) +- RDKEMW-6515: Scan and Fix coverity issues of Entservices and rdkservices-cpc [`#234`](https://github.com/rdkcentral/entservices-inputoutput/pull/234) +- Merge tag '1.4.3' into develop [`3b90d4b`](https://github.com/rdkcentral/entservices-inputoutput/commit/3b90d4b70baabf9367bfda236f4695b8a7974313) + #### [1.4.3](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.2...1.4.3) +> 19 August 2025 + - RDKEMW-6681: getDolbyVisionMode api fails to return "Dark/Bright" in … [`#223`](https://github.com/rdkcentral/entservices-inputoutput/pull/223) - RDKEMW-4778 : Automate git flow merges to main branch for entservices repos [`#209`](https://github.com/rdkcentral/entservices-inputoutput/pull/209) - RDKEMW-6681: getDolbyVisionMode api fails to return "Dark/Bright" in response for AVOutput plugins. [`9db7ba4`](https://github.com/rdkcentral/entservices-inputoutput/commit/9db7ba48bd2c1d6b45c7f575ae5bacec2b0f8308) +- 1.4.3 release changelog updates [`ef1583d`](https://github.com/rdkcentral/entservices-inputoutput/commit/ef1583d9967693a1607839f41057fb2a8f0f3060) - Merge tag '1.4.2' into develop [`be41736`](https://github.com/rdkcentral/entservices-inputoutput/commit/be41736e250601991249354d91777def97c17546) #### [1.4.2](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.1...1.4.2) From 996d62ca2d4efae56590fd2efe4d65ed82d9094f Mon Sep 17 00:00:00 2001 From: hgfell683 <107510770+hgfell683@users.noreply.github.com> Date: Wed, 3 Sep 2025 13:15:39 -0400 Subject: [PATCH 47/52] RDKEMW-7169 - Gtest Add missing empty files (#241) * RDKEMW-7169 - Gtest Add missing empty files * RDKEMW-7169 - Gtest Add missing empty files * RDKEMW-7169 - Gtest Add missing empty files --------- Co-authored-by: Srikanth <107277821+srikanth-vv@users.noreply.github.com> --- .github/workflows/L1-tests.yml | 8 +++++++- .github/workflows/L2-tests.yml | 7 ++++++- build_dependencies.sh | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 4f85ca8a..cc031231 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -274,6 +274,9 @@ jobs: rdk/ds/frontPanelIndicator.hpp rdk/ds/frontPanelConfig.hpp rdk/ds/frontPanelTextDisplay.hpp + rdk/ds/audioOutputPortType.hpp + rdk/ds/audioOutputPortConfig.hpp + rdk/ds/pixelResolution.hpp rdk/iarmbus/libIARM.h rdk/iarmbus/libIBus.h rdk/iarmbus/libIBusDaemon.h @@ -290,6 +293,7 @@ jobs: telemetry_busmessage_sender.h maintenanceMGR.h pkg.h + edid-parser.hpp secure_wrapper.h wpa_ctrl.h proc/readproc.h @@ -297,7 +301,7 @@ jobs: gdialservice.h gdialservicecommon.h && - cp -r /usr/include/gstreamer-1.0/gst /usr/include/glib-2.0/* /usr/lib/x86_64-linux-gnu/glib-2.0/include/* /usr/local/include/trower-base64/base64.h . + cp -r /usr/include/gstreamer-1.0/gst /usr/include/glib-2.0/* /usr/lib/x86_64-linux-gnu/glib-2.0/include/* /usr/local/include/trower-base64/base64.h /usr/include/libdrm/drm.h /usr/include/libdrm/drm_mode.h /usr/include/xf86drm.h . - name: Set clang toolchain if: ${{ matrix.compiler == 'clang' }} @@ -358,6 +362,7 @@ jobs: -I $GITHUB_WORKSPACE/Thunder/Source -I $GITHUB_WORKSPACE/Thunder/Source/core -I $GITHUB_WORKSPACE/install/usr/include + -I ./usr/include/libdrm -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Iarm.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Rfc.h @@ -495,6 +500,7 @@ jobs: -I $GITHUB_WORKSPACE/Thunder/Source/core -I $GITHUB_WORKSPACE/install/usr/include -I $GITHUB_WORKSPACE/install/usr/include/WPEFramework + -I ./usr/include/libdrm -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Iarm.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Rfc.h diff --git a/.github/workflows/L2-tests.yml b/.github/workflows/L2-tests.yml index 70b3894a..34cdc6d6 100755 --- a/.github/workflows/L2-tests.yml +++ b/.github/workflows/L2-tests.yml @@ -220,6 +220,9 @@ jobs: rdk/ds/manager.hpp rdk/ds/dsTypes.h rdk/ds/dsUtl.h + rdk/ds/audioOutputPortType.hpp + rdk/ds/audioOutputPortConfig.hpp + rdk/ds/pixelResolution.hpp rdk/iarmbus/libIARM.h rdk/iarmbus/libIBus.h rdk/iarmbus/libIBusDaemon.h @@ -234,6 +237,7 @@ jobs: systemaudioplatform.h maintenanceMGR.h pkg.h + edid-parser.hpp btmgr.h tvError.h tvTypes.h @@ -249,7 +253,7 @@ jobs: rdk/ds/VideoDFC.hpp dsRpc.h && - cp -r /usr/include/gstreamer-1.0/gst /usr/include/glib-2.0/* /usr/lib/x86_64-linux-gnu/glib-2.0/include/* /usr/local/include/trower-base64/base64.h . + cp -r /usr/include/gstreamer-1.0/gst /usr/include/glib-2.0/* /usr/lib/x86_64-linux-gnu/glib-2.0/include/* /usr/local/include/trower-base64/base64.h /usr/include/libdrm/drm.h /usr/include/libdrm/drm_mode.h /usr/include/xf86drm.h . - name: Set clang toolchain if: ${{ matrix.compiler == 'clang' }} @@ -397,6 +401,7 @@ jobs: -I $GITHUB_WORKSPACE/entservices-inputoutput/helpers -I $GITHUB_WORKSPACE/install/usr/include -I $GITHUB_WORKSPACE/install/usr/include/WPEFramework + -I ./usr/include/libdrm -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Iarm.h -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Rfc.h diff --git a/build_dependencies.sh b/build_dependencies.sh index cbd25a7f..d75c69d3 100644 --- a/build_dependencies.sh +++ b/build_dependencies.sh @@ -162,6 +162,9 @@ touch rbus.h touch telemetry_busmessage_sender.h touch maintenanceMGR.h touch pkg.h +touch edid-parser.hpp +touch drm.h +touch drm_mode.h touch secure_wrapper.h touch wpa_ctrl.h touch btmgr.h From 4354afac08c4671cbed356d81a2ed2f612139464 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 3 Sep 2025 17:20:41 +0000 Subject: [PATCH 48/52] 1.4.5 release changelog updates --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e276ad21..db5bc7b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,18 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.4.5](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.4...1.4.5) + +- RDKEMW-7169 - Gtest Add missing empty files [`#241`](https://github.com/rdkcentral/entservices-inputoutput/pull/241) +- Merge tag '1.4.4' into develop [`0fabfaf`](https://github.com/rdkcentral/entservices-inputoutput/commit/0fabfaf0816dda67077fd7fe59e074a962e644ef) + #### [1.4.4](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.3...1.4.4) +> 1 September 2025 + - Update component-release.yml [`#242`](https://github.com/rdkcentral/entservices-inputoutput/pull/242) - RDKEMW-6515: Scan and Fix coverity issues of Entservices and rdkservices-cpc [`#234`](https://github.com/rdkcentral/entservices-inputoutput/pull/234) +- 1.4.4 release changelog updates [`feec135`](https://github.com/rdkcentral/entservices-inputoutput/commit/feec135c1c56d36401582981b6dfcd11993358fb) - Merge tag '1.4.3' into develop [`3b90d4b`](https://github.com/rdkcentral/entservices-inputoutput/commit/3b90d4b70baabf9367bfda236f4695b8a7974313) #### [1.4.3](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.2...1.4.3) From f8c01b325167f757ea97580dbcc69f2f79ee8800 Mon Sep 17 00:00:00 2001 From: hgfell683 <107510770+hgfell683@users.noreply.github.com> Date: Thu, 4 Sep 2025 11:29:13 -0400 Subject: [PATCH 49/52] Feature/rdkemw 7169 (#245) * RDKEMW-7169 - Gtest Add missing empty files * RDKEMW-7169 - Gtest Add missing empty files * RDKEMW-7169 - Gtest Add missing empty files * RDKEMW-7169 - Gtest Add missing empty files * RDKEMW-7169 - Gtest Add missing empty files --------- Co-authored-by: Srikanth <107277821+srikanth-vv@users.noreply.github.com> --- build_dependencies.sh | 2 -- cov_build.sh | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/build_dependencies.sh b/build_dependencies.sh index d75c69d3..2ba9a85d 100644 --- a/build_dependencies.sh +++ b/build_dependencies.sh @@ -163,8 +163,6 @@ touch telemetry_busmessage_sender.h touch maintenanceMGR.h touch pkg.h touch edid-parser.hpp -touch drm.h -touch drm_mode.h touch secure_wrapper.h touch wpa_ctrl.h touch btmgr.h diff --git a/cov_build.sh b/cov_build.sh index bde2bce8..66632fce 100644 --- a/cov_build.sh +++ b/cov_build.sh @@ -37,6 +37,7 @@ cmake -G Ninja -S "$GITHUB_WORKSPACE" -B build/entservices-inputoutput \ -I ${GITHUB_WORKSPACE}/entservices-testframework/Tests/mocks \ -I ${GITHUB_WORKSPACE}/entservices-testframework/Tests/mocks/thunder \ -I ${GITHUB_WORKSPACE}/entservices-testframework/Tests/mocks/devicesettings \ +-I /usr/include/libdrm \ -include ${GITHUB_WORKSPACE}/entservices-testframework/Tests/mocks/devicesettings.h \ -include ${GITHUB_WORKSPACE}/entservices-testframework/Tests/mocks/Iarm.h \ -include ${GITHUB_WORKSPACE}/entservices-testframework/Tests/mocks/Rfc.h \ From 7a0d569f253b8a08926e959509e329159aa2d509 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 4 Sep 2025 15:29:46 +0000 Subject: [PATCH 50/52] 1.4.6 release changelog updates --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db5bc7b0..d9bb2734 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,17 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.4.6](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.5...1.4.6) + +- Feature/rdkemw 7169 [`#245`](https://github.com/rdkcentral/entservices-inputoutput/pull/245) +- Merge tag '1.4.5' into develop [`7268514`](https://github.com/rdkcentral/entservices-inputoutput/commit/7268514652bf9f0cda3f3a6433a0f0720bf9d63c) + #### [1.4.5](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.4...1.4.5) +> 3 September 2025 + - RDKEMW-7169 - Gtest Add missing empty files [`#241`](https://github.com/rdkcentral/entservices-inputoutput/pull/241) +- 1.4.5 release changelog updates [`4354afa`](https://github.com/rdkcentral/entservices-inputoutput/commit/4354afac08c4671cbed356d81a2ed2f612139464) - Merge tag '1.4.4' into develop [`0fabfaf`](https://github.com/rdkcentral/entservices-inputoutput/commit/0fabfaf0816dda67077fd7fe59e074a962e644ef) #### [1.4.4](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.3...1.4.4) From b334b82725cb404c3b29f0c9f4eed123646f3c36 Mon Sep 17 00:00:00 2001 From: arjunbinu <51983664+arjunbinu@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:02:25 +0100 Subject: [PATCH 51/52] RDKEMW-7712: Sync low latency for AVOutput initialization (#6338) --- AVOutput/AVOutputTVHelper.cpp | 7 +++++++ AVOutput/CHANGELOG.md | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index 6fbcbab0..5c5e5b3e 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -1209,6 +1209,13 @@ namespace Plugin { LOGERR("Backlight Sync to cache Failed !!!\n"); } + if( !updateAVoutputTVParam("sync","LowLatencyState",info,PQ_PARAM_LOWLATENCY_STATE,level) ) { + LOGINFO("LowLatencyState Successfully Synced to Drive Cache\n"); + } + else { + LOGERR("LowLatencyState Sync to cache Failed !!!\n"); + } + syncCMSParams(); //sync CMS syncWBParams(); diff --git a/AVOutput/CHANGELOG.md b/AVOutput/CHANGELOG.md index cf722532..7daed548 100644 --- a/AVOutput/CHANGELOG.md +++ b/AVOutput/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +<<<<<<< HEAD +## [1.1.4] - 2025-09-08 +### Fixed +- Sync low latency for AVOutput initialization + ## [1.1.3] - 2025-08-08 ### Fixed - Fixed getDolbyVisionMode() for non DV content From 597942340c4b1ab704fe1220b956803aa10cb60f Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 9 Sep 2025 16:02:42 +0000 Subject: [PATCH 52/52] 1.4.7 release changelog updates --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9bb2734..867461dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,17 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.4.7](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.6...1.4.7) + +- RDKEMW-7712: Sync low latency for AVOutput initialization (#6338) [`#249`](https://github.com/rdkcentral/entservices-inputoutput/pull/249) +- Merge tag '1.4.6' into develop [`bef0aa3`](https://github.com/rdkcentral/entservices-inputoutput/commit/bef0aa3bf2638d0223008f10babecde595d850df) + #### [1.4.6](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.5...1.4.6) +> 4 September 2025 + - Feature/rdkemw 7169 [`#245`](https://github.com/rdkcentral/entservices-inputoutput/pull/245) +- 1.4.6 release changelog updates [`7a0d569`](https://github.com/rdkcentral/entservices-inputoutput/commit/7a0d569f253b8a08926e959509e329159aa2d509) - Merge tag '1.4.5' into develop [`7268514`](https://github.com/rdkcentral/entservices-inputoutput/commit/7268514652bf9f0cda3f3a6433a0f0720bf9d63c) #### [1.4.5](https://github.com/rdkcentral/entservices-inputoutput/compare/1.4.4...1.4.5)