diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index e0567f634d..c146887ed4 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -143,6 +143,7 @@ jobs: patch -p1 < ${{github.workspace}}/rdkservices/Tests/L2Tests/patches/0001-DELIA-66976-SystemAudioPlayer-interface.patch patch -p1 < ${{github.workspace}}/rdkservices/Tests/L2Tests/patches/0002-DELIA-66976-specially-for-comcast-bring-back-the-old.patch patch -p1 < ${{github.workspace}}/rdkservices/Tests/L2Tests/patches/DeviceInfo_brand.patch + patch -p1 < ${{github.workspace}}/rdkservices/Tests/L2Tests/patches/RDKTV-35484-DeviceIdentification2.patch cd .. - name: Build ThunderInterfaces diff --git a/DeviceInfo/CMakeLists.txt b/DeviceInfo/CMakeLists.txt index a1c880ae06..124ab57efd 100644 --- a/DeviceInfo/CMakeLists.txt +++ b/DeviceInfo/CMakeLists.txt @@ -18,8 +18,16 @@ set(PLUGIN_NAME DeviceInfo) set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + set(PLUGIN_DEVICEINFO_MODE "Off" CACHE STRING "Controls if the plugin should run in its own process, in process or remote") set(PLUGIN_DEVICEINFO_STARTUPORDER "" CACHE STRING "Start-up order for DeviceInfo plugin") +set(PLUGIN_DEVICEIDENTIFICATION_INTERFACE_NAME "eth0" CACHE STRING "Ethernet Card name which has to be associated for the Raw Device Id creation") +option(PLUGIN_DEVICEIDENTIFICATION_USE_MFR "Get device identification details using MFR library" OFF) + +if (DEVICE_IDENTIFICATION_CHIPSET_INFO) + add_definitions (-DDEVICE_IDENTIFICATION_CHIPSET_INFO=\"${DEVICE_IDENTIFICATION_CHIPSET_INFO}\") +endif (DEVICE_IDENTIFICATION_CHIPSET_INFO) find_package(${NAMESPACE}Plugins REQUIRED) find_package(${NAMESPACE}Definitions REQUIRED) @@ -27,6 +35,9 @@ find_package(CompileSettingsDebug CONFIG REQUIRED) find_package(RFC) find_package(DS) find_package(IARMBus) +find_package(NEXUS QUIET) +find_package(BCM_HOST QUIET) +find_package(MFRFWLibs QUIET) add_library(${MODULE_NAME} SHARED DeviceInfo.cpp @@ -37,10 +48,75 @@ add_library(${MODULE_NAME} SHARED Implementation/DeviceInfo.cpp Module.cpp) +if (PLUGIN_DEVICEIDENTIFICATION_USE_MFR AND MFRFWLIBS_FOUND) + target_sources(${MODULE_NAME} + PRIVATE + Implementation/MFR/MFR.cpp) + target_link_libraries(${MODULE_NAME} + PRIVATE + MFRFWLibs::MFRFWLibs) +elseif (BUILD_BROADCOM) + target_sources(${MODULE_NAME} + PRIVATE + Implementation/Broadcom/Broadcom.cpp) +elseif (NEXUS_FOUND) + find_package(NXCLIENT REQUIRED) + target_link_libraries(${MODULE_NAME} + PRIVATE + NEXUS::NEXUS + NXCLIENT::NXCLIENT) + if (DEVICEIDENTIFICATION_IMPLEMENTATION_PATH) + target_sources(${MODULE_NAME} + PRIVATE + ${DEVICEIDENTIFICATION_IMPLEMENTATION_PATH}/Nexus.cpp) + else() + include(GetExternalCode) + set(DEVICEIDENTIFICATION_IMPLEMENTATION_VERSION "master" CACHE STRING "DeviceIdentification implementation version") + set(DEVICEIDENTIFICATION_IMPLEMENTATION_REPOSITORY "https://code.rdkcentral.com/r/soc/broadcom/components/rdkcentral/thundernanoservices/DeviceIdentification" CACHE STRING "DeviceIdentification implementation repository") + GetExternalCode( + GIT_REPOSITORY ${DEVICEIDENTIFICATION_IMPLEMENTATION_REPOSITORY} + GIT_TAG ${DEVICEIDENTIFICATION_IMPLEMENTATION_VERSION} + SOURCE_DIR "Implementation/Nexus" + ) + target_sources(${MODULE_NAME} + PRIVATE + Implementation/Nexus/Nexus.cpp) + endif() +elseif (BCM_HOST_FOUND) + target_sources(${MODULE_NAME} + PRIVATE + Implementation/RPI/RPI.cpp) + target_link_libraries(${MODULE_NAME} + PRIVATE + BCM_HOST::BCM_HOST) +elseif (BUILD_AMLOGIC) + target_sources(${MODULE_NAME} + PRIVATE + Implementation/Amlogic/Amlogic.cpp) + target_compile_definitions(${MODULE_NAME} + PRIVATE + DISABLE_DEVICEID_CONTROL=1) +elseif (BUILD_REALTEK) + target_sources(${MODULE_NAME} + PRIVATE + Implementation/Realtek/Realtek.cpp) +elseif(UNIX AND NOT APPLE) + target_sources(${MODULE_NAME} + PRIVATE + Implementation/Linux/Linux.cpp) + set(GENERIC_DEVICEIDENTIFIATION ON) +else () + message(FATAL_ERROR "There is no platform backend for device identifier plugin") +endif() + set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES) +target_include_directories(${MODULE_NAME} + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}) + target_include_directories(${MODULE_NAME} PRIVATE ${RFC_INCLUDE_DIRS} ${DS_INCLUDE_DIRS} diff --git a/DeviceInfo/DeviceInfo.conf.in b/DeviceInfo/DeviceInfo.conf.in index 2a8f0b8924..4694324300 100644 --- a/DeviceInfo/DeviceInfo.conf.in +++ b/DeviceInfo/DeviceInfo.conf.in @@ -3,6 +3,10 @@ startuporder = "@PLUGIN_DEVICEINFO_STARTUPORDER@" configuration = JSON() +if boolean("@GENERIC_DEVICEIDENTIFIATION@"): + if boolean("@PLUGIN_DEVICEIDENTIFICATION_INTERFACE_NAME@"): + configuration.add("interface", @PLUGIN_DEVICEIDENTIFICATION_INTERFACE_NAME@) + rootobject = JSON() rootobject.add("mode", "@PLUGIN_DEVICEINFO_MODE@") configuration.add("root", rootobject) diff --git a/DeviceInfo/DeviceInfo.config b/DeviceInfo/DeviceInfo.config index a50586960a..a3005b2a0d 100644 --- a/DeviceInfo/DeviceInfo.config +++ b/DeviceInfo/DeviceInfo.config @@ -7,6 +7,12 @@ set (startuporder ${PLUGIN_DEVICEINFO_STARTUPORDER}) endif() map() +if(GENERIC_DEVICEIDENTIFIATION) + if(PLUGIN_DEVICEIDENTIFICATION_INTERFACE_NAME) + kv(interface ${PLUGIN_DEVICEIDENTIFICATION_INTERFACE_NAME}) + endif() +endif() + key(root) map() kv(mode ${PLUGIN_DEVICEINFO_MODE}) diff --git a/DeviceInfo/DeviceInfo.cpp b/DeviceInfo/DeviceInfo.cpp index e2fa9d6a76..55f28459fd 100644 --- a/DeviceInfo/DeviceInfo.cpp +++ b/DeviceInfo/DeviceInfo.cpp @@ -18,8 +18,14 @@ */ #include "DeviceInfo.h" +#include +#include +#include "tracing/Logging.h" +#include "UtilsJsonRpc.h" +#include "UtilsController.h" #include + #define API_VERSION_NUMBER_MAJOR 1 #define API_VERSION_NUMBER_MINOR 1 #define API_VERSION_NUMBER_PATCH 0 @@ -30,11 +36,19 @@ namespace { // Version (Major, Minor, Patch) API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH, // Preconditions +#ifdef DISABLE_DEVICEID_CONTROL + { PluginHost::ISubSystem::IDENTIFIER }, +#else {}, +#endif // Terminations {}, // Controls +#ifdef DISABLE_DEVICEID_CONTROL {} +#else + { PluginHost::ISubSystem::IDENTIFIER } +#endif ); } @@ -48,7 +62,7 @@ namespace Plugin { { ASSERT(_service == nullptr); ASSERT(service != nullptr); - + ASSERT(_identifier == nullptr); ASSERT(_subSystem == nullptr); _skipURL = static_cast(service->WebPrefix().length()); @@ -61,11 +75,34 @@ namespace Plugin { _deviceAudioCapabilities = service->Root(_connectionId, 2000, _T("DeviceAudioCapabilities")); _deviceVideoCapabilities = service->Root(_connectionId, 2000, _T("DeviceVideoCapabilities")); _firmwareVersion = service->Root(_connectionId, 2000, _T("FirmwareVersion")); + _device = service->Root(_connectionId, 2000, _T("DeviceImplementation")); + if (_device != nullptr) { + Exchange::IConfiguration* configure = _device->QueryInterface(); + if (configure != nullptr) { + configure->Configure(service); + configure->Release(); + } + + _identifier = _device->QueryInterface(); + if (_identifier == nullptr) { + + _device->Release(); + _device = nullptr; + } else { + _deviceId = GetDeviceId(); + if (_deviceId.empty() != true) { +#ifndef DISABLE_DEVICEID_CONTROL + service->SubSystems()->Set(PluginHost::ISubSystem::IDENTIFIER, _identifier); +#endif + } + } + } ASSERT(_deviceInfo != nullptr); ASSERT(_deviceAudioCapabilities != nullptr); ASSERT(_deviceVideoCapabilities != nullptr); ASSERT(_firmwareVersion != nullptr); + ASSERT(_device != nullptr); // On success return empty, to indicate there is no error text. @@ -73,6 +110,7 @@ namespace Plugin { && (_deviceInfo != nullptr) && (_deviceAudioCapabilities != nullptr) && (_deviceVideoCapabilities != nullptr) + && (_device != nullptr) && (_firmwareVersion != nullptr)) ? EMPTY_STRING : _T("Could not retrieve System Information."); @@ -82,10 +120,22 @@ namespace Plugin { { ASSERT(_service == service); + if (_identifier != nullptr) { + if (_deviceId.empty() != true) { +#ifndef DISABLE_DEVICEID_CONTROL + service->SubSystems()->Set(PluginHost::ISubSystem::IDENTIFIER, nullptr); +#endif + _deviceId.clear(); + } + _identifier->Release(); + _identifier = nullptr; + } + _deviceInfo->Release(); _deviceAudioCapabilities->Release(); _deviceVideoCapabilities->Release(); _firmwareVersion->Release(); + _device->Release(); if (_subSystem != nullptr) { _subSystem->Release(); @@ -221,5 +271,74 @@ namespace Plugin { socketPortInfo.Runs = Core::ResourceMonitor::Instance().Runs(); } + string DeviceInfo::RetrieveSerialNumberThroughCOMRPC() const + { + std::string Number; + if (_service) + { + if(_deviceInfo) + { + _deviceInfo->SerialNumber(Number); + } + else + { + LOGERR("Failed to create DeviceInfo object\n"); + } + } + return Number; + } + string DeviceInfo::GetDeviceId() const + { + string result; + string serial; +#ifndef DISABLE_DEVICEID_CONTROL + ASSERT(_identifier != nullptr); + + if (_identifier != nullptr) { + uint8_t myBuffer[64]; + + myBuffer[0] = _identifier->Identifier(sizeof(myBuffer) - 1, &(myBuffer[1])); + + if (myBuffer[0] != 0) { + result = Core::SystemInfo::Instance().Id(myBuffer, ~0); + } + else + { + serial = RetrieveSerialNumberThroughCOMRPC(); + + if (!serial.empty()) { + uint8_t ret = serial.length(); + + if (ret > (sizeof(myBuffer) - 1)){ + ret = sizeof(myBuffer) - 1; + } + myBuffer[0] = ret; + ::memcpy(&(myBuffer[1]), serial.c_str(), ret); + + if(myBuffer[0] != 0){ + result = Core::SystemInfo::Instance().Id(myBuffer, ~0); + } + } + } + + } +#else + // extract DeviceId set by Thunder + if (_service->SubSystems()->IsActive(PluginHost::ISubSystem::IDENTIFIER) == true) { + + const PluginHost::ISubSystem::IIdentifier* identifier(_service->SubSystems()->Get()); + + if (identifier != nullptr) { + uint8_t myBuffer[64]; + + if ((myBuffer[0] = identifier->Identifier(sizeof(myBuffer) - 1, &(myBuffer[1]))) != 0) { + result = Core::SystemInfo::Instance().Id(myBuffer, ~0); + } + identifier->Release(); + } + } +#endif + return result; + } } // namespace Plugin } // namespace WPEFramework diff --git a/DeviceInfo/DeviceInfo.h b/DeviceInfo/DeviceInfo.h index 191e250b3d..0f43677c97 100644 --- a/DeviceInfo/DeviceInfo.h +++ b/DeviceInfo/DeviceInfo.h @@ -27,6 +27,7 @@ #include #endif /* USE_THUNDER_R4 */ #include +#include #include namespace WPEFramework { @@ -73,6 +74,9 @@ namespace Plugin { , _deviceAudioCapabilities(nullptr) , _deviceVideoCapabilities(nullptr) , _firmwareVersion(nullptr) + , _deviceId() + , _identifier(nullptr) + , _device(nullptr) { RegisterAll(); } @@ -90,6 +94,7 @@ namespace Plugin { INTERFACE_AGGREGATE(Exchange::IDeviceAudioCapabilities, _deviceAudioCapabilities) INTERFACE_AGGREGATE(Exchange::IDeviceVideoCapabilities, _deviceVideoCapabilities) INTERFACE_AGGREGATE(Exchange::IFirmwareVersion, _firmwareVersion) + INTERFACE_AGGREGATE(Exchange::IDeviceIdentification2, _device) END_INTERFACE_MAP public: @@ -123,6 +128,7 @@ namespace Plugin { uint32_t get_supportedaudioports(JsonData::DeviceInfo::SupportedaudioportsData& response) const; uint32_t get_supportedvideodisplays(JsonData::DeviceInfo::SupportedvideodisplaysData& response) const; uint32_t get_hostedid(JsonData::DeviceInfo::HostedidData& response) const; + uint32_t get_chipset(JsonData::DeviceInfo::ChipsetData& response) const; uint32_t endpoint_defaultresolution(const JsonData::DeviceInfo::SupportedresolutionsParamsInfo& params, JsonData::DeviceInfo::DefaultresolutionResultData& response) const; uint32_t endpoint_supportedresolutions(const JsonData::DeviceInfo::SupportedresolutionsParamsInfo& params, JsonData::DeviceInfo::SupportedresolutionsResultData& response) const; uint32_t endpoint_supportedhdcp(const JsonData::DeviceInfo::SupportedresolutionsParamsInfo& params, JsonData::DeviceInfo::SupportedhdcpResultData& response) const; @@ -133,6 +139,8 @@ namespace Plugin { void SysInfo(JsonData::DeviceInfo::SysteminfoData& systemInfo) const; void AddressInfo(Core::JSON::ArrayType& addressInfo) const; void SocketPortInfo(JsonData::DeviceInfo::SocketinfoData& socketPortInfo) const; + string GetDeviceId() const; + string RetrieveSerialNumberThroughCOMRPC() const; private: uint8_t _skipURL; @@ -143,6 +151,10 @@ namespace Plugin { Exchange::IDeviceAudioCapabilities* _deviceAudioCapabilities; Exchange::IDeviceVideoCapabilities* _deviceVideoCapabilities; Exchange::IFirmwareVersion* _firmwareVersion; + string _deviceId; + PluginHost::ISubSystem::IIdentifier* _identifier; + Exchange::IDeviceIdentification2* _device; + }; } // namespace Plugin diff --git a/DeviceInfo/DeviceInfo.json b/DeviceInfo/DeviceInfo.json index b7918adb44..69f2399eba 100644 --- a/DeviceInfo/DeviceInfo.json +++ b/DeviceInfo/DeviceInfo.json @@ -488,6 +488,28 @@ } ] }, + "chipset": { + "summary": "Chipset used for this device", + "readonly": true, + "params": { + "type": "object", + "properties": { + "chipset": { + "type": "string", + "example": "T962X3" + } + }, + "required": [ + "chipset" + ] + }, + "errors": [ + { + "description": "General error", + "$ref": "#/common/errors/general" + } + ] + }, "modelid": { "summary": "Device model number or SKU", "readonly": true, diff --git a/DeviceInfo/DeviceInfoJsonRpc.cpp b/DeviceInfo/DeviceInfoJsonRpc.cpp index e777f2138b..9f24d2f29e 100644 --- a/DeviceInfo/DeviceInfoJsonRpc.cpp +++ b/DeviceInfo/DeviceInfoJsonRpc.cpp @@ -45,6 +45,7 @@ namespace Plugin { Property(_T("supportedaudioports"), &DeviceInfo::get_supportedaudioports, nullptr, this); Property(_T("supportedvideodisplays"), &DeviceInfo::get_supportedvideodisplays, nullptr, this); Property(_T("hostedid"), &DeviceInfo::get_hostedid, nullptr, this); + Property(_T("chipset"), &DeviceInfo::get_chipset, nullptr, this); Register(_T("defaultresolution"), &DeviceInfo::endpoint_defaultresolution, this); Register(_T("supportedresolutions"), &DeviceInfo::endpoint_supportedresolutions, this); Register(_T("supportedhdcp"), &DeviceInfo::endpoint_supportedhdcp, this); @@ -69,6 +70,7 @@ namespace Plugin { Unregister(_T("supportedaudioports")); Unregister(_T("supportedvideodisplays")); Unregister(_T("hostedid")); + Unregister(_T("chipset")); Unregister(_T("defaultresolution")); Unregister(_T("supportedresolutions")); Unregister(_T("supportedhdcp")); @@ -339,6 +341,31 @@ namespace Plugin { return result; } + // Property: chipset - Chipset used for this device + // Return codes: + // - ERROR_NONE: Success + // - ERROR_GENERAL: General error + uint32_t DeviceInfo::get_chipset(JsonData::DeviceInfo::ChipsetData& response) const + { + uint32_t result = Core::ERROR_NONE ; + Exchange::IDeviceIdentification2::DeviceInfo info; + if(_device) + { + result = _device->Identification (info); + + if (result == Core::ERROR_NONE) { + response.Chipset = info.chipset; + } + } + else + { + LOGERR("Failed to get _device object\n"); + result = Core::ERROR_GENERAL ; + } + return result; + } + + // Method: defaultresolution - Default resolution on the selected video display port // Return codes: // - ERROR_NONE: Success diff --git a/DeviceInfo/Implementation/Amlogic/Amlogic.cpp b/DeviceInfo/Implementation/Amlogic/Amlogic.cpp new file mode 100644 index 0000000000..f50c7eb17d --- /dev/null +++ b/DeviceInfo/Implementation/Amlogic/Amlogic.cpp @@ -0,0 +1,127 @@ +#include "../../Module.h" +#include + +#include + +namespace WPEFramework { +namespace Plugin { + class DeviceImplementation : public Exchange::IDeviceIdentification2 , public PluginHost::ISubSystem::IIdentifier { + static constexpr const TCHAR* ChipsetInfo= _T("T962X3"); + static constexpr const TCHAR* VERSIONFile = _T("/version.txt"); + + public: + DeviceImplementation() + { + UpdateChipset(_chipset); + UpdateFirmwareVersion(_firmwareVersion); + UpdateIdentifier(); + } + + DeviceImplementation(const DeviceImplementation&) = delete; + DeviceImplementation& operator=(const DeviceImplementation&) = delete; + + virtual ~DeviceImplementation() + { + /* Nothing to do here. */ + } + + public: + // IIdentifier interface + uint8_t Identifier(const uint8_t length, uint8_t buffer[]) const override + { + uint8_t result = 0; + if ((_identity.length())) { + result = (_identity.length() > length ? length : _identity.length()); + ::memcpy(buffer, _identity.c_str(), result); + } else { + SYSLOG(Logging::Notification, (_T("Cannot determine system identity"))); + } + + return result; + } + string Architecture() const override + { + return Core::SystemInfo::Instance().Architecture(); + } + string Chipset() const override + { + return _chipset; + } + string FirmwareVersion() const override + { + return _firmwareVersion; + } + + // IDeviceIdentification2 interface + + Core::hresult Identification(DeviceInfo& info) const override + { + info.deviceID = ""; + uint8_t myBuffer[64]; + + myBuffer[0] = Identifier(sizeof(myBuffer) - 1, &(myBuffer[1])); + + if (myBuffer[0] != 0) { + info.deviceID = Core::SystemInfo::Instance().Id(myBuffer, ~0); + } + + info.firmwareVersion = FirmwareVersion(); + info.chipset = Chipset(); + + return Core::ERROR_NONE; + } + + BEGIN_INTERFACE_MAP(DeviceImplementation) + INTERFACE_ENTRY(PluginHost::ISubSystem::IIdentifier) + INTERFACE_ENTRY(Exchange::IDeviceIdentification2) + END_INTERFACE_MAP + + private: + inline void UpdateFirmwareVersion(string& firmwareVersion) const + { + string line; + std::ifstream file(VERSIONFile); + + if (file.is_open()) { + while (getline(file, line)) { + if (line.find("SDK_VERSION") != std::string::npos) { + std::size_t position = line.find('='); + if (position != std::string::npos) { + firmwareVersion.assign(line.substr(position + 1, string::npos)); + break; + } + } + } + + file.close(); + } + } + + inline void UpdateChipset(string& chipset) const + { + +#ifndef DEVICE_IDENTIFICATION_CHIPSET_INFO + chipset.assign(ChipsetInfo); +#else + chipset.assign(DEVICE_IDENTIFICATION_CHIPSET_INFO); +#endif + } + + inline void UpdateIdentifier() + { + /* + * @TODO : Update proper code for identifier when SOC ID is made + * available for Amlogic boards + */ + _identity.assign(""); + } + + private: + string _chipset; + string _firmwareVersion; + string _identity; + }; + + SERVICE_REGISTRATION(DeviceImplementation, 1, 0); +} +} diff --git a/DeviceInfo/Implementation/Broadcom/Broadcom.cpp b/DeviceInfo/Implementation/Broadcom/Broadcom.cpp new file mode 100644 index 0000000000..e8a1c7fd44 --- /dev/null +++ b/DeviceInfo/Implementation/Broadcom/Broadcom.cpp @@ -0,0 +1,165 @@ +/* + * 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. + */ + +#include "../../Module.h" +#include +#include +#include + +namespace WPEFramework { +namespace Plugin { + +class DeviceImplementation : public Exchange::IDeviceIdentification2, public PluginHost::ISubSystem::IIdentifier { + static constexpr const TCHAR* PlatformFile = _T("/proc/brcm/platform"); + +public: + DeviceImplementation() + : _chipset() + , _firmwareVersion() + , _identifier() + { + UpdateDeviceInfo(_identifier, _chipset, _firmwareVersion); + } + + DeviceImplementation(const DeviceImplementation&) = delete; + DeviceImplementation& operator= (const DeviceImplementation&) = delete; + virtual ~DeviceImplementation() + { + } + +public: + // Device Propertirs interface + string Architecture() const override + { + return Core::SystemInfo::Instance().Architecture();; + } + string Chipset() const override + { + return _chipset; + } + string FirmwareVersion() const override + { + return _firmwareVersion; + } + + uint8_t Identifier(const uint8_t length, uint8_t buffer[]) const override + { + uint8_t ret = 0; + if (_identifier.length()) { + ret = (_identifier.length() > length ? length : _identifier.length()); + ::memcpy(buffer, _identifier.c_str(), ret); + } + return ret; + } + + // IDeviceIdentification2 interface + + Core::hresult Identification(DeviceInfo& info) const override + { + info.deviceID = ""; + uint8_t myBuffer[64]; + + myBuffer[0] = Identifier(sizeof(myBuffer) - 1, &(myBuffer[1])); + + if (myBuffer[0] != 0) { + info.deviceID = Core::SystemInfo::Instance().Id(myBuffer, ~0); + } + + info.firmwareVersion = FirmwareVersion(); + info.chipset = Chipset(); + + return Core::ERROR_NONE; + } + + BEGIN_INTERFACE_MAP(DeviceImplementation) + INTERFACE_ENTRY(Exchange::IDeviceIdentification2) + INTERFACE_ENTRY(PluginHost::ISubSystem::IIdentifier) + END_INTERFACE_MAP + +private: + inline void UpdateDeviceInfo(string& identifier, string& chipset, string& firmwareVersion) const + { + identifier.assign(extractSerialNumber()); + chipset.assign(extractChipId()); + firmwareVersion.assign(extractFirmwareVersion()); + } + + inline std::string extractSerialNumber() const + { + std::string serialNumber; + std::ifstream serialNumberFile("/proc/device-tree/serial-number"); + + if (serialNumberFile.is_open()) + { + getline(serialNumberFile,serialNumber); + serialNumberFile.close(); + } + + return serialNumber; + } + + inline std::string extractChipId() const + { + std::string chipId; + std::ifstream chipIdFile("/proc/device-tree/model"); + + if (chipIdFile.is_open()) + { + getline(chipIdFile, chipId); + chipIdFile.close(); + } + + return chipId; + } + + inline std::string extractFirmwareVersion() const + { + std::string versionIdentifier("VERSION"); + std::ifstream versionFile("/version.txt"); + std::string line; + std::string firmwareVersion; + + if (versionFile.is_open()) + { + while (getline(versionFile, line)) + { + if (0 == line.find(versionIdentifier)) + { + std::size_t position = line.find(versionIdentifier) + versionIdentifier.length() + 1; // +1 is to skip '=' + if (position != std::string::npos) + { + firmwareVersion.assign(line.substr(position, std::string::npos)); + } + } + } + versionFile.close(); + } + + return firmwareVersion; + } + +private: + string _chipset; + string _firmwareVersion; + string _identifier; +}; + + SERVICE_REGISTRATION(DeviceImplementation, 1, 0); +} +} diff --git a/DeviceInfo/Implementation/Linux/Linux.cpp b/DeviceInfo/Implementation/Linux/Linux.cpp new file mode 100644 index 0000000000..fa7e2a960d --- /dev/null +++ b/DeviceInfo/Implementation/Linux/Linux.cpp @@ -0,0 +1,238 @@ +/* + * 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. + */ + +#include "../../Module.h" +#include +#include + +#include +#include + +namespace WPEFramework { +namespace Plugin { + class DeviceImplementation : public Exchange::IDeviceIdentification2, public PluginHost::ISubSystem::IIdentifier, public Exchange::IConfiguration { + private: + static uint8_t constexpr MacSize = 6; + + private: + class Config : public Core::JSON::Container { + public: + Config(const Config&); + Config& operator=(const Config&); + + Config() + : Core::JSON::Container() + , Interface() + { + Add(_T("interface"), &Interface); + } + + ~Config() override + { + } + + public: + Core::JSON::String Interface; + }; + + private: + class AdapterObserver : public WPEFramework::Core::AdapterObserver::INotification { + public: + static int32_t constexpr WaitTime = 5000; //Just wait for 5 seconds + + public: + AdapterObserver() = delete; + AdapterObserver(const AdapterObserver&) = delete; + AdapterObserver& operator=(const AdapterObserver&) = delete; + + AdapterObserver(const string& interface) + : _signal(false, true) + , _interface(interface) + , _observer(this) + { + _observer.Open(); + if (_interface.empty() != true) { + // Check given interface has valid MAC + if (IsInterfaceHasValidMAC(interface) == true) { + _signal.SetEvent(); + } + } else { + // If interface is not given then, + // check any of the activated interface has valid MAC + if (IsAnyInterfaceHasValidMAC() == true) { + _signal.SetEvent(); + } + } + } + ~AdapterObserver() override + { + _observer.Close(); + } + + public: + virtual void Event(const string& interface) override + { + if (_interface.empty() != true) { + // Check configured interface has valid MAC + if (interface == _interface) { + if (IsInterfaceHasValidMAC(interface) == true) { + _signal.SetEvent(); + } + } + } else { + // If interface is not configured then, + // check activated interface has valid MAC + if (IsInterfaceHasValidMAC(interface) == true) { + _signal.SetEvent(); + } + } + } + inline uint32_t WaitForCompletion(int32_t waitTime) + { + return _signal.Lock(waitTime); + } + const uint8_t* MACAddress() + { + return _MACAddressBuffer; + } + + private: + inline bool IsAnyInterfaceHasValidMAC() + { + bool valid = false; + Core::AdapterIterator adapters; + + while ((adapters.Next() == true)) { + if ((valid = IsValidMAC(adapters)) == true) { + break; + } + } + return valid; + } + inline bool IsInterfaceHasValidMAC(const string& interface) + { + Core::AdapterIterator adapter(interface); + return IsValidMAC(adapter); + } + inline bool IsValidMAC(Core::AdapterIterator adapter) + { + bool valid = false; + if ((adapter.IsValid() == true) && ((valid = adapter.HasMAC()) == true)) { + memset(_MACAddressBuffer, 0, Core::AdapterIterator::MacSize); + adapter.MACAddress(_MACAddressBuffer, Core::AdapterIterator::MacSize); + } + return valid; + } + + private: + Core::Event _signal; + string _interface; + Core::AdapterObserver _observer; + uint8_t _MACAddressBuffer[Core::AdapterIterator::MacSize]; + }; + public: + DeviceImplementation() = default; + virtual ~DeviceImplementation() = default; + + DeviceImplementation(const DeviceImplementation&) = delete; + DeviceImplementation& operator=(const DeviceImplementation&) = delete; + + public: + uint32_t Configure(PluginHost::IShell* service) override + { + if (service) { + Config config; + config.FromString(service->ConfigLine()); + + _interface = config.Interface.Value(); + UpdateDeviceId(); + } + + return Core::ERROR_NONE; + } + + uint8_t Identifier(const uint8_t length, uint8_t* buffer) const override + { + uint8_t ret = 0; + if (_identifier.length()) { + ret = (_identifier.length() > length ? length : _identifier.length()); + ::memcpy(buffer, _identifier.c_str(), ret); + } + return ret; + } + string Architecture() const override + { + return Core::SystemInfo::Instance().Architecture(); + } + string Chipset() const override + { + return Core::SystemInfo::Instance().Chipset(); + } + string FirmwareVersion() const override + { + return Core::SystemInfo::Instance().FirmwareVersion(); + } + + // IDeviceIdentification2 interface + + Core::hresult Identification(DeviceInfo& info) const override + { + info.deviceID = ""; + uint8_t myBuffer[64]; + + myBuffer[0] = Identifier(sizeof(myBuffer) - 1, &(myBuffer[1])); + + if (myBuffer[0] != 0) { + info.deviceID = Core::SystemInfo::Instance().Id(myBuffer, ~0); + } + + info.firmwareVersion = FirmwareVersion(); + info.chipset = Chipset(); + + return Core::ERROR_NONE; + } + + private: + void UpdateDeviceId() + { + AdapterObserver observer(_interface); + + if (observer.WaitForCompletion(AdapterObserver::WaitTime) == Core::ERROR_NONE) { + _identifier.assign(reinterpret_cast(observer.MACAddress()), Core::AdapterIterator::MacSize); + } else { + TRACE(Trace::Error, (_T("There is no any valid physical interface available"))); + } + } + + public: + BEGIN_INTERFACE_MAP(DeviceImplementation) + INTERFACE_ENTRY(PluginHost::ISubSystem::IIdentifier) + INTERFACE_ENTRY(Exchange::IConfiguration) + INTERFACE_ENTRY(Exchange::IDeviceIdentification2) + END_INTERFACE_MAP + + private: + string _interface; + string _identifier; + }; + + SERVICE_REGISTRATION(DeviceImplementation, 1, 0); + +} +} diff --git a/DeviceInfo/Implementation/MFR/MFR.cpp b/DeviceInfo/Implementation/MFR/MFR.cpp new file mode 100644 index 0000000000..d5b7233b7a --- /dev/null +++ b/DeviceInfo/Implementation/MFR/MFR.cpp @@ -0,0 +1,144 @@ +/* + * 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. + */ + +#include "../../Module.h" +#include + +#include + +extern "C" { +#include +} + +namespace WPEFramework { +namespace Plugin { + class DeviceImplementation : public Exchange::IDeviceIdentification2, public PluginHost::ISubSystem::IIdentifier { + + public: + DeviceImplementation() + { + UpdateChipset(_chipset); + UpdateFirmwareVersion(_firmwareVersion); + UpdateIdentifier(); + } + + DeviceImplementation(const DeviceImplementation&) = delete; + DeviceImplementation& operator=(const DeviceImplementation&) = delete; + virtual ~DeviceImplementation() + { + /* Nothing to do here. */ + } + + public: + // IIdentifier interface + uint8_t Identifier(const uint8_t length, uint8_t buffer[]) const override + { + uint8_t result = 0; + if ((_identity.length()) && (_status == mfrERR_NONE)) { + result = (_identity.length() > length ? length : _identity.length()); + ::memcpy(buffer, _identity.c_str(), result); + } else { + SYSLOG(Logging::Notification, (_T("Cannot determine system identity; Error:[%d]!"), static_cast(_status))); + } + return result; + } + string Architecture() const override + { + return Core::SystemInfo::Instance().Architecture(); + } + string Chipset() const override + { + return _chipset; + } + string FirmwareVersion() const override + { + return _firmwareVersion; + } + + // IDeviceIdentification2 interface + + Core::hresult Identification(DeviceInfo& info) const override + { + info.deviceID = ""; + uint8_t myBuffer[64]; + + myBuffer[0] = Identifier(sizeof(myBuffer) - 1, &(myBuffer[1])); + + if (myBuffer[0] != 0) { + info.deviceID = Core::SystemInfo::Instance().Id(myBuffer, ~0); + } + + info.firmwareVersion = FirmwareVersion(); + info.chipset = Chipset(); + + return Core::ERROR_NONE; + } + + BEGIN_INTERFACE_MAP(DeviceImplementation) + INTERFACE_ENTRY(PluginHost::ISubSystem::IIdentifier) + INTERFACE_ENTRY(Exchange::IDeviceIdentification2) + END_INTERFACE_MAP + + private: + inline void UpdateFirmwareVersion(string& firmwareVersion) const + { + int retVal = -1; + mfrSerializedData_t mfrSerializedData; + retVal = mfrGetSerializedData(mfrSERIALIZED_TYPE_SOFTWAREVERSION, &mfrSerializedData); + if ((mfrERR_NONE == retVal) && mfrSerializedData.bufLen) { + firmwareVersion = mfrSerializedData.buf; + if (mfrSerializedData.freeBuf) { + mfrSerializedData.freeBuf(mfrSerializedData.buf); + } + } + } + inline void UpdateChipset(string& chipset) const + { + int retVal = -1; + mfrSerializedData_t mfrSerializedData; + retVal = mfrGetSerializedData(mfrSERIALIZED_TYPE_CHIPSETINFO, &mfrSerializedData); + if ((mfrERR_NONE == retVal) && mfrSerializedData.bufLen) { + chipset = mfrSerializedData.buf; + if (mfrSerializedData.freeBuf) { + mfrSerializedData.freeBuf(mfrSerializedData.buf); + } + } + } + inline void UpdateIdentifier() + { + mfrSerializedData_t mfrSerializedData; + _status = mfrGetSerializedData(mfrSERIALIZED_TYPE_SERIALNUMBER, &mfrSerializedData); + if ((mfrERR_NONE == _status) && mfrSerializedData.bufLen) { + _identity = mfrSerializedData.buf; + if (mfrSerializedData.freeBuf) { + mfrSerializedData.freeBuf(mfrSerializedData.buf); + } + } + } + + private: + string _chipset; + string _firmwareVersion; + string _identity; + mfrError_t _status; + }; + + SERVICE_REGISTRATION(DeviceImplementation, 1, 0); +} +} diff --git a/DeviceInfo/Implementation/RPI/RPI.cpp b/DeviceInfo/Implementation/RPI/RPI.cpp new file mode 100644 index 0000000000..9c04f712ab --- /dev/null +++ b/DeviceInfo/Implementation/RPI/RPI.cpp @@ -0,0 +1,158 @@ +/* + * 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. + */ + +#include "../../Module.h" + +#include +#include +#include + +namespace WPEFramework { +namespace Plugin { + + class DeviceImplementation : public Exchange::IDeviceIdentification2, public PluginHost::ISubSystem::IIdentifier { + private: + static constexpr const TCHAR* SerialInfoPath = "/sys/firmware/devicetree/base/serial-number"; + + public: + DeviceImplementation() + : _firmwareVersion() + , _identifier() + { + bcm_host_init(); + + UpdateFirmwareVersion(_firmwareVersion); + UpdateDeviceIdentifier(_identifier); + } + + DeviceImplementation(const DeviceImplementation&) = delete; + DeviceImplementation& operator=(const DeviceImplementation&) = delete; + virtual ~DeviceImplementation() + { + bcm_host_deinit(); + } + + public: + // IIdentifier interface + uint8_t Identifier(const uint8_t length, uint8_t* buffer) const override + { + uint8_t ret = 0; + if (_identifier.length()) { + ret = (_identifier.length() > length ? length : _identifier.length()); + ::memcpy(buffer, _identifier.c_str(), ret); + } + return ret; + } + string Architecture() const override + { + return Core::SystemInfo::Instance().Architecture(); + } + string Chipset() const override + { + return Core::SystemInfo::Instance().Chipset(); + } + string FirmwareVersion() const override + { + return _firmwareVersion; + } + + // IDeviceIdentification2 interface + + Core::hresult Identification(DeviceInfo& info) const override + { + info.deviceID = ""; + uint8_t myBuffer[64]; + + myBuffer[0] = Identifier(sizeof(myBuffer) - 1, &(myBuffer[1])); + + if (myBuffer[0] != 0) { + info.deviceID = Core::SystemInfo::Instance().Id(myBuffer, ~0); + } + + info.firmwareVersion = FirmwareVersion(); + info.chipset = Chipset(); + + return Core::ERROR_NONE; + } + + BEGIN_INTERFACE_MAP(DeviceImplementation) + INTERFACE_ENTRY(PluginHost::ISubSystem::IIdentifier) + INTERFACE_ENTRY(Exchange::IDeviceIdentification2) + END_INTERFACE_MAP + + private: + inline void UpdateFirmwareVersion(string& firmwareVersion) const + { + Command("version", firmwareVersion); + if (firmwareVersion.length() > 0) { + + string::size_type i = 0; + while (i < firmwareVersion.length()) { + i = firmwareVersion.find_first_of("\n\r", i); + if (i != std::string::npos) { + firmwareVersion.replace(i, 1, ", "); + } + } + } + } + inline void UpdateDeviceIdentifier(string& identifier) const + { + string fileName = SerialInfoPath; + WPEFramework::Core::File serialFile(fileName); + + if (serialFile.Open(true) == true) { + uint8_t serialInfo[serialFile.Size()]; + uint32_t size = serialFile.Read(serialInfo, static_cast(sizeof(serialInfo))); + identifier.assign(reinterpret_cast(serialInfo), size); + identifier.erase(0, identifier.find_first_not_of('0')); + } + } + void Command(const char request[], string& value) const + { + char buffer[512]; + + // Reset the string + buffer[0] = '\0'; + + int VARIABLE_IS_NOT_USED status = vc_gencmd(buffer, sizeof(buffer), &request[0]); + assert((status == 0) && "Error: vc_gencmd failed.\n"); + + // Make sure it is null-terminated + buffer[sizeof(buffer) - 1] = '\0'; + + // We do not need the stuff that is before the '=', we know what we requested :-) + char* equal = strchr(buffer, '='); + if (equal != nullptr) { + equal++; + } else { + equal = buffer; + } + + // Create string from buffer. + Core::ToString(equal, value); + } + + private: + string _firmwareVersion; + string _identifier; + }; + + SERVICE_REGISTRATION(DeviceImplementation, 1, 0); +} +} diff --git a/DeviceInfo/Implementation/Realtek/Realtek.cpp b/DeviceInfo/Implementation/Realtek/Realtek.cpp new file mode 100644 index 0000000000..24eac00652 --- /dev/null +++ b/DeviceInfo/Implementation/Realtek/Realtek.cpp @@ -0,0 +1,264 @@ +/* + * 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. + */ +#include "../../Module.h" +#include +#include + +#include +#include + +namespace WPEFramework { +namespace Plugin { + + class DeviceImplementation : public Exchange::IDeviceIdentification2 , public PluginHost::ISubSystem::IIdentifier, public Exchange::IConfiguration { + static constexpr const TCHAR* VERSIONFile = _T("/version.txt"); + private: + static uint8_t constexpr MacSize = 6; + + private: + class Config : public Core::JSON::Container { + public: + Config(const Config&); + Config& operator=(const Config&); + + Config() + : Core::JSON::Container() + , Interface() + { + Add(_T("interface"), &Interface); + } + + ~Config() override + { + } + + public: + Core::JSON::String Interface; + }; + + private: + class AdapterObserver : public WPEFramework::Core::AdapterObserver::INotification { + public: + static int32_t constexpr WaitTime = 5000; //Just wait for 5 seconds + + public: + AdapterObserver() = delete; + AdapterObserver(const AdapterObserver&) = delete; + AdapterObserver& operator=(const AdapterObserver&) = delete; + + AdapterObserver(const string& interface) + : _signal(false, true) + , _interface(interface) + , _observer(this) + { + _observer.Open(); + if (_interface.empty() != true) { + // Check given interface has valid MAC + if (IsInterfaceHasValidMAC(interface) == true) { + _signal.SetEvent(); + } + } else { + // If interface is not given then, + // check any of the activated interface has valid MAC + if (IsAnyInterfaceHasValidMAC() == true) { + _signal.SetEvent(); + } + } + } + ~AdapterObserver() override + { + _observer.Close(); + } + + public: + virtual void Event(const string& interface) override + { + if (_interface.empty() != true) { + // Check configured interface has valid MAC + if (interface == _interface) { + if (IsInterfaceHasValidMAC(interface) == true) { + _signal.SetEvent(); + } + } + } else { + // If interface is not configured then, + // check activated interface has valid MAC + if (IsInterfaceHasValidMAC(interface) == true) { + _signal.SetEvent(); + } + } + } + inline uint32_t WaitForCompletion(int32_t waitTime) + { + return _signal.Lock(waitTime); + } + const uint8_t* MACAddress() + { + return _MACAddressBuffer; + } + + private: + inline bool IsAnyInterfaceHasValidMAC() + { + bool valid = false; + Core::AdapterIterator adapters; + + while ((adapters.Next() == true)) { + if ((valid = IsValidMAC(adapters)) == true) { + break; + } + } + return valid; + } + inline bool IsInterfaceHasValidMAC(const string& interface) + { + Core::AdapterIterator adapter(interface); + return IsValidMAC(adapter); + } + inline bool IsValidMAC(Core::AdapterIterator adapter) + { + bool valid = false; + if ((adapter.IsValid() == true) && ((valid = adapter.HasMAC()) == true)) { + memset(_MACAddressBuffer, 0, Core::AdapterIterator::MacSize); + adapter.MACAddress(_MACAddressBuffer, Core::AdapterIterator::MacSize); + } + return valid; + } + + private: + Core::Event _signal; + string _interface; + Core::AdapterObserver _observer; + uint8_t _MACAddressBuffer[Core::AdapterIterator::MacSize]; + }; + + public: + DeviceImplementation() + { + UpdateFirmwareVersion(_firmwareVersion); + } + virtual ~DeviceImplementation() = default; + + DeviceImplementation(const DeviceImplementation&) = delete; + DeviceImplementation& operator=(const DeviceImplementation&) = delete; + + public: + uint32_t Configure(PluginHost::IShell* service) override + { + if (service) { + Config config; + config.FromString(service->ConfigLine()); + + _interface = config.Interface.Value(); + UpdateDeviceId(); + } + + return Core::ERROR_NONE; + } + + // Device Propertirs interface + + // Identifier interface + uint8_t Identifier(const uint8_t length, uint8_t* buffer) const override + { + uint8_t ret = 0; + if (_identifier.length()) { + ret = (_identifier.length() > length ? length : _identifier.length()); + ::memcpy(buffer, _identifier.c_str(), ret); + } + return ret; + } + string Architecture() const override + { + return Core::SystemInfo::Instance().Architecture(); + } + string Chipset() const override + { + return Core::SystemInfo::Instance().Chipset(); + } + string FirmwareVersion() const override + { + return _firmwareVersion; + } + + // IDeviceIdentification2 interface + + Core::hresult Identification(DeviceInfo& info) const override + { + info.deviceID = ""; + uint8_t myBuffer[64]; + + myBuffer[0] = Identifier(sizeof(myBuffer) - 1, &(myBuffer[1])); + + if (myBuffer[0] != 0) { + info.deviceID = Core::SystemInfo::Instance().Id(myBuffer, ~0); + } + + info.firmwareVersion = FirmwareVersion(); + info.chipset = Chipset(); + + return Core::ERROR_NONE; + } + + + private: + void UpdateDeviceId() + { + AdapterObserver observer(_interface); + + if (observer.WaitForCompletion(AdapterObserver::WaitTime) == Core::ERROR_NONE) { + _identifier.assign(reinterpret_cast(observer.MACAddress()), Core::AdapterIterator::MacSize); + } else { + TRACE(Trace::Error, (_T("There is no any valid physical interface available"))); + } + } + inline void UpdateFirmwareVersion(string& firmwareVersion) const + { + string line; + std::ifstream file(VERSIONFile); + if (file.is_open()) { + while (getline(file, line)) { + if (line.find("SDK_VERSION") != std::string::npos) { + std::size_t position = line.find('='); + if (position != std::string::npos) { + firmwareVersion.assign(line.substr(position + 1, string::npos)); + break; + } + } + } + file.close(); + } + } + + public: + BEGIN_INTERFACE_MAP(DeviceImplementation) + INTERFACE_ENTRY(PluginHost::ISubSystem::IIdentifier) + INTERFACE_ENTRY(Exchange::IConfiguration) + INTERFACE_ENTRY(Exchange::IDeviceIdentification2) + END_INTERFACE_MAP + + private: + string _firmwareVersion; + string _interface; + string _identifier; + }; + + SERVICE_REGISTRATION(DeviceImplementation, 1, 0); +} +} diff --git a/DeviceInfo/cmake/FindBCM_HOST.cmake b/DeviceInfo/cmake/FindBCM_HOST.cmake new file mode 100644 index 0000000000..438007c8a6 --- /dev/null +++ b/DeviceInfo/cmake/FindBCM_HOST.cmake @@ -0,0 +1 @@ +../../cmake/FindBCM_HOST.cmake diff --git a/DeviceInfo/cmake/FindMFRFWLibs.cmake b/DeviceInfo/cmake/FindMFRFWLibs.cmake new file mode 100644 index 0000000000..b213617541 --- /dev/null +++ b/DeviceInfo/cmake/FindMFRFWLibs.cmake @@ -0,0 +1,60 @@ +# - Try to find MFRFWLIBS +# Once done this will define +# MFRFWLIBS_FOUND - System has MFRFWLibs +# MFRFWLIBS_INCLUDE_DIRS - The MFRFWLibs include directories +# MFRFWLIBS_LIBRARIES - The libraries needed to use MFRFWLibs +# +# 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 +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS +# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + +if(MFRFWLibs_FIND_QUIETLY) + set(_MFRFWLIBS_MODE QUIET) +elseif(MFRFWLibs_FIND_REQUIRED) + set(_MFRFWLIBS_MODE REQUIRED) +endif() + +find_package(PkgConfig) +pkg_check_modules(MFRFWLIBS ${_MFRFWLIBS_MODE} fwupgrade) +find_library(MFRFWLIBS_LIBRARY NAMES ${MFRFWLIBS_LIBRARIES} + HINTS ${MFRFWLIBS_LIBDIR} ${MFRFWLIBS_LIBRARY_DIRS} + ) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MFRFWLibs DEFAULT_MSG MFRFWLIBS_LIBRARY MFRFWLIBS_LIBRARIES) +mark_as_advanced(MFRFWLIBS_INCLUDE_DIRS MFRFWLIBS_LIBRARIES) + +if(MFRFWLibs_FOUND AND NOT TARGET MFRFWLibs::MFRFWLibs) + add_library(MFRFWLibs::MFRFWLibs UNKNOWN IMPORTED) + set_target_properties(MFRFWLibs::MFRFWLibs PROPERTIES + IMPORTED_LOCATION "${MFRFWLIBS_LIBRARY}" + INTERFACE_LINK_LIBRARIES "${MFRFWLIBS_LIBRARIES}" + INTERFACE_COMPILE_OPTIONS "${MFRFWLIBS_DEFINITIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${MFRFWLIBS_INCLUDE_DIRS}" + ) +endif() diff --git a/DeviceInfo/cmake/FindNEXUS.cmake b/DeviceInfo/cmake/FindNEXUS.cmake new file mode 100644 index 0000000000..1c154e1532 --- /dev/null +++ b/DeviceInfo/cmake/FindNEXUS.cmake @@ -0,0 +1 @@ +../../cmake/FindNEXUS.cmake diff --git a/DeviceInfo/cmake/FindNXCLIENT.cmake b/DeviceInfo/cmake/FindNXCLIENT.cmake new file mode 100644 index 0000000000..f465a38dc7 --- /dev/null +++ b/DeviceInfo/cmake/FindNXCLIENT.cmake @@ -0,0 +1 @@ +../../cmake/FindNXCLIENT.cmake diff --git a/Tests/L1Tests/tests/test_DeviceIdentification.cpp b/Tests/L1Tests/tests/test_DeviceIdentification.cpp index 7fc8b1b908..4de257be98 100755 --- a/Tests/L1Tests/tests/test_DeviceIdentification.cpp +++ b/Tests/L1Tests/tests/test_DeviceIdentification.cpp @@ -10,39 +10,6 @@ using namespace WPEFramework; using ::testing::NiceMock; -namespace { -const string testArchitecture = _T("testArchitecture"); -const string testChipset = _T("testChipset"); -const string testFirmwareVersion = _T("testFirmwareVersion"); -const string testId = _T("testIdentity"); -const string deviceId = _T("WPEdGVzdElkZW50aXR5"); -} - -namespace WPEFramework { -namespace Plugin { - class DeviceImplementation : public PluginHost::ISubSystem::IIdentifier { - public: - virtual ~DeviceImplementation() = default; - - string Architecture() const override { return testArchitecture; } - string Chipset() const override { return testChipset; } - string FirmwareVersion() const override { return testFirmwareVersion; } - uint8_t Identifier(const uint8_t length, uint8_t buffer[]) const override - { - ::memcpy(buffer, testId.c_str(), testId.length()); - - return testId.length(); - } - - BEGIN_INTERFACE_MAP(DeviceImplementation) - INTERFACE_ENTRY(PluginHost::ISubSystem::IIdentifier) - END_INTERFACE_MAP - }; - - SERVICE_REGISTRATION(DeviceImplementation, 1, 0); -} -} - class DeviceIdentificationTest : public ::testing::Test { protected: Core::ProxyType plugin; diff --git a/Tests/L1Tests/tests/test_DeviceInfoDeviceIdentification.cpp b/Tests/L1Tests/tests/test_DeviceInfoDeviceIdentification.cpp new file mode 100755 index 0000000000..30797aaa3a --- /dev/null +++ b/Tests/L1Tests/tests/test_DeviceInfoDeviceIdentification.cpp @@ -0,0 +1,94 @@ +#include + +#include "DeviceInfo.h" +#include "COMLinkMock.h" +#include "ServiceMock.h" +#include "SystemInfo.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +namespace { +const string testArchitecture = _T("testArchitecture"); +const string testChipset = _T("testChipset"); +const string testFirmwareVersion = _T("testFirmwareVersion"); +const string testId = _T("testIdentity"); +const string deviceId = _T("WPEdGVzdElkZW50aXR5"); +} + +namespace WPEFramework { +namespace Plugin { + class DeviceImplementation : public Exchange::IDeviceIdentification2, public PluginHost::ISubSystem::IIdentifier { + public: + virtual ~DeviceImplementation() = default; + + string Architecture() const override { return testArchitecture; } + string Chipset() const override { return testChipset; } + string FirmwareVersion() const override { return testFirmwareVersion; } + uint8_t Identifier(const uint8_t length, uint8_t buffer[]) const override + { + ::memcpy(buffer, testId.c_str(), testId.length()); + + return testId.length(); + } + + Core::hresult Identification(DeviceInfo& info) const override + { + info.deviceID = deviceId; + info.firmwareVersion = FirmwareVersion(); + info.chipset = Chipset(); + + return Core::ERROR_NONE; + } + + + BEGIN_INTERFACE_MAP(DeviceImplementation) + INTERFACE_ENTRY(Exchange::IDeviceIdentification2) + INTERFACE_ENTRY(PluginHost::ISubSystem::IIdentifier) + END_INTERFACE_MAP + }; + + SERVICE_REGISTRATION(DeviceImplementation, 1, 0); +} +} + +class DeviceInfoDeviceIdentificationTest : public ::testing::Test { +protected: + Core::ProxyType deviceInfoDeviceIdentification; + Exchange::IDeviceIdentification2* interface; + + DeviceInfoDeviceIdentificationTest() + : deviceInfoDeviceIdentification(Core::ProxyType::Create()) + { + interface = static_cast( + deviceInfoDeviceIdentification->QueryInterface(Exchange::IDeviceIdentification2::ID)); + } + virtual ~DeviceInfoDeviceIdentificationTest() + { + interface->Release(); + } + + virtual void SetUp() + { + ASSERT_TRUE(interface != nullptr); + } + + virtual void TearDown() + { + ASSERT_TRUE(interface != nullptr); + } +}; + + + +TEST_F(DeviceInfoDeviceIdentificationTest, Identification) +{ + Exchange::IDeviceIdentification2::DeviceInfo info; + EXPECT_EQ(Core::ERROR_NONE, interface->Identification(info)); + EXPECT_EQ(info.chipset, _T("testChipset")); + EXPECT_EQ(info.deviceID, _T("WPEdGVzdElkZW50aXR5")); + EXPECT_EQ(info.firmwareVersion, _T("testFirmwareVersion")); +} + + diff --git a/Tests/L2Tests/patches/RDKTV-35484-DeviceIdentification2.patch b/Tests/L2Tests/patches/RDKTV-35484-DeviceIdentification2.patch new file mode 100644 index 0000000000..4341168c5f --- /dev/null +++ b/Tests/L2Tests/patches/RDKTV-35484-DeviceIdentification2.patch @@ -0,0 +1,100 @@ +diff --git a/interfaces/IDeviceIdentification2.h b/interfaces/IDeviceIdentification2.h +new file mode 100644 +index 0000000..1317028 +--- /dev/null ++++ b/interfaces/IDeviceIdentification2.h +@@ -0,0 +1,49 @@ ++/* ++ * If not stated otherwise in this file or this component's LICENSE file the ++ * following copyright and licenses apply: ++ * ++ * Copyright 2024 Metrological ++ * ++ * 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 "Module.h" ++ ++namespace WPEFramework { ++ ++namespace Exchange { ++ ++ // @json 1.0.0 @uncompliant:collapsed @text:legacy_lowercase ++ struct EXTERNAL IDeviceIdentification2 : virtual public Core::IUnknown { ++ ++ enum { ID = ID_DEVICEIDENTIFICATION2 }; ++ ++ struct DeviceInfo { ++ string deviceID /* @brief Device ID (e.g. WPEuCfrLF45) */; ++ string firmwareVersion /* @brief Version of the device firmware (e.g. 1.0.0) */; ++ string chipset /* @brief Chipset used for this device (e.g. BCM2711) */; ++ }; ++ ++ // @property ++ // @text deviceidentification ++ // @brief Get device paltform specific information ++ // @retval ERROR_UNAVAILABLE Identification not availbale ++ virtual Core::hresult Identification(DeviceInfo& info /* @out */) const = 0; ++ ++ }; ++ ++} // namespace Exchange ++ ++} +diff --git a/jsonrpc/DeviceInfo.json b/jsonrpc/DeviceInfo.json +index 9a1be64..4bf2604 100644 +--- a/jsonrpc/DeviceInfo.json ++++ b/jsonrpc/DeviceInfo.json +@@ -529,6 +529,28 @@ + } + ] + }, ++ "chipset": { ++ "summary": "Chipset used for this device", ++ "readonly": true, ++ "params": { ++ "type": "object", ++ "properties": { ++ "chipset": { ++ "type": "string", ++ "example": "T962X3" ++ } ++ }, ++ "required": [ ++ "chipset" ++ ] ++ }, ++ "errors": [ ++ { ++ "description": "General error", ++ "$ref": "#/common/errors/general" ++ } ++ ] ++ }, + "modelid": { + "summary": "Device model number or SKU", + "readonly": true, +diff --git a/interfaces/Ids.h b/interfaces/Ids.h +index 70ce61d..e7108ce 100644 +--- a/interfaces/Ids.h ++++ b/interfaces/Ids.h +@@ -292,6 +292,7 @@ namespace Exchange { + ID_SYSTEMAUDIOPLAYER = ID_BROWSER+ 0x530, + ID_SYSTEMAUDIOPLAYER_NOTIFICATION = ID_SYSTEMAUDIOPLAYER + 1, + ++ ID_DEVICEIDENTIFICATION2, + }; + } + }