From a3c5dc27b37747b2fe0915f839db7529415189f2 Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Mon, 3 Mar 2025 18:08:33 +0000 Subject: [PATCH 1/6] Revert "1.0.2 release changelog updates" This reverts commit 6d2b6c6c40e915a1fdde6bfb6275b25c1b94b617. --- CHANGELOG.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1d84dfe..50ce6aa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,21 +4,10 @@ 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.0.2](https://github.com/rdkcentral/entservices-inputoutput/compare/1.0.1...1.0.2) - -- RDKEMW-1691 : Remove unsupported plugins in rdk-e [`#4`](https://github.com/rdkcentral/entservices-inputoutput/pull/4) -- RDK-55887: Update the Plugin Client with QueryInterface with CallSign [`#8`](https://github.com/rdkcentral/entservices-inputoutput/pull/8) -- test [`43988dc`](https://github.com/rdkcentral/entservices-inputoutput/commit/43988dcac9cd750a0afab83f2e85c44f3cb79b7b) -- Delete HdmiInput directory [`73fdb8c`](https://github.com/rdkcentral/entservices-inputoutput/commit/73fdb8c516741a054e8e9026816a6fd92cecbbf8) -- Delete CompositeInput directory [`1b86833`](https://github.com/rdkcentral/entservices-inputoutput/commit/1b8683384658fe40c9bb6fcb0f5f8976b0f37db4) - #### [1.0.1](https://github.com/rdkcentral/entservices-inputoutput/compare/1.0.0...1.0.1) -> 19 February 2025 - - Update AVInput AVOutput plugins with latest HPK 1.4.4 interface options [`#3`](https://github.com/rdkcentral/entservices-inputoutput/pull/3) - RDKE-672 - Changelog updates for 1.0.0 [`#2`](https://github.com/rdkcentral/entservices-inputoutput/pull/2) -- RDKE-672 - Changelog updates for 1.0.0 [`#1`](https://github.com/rdkcentral/entservices-inputoutput/pull/1) - Remove ODM APIs - Phase 1 [`0dd73c6`](https://github.com/rdkcentral/entservices-inputoutput/commit/0dd73c6e92a8b197fa2bb8a1d0e7614c0acb3d0b) - Composite VideoMode update [`b89381b`](https://github.com/rdkcentral/entservices-inputoutput/commit/b89381be1c5931a918fbf0c677e9539503185245) - RDKServices changes - getHdmiVersion [`7e0ef17`](https://github.com/rdkcentral/entservices-inputoutput/commit/7e0ef17e4baed5ff3449b645cf3c56211c39c76c) From fe008d693df3f37a0d48d7e6d99e8861fa62b6ec Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Mon, 3 Mar 2025 18:16:33 +0000 Subject: [PATCH 2/6] Revert "Update CMakeLists.txt" This reverts commit baf11f9ee5c7e48b674bfcda0aedc68a6b2bb862. --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c59b694..da03226b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,10 @@ if(PLUGIN_HDCPPROFILE) add_subdirectory(HdcpProfile) endif() +if(PLUGIN_HDMIINPUT) + add_subdirectory(HdmiInput) +endif() + if(WPEFRAMEWORK_CREATE_IPKG_TARGETS) set(CPACK_GENERATOR "DEB") set(CPACK_DEB_COMPONENT_INSTALL ON) From 3410ee7c6a5dcb3ae232436133d205f2d7d79574 Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Mon, 3 Mar 2025 18:17:33 +0000 Subject: [PATCH 3/6] RDKEMW-1691 : Revert Unsupported plugin changes. --- CMakeLists.txt | 8 + CompositeInput/CHANGELOG.md | 28 + CompositeInput/CMakeLists.txt | 54 + CompositeInput/CompositeInput.conf.in | 4 + CompositeInput/CompositeInput.config | 7 + CompositeInput/CompositeInput.cpp | 519 +++++++ CompositeInput/CompositeInput.h | 93 ++ CompositeInput/Module.cpp | 22 + CompositeInput/Module.h | 29 + CompositeInput/README.md | 9 + CompositeInput/cmake/FindDS.cmake | 57 + CompositeInput/cmake/FindIARMBus.cmake | 44 + HdmiCec_2/CHANGELOG.md | 16 + HdmiCec_2/CMakeLists.txt | 51 + HdmiCec_2/HdmiCec_2.conf.in | 5 + HdmiCec_2/HdmiCec_2.config | 7 + HdmiCec_2/HdmiCec_2.cpp | 1777 ++++++++++++++++++++++++ HdmiCec_2/HdmiCec_2.h | 338 +++++ HdmiCec_2/Module.cpp | 22 + HdmiCec_2/Module.h | 29 + HdmiCec_2/README.md | 9 + HdmiInput/CHANGELOG.md | 27 + HdmiInput/CMakeLists.txt | 64 + HdmiInput/HdmiInput.conf.in | 4 + HdmiInput/HdmiInput.config | 7 + HdmiInput/HdmiInput.cpp | 1431 +++++++++++++++++++ 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 + 32 files changed, 4961 insertions(+) create mode 100644 CompositeInput/CHANGELOG.md create mode 100644 CompositeInput/CMakeLists.txt create mode 100644 CompositeInput/CompositeInput.conf.in create mode 100644 CompositeInput/CompositeInput.config create mode 100644 CompositeInput/CompositeInput.cpp create mode 100644 CompositeInput/CompositeInput.h create mode 100644 CompositeInput/Module.cpp create mode 100644 CompositeInput/Module.h create mode 100644 CompositeInput/README.md create mode 100644 CompositeInput/cmake/FindDS.cmake create mode 100644 CompositeInput/cmake/FindIARMBus.cmake create mode 100644 HdmiCec_2/CHANGELOG.md create mode 100644 HdmiCec_2/CMakeLists.txt create mode 100644 HdmiCec_2/HdmiCec_2.conf.in create mode 100644 HdmiCec_2/HdmiCec_2.config create mode 100644 HdmiCec_2/HdmiCec_2.cpp create mode 100644 HdmiCec_2/HdmiCec_2.h create mode 100644 HdmiCec_2/Module.cpp create mode 100644 HdmiCec_2/Module.h create mode 100644 HdmiCec_2/README.md create mode 100644 HdmiInput/CHANGELOG.md create mode 100644 HdmiInput/CMakeLists.txt create mode 100644 HdmiInput/HdmiInput.conf.in create mode 100644 HdmiInput/HdmiInput.config create mode 100644 HdmiInput/HdmiInput.cpp create mode 100644 HdmiInput/HdmiInput.h create mode 100644 HdmiInput/Module.cpp create mode 100644 HdmiInput/Module.h create mode 100644 HdmiInput/README.md create mode 100644 HdmiInput/cmake/FindDS.cmake create mode 100644 HdmiInput/cmake/FindIARMBus.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index da03226b..4940d61d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,10 @@ if(PLUGIN_AVOUTPUT) add_subdirectory(AVOutput) endif() +if(PLUGIN_HDMICEC2) + add_subdirectory(HdmiCec_2) +endif() + if(PLUGIN_HDMICECSOURCE) add_subdirectory(HdmiCecSource) endif() @@ -60,6 +64,10 @@ if(PLUGIN_HDMIINPUT) add_subdirectory(HdmiInput) endif() +if(PLUGIN_COMPOSITEINPUT) + add_subdirectory(CompositeInput) +endif() + if(WPEFRAMEWORK_CREATE_IPKG_TARGETS) set(CPACK_GENERATOR "DEB") set(CPACK_DEB_COMPONENT_INSTALL ON) diff --git a/CompositeInput/CHANGELOG.md b/CompositeInput/CHANGELOG.md new file mode 100644 index 00000000..06bea2b4 --- /dev/null +++ b/CompositeInput/CHANGELOG.md @@ -0,0 +1,28 @@ +# 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.1.5] - 2025-02-17 +### Added + +Added support for handling the videoStreamInfoUpdate for composite Input. + +## [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/CompositeInput/CMakeLists.txt b/CompositeInput/CMakeLists.txt new file mode 100644 index 00000000..a4d6084a --- /dev/null +++ b/CompositeInput/CMakeLists.txt @@ -0,0 +1,54 @@ +# 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 CompositeInput) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +set(PLUGIN_COMPOSITEINPUT_STARTUPORDER "" CACHE STRING "To configure startup order of CompositeInput plugin") + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + CompositeInput.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}) + +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(CompositeInput.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/CompositeInput/CompositeInput.conf.in b/CompositeInput/CompositeInput.conf.in new file mode 100644 index 00000000..7c230b92 --- /dev/null +++ b/CompositeInput/CompositeInput.conf.in @@ -0,0 +1,4 @@ +precondition = ["Platform"] +callsign = "org.rdk.CompositeInput" +autostart = "false" +startuporder = "@PLUGIN_COMPOSITEINPUT_STARTUPORDER@" diff --git a/CompositeInput/CompositeInput.config b/CompositeInput/CompositeInput.config new file mode 100644 index 00000000..0762bf3c --- /dev/null +++ b/CompositeInput/CompositeInput.config @@ -0,0 +1,7 @@ +set (autostart false) +set (preconditions Platform) +set (callsign "org.rdk.CompositeInput") + +if(PLUGIN_COMPOSITEINPUT_STARTUPORDER) +set (startuporder ${PLUGIN_COMPOSITEINPUT_STARTUPORDER}) +endif() diff --git a/CompositeInput/CompositeInput.cpp b/CompositeInput/CompositeInput.cpp new file mode 100644 index 00000000..fa06704a --- /dev/null +++ b/CompositeInput/CompositeInput.cpp @@ -0,0 +1,519 @@ +/** +* 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 "CompositeInput.h" +#include "UtilsJsonRpc.h" +#include "UtilsIarm.h" + +#include "compositeIn.hpp" +#include "exception.hpp" +#include "dsUtl.h" +#include "dsError.h" +#include "dsMgr.h" + +#define API_VERSION_NUMBER_MAJOR 1 +#define API_VERSION_NUMBER_MINOR 1 +#define API_VERSION_NUMBER_PATCH 5 + +#define COMPOSITE_HOT_PLUG_EVENT_CONNECTED 1 +#define COMPOSITE_HOT_PLUG_EVENT_DISCONNECTED 0 + +#define COMPOSITEINPUT_METHOD_GET_COMPOSITE_INPUT_DEVICES "getCompositeInputDevices" +#define COMPOSITEINPUT_METHOD_START_COMPOSITE_INPUT "startCompositeInput" +#define COMPOSITEINPUT_METHOD_STOP_COMPOSITE_INPUT "stopCompositeInput" +#define COMPOSITEINPUT_METHOD_SCALE_COMPOSITE_INPUT "setVideoRectangle" + +#define COMPOSITEINPUT_EVENT_ON_DEVICES_CHANGED "onDevicesChanged" +#define COMPOSITEINPUT_EVENT_ON_SIGNAL_CHANGED "onSignalChanged" +#define COMPOSITEINPUT_EVENT_ON_STATUS_CHANGED "onInputStatusChanged" +#define COMPOSITEINPUT_EVENT_ON_VIDEO_MODE_UPDATED "videoStreamInfoUpdate" + +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(CompositeInput, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + + CompositeInput* CompositeInput::_instance = nullptr; + + CompositeInput::CompositeInput() + : PluginHost::JSONRPC() + { + CompositeInput::_instance = this; + + //InitializeIARM(); + + Register(COMPOSITEINPUT_METHOD_GET_COMPOSITE_INPUT_DEVICES, &CompositeInput::getCompositeInputDevicesWrapper, this); + Register(COMPOSITEINPUT_METHOD_START_COMPOSITE_INPUT, &CompositeInput::startCompositeInput, this); + Register(COMPOSITEINPUT_METHOD_STOP_COMPOSITE_INPUT, &CompositeInput::stopCompositeInput, this); + Register(COMPOSITEINPUT_METHOD_SCALE_COMPOSITE_INPUT, &CompositeInput::setVideoRectangleWrapper, this); + } + + CompositeInput::~CompositeInput() + { + } + const string CompositeInput::Initialize(PluginHost::IShell * /* service */) + { + CompositeInput::_instance = this; + InitializeIARM(); + return (string()); + } + + void CompositeInput::Deinitialize(PluginHost::IShell* /* service */) + { + CompositeInput::_instance = nullptr; + + DeinitializeIARM(); + } + + void CompositeInput::InitializeIARM() + { + if (Utils::IARM::init()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, dsCompositeEventHandler) ); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, dsCompositeSignalStatusEventHandler) ); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS, dsCompositeStatusEventHandler) ); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE,dsCompositeVideoModeEventHandler) ); + } + } + + void CompositeInput::DeinitializeIARM() + { + if (Utils::IARM::isConnected()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, dsCompositeEventHandler) ); + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, dsCompositeSignalStatusEventHandler) ); + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS, dsCompositeStatusEventHandler) ); + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE, dsCompositeVideoModeEventHandler) ); + } + } + + uint32_t CompositeInput::startCompositeInput(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) { + LOGERR("Failed to portId value..!"); + returnResponse(false); + } + + bool success = true; + try + { + device::CompositeInput::getInstance().selectPort(portId); + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(sPortId); + success = false; + } + returnResponse(success); + + } + + uint32_t CompositeInput::stopCompositeInput(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + bool success = true; + try + { + device::CompositeInput::getInstance().selectPort(-1); + } + catch (const device::Exception& err) + { + LOGWARN("CompositeInputService::stopCompositeInput Failed"); + success = false; + } + returnResponse(success); + + } + + uint32_t CompositeInput::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 (...) { + LOGWARN("Invalid Arguments"); + response["message"] = "Invalid Arguments"; + returnResponse(false); + } + + result = setVideoRectangle(x, y, w, h); + if (false == result) { + LOGWARN("CompositeInputService::setVideoRectangle Failed"); + response["message"] = "failed to set scale"; + } + } + + returnResponse(result); + + } + + bool CompositeInput::setVideoRectangle(int x, int y, int width, int height) + { + bool ret = true; + + try + { + device::CompositeInput::getInstance().scaleVideo(x, y, width, height); + } + catch (const device::Exception& err) + { + ret = false; + } + + return ret; + } + + uint32_t CompositeInput::getCompositeInputDevicesWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + response["devices"] = getCompositeInputDevices(); + + returnResponse(true); + } + + JsonArray CompositeInput::getCompositeInputDevices() + { + JsonArray list; + try + { + int num = device::CompositeInput::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 << "cvbsin://localhost/deviceid/" << i; + hash["locator"] = locator.str(); + hash["connected"] = device::CompositeInput::getInstance().isPortConnected(i) ? "true" : "false"; + LOGWARN("CompositeInputService::getCompositeInputDevices 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("CompositeInputService::getCompositeInputDevices Failed"); + } + + return list; + } + + + /** + * @brief This function is used to translate COMPOSITE input hotplug to + * deviceChanged event. + * + * @param[in] input Number of input port integer. + * @param[in] connection status of input port integer. + */ + void CompositeInput::compositeInputHotplug( int input , int connect) + { + LOGWARN("compositeInputHotplug [%d, %d]", input, connect); + + JsonObject params; + params["devices"] = getCompositeInputDevices(); + sendNotify(COMPOSITEINPUT_EVENT_ON_DEVICES_CHANGED, params); + } + + /** + * @brief This function is used to translate Composite input signal change + * to onSignalChanged event. + * + * @param[in] port Composite In port id. + * @param[in] signalStatus signal status of Composite In port. + */ + void CompositeInput::compositeInputSignalChange( int port , int signalStatus) + { + LOGWARN("compositeInputSignalChange [%d, %d]", port, signalStatus); + + JsonObject params; + params["id"] = port; + std::stringstream locator; + locator << "cvbsin://localhost/deviceid/" << port; + params["locator"] = locator.str(); + + switch (signalStatus) { + case dsCOMP_IN_SIGNAL_STATUS_NOSIGNAL: + params["signalStatus"] = "noSignal"; + break; + + case dsCOMP_IN_SIGNAL_STATUS_UNSTABLE: + params["signalStatus"] = "unstableSignal"; + break; + + case dsCOMP_IN_SIGNAL_STATUS_NOTSUPPORTED: + params["signalStatus"] = "notSupportedSignal"; + break; + + case dsCOMP_IN_SIGNAL_STATUS_STABLE: + params["signalStatus"] = "stableSignal"; + break; + + default: + params["signalStatus"] = "none"; + break; + } + + sendNotify(COMPOSITEINPUT_EVENT_ON_SIGNAL_CHANGED, params); + } + + /** + * @brief This function is used to translate Composite input status change to + * inputStatusChanged event. + * + * @param[in] port Composite In port id. + * @param[bool] isPresented Composite In presentation started/stopped. + */ + void CompositeInput::compositeInputStatusChange( int port , bool isPresented) + { + LOGWARN("compositeInputStatusChange [%d, %d]", port, isPresented); + + JsonObject params; + params["id"] = port; + std::stringstream locator; + locator << "cvbsin://localhost/deviceid/" << port; + params["locator"] = locator.str(); + + if(isPresented) { + params["status"] = "started"; + } + else { + params["status"] = "stopped"; + } + + sendNotify(COMPOSITEINPUT_EVENT_ON_STATUS_CHANGED, params); + } + /** + * @brief This function is used to translate Composite input video mode change to + * videoStreamInfoUpdate event. + * + * @param[in] port Composite In port id. + * @param[dsVideoPortResolution_t] video resolution data + */ + void CompositeInput::compositeInputVideoModeUpdate( int port , dsVideoPortResolution_t resolution) + { + LOGWARN("compositeInputVideoModeUpdate [%d]", port); + + JsonObject params; + params["id"] = port; + std::stringstream locator; + locator << "cvbsin://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; + default: + params["width"] = 720; + params["height"] = 576; + break; + } + + params["progressive"] = false; + + 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; + + default: + params["frameRateN"] = 60000; + params["frameRateD"] = 1000; + break; + } + + sendNotify(COMPOSITEINPUT_EVENT_ON_VIDEO_MODE_UPDATED, params); + } + + void CompositeInput::dsCompositeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + if(!CompositeInput::_instance) + return; + + if (IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + int compositein_hotplug_port = eventData->data.composite_in_connect.port; + int compositein_hotplug_conn = eventData->data.composite_in_connect.isPortConnected; + LOGWARN("Received IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG event data:%d", compositein_hotplug_port); + + CompositeInput::_instance->compositeInputHotplug(compositein_hotplug_port, compositein_hotplug_conn ? COMPOSITE_HOT_PLUG_EVENT_CONNECTED : COMPOSITE_HOT_PLUG_EVENT_DISCONNECTED); + } + } + + void CompositeInput::dsCompositeSignalStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + if(!CompositeInput::_instance) + return; + + if (IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + int composite_in_port = eventData->data.composite_in_sig_status.port; + int composite_in_signal_status = eventData->data.composite_in_sig_status.status; + LOGWARN("Received IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS event port: %d, signal status: %d", composite_in_port,composite_in_signal_status); + + CompositeInput::_instance->compositeInputSignalChange(composite_in_port, composite_in_signal_status); + } + } + + void CompositeInput::dsCompositeStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + if(!CompositeInput::_instance) + return; + + if (IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + int composite_in_port = eventData->data.composite_in_status.port; + bool composite_in_status = eventData->data.composite_in_status.isPresented; + LOGWARN("Received IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS event port: %d, started: %d", composite_in_port,composite_in_status); + + CompositeInput::_instance->compositeInputStatusChange(composite_in_port, composite_in_status); + } + } + void CompositeInput::dsCompositeVideoModeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + if(!CompositeInput::_instance) + return; + + if (IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + int composite_in_port = eventData->data.composite_in_video_mode.port; + dsVideoPortResolution_t resolution = {}; + resolution.pixelResolution = eventData->data.composite_in_video_mode.resolution.pixelResolution; + resolution.interlaced = eventData->data.composite_in_video_mode.resolution.interlaced; + resolution.frameRate = eventData->data.composite_in_video_mode.resolution.frameRate; + LOGWARN("Received IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE event port: %d, pixelResolution: %d, interlaced : %d, frameRate: %d \n", composite_in_port,resolution.pixelResolution, resolution.interlaced, resolution.frameRate); + + CompositeInput::_instance->compositeInputVideoModeUpdate(composite_in_port, resolution); + + } + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/CompositeInput/CompositeInput.h b/CompositeInput/CompositeInput.h new file mode 100644 index 00000000..3d1de607 --- /dev/null +++ b/CompositeInput/CompositeInput.h @@ -0,0 +1,93 @@ +/** +* 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 "dsTypes.h" +#include "Module.h" + +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 CompositeInput : public PluginHost::IPlugin, public PluginHost::JSONRPC { + private: + + // We do not allow this plugin to be copied !! + CompositeInput(const CompositeInput&) = delete; + CompositeInput& operator=(const CompositeInput&) = delete; + + void InitializeIARM(); + void DeinitializeIARM(); + + //Begin methods + uint32_t getCompositeInputDevicesWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t startCompositeInput(const JsonObject& parameters, JsonObject& response); + uint32_t stopCompositeInput(const JsonObject& parameters, JsonObject& response); + + uint32_t setVideoRectangleWrapper(const JsonObject& parameters, JsonObject& response); + //End methods + + JsonArray getCompositeInputDevices(); + + bool setVideoRectangle(int x, int y, int width, int height); + + void compositeInputHotplug( int input , int connect); + static void dsCompositeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + + void compositeInputSignalChange( int port , int signalStatus); + static void dsCompositeSignalStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + + void compositeInputStatusChange( int port , bool isPresented); + static void dsCompositeStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + + void compositeInputVideoModeUpdate( int port , dsVideoPortResolution_t resolution); + static void dsCompositeVideoModeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + public: + CompositeInput(); + virtual ~CompositeInput(); + 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(CompositeInput) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + END_INTERFACE_MAP + + public: + static CompositeInput* _instance; + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/CompositeInput/Module.cpp b/CompositeInput/Module.cpp new file mode 100644 index 00000000..ce759b61 --- /dev/null +++ b/CompositeInput/Module.cpp @@ -0,0 +1,22 @@ +/** +* 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/CompositeInput/Module.h b/CompositeInput/Module.h new file mode 100644 index 00000000..094a815d --- /dev/null +++ b/CompositeInput/Module.h @@ -0,0 +1,29 @@ +/** +* 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_CompositeInput +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/CompositeInput/README.md b/CompositeInput/README.md new file mode 100644 index 00000000..11123c51 --- /dev/null +++ b/CompositeInput/README.md @@ -0,0 +1,9 @@ +----------------- +Build: + +bitbake wpeframework-service-plugins + +----------------- +Test: + +curl --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0","id":"3","method": "CompositeInput.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/CompositeInput/cmake/FindDS.cmake b/CompositeInput/cmake/FindDS.cmake new file mode 100644 index 00000000..926c02e0 --- /dev/null +++ b/CompositeInput/cmake/FindDS.cmake @@ -0,0 +1,57 @@ +# 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/CompositeInput/cmake/FindIARMBus.cmake b/CompositeInput/cmake/FindIARMBus.cmake new file mode 100644 index 00000000..bc716bcd --- /dev/null +++ b/CompositeInput/cmake/FindIARMBus.cmake @@ -0,0 +1,44 @@ +# 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/HdmiCec_2/CHANGELOG.md b/HdmiCec_2/CHANGELOG.md new file mode 100644 index 00000000..2e200c40 --- /dev/null +++ b/HdmiCec_2/CHANGELOG.md @@ -0,0 +1,16 @@ +# 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. + diff --git a/HdmiCec_2/CMakeLists.txt b/HdmiCec_2/CMakeLists.txt new file mode 100644 index 00000000..15a33ef0 --- /dev/null +++ b/HdmiCec_2/CMakeLists.txt @@ -0,0 +1,51 @@ +# 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 HdmiCec_2) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +set(PLUGIN_HDMICEC2_STARTUPORDER "" CACHE STRING "To configure startup order of HdmiCec_2 plugin") +set(PLUGIN_HDMICEC2_AUTOSTART false CACHE STRING "To automatically start HdmiCec_2 plugin.") +set_source_files_properties(HdmiCec_2.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + HdmiCec_2.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +find_package(DS) +find_package(IARMBus) +find_package(CEC) + +target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) +target_include_directories(${MODULE_NAME} PRIVATE ${CEC_INCLUDE_DIRS}) +target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) + +target_link_libraries(${MODULE_NAME} 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) +endif () + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/HdmiCec_2/HdmiCec_2.conf.in b/HdmiCec_2/HdmiCec_2.conf.in new file mode 100644 index 00000000..3195f1ff --- /dev/null +++ b/HdmiCec_2/HdmiCec_2.conf.in @@ -0,0 +1,5 @@ +precondition = ["Platform"] +callsign = "org.rdk.HdmiCec_2" +autostart = "false" +autostart = "@PLUGIN_HDMICEC2_AUTOSTART@" +startuporder = "@PLUGIN_HDMICEC2_STARTUPORDER@" diff --git a/HdmiCec_2/HdmiCec_2.config b/HdmiCec_2/HdmiCec_2.config new file mode 100644 index 00000000..df918d0c --- /dev/null +++ b/HdmiCec_2/HdmiCec_2.config @@ -0,0 +1,7 @@ +set (autostart ${PLUGIN_HDMICEC2_AUTOSTART}) +set (preconditions Platform) +set (callsign "org.rdk.HdmiCec_2") + +if(PLUGIN_HDMICEC2_STARTUPORDER) +set (startuporder ${PLUGIN_HDMICEC2_STARTUPORDER}) +endif() diff --git a/HdmiCec_2/HdmiCec_2.cpp b/HdmiCec_2/HdmiCec_2.cpp new file mode 100644 index 00000000..ebf6728d --- /dev/null +++ b/HdmiCec_2/HdmiCec_2.cpp @@ -0,0 +1,1777 @@ +/** +* 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 "HdmiCec_2.h" + + +#include "ccec/Connection.hpp" +#include "ccec/CECFrame.hpp" +#include "ccec/MessageEncoder.hpp" +#include "host.hpp" +#include "ccec/host/RDK.hpp" + + +#include "ccec/drivers/iarmbus/CecIARMBusMgr.h" + +#include "dsMgr.h" +#include "dsDisplay.h" +#include "videoOutputPort.hpp" +#include "manager.hpp" +#include "websocket/URL.h" + +#include "UtilsIarm.h" +#include "UtilsJsonRpc.h" +#include "UtilssyncPersistFile.h" + +#define HDMICEC2_METHOD_SET_ENABLED "setEnabled" +#define HDMICEC2_METHOD_GET_ENABLED "getEnabled" +#define HDMICEC2_METHOD_OTP_SET_ENABLED "setOTPEnabled" +#define HDMICEC2_METHOD_OTP_GET_ENABLED "getOTPEnabled" +#define HDMICEC2_METHOD_SET_OSD_NAME "setOSDName" +#define HDMICEC2_METHOD_GET_OSD_NAME "getOSDName" +#define HDMICEC2_METHOD_SET_VENDOR_ID "setVendorId" +#define HDMICEC2_METHOD_GET_VENDOR_ID "getVendorId" +#define HDMICEC2_METHOD_PERFORM_OTP_ACTION "performOTPAction" +#define HDMICEC2_METHOD_SEND_STANDBY_MESSAGE "sendStandbyMessage" +#define HDMICEC2_METHOD_GET_ACTIVE_SOURCE_STATUS "getActiveSourceStatus" +#define HDMICEC2_METHOD_SEND_KEY_PRESS "sendKeyPressEvent" +#define HDMICEC_EVENT_ON_DEVICES_CHANGED "onDevicesChanged" +#define HDMICEC_EVENT_ON_HDMI_HOT_PLUG "onHdmiHotPlug" +#define HDMICEC_EVENT_ON_STANDBY_MSG_RECEIVED "standbyMessageReceived" +#define DEV_TYPE_TUNER 1 +#define HDMI_HOT_PLUG_EVENT_CONNECTED 0 +#define ABORT_REASON_ID 5 + +#define API_VERSION_NUMBER_MAJOR 1 +#define API_VERSION_NUMBER_MINOR 0 +#define API_VERSION_NUMBER_PATCH 12 + +enum { + HDMICEC2_EVENT_DEVICE_ADDED=0, + HDMICEC2_EVENT_DEVICE_REMOVED, + HDMICEC2_EVENT_DEVICE_INFO_UPDATED, + HDMICEC2_EVENT_ACTIVE_SOURCE_STATUS_UPDATED, +}; + +static const char *eventString[] = { + "onDeviceAdded", + "onDeviceRemoved", + "onDeviceInfoUpdated", + "onActiveSourceStatusUpdated" +}; + +#define CEC_SETTING_ENABLED_FILE "/opt/persistent/ds/cecData_2.json" +#define CEC_SETTING_ENABLED "cecEnabled" +#define CEC_SETTING_OTP_ENABLED "cecOTPEnabled" +#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 OSDName osdName = "TV Box"; +static int32_t powerState = 1; +static PowerStatus tvPowerState = 1; +static bool isDeviceActiveSource = false; +static bool isLGTvConnected = false; + +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(HdmiCec_2, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + + HdmiCec_2* HdmiCec_2::_instance = nullptr; + static int libcecInitStatus = 0; + +//=========================================== HdmiCec_2FrameListener ========================================= + void HdmiCec_2FrameListener::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); + } + +//=========================================== HdmiCec_2Processor ========================================= + void HdmiCec_2Processor::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(msg.physicalAddress.toString() == physical_addr.toString()) + isDeviceActiveSource = true; + else + isDeviceActiveSource = false; + LOGINFO("ActiveSource isDeviceActiveSource status :%d \n", isDeviceActiveSource); + HdmiCec_2::_instance->sendActiveSourceEvent(); + HdmiCec_2::_instance->addDevice(header.from.toInt()); + } + void HdmiCec_2Processor::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()); + } + void HdmiCec_2Processor::process (const ImageViewOn &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ImageViewOn \n"); + HdmiCec_2::_instance->addDevice(header.from.toInt()); + } + void HdmiCec_2Processor::process (const TextViewOn &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: TextViewOn\n"); + HdmiCec_2::_instance->addDevice(header.from.toInt()); + } + void HdmiCec_2Processor::process (const RequestActiveSource &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RequestActiveSource\n"); + if(isDeviceActiveSource) + { + LOGINFO("sending ActiveSource\n"); + try + { + conn.sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(ActiveSource(physical_addr))); + } + catch(...) + { + LOGWARN("Exception while sending ActiveSource"); + } + } + } + void HdmiCec_2Processor::process (const Standby &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Standby from %s\n", header.from.toString().c_str()); + HdmiCec_2::_instance->SendStandbyMsgEvent(header.from.toInt()); + + } + void HdmiCec_2Processor::process (const GetCECVersion &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GetCECVersion sending CECVersion response \n"); + try + { + conn.sendTo(header.from, MessageEncoder().encode(CECVersion(Version::V_1_4))); + } + catch(...) + { + LOGWARN("Exception while sending CECVersion "); + } + } + void HdmiCec_2Processor::process (const CECVersion &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); + HdmiCec_2::_instance->addDevice(header.from.toInt()); + } + void HdmiCec_2Processor::process (const SetMenuLanguage &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); + } + void HdmiCec_2Processor::process (const GiveOSDName &msg, const Header &header) + { + printHeader(header); + if (!(header.from == LogicalAddress(LogicalAddress::UNREGISTERED))) + { + LOGINFO("Command: GiveOSDName sending SetOSDName : %s\n",osdName.toString().c_str()); + try + { + conn.sendTo(header.from, MessageEncoder().encode(SetOSDName(osdName))); + } + catch(...) + { + LOGWARN("Exception while sending SetOSDName"); + } + } + } + void HdmiCec_2Processor::process (const GivePhysicalAddress &msg, const Header &header) + { + LOGINFO("Command: GivePhysicalAddress\n"); + 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()))); + } + catch(...) + { + LOGWARN("Exception while sending ReportPhysicalAddress "); + } + } + void HdmiCec_2Processor::process (const GiveDeviceVendorID &msg, const Header &header) + { + printHeader(header); + try + { + LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n",(isLGTvConnected)?lgVendorId.toString().c_str():appVendorId.toString().c_str()); + if(isLGTvConnected) + conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(lgVendorId))); + else + conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); + } + catch(...) + { + LOGWARN("Exception while sending DeviceVendorID"); + } + + } + void HdmiCec_2Processor::process (const SetOSDString &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetOSDString OSDString : %s\n",msg.osdString.toString().c_str()); + } + void HdmiCec_2Processor::process (const SetOSDName &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetOSDName OSDName : %s\n",msg.osdName.toString().c_str()); + if (HdmiCec_2::_instance) { + bool isOSDNameUpdated = HdmiCec_2::_instance->deviceList[header.from.toInt()].update(msg.osdName); + if (isOSDNameUpdated) + HdmiCec_2::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } else { + LOGWARN("Exception HdmiCec_2::_instance NULL"); + } + } + void HdmiCec_2Processor::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()); + if(msg.to.toString() == physical_addr.toString()) + isDeviceActiveSource = true; + else + isDeviceActiveSource = false; + LOGINFO("physical_addr : %s isDeviceActiveSource :%d \n",physical_addr.toString().c_str(),isDeviceActiveSource); + HdmiCec_2::_instance->sendActiveSourceEvent(); + } + void HdmiCec_2Processor::process (const RoutingInformation &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RoutingInformation Routing Information to Sink : %s\n",msg.toSink.toString().c_str()); + if(msg.toSink.toString() == physical_addr.toString()) + isDeviceActiveSource = true; + else + isDeviceActiveSource = false; + LOGINFO("physical_addr : %s isDeviceActiveSource :%d \n",physical_addr.toString().c_str(),isDeviceActiveSource); + HdmiCec_2::_instance->sendActiveSourceEvent(); + } + void HdmiCec_2Processor::process (const SetStreamPath &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetStreamPath Set Stream Path to Sink : %s\n",msg.toSink.toString().c_str()); + if(msg.toSink.toString() == physical_addr.toString()) + isDeviceActiveSource = true; + else + isDeviceActiveSource = false; + LOGINFO("physical_addr : %s isDeviceActiveSource :%d \n",physical_addr.toString().c_str(),isDeviceActiveSource); + HdmiCec_2::_instance->sendActiveSourceEvent(); + + } + void HdmiCec_2Processor::process (const GetMenuLanguage &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GetMenuLanguage\n"); + } + void HdmiCec_2Processor::process (const ReportPhysicalAddress &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ReportPhysicalAddress\n"); + HdmiCec_2::_instance->addDevice(header.from.toInt()); + } + void HdmiCec_2Processor::process (const DeviceVendorID &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: DeviceVendorID VendorID : %s\n",msg.vendorId.toString().c_str()); + if (HdmiCec_2::_instance){ + bool isVendorIdUpdated = HdmiCec_2::_instance->deviceList[header.from.toInt()].update(msg.vendorId); + if (isVendorIdUpdated) + HdmiCec_2::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + else { + LOGWARN("Exception HdmiCec_2::_instance NULL"); + } + + } + void HdmiCec_2Processor::process (const GiveDevicePowerStatus &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveDevicePowerStatus sending powerState :%d \n",powerState); + try + { + conn.sendTo(header.from, MessageEncoder().encode(ReportPowerStatus(PowerStatus(powerState)))); + } + catch(...) + { + LOGWARN("Exception while sending ReportPowerStatus"); + } + } + void HdmiCec_2Processor::process (const ReportPowerStatus &msg, const Header &header) + { + printHeader(header); + if ((header.from == LogicalAddress(LogicalAddress::TV))) + tvPowerState = msg.status; + LOGINFO("Command: ReportPowerStatus TV Power Status from:%s status : %s \n",header.from.toString().c_str(),msg.status.toString().c_str()); + HdmiCec_2::_instance->addDevice(header.from.toInt()); + } + void HdmiCec_2Processor::process (const FeatureAbort &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: FeatureAbort\n"); + } + void HdmiCec_2Processor::process (const Abort &msg, const Header &header) + { + printHeader(header); + if (!(header.from == LogicalAddress(LogicalAddress::BROADCAST))) + { + LOGINFO("Command: Abort, sending FeatureAbort"); + try + { + conn.sendTo(header.from, MessageEncoder().encode(FeatureAbort(OpCode(msg.opCode()),AbortReason(ABORT_REASON_ID)))); + } + catch(...) + { + LOGWARN("Exception while sending FeatureAbort command"); + } + + } + LOGINFO("Command: Abort\n"); + } + void HdmiCec_2Processor::process (const Polling &msg, const Header &header) { + printHeader(header); + LOGINFO("Command: Polling\n"); + } + + +//=========================================== HdmiCec_2 ========================================= + + HdmiCec_2::HdmiCec_2() + : PluginHost::JSONRPC(),cecEnableStatus(false),smConnection(nullptr), m_sendKeyEventThreadRun(false) + , _pwrMgrNotification(*this) + , _registeredEventHandlers(false) + { + LOGWARN("ctor"); + smConnection = NULL; + cecEnableStatus = false; + IsCecMgrActivated = false; + Register(HDMICEC2_METHOD_SET_ENABLED, &HdmiCec_2::setEnabledWrapper, this); + Register(HDMICEC2_METHOD_GET_ENABLED, &HdmiCec_2::getEnabledWrapper, this); + Register(HDMICEC2_METHOD_OTP_SET_ENABLED, &HdmiCec_2::setOTPEnabledWrapper, this); + Register(HDMICEC2_METHOD_OTP_GET_ENABLED, &HdmiCec_2::getOTPEnabledWrapper, this); + Register(HDMICEC2_METHOD_SET_OSD_NAME, &HdmiCec_2::setOSDNameWrapper, this); + Register(HDMICEC2_METHOD_GET_OSD_NAME, &HdmiCec_2::getOSDNameWrapper, this); + Register(HDMICEC2_METHOD_SET_VENDOR_ID, &HdmiCec_2::setVendorIdWrapper, this); + Register(HDMICEC2_METHOD_GET_VENDOR_ID, &HdmiCec_2::getVendorIdWrapper, this); + Register(HDMICEC2_METHOD_PERFORM_OTP_ACTION, &HdmiCec_2::performOTPActionWrapper, this); + Register(HDMICEC2_METHOD_SEND_STANDBY_MESSAGE, &HdmiCec_2::sendStandbyMessageWrapper, this); + Register(HDMICEC2_METHOD_GET_ACTIVE_SOURCE_STATUS, &HdmiCec_2::getActiveSourceStatus, this); + Register(HDMICEC2_METHOD_SEND_KEY_PRESS,&HdmiCec_2::sendRemoteKeyPressWrapper,this); + Register("getDeviceList", &HdmiCec_2::getDeviceList, this); + } + + HdmiCec_2::~HdmiCec_2() + { + IsCecMgrActivated = false; + LOGWARN("dtor"); + } + + const string HdmiCec_2::Initialize(PluginHost::IShell* service) + { + LOGWARN("Initlaizing CEC_2"); + string msg; + HdmiCec_2::_instance = this; + smConnection = NULL; + IsCecMgrActivated = false; + uint32_t res = Core::ERROR_GENERAL; + PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + if (Utils::IARM::init()) { + + + //Initialize cecEnableStatus to false in ctor + cecEnableStatus = false; + + logicalAddressDeviceType = "None"; + logicalAddress = 0xFF; + + char c; + IARM_Result_t retVal = IARM_RESULT_SUCCESS; + retVal = IARM_Bus_Call_with_IPCTimeout(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_API_isAvailable, (void *)&c, sizeof(c), 1000); + if(retVal != IARM_RESULT_SUCCESS) { + msg = "IARM_BUS_CECMGR is not available"; + LOGINFO("CECMGR is not available. Failed to activate HdmiCec_2 Plugin"); + return msg; + } else { + LOGINFO("CECMGR is available. Activate HdmiCec_2 Plugin. IsCecMgrActivated: %d", IsCecMgrActivated); + IsCecMgrActivated = true; + } + + //CEC plugin functionalities will only work if CECmgr is available. If plugin Initialize failure upper layer will call dtor directly. + InitializeIARM(); + InitializePowerManager(service); + + // load persistence setting + loadSettings(); + + try + { + //TODO(MROLLINS) this is probably per process so we either need to be running in our own process or be carefull no other plugin is calling it + device::Manager::Initialize(); + std::string strVideoPort = device::Host::getInstance().getDefaultVideoPortName(); + device::VideoOutputPort vPort = device::Host::getInstance().getVideoOutputPort(strVideoPort.c_str()); + if (vPort.isDisplayConnected()) + { + std::vector edidVec; + vPort.getDisplay().getEDIDBytes(edidVec); + //Set LG vendor id if connected with LG TV + if(edidVec.at(8) == 0x1E && edidVec.at(9) == 0x6D) + { + isLGTvConnected = true; + } + LOGINFO("manufacturer byte from edid :%x: %x isLGTvConnected :%d",edidVec.at(8),edidVec.at(9),isLGTvConnected); + } + } + catch(...) + { + LOGWARN("Exception in getting edid info .\r\n"); + } + + // get power state: + ASSERT (_powerManagerPlugin); + if (_powerManagerPlugin){ + res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); + if (Core::ERROR_NONE == res) + { + powerState = (pwrStateCur == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON)?0:1 ; + LOGINFO("Current state is PowerManagerPlugin: (%d) powerState :%d \n",pwrStateCur,powerState); + } + } + + if (cecSettingEnabled) + { + try + { + CECEnable(); + } + catch(...) + { + LOGWARN("Exception while enabling CEC settings .\r\n"); + } + } + } else { + msg = "IARM bus is not available"; + LOGERR("IARM bus is not available. Failed to activate HdmiCec_2 Plugin"); + } + + // On success return empty, to indicate there is no error text. + return msg; + } + + uint32_t HdmiCec_2::getActiveSourceStatus(const JsonObject& parameters, JsonObject& response) + { + response["status"] = isDeviceActiveSource; + returnResponse(true); + } + + void HdmiCec_2::Deinitialize(PluginHost::IShell* /* service */) + { + LOGWARN("Deinitialize CEC_2"); + if(_powerManagerPlugin) + { + _powerManagerPlugin.Reset(); + } + _registeredEventHandlers = false; + if(true == getEnabled()) + { + setEnabled(false,false); + } + isDeviceActiveSource = false; + HdmiCec_2::_instance->sendActiveSourceEvent(); + HdmiCec_2::_instance = nullptr; + smConnection = NULL; + + DeinitializeIARM(); + } + + void HdmiCec_2::registerEventHandlers() + { + ASSERT (_powerManagerPlugin); + + if(!_registeredEventHandlers && _powerManagerPlugin) { + _registeredEventHandlers = true; + _powerManagerPlugin->Register(&_pwrMgrNotification); + } + } + + void HdmiCec_2::InitializePowerManager(PluginHost::IShell* service) + { + LOGINFO("Connect the COM-RPC socket\n"); + _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) + .withIShell(service) + .createInterface(); + registerEventHandlers(); + } + + + void HdmiCec_2::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 HdmiCec_2::sendKeyReleaseEvent(const int logicalAddress) + { + LOGINFO(" sendKeyReleaseEvent logicalAddress 0x%x \n",logicalAddress); + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); + + } + void HdmiCec_2::SendStandbyMsgEvent(const int logicalAddress) + { + JsonObject params; + params["logicalAddress"] = JsonValue(logicalAddress); + sendNotify(HDMICEC_EVENT_ON_STANDBY_MSG_RECEIVED, params); + } + uint32_t HdmiCec_2::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); + 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:%d \n",(int)m_SendKeyQueue.size()); + returnResponse(true); + } + + uint32_t HdmiCec_2::sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response) + { + if(sendStandbyMessage()) + { + returnResponse(true); + } + else + { + returnResponse(false); + } + } + + bool HdmiCec_2::sendStandbyMessage() + { + bool ret = false; + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return ret; + } + if(true == cecEnableStatus) + { + if (smConnection){ + try + { + smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(Standby())); + ret = true; + } + catch(...) + { + LOGWARN("Exception while sending CEC StandBy Message"); + } + } + else { + LOGWARN("smConnection is NULL"); + } + } + else + LOGWARN("cecEnableStatus=false"); + return ret; + } + + + const void HdmiCec_2::InitializeIARM() + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED,cecMgrEventHandler) ); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_STATUS_UPDATED,cecMgrEventHandler) ); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, dsHdmiEventHandler) ); + } + + void HdmiCec_2::DeinitializeIARM() + { + if (Utils::IARM::isConnected()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED, cecMgrEventHandler) ); + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_STATUS_UPDATED, cecMgrEventHandler) ); + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, dsHdmiEventHandler) ); + } + } + + void HdmiCec_2::cecMgrEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + if(!HdmiCec_2::_instance) + return; + + if( !strcmp(owner, IARM_BUS_CECMGR_NAME)) + { + switch (eventId) + { + case IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED: + { + HdmiCec_2::_instance->onCECDaemonInit(); + } + break; + case IARM_BUS_CECMGR_EVENT_STATUS_UPDATED: + { + IARM_Bus_CECMgr_Status_Updated_Param_t *evtData = new IARM_Bus_CECMgr_Status_Updated_Param_t; + if(evtData) + { + memcpy(evtData,data,sizeof(IARM_Bus_CECMgr_Status_Updated_Param_t)); + HdmiCec_2::_instance->cecStatusUpdated(evtData); + } + } + break; + default: + /*Do nothing*/ + break; + } + } + } + + void HdmiCec_2::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + if(!HdmiCec_2::_instance) + return; + + if (IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + int hdmi_hotplug_event = eventData->data.hdmi_hpd.event; + LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG event data:%d \r\n", hdmi_hotplug_event); + HdmiCec_2::_instance->onHdmiHotPlug(hdmi_hotplug_event); + //Trigger CEC device poll here + pthread_cond_signal(&(_instance->m_condSig)); + } + } + + void HdmiCec_2::onPowerModeChanged(const PowerState ¤tState, const PowerState &newState) + { + if(!HdmiCec_2::_instance) + return; + + LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", + currentState, newState); + if (WPEFramework::Exchange::IPowerManager::POWER_STATE_ON == newState) + { + powerState = 0; + } + else + powerState = 1; + + } + + void HdmiCec_2::onCECDaemonInit() + { + if(true == getEnabled()) + { + LOGINFO("%s %d. Calling setEnabled false", __func__, __LINE__); + setEnabled(false,false); + LOGINFO("%s %d. Calling setEnabled true", __func__, __LINE__); + setEnabled(true,false); + } + else + { + /*Do nothing as CEC is not already enabled*/ + } + } + + void HdmiCec_2::cecStatusUpdated(void *evtStatus) + { + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return; + } + IARM_Bus_CECMgr_Status_Updated_Param_t *evtData = (IARM_Bus_CECMgr_Status_Updated_Param_t *)evtStatus; + if(evtData) + { + try{ + getPhysicalAddress(); + + int logicalAddr = evtData->logicalAddress; + std::string logicalAddrDeviceType = DeviceType(LogicalAddress(evtData->logicalAddress).getType()).toString().c_str(); + + LOGINFO("cecLogicalAddressUpdated: logical address updated: %d , saved : %d ", logicalAddr, logicalAddress.toInt()); + if (logicalAddr != logicalAddress.toInt() || logicalAddrDeviceType != logicalAddressDeviceType) + { + logicalAddress = logicalAddr; + logicalAddressDeviceType = logicalAddrDeviceType; + } + } + catch (const std::exception& e) + { + LOGWARN("CEC exception caught from cecStatusUpdated"); + } + + delete evtData; + } + return; + } + + void HdmiCec_2::sendActiveSourceEvent() + { + JsonObject params; + params["status"] = isDeviceActiveSource; + LOGWARN(" sendActiveSourceEvent isDeviceActiveSource: %d ",isDeviceActiveSource); + sendNotify(eventString[HDMICEC2_EVENT_ACTIVE_SOURCE_STATUS_UPDATED], params); + } + + void HdmiCec_2::onHdmiHotPlug(int connectStatus) + { + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return; + } + if (HDMI_HOT_PLUG_EVENT_CONNECTED == connectStatus) + { + LOGINFO ("onHdmiHotPlug Status : %d ", connectStatus); + getPhysicalAddress(); + getLogicalAddress(); + try + { + std::string strVideoPort = device::Host::getInstance().getDefaultVideoPortName(); + device::VideoOutputPort vPort = device::Host::getInstance().getVideoOutputPort(strVideoPort.c_str()); + if (vPort.isDisplayConnected()) + { + std::vector edidVec; + vPort.getDisplay().getEDIDBytes(edidVec); + //Set LG vendor id if connected with LG TV + if(edidVec.at(8) == 0x1E && edidVec.at(9) == 0x6D) + { + isLGTvConnected = true; + } + LOGINFO("manufacturer byte from edid :%x: %x isLGTvConnected :%d",edidVec.at(8),edidVec.at(9),isLGTvConnected); + } + } + catch(...) + { + LOGWARN("Exception in getting edid info .\r\n"); + } + if(smConnection) + { + try + { + LOGINFO(" sending ReportPhysicalAddress response physical_addr :%s logicalAddress :%x \n",physical_addr.toString().c_str(), logicalAddress.toInt()); + smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ReportPhysicalAddress(physical_addr,logicalAddress.toInt()))); + + LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n", \ + (isLGTvConnected)?lgVendorId.toString().c_str():appVendorId.toString().c_str()); + if(isLGTvConnected) + smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(lgVendorId))); + else + smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); + } + catch(...) + { + LOGWARN("Exception while sending Messages onHdmiHotPlug\n"); + } + } + } + return; + } + + uint32_t HdmiCec_2::setEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + bool enabled = false; + + if (parameters.HasLabel("enabled")) + { + getBoolParameter("enabled", enabled); + } + else + { + returnResponse(false); + } + + setEnabled(enabled,true); + returnResponse(true); + } + + uint32_t HdmiCec_2::getEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + response["enabled"] = getEnabled(); + returnResponse(true); + } + uint32_t HdmiCec_2::setOTPEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + bool enabled = false; + + if (parameters.HasLabel("enabled")) + { + getBoolParameter("enabled", enabled); + } + else + { + returnResponse(false); + } + + setOTPEnabled(enabled); + returnResponse(true); + } + + uint32_t HdmiCec_2::getOTPEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + response["enabled"] = getOTPEnabled(); + returnResponse(true); + } + + uint32_t HdmiCec_2::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 + { + returnResponse(false); + } + returnResponse(true); + } + + uint32_t HdmiCec_2::getOSDNameWrapper(const JsonObject& parameters, JsonObject& response) + { + response["name"] = osdName.toString(); + LOGINFO("getOSDNameWrapper osdName : %s \n",osdName.toString().c_str()); + returnResponse(true); + } + + uint32_t HdmiCec_2::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 HdmiCec_2::getVendorIdWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("getVendorIdWrapper appVendorId : %s \n",appVendorId.toString().c_str()); + response["vendorid"] = appVendorId.toString() ; + returnResponse(true); + } + + + uint32_t HdmiCec_2::performOTPActionWrapper(const JsonObject& parameters, JsonObject& response) + { + if(performOTPAction()) + { + returnResponse(true); + } + else + { + returnResponse(false); + } + } + + bool HdmiCec_2::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_OTP_ENABLED 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_OTP_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 HdmiCec_2::setEnabled(bool enabled, bool isPersist) + { + LOGINFO("Entered setEnabled "); + + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return; + } else { + LOGWARN("CEC Mgr activated. proceeding with %s", __func__); + } + if (isPersist && (cecSettingEnabled != enabled)) + { + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_ENABLED, JsonValue(enabled)); + cecSettingEnabled = enabled; + } + if(true == enabled) + { + CECEnable(); + } + else + { + CECDisable(); + } + return; + } + + void HdmiCec_2::setOTPEnabled(bool enabled) + { + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return; + } + if (cecOTPSettingEnabled != enabled) + { + LOGINFO("persist setOTPEnabled "); + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_OTP_ENABLED, JsonValue(enabled)); + cecOTPSettingEnabled = enabled; + } + return; + } + + void HdmiCec_2::CECEnable(void) + { + LOGINFO("Entered CECEnable"); + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return; + } + if (cecEnableStatus) + { + LOGWARN("CEC Already Enabled"); + return; + } + + if(0 == libcecInitStatus) + { + try + { + LibCCEC::getInstance().init(); + } + catch (const std::exception& e) + { + LOGWARN("CEC exception caught from LibCCEC::getInstance().init()"); + } + } + libcecInitStatus++; + + m_sendKeyEventThreadExit = false; + try { + if (m_sendKeyEventThread.get().joinable()) { + m_sendKeyEventThread.get().join(); + } + m_sendKeyEventThread = Utils::ThreadRAII(std::thread(threadSendKeyEvent)); + } catch(const std::system_error& e) { + LOGERR("exception in creating threadSendKeyEvent %s", e.what()); + } + + + //Acquire CEC Addresses + getPhysicalAddress(); + getLogicalAddress(); + + smConnection = new Connection(logicalAddress.toInt(),false,"ServiceManager::Connection::"); + smConnection->open(); + msgProcessor = new HdmiCec_2Processor(*smConnection); + msgFrameListener = new HdmiCec_2FrameListener(*msgProcessor); + smConnection->addFrameListener(msgFrameListener); + + cecEnableStatus = true; + + if(smConnection) + { + 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())); + isDeviceActiveSource = false; + LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n", \ + (isLGTvConnected)?lgVendorId.toString().c_str():appVendorId.toString().c_str()); + if(isLGTvConnected) + smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(lgVendorId))); + else + smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); + + LOGWARN("Start Update thread %p", smConnection ); + m_updateThreadExit = false; + _instance->m_lockUpdate = PTHREAD_MUTEX_INITIALIZER; + _instance->m_condSigUpdate = PTHREAD_COND_INITIALIZER; + try { + if (m_UpdateThread.get().joinable()) { + m_UpdateThread.get().join(); + } + m_UpdateThread = Utils::ThreadRAII(std::thread(threadUpdateCheck)); + } catch(const std::system_error& e) { + LOGERR("exception in creating threadUpdateCheck %s", e.what()); + } + + LOGWARN("Start Thread %p", smConnection ); + m_pollThreadExit = false; + _instance->m_numberOfDevices = 0; + _instance->m_lock = PTHREAD_MUTEX_INITIALIZER; + _instance->m_condSig = PTHREAD_COND_INITIALIZER; + try { + if (m_pollThread.get().joinable()) { + m_pollThread.get().join(); + } + m_pollThread = Utils::ThreadRAII(std::thread(threadRun)); + } catch(const std::system_error& e) { + LOGERR("exception in creating threadRun %s", e.what()); + } + + } + return; + } + + void HdmiCec_2::CECDisable(void) + { + LOGINFO("Entered CECDisable "); + + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return; + } else { + LOGWARN("CEC Mgr activated. proceeding with %s", __func__); + } + if(!cecEnableStatus) + { + LOGWARN("CEC Already Disabled "); + return; + } + + { + m_sendKeyEventThreadExit = true; + std::unique_lock lk(m_sendKeyEventMutex); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + } + try + { + if (m_sendKeyEventThread.get().joinable()) + m_sendKeyEventThread.get().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()); + } + + if (smConnection != NULL) + { + LOGWARN("Stop Thread %p", smConnection ); + + m_updateThreadExit = true; + //Trigger codition to exit poll loop + pthread_mutex_lock(&(_instance->m_lockUpdate)); //Join mutex lock to wait until thread is in its wait condition + pthread_cond_signal(&(_instance->m_condSigUpdate)); + pthread_mutex_unlock(&(_instance->m_lockUpdate)); + if (m_UpdateThread.get().joinable()) {//Join thread to make sure it's deleted before moving on. + m_UpdateThread.get().join(); + } + LOGWARN("Deleted update Thread %p", smConnection ); + + m_pollThreadExit = true; + //Trigger codition to exit poll loop + pthread_mutex_lock(&(_instance->m_lock)); //Join mutex lock to wait until thread is in its wait condition + pthread_cond_signal(&(_instance->m_condSig)); + pthread_mutex_unlock(&(_instance->m_lock)); + if (m_pollThread.get().joinable()) {//Join thread to make sure it's deleted before moving on. + m_pollThread.get().join(); + } + LOGWARN("Deleted Thread %p", smConnection ); + //Clear cec device cache. + removeAllCecDevices(); + + smConnection->close(); + delete smConnection; + delete msgProcessor; + delete msgFrameListener; + msgProcessor = NULL; + msgFrameListener = NULL; + smConnection = NULL; + } + cecEnableStatus = false; + + if(1 == libcecInitStatus) + { + try + { + LibCCEC::getInstance().term(); + } + catch (const std::exception& e) + { + LOGWARN("CEC exception caught from LibCCEC::getInstance().term() "); + } + } + + libcecInitStatus--; + + return; + } + + + void HdmiCec_2::getPhysicalAddress() + { + LOGINFO("Entered getPhysicalAddress "); + + uint32_t physAddress = 0x0F0F0F0F; + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return; + } + + 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; + } + + void HdmiCec_2::getLogicalAddress() + { + LOGINFO("Entered getLogicalAddress "); + + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return; + } + try{ + LogicalAddress addr = LibCCEC::getInstance().getLogicalAddress(DEV_TYPE_TUNER); + + std::string logicalAddrDeviceType = DeviceType(LogicalAddress(addr).getType()).toString().c_str(); + + LOGINFO("logical address obtained is %d , saved logical address is %d ", addr.toInt(), logicalAddress.toInt()); + + if (logicalAddress.toInt() != addr.toInt() || logicalAddressDeviceType != logicalAddrDeviceType) + + { + logicalAddress = addr; + logicalAddressDeviceType = logicalAddrDeviceType; + } + } + catch (const std::exception& e) + { + LOGWARN("CEC exception caught from getLogicalAddress "); + } + return; + } + + bool HdmiCec_2::getEnabled() + { + LOGINFO("getEnabled :%d ",cecEnableStatus); + return cecEnableStatus; + } + + bool HdmiCec_2::getOTPEnabled() + { + if(true == cecOTPSettingEnabled) + return true; + else + return false; + LOGINFO("getOTPEnabled :%d ",cecOTPSettingEnabled); + } + + bool HdmiCec_2::performOTPAction() + { + LOGINFO("performOTPAction "); + bool ret = false; + if (!IsCecMgrActivated) { + LOGWARN("CEC Mgr not activated CEC communication is not possible"); + return ret; + } + if((true == cecEnableStatus) && (cecOTPSettingEnabled == true)) + { + if (smConnection) { + try + { + LOGINFO("Command: sending ImageViewOn TV \r\n"); + smConnection->sendTo(LogicalAddress::TV, MessageEncoder().encode(ImageViewOn())); + usleep(10000); + LOGINFO("Command: sending ActiveSource physical_addr :%s \r\n",physical_addr.toString().c_str()); + smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(ActiveSource(physical_addr))); + usleep(10000); + isDeviceActiveSource = true; + LOGINFO("Command: sending GiveDevicePowerStatus \r\n"); + smConnection->sendTo(LogicalAddress::TV, MessageEncoder().encode(GiveDevicePowerStatus())); + ret = true; + } + catch(...) + { + LOGWARN("Exception while processing performOTPAction"); + } + } + else { + LOGWARN("smConnection is NULL"); + } + } + else + LOGWARN("cecEnableStatus=false"); + return ret; + } + + uint32_t HdmiCec_2::getDeviceList (const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: + LOGINFOMETHOD(); + //Trigger CEC device poll here + pthread_cond_signal(&(_instance->m_condSig)); + + bool success = true; + response["numberofdevices"] = HdmiCec_2::_instance->m_numberOfDevices; + LOGINFO("getDeviceListWrapper m_numberOfDevices :%d \n", HdmiCec_2::_instance->m_numberOfDevices); + JsonArray deviceListArg; + try + { + int i = 0; + for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { + if (BIT_CHECK(deviceList[i].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) { + JsonObject device; + device["logicalAddress"] = HdmiCec_2::_instance->deviceList[i].m_logicalAddress.toInt(); + device["osdName"] = HdmiCec_2::_instance->deviceList[i].m_osdName.toString().c_str(); + device["vendorID"] = HdmiCec_2::_instance->deviceList[i].m_vendorID.toString().c_str(); + deviceListArg.Add(device); + } + } + } + catch (...) + { + LOGERR("Exception in api"); + success = false; + } + response["deviceList"] = deviceListArg; + returnResponse(success); + } + + bool HdmiCec_2::pingDeviceUpdateList (int idev) + { + bool isConnected = false; + //self ping is not required + if (idev == logicalAddress.toInt()){ + return isConnected; + } + if(!HdmiCec_2::_instance) + { + LOGERR("HdmiCec_2::_instance not existing"); + return isConnected; + } + if ( !(_instance->smConnection) || logicalAddress.toInt() == LogicalAddress::UNREGISTERED || (false==cecEnableStatus)){ + LOGERR("Exiting from pingDeviceUpdateList _instance->smConnection:%p, logicalAddress:%d, cecEnableStatus=%d", + _instance->smConnection, logicalAddress.toInt(), cecEnableStatus); + return isConnected; + } + + LOGWARN("PING for 0x%x \r\n",idev); + try { + _instance->smConnection->ping(logicalAddress, LogicalAddress(idev), Throw_e()); + } + catch(CECNoAckException &e) + { + if (BIT_CHECK(_instance->deviceList[idev].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) { + LOGINFO("Device disconnected: %d \r\n",idev); + removeDevice (idev); + } else { + LOGINFO("Device is not connected: %d. Ping caught %s\r\n",idev, e.what()); + } + isConnected = false; + return isConnected;; + } + catch(IOException &e) + { + LOGINFO("Device is not reachable: %d. Ping caught %s\r\n",idev, e.what()); + isConnected = false; + return isConnected;; + } + catch(Exception &e) + { + LOGINFO("Ping caught %s \r\n",e.what()); + } + + /* If we get ACK, then the device is present in the network*/ + isConnected = true; + if ( !(BIT_CHECK(_instance->deviceList[idev].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) ) + { + LOGINFO("Device connected: %d \r\n",idev); + addDevice (idev); + } + return isConnected; + } + + void HdmiCec_2::sendDeviceUpdateInfo(const int logicalAddress) + { + JsonObject params; + params["logicalAddress"] = JsonValue(logicalAddress); + LOGINFO("Device info updated notification send: for logical address:%d\r\n", logicalAddress); + sendNotify(eventString[HDMICEC2_EVENT_DEVICE_INFO_UPDATED], params); + } + + void HdmiCec_2::addDevice(const int logicalAddress) { + + if(!HdmiCec_2::_instance) + return; + + if ( logicalAddress >= LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + if ( !(BIT_CHECK(HdmiCec_2::_instance->deviceList[logicalAddress].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) ) + { + BIT_SET(HdmiCec_2::_instance->deviceList[logicalAddress].m_deviceInfoStatus, BIT_DEVICE_PRESENT); + HdmiCec_2::_instance->deviceList[logicalAddress].m_logicalAddress = LogicalAddress(logicalAddress); + HdmiCec_2::_instance->m_numberOfDevices++; + LOGINFO("New cec ligical address add notification send: \r\n"); + sendNotify(eventString[HDMICEC2_EVENT_DEVICE_ADDED], JsonObject()); + } + //Two source devices can have same logical address. + requestCecDevDetails(logicalAddress); + } + + void HdmiCec_2::removeAllCecDevices() { + int i = 0; + for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { + removeDevice (i); + } + } + void HdmiCec_2::removeDevice(const int logicalAddress) { + if(!HdmiCec_2::_instance) + return; + + if ( logicalAddress >= LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + if (BIT_CHECK(HdmiCec_2::_instance->deviceList[logicalAddress].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) + { + _instance->m_numberOfDevices--; + _instance->deviceList[logicalAddress].clear(); + LOGINFO("Cec ligical address remove notification send: \r\n"); + sendNotify(eventString[HDMICEC2_EVENT_DEVICE_REMOVED], JsonObject()); + } + } + + void HdmiCec_2::sendUnencryptMsg(unsigned char* msg, int size) + { + LOGINFO("sendMessage "); + + if(true == cecEnableStatus) + { + std::vector buf; + buf.resize(size); + + int itr = 0; + for (itr= 0; itrsendAsync(frame); + } + else + LOGWARN("cecEnableStatus=false"); + return; + } + + void HdmiCec_2::requestVendorID(const int newDevlogicalAddress) + { + //Get OSD name and vendor ID only from connected devices. Since devices are identified using polling + //Once OSD name and Vendor ID is updated. We have to poll again in next iteration also. Just to check + //a new device is reconnected with same logical address + unsigned char msg [2]; + unsigned int logicalAddr = logicalAddress.toInt(); + unsigned char sender = (unsigned char)(logicalAddr & 0x0f); + unsigned char receiver = (unsigned char) (newDevlogicalAddress & 0x0f); + + msg [0] = (sender<<4)|receiver; + //Request vendor id + msg [1] = 0x8c; + LOGINFO("Sending msg request vendor id %x %x", msg [0], msg [1]); + _instance->sendUnencryptMsg (msg, sizeof(msg)); + + } + + void HdmiCec_2::requestOsdName(const int newDevlogicalAddress) + { + //Get OSD name and vendor ID only from connected devices. Since devices are identified using polling + //Once OSD name and Vendor ID is updated. We have to poll again in next iteration also. Just to check + //a new device is reconnected with same logical address + unsigned char msg [2]; + unsigned int logicalAddr = logicalAddress.toInt(); + unsigned char sender = (unsigned char)(logicalAddr & 0x0f); + unsigned char receiver = (unsigned char) (newDevlogicalAddress & 0x0f); + + msg [0] = (sender<<4)|receiver; + //Request OSD name + msg [1] = 0x46; + LOGINFO("Sending msg request osd name %x %x", msg [0], msg [1]); + _instance->sendUnencryptMsg (msg, sizeof(msg)); + + } + + void HdmiCec_2::requestCecDevDetails(const int newDevlogicalAddress) + { + //Get OSD name and vendor ID only from connected devices. Since devices are identified using polling + //Once OSD name and Vendor ID is updated. We have to poll again in next iteration also. Just to check + //a new device is reconnected with same logical address + requestVendorID (newDevlogicalAddress); + requestOsdName (newDevlogicalAddress); + } + + void HdmiCec_2::threadRun() + { + if(!HdmiCec_2::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO("Entering ThreadRun: _instance->m_pollThreadExit %d",_instance->m_pollThreadExit); + int i = 0; + pthread_mutex_lock(&(_instance->m_lock));//pthread_cond_wait should be mutex protected. //pthread_cond_wait will unlock the mutex and perfoms wait for the condition. + while (!_instance->m_pollThreadExit) { + bool isActivateUpdateThread = false; + LOGINFO("Starting cec device polling"); + for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { + bool isConnected = _instance->pingDeviceUpdateList(i); + if (isConnected){ + isActivateUpdateThread = isConnected; + } + + } + if (isActivateUpdateThread){ + //i any of devices is connected activate thread update check + pthread_cond_signal(&(_instance->m_condSigUpdate)); + } + //Wait for mutex signal here to continue the worker thread again. + pthread_cond_wait(&(_instance->m_condSig), &(_instance->m_lock)); + + } + pthread_mutex_unlock(&(_instance->m_lock)); + LOGINFO("%s: Thread exited", __FUNCTION__); + } + void HdmiCec_2::threadSendKeyEvent() + { + if(!HdmiCec_2::_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(); + + LOGINFO("sendRemoteKeyThread : logical addr:0x%x keyCode: 0x%x queue size :%d \n",keyInfo.logicalAddr,keyInfo.keyCode,(int)_instance->m_SendKeyQueue.size()); + _instance->sendKeyPressEvent(keyInfo.logicalAddr,keyInfo.keyCode); + _instance->sendKeyReleaseEvent(keyInfo.logicalAddr); + } + LOGINFO("%s: Thread exited", __FUNCTION__); + } + void HdmiCec_2::threadUpdateCheck() + { + if(!HdmiCec_2::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO("Entering ThreadUpdate: _instance->m_updateThreadExit %d",_instance->m_updateThreadExit); + int i = 0; + pthread_mutex_lock(&(_instance->m_lockUpdate));//pthread_cond_wait should be mutex protected. //pthread_cond_wait will unlock the mutex and perfoms wait for the condition. + while (!_instance->m_updateThreadExit) { + //Wait for mutex signal here to continue the worker thread again. + pthread_cond_wait(&(_instance->m_condSigUpdate), &(_instance->m_lockUpdate)); + + LOGINFO("Starting cec device update check"); + for(i=0; ((i< LogicalAddress::UNREGISTERED)&&(!_instance->m_updateThreadExit)); i++ ) { + //If details are not updated. update now. + if (BIT_CHECK(HdmiCec_2::_instance->deviceList[i].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) + { + int itr = 0; + bool retry = true; + int iCounter = 0; + for (itr = 0; ((itr<5)&&(retry)); itr++){ + + if (!HdmiCec_2::_instance->deviceList[i].m_isOSDNameUpdated){ + iCounter = 0; + while ((!_instance->m_updateThreadExit) && (iCounter < (2*10))) { //sleep for 2sec. + usleep (100 * 1000); //sleep for 100 milli sec + iCounter ++; + } + + HdmiCec_2::_instance->requestOsdName (i); + retry = true; + } + else { + retry = false; + } + + if (!HdmiCec_2::_instance->deviceList[i].m_isVendorIDUpdated){ + iCounter = 0; + while ((!_instance->m_updateThreadExit) && (iCounter < (2*10))) { //sleep for 1sec. + usleep (100 * 1000); //sleep for 100 milli sec + iCounter ++; + } + + HdmiCec_2::_instance->requestVendorID (i); + retry = true; + } + } + if (retry){ + LOGINFO("cec device: %d update time out", i); + } + } + } + + } + pthread_mutex_unlock(&(_instance->m_lockUpdate)); + LOGINFO("%s: Thread exited", __FUNCTION__); + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/HdmiCec_2/HdmiCec_2.h b/HdmiCec_2/HdmiCec_2.h new file mode 100644 index 00000000..0882ae7f --- /dev/null +++ b/HdmiCec_2/HdmiCec_2.h @@ -0,0 +1,338 @@ +/** +* 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 +#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" +#include + +#undef Assert // this define from Connection.hpp conflicts with WPEFramework + +#include "Module.h" + +#include "UtilsBIT.h" +#include "UtilsThreadRAII.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 HdmiCec_2FrameListener : public FrameListener + { + public: + HdmiCec_2FrameListener(MessageProcessor &processor) : processor(processor) {} + void notify(const CECFrame &in) const; + ~HdmiCec_2FrameListener() {} + private: + MessageProcessor &processor; + }; + + class HdmiCec_2Processor : public MessageProcessor + { + public: + HdmiCec_2Processor(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); + 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()); + } + + }; + +#define BIT_DEVICE_PRESENT (0) + + class CECDeviceInfo_2 { + public: + + LogicalAddress m_logicalAddress; + VendorID m_vendorID; + OSDName m_osdName; + // + short m_deviceInfoStatus; + bool m_isOSDNameUpdated; + bool m_isVendorIDUpdated; + std::mutex m_; + std::condition_variable cv_; + std::unique_lock lk; + + CECDeviceInfo_2() + : m_logicalAddress(0),m_vendorID(0,0,0),m_osdName("NA"), m_isOSDNameUpdated (false), m_isVendorIDUpdated (false) + { + BITMASK_CLEAR(m_deviceInfoStatus, 0xFFFF); //Clear all bits + } + + void clear( ) + { + m_logicalAddress = 0; + m_vendorID = VendorID(0,0,0); + m_osdName = "NA"; + BITMASK_CLEAR(m_deviceInfoStatus, 0xFFFF); //Clear all bits + m_isOSDNameUpdated = false; + m_isVendorIDUpdated = false; + } + + bool update ( const VendorID &vendorId) { + bool isVendorIdUpdated = false; + if (!m_isVendorIDUpdated) + isVendorIdUpdated = true; //First time no need to cross check the value. Since actual value can be default value + else + isVendorIdUpdated = (m_vendorID.toString().compare(vendorId.toString())==0)?false:true; + + m_isVendorIDUpdated = true; + m_vendorID = vendorId; + return isVendorIdUpdated; + } + + bool update ( const OSDName &osdName ) { + bool isOSDNameUpdated = false; + if (!m_isOSDNameUpdated) + isOSDNameUpdated = true; //First time no need to cross check the value. Since actual value can be default value + else + isOSDNameUpdated = (m_osdName.toString().compare(osdName.toString())==0)?false:true; + + m_isOSDNameUpdated = true; + m_osdName = osdName; + return isOSDNameUpdated; + } + + }; + + // 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 HdmiCec_2 : public PluginHost::IPlugin, public PluginHost::JSONRPC { + 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: + HdmiCec_2(); + virtual ~HdmiCec_2(); + virtual const string Initialize(PluginHost::IShell* service) override; + virtual void Deinitialize(PluginHost::IShell* service) override; + virtual string Information() const override { return {}; } + void onPowerModeChanged(const PowerState ¤tState, const PowerState &newState); + void registerEventHandlers(); + static HdmiCec_2* _instance; + CECDeviceInfo_2 deviceList[16]; + pthread_cond_t m_condSig; + pthread_mutex_t m_lock; + pthread_cond_t m_condSigUpdate; + pthread_mutex_t m_lockUpdate; + + void SendStandbyMsgEvent(const int logicalAddress); + void sendActiveSourceEvent(); + void addDevice(const int logicalAddress); + void removeDevice(const int logicalAddress); + void sendUnencryptMsg(unsigned char* msg, int size); + void sendDeviceUpdateInfo(const int logicalAddress); + void sendKeyPressEvent(const int logicalAddress, int keyCode); + void sendKeyReleaseEvent(const int logicalAddress); + typedef struct sendKeyInfo + { + int logicalAddr; + int keyCode; + }SendKeyInfo; + BEGIN_INTERFACE_MAP(HdmiCec_2) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + END_INTERFACE_MAP + + private: + class PowerManagerNotification : public Exchange::IPowerManager::INotification { + private: + PowerManagerNotification(const PowerManagerNotification&) = delete; + PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; + + public: + explicit PowerManagerNotification(HdmiCec_2& parent) + : _parent(parent) + { + } + ~PowerManagerNotification() override = default; + + public: + void OnPowerModeChanged(const PowerState ¤tState, const PowerState &newState) override + { + _parent.onPowerModeChanged(currentState, newState); + } + void OnPowerModePreChange(const PowerState ¤tState, const PowerState &newState) override {} + void OnDeepSleepTimeout(const int &wakeupTimeout) override {} + void OnNetworkStandbyModeChanged(const bool &enabled) override {} + void OnThermalModeChanged(const ThermalTemperature ¤tThermalLevel, const ThermalTemperature &newThermalLevel, const float ¤tTemperature) override {} + void OnRebootBegin(const string &rebootReasonCustom, const string &rebootReasonOther, const string &rebootRequestor) override {} + + BEGIN_INTERFACE_MAP(PowerManagerNotification) + INTERFACE_ENTRY(Exchange::IPowerManager::INotification) + END_INTERFACE_MAP + + private: + HdmiCec_2& _parent; + }; + // We do not allow this plugin to be copied !! + HdmiCec_2(const HdmiCec_2&) = delete; + HdmiCec_2& operator=(const HdmiCec_2&) = delete; + + //Begin methods + uint32_t setEnabledWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getEnabledWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setOTPEnabledWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getOTPEnabledWrapper(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 performOTPActionWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getDeviceList (const JsonObject& parameters, JsonObject& response); + uint32_t getActiveSourceStatus(const JsonObject& parameters, JsonObject& response); + uint32_t sendRemoteKeyPressWrapper(const JsonObject& parameters, JsonObject& response); + + //End methods + std::string logicalAddressDeviceType; + bool cecSettingEnabled; + bool cecOTPSettingEnabled; + bool cecEnableStatus; + bool IsCecMgrActivated; + Connection *smConnection; + int m_numberOfDevices; + bool m_pollThreadExit; + Utils::ThreadRAII m_pollThread; + bool m_updateThreadExit; + Utils::ThreadRAII m_UpdateThread; + bool m_sendKeyEventThreadExit; + bool m_sendKeyEventThreadRun; + Utils::ThreadRAII m_sendKeyEventThread; + std::mutex m_sendKeyEventMutex; + std::queue m_SendKeyQueue; + std::condition_variable m_sendKeyCV; + + HdmiCec_2Processor *msgProcessor; + HdmiCec_2FrameListener *msgFrameListener; + PowerManagerInterfaceRef _powerManagerPlugin; + Core::Sink _pwrMgrNotification; + bool _registeredEventHandlers; + void InitializePowerManagerPluginHost::IShell *service + const void InitializeIARM(); + void DeinitializeIARM(); + static void cecMgrEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + void onCECDaemonInit(); + void cecStatusUpdated(void *evtStatus); + void onHdmiHotPlug(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 isPersist); + bool getEnabled(); + void setOTPEnabled(bool enabled); + bool getOTPEnabled(); + bool performOTPAction(); + void CECEnable(void); + void CECDisable(void); + void getPhysicalAddress(); + void getLogicalAddress(); + void cecAddressesChanged(int changeStatus); + bool sendStandbyMessage(); + bool pingDeviceUpdateList (int idev); + void removeAllCecDevices(); + void requestVendorID(const int newDevlogicalAddress); + void requestOsdName(const int newDevlogicalAddress); + void requestCecDevDetails(const int logicalAddress); + static void threadRun(); + static void threadUpdateCheck(); + static void threadSendKeyEvent(); + }; + } // namespace Plugin +} // namespace WPEFramework + + + + diff --git a/HdmiCec_2/Module.cpp b/HdmiCec_2/Module.cpp new file mode 100644 index 00000000..ce759b61 --- /dev/null +++ b/HdmiCec_2/Module.cpp @@ -0,0 +1,22 @@ +/** +* 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/HdmiCec_2/Module.h b/HdmiCec_2/Module.h new file mode 100644 index 00000000..5409162d --- /dev/null +++ b/HdmiCec_2/Module.h @@ -0,0 +1,29 @@ +/** +* 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_HdmiCec_2 +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/HdmiCec_2/README.md b/HdmiCec_2/README.md new file mode 100644 index 00000000..fe054a42 --- /dev/null +++ b/HdmiCec_2/README.md @@ -0,0 +1,9 @@ +----------------- +Build: + +bitbake wpeframework-service-plugins + +----------------- +Test: + +curl --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0","id":"3","method": "rdk.org.HdmiCec_2.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/HdmiInput/CHANGELOG.md b/HdmiInput/CHANGELOG.md new file mode 100644 index 00000000..3e73c318 --- /dev/null +++ b/HdmiInput/CHANGELOG.md @@ -0,0 +1,27 @@ +# 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 new file mode 100644 index 00000000..b5d667a4 --- /dev/null +++ b/HdmiInput/CMakeLists.txt @@ -0,0 +1,64 @@ +# 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 new file mode 100644 index 00000000..e16bde27 --- /dev/null +++ b/HdmiInput/HdmiInput.conf.in @@ -0,0 +1,4 @@ +precondition = ["Platform"] +callsign = "org.rdk.HdmiInput" +autostart = "false" +startuporder = "@PLUGIN_HDMIINPUT_STARTUPORDER@" diff --git a/HdmiInput/HdmiInput.config b/HdmiInput/HdmiInput.config new file mode 100644 index 00000000..2b918b14 --- /dev/null +++ b/HdmiInput/HdmiInput.config @@ -0,0 +1,7 @@ +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 new file mode 100644 index 00000000..e45efa09 --- /dev/null +++ b/HdmiInput/HdmiInput.cpp @@ -0,0 +1,1431 @@ +/** +* 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; + + 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 new file mode 100644 index 00000000..ff93202e --- /dev/null +++ b/HdmiInput/HdmiInput.h @@ -0,0 +1,139 @@ +/** +* 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 new file mode 100644 index 00000000..ce759b61 --- /dev/null +++ b/HdmiInput/Module.cpp @@ -0,0 +1,22 @@ +/** +* 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 new file mode 100644 index 00000000..54e672c3 --- /dev/null +++ b/HdmiInput/Module.h @@ -0,0 +1,29 @@ +/** +* 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 new file mode 100644 index 00000000..998e3280 --- /dev/null +++ b/HdmiInput/README.md @@ -0,0 +1,9 @@ +----------------- +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 new file mode 100644 index 00000000..926c02e0 --- /dev/null +++ b/HdmiInput/cmake/FindDS.cmake @@ -0,0 +1,57 @@ +# 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 new file mode 100644 index 00000000..bc716bcd --- /dev/null +++ b/HdmiInput/cmake/FindIARMBus.cmake @@ -0,0 +1,44 @@ +# 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) From fce9908fac4e11f61e00268b17ef6ead7558f69f Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Tue, 4 Mar 2025 00:10:22 +0530 Subject: [PATCH 4/6] Delete CompositeInput directory --- CompositeInput/CHANGELOG.md | 28 -- CompositeInput/CMakeLists.txt | 54 --- CompositeInput/CompositeInput.conf.in | 4 - CompositeInput/CompositeInput.config | 7 - CompositeInput/CompositeInput.cpp | 519 ------------------------- CompositeInput/CompositeInput.h | 93 ----- CompositeInput/Module.cpp | 22 -- CompositeInput/Module.h | 29 -- CompositeInput/README.md | 9 - CompositeInput/cmake/FindDS.cmake | 57 --- CompositeInput/cmake/FindIARMBus.cmake | 44 --- 11 files changed, 866 deletions(-) delete mode 100644 CompositeInput/CHANGELOG.md delete mode 100644 CompositeInput/CMakeLists.txt delete mode 100644 CompositeInput/CompositeInput.conf.in delete mode 100644 CompositeInput/CompositeInput.config delete mode 100644 CompositeInput/CompositeInput.cpp delete mode 100644 CompositeInput/CompositeInput.h delete mode 100644 CompositeInput/Module.cpp delete mode 100644 CompositeInput/Module.h delete mode 100644 CompositeInput/README.md delete mode 100644 CompositeInput/cmake/FindDS.cmake delete mode 100644 CompositeInput/cmake/FindIARMBus.cmake diff --git a/CompositeInput/CHANGELOG.md b/CompositeInput/CHANGELOG.md deleted file mode 100644 index 06bea2b4..00000000 --- a/CompositeInput/CHANGELOG.md +++ /dev/null @@ -1,28 +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.1.5] - 2025-02-17 -### Added - -Added support for handling the videoStreamInfoUpdate for composite Input. - -## [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/CompositeInput/CMakeLists.txt b/CompositeInput/CMakeLists.txt deleted file mode 100644 index a4d6084a..00000000 --- a/CompositeInput/CMakeLists.txt +++ /dev/null @@ -1,54 +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 CompositeInput) -set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) - -set(PLUGIN_COMPOSITEINPUT_STARTUPORDER "" CACHE STRING "To configure startup order of CompositeInput plugin") - -find_package(${NAMESPACE}Plugins REQUIRED) - -add_library(${MODULE_NAME} SHARED - CompositeInput.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}) - -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(CompositeInput.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/CompositeInput/CompositeInput.conf.in b/CompositeInput/CompositeInput.conf.in deleted file mode 100644 index 7c230b92..00000000 --- a/CompositeInput/CompositeInput.conf.in +++ /dev/null @@ -1,4 +0,0 @@ -precondition = ["Platform"] -callsign = "org.rdk.CompositeInput" -autostart = "false" -startuporder = "@PLUGIN_COMPOSITEINPUT_STARTUPORDER@" diff --git a/CompositeInput/CompositeInput.config b/CompositeInput/CompositeInput.config deleted file mode 100644 index 0762bf3c..00000000 --- a/CompositeInput/CompositeInput.config +++ /dev/null @@ -1,7 +0,0 @@ -set (autostart false) -set (preconditions Platform) -set (callsign "org.rdk.CompositeInput") - -if(PLUGIN_COMPOSITEINPUT_STARTUPORDER) -set (startuporder ${PLUGIN_COMPOSITEINPUT_STARTUPORDER}) -endif() diff --git a/CompositeInput/CompositeInput.cpp b/CompositeInput/CompositeInput.cpp deleted file mode 100644 index fa06704a..00000000 --- a/CompositeInput/CompositeInput.cpp +++ /dev/null @@ -1,519 +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 "CompositeInput.h" -#include "UtilsJsonRpc.h" -#include "UtilsIarm.h" - -#include "compositeIn.hpp" -#include "exception.hpp" -#include "dsUtl.h" -#include "dsError.h" -#include "dsMgr.h" - -#define API_VERSION_NUMBER_MAJOR 1 -#define API_VERSION_NUMBER_MINOR 1 -#define API_VERSION_NUMBER_PATCH 5 - -#define COMPOSITE_HOT_PLUG_EVENT_CONNECTED 1 -#define COMPOSITE_HOT_PLUG_EVENT_DISCONNECTED 0 - -#define COMPOSITEINPUT_METHOD_GET_COMPOSITE_INPUT_DEVICES "getCompositeInputDevices" -#define COMPOSITEINPUT_METHOD_START_COMPOSITE_INPUT "startCompositeInput" -#define COMPOSITEINPUT_METHOD_STOP_COMPOSITE_INPUT "stopCompositeInput" -#define COMPOSITEINPUT_METHOD_SCALE_COMPOSITE_INPUT "setVideoRectangle" - -#define COMPOSITEINPUT_EVENT_ON_DEVICES_CHANGED "onDevicesChanged" -#define COMPOSITEINPUT_EVENT_ON_SIGNAL_CHANGED "onSignalChanged" -#define COMPOSITEINPUT_EVENT_ON_STATUS_CHANGED "onInputStatusChanged" -#define COMPOSITEINPUT_EVENT_ON_VIDEO_MODE_UPDATED "videoStreamInfoUpdate" - -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(CompositeInput, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - - CompositeInput* CompositeInput::_instance = nullptr; - - CompositeInput::CompositeInput() - : PluginHost::JSONRPC() - { - CompositeInput::_instance = this; - - //InitializeIARM(); - - Register(COMPOSITEINPUT_METHOD_GET_COMPOSITE_INPUT_DEVICES, &CompositeInput::getCompositeInputDevicesWrapper, this); - Register(COMPOSITEINPUT_METHOD_START_COMPOSITE_INPUT, &CompositeInput::startCompositeInput, this); - Register(COMPOSITEINPUT_METHOD_STOP_COMPOSITE_INPUT, &CompositeInput::stopCompositeInput, this); - Register(COMPOSITEINPUT_METHOD_SCALE_COMPOSITE_INPUT, &CompositeInput::setVideoRectangleWrapper, this); - } - - CompositeInput::~CompositeInput() - { - } - const string CompositeInput::Initialize(PluginHost::IShell * /* service */) - { - CompositeInput::_instance = this; - InitializeIARM(); - return (string()); - } - - void CompositeInput::Deinitialize(PluginHost::IShell* /* service */) - { - CompositeInput::_instance = nullptr; - - DeinitializeIARM(); - } - - void CompositeInput::InitializeIARM() - { - if (Utils::IARM::init()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, dsCompositeEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, dsCompositeSignalStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS, dsCompositeStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE,dsCompositeVideoModeEventHandler) ); - } - } - - void CompositeInput::DeinitializeIARM() - { - if (Utils::IARM::isConnected()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, dsCompositeEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, dsCompositeSignalStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS, dsCompositeStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE, dsCompositeVideoModeEventHandler) ); - } - } - - uint32_t CompositeInput::startCompositeInput(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) { - LOGERR("Failed to portId value..!"); - returnResponse(false); - } - - bool success = true; - try - { - device::CompositeInput::getInstance().selectPort(portId); - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(sPortId); - success = false; - } - returnResponse(success); - - } - - uint32_t CompositeInput::stopCompositeInput(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - bool success = true; - try - { - device::CompositeInput::getInstance().selectPort(-1); - } - catch (const device::Exception& err) - { - LOGWARN("CompositeInputService::stopCompositeInput Failed"); - success = false; - } - returnResponse(success); - - } - - uint32_t CompositeInput::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 (...) { - LOGWARN("Invalid Arguments"); - response["message"] = "Invalid Arguments"; - returnResponse(false); - } - - result = setVideoRectangle(x, y, w, h); - if (false == result) { - LOGWARN("CompositeInputService::setVideoRectangle Failed"); - response["message"] = "failed to set scale"; - } - } - - returnResponse(result); - - } - - bool CompositeInput::setVideoRectangle(int x, int y, int width, int height) - { - bool ret = true; - - try - { - device::CompositeInput::getInstance().scaleVideo(x, y, width, height); - } - catch (const device::Exception& err) - { - ret = false; - } - - return ret; - } - - uint32_t CompositeInput::getCompositeInputDevicesWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - response["devices"] = getCompositeInputDevices(); - - returnResponse(true); - } - - JsonArray CompositeInput::getCompositeInputDevices() - { - JsonArray list; - try - { - int num = device::CompositeInput::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 << "cvbsin://localhost/deviceid/" << i; - hash["locator"] = locator.str(); - hash["connected"] = device::CompositeInput::getInstance().isPortConnected(i) ? "true" : "false"; - LOGWARN("CompositeInputService::getCompositeInputDevices 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("CompositeInputService::getCompositeInputDevices Failed"); - } - - return list; - } - - - /** - * @brief This function is used to translate COMPOSITE input hotplug to - * deviceChanged event. - * - * @param[in] input Number of input port integer. - * @param[in] connection status of input port integer. - */ - void CompositeInput::compositeInputHotplug( int input , int connect) - { - LOGWARN("compositeInputHotplug [%d, %d]", input, connect); - - JsonObject params; - params["devices"] = getCompositeInputDevices(); - sendNotify(COMPOSITEINPUT_EVENT_ON_DEVICES_CHANGED, params); - } - - /** - * @brief This function is used to translate Composite input signal change - * to onSignalChanged event. - * - * @param[in] port Composite In port id. - * @param[in] signalStatus signal status of Composite In port. - */ - void CompositeInput::compositeInputSignalChange( int port , int signalStatus) - { - LOGWARN("compositeInputSignalChange [%d, %d]", port, signalStatus); - - JsonObject params; - params["id"] = port; - std::stringstream locator; - locator << "cvbsin://localhost/deviceid/" << port; - params["locator"] = locator.str(); - - switch (signalStatus) { - case dsCOMP_IN_SIGNAL_STATUS_NOSIGNAL: - params["signalStatus"] = "noSignal"; - break; - - case dsCOMP_IN_SIGNAL_STATUS_UNSTABLE: - params["signalStatus"] = "unstableSignal"; - break; - - case dsCOMP_IN_SIGNAL_STATUS_NOTSUPPORTED: - params["signalStatus"] = "notSupportedSignal"; - break; - - case dsCOMP_IN_SIGNAL_STATUS_STABLE: - params["signalStatus"] = "stableSignal"; - break; - - default: - params["signalStatus"] = "none"; - break; - } - - sendNotify(COMPOSITEINPUT_EVENT_ON_SIGNAL_CHANGED, params); - } - - /** - * @brief This function is used to translate Composite input status change to - * inputStatusChanged event. - * - * @param[in] port Composite In port id. - * @param[bool] isPresented Composite In presentation started/stopped. - */ - void CompositeInput::compositeInputStatusChange( int port , bool isPresented) - { - LOGWARN("compositeInputStatusChange [%d, %d]", port, isPresented); - - JsonObject params; - params["id"] = port; - std::stringstream locator; - locator << "cvbsin://localhost/deviceid/" << port; - params["locator"] = locator.str(); - - if(isPresented) { - params["status"] = "started"; - } - else { - params["status"] = "stopped"; - } - - sendNotify(COMPOSITEINPUT_EVENT_ON_STATUS_CHANGED, params); - } - /** - * @brief This function is used to translate Composite input video mode change to - * videoStreamInfoUpdate event. - * - * @param[in] port Composite In port id. - * @param[dsVideoPortResolution_t] video resolution data - */ - void CompositeInput::compositeInputVideoModeUpdate( int port , dsVideoPortResolution_t resolution) - { - LOGWARN("compositeInputVideoModeUpdate [%d]", port); - - JsonObject params; - params["id"] = port; - std::stringstream locator; - locator << "cvbsin://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; - default: - params["width"] = 720; - params["height"] = 576; - break; - } - - params["progressive"] = false; - - 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; - - default: - params["frameRateN"] = 60000; - params["frameRateD"] = 1000; - break; - } - - sendNotify(COMPOSITEINPUT_EVENT_ON_VIDEO_MODE_UPDATED, params); - } - - void CompositeInput::dsCompositeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!CompositeInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int compositein_hotplug_port = eventData->data.composite_in_connect.port; - int compositein_hotplug_conn = eventData->data.composite_in_connect.isPortConnected; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG event data:%d", compositein_hotplug_port); - - CompositeInput::_instance->compositeInputHotplug(compositein_hotplug_port, compositein_hotplug_conn ? COMPOSITE_HOT_PLUG_EVENT_CONNECTED : COMPOSITE_HOT_PLUG_EVENT_DISCONNECTED); - } - } - - void CompositeInput::dsCompositeSignalStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!CompositeInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int composite_in_port = eventData->data.composite_in_sig_status.port; - int composite_in_signal_status = eventData->data.composite_in_sig_status.status; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS event port: %d, signal status: %d", composite_in_port,composite_in_signal_status); - - CompositeInput::_instance->compositeInputSignalChange(composite_in_port, composite_in_signal_status); - } - } - - void CompositeInput::dsCompositeStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!CompositeInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int composite_in_port = eventData->data.composite_in_status.port; - bool composite_in_status = eventData->data.composite_in_status.isPresented; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS event port: %d, started: %d", composite_in_port,composite_in_status); - - CompositeInput::_instance->compositeInputStatusChange(composite_in_port, composite_in_status); - } - } - void CompositeInput::dsCompositeVideoModeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!CompositeInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int composite_in_port = eventData->data.composite_in_video_mode.port; - dsVideoPortResolution_t resolution = {}; - resolution.pixelResolution = eventData->data.composite_in_video_mode.resolution.pixelResolution; - resolution.interlaced = eventData->data.composite_in_video_mode.resolution.interlaced; - resolution.frameRate = eventData->data.composite_in_video_mode.resolution.frameRate; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE event port: %d, pixelResolution: %d, interlaced : %d, frameRate: %d \n", composite_in_port,resolution.pixelResolution, resolution.interlaced, resolution.frameRate); - - CompositeInput::_instance->compositeInputVideoModeUpdate(composite_in_port, resolution); - - } - } - - } // namespace Plugin -} // namespace WPEFramework diff --git a/CompositeInput/CompositeInput.h b/CompositeInput/CompositeInput.h deleted file mode 100644 index 3d1de607..00000000 --- a/CompositeInput/CompositeInput.h +++ /dev/null @@ -1,93 +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 "dsTypes.h" -#include "Module.h" - -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 CompositeInput : public PluginHost::IPlugin, public PluginHost::JSONRPC { - private: - - // We do not allow this plugin to be copied !! - CompositeInput(const CompositeInput&) = delete; - CompositeInput& operator=(const CompositeInput&) = delete; - - void InitializeIARM(); - void DeinitializeIARM(); - - //Begin methods - uint32_t getCompositeInputDevicesWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t startCompositeInput(const JsonObject& parameters, JsonObject& response); - uint32_t stopCompositeInput(const JsonObject& parameters, JsonObject& response); - - uint32_t setVideoRectangleWrapper(const JsonObject& parameters, JsonObject& response); - //End methods - - JsonArray getCompositeInputDevices(); - - bool setVideoRectangle(int x, int y, int width, int height); - - void compositeInputHotplug( int input , int connect); - static void dsCompositeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void compositeInputSignalChange( int port , int signalStatus); - static void dsCompositeSignalStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void compositeInputStatusChange( int port , bool isPresented); - static void dsCompositeStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void compositeInputVideoModeUpdate( int port , dsVideoPortResolution_t resolution); - static void dsCompositeVideoModeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - public: - CompositeInput(); - virtual ~CompositeInput(); - 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(CompositeInput) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - END_INTERFACE_MAP - - public: - static CompositeInput* _instance; - }; - } // namespace Plugin -} // namespace WPEFramework diff --git a/CompositeInput/Module.cpp b/CompositeInput/Module.cpp deleted file mode 100644 index ce759b61..00000000 --- a/CompositeInput/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/CompositeInput/Module.h b/CompositeInput/Module.h deleted file mode 100644 index 094a815d..00000000 --- a/CompositeInput/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_CompositeInput -#endif - -#include -#include - -#undef EXTERNAL -#define EXTERNAL diff --git a/CompositeInput/README.md b/CompositeInput/README.md deleted file mode 100644 index 11123c51..00000000 --- a/CompositeInput/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": "CompositeInput.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/CompositeInput/cmake/FindDS.cmake b/CompositeInput/cmake/FindDS.cmake deleted file mode 100644 index 926c02e0..00000000 --- a/CompositeInput/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/CompositeInput/cmake/FindIARMBus.cmake b/CompositeInput/cmake/FindIARMBus.cmake deleted file mode 100644 index bc716bcd..00000000 --- a/CompositeInput/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) From 1cfa184e09da59bc5dc40c45234d68b25f01461c Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Tue, 4 Mar 2025 00:10:36 +0530 Subject: [PATCH 5/6] Delete HdmiCec_2 directory --- HdmiCec_2/CHANGELOG.md | 16 - HdmiCec_2/CMakeLists.txt | 51 - HdmiCec_2/HdmiCec_2.conf.in | 5 - HdmiCec_2/HdmiCec_2.config | 7 - HdmiCec_2/HdmiCec_2.cpp | 1777 ----------------------------------- HdmiCec_2/HdmiCec_2.h | 338 ------- HdmiCec_2/Module.cpp | 22 - HdmiCec_2/Module.h | 29 - HdmiCec_2/README.md | 9 - 9 files changed, 2254 deletions(-) delete mode 100644 HdmiCec_2/CHANGELOG.md delete mode 100644 HdmiCec_2/CMakeLists.txt delete mode 100644 HdmiCec_2/HdmiCec_2.conf.in delete mode 100644 HdmiCec_2/HdmiCec_2.config delete mode 100644 HdmiCec_2/HdmiCec_2.cpp delete mode 100644 HdmiCec_2/HdmiCec_2.h delete mode 100644 HdmiCec_2/Module.cpp delete mode 100644 HdmiCec_2/Module.h delete mode 100644 HdmiCec_2/README.md diff --git a/HdmiCec_2/CHANGELOG.md b/HdmiCec_2/CHANGELOG.md deleted file mode 100644 index 2e200c40..00000000 --- a/HdmiCec_2/CHANGELOG.md +++ /dev/null @@ -1,16 +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. - diff --git a/HdmiCec_2/CMakeLists.txt b/HdmiCec_2/CMakeLists.txt deleted file mode 100644 index 15a33ef0..00000000 --- a/HdmiCec_2/CMakeLists.txt +++ /dev/null @@ -1,51 +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 HdmiCec_2) -set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) - -set(PLUGIN_HDMICEC2_STARTUPORDER "" CACHE STRING "To configure startup order of HdmiCec_2 plugin") -set(PLUGIN_HDMICEC2_AUTOSTART false CACHE STRING "To automatically start HdmiCec_2 plugin.") -set_source_files_properties(HdmiCec_2.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") - -find_package(${NAMESPACE}Plugins REQUIRED) - -add_library(${MODULE_NAME} SHARED - HdmiCec_2.cpp - Module.cpp) - -set_target_properties(${MODULE_NAME} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES) - -find_package(DS) -find_package(IARMBus) -find_package(CEC) - -target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) -target_include_directories(${MODULE_NAME} PRIVATE ${CEC_INCLUDE_DIRS}) -target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) - -target_link_libraries(${MODULE_NAME} 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) -endif () - -install(TARGETS ${MODULE_NAME} - DESTINATION lib/${STORAGE_DIRECTORY}/plugins) - -write_config(${PLUGIN_NAME}) diff --git a/HdmiCec_2/HdmiCec_2.conf.in b/HdmiCec_2/HdmiCec_2.conf.in deleted file mode 100644 index 3195f1ff..00000000 --- a/HdmiCec_2/HdmiCec_2.conf.in +++ /dev/null @@ -1,5 +0,0 @@ -precondition = ["Platform"] -callsign = "org.rdk.HdmiCec_2" -autostart = "false" -autostart = "@PLUGIN_HDMICEC2_AUTOSTART@" -startuporder = "@PLUGIN_HDMICEC2_STARTUPORDER@" diff --git a/HdmiCec_2/HdmiCec_2.config b/HdmiCec_2/HdmiCec_2.config deleted file mode 100644 index df918d0c..00000000 --- a/HdmiCec_2/HdmiCec_2.config +++ /dev/null @@ -1,7 +0,0 @@ -set (autostart ${PLUGIN_HDMICEC2_AUTOSTART}) -set (preconditions Platform) -set (callsign "org.rdk.HdmiCec_2") - -if(PLUGIN_HDMICEC2_STARTUPORDER) -set (startuporder ${PLUGIN_HDMICEC2_STARTUPORDER}) -endif() diff --git a/HdmiCec_2/HdmiCec_2.cpp b/HdmiCec_2/HdmiCec_2.cpp deleted file mode 100644 index ebf6728d..00000000 --- a/HdmiCec_2/HdmiCec_2.cpp +++ /dev/null @@ -1,1777 +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 "HdmiCec_2.h" - - -#include "ccec/Connection.hpp" -#include "ccec/CECFrame.hpp" -#include "ccec/MessageEncoder.hpp" -#include "host.hpp" -#include "ccec/host/RDK.hpp" - - -#include "ccec/drivers/iarmbus/CecIARMBusMgr.h" - -#include "dsMgr.h" -#include "dsDisplay.h" -#include "videoOutputPort.hpp" -#include "manager.hpp" -#include "websocket/URL.h" - -#include "UtilsIarm.h" -#include "UtilsJsonRpc.h" -#include "UtilssyncPersistFile.h" - -#define HDMICEC2_METHOD_SET_ENABLED "setEnabled" -#define HDMICEC2_METHOD_GET_ENABLED "getEnabled" -#define HDMICEC2_METHOD_OTP_SET_ENABLED "setOTPEnabled" -#define HDMICEC2_METHOD_OTP_GET_ENABLED "getOTPEnabled" -#define HDMICEC2_METHOD_SET_OSD_NAME "setOSDName" -#define HDMICEC2_METHOD_GET_OSD_NAME "getOSDName" -#define HDMICEC2_METHOD_SET_VENDOR_ID "setVendorId" -#define HDMICEC2_METHOD_GET_VENDOR_ID "getVendorId" -#define HDMICEC2_METHOD_PERFORM_OTP_ACTION "performOTPAction" -#define HDMICEC2_METHOD_SEND_STANDBY_MESSAGE "sendStandbyMessage" -#define HDMICEC2_METHOD_GET_ACTIVE_SOURCE_STATUS "getActiveSourceStatus" -#define HDMICEC2_METHOD_SEND_KEY_PRESS "sendKeyPressEvent" -#define HDMICEC_EVENT_ON_DEVICES_CHANGED "onDevicesChanged" -#define HDMICEC_EVENT_ON_HDMI_HOT_PLUG "onHdmiHotPlug" -#define HDMICEC_EVENT_ON_STANDBY_MSG_RECEIVED "standbyMessageReceived" -#define DEV_TYPE_TUNER 1 -#define HDMI_HOT_PLUG_EVENT_CONNECTED 0 -#define ABORT_REASON_ID 5 - -#define API_VERSION_NUMBER_MAJOR 1 -#define API_VERSION_NUMBER_MINOR 0 -#define API_VERSION_NUMBER_PATCH 12 - -enum { - HDMICEC2_EVENT_DEVICE_ADDED=0, - HDMICEC2_EVENT_DEVICE_REMOVED, - HDMICEC2_EVENT_DEVICE_INFO_UPDATED, - HDMICEC2_EVENT_ACTIVE_SOURCE_STATUS_UPDATED, -}; - -static const char *eventString[] = { - "onDeviceAdded", - "onDeviceRemoved", - "onDeviceInfoUpdated", - "onActiveSourceStatusUpdated" -}; - -#define CEC_SETTING_ENABLED_FILE "/opt/persistent/ds/cecData_2.json" -#define CEC_SETTING_ENABLED "cecEnabled" -#define CEC_SETTING_OTP_ENABLED "cecOTPEnabled" -#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 OSDName osdName = "TV Box"; -static int32_t powerState = 1; -static PowerStatus tvPowerState = 1; -static bool isDeviceActiveSource = false; -static bool isLGTvConnected = false; - -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(HdmiCec_2, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - - HdmiCec_2* HdmiCec_2::_instance = nullptr; - static int libcecInitStatus = 0; - -//=========================================== HdmiCec_2FrameListener ========================================= - void HdmiCec_2FrameListener::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); - } - -//=========================================== HdmiCec_2Processor ========================================= - void HdmiCec_2Processor::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(msg.physicalAddress.toString() == physical_addr.toString()) - isDeviceActiveSource = true; - else - isDeviceActiveSource = false; - LOGINFO("ActiveSource isDeviceActiveSource status :%d \n", isDeviceActiveSource); - HdmiCec_2::_instance->sendActiveSourceEvent(); - HdmiCec_2::_instance->addDevice(header.from.toInt()); - } - void HdmiCec_2Processor::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()); - } - void HdmiCec_2Processor::process (const ImageViewOn &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ImageViewOn \n"); - HdmiCec_2::_instance->addDevice(header.from.toInt()); - } - void HdmiCec_2Processor::process (const TextViewOn &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: TextViewOn\n"); - HdmiCec_2::_instance->addDevice(header.from.toInt()); - } - void HdmiCec_2Processor::process (const RequestActiveSource &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RequestActiveSource\n"); - if(isDeviceActiveSource) - { - LOGINFO("sending ActiveSource\n"); - try - { - conn.sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(ActiveSource(physical_addr))); - } - catch(...) - { - LOGWARN("Exception while sending ActiveSource"); - } - } - } - void HdmiCec_2Processor::process (const Standby &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Standby from %s\n", header.from.toString().c_str()); - HdmiCec_2::_instance->SendStandbyMsgEvent(header.from.toInt()); - - } - void HdmiCec_2Processor::process (const GetCECVersion &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GetCECVersion sending CECVersion response \n"); - try - { - conn.sendTo(header.from, MessageEncoder().encode(CECVersion(Version::V_1_4))); - } - catch(...) - { - LOGWARN("Exception while sending CECVersion "); - } - } - void HdmiCec_2Processor::process (const CECVersion &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); - HdmiCec_2::_instance->addDevice(header.from.toInt()); - } - void HdmiCec_2Processor::process (const SetMenuLanguage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); - } - void HdmiCec_2Processor::process (const GiveOSDName &msg, const Header &header) - { - printHeader(header); - if (!(header.from == LogicalAddress(LogicalAddress::UNREGISTERED))) - { - LOGINFO("Command: GiveOSDName sending SetOSDName : %s\n",osdName.toString().c_str()); - try - { - conn.sendTo(header.from, MessageEncoder().encode(SetOSDName(osdName))); - } - catch(...) - { - LOGWARN("Exception while sending SetOSDName"); - } - } - } - void HdmiCec_2Processor::process (const GivePhysicalAddress &msg, const Header &header) - { - LOGINFO("Command: GivePhysicalAddress\n"); - 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()))); - } - catch(...) - { - LOGWARN("Exception while sending ReportPhysicalAddress "); - } - } - void HdmiCec_2Processor::process (const GiveDeviceVendorID &msg, const Header &header) - { - printHeader(header); - try - { - LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n",(isLGTvConnected)?lgVendorId.toString().c_str():appVendorId.toString().c_str()); - if(isLGTvConnected) - conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(lgVendorId))); - else - conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); - } - catch(...) - { - LOGWARN("Exception while sending DeviceVendorID"); - } - - } - void HdmiCec_2Processor::process (const SetOSDString &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetOSDString OSDString : %s\n",msg.osdString.toString().c_str()); - } - void HdmiCec_2Processor::process (const SetOSDName &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetOSDName OSDName : %s\n",msg.osdName.toString().c_str()); - if (HdmiCec_2::_instance) { - bool isOSDNameUpdated = HdmiCec_2::_instance->deviceList[header.from.toInt()].update(msg.osdName); - if (isOSDNameUpdated) - HdmiCec_2::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } else { - LOGWARN("Exception HdmiCec_2::_instance NULL"); - } - } - void HdmiCec_2Processor::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()); - if(msg.to.toString() == physical_addr.toString()) - isDeviceActiveSource = true; - else - isDeviceActiveSource = false; - LOGINFO("physical_addr : %s isDeviceActiveSource :%d \n",physical_addr.toString().c_str(),isDeviceActiveSource); - HdmiCec_2::_instance->sendActiveSourceEvent(); - } - void HdmiCec_2Processor::process (const RoutingInformation &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RoutingInformation Routing Information to Sink : %s\n",msg.toSink.toString().c_str()); - if(msg.toSink.toString() == physical_addr.toString()) - isDeviceActiveSource = true; - else - isDeviceActiveSource = false; - LOGINFO("physical_addr : %s isDeviceActiveSource :%d \n",physical_addr.toString().c_str(),isDeviceActiveSource); - HdmiCec_2::_instance->sendActiveSourceEvent(); - } - void HdmiCec_2Processor::process (const SetStreamPath &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetStreamPath Set Stream Path to Sink : %s\n",msg.toSink.toString().c_str()); - if(msg.toSink.toString() == physical_addr.toString()) - isDeviceActiveSource = true; - else - isDeviceActiveSource = false; - LOGINFO("physical_addr : %s isDeviceActiveSource :%d \n",physical_addr.toString().c_str(),isDeviceActiveSource); - HdmiCec_2::_instance->sendActiveSourceEvent(); - - } - void HdmiCec_2Processor::process (const GetMenuLanguage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GetMenuLanguage\n"); - } - void HdmiCec_2Processor::process (const ReportPhysicalAddress &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ReportPhysicalAddress\n"); - HdmiCec_2::_instance->addDevice(header.from.toInt()); - } - void HdmiCec_2Processor::process (const DeviceVendorID &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: DeviceVendorID VendorID : %s\n",msg.vendorId.toString().c_str()); - if (HdmiCec_2::_instance){ - bool isVendorIdUpdated = HdmiCec_2::_instance->deviceList[header.from.toInt()].update(msg.vendorId); - if (isVendorIdUpdated) - HdmiCec_2::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - else { - LOGWARN("Exception HdmiCec_2::_instance NULL"); - } - - } - void HdmiCec_2Processor::process (const GiveDevicePowerStatus &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveDevicePowerStatus sending powerState :%d \n",powerState); - try - { - conn.sendTo(header.from, MessageEncoder().encode(ReportPowerStatus(PowerStatus(powerState)))); - } - catch(...) - { - LOGWARN("Exception while sending ReportPowerStatus"); - } - } - void HdmiCec_2Processor::process (const ReportPowerStatus &msg, const Header &header) - { - printHeader(header); - if ((header.from == LogicalAddress(LogicalAddress::TV))) - tvPowerState = msg.status; - LOGINFO("Command: ReportPowerStatus TV Power Status from:%s status : %s \n",header.from.toString().c_str(),msg.status.toString().c_str()); - HdmiCec_2::_instance->addDevice(header.from.toInt()); - } - void HdmiCec_2Processor::process (const FeatureAbort &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: FeatureAbort\n"); - } - void HdmiCec_2Processor::process (const Abort &msg, const Header &header) - { - printHeader(header); - if (!(header.from == LogicalAddress(LogicalAddress::BROADCAST))) - { - LOGINFO("Command: Abort, sending FeatureAbort"); - try - { - conn.sendTo(header.from, MessageEncoder().encode(FeatureAbort(OpCode(msg.opCode()),AbortReason(ABORT_REASON_ID)))); - } - catch(...) - { - LOGWARN("Exception while sending FeatureAbort command"); - } - - } - LOGINFO("Command: Abort\n"); - } - void HdmiCec_2Processor::process (const Polling &msg, const Header &header) { - printHeader(header); - LOGINFO("Command: Polling\n"); - } - - -//=========================================== HdmiCec_2 ========================================= - - HdmiCec_2::HdmiCec_2() - : PluginHost::JSONRPC(),cecEnableStatus(false),smConnection(nullptr), m_sendKeyEventThreadRun(false) - , _pwrMgrNotification(*this) - , _registeredEventHandlers(false) - { - LOGWARN("ctor"); - smConnection = NULL; - cecEnableStatus = false; - IsCecMgrActivated = false; - Register(HDMICEC2_METHOD_SET_ENABLED, &HdmiCec_2::setEnabledWrapper, this); - Register(HDMICEC2_METHOD_GET_ENABLED, &HdmiCec_2::getEnabledWrapper, this); - Register(HDMICEC2_METHOD_OTP_SET_ENABLED, &HdmiCec_2::setOTPEnabledWrapper, this); - Register(HDMICEC2_METHOD_OTP_GET_ENABLED, &HdmiCec_2::getOTPEnabledWrapper, this); - Register(HDMICEC2_METHOD_SET_OSD_NAME, &HdmiCec_2::setOSDNameWrapper, this); - Register(HDMICEC2_METHOD_GET_OSD_NAME, &HdmiCec_2::getOSDNameWrapper, this); - Register(HDMICEC2_METHOD_SET_VENDOR_ID, &HdmiCec_2::setVendorIdWrapper, this); - Register(HDMICEC2_METHOD_GET_VENDOR_ID, &HdmiCec_2::getVendorIdWrapper, this); - Register(HDMICEC2_METHOD_PERFORM_OTP_ACTION, &HdmiCec_2::performOTPActionWrapper, this); - Register(HDMICEC2_METHOD_SEND_STANDBY_MESSAGE, &HdmiCec_2::sendStandbyMessageWrapper, this); - Register(HDMICEC2_METHOD_GET_ACTIVE_SOURCE_STATUS, &HdmiCec_2::getActiveSourceStatus, this); - Register(HDMICEC2_METHOD_SEND_KEY_PRESS,&HdmiCec_2::sendRemoteKeyPressWrapper,this); - Register("getDeviceList", &HdmiCec_2::getDeviceList, this); - } - - HdmiCec_2::~HdmiCec_2() - { - IsCecMgrActivated = false; - LOGWARN("dtor"); - } - - const string HdmiCec_2::Initialize(PluginHost::IShell* service) - { - LOGWARN("Initlaizing CEC_2"); - string msg; - HdmiCec_2::_instance = this; - smConnection = NULL; - IsCecMgrActivated = false; - uint32_t res = Core::ERROR_GENERAL; - PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - if (Utils::IARM::init()) { - - - //Initialize cecEnableStatus to false in ctor - cecEnableStatus = false; - - logicalAddressDeviceType = "None"; - logicalAddress = 0xFF; - - char c; - IARM_Result_t retVal = IARM_RESULT_SUCCESS; - retVal = IARM_Bus_Call_with_IPCTimeout(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_API_isAvailable, (void *)&c, sizeof(c), 1000); - if(retVal != IARM_RESULT_SUCCESS) { - msg = "IARM_BUS_CECMGR is not available"; - LOGINFO("CECMGR is not available. Failed to activate HdmiCec_2 Plugin"); - return msg; - } else { - LOGINFO("CECMGR is available. Activate HdmiCec_2 Plugin. IsCecMgrActivated: %d", IsCecMgrActivated); - IsCecMgrActivated = true; - } - - //CEC plugin functionalities will only work if CECmgr is available. If plugin Initialize failure upper layer will call dtor directly. - InitializeIARM(); - InitializePowerManager(service); - - // load persistence setting - loadSettings(); - - try - { - //TODO(MROLLINS) this is probably per process so we either need to be running in our own process or be carefull no other plugin is calling it - device::Manager::Initialize(); - std::string strVideoPort = device::Host::getInstance().getDefaultVideoPortName(); - device::VideoOutputPort vPort = device::Host::getInstance().getVideoOutputPort(strVideoPort.c_str()); - if (vPort.isDisplayConnected()) - { - std::vector edidVec; - vPort.getDisplay().getEDIDBytes(edidVec); - //Set LG vendor id if connected with LG TV - if(edidVec.at(8) == 0x1E && edidVec.at(9) == 0x6D) - { - isLGTvConnected = true; - } - LOGINFO("manufacturer byte from edid :%x: %x isLGTvConnected :%d",edidVec.at(8),edidVec.at(9),isLGTvConnected); - } - } - catch(...) - { - LOGWARN("Exception in getting edid info .\r\n"); - } - - // get power state: - ASSERT (_powerManagerPlugin); - if (_powerManagerPlugin){ - res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); - if (Core::ERROR_NONE == res) - { - powerState = (pwrStateCur == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON)?0:1 ; - LOGINFO("Current state is PowerManagerPlugin: (%d) powerState :%d \n",pwrStateCur,powerState); - } - } - - if (cecSettingEnabled) - { - try - { - CECEnable(); - } - catch(...) - { - LOGWARN("Exception while enabling CEC settings .\r\n"); - } - } - } else { - msg = "IARM bus is not available"; - LOGERR("IARM bus is not available. Failed to activate HdmiCec_2 Plugin"); - } - - // On success return empty, to indicate there is no error text. - return msg; - } - - uint32_t HdmiCec_2::getActiveSourceStatus(const JsonObject& parameters, JsonObject& response) - { - response["status"] = isDeviceActiveSource; - returnResponse(true); - } - - void HdmiCec_2::Deinitialize(PluginHost::IShell* /* service */) - { - LOGWARN("Deinitialize CEC_2"); - if(_powerManagerPlugin) - { - _powerManagerPlugin.Reset(); - } - _registeredEventHandlers = false; - if(true == getEnabled()) - { - setEnabled(false,false); - } - isDeviceActiveSource = false; - HdmiCec_2::_instance->sendActiveSourceEvent(); - HdmiCec_2::_instance = nullptr; - smConnection = NULL; - - DeinitializeIARM(); - } - - void HdmiCec_2::registerEventHandlers() - { - ASSERT (_powerManagerPlugin); - - if(!_registeredEventHandlers && _powerManagerPlugin) { - _registeredEventHandlers = true; - _powerManagerPlugin->Register(&_pwrMgrNotification); - } - } - - void HdmiCec_2::InitializePowerManager(PluginHost::IShell* service) - { - LOGINFO("Connect the COM-RPC socket\n"); - _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) - .withIShell(service) - .createInterface(); - registerEventHandlers(); - } - - - void HdmiCec_2::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 HdmiCec_2::sendKeyReleaseEvent(const int logicalAddress) - { - LOGINFO(" sendKeyReleaseEvent logicalAddress 0x%x \n",logicalAddress); - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); - - } - void HdmiCec_2::SendStandbyMsgEvent(const int logicalAddress) - { - JsonObject params; - params["logicalAddress"] = JsonValue(logicalAddress); - sendNotify(HDMICEC_EVENT_ON_STANDBY_MSG_RECEIVED, params); - } - uint32_t HdmiCec_2::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); - 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:%d \n",(int)m_SendKeyQueue.size()); - returnResponse(true); - } - - uint32_t HdmiCec_2::sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response) - { - if(sendStandbyMessage()) - { - returnResponse(true); - } - else - { - returnResponse(false); - } - } - - bool HdmiCec_2::sendStandbyMessage() - { - bool ret = false; - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return ret; - } - if(true == cecEnableStatus) - { - if (smConnection){ - try - { - smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(Standby())); - ret = true; - } - catch(...) - { - LOGWARN("Exception while sending CEC StandBy Message"); - } - } - else { - LOGWARN("smConnection is NULL"); - } - } - else - LOGWARN("cecEnableStatus=false"); - return ret; - } - - - const void HdmiCec_2::InitializeIARM() - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED,cecMgrEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_STATUS_UPDATED,cecMgrEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, dsHdmiEventHandler) ); - } - - void HdmiCec_2::DeinitializeIARM() - { - if (Utils::IARM::isConnected()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED, cecMgrEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_STATUS_UPDATED, cecMgrEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, dsHdmiEventHandler) ); - } - } - - void HdmiCec_2::cecMgrEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiCec_2::_instance) - return; - - if( !strcmp(owner, IARM_BUS_CECMGR_NAME)) - { - switch (eventId) - { - case IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED: - { - HdmiCec_2::_instance->onCECDaemonInit(); - } - break; - case IARM_BUS_CECMGR_EVENT_STATUS_UPDATED: - { - IARM_Bus_CECMgr_Status_Updated_Param_t *evtData = new IARM_Bus_CECMgr_Status_Updated_Param_t; - if(evtData) - { - memcpy(evtData,data,sizeof(IARM_Bus_CECMgr_Status_Updated_Param_t)); - HdmiCec_2::_instance->cecStatusUpdated(evtData); - } - } - break; - default: - /*Do nothing*/ - break; - } - } - } - - void HdmiCec_2::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiCec_2::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_hotplug_event = eventData->data.hdmi_hpd.event; - LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG event data:%d \r\n", hdmi_hotplug_event); - HdmiCec_2::_instance->onHdmiHotPlug(hdmi_hotplug_event); - //Trigger CEC device poll here - pthread_cond_signal(&(_instance->m_condSig)); - } - } - - void HdmiCec_2::onPowerModeChanged(const PowerState ¤tState, const PowerState &newState) - { - if(!HdmiCec_2::_instance) - return; - - LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", - currentState, newState); - if (WPEFramework::Exchange::IPowerManager::POWER_STATE_ON == newState) - { - powerState = 0; - } - else - powerState = 1; - - } - - void HdmiCec_2::onCECDaemonInit() - { - if(true == getEnabled()) - { - LOGINFO("%s %d. Calling setEnabled false", __func__, __LINE__); - setEnabled(false,false); - LOGINFO("%s %d. Calling setEnabled true", __func__, __LINE__); - setEnabled(true,false); - } - else - { - /*Do nothing as CEC is not already enabled*/ - } - } - - void HdmiCec_2::cecStatusUpdated(void *evtStatus) - { - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return; - } - IARM_Bus_CECMgr_Status_Updated_Param_t *evtData = (IARM_Bus_CECMgr_Status_Updated_Param_t *)evtStatus; - if(evtData) - { - try{ - getPhysicalAddress(); - - int logicalAddr = evtData->logicalAddress; - std::string logicalAddrDeviceType = DeviceType(LogicalAddress(evtData->logicalAddress).getType()).toString().c_str(); - - LOGINFO("cecLogicalAddressUpdated: logical address updated: %d , saved : %d ", logicalAddr, logicalAddress.toInt()); - if (logicalAddr != logicalAddress.toInt() || logicalAddrDeviceType != logicalAddressDeviceType) - { - logicalAddress = logicalAddr; - logicalAddressDeviceType = logicalAddrDeviceType; - } - } - catch (const std::exception& e) - { - LOGWARN("CEC exception caught from cecStatusUpdated"); - } - - delete evtData; - } - return; - } - - void HdmiCec_2::sendActiveSourceEvent() - { - JsonObject params; - params["status"] = isDeviceActiveSource; - LOGWARN(" sendActiveSourceEvent isDeviceActiveSource: %d ",isDeviceActiveSource); - sendNotify(eventString[HDMICEC2_EVENT_ACTIVE_SOURCE_STATUS_UPDATED], params); - } - - void HdmiCec_2::onHdmiHotPlug(int connectStatus) - { - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return; - } - if (HDMI_HOT_PLUG_EVENT_CONNECTED == connectStatus) - { - LOGINFO ("onHdmiHotPlug Status : %d ", connectStatus); - getPhysicalAddress(); - getLogicalAddress(); - try - { - std::string strVideoPort = device::Host::getInstance().getDefaultVideoPortName(); - device::VideoOutputPort vPort = device::Host::getInstance().getVideoOutputPort(strVideoPort.c_str()); - if (vPort.isDisplayConnected()) - { - std::vector edidVec; - vPort.getDisplay().getEDIDBytes(edidVec); - //Set LG vendor id if connected with LG TV - if(edidVec.at(8) == 0x1E && edidVec.at(9) == 0x6D) - { - isLGTvConnected = true; - } - LOGINFO("manufacturer byte from edid :%x: %x isLGTvConnected :%d",edidVec.at(8),edidVec.at(9),isLGTvConnected); - } - } - catch(...) - { - LOGWARN("Exception in getting edid info .\r\n"); - } - if(smConnection) - { - try - { - LOGINFO(" sending ReportPhysicalAddress response physical_addr :%s logicalAddress :%x \n",physical_addr.toString().c_str(), logicalAddress.toInt()); - smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ReportPhysicalAddress(physical_addr,logicalAddress.toInt()))); - - LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n", \ - (isLGTvConnected)?lgVendorId.toString().c_str():appVendorId.toString().c_str()); - if(isLGTvConnected) - smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(lgVendorId))); - else - smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); - } - catch(...) - { - LOGWARN("Exception while sending Messages onHdmiHotPlug\n"); - } - } - } - return; - } - - uint32_t HdmiCec_2::setEnabledWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - bool enabled = false; - - if (parameters.HasLabel("enabled")) - { - getBoolParameter("enabled", enabled); - } - else - { - returnResponse(false); - } - - setEnabled(enabled,true); - returnResponse(true); - } - - uint32_t HdmiCec_2::getEnabledWrapper(const JsonObject& parameters, JsonObject& response) - { - response["enabled"] = getEnabled(); - returnResponse(true); - } - uint32_t HdmiCec_2::setOTPEnabledWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - bool enabled = false; - - if (parameters.HasLabel("enabled")) - { - getBoolParameter("enabled", enabled); - } - else - { - returnResponse(false); - } - - setOTPEnabled(enabled); - returnResponse(true); - } - - uint32_t HdmiCec_2::getOTPEnabledWrapper(const JsonObject& parameters, JsonObject& response) - { - response["enabled"] = getOTPEnabled(); - returnResponse(true); - } - - uint32_t HdmiCec_2::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 - { - returnResponse(false); - } - returnResponse(true); - } - - uint32_t HdmiCec_2::getOSDNameWrapper(const JsonObject& parameters, JsonObject& response) - { - response["name"] = osdName.toString(); - LOGINFO("getOSDNameWrapper osdName : %s \n",osdName.toString().c_str()); - returnResponse(true); - } - - uint32_t HdmiCec_2::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 HdmiCec_2::getVendorIdWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFO("getVendorIdWrapper appVendorId : %s \n",appVendorId.toString().c_str()); - response["vendorid"] = appVendorId.toString() ; - returnResponse(true); - } - - - uint32_t HdmiCec_2::performOTPActionWrapper(const JsonObject& parameters, JsonObject& response) - { - if(performOTPAction()) - { - returnResponse(true); - } - else - { - returnResponse(false); - } - } - - bool HdmiCec_2::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_OTP_ENABLED 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_OTP_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 HdmiCec_2::setEnabled(bool enabled, bool isPersist) - { - LOGINFO("Entered setEnabled "); - - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return; - } else { - LOGWARN("CEC Mgr activated. proceeding with %s", __func__); - } - if (isPersist && (cecSettingEnabled != enabled)) - { - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_ENABLED, JsonValue(enabled)); - cecSettingEnabled = enabled; - } - if(true == enabled) - { - CECEnable(); - } - else - { - CECDisable(); - } - return; - } - - void HdmiCec_2::setOTPEnabled(bool enabled) - { - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return; - } - if (cecOTPSettingEnabled != enabled) - { - LOGINFO("persist setOTPEnabled "); - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_OTP_ENABLED, JsonValue(enabled)); - cecOTPSettingEnabled = enabled; - } - return; - } - - void HdmiCec_2::CECEnable(void) - { - LOGINFO("Entered CECEnable"); - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return; - } - if (cecEnableStatus) - { - LOGWARN("CEC Already Enabled"); - return; - } - - if(0 == libcecInitStatus) - { - try - { - LibCCEC::getInstance().init(); - } - catch (const std::exception& e) - { - LOGWARN("CEC exception caught from LibCCEC::getInstance().init()"); - } - } - libcecInitStatus++; - - m_sendKeyEventThreadExit = false; - try { - if (m_sendKeyEventThread.get().joinable()) { - m_sendKeyEventThread.get().join(); - } - m_sendKeyEventThread = Utils::ThreadRAII(std::thread(threadSendKeyEvent)); - } catch(const std::system_error& e) { - LOGERR("exception in creating threadSendKeyEvent %s", e.what()); - } - - - //Acquire CEC Addresses - getPhysicalAddress(); - getLogicalAddress(); - - smConnection = new Connection(logicalAddress.toInt(),false,"ServiceManager::Connection::"); - smConnection->open(); - msgProcessor = new HdmiCec_2Processor(*smConnection); - msgFrameListener = new HdmiCec_2FrameListener(*msgProcessor); - smConnection->addFrameListener(msgFrameListener); - - cecEnableStatus = true; - - if(smConnection) - { - 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())); - isDeviceActiveSource = false; - LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n", \ - (isLGTvConnected)?lgVendorId.toString().c_str():appVendorId.toString().c_str()); - if(isLGTvConnected) - smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(lgVendorId))); - else - smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); - - LOGWARN("Start Update thread %p", smConnection ); - m_updateThreadExit = false; - _instance->m_lockUpdate = PTHREAD_MUTEX_INITIALIZER; - _instance->m_condSigUpdate = PTHREAD_COND_INITIALIZER; - try { - if (m_UpdateThread.get().joinable()) { - m_UpdateThread.get().join(); - } - m_UpdateThread = Utils::ThreadRAII(std::thread(threadUpdateCheck)); - } catch(const std::system_error& e) { - LOGERR("exception in creating threadUpdateCheck %s", e.what()); - } - - LOGWARN("Start Thread %p", smConnection ); - m_pollThreadExit = false; - _instance->m_numberOfDevices = 0; - _instance->m_lock = PTHREAD_MUTEX_INITIALIZER; - _instance->m_condSig = PTHREAD_COND_INITIALIZER; - try { - if (m_pollThread.get().joinable()) { - m_pollThread.get().join(); - } - m_pollThread = Utils::ThreadRAII(std::thread(threadRun)); - } catch(const std::system_error& e) { - LOGERR("exception in creating threadRun %s", e.what()); - } - - } - return; - } - - void HdmiCec_2::CECDisable(void) - { - LOGINFO("Entered CECDisable "); - - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return; - } else { - LOGWARN("CEC Mgr activated. proceeding with %s", __func__); - } - if(!cecEnableStatus) - { - LOGWARN("CEC Already Disabled "); - return; - } - - { - m_sendKeyEventThreadExit = true; - std::unique_lock lk(m_sendKeyEventMutex); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - } - try - { - if (m_sendKeyEventThread.get().joinable()) - m_sendKeyEventThread.get().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()); - } - - if (smConnection != NULL) - { - LOGWARN("Stop Thread %p", smConnection ); - - m_updateThreadExit = true; - //Trigger codition to exit poll loop - pthread_mutex_lock(&(_instance->m_lockUpdate)); //Join mutex lock to wait until thread is in its wait condition - pthread_cond_signal(&(_instance->m_condSigUpdate)); - pthread_mutex_unlock(&(_instance->m_lockUpdate)); - if (m_UpdateThread.get().joinable()) {//Join thread to make sure it's deleted before moving on. - m_UpdateThread.get().join(); - } - LOGWARN("Deleted update Thread %p", smConnection ); - - m_pollThreadExit = true; - //Trigger codition to exit poll loop - pthread_mutex_lock(&(_instance->m_lock)); //Join mutex lock to wait until thread is in its wait condition - pthread_cond_signal(&(_instance->m_condSig)); - pthread_mutex_unlock(&(_instance->m_lock)); - if (m_pollThread.get().joinable()) {//Join thread to make sure it's deleted before moving on. - m_pollThread.get().join(); - } - LOGWARN("Deleted Thread %p", smConnection ); - //Clear cec device cache. - removeAllCecDevices(); - - smConnection->close(); - delete smConnection; - delete msgProcessor; - delete msgFrameListener; - msgProcessor = NULL; - msgFrameListener = NULL; - smConnection = NULL; - } - cecEnableStatus = false; - - if(1 == libcecInitStatus) - { - try - { - LibCCEC::getInstance().term(); - } - catch (const std::exception& e) - { - LOGWARN("CEC exception caught from LibCCEC::getInstance().term() "); - } - } - - libcecInitStatus--; - - return; - } - - - void HdmiCec_2::getPhysicalAddress() - { - LOGINFO("Entered getPhysicalAddress "); - - uint32_t physAddress = 0x0F0F0F0F; - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return; - } - - 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; - } - - void HdmiCec_2::getLogicalAddress() - { - LOGINFO("Entered getLogicalAddress "); - - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return; - } - try{ - LogicalAddress addr = LibCCEC::getInstance().getLogicalAddress(DEV_TYPE_TUNER); - - std::string logicalAddrDeviceType = DeviceType(LogicalAddress(addr).getType()).toString().c_str(); - - LOGINFO("logical address obtained is %d , saved logical address is %d ", addr.toInt(), logicalAddress.toInt()); - - if (logicalAddress.toInt() != addr.toInt() || logicalAddressDeviceType != logicalAddrDeviceType) - - { - logicalAddress = addr; - logicalAddressDeviceType = logicalAddrDeviceType; - } - } - catch (const std::exception& e) - { - LOGWARN("CEC exception caught from getLogicalAddress "); - } - return; - } - - bool HdmiCec_2::getEnabled() - { - LOGINFO("getEnabled :%d ",cecEnableStatus); - return cecEnableStatus; - } - - bool HdmiCec_2::getOTPEnabled() - { - if(true == cecOTPSettingEnabled) - return true; - else - return false; - LOGINFO("getOTPEnabled :%d ",cecOTPSettingEnabled); - } - - bool HdmiCec_2::performOTPAction() - { - LOGINFO("performOTPAction "); - bool ret = false; - if (!IsCecMgrActivated) { - LOGWARN("CEC Mgr not activated CEC communication is not possible"); - return ret; - } - if((true == cecEnableStatus) && (cecOTPSettingEnabled == true)) - { - if (smConnection) { - try - { - LOGINFO("Command: sending ImageViewOn TV \r\n"); - smConnection->sendTo(LogicalAddress::TV, MessageEncoder().encode(ImageViewOn())); - usleep(10000); - LOGINFO("Command: sending ActiveSource physical_addr :%s \r\n",physical_addr.toString().c_str()); - smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(ActiveSource(physical_addr))); - usleep(10000); - isDeviceActiveSource = true; - LOGINFO("Command: sending GiveDevicePowerStatus \r\n"); - smConnection->sendTo(LogicalAddress::TV, MessageEncoder().encode(GiveDevicePowerStatus())); - ret = true; - } - catch(...) - { - LOGWARN("Exception while processing performOTPAction"); - } - } - else { - LOGWARN("smConnection is NULL"); - } - } - else - LOGWARN("cecEnableStatus=false"); - return ret; - } - - uint32_t HdmiCec_2::getDeviceList (const JsonObject& parameters, JsonObject& response) - { //sample servicemanager response: - LOGINFOMETHOD(); - //Trigger CEC device poll here - pthread_cond_signal(&(_instance->m_condSig)); - - bool success = true; - response["numberofdevices"] = HdmiCec_2::_instance->m_numberOfDevices; - LOGINFO("getDeviceListWrapper m_numberOfDevices :%d \n", HdmiCec_2::_instance->m_numberOfDevices); - JsonArray deviceListArg; - try - { - int i = 0; - for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { - if (BIT_CHECK(deviceList[i].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) { - JsonObject device; - device["logicalAddress"] = HdmiCec_2::_instance->deviceList[i].m_logicalAddress.toInt(); - device["osdName"] = HdmiCec_2::_instance->deviceList[i].m_osdName.toString().c_str(); - device["vendorID"] = HdmiCec_2::_instance->deviceList[i].m_vendorID.toString().c_str(); - deviceListArg.Add(device); - } - } - } - catch (...) - { - LOGERR("Exception in api"); - success = false; - } - response["deviceList"] = deviceListArg; - returnResponse(success); - } - - bool HdmiCec_2::pingDeviceUpdateList (int idev) - { - bool isConnected = false; - //self ping is not required - if (idev == logicalAddress.toInt()){ - return isConnected; - } - if(!HdmiCec_2::_instance) - { - LOGERR("HdmiCec_2::_instance not existing"); - return isConnected; - } - if ( !(_instance->smConnection) || logicalAddress.toInt() == LogicalAddress::UNREGISTERED || (false==cecEnableStatus)){ - LOGERR("Exiting from pingDeviceUpdateList _instance->smConnection:%p, logicalAddress:%d, cecEnableStatus=%d", - _instance->smConnection, logicalAddress.toInt(), cecEnableStatus); - return isConnected; - } - - LOGWARN("PING for 0x%x \r\n",idev); - try { - _instance->smConnection->ping(logicalAddress, LogicalAddress(idev), Throw_e()); - } - catch(CECNoAckException &e) - { - if (BIT_CHECK(_instance->deviceList[idev].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) { - LOGINFO("Device disconnected: %d \r\n",idev); - removeDevice (idev); - } else { - LOGINFO("Device is not connected: %d. Ping caught %s\r\n",idev, e.what()); - } - isConnected = false; - return isConnected;; - } - catch(IOException &e) - { - LOGINFO("Device is not reachable: %d. Ping caught %s\r\n",idev, e.what()); - isConnected = false; - return isConnected;; - } - catch(Exception &e) - { - LOGINFO("Ping caught %s \r\n",e.what()); - } - - /* If we get ACK, then the device is present in the network*/ - isConnected = true; - if ( !(BIT_CHECK(_instance->deviceList[idev].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) ) - { - LOGINFO("Device connected: %d \r\n",idev); - addDevice (idev); - } - return isConnected; - } - - void HdmiCec_2::sendDeviceUpdateInfo(const int logicalAddress) - { - JsonObject params; - params["logicalAddress"] = JsonValue(logicalAddress); - LOGINFO("Device info updated notification send: for logical address:%d\r\n", logicalAddress); - sendNotify(eventString[HDMICEC2_EVENT_DEVICE_INFO_UPDATED], params); - } - - void HdmiCec_2::addDevice(const int logicalAddress) { - - if(!HdmiCec_2::_instance) - return; - - if ( logicalAddress >= LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - if ( !(BIT_CHECK(HdmiCec_2::_instance->deviceList[logicalAddress].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) ) - { - BIT_SET(HdmiCec_2::_instance->deviceList[logicalAddress].m_deviceInfoStatus, BIT_DEVICE_PRESENT); - HdmiCec_2::_instance->deviceList[logicalAddress].m_logicalAddress = LogicalAddress(logicalAddress); - HdmiCec_2::_instance->m_numberOfDevices++; - LOGINFO("New cec ligical address add notification send: \r\n"); - sendNotify(eventString[HDMICEC2_EVENT_DEVICE_ADDED], JsonObject()); - } - //Two source devices can have same logical address. - requestCecDevDetails(logicalAddress); - } - - void HdmiCec_2::removeAllCecDevices() { - int i = 0; - for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { - removeDevice (i); - } - } - void HdmiCec_2::removeDevice(const int logicalAddress) { - if(!HdmiCec_2::_instance) - return; - - if ( logicalAddress >= LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - if (BIT_CHECK(HdmiCec_2::_instance->deviceList[logicalAddress].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) - { - _instance->m_numberOfDevices--; - _instance->deviceList[logicalAddress].clear(); - LOGINFO("Cec ligical address remove notification send: \r\n"); - sendNotify(eventString[HDMICEC2_EVENT_DEVICE_REMOVED], JsonObject()); - } - } - - void HdmiCec_2::sendUnencryptMsg(unsigned char* msg, int size) - { - LOGINFO("sendMessage "); - - if(true == cecEnableStatus) - { - std::vector buf; - buf.resize(size); - - int itr = 0; - for (itr= 0; itrsendAsync(frame); - } - else - LOGWARN("cecEnableStatus=false"); - return; - } - - void HdmiCec_2::requestVendorID(const int newDevlogicalAddress) - { - //Get OSD name and vendor ID only from connected devices. Since devices are identified using polling - //Once OSD name and Vendor ID is updated. We have to poll again in next iteration also. Just to check - //a new device is reconnected with same logical address - unsigned char msg [2]; - unsigned int logicalAddr = logicalAddress.toInt(); - unsigned char sender = (unsigned char)(logicalAddr & 0x0f); - unsigned char receiver = (unsigned char) (newDevlogicalAddress & 0x0f); - - msg [0] = (sender<<4)|receiver; - //Request vendor id - msg [1] = 0x8c; - LOGINFO("Sending msg request vendor id %x %x", msg [0], msg [1]); - _instance->sendUnencryptMsg (msg, sizeof(msg)); - - } - - void HdmiCec_2::requestOsdName(const int newDevlogicalAddress) - { - //Get OSD name and vendor ID only from connected devices. Since devices are identified using polling - //Once OSD name and Vendor ID is updated. We have to poll again in next iteration also. Just to check - //a new device is reconnected with same logical address - unsigned char msg [2]; - unsigned int logicalAddr = logicalAddress.toInt(); - unsigned char sender = (unsigned char)(logicalAddr & 0x0f); - unsigned char receiver = (unsigned char) (newDevlogicalAddress & 0x0f); - - msg [0] = (sender<<4)|receiver; - //Request OSD name - msg [1] = 0x46; - LOGINFO("Sending msg request osd name %x %x", msg [0], msg [1]); - _instance->sendUnencryptMsg (msg, sizeof(msg)); - - } - - void HdmiCec_2::requestCecDevDetails(const int newDevlogicalAddress) - { - //Get OSD name and vendor ID only from connected devices. Since devices are identified using polling - //Once OSD name and Vendor ID is updated. We have to poll again in next iteration also. Just to check - //a new device is reconnected with same logical address - requestVendorID (newDevlogicalAddress); - requestOsdName (newDevlogicalAddress); - } - - void HdmiCec_2::threadRun() - { - if(!HdmiCec_2::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO("Entering ThreadRun: _instance->m_pollThreadExit %d",_instance->m_pollThreadExit); - int i = 0; - pthread_mutex_lock(&(_instance->m_lock));//pthread_cond_wait should be mutex protected. //pthread_cond_wait will unlock the mutex and perfoms wait for the condition. - while (!_instance->m_pollThreadExit) { - bool isActivateUpdateThread = false; - LOGINFO("Starting cec device polling"); - for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { - bool isConnected = _instance->pingDeviceUpdateList(i); - if (isConnected){ - isActivateUpdateThread = isConnected; - } - - } - if (isActivateUpdateThread){ - //i any of devices is connected activate thread update check - pthread_cond_signal(&(_instance->m_condSigUpdate)); - } - //Wait for mutex signal here to continue the worker thread again. - pthread_cond_wait(&(_instance->m_condSig), &(_instance->m_lock)); - - } - pthread_mutex_unlock(&(_instance->m_lock)); - LOGINFO("%s: Thread exited", __FUNCTION__); - } - void HdmiCec_2::threadSendKeyEvent() - { - if(!HdmiCec_2::_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(); - - LOGINFO("sendRemoteKeyThread : logical addr:0x%x keyCode: 0x%x queue size :%d \n",keyInfo.logicalAddr,keyInfo.keyCode,(int)_instance->m_SendKeyQueue.size()); - _instance->sendKeyPressEvent(keyInfo.logicalAddr,keyInfo.keyCode); - _instance->sendKeyReleaseEvent(keyInfo.logicalAddr); - } - LOGINFO("%s: Thread exited", __FUNCTION__); - } - void HdmiCec_2::threadUpdateCheck() - { - if(!HdmiCec_2::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO("Entering ThreadUpdate: _instance->m_updateThreadExit %d",_instance->m_updateThreadExit); - int i = 0; - pthread_mutex_lock(&(_instance->m_lockUpdate));//pthread_cond_wait should be mutex protected. //pthread_cond_wait will unlock the mutex and perfoms wait for the condition. - while (!_instance->m_updateThreadExit) { - //Wait for mutex signal here to continue the worker thread again. - pthread_cond_wait(&(_instance->m_condSigUpdate), &(_instance->m_lockUpdate)); - - LOGINFO("Starting cec device update check"); - for(i=0; ((i< LogicalAddress::UNREGISTERED)&&(!_instance->m_updateThreadExit)); i++ ) { - //If details are not updated. update now. - if (BIT_CHECK(HdmiCec_2::_instance->deviceList[i].m_deviceInfoStatus, BIT_DEVICE_PRESENT)) - { - int itr = 0; - bool retry = true; - int iCounter = 0; - for (itr = 0; ((itr<5)&&(retry)); itr++){ - - if (!HdmiCec_2::_instance->deviceList[i].m_isOSDNameUpdated){ - iCounter = 0; - while ((!_instance->m_updateThreadExit) && (iCounter < (2*10))) { //sleep for 2sec. - usleep (100 * 1000); //sleep for 100 milli sec - iCounter ++; - } - - HdmiCec_2::_instance->requestOsdName (i); - retry = true; - } - else { - retry = false; - } - - if (!HdmiCec_2::_instance->deviceList[i].m_isVendorIDUpdated){ - iCounter = 0; - while ((!_instance->m_updateThreadExit) && (iCounter < (2*10))) { //sleep for 1sec. - usleep (100 * 1000); //sleep for 100 milli sec - iCounter ++; - } - - HdmiCec_2::_instance->requestVendorID (i); - retry = true; - } - } - if (retry){ - LOGINFO("cec device: %d update time out", i); - } - } - } - - } - pthread_mutex_unlock(&(_instance->m_lockUpdate)); - LOGINFO("%s: Thread exited", __FUNCTION__); - } - - } // namespace Plugin -} // namespace WPEFramework diff --git a/HdmiCec_2/HdmiCec_2.h b/HdmiCec_2/HdmiCec_2.h deleted file mode 100644 index 0882ae7f..00000000 --- a/HdmiCec_2/HdmiCec_2.h +++ /dev/null @@ -1,338 +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 -#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" -#include - -#undef Assert // this define from Connection.hpp conflicts with WPEFramework - -#include "Module.h" - -#include "UtilsBIT.h" -#include "UtilsThreadRAII.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 HdmiCec_2FrameListener : public FrameListener - { - public: - HdmiCec_2FrameListener(MessageProcessor &processor) : processor(processor) {} - void notify(const CECFrame &in) const; - ~HdmiCec_2FrameListener() {} - private: - MessageProcessor &processor; - }; - - class HdmiCec_2Processor : public MessageProcessor - { - public: - HdmiCec_2Processor(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); - 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()); - } - - }; - -#define BIT_DEVICE_PRESENT (0) - - class CECDeviceInfo_2 { - public: - - LogicalAddress m_logicalAddress; - VendorID m_vendorID; - OSDName m_osdName; - // - short m_deviceInfoStatus; - bool m_isOSDNameUpdated; - bool m_isVendorIDUpdated; - std::mutex m_; - std::condition_variable cv_; - std::unique_lock lk; - - CECDeviceInfo_2() - : m_logicalAddress(0),m_vendorID(0,0,0),m_osdName("NA"), m_isOSDNameUpdated (false), m_isVendorIDUpdated (false) - { - BITMASK_CLEAR(m_deviceInfoStatus, 0xFFFF); //Clear all bits - } - - void clear( ) - { - m_logicalAddress = 0; - m_vendorID = VendorID(0,0,0); - m_osdName = "NA"; - BITMASK_CLEAR(m_deviceInfoStatus, 0xFFFF); //Clear all bits - m_isOSDNameUpdated = false; - m_isVendorIDUpdated = false; - } - - bool update ( const VendorID &vendorId) { - bool isVendorIdUpdated = false; - if (!m_isVendorIDUpdated) - isVendorIdUpdated = true; //First time no need to cross check the value. Since actual value can be default value - else - isVendorIdUpdated = (m_vendorID.toString().compare(vendorId.toString())==0)?false:true; - - m_isVendorIDUpdated = true; - m_vendorID = vendorId; - return isVendorIdUpdated; - } - - bool update ( const OSDName &osdName ) { - bool isOSDNameUpdated = false; - if (!m_isOSDNameUpdated) - isOSDNameUpdated = true; //First time no need to cross check the value. Since actual value can be default value - else - isOSDNameUpdated = (m_osdName.toString().compare(osdName.toString())==0)?false:true; - - m_isOSDNameUpdated = true; - m_osdName = osdName; - return isOSDNameUpdated; - } - - }; - - // 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 HdmiCec_2 : public PluginHost::IPlugin, public PluginHost::JSONRPC { - 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: - HdmiCec_2(); - virtual ~HdmiCec_2(); - virtual const string Initialize(PluginHost::IShell* service) override; - virtual void Deinitialize(PluginHost::IShell* service) override; - virtual string Information() const override { return {}; } - void onPowerModeChanged(const PowerState ¤tState, const PowerState &newState); - void registerEventHandlers(); - static HdmiCec_2* _instance; - CECDeviceInfo_2 deviceList[16]; - pthread_cond_t m_condSig; - pthread_mutex_t m_lock; - pthread_cond_t m_condSigUpdate; - pthread_mutex_t m_lockUpdate; - - void SendStandbyMsgEvent(const int logicalAddress); - void sendActiveSourceEvent(); - void addDevice(const int logicalAddress); - void removeDevice(const int logicalAddress); - void sendUnencryptMsg(unsigned char* msg, int size); - void sendDeviceUpdateInfo(const int logicalAddress); - void sendKeyPressEvent(const int logicalAddress, int keyCode); - void sendKeyReleaseEvent(const int logicalAddress); - typedef struct sendKeyInfo - { - int logicalAddr; - int keyCode; - }SendKeyInfo; - BEGIN_INTERFACE_MAP(HdmiCec_2) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - END_INTERFACE_MAP - - private: - class PowerManagerNotification : public Exchange::IPowerManager::INotification { - private: - PowerManagerNotification(const PowerManagerNotification&) = delete; - PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; - - public: - explicit PowerManagerNotification(HdmiCec_2& parent) - : _parent(parent) - { - } - ~PowerManagerNotification() override = default; - - public: - void OnPowerModeChanged(const PowerState ¤tState, const PowerState &newState) override - { - _parent.onPowerModeChanged(currentState, newState); - } - void OnPowerModePreChange(const PowerState ¤tState, const PowerState &newState) override {} - void OnDeepSleepTimeout(const int &wakeupTimeout) override {} - void OnNetworkStandbyModeChanged(const bool &enabled) override {} - void OnThermalModeChanged(const ThermalTemperature ¤tThermalLevel, const ThermalTemperature &newThermalLevel, const float ¤tTemperature) override {} - void OnRebootBegin(const string &rebootReasonCustom, const string &rebootReasonOther, const string &rebootRequestor) override {} - - BEGIN_INTERFACE_MAP(PowerManagerNotification) - INTERFACE_ENTRY(Exchange::IPowerManager::INotification) - END_INTERFACE_MAP - - private: - HdmiCec_2& _parent; - }; - // We do not allow this plugin to be copied !! - HdmiCec_2(const HdmiCec_2&) = delete; - HdmiCec_2& operator=(const HdmiCec_2&) = delete; - - //Begin methods - uint32_t setEnabledWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getEnabledWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setOTPEnabledWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getOTPEnabledWrapper(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 performOTPActionWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getDeviceList (const JsonObject& parameters, JsonObject& response); - uint32_t getActiveSourceStatus(const JsonObject& parameters, JsonObject& response); - uint32_t sendRemoteKeyPressWrapper(const JsonObject& parameters, JsonObject& response); - - //End methods - std::string logicalAddressDeviceType; - bool cecSettingEnabled; - bool cecOTPSettingEnabled; - bool cecEnableStatus; - bool IsCecMgrActivated; - Connection *smConnection; - int m_numberOfDevices; - bool m_pollThreadExit; - Utils::ThreadRAII m_pollThread; - bool m_updateThreadExit; - Utils::ThreadRAII m_UpdateThread; - bool m_sendKeyEventThreadExit; - bool m_sendKeyEventThreadRun; - Utils::ThreadRAII m_sendKeyEventThread; - std::mutex m_sendKeyEventMutex; - std::queue m_SendKeyQueue; - std::condition_variable m_sendKeyCV; - - HdmiCec_2Processor *msgProcessor; - HdmiCec_2FrameListener *msgFrameListener; - PowerManagerInterfaceRef _powerManagerPlugin; - Core::Sink _pwrMgrNotification; - bool _registeredEventHandlers; - void InitializePowerManagerPluginHost::IShell *service - const void InitializeIARM(); - void DeinitializeIARM(); - static void cecMgrEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - void onCECDaemonInit(); - void cecStatusUpdated(void *evtStatus); - void onHdmiHotPlug(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 isPersist); - bool getEnabled(); - void setOTPEnabled(bool enabled); - bool getOTPEnabled(); - bool performOTPAction(); - void CECEnable(void); - void CECDisable(void); - void getPhysicalAddress(); - void getLogicalAddress(); - void cecAddressesChanged(int changeStatus); - bool sendStandbyMessage(); - bool pingDeviceUpdateList (int idev); - void removeAllCecDevices(); - void requestVendorID(const int newDevlogicalAddress); - void requestOsdName(const int newDevlogicalAddress); - void requestCecDevDetails(const int logicalAddress); - static void threadRun(); - static void threadUpdateCheck(); - static void threadSendKeyEvent(); - }; - } // namespace Plugin -} // namespace WPEFramework - - - - diff --git a/HdmiCec_2/Module.cpp b/HdmiCec_2/Module.cpp deleted file mode 100644 index ce759b61..00000000 --- a/HdmiCec_2/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/HdmiCec_2/Module.h b/HdmiCec_2/Module.h deleted file mode 100644 index 5409162d..00000000 --- a/HdmiCec_2/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_HdmiCec_2 -#endif - -#include -#include - -#undef EXTERNAL -#define EXTERNAL diff --git a/HdmiCec_2/README.md b/HdmiCec_2/README.md deleted file mode 100644 index fe054a42..00000000 --- a/HdmiCec_2/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": "rdk.org.HdmiCec_2.1."}' http://127.0.0.1:9998/jsonrpc From 5bd872a027be115cf8d0bdca0cd054c2036e51d2 Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Tue, 4 Mar 2025 00:11:03 +0530 Subject: [PATCH 6/6] Update CMakeLists.txt --- CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4940d61d..d474ddb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,10 +44,6 @@ if(PLUGIN_AVOUTPUT) add_subdirectory(AVOutput) endif() -if(PLUGIN_HDMICEC2) - add_subdirectory(HdmiCec_2) -endif() - if(PLUGIN_HDMICECSOURCE) add_subdirectory(HdmiCecSource) endif() @@ -64,9 +60,6 @@ if(PLUGIN_HDMIINPUT) add_subdirectory(HdmiInput) endif() -if(PLUGIN_COMPOSITEINPUT) - add_subdirectory(CompositeInput) -endif() if(WPEFRAMEWORK_CREATE_IPKG_TARGETS) set(CPACK_GENERATOR "DEB")