diff --git a/ActivityMonitor/ActivityMonitor.config b/ActivityMonitor/ActivityMonitor.config new file mode 100644 index 0000000000..5cf500c19d --- /dev/null +++ b/ActivityMonitor/ActivityMonitor.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "org.rdk.ActivityMonitor") diff --git a/ActivityMonitor/ActivityMonitor.cpp b/ActivityMonitor/ActivityMonitor.cpp new file mode 100644 index 0000000000..dac25dad54 --- /dev/null +++ b/ActivityMonitor/ActivityMonitor.cpp @@ -0,0 +1,979 @@ +/** +* 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 "ActivityMonitor.h" + +#include "utils.h" + + +#define ACTIVITY_MONITOR_METHOD_GET_APPLICATION_MEMORY_USAGE "getApplicationMemoryUsage" +#define ACTIVITY_MONITOR_METHOD_GET_ALL_MEMORY_USAGE "getAllMemoryUsage" +#define ACTIVITY_MONITOR_METHOD_ENABLE_MONITORING "enableMonitoring" +#define ACTIVITY_MONITOR_METHOD_DISABLE_MONITORING "disableMonitoring" + +#define ACTIVITY_MONITOR_EVT_ON_MEMORY_THRESHOLD "onMemoryThreshold" +#define ACTIVITY_MONITOR_EVT_ON_CPU_THRESHOLD "onCPUThreshold" + +#define VERSION_TXT_FILE "/version.txt" + +#define REGISTRY_FILENAME "/home/root/waylandregistryreceiver.conf" +#define REGISTRY_FILENAME_RNE "/home/root/waylandregistryrne.conf" +#define REGISTRY_FILENAME_DEV "/opt/waylandregistry.conf" + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(ActivityMonitor, 1, 0); + + ActivityMonitor* ActivityMonitor::_instance = nullptr; + + + struct AppConfig + { + AppConfig() + { + pid = memoryThresholdsMB = cpuThresholdPercent = cpuThresholdSeconds = 0; + state = STATE_NORMAL; + cpuUsage = 0; + memExceeded = cpuExceededPercent = 0; + eventSent = false; + } + + enum { + STATE_NORMAL, + STATE_EXCEEDED, + STATE_RECEDED, + }; + + unsigned int pid; + unsigned int memoryThresholdsMB; + unsigned int cpuThresholdPercent; + unsigned int cpuThresholdSeconds; + + int state; + long long unsigned int cpuUsage; + std::chrono::system_clock::time_point cpuThreshold; + unsigned int memExceeded; + unsigned int cpuExceededPercent; + bool eventSent; + }; + + struct MonitorParams + { + double memoryIntervalSeconds; + double cpuIntervalSeconds; + std::list config; + long long unsigned int totalCpuUsage; + std::chrono::system_clock::time_point lastMemCheck; + std::chrono::system_clock::time_point lastCpuCheck; + }; + + class MemoryInfo + { + public: + static bool isDevOrVBNImage(); + static void initRegistry(); + + static long long unsigned int getTotalCpuUsage(); + + static unsigned int parseLine(const char *line); + + static unsigned int getFreeMemory(); + static void readSmaps(const char *pid, unsigned int &pvtOut, unsigned int &sharedOut); + + static void getProcStat(const char *dirName, std::string &cmdName, unsigned int &ppid, bool calcCpu, long long unsigned int &cpuTicks); + static void getProcInfo(bool calcMem, bool calcCpu, std::vector &pidsOut, std::vector &cmdsOut, std::vector &memUsageOut, std::vector &cpuUsageOut); + + private: + static std::map registry; + }; + + std::map MemoryInfo::registry; + + + ActivityMonitor::ActivityMonitor() + : AbstractPlugin() + , m_monitorParams(NULL) + , m_stopMonitoring(false) + { + LOGINFO(); + ActivityMonitor::_instance = this; + + registerMethod(ACTIVITY_MONITOR_METHOD_GET_APPLICATION_MEMORY_USAGE, &ActivityMonitor::getApplicationMemoryUsage, this); + registerMethod(ACTIVITY_MONITOR_METHOD_GET_ALL_MEMORY_USAGE, &ActivityMonitor::getAllMemoryUsage, this); + registerMethod(ACTIVITY_MONITOR_METHOD_ENABLE_MONITORING, &ActivityMonitor::enableMonitoring, this); + registerMethod(ACTIVITY_MONITOR_METHOD_DISABLE_MONITORING, &ActivityMonitor::disableMonitoring, this); + } + + ActivityMonitor::~ActivityMonitor() + { + LOGINFO(); + ActivityMonitor::_instance = nullptr; + + if (m_monitor.joinable()) + m_monitor.join(); + + delete m_monitorParams; + } + + uint32_t ActivityMonitor::getApplicationMemoryUsage(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + if (parameters.HasLabel("pid")) + { + unsigned int pidToFind = 0; + getNumberParameter("pid", pidToFind); + if (pidToFind > 0) + { + std::vector pids; + std::vector cmds; + std::vector memUsage; + std::vector cpuUsage; + + MemoryInfo::getProcInfo(true, false, pids, cmds, memUsage, cpuUsage); + + for (unsigned int n = 0; n < pids.size(); n++) + { + if (pids[n] == pidToFind) + { + JsonObject h; + h["appPid"] = pidToFind; + h["appName"] = cmds[n]; + h["memoryMB"] = memUsage[n]; + + response["applicationMemory"] = h; + returnResponse(true); + } + } + } + } + + returnResponse(false); + } + + uint32_t ActivityMonitor::getAllMemoryUsage(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + response["freeMemoryMB"] = MemoryInfo::getFreeMemory(); + + JsonArray sl; + + std::vector pids; + std::vector cmds; + std::vector memUsage; + std::vector cpuUsage; + + MemoryInfo::getProcInfo(true, false, pids, cmds, memUsage, cpuUsage); + + for (unsigned int n = 0; n < pids.size(); n++) + { + JsonObject h; + + h["appPid"] = pids[n]; + h["appName"] = cmds[n]; + h["memoryMB"] = memUsage[n]; + + sl.Add(h); + } + + response["applicationMemory"] = sl; + + returnResponse(true); + } + + uint32_t ActivityMonitor::enableMonitoring(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + { + std::lock_guard lock(m_monitoringMutex); + m_stopMonitoring = true; + } + + if (m_monitor.joinable()) + { + LOGWARN("Terminating monitor thread"); + m_monitor.join(); + } + + JsonArray configArray = parameters["config"].Array(); + + if (0 == configArray.Length()) + { + LOGWARN("Got empty list of processes to monitor"); + returnResponse(false); + } + + float memoryIntervalSeconds = 0; + float cpuIntervalSeconds = 0; + + try + { + memoryIntervalSeconds = std::stof(parameters["memoryIntervalSeconds"] .String()); + cpuIntervalSeconds = std::stof(parameters["cpuIntervalSeconds"].String()); + } + catch (...) {} + + if (0 == memoryIntervalSeconds && 0 == cpuIntervalSeconds) + { + LOGWARN("Interval for both CPU and Memory usage monitoring can't be 0"); + returnResponse(false); + } + + delete m_monitorParams; + + m_monitorParams = new MonitorParams(); + + m_monitorParams->totalCpuUsage = 0; + + m_monitorParams->lastMemCheck = std::chrono::system_clock::now(); + m_monitorParams->lastCpuCheck = std::chrono::system_clock::now(); + + m_monitorParams->memoryIntervalSeconds = memoryIntervalSeconds; + m_monitorParams->cpuIntervalSeconds = cpuIntervalSeconds; + + JsonArray::Iterator index(configArray.Elements()); + + while (index.Next() == true) + { + if (Core::JSON::Variant::type::OBJECT == index.Current().Content()) + { + JsonObject m = index.Current().Object(); + + AppConfig conf; + + getNumberParameterObject(m, "appPid", conf.pid); + getNumberParameterObject(m, "memoryThresholdMB", conf.memoryThresholdsMB); + getNumberParameterObject(m, "cpuThresholdPercent", conf.cpuThresholdPercent); + getNumberParameterObject(m, "cpuThresholdSeconds", conf.cpuThresholdSeconds); + + + m_monitorParams->config.push_back(conf); + } + else + LOGWARN("Unexpected variant type"); + } + + if (m_monitor.joinable()) + m_monitor.join(); + + { + std::lock_guard lock(m_monitoringMutex); + m_stopMonitoring = false; + } + + m_monitor = std::thread(threadRun, this); + + returnResponse(true); + } + + uint32_t ActivityMonitor::disableMonitoring(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + { + std::lock_guard lock(m_monitoringMutex); + m_stopMonitoring = true; + } + + if (m_monitor.joinable()) + m_monitor.join(); + else + LOGWARN("Monitoring is already disabled"); + + delete m_monitorParams; + m_monitorParams = NULL; + + returnResponse(true); + } + + bool MemoryInfo::isDevOrVBNImage() + { + std::vector buf; + buf.resize(1024); + + FILE *f = fopen(VERSION_TXT_FILE, "r"); + if (!f) + { + LOGERR("Failed to open %s: %s", VERSION_TXT_FILE, strerror(errno)); + return false; + } + + if (!fgets(buf.data(), buf.size(), f)) + { + LOGERR("Failed to read from %s: %s", VERSION_TXT_FILE, strerror(errno)); + fclose(f); + return false; + } + + fclose(f); + + std::string s(buf.data()); + + size_t pos = s.find("imagename:"); + if (pos != std::string::npos) + { + s = s.substr(pos + strlen("imagename:")); + s = s.substr(0, s.find_first_of("\r\n")); + } + else + s = ""; + + return s.find("PROD") == std::string::npos && (s.find("DEV") != std::string::npos || s.find("VBN") != std::string::npos); + } + + void MemoryInfo::initRegistry() + { + const char *registryFilename = REGISTRY_FILENAME; + + if (0 == access(REGISTRY_FILENAME_DEV, R_OK) && isDevOrVBNImage()) + registryFilename = REGISTRY_FILENAME_DEV; + else if (0 == access(REGISTRY_FILENAME_RNE, R_OK)) + registryFilename = REGISTRY_FILENAME_RNE; + + JsonObject regObj; + + Core::File file; + file = registryFilename; + + LOGINFO("Loading registry from %s", registryFilename); + + file.Open(); + regObj.FromFile(file); + + file.Close(); + + if (regObj.HasLabel("waylandapps") && Core::JSON::Variant::type::ARRAY == regObj["waylandapps"].Content()) + { + JsonArray apps = regObj["waylandapps"].Array(); + JsonArray::Iterator index(apps.Elements()); + + int cnt = 0; + while (index.Next() == true) + { + if (Core::JSON::Variant::type::OBJECT == index.Current().Content()) + { + JsonObject appEntry = index.Current().Object(); + + std::string binary = appEntry["binary"].String(); + + if (binary.size() > 0 && binary[binary.size() - 1] == '%') + binary = binary.substr(0, binary.size() - 1); + + size_t li = binary.find_last_of('/'); + if (std::string::npos != li) + binary = binary.substr(li + 1, binary.size() - li - 1); + + registry[binary.c_str()] = appEntry["name"].String(); + cnt++; + } + else + LOGWARN("Unexpected variant type"); + } + + LOGINFO("Loaded registry, %d entries", registry.size()); + } + else + LOGERR("Didn't find registry data"); + } + + long long unsigned int MemoryInfo::getTotalCpuUsage() + { + FILE *f = fopen("/proc/stat", "r"); + + std::vector buf; + buf.resize(1024); + + if (NULL == fgets(buf.data(), buf.size(), f)) + { + LOGERR("Failed to read stat, buffer is too small"); + return 0; + } + + fclose(f); + + long long unsigned int user = 0, nice = 0, system = 0, idle = 0; + + int vc = sscanf(buf.data(), "%*s %llu %llu %llu %llu", &user, &nice, &system, &idle); + if (4 != vc) + LOGERR("Failed to parse /proc/stat, number of items matched: %d", vc); + + return user + nice + system + idle; + } + + unsigned int MemoryInfo::parseLine(const char *line) + { + std::string s(line); + + unsigned int val; + + size_t begin = s.find_first_of("0123456789"); + size_t end = std::string::npos; + if (std::string::npos != begin) + end = s.find_first_not_of("0123456789", begin); + + if (std::string::npos != begin && std::string::npos != end) + { + s = s.substr(begin, end); + val = strtoul(s.c_str(), NULL, 10); + return val; + } + else + LOGERR("Failed to parse value from %s", line); + + return 0; + } + + unsigned int MemoryInfo::getFreeMemory() + { + FILE *f = fopen("/proc/meminfo", "r"); + if (NULL == f) + { + LOGERR("Failed to open /proc/meminfo:%s", strerror(errno)); + return 0; + } + + std::vector buf; + buf.resize(1024); + + unsigned int total = 0; + + while (fgets(buf.data(), buf.size(), f)) + { + if (strstr(buf.data(), "MemFree:") == buf.data() || strstr(buf.data(), "Buffers:") == buf.data() || strstr(buf.data(), "Cached:") == buf.data()) + total += parseLine(buf.data()); + } + + fclose(f); + + return total / 1024; // From KB to MB + } + + void MemoryInfo::readSmaps(const char *pid, unsigned int &pvtOut, unsigned int &sharedOut) + { + std::string smapsName = "/proc/"; + smapsName += pid; + smapsName += "/smaps"; + + FILE *f = fopen(smapsName.c_str(), "r"); + if (NULL == f) + { + pvtOut = sharedOut = 0; + return; + } + + std::vector buf; + buf.resize(1024); + + size_t shared = 0; + size_t pvt = 0; + size_t pss = 0; + bool withPss = false; + + while (fgets(buf.data(), buf.size(), f)) + { + if (strstr(buf.data(), "Shared") == buf.data()) + { + shared += parseLine(buf.data()); + } + else if (strstr(buf.data(), "Private") == buf.data()) + { + pvt += parseLine(buf.data()); + } + else if (strstr(buf.data(), "Pss") == buf.data()) + { + withPss = true; + pss += parseLine(buf.data()); + } + } + + fclose(f); + + if (withPss) + shared = pss - pvt; + + pvtOut = pvt; + sharedOut = shared; + } + + void MemoryInfo::getProcStat(const char *dirName, std::string &cmdName, unsigned int &ppid, bool calcCpu, long long unsigned int &cpuTicks) + { + std::string statName = "/proc/"; + statName += dirName; + statName += "/stat"; + + std::vector buf; + buf.resize(1024); + + size_t r = 0; + FILE *f = fopen(statName.c_str(), "r"); + if (f) + { + r = fread(buf.data(), 1, buf.size(), f); + if (buf.size() == r) + { + LOGERR("Failed to read stat, buffer is too small"); + } + fclose(f); + } + + std::string stat(buf.data(), r); + + std::size_t p1 = stat.find_first_of("("); + std::size_t p2 = stat.find_first_of(")"); + if (std::string::npos == p1 || std::string::npos == p2) + { + //LOGINFO("Failed to parse command name from stat file '%s', '%s'", statName.c_str(), stat.c_str()); + return; + } + + cmdName = stat.substr(p1 + 1, p2 - p1 - 1); + + size_t pos = p2, cnt = 0; + + while ((pos = stat.find_first_of(" ", pos + 1)) != std::string::npos) + { + cnt++; + if (2 == cnt) + break; + } + + ppid = 0; + + int vc = sscanf(buf.data() + pos, "%d", &ppid); + if (1 != vc) + LOGERR("Failed to parse parent pid from '%s'", stat.c_str()); + + if (calcCpu) + { + while ((pos = stat.find_first_of(" ", pos + 1)) != std::string::npos) + { + cnt++; + if (12 == cnt) + break; + } + + long long unsigned int utime = 0, stime = 0, cutime = 0, cstime = 0; + + vc = sscanf(buf.data() + pos, + "%llu %llu " //utime, stime + "%llu %llu ", //cutime, cstime + &utime, &stime, &cutime, &cstime); + if (4 != vc) + { + LOGERR("Failed to parse parent cpu ticks from '%s', number of items matched: %d", stat.c_str(), vc); + } + + cpuTicks = utime + stime + cutime + cstime; + } + + } + + void MemoryInfo::getProcInfo(bool calcMem, bool calcCpu, std::vector &pidsOut, std::vector &cmdsOut, std::vector &memUsageOut, std::vector &cpuUsageOut) + { + if (0 == registry.size()) + MemoryInfo::initRegistry(); + + if (!calcMem && !calcCpu) + { + LOGERR("Nothing to do"); + return; + } + + std::vector cmds; + std::vector pids; + std::vector ppids; + std::vector cpuUsage; + + DIR *d = opendir("/proc"); + + struct dirent *de; + + while ((de = readdir(d))) + { + if (0 == de->d_name[0]) + continue; + + char *end; + pid_t pid = strtoul(de->d_name, &end, 10); + if (0 != *end) + continue; + + std::string cmdName; + unsigned int ppid = 0; + long long unsigned int cpuTicks = 0; + + MemoryInfo::getProcStat(de->d_name, cmdName, ppid, calcCpu, cpuTicks); + + cmds.push_back(cmdName); + pids.push_back(pid); + ppids.push_back(ppid); + cpuUsage.push_back(cpuTicks); + } + + std::map pidMap; + for (unsigned int n = 0; n < pids.size(); n++) + pidMap[pids[n]] = n; + + std::map > cmdMap; + + for (unsigned int n = 0; n < cmds.size(); n++) + { + unsigned int lastIdx = cmds.size(); + + for (unsigned int pid = pids[n],idx,cnt = 0; pid != 0; pid = ppids[idx],cnt++) + { + idx = pidMap[pid]; + std::string cmd = cmds[idx]; + + if (registry.find(cmd) != registry.end()) + { + lastIdx = idx; + } + + if (cnt >= 100) + { + LOGERR("Too many iterations for process tree"); + lastIdx = cmds.size(); + break; + } + } + + if (lastIdx < cmds.size()) + cmdMap[lastIdx].push_back(n); + } + + std::map cmdCount; + if (calcMem) + { + for (unsigned int n = 0; n < cmds.size(); n++) + cmdCount[cmds[n]]++; + } + + for (std::map >::const_iterator it = cmdMap.cbegin(); it != cmdMap.cend(); it++) + { + unsigned int memUsage = 0; + if (calcMem) + { + for (unsigned int n = 0; n < it->second.size(); n++) + { + char s[256]; + snprintf(s, sizeof(s), "%u", pids[it->second[n]]); + + unsigned int pvt, shared; + + readSmaps(s, pvt, shared); + unsigned int cnt = cmdCount[cmds[it->second[n]]]; + if (0 == cnt) + { + LOGERR("Commnd count for %s was 0", cmds[n].c_str()); + cnt = 1; + } + unsigned int usage = (pvt + shared / cnt) / 1024; + + if (it->first != it->second[n]) + { + pidsOut.push_back(pids[it->second[n]]); + cmdsOut.push_back(cmds[it->second[n]]); + memUsageOut.push_back(usage); + } + + memUsage += usage; + } + } + + long long unsigned int cpu_usage = 0; + if (calcCpu) + { + for (unsigned int n = 0; n < it->second.size(); n++) + { + if (it->first != it->second[n]) + { + if (!calcMem) // If calcMem was disabled, pid and cmd should be added here. + { + pidsOut.push_back(pids[it->second[n]]); + cmdsOut.push_back(cmds[it->second[n]]); + } + + cpuUsageOut.push_back(cpuUsage[it->second[n]]); + } + cpu_usage += cpuUsage[it->second[n]]; + } + } + + pidsOut.push_back(pids[it->first]); + cmdsOut.push_back(cmds[it->first]); + memUsageOut.push_back(memUsage); + cpuUsageOut.push_back(cpu_usage); + } + } + + void ActivityMonitor::threadRun(ActivityMonitor *am) + { + am->monitoring(); + } + + void ActivityMonitor::monitoring() + { + if (0 == m_monitorParams->config.size()) + { + LOGERR("Empty app list to monitor"); + return; + } + + while (1) + { + { + std::lock_guard lock(m_monitoringMutex); + + if (m_stopMonitoring) + break; + } + + std::chrono::duration elapsed = std::chrono::system_clock::now() - m_monitorParams->lastMemCheck; + bool memCheck = m_monitorParams->memoryIntervalSeconds > 0 && elapsed.count() > m_monitorParams->memoryIntervalSeconds - 0.01; + + elapsed = std::chrono::system_clock::now() - m_monitorParams->lastCpuCheck; + bool cpuCheck = m_monitorParams->cpuIntervalSeconds > 0 && elapsed.count() > m_monitorParams->cpuIntervalSeconds - 0.01; + + std::vector pids; + std::vector cmds; + std::vector memUsage; + std::vector cpuUsage; + + MemoryInfo::getProcInfo(memCheck, cpuCheck, pids, cmds, memUsage, cpuUsage); + + long long unsigned int totalCpuUsage = 0; + + if (cpuCheck) + { + totalCpuUsage = MemoryInfo::getTotalCpuUsage(); + } + + for (std::list ::iterator it = m_monitorParams->config.begin(); it != m_monitorParams->config.end(); it++) + { + unsigned int pid = it->pid; + unsigned int memoryUsed = 0; + + if (memCheck) + { + for (unsigned int n = 0; n < pids.size(); n++) + { + if (pids[n] == pid) + { + memoryUsed = memUsage[n]; + break; + } + } + + if (0 == memoryUsed) + { + LOGERR("Failed to determine memory usage for %u", pid); + } + + if (memoryUsed >= it->memoryThresholdsMB) + { + if (0 == it->memExceeded) + { + it->memExceeded = memoryUsed; + + JsonObject memResult; + memResult["appPid"] = pid; + memResult["threshold"] = "exceeded"; + memResult["memoryMB"] = memoryUsed; + + LOGWARN("MemoryThreshold event appPid = %u, threshold = exceeded, memoryMB = %u", pid, memoryUsed); + onMemoryThresholdOccurred(memResult); + } + } + else + { + if (0 != it->memExceeded && memoryUsed < it->memExceeded - it->memExceeded / 20) + { + it->memExceeded = 0; + + JsonObject memResult; + memResult["appPid"] = pid; + memResult["threshold"] = "receded"; + memResult["memoryMB"] = memoryUsed; + + LOGWARN("MemoryThreshold event appPid = %u, threshold = receded, memoryMB = %u", pid, memoryUsed); + + onMemoryThresholdOccurred(memResult); + } + + } + } + + if (cpuCheck) + { + long long unsigned int usage = 0; + + if (0 != m_monitorParams->totalCpuUsage) + { + for (unsigned int n = 0; n < pids.size(); n++) + { + if (pids[n] == pid) + { + usage = cpuUsage[n]; + break; + } + } + + if (0 != it->cpuUsage) + { + unsigned int percents = 0; + if (usage < it->cpuUsage) + { + LOGERR("Wrong values for previous and current cpu usage %llu:%llu for pid: %u", usage, it->cpuUsage, pid); + } + else if (totalCpuUsage <= m_monitorParams->totalCpuUsage) + { + LOGERR("Wrong values for previous and current total cpu ticks %llu:%llu", totalCpuUsage, m_monitorParams->totalCpuUsage); + } + else + { + percents = 100 * ( usage - it->cpuUsage) / (totalCpuUsage - m_monitorParams->totalCpuUsage); + } + + if (percents >= it->cpuThresholdPercent) + { + if (AppConfig::STATE_NORMAL == it->state) + { + it->state = AppConfig::STATE_EXCEEDED; + it->cpuThreshold = std::chrono::system_clock::now(); + it->cpuExceededPercent = percents; + it->eventSent = false; + } + else if (AppConfig::STATE_EXCEEDED == it->state) + { + std::chrono::duration elapsed = std::chrono::system_clock::now() - it->cpuThreshold; + + if (elapsed.count() >= it->cpuThresholdSeconds && !it->eventSent) + { + JsonObject cpuResult; + cpuResult["appPid"] = pid; + cpuResult["threshold"] = "exceeded"; + cpuResult["cpuPercent"] = percents; + + LOGWARN("CPUThreshold event appPid = %u, threshold = exceeded, cpuPercent = %u", pid, percents); + + onCPUThresholdOccurred(cpuResult); + + it->eventSent = true; + } + } + else if (AppConfig::STATE_RECEDED == it->state) + { + it->state = AppConfig::STATE_EXCEEDED; + } + } + else + { + if (AppConfig::STATE_EXCEEDED == it->state) + { + + if (!it->eventSent) + { + it->state = AppConfig::STATE_NORMAL; + } + else if (percents < it->cpuExceededPercent - it->cpuExceededPercent / 20) + { + it->state = AppConfig::STATE_RECEDED; + it->cpuThreshold = std::chrono::system_clock::now(); + } + + } + else if (AppConfig::STATE_RECEDED == it->state) + { + if (percents < it->cpuExceededPercent - it->cpuExceededPercent / 20) + { + std::chrono::duration elapsed = std::chrono::system_clock::now() - it->cpuThreshold; + + if (elapsed.count() >= it->cpuThresholdSeconds) + { + JsonObject cpuResult; + cpuResult["type"] = "CPU"; + cpuResult["appPid"] = pid; + cpuResult["threshold"] = "receded"; + cpuResult["cpuPercent"] = percents; + + LOGWARN("CPUThreshold event appPid = %u, threshold = receded, cpuPercent = %u", pid, percents); + + onCPUThresholdOccurred(cpuResult); + it->state = AppConfig::STATE_NORMAL; + } + } + else + { + it->state = AppConfig::STATE_EXCEEDED; + } + + } + } + } + } + + it->cpuUsage = usage; + } + } + + if (memCheck) + m_monitorParams->lastMemCheck = std::chrono::system_clock::now(); + + if (cpuCheck) + { + m_monitorParams->lastCpuCheck = std::chrono::system_clock::now(); + m_monitorParams->totalCpuUsage = totalCpuUsage; + } + + elapsed = std::chrono::system_clock::now() - m_monitorParams->lastMemCheck; + double sleepTime = m_monitorParams->memoryIntervalSeconds > 0 ? m_monitorParams->memoryIntervalSeconds - elapsed.count() : 10000; + + elapsed = std::chrono::system_clock::now() - m_monitorParams->lastCpuCheck; + if (m_monitorParams->cpuIntervalSeconds > 0 && m_monitorParams->cpuIntervalSeconds - elapsed.count() < sleepTime) + sleepTime = m_monitorParams->cpuIntervalSeconds - elapsed.count(); + + if (sleepTime < 0.01) + { + LOGERR("SleepTime is too low, using 0.01 seconds"); + sleepTime = 0.01; + } + + usleep(int(sleepTime * 1000000)); + } + } + + void ActivityMonitor::onMemoryThresholdOccurred(const JsonObject& result) + { + sendNotify(ACTIVITY_MONITOR_EVT_ON_MEMORY_THRESHOLD, result); + } + + void ActivityMonitor::onCPUThresholdOccurred(const JsonObject& result) + { + sendNotify(ACTIVITY_MONITOR_EVT_ON_CPU_THRESHOLD, result); + } + + } // namespace Plugin +} // namespace WPEFramework + + diff --git a/ActivityMonitor/ActivityMonitor.h b/ActivityMonitor/ActivityMonitor.h new file mode 100644 index 0000000000..21f9516089 --- /dev/null +++ b/ActivityMonitor/ActivityMonitor.h @@ -0,0 +1,85 @@ +/** +* 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 "Module.h" +#include "utils.h" + +#include "AbstractPlugin.h" + +namespace WPEFramework { + + namespace Plugin { + + struct MonitorParams; + + // 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 ActivityMonitor : public AbstractPlugin { + private: + + // We do not allow this plugin to be copied !! + ActivityMonitor(const ActivityMonitor&) = delete; + ActivityMonitor& operator=(const ActivityMonitor&) = delete; + + //Begin methods + uint32_t getApplicationMemoryUsage(const JsonObject& parameters, JsonObject& response); + uint32_t getAllMemoryUsage(const JsonObject& parameters, JsonObject& response); + uint32_t enableMonitoring(const JsonObject& parameters, JsonObject& response); + uint32_t disableMonitoring(const JsonObject& parameters, JsonObject& response); + //End methods + + //Begin events + void onMemoryThresholdOccurred(const JsonObject& result); + void onCPUThresholdOccurred(const JsonObject& result); + //End events + + public: + ActivityMonitor(); + virtual ~ActivityMonitor(); + + public: + static ActivityMonitor* _instance; + private: + + static void threadRun(ActivityMonitor *am); + void monitoring(); + + std::thread m_monitor; + std::mutex m_monitoringMutex; + + MonitorParams *m_monitorParams; + bool m_stopMonitoring; + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/ActivityMonitor/CMakeLists.txt b/ActivityMonitor/CMakeLists.txt new file mode 100644 index 0000000000..78f8094ac1 --- /dev/null +++ b/ActivityMonitor/CMakeLists.txt @@ -0,0 +1,22 @@ +set(PLUGIN_NAME ActivityMonitor) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + ActivityMonitor.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) + +target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES}) + + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/ActivityMonitor/Module.cpp b/ActivityMonitor/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/ActivityMonitor/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/ActivityMonitor/Module.h b/ActivityMonitor/Module.h new file mode 100644 index 0000000000..86b2d5b1c2 --- /dev/null +++ b/ActivityMonitor/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 CoPilot +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/ActivityMonitor/README.md b/ActivityMonitor/README.md new file mode 100644 index 0000000000..df7dcfda55 --- /dev/null +++ b/ActivityMonitor/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": "ActivityMonitor.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..2e8f3d1137 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,138 @@ +cmake_minimum_required(VERSION 3.3) + +find_package(WPEFramework) + +# All packages that did not deliver a CMake Find script (and some deprecated scripts that need to be removed) +# are located in the cmake directory. Include it in the search. +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/") + +include(services.cmake) + +option(PLUGIN_DISPLAYSETTINGS "Include DisplaySettings plugin" ON) +option(PLUGIN_TTSSETTINGS "Include TTSSettings plugin" ON) +option(PLUGIN_TTSRESOURCE "Include TTSResource Plugin plugin" ON) +option(PLUGIN_LOGGING_PREFERENCES "Include LoggingPreferences plugin" ON) +option(PLUGIN_USER_PREFERENCES "Include UserPreferences plugin" ON) +option(PLUGIN_PROXIES "Include Proxies plugin" ON) +option(PLUGIN_HOMENETWORKING "Include HomeNetworking plugin" ON) + + +# Library installation section +string(TOLOWER ${NAMESPACE} STORAGE_DIRECTORY) + +# for writing pc and config files +include(CmakeHelperFunctions) + +get_directory_property(SEVICES_DEFINES COMPILE_DEFINITIONS) + +if(PLUGIN_DISPLAYSETTINGS) + add_subdirectory(DisplaySettings) +endif() + +if(PLUGIN_VREXMANAGER) + add_subdirectory(VrexManager) +endif() + +if (NOT OEM_VENDOR_SAMSUNG) # Disabling these service until image oversize issue is fixed on Samsung Xg2v2 + if(PLUGIN_HOMENETWORKING) + add_subdirectory(HomeNetworking) + endif() + + if(PLUGIN_LOGGING_PREFERENCES) + add_subdirectory(LoggingPreferences) + endif() + + if(PLUGIN_USER_PREFERENCES) + add_subdirectory(UserPreferences) + endif() + + if(PLUGIN_PROXIES) + add_subdirectory(Proxies) + endif() + + if(SEVICES_DEFINES MATCHES "HAS_FRONT_PANEL") + add_subdirectory(FrontPanel) + endif() + + if(HAS_API_COPILOT) + add_subdirectory(CoPilot) + endif() + + if(HAS_API_STORAGE_MANAGER) + add_subdirectory(StorageManager) + endif() + + if(DEVICE_PROVISIONING) + add_subdirectory(DeviceProvisioning) + endif() + + if(HAS_API_FRAME_RATE) + add_subdirectory(FrameRate) + endif() + + if(HAS_ACTIVITY_MONITOR) + add_subdirectory(ActivityMonitor) + endif() + + if(WAREHOUSE_API) + add_subdirectory(Warehouse) + endif() + + # if(HAS_API_HDMI_CEC) + # add_subdirectory(HdmiCec) + # endif() + + if (HAS_API_DEVICEDIAGNOSTICS) + add_subdirectory(DeviceDiagnostics) + endif() + + if (ENABLE_HDCP_PROFILE) + add_subdirectory(HdcpProfile) + endif() + + if (HAS_API_HDMI_INPUT) + add_subdirectory(HdmiInput) + endif() + + if (HAS_TIMER) + add_subdirectory(Timer) + endif() + + if(SLEEP_TIMER) + add_subdirectory(SleepTimer) + endif() + + if(PLUGIN_TTSSETTINGS) + add_subdirectory(TTSSettings) + endif() + + if(PLUGIN_TTSRESOURCE) + add_subdirectory(TTSResource) + endif() + + if(HAS_STATE_OBSERVER) + add_subdirectory(StateObserver) + endif() + +endif() + +if(WPEFRAMEWORK_CREATE_IPKG_TARGETS) + set(CPACK_GENERATOR "DEB") + set(CPACK_DEB_COMPONENT_INSTALL ON) + set(CPACK_COMPONENTS_GROUPING IGNORE) + + set(CPACK_DEBIAN_PACKAGE_NAME "${WPEFRAMEWORK_PLUGINS_OPKG_NAME}") + set(CPACK_DEBIAN_PACKAGE_VERSION "${WPEFRAMEWORK_PLUGINS_OPKG_VERSION}") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${WPEFRAMEWORK_PLUGINS_OPKG_ARCHITECTURE}") + set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${WPEFRAMEWORK_PLUGINS_OPKG_MAINTAINER}") + set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${WPEFRAMEWORK_PLUGINS_OPKG_DESCRIPTION}") + set(CPACK_PACKAGE_FILE_NAME "${WPEFRAMEWORK_PLUGINS_OPKG_FILE_NAME}") + + # list of components from which packages will be generated + set(CPACK_COMPONENTS_ALL + ${NAMESPACE}WebKitBrowser + WPEInjectedBundle + ) + + include(CPack) +endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..161c092843 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +Contributing +============ + +If you would like to contribute code to this project you can do so through GitHub by forking the repository and sending a pull request. Before RDK accepts your code into the project you must sign the RDK Contributor License Agreement (CLA). \ No newline at end of file diff --git a/COPYING b/COPYING new file mode 120000 index 0000000000..7a694c9699 --- /dev/null +++ b/COPYING @@ -0,0 +1 @@ +LICENSE \ No newline at end of file diff --git a/CoPilot/CMakeLists.txt b/CoPilot/CMakeLists.txt new file mode 100644 index 0000000000..797039adc0 --- /dev/null +++ b/CoPilot/CMakeLists.txt @@ -0,0 +1,29 @@ +set(PLUGIN_NAME CoPilot) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + CoPilot.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +find_package(IARMBus) + +target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) + +#target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) +#target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${DS_LIBRARIES}) + +target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES}) + +#target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) + + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/CoPilot/CoPilot.config b/CoPilot/CoPilot.config new file mode 100644 index 0000000000..4f7159d7dc --- /dev/null +++ b/CoPilot/CoPilot.config @@ -0,0 +1,3 @@ +set (autostart false) +set (preconditions Platform) +set (callsign "com.comcast.CoPilot") diff --git a/CoPilot/CoPilot.cpp b/CoPilot/CoPilot.cpp new file mode 100644 index 0000000000..dd3c0c5e79 --- /dev/null +++ b/CoPilot/CoPilot.cpp @@ -0,0 +1,241 @@ +/** +* 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 "CoPilot.h" + +#include + +#include "libIBus.h" +#include "sysMgr.h" + +#include "utils.h" + +#define SERVICE_NAME "CoPilotService" + +#define COPILOT_METHOD_TERMINATE "terminate" +#define COPILOT_METHOD_GET_STATE "getState" +#define COPILOT_EVT_ON_STATE_CHANGE "onStateChange" + +#define DEVICE_PROPERTIES "/etc/device.properties" + +#define VNC_MIPSEL "vnc-Comcast-mipsel" +#define VNC_X86 "vnc-Comcast-x86" +#define VNC_ARM "vnc-Comcast-armcortex" + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(CoPilot, 1, 0); + + CoPilot* CoPilot::_instance = nullptr; + + CoPilot::CoPilot() + : AbstractPlugin() + { + LOGINFO(); + CoPilot::_instance = this; + + registerMethod(COPILOT_METHOD_TERMINATE, &CoPilot::terminateWrapper, this); + registerMethod(COPILOT_METHOD_GET_STATE, &CoPilot::getStateWrapper, this); + } + + CoPilot::~CoPilot() + { + LOGINFO(); + CoPilot::_instance = nullptr; + + if (m_terminator.joinable()) + m_terminator.join(); + } + + void CoPilot::threadRun(CoPilot *coPilot) + { + coPilot->terminate(); + } + + uint32_t CoPilot::terminateWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + LOGWARN("Received request to terminate CoPilot"); + + // asynchronously + if (m_terminator.joinable()) + m_terminator.join(); + + m_terminator = std::thread(threadRun, this); + + returnResponse(true); + } + + void CoPilot::terminate() + { + const char *processName = getVncName(); + bool firstTry = true; + int time = 0; + const int delay = 500; + const int timeToHardTerminate = 5000; + do { + std::string checkScript = "pgrep -f "; + checkScript += processName; + + int exitStatus = runScript(checkScript.c_str()); + + if (exitStatus != 0) + { + LOGINFO("%s is not running", processName); + break; + } + + LOGWARN("terminating %s", processName); + + if (firstTry) + stateChanged(CopilotStateTerminating); + else + usleep(delay * 1000); + + std::string killScript = "pkill "; + killScript += time < timeToHardTerminate ? "" : "-9 "; + killScript += "-f "; + killScript += processName; + + exitStatus = runScript(killScript.c_str()); + + if (exitStatus != 0) + { + LOGINFO("%s did not terminate (is it running?)", processName); + } + else + { + LOGINFO("terminated %s", processName); + } + + LOGINFO("elapsed %d ms", time); + + firstTry = false; + time += delay; + } while (true); + stateChanged(CopilotStateUninitialized); + } + + /** + * @brief Gets the brightness of the specified LED. + * + * @param[in] argList List of arguments (Not used). + * + * @return Returns a ServiceParams object containing brightness value and function result. + * @ingroup SERVMGR_CoPilot_API + */ + uint32_t CoPilot::getStateWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + uint32_t state = getState(); + response["state"] = state; + returnResponse(true); + } + + CoPilot::CopilotState CoPilot::getState() + { + CopilotState state; + + // synchronously + const char *processName = getVncName(); + std::string script = "pgrep -f "; + script += processName; + int exitStatus = runScript(script.c_str()); + if (exitStatus != 0) + { + LOGINFO("%s is not running", processName); + state = CopilotStateUninitialized; + } + else + { + LOGINFO("%s is running", processName); + state = CopilotStateInProgress; + } + return state; + } + + int CoPilot::runScript(const char *script) + { + IARM_Bus_SYSMgr_RunScript_t runScriptParam; + runScriptParam.return_value = -1; + strcpy(runScriptParam.script_path, script); + IARM_Bus_Call(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_API_RunScript, &runScriptParam, sizeof(runScriptParam)); + + int returnValue = runScriptParam.return_value; + int exitStatus = returnValue == -1 ? -1 : WEXITSTATUS(returnValue); + + LOGWARN("script '%s' exit status: %d", script, exitStatus); + return exitStatus; + } + + + const char *CoPilot::getVncName() + { + const char *vncName = VNC_MIPSEL; + + FILE *f = fopen(DEVICE_PROPERTIES, "r"); + if (NULL == f) + { + LOGERR("Failed to open %s:%s", DEVICE_PROPERTIES, strerror(errno)); + return vncName; + } + + std::vector buf; + buf.resize(1024); + + while (fgets(buf.data(), buf.size(), f)) + { + std::string line(buf.data()); + if (line.find("CPU_ARCH") != std::string::npos) + { + std::size_t eq = line.find_first_of("="); + if (std::string::npos != eq) + { + if (line.find("mipsel", eq) != std::string::npos) + vncName = VNC_MIPSEL; + if (line.find("x86", eq) != std::string::npos) + vncName = VNC_X86; + if (line.find("ARM", eq) != std::string::npos) + vncName = VNC_ARM; + } + + break; + } + } + + fclose(f); + + return vncName; + } + + void CoPilot::stateChanged(CopilotState state) + { + LOGINFO(); + + JsonObject params; + params["state"] = (uint32_t) state; + sendNotify(COPILOT_EVT_ON_STATE_CHANGE, params); + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/CoPilot/CoPilot.h b/CoPilot/CoPilot.h new file mode 100644 index 0000000000..d49902dffe --- /dev/null +++ b/CoPilot/CoPilot.h @@ -0,0 +1,87 @@ +/** +* 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 "Module.h" +#include "utils.h" + +#include "AbstractPlugin.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 CoPilot : public AbstractPlugin { + private: + + enum CopilotState + { + CopilotStateUninitialized = 0, + CopilotStateInProgress = 1, + CopilotStateTerminating = 2, + }; + + // We do not allow this plugin to be copied !! + CoPilot(const CoPilot&) = delete; + CoPilot& operator=(const CoPilot&) = delete; + + CopilotState getState(); + + static int runScript(const char *script); + static const char *getVncName(); + + //Begin methods + uint32_t terminateWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getStateWrapper(const JsonObject& parameters, JsonObject& response); + //End methods + + //Begin events + void stateChanged(CopilotState state); + //End events + + public: + CoPilot(); + virtual ~CoPilot(); + + void terminate(); + + public: + static CoPilot* _instance; + private: + static void threadRun(CoPilot *coPilot); + + std::thread m_terminator; + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/CoPilot/CoPilot.json b/CoPilot/CoPilot.json new file mode 100644 index 0000000000..b5043b76f8 --- /dev/null +++ b/CoPilot/CoPilot.json @@ -0,0 +1,8 @@ +{ + "locator":"libWPEFrameworkCoPilot.so", + "classname":"CoPilot", + "precondition":[ + "Platform" + ], + "autostart":true +} \ No newline at end of file diff --git a/CoPilot/Module.cpp b/CoPilot/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/CoPilot/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/CoPilot/Module.h b/CoPilot/Module.h new file mode 100644 index 0000000000..86b2d5b1c2 --- /dev/null +++ b/CoPilot/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 CoPilot +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/CoPilot/README.md b/CoPilot/README.md new file mode 100644 index 0000000000..a2b2ce3228 --- /dev/null +++ b/CoPilot/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": "CoPilot.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/CoPilot/cmake/FindIARMBus.cmake b/CoPilot/cmake/FindIARMBus.cmake new file mode 100644 index 0000000000..6f8986c826 --- /dev/null +++ b/CoPilot/cmake/FindIARMBus.cmake @@ -0,0 +1,33 @@ +# - 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(IARMBUS_INCLUDE_DIRS NAMES libIARM.h PATH_SUFFIXES rdk/iarmbus) +#find_path(IARMIR_INCLUDE_DIRS NAMES irMgr.h PATH_SUFFIXES rdk/iarmmgrs/ir) +find_path(IARMIR_INCLUDE_DIRS NAMES sysMgr.h PATH_SUFFIXES rdk/iarmmgrs/sysmgr) +find_path(SYSMGR_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") + + +if (DS_FOUND) +endif (DS_FOUND) + +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/DeviceDiagnostics/CMakeLists.txt b/DeviceDiagnostics/CMakeLists.txt new file mode 100644 index 0000000000..e5d01a5004 --- /dev/null +++ b/DeviceDiagnostics/CMakeLists.txt @@ -0,0 +1,23 @@ +set(PLUGIN_NAME DeviceDiagnostics) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + DeviceDiagnostics.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +find_package(Curl) + +target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) + +target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${CURL_LIBRARY}) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/DeviceDiagnostics/DeviceDiagnostics.config b/DeviceDiagnostics/DeviceDiagnostics.config new file mode 100644 index 0000000000..9e9f9ffe2f --- /dev/null +++ b/DeviceDiagnostics/DeviceDiagnostics.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "org.rdk.DeviceDiagnostics") diff --git a/DeviceDiagnostics/DeviceDiagnostics.cpp b/DeviceDiagnostics/DeviceDiagnostics.cpp new file mode 100644 index 0000000000..1a3eb86f1a --- /dev/null +++ b/DeviceDiagnostics/DeviceDiagnostics.cpp @@ -0,0 +1,152 @@ +/** +* 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 "DeviceDiagnostics.h" + +#include + +#include "utils.h" + +#define DEVICE_DIAGNOSTICS_METHOD_NAME_GET_CONFIGURATION "getConfiguration" + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(DeviceDiagnostics, 1, 0); + + DeviceDiagnostics* DeviceDiagnostics::_instance = nullptr; + + const int curlTimeoutInSeconds = 30; + + static size_t writeCurlResponse(void *ptr, size_t size, size_t nmemb, std::string stream) + { + size_t realsize = size * nmemb; + std::string temp(static_cast(ptr), realsize); + stream.append(temp); + return realsize; + } + + DeviceDiagnostics::DeviceDiagnostics() + : AbstractPlugin() + { + LOGINFO(); + DeviceDiagnostics::_instance = this; + + registerMethod(DEVICE_DIAGNOSTICS_METHOD_NAME_GET_CONFIGURATION, &DeviceDiagnostics::getConfigurationWrapper, this); + } + + DeviceDiagnostics::~DeviceDiagnostics() + { + LOGINFO(); + DeviceDiagnostics::_instance = nullptr; + } + + uint32_t DeviceDiagnostics::getConfigurationWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + JsonArray names = parameters["names"].Array(); + + JsonObject requestParams; + JsonArray namePairs; + + JsonArray::Iterator index(names.Elements()); + + while (index.Next() == true) + { + if (Core::JSON::Variant::type::STRING == index.Current().Content()) + { + //JSON::String s = index.Current().String(); + JsonObject o; + o["name"] = index.Current().String(); + namePairs.Add(o); + } + else + LOGWARN("Unexpected variant type"); + } + + requestParams["paramList"] = namePairs; + + string json; + requestParams.ToString(json); + + if (0 == getConfiguration(json, response)) + returnResponse(true); + + returnResponse(false); + } + + int DeviceDiagnostics::getConfiguration(const std::string& postData, JsonObject& out) + { + LOGINFO("%s",__FUNCTION__); + + JsonObject DeviceDiagnosticsResult; + int result = -1; + + long http_code = 0; + std::string response; + CURL *curl_handle = NULL; + CURLcode res = CURLE_OK; + curl_handle = curl_easy_init(); + + LOGINFO("data: %s", postData.c_str()); + + if (curl_handle) { + + curl_easy_setopt(curl_handle, CURLOPT_URL, "http://127.0.0.1:10999"); + curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, postData.c_str()); + curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, postData.size()); + curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); //when redirected, follow the redirections + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writeCurlResponse); + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &response); + curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, curlTimeoutInSeconds); + + res = curl_easy_perform(curl_handle); + curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_code); + + LOGWARN("Perfomed curl call : %d http response code: %ld", res, http_code); + curl_easy_cleanup(curl_handle); + } + else { + LOGWARN("Could not perform curl "); + } + + if (res == CURLE_OK && (http_code == 0 || http_code == 200)) + { + LOGWARN("curl Response: %s", response.c_str()); + + JsonObject jsonHash; + jsonHash.FromString(response); + + if (jsonHash.HasLabel("paramList")) + { + LOGWARN("key paramList present"); + out["paramList"] = jsonHash["paramList"]; + result = 0; + } + } + return result; + } + + + } // namespace Plugin +} // namespace WPEFramework + + diff --git a/DeviceDiagnostics/DeviceDiagnostics.h b/DeviceDiagnostics/DeviceDiagnostics.h new file mode 100644 index 0000000000..cb0628b65a --- /dev/null +++ b/DeviceDiagnostics/DeviceDiagnostics.h @@ -0,0 +1,67 @@ +/** +* 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 "Module.h" + +#include "utils.h" +#include "AbstractPlugin.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 DeviceDiagnostics : public AbstractPlugin { + private: + + // We do not allow this plugin to be copied !! + DeviceDiagnostics(const DeviceDiagnostics&) = delete; + DeviceDiagnostics& operator=(const DeviceDiagnostics&) = delete; + + //Begin methods + uint32_t getConfigurationWrapper(const JsonObject& parameters, JsonObject& response); + //End methods + + int getConfiguration(const std::string& postData, JsonObject& response); + + public: + DeviceDiagnostics(); + virtual ~DeviceDiagnostics(); + + public: + static DeviceDiagnostics* _instance; + + }; + } // namespace Plugin +} // namespace WPEFramework + + diff --git a/DeviceDiagnostics/Module.cpp b/DeviceDiagnostics/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/DeviceDiagnostics/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/DeviceDiagnostics/Module.h b/DeviceDiagnostics/Module.h new file mode 100644 index 0000000000..b981e95ef4 --- /dev/null +++ b/DeviceDiagnostics/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 DeviceDiagnostics +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/DeviceDiagnostics/README.md b/DeviceDiagnostics/README.md new file mode 100644 index 0000000000..08a4f057f0 --- /dev/null +++ b/DeviceDiagnostics/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": "DeviceDiagnostics.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/DisplaySettings/CMakeLists.txt b/DisplaySettings/CMakeLists.txt new file mode 100644 index 0000000000..d5acb49df9 --- /dev/null +++ b/DisplaySettings/CMakeLists.txt @@ -0,0 +1,30 @@ +set(PLUGIN_NAME DisplaySettings) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + DisplaySettings.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +target_include_directories(${MODULE_NAME} PRIVATE ../helpers) + +find_package(DS) +if (DS_FOUND) + find_package(IARMBus) + add_definitions(-DDS_FOUND) + target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) + target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${DS_LIBRARIES}) +else (DS_FOUND) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +endif(DS_FOUND) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/DisplaySettings/DisplaySettings.config b/DisplaySettings/DisplaySettings.config new file mode 100644 index 0000000000..cc0c2f00c3 --- /dev/null +++ b/DisplaySettings/DisplaySettings.config @@ -0,0 +1,3 @@ +set (autostart false) +set (preconditions Platform) +set (callsign "org.rdk.DisplaySettings") diff --git a/DisplaySettings/DisplaySettings.cpp b/DisplaySettings/DisplaySettings.cpp new file mode 100644 index 0000000000..fdc8683b40 --- /dev/null +++ b/DisplaySettings/DisplaySettings.cpp @@ -0,0 +1,1332 @@ +/** +* 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. +**/ + +//I have put several "TODO(MROLLINS)" in the code below to mark areas of concern I encountered +// when refactoring the servicemanager's version of displaysettings into this new thunder plugin format + +#include "DisplaySettings.h" +#include +#include "dsMgr.h" +#include "libIBusDaemon.h" +#include "host.hpp" +#include "exception.hpp" +#include "videoOutputPort.hpp" +#include "videoOutputPortType.hpp" +#include "videoOutputPortConfig.hpp" +#include "videoResolution.hpp" +#include "audioOutputPort.hpp" +#include "audioOutputPortType.hpp" +#include "audioOutputPortConfig.hpp" +#include "manager.hpp" +#include "dsUtl.h" +#include "dsError.h" +#include "list.hpp" +#include "libIBus.h" +#include "dsDisplay.h" +#include "rdk/iarmmgrs-hal/pwrMgr.h" + +#include "tracing/Logging.h" +#include +#include "utils.h" + +using namespace std; + +#define HDMI_HOT_PLUG_EVENT_CONNECTED 0 + +#ifdef USE_IARM +namespace +{ + /** + * @struct Mapping + * @brief Structure that defines members for the display setting service. + * @ingroup SERVMGR_DISPSETTINGS + */ + struct Mapping + { + const char *IArmBusName; + const char *SvcManagerName; + }; + + static struct Mapping name_mappings[] = { + { "Full", "FULL" }, + { "None", "NONE" }, + { "mono", "MONO" }, + { "stereo", "STEREO" }, + { "surround", "SURROUND" }, + { "unknown", "UNKNOWN" }, + // TODO: add your mappings here + // { , }, + { 0, 0 } + }; + + string svc2iarm(const string &name) + { + const char *s = name.c_str(); + + int i = 0; + while (name_mappings[i].SvcManagerName) + { + if (strcmp(s, name_mappings[i].SvcManagerName) == 0) + return name_mappings[i].IArmBusName; + i++; + } + return name; + } + + string iarm2svc(const string &name) + { + const char *s = name.c_str(); + + int i = 0; + while (name_mappings[i].IArmBusName) + { + if (strcmp(s, name_mappings[i].IArmBusName) == 0) + return name_mappings[i].SvcManagerName; + i++; + } + return name; + } +} +#endif + +namespace WPEFramework { + + namespace Plugin { + + SERVICE_REGISTRATION(DisplaySettings, 1, 0); + + DisplaySettings* DisplaySettings::_instance = nullptr; + + DisplaySettings::DisplaySettings() + : AbstractPlugin() + { + LOGINFO("ctor"); + DisplaySettings::_instance = this; + + registerMethod("getConnectedVideoDisplays", &DisplaySettings::getConnectedVideoDisplays, this); + registerMethod("getConnectedAudioPorts", &DisplaySettings::getConnectedAudioPorts, this); + registerMethod("getSupportedResolutions", &DisplaySettings::getSupportedResolutions, this); + registerMethod("getSupportedVideoDisplays", &DisplaySettings::getSupportedVideoDisplays, this); + registerMethod("getSupportedTvResolutions", &DisplaySettings::getSupportedTvResolutions, this); + registerMethod("getSupportedSettopResolutions", &DisplaySettings::getSupportedSettopResolutions, this); + registerMethod("getSupportedAudioPorts", &DisplaySettings::getSupportedAudioPorts, this); + registerMethod("getSupportedAudioModes", &DisplaySettings::getSupportedAudioModes, this); + registerMethod("getZoomSetting", &DisplaySettings::getZoomSetting, this); + registerMethod("setZoomSetting", &DisplaySettings::setZoomSetting, this); + registerMethod("getCurrentResolution", &DisplaySettings::getCurrentResolution, this); + registerMethod("setCurrentResolution", &DisplaySettings::setCurrentResolution, this); + registerMethod("getSoundMode", &DisplaySettings::getSoundMode, this); + registerMethod("setSoundMode", &DisplaySettings::setSoundMode, this); + registerMethod("readEDID", &DisplaySettings::readEDID, this); + registerMethod("readHostEDID", &DisplaySettings::readHostEDID, this); + registerMethod("getActiveInput", &DisplaySettings::getActiveInput, this); + registerMethod("getTvHDRSupport", &DisplaySettings::getTvHDRSupport, this); + registerMethod("getSettopHDRSupport", &DisplaySettings::getSettopHDRSupport, this); + registerMethod("setVideoPortStatusInStandby", &DisplaySettings::setVideoPortStatusInStandby, this); + registerMethod("getVideoPortStatusInStandby", &DisplaySettings::getVideoPortStatusInStandby, this); + registerMethod("getCurrentOutputSettings", &DisplaySettings::getCurrentOutputSettings, this); + } + + DisplaySettings::~DisplaySettings() + { + LOGINFO("dtor"); + DisplaySettings::_instance = nullptr; + } + + const string DisplaySettings::Initialize(PluginHost::IShell* /* service */) + { + LOGINFO(); + InitializeIARM(); + // On success return empty, to indicate there is no error text. + return (string()); + } + + void DisplaySettings::Deinitialize(PluginHost::IShell* /* service */) + { + LOGINFO(); + DeinitializeIARM(); + } + + void DisplaySettings::InitializeIARM() + { + LOGINFO(); + IARM_Result_t res; + IARM_CHECK( IARM_Bus_Init("Display_Settings") ); + IARM_CHECK( IARM_Bus_Connect() ); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_RX_SENSE, DisplResolutionHandler) ); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_ZOOM_SETTINGS, DisplResolutionHandler) ); + //TODO(MROLLINS) localinput.cpp has PreChange guared with #if !defined(DISABLE_PRE_RES_CHANGE_EVENTS) + //Can we set it all the time from inside here and let localinput put guards around listening for our event? + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_RES_PRECHANGE,ResolutionPreChange) ); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE, ResolutionPostChange) ); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, dsHdmiEventHandler) ); + 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(); + LOGINFO("device::Manager::Initialize success"); + } + catch(...) + { + LOGINFO("device::Manager::Initialize failed"); + } + } + + //TODO(MROLLINS) - we need to install crash handler to ensure DeinitializeIARM gets called + void DisplaySettings::DeinitializeIARM() + { + LOGINFO(); + IARM_Result_t res; + IARM_CHECK( IARM_Bus_UnRegisterEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_RX_SENSE) ); + IARM_CHECK( IARM_Bus_UnRegisterEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_ZOOM_SETTINGS) ); + IARM_CHECK( IARM_Bus_Disconnect() ); + IARM_CHECK( IARM_Bus_Term() ); + 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::DeInitialize(); + LOGINFO("device::Manager::DeInitialize success"); + } + catch(...) + { + LOGINFO("device::Manager::DeInitialize failed"); + } + + } + + void DisplaySettings::ResolutionPreChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + LOGINFO(); + if(DisplaySettings::_instance) + { + DisplaySettings::_instance->resolutionPreChange(); + } + } + + void DisplaySettings::ResolutionPostChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + LOGINFO(); + + int dw = 1280; + int dh = 720; + + if (strcmp(owner, IARM_BUS_DSMGR_NAME) == 0) + { + switch (eventId) { + case IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE: + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + dw = eventData->data.resn.width; + dh = eventData->data.resn.height; + LOGINFO("width: %d, height: %d", dw, dh); + break; + } + } + + if(DisplaySettings::_instance) + { + DisplaySettings::_instance->resolutionChanged(dw, dh); + } + } + + void DisplaySettings::DisplResolutionHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + LOGINFO(); + //TODO(MROLLINS) Receiver has this whole thing guarded by #ifndef HEADLESS_GW + if (strcmp(owner,IARM_BUS_DSMGR_NAME) == 0) + { + switch (eventId) + { + case IARM_BUS_DSMGR_EVENT_RES_PRECHANGE: + break; + case IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE: + { + int dw = 1280; + int dh = 720; + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + dw = eventData->data.resn.width ; + dh = eventData->data.resn.height ; + if(DisplaySettings::_instance) + DisplaySettings::_instance->resolutionChanged(dw,dh); + } + break; + case IARM_BUS_DSMGR_EVENT_ZOOM_SETTINGS: + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + if(eventData->data.dfc.zoomsettings == dsVIDEO_ZOOM_NONE) + { + LOGINFO("dsVIDEO_ZOOM_NONE Settings"); + if(DisplaySettings::_instance) + DisplaySettings::_instance->zoomSettingUpdated("NONE"); + } + else if(eventData->data.dfc.zoomsettings == dsVIDEO_ZOOM_FULL) + { + LOGINFO("dsVIDEO_ZOOM_FULL Settings"); + if(DisplaySettings::_instance) + DisplaySettings::_instance->zoomSettingUpdated("FULL"); + } + } + break; + case IARM_BUS_DSMGR_EVENT_RX_SENSE: + { + + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + if(eventData->data.hdmi_rxsense.status == dsDISPLAY_RXSENSE_ON) + { + LOGINFO("Got dsDISPLAY_RXSENSE_ON -> notifyactiveInputChanged(true)"); + if(DisplaySettings::_instance) + DisplaySettings::_instance->activeInputChanged(true); + } + else if(eventData->data.hdmi_rxsense.status == dsDISPLAY_RXSENSE_OFF) + { + LOGINFO("Got dsDISPLAY_RXSENSE_OFF -> notifyactiveInputChanged(false)"); + if(DisplaySettings::_instance) + DisplaySettings::_instance->activeInputChanged(false); + } + } + break; + default: + break; + } + } + } + + void DisplaySettings::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + LOGINFO(); + switch (eventId) + { + case IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG : + //TODO(MROLLINS) note that there are several services listening for the notifyHdmiHotPlugEvent ServiceManagerNotifier broadcast + //So if DisplaySettings becomes the owner/originator of this, then those future thunder plugins need to listen to our event + //But of course, nothing is stopping any thunder plugin for listening to iarm event directly -- this is getting murky + { + 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 ", hdmi_hotplug_event); + if(DisplaySettings::_instance) + DisplaySettings::_instance->connectedVideoDisplaysUpdated(hdmi_hotplug_event); + } + break; + //TODO(MROLLINS) localinput.cpp was also sending these and they were getting handled by services other then DisplaySettings. Should DisplaySettings own these as well ? + /* + case IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG : + { + 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; + LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG event data:%d, %d ", hdmiin_hotplug_port); + ServiceManagerNotifier::getInstance()->notifyHdmiInputHotPlugEvent(hdmiin_hotplug_port, hdmiin_hotplug_conn); + } + break; + case IARM_BUS_DSMGR_EVENT_HDCP_STATUS : + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + int hdcpStatus = eventData->data.hdmi_hdcp.hdcpStatus; + LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDCP_STATUS event data:%d ", hdcpStatus); + ServiceManagerNotifier::getInstance()->notifyHdmiOutputHDCPStatus(hdcpStatus); + } + break; + */ + default: + //do nothing + break; + } + } + + 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); + } + + //Begin methods + uint32_t DisplaySettings::getConnectedVideoDisplays(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: {"connectedVideoDisplays":["HDMI0"],"success":true} + //this : {"connectedVideoDisplays":["HDMI0"]} + LOGINFOMETHOD(); + + vector connectedVideoDisplays; + getConnectedVideoDisplaysHelper(connectedVideoDisplays); + setResponseArray(response, "connectedVideoDisplays", connectedVideoDisplays); + returnResponse(true); + } + + uint32_t DisplaySettings::getConnectedAudioPorts(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: {"success":true,"connectedAudioPorts":["HDMI0"]} + LOGINFOMETHOD(); + vector connectedAudioPorts; + try + { + device::List aPorts = device::Host::getInstance().getAudioOutputPorts(); + for (size_t i = 0; i < aPorts.size(); i++) + { + device::AudioOutputPort &aPort = aPorts.at(i); + if (aPort.isConnected()) + { + string portName = aPort.getName(); + vectorSet(connectedAudioPorts, portName); + } + } + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } + setResponseArray(response, "connectedAudioPorts", connectedAudioPorts); + returnResponse(true); + } + + uint32_t DisplaySettings::getSupportedResolutions(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response:{"success":true,"supportedResolutions":["720p","1080i","1080p60"]} + LOGINFOMETHOD(); + string videoDisplay = parameters.HasLabel("videoDisplay") ? parameters["videoDisplay"].String() : "HDMI0"; + vector supportedResolutions; + try + { + device::VideoOutputPort &vPort = device::Host::getInstance().getVideoOutputPort(videoDisplay); + const device::List resolutions = device::VideoOutputPortConfig::getInstance().getPortType(vPort.getType().getId()).getSupportedResolutions(); + for (size_t i = 0; i < resolutions.size(); i++) { + const device::VideoResolution &resolution = resolutions.at(i); + string supportedResolution = resolution.getName(); + vectorSet(supportedResolutions,supportedResolution); + } + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(videoDisplay); + } + setResponseArray(response, "supportedResolutions", supportedResolutions); + returnResponse(true); + } + + uint32_t DisplaySettings::getSupportedVideoDisplays(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: {"supportedVideoDisplays":["HDMI0"],"success":true} + LOGINFOMETHOD(); + vector supportedVideoDisplays; + try + { + device::List vPorts = device::Host::getInstance().getVideoOutputPorts(); + for (size_t i = 0; i < vPorts.size(); i++) + { + device::VideoOutputPort &vPort = vPorts.at(i); + string videoDisplay = vPort.getName(); + vectorSet(supportedVideoDisplays, videoDisplay); + } + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } + setResponseArray(response, "supportedVideoDisplays", supportedVideoDisplays); + returnResponse(true); + } + + uint32_t DisplaySettings::getSupportedTvResolutions(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response:{"success":true,"supportedTvResolutions":["480i","480p","576i","720p","1080i","1080p"]} + LOGINFOMETHOD(); + string videoDisplay = parameters.HasLabel("videoDisplay") ? parameters["videoDisplay"].String() : "HDMI0"; + vector supportedTvResolutions; + try + { + int tvResolutions = 0; + device::VideoOutputPort &vPort = device::Host::getInstance().getVideoOutputPort(videoDisplay); + vPort.getSupportedTvResolutions(&tvResolutions); + if(!tvResolutions)supportedTvResolutions.emplace_back("none"); + if(tvResolutions & dsTV_RESOLUTION_480i)supportedTvResolutions.emplace_back("480i"); + if(tvResolutions & dsTV_RESOLUTION_480p)supportedTvResolutions.emplace_back("480p"); + if(tvResolutions & dsTV_RESOLUTION_576i)supportedTvResolutions.emplace_back("576i"); + if(tvResolutions & dsTV_RESOLUTION_576p)supportedTvResolutions.emplace_back("576p"); + if(tvResolutions & dsTV_RESOLUTION_720p)supportedTvResolutions.emplace_back("720p"); + if(tvResolutions & dsTV_RESOLUTION_1080i)supportedTvResolutions.emplace_back("1080i"); + if(tvResolutions & dsTV_RESOLUTION_1080p)supportedTvResolutions.emplace_back("1080p"); + if(tvResolutions & dsTV_RESOLUTION_2160p30)supportedTvResolutions.emplace_back("2160p30"); + if(tvResolutions & dsTV_RESOLUTION_2160p60)supportedTvResolutions.emplace_back("2160p60"); + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(videoDisplay); + } + setResponseArray(response, "supportedTvResolutions", supportedTvResolutions); + returnResponse(true); + } + + uint32_t DisplaySettings::getSupportedSettopResolutions(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response:{"success":true,"supportedSettopResolutions":["720p","1080i","1080p60"]} + LOGINFOMETHOD(); + vector supportedSettopResolutions; + try + { + device::VideoDevice &device = device::Host::getInstance().getVideoDevices().at(0); + list resolutions; + device.getSettopSupportedResolutions(resolutions); + for (list::const_iterator ci = resolutions.begin(); ci != resolutions.end(); ++ci) + { + string supportedResolution = *ci; + vectorSet(supportedSettopResolutions, supportedResolution); + } + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } + setResponseArray(response, "supportedSettopResolutions", supportedSettopResolutions); + returnResponse(true); + } + + uint32_t DisplaySettings::getSupportedAudioPorts(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: {"success":true,"supportedAudioPorts":["HDMI0"]} + LOGINFOMETHOD(); + vector supportedAudioPorts; + try + { + device::List aPorts = device::Host::getInstance().getAudioOutputPorts(); + for (size_t i = 0; i < aPorts.size(); i++) + { + device::AudioOutputPort &vPort = aPorts.at(i); + string portName = vPort.getName(); + vectorSet(supportedAudioPorts,portName); + } + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } + setResponseArray(response, "supportedAudioPorts", supportedAudioPorts); + returnResponse(true); + } + + uint32_t DisplaySettings::getSupportedAudioModes(const JsonObject& parameters, JsonObject& response) + { //sample response: {"success":true,"supportedAudioModes":["STEREO","PASSTHRU","AUTO (Dolby Digital 5.1)"]} + LOGINFOMETHOD(); + string audioPort = parameters["audioPort"].String(); + vector supportedAudioModes; + try + { + bool HAL_hasSurround = false; + + device::List vPorts = device::Host::getInstance().getVideoOutputPorts(); + for (size_t i = 0; i < vPorts.size(); i++) { + device::AudioOutputPort &aPort = vPorts.at(i).getAudioOutputPort(); + for (size_t i = 0; i < aPort.getSupportedStereoModes().size(); i++) { + if (audioPort.empty() || stringContains(aPort.getName(), audioPort.c_str())) + { + string audioMode = aPort.getSupportedStereoModes().at(i).getName(); + + // Starging Version 5, "Surround" mode is replaced by "Auto Mode" + if (strcasecmp(audioMode.c_str(),"SURROUND") == 0) + { + HAL_hasSurround = true; + continue; + } + + vectorSet(supportedAudioModes,audioMode); + } + } + } + + if (audioPort.empty() || stringContains(audioPort, "HDMI")) + { + device::VideoOutputPort vPort = device::VideoOutputPortConfig::getInstance().getPort("HDMI0"); + int surroundMode = vPort.getDisplay().getSurroundMode(); + if (vPort.isDisplayConnected() && surroundMode) + { + if(surroundMode & dsSURROUNDMODE_DDPLUS ) + { + LOGINFO("HDMI0 has surround DD Plus "); + supportedAudioModes.emplace_back("AUTO (Dolby Digital Plus)"); + } + else if(surroundMode & dsSURROUNDMODE_DD ) + { + LOGINFO("HDMI0 has surround DD5.1 "); + supportedAudioModes.emplace_back("AUTO (Dolby Digital 5.1)"); + } + } + else { + LOGINFO("HDMI0 does not have surround"); + supportedAudioModes.emplace_back("AUTO (Stereo)"); + } + } + + if (audioPort.empty() || stringContains(audioPort, "SPDIF")) + { + if (HAL_hasSurround) { + supportedAudioModes.emplace_back("Surround"); + } + } + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(audioPort); + } + setResponseArray(response, "supportedAudioModes", supportedAudioModes); + returnResponse(true); + } + + uint32_t DisplaySettings::getZoomSetting(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: + LOGINFOMETHOD(); + string zoomSetting = "unknown"; + try + { + // TODO: why is this always the first one in the list + device::VideoDevice &decoder = device::Host::getInstance().getVideoDevices().at(0); + zoomSetting = decoder.getDFC().getName(); + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } +#ifdef USE_IARM + zoomSetting = iarm2svc(zoomSetting); +#endif + response["zoomSetting"] = zoomSetting; + returnResponse(true); + } + + uint32_t DisplaySettings::setZoomSetting(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: + LOGINFOMETHOD(); + + returnIfParamNotFound(parameters, "zoomSetting"); + string zoomSetting = parameters["zoomSetting"].String(); + + bool success = true; + try + { +#ifdef USE_IARM + zoomSetting = svc2iarm(zoomSetting); +#endif + // TODO: why is this always the first one in the list? + device::VideoDevice &decoder = device::Host::getInstance().getVideoDevices().at(0); + decoder.setDFC(zoomSetting); + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(zoomSetting); + success = false; + } + returnResponse(success); + } + + uint32_t DisplaySettings::getCurrentResolution(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response:{"success":true,"resolution":"720p"} + LOGINFOMETHOD(); + string videoDisplay = parameters.HasLabel("videoDisplay") ? parameters["videoDisplay"].String() : "HDMI0"; + bool success = true; + try + { + device::VideoOutputPort &vPort = device::Host::getInstance().getVideoOutputPort(videoDisplay); + response["resolution"] = vPort.getResolution().getName(); + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(videoDisplay); + success = false; + } + returnResponse(success); + } + + uint32_t DisplaySettings::setCurrentResolution(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: + LOGINFOMETHOD(); + returnIfParamNotFound(parameters, "videoDisplay"); + returnIfParamNotFound(parameters, "resolution"); + + string videoDisplay = parameters["videoDisplay"].String(); + string resolution = parameters["resolution"].String(); + + bool hasPersist = parameters.HasLabel("persist"); + bool persist = hasPersist ? parameters["persist"].Boolean() : true; + if (!hasPersist) LOGINFO("persist: true"); + + bool success = true; + try + { + device::VideoOutputPort &vPort = device::Host::getInstance().getVideoOutputPort(videoDisplay); + vPort.setResolution(resolution); + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION2(videoDisplay, resolution); + success = false; + } + returnResponse(success); + } + + uint32_t DisplaySettings::getSoundMode(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response:{"success":true,"soundMode":"AUTO (Dolby Digital 5.1)"} + LOGINFOMETHOD(); + string videoDisplay = parameters["videoDisplay"].String();//empty value will browse all ports + bool validPortName = true; + + if (videoDisplay.empty()) + { + /* Empty is allowed */ + } + if (stringContains(videoDisplay,"HDMI")) + { + videoDisplay = "HDMI0"; + } + else if (stringContains(videoDisplay,"SPDIF")) + { + videoDisplay = "SPDIF0"; + } + else + { + validPortName = false; + } + + if (!validPortName) + videoDisplay = "HDMI0"; + + string modeString(""); + device::AudioStereoMode mode = device::AudioStereoMode::kStereo; //default to stereo + + try + { + /* Return the sound mode of the audio ouput connected to the specified videoDisplay */ + /* Check if HDMI is connected - Return (default) Stereo Mode if not connected */ + if (videoDisplay.empty()) + { + if (device::Host::getInstance().getVideoOutputPort("HDMI0").isDisplayConnected()) + { + videoDisplay = "HDMI0"; + } + else + { + /* * If HDMI is not connected + * Get the SPDIF if it is supported by platform + * If Platform does not have connected ports. Default to HDMI. + */ + videoDisplay = "HDMI0"; + device::List vPorts = device::Host::getInstance().getVideoOutputPorts(); + for (size_t i = 0; i < vPorts.size(); i++) + { + device::VideoOutputPort &vPort = vPorts.at(i); + if (vPort.isDisplayConnected()) + { + videoDisplay = "SPDIF0"; + break; + } + } + } + } + + device::AudioOutputPort aPort = device::Host::getInstance().getAudioOutputPort(videoDisplay); + + if (aPort.isConnected()) + { + + mode = aPort.getStereoMode(); + + if (aPort.getType().getId() == device::AudioOutputPortType::kHDMI) + { + /* In DS5, "Surround" implies "Auto" */ + if (aPort.getStereoAuto() || mode == device::AudioStereoMode::kSurround) + { + LOGINFO("HDMI0 is in Auto Mode"); + int surroundMode = device::Host::getInstance().getVideoOutputPort("HDMI0").getDisplay().getSurroundMode(); + if ( surroundMode & dsSURROUNDMODE_DDPLUS) + { + LOGINFO("HDMI0 has surround DDPlus"); + modeString.append("AUTO (Dolby Digital Plus)"); + } + else if (surroundMode & dsSURROUNDMODE_DD) + { + LOGINFO("HDMI0 has surround DD 5.1"); + modeString.append("AUTO (Dolby Digital 5.1)"); + } + else + { + LOGINFO("HDMI0 does not surround"); + modeString.append("AUTO (Stereo)"); + } + } + else + { + modeString.append(mode.toString()); + } + } + else + { + if (mode == device::AudioStereoMode::kSurround) + { + modeString.append("Surround"); + } + else + { + modeString.append(mode.toString()); + } + } + } + else + { + /* + * VideoDisplay is not connected. Its audio mode is unknown. Return + * "Stereo" as safe default; + */ + mode = device::AudioStereoMode::kStereo; + modeString.append("AUTO (Stereo)"); + } + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + // + // Exception + // "Stereo" as safe default; + // + mode = device::AudioStereoMode::kStereo; + modeString += "AUTO (Stereo)"; + } + + LOGWARN("display = %s, mode = %s!", videoDisplay.c_str(), modeString.c_str()); +#ifdef USE_IARM + modeString = iarm2svc(modeString); +#endif + response["soundMode"] = modeString; + returnResponse(true); + } + + uint32_t DisplaySettings::setSoundMode(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: + LOGINFOMETHOD(); + string videoDisplay = parameters["audioPort"].String();//missing or empty string and we will set all ports + + returnIfParamNotFound(parameters, "soundMode"); + string soundMode = parameters["soundMode"].String(); + + bool hasPersist = parameters.HasLabel("persist"); + bool persist = hasPersist ? parameters["persist"].Boolean() : true; + if (!hasPersist) LOGINFO("persist: true"); + + bool success = true; + device::AudioStereoMode mode = device::AudioStereoMode::kStereo; //default to stereo + bool stereoAuto = false; + + if (soundMode == "mono") + { + mode = device::AudioStereoMode::kMono; + } + else if (soundMode == "stereo") + { + mode = device::AudioStereoMode::kStereo; + } + else if (soundMode == "surround") + { + mode = device::AudioStereoMode::kSurround; + } + else if (soundMode == "passthru") + { + mode = device::AudioStereoMode::kPassThru; + } + else if ((soundMode == "auto") || (strncasecmp(soundMode.c_str(), "auto ", 5) == 0)) + { + /* + * anthing after "auto" is only descriptive, and can be ignored. + * use kSurround in this case. + */ + if (videoDisplay.empty()) + videoDisplay = "HDMI0"; + stereoAuto = true; + mode = device::AudioStereoMode::kSurround; + } + else if (soundMode == "dolby digital 5.1") + { + mode = device::AudioStereoMode::kSurround; + } + else + { + } + + bool validPortName = true; + + if (videoDisplay.empty()) + { + /* Empty is allowed */ + } + else if (stringContains(videoDisplay,"HDMI")) + { + videoDisplay = "HDMI0"; + } + else if (stringContains(videoDisplay,"SPDIF")) + { + videoDisplay = "SPDIF0"; + } + else + { + validPortName = false; + } + + if (!validPortName) + { + LOGERR("Invalid port Name: display = %s, mode = %s!", videoDisplay.c_str(), soundMode.c_str()); + returnResponse(false); + } + + LOGWARN("display = %s, mode = %s!", videoDisplay.c_str(), soundMode.c_str()); + + try + { + //now setting the sound mode for specified video display types + if (!videoDisplay.empty()) + { + device::AudioOutputPort aPort = device::Host::getInstance().getAudioOutputPort(videoDisplay); + if (aPort.isConnected()) + { + /* Auto mode is only for HDMI and DS5 and non-Passthru*/ + if (aPort.getType().getId() == device::AudioOutputPortType::kHDMI && (!(mode == device::AudioStereoMode::kPassThru))) + { + aPort.setStereoAuto(stereoAuto, persist); + if (stereoAuto) + { + if (device::Host::getInstance().getVideoOutputPort("HDMI0").getDisplay().getSurroundMode()) + { + mode = device::AudioStereoMode::kSurround; + } + else + { + mode = device::AudioStereoMode::kStereo; + } + } + } + else if (aPort.getType().getId() == device::AudioOutputPortType::kHDMI) { + LOGERR("Reset auto on %s for mode = %s!", videoDisplay.c_str(), soundMode.c_str()); + aPort.setStereoAuto(false, persist); + } + //TODO: if mode has not changed, we can skip the extra call + aPort.setStereoMode(mode.toString(), persist); + } + } + else + { + /* No videoDisplay is specified, setMode to all connected ports */ + JsonObject params; + params["videoDisplay"] = "HDMI0"; + params["soundMode"] = soundMode; + JsonObject unusedResponse; + setSoundMode(params, response); + params["videoDisplay"] = "SPDIF0"; + setSoundMode(params, unusedResponse); + } + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + success = false; + } + //TODO(MROLLINS) -- so this is interesting. ServiceManager had a settingChanged event that I guess handled settings from many services. + //Does that mean we need to save our setting back to another plugin that would own settings (and this settingsChanged event) ? + //ServiceManager::getInstance()->saveSetting(this, SETTING_DISPLAY_SERVICE_SOUND_MODE, soundMode); + + returnResponse(success); + } + + uint32_t DisplaySettings::readEDID(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: {"EDID":"AP///////wBSYgYCAQEBAQEXAQOAoFp4CvCdo1VJmyYPR0ovzgCBgIvAAQEBAQEBAQEBAQEBAjqAGHE4LUBYLEUAQIRjAAAeZiFQsFEAGzBAcDYAQIRjAAAeAAAA/ABUT1NISUJBLVRWCiAgAAAA/QAXSw9EDwAKICAgICAgAbECAytxSpABAgMEBQYHICImCQcHEQcYgwEAAGwDDAAQADgtwBUVHx/jBQMBAR2AGHEcFiBYLCUAQIRjAACeAR0AclHQHiBuKFUAQIRjAAAejArQiiDgLRAQPpYAsIRDAAAYjAqgFFHwFgAmfEMAsIRDAACYAAAAAAAAAAAAAAAA9w==" + //sample this thunder plugin : {"EDID":"AP///////wBSYgYCAQEBAQEXAQOAoFp4CvCdo1VJmyYPR0ovzgCBgIvAAQEBAQEBAQEBAQEBAjqAGHE4LUBYLEUAQIRjAAAeZiFQsFEAGzBAcDYAQIRjAAAeAAAA/ABUT1NISUJBLVRWCiAgAAAA/QAXSw9EDwAKICAgICAgAbECAytxSpABAgMEBQYHICImCQcHEQcYgwEAAGwDDAAQADgtwBUVHx/jBQMBAR2AGHEcFiBYLCUAQIRjAACeAR0AclHQHiBuKFUAQIRjAAAejArQiiDgLRAQPpYAsIRDAAAYjAqgFFHwFgAmfEMAsIRDAACYAAAAAAAAAAAAAAAA9w"} + LOGINFOMETHOD(); + + vector edidVec({'u','n','k','n','o','w','n' }); + try + { + vector edidVec2; + device::VideoOutputPort vPort = device::Host::getInstance().getVideoOutputPort("HDMI0"); + if (vPort.isDisplayConnected()) + { + vPort.getDisplay().getEDIDBytes(edidVec2); + edidVec = edidVec2;//edidVec must be "unknown" unless we successfully get to this line + } + else + { + LOGWARN("failure: HDMI0 not connected!"); + } + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } + //convert to base64 + uint16_t size = min(edidVec.size(), (size_t)numeric_limits::max()); + if(edidVec.size() > (size_t)numeric_limits::max()) + LOGERR("Size too large to use ToString base64 wpe api"); + string edidbase64; + Core::ToString((uint8_t*)&edidVec[0], size, false, edidbase64); + response["EDID"] = edidbase64; + returnResponse(true); + } + + uint32_t DisplaySettings::readHostEDID(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: + LOGINFOMETHOD(); + + vector edidVec({'u','n','k','n','o','w','n' }); + try + { + vector edidVec2; + device::Host::getInstance().getHostEDID(edidVec2); + edidVec = edidVec2;//edidVec must be "unknown" unless we successfully get to this line + LOGINFO("getHostEDID size is %d.", int(edidVec2.size())); + } + catch (const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } + //convert to base64 + string base64String; + uint16_t size = min(edidVec.size(), (size_t)numeric_limits::max()); + if(edidVec.size() > (size_t)numeric_limits::max()) + LOGINFO("size too large to use ToString base64 wpe api"); + Core::ToString((uint8_t*)&edidVec[0], size, false, base64String); + response["EDID"] = base64String; + returnResponse(true); + } + + uint32_t DisplaySettings::getActiveInput(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response: + LOGINFOMETHOD(); + + string videoDisplay = parameters.HasLabel("videoDisplay") ? parameters["videoDisplay"].String() : "HDMI0"; + bool active = true; + try + { + device::VideoOutputPort &vPort = device::Host::getInstance().getVideoOutputPort(videoDisplay); + active = (vPort.isDisplayConnected() && vPort.isActive()); + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(videoDisplay); + } + response["activeInput"] = JsonValue(active); + returnResponse(true); + } + + uint32_t DisplaySettings::getTvHDRSupport(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response:{"standards":["none"],"supportsHDR":false} + LOGINFOMETHOD(); + + JsonArray hdrCapabilities; + int capabilities = dsHDRSTANDARD_NONE; + + try + { + device::VideoOutputPort vPort = device::VideoOutputPortConfig::getInstance().getPort("HDMI0"); + if (vPort.isDisplayConnected()) + vPort.getTVHDRCapabilities(&capabilities); + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } + + if(!capabilities)hdrCapabilities.Add("none"); + if(capabilities & dsHDRSTANDARD_HDR10)hdrCapabilities.Add("HDR10"); + if(capabilities & dsHDRSTANDARD_DolbyVision)hdrCapabilities.Add("Dolby Vision"); + if(capabilities & dsHDRSTANDARD_TechnicolorPrime)hdrCapabilities.Add("Technicolor Prime"); + + if(capabilities) + { + response["supportsHDR"] = true; + } + else + { + response["supportsHDR"] = false; + } + response["standards"] = hdrCapabilities; + for (uint32_t i = 0; i < hdrCapabilities.Length(); i++) + { + LOGINFO("capabilities: %s", hdrCapabilities[i].String().c_str()); + } + returnResponse(true); + } + + uint32_t DisplaySettings::getSettopHDRSupport(const JsonObject& parameters, JsonObject& response) + { //sample servicemanager response:{"standards":["HDR10"],"supportsHDR":true} + LOGINFOMETHOD(); + + JsonArray hdrCapabilities; + int capabilities = dsHDRSTANDARD_NONE; + + try + { + device::VideoDevice &device = device::Host::getInstance().getVideoDevices().at(0); + device.getHDRCapabilities(&capabilities); + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } + + if(!capabilities)hdrCapabilities.Add("none"); + if(capabilities & dsHDRSTANDARD_HDR10)hdrCapabilities.Add("HDR10"); + if(capabilities & dsHDRSTANDARD_DolbyVision)hdrCapabilities.Add("Dolby Vision"); + if(capabilities & dsHDRSTANDARD_TechnicolorPrime)hdrCapabilities.Add("Technicolor Prime"); + + if(capabilities) + { + response["supportsHDR"] = true; + } + else + { + response["supportsHDR"] = false; + } + response["standards"] = hdrCapabilities; + for (uint32_t i = 0; i < hdrCapabilities.Length(); i++) + { + LOGINFO("capabilities: %s", hdrCapabilities[i].String().c_str()); + } + returnResponse(true); + } + + uint32_t DisplaySettings::setVideoPortStatusInStandby(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + returnIfParamNotFound(parameters, "portName"); + string portname = parameters["portName"].String(); + + bool enabled = parameters["enabled"].Boolean(); + IARM_Bus_PWRMgr_StandbyVideoState_Param_t param; + param.isEnabled = enabled; + strncpy(param.port, portname.c_str(), PWRMGR_MAX_VIDEO_PORT_NAME_LENGTH); + bool success = true; + if(IARM_RESULT_SUCCESS != IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_SetStandbyVideoState, ¶m, sizeof(param))) + { + LOGERR("Port: %s. enable: %d", param.port, param.isEnabled); + response["error_message"] = "Bus failure"; + success = false; + } + else if(0 != param.result) + { + LOGERR("Result %d. Port: %s. enable:%d", param.result, param.port, param.isEnabled); + response["error_message"] = "internal error"; + success = false; + } + returnResponse(success); + } + + uint32_t DisplaySettings::getVideoPortStatusInStandby(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + returnIfParamNotFound(parameters, "portName"); + string portname = parameters["portName"].String(); + + bool success = true; + IARM_Bus_PWRMgr_StandbyVideoState_Param_t param; + strncpy(param.port, portname.c_str(), PWRMGR_MAX_VIDEO_PORT_NAME_LENGTH); + if(IARM_RESULT_SUCCESS != IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_GetStandbyVideoState, ¶m, sizeof(param))) + { + LOGERR("Port: %s. enable:%d", param.port, param.isEnabled); + response["error_message"] = "Bus failure"; + success = false; + } + else if(0 != param.result) + { + LOGERR("Result %d. Port: %s. enable:%d", param.result, param.port, param.isEnabled); + response["error_message"] = "internal error"; + success = false; + } + else + { + bool enabled(0 != param.isEnabled); + LOGINFO("video port is %s", enabled ? "enabled" : "disabled"); + response["videoPortStatusInStandby"] = enabled; + } + returnResponse(success); + } + + uint32_t DisplaySettings::getCurrentOutputSettings(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + bool success = true; + try + { + device::VideoOutputPort vPort = device::Host::getInstance().getVideoOutputPort("HDMI0"); + if (vPort.isDisplayConnected()) + { + int videoEOTF, matrixCoefficients, colorSpace, colorDepth; + vPort.getCurrentOutputSettings(videoEOTF, matrixCoefficients, colorSpace, colorDepth); + + response["colorSpace"] = colorSpace; + response["colorDepth"] = colorDepth; + response["matrixCoefficients"] = matrixCoefficients; + response["videoEOTF"] = videoEOTF; + } + else + { + LOGERR("HDMI0 not connected!"); + success = false; + } + } + catch (const device::Exception& err) + { + LOGINFO("caught an exception: %d, %s", err.getCode(), err.what()); + success = false; + } + + returnResponse(success); + } + //End methods + + //Begin events + void DisplaySettings::resolutionPreChange() + { + LOGINFO(); + sendNotify("resolutionPreChange", JsonObject()); + } + + void DisplaySettings::resolutionChanged(int width, int height) + { + LOGINFO(); + vector connectedDisplays; + getConnectedVideoDisplaysHelper(connectedDisplays); + + string firstDisplay = ""; + string firstResolution = ""; + bool firstResolutionSet = false; + for (int i = 0; i < (int)connectedDisplays.size(); i++) + { + string resolution; + string display = connectedDisplays.at(i); + try + { + resolution = device::Host::getInstance().getVideoOutputPort(display).getResolution().getName(); + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION1(display); + } + if (!resolution.empty()) + { + if (stringContains(display,"HDMI")) + { + // only report first HDMI connected device is HDMI is connected + JsonObject params; + params["width"] = width; + params["height"] = height; + params["videoDisplayType"] = display; + params["resolution"] = resolution; + sendNotify("resolutionChanged", params); + return; + } + else if (!firstResolutionSet) + { + firstDisplay = display; + firstResolution = resolution; + firstResolutionSet = true; + } + } + } + if (firstResolutionSet) + { + //if HDMI is not connected then notify the server of first connected device + JsonObject params; + params["width"] = width; + params["height"] = height; + params["videoDisplayType"] = firstDisplay; + params["resolution"] = firstResolution; + sendNotify("resolutionChanged", params); + } + } + + void DisplaySettings::zoomSettingUpdated(const string& zoomSetting) + {//servicemanager sample: {"name":"zoomSettingUpdated","params":{"zoomSetting":"None","success":true,"videoDisplayType":"all"} + //servicemanager sample: {"name":"zoomSettingUpdated","params":{"zoomSetting":"Full","success":true,"videoDisplayType":"all"} + LOGINFO(); + JsonObject params; + params["zoomSetting"] = zoomSetting; + params["videoDisplayType"] = "all"; + sendNotify("zoomSettingUpdated", params); + } + + void DisplaySettings::activeInputChanged(bool activeInput) + { + LOGINFO(); + JsonObject params; + params["activeInput"] = activeInput; + sendNotify("activeInputChanged", params); + } + + void DisplaySettings::connectedVideoDisplaysUpdated(int hdmiHotPlugEvent) + { + LOGINFO(); + static int previousStatus = HDMI_HOT_PLUG_EVENT_CONNECTED; + static int firstTime = 1; + + if (firstTime || previousStatus != hdmiHotPlugEvent) + { + firstTime = 0; + JsonArray connectedDisplays; + if (HDMI_HOT_PLUG_EVENT_CONNECTED == hdmiHotPlugEvent) + { + connectedDisplays.Add("HDMI0"); + } + else + { + /* notify Empty list on HDMI-output-disconnect hotplug */ + } + + JsonObject params; + params["connectedVideoDisplays"] = connectedDisplays; + sendNotify("connectedVideoDisplaysUpdated", params); + } + previousStatus = hdmiHotPlugEvent; + } + //End events + + void DisplaySettings::getConnectedVideoDisplaysHelper(vector& connectedDisplays) + { + LOGINFO(); + try + { + device::List vPorts = device::Host::getInstance().getVideoOutputPorts(); + for (size_t i = 0; i < vPorts.size(); i++) + { + device::VideoOutputPort &vPort = vPorts.at(i); + if (vPort.isDisplayConnected()) + { + string displayName = vPort.getName(); + if (strncasecmp(displayName.c_str(), "hdmi", 4)==0) + { + connectedDisplays.clear(); + connectedDisplays.emplace_back(displayName); + break; + } + else + { + vectorSet(connectedDisplays, displayName); + } + } + } + } + catch(const device::Exception& err) + { + LOG_DEVICE_EXCEPTION0(); + } + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/DisplaySettings/DisplaySettings.h b/DisplaySettings/DisplaySettings.h new file mode 100644 index 0000000000..4cecd7ebcb --- /dev/null +++ b/DisplaySettings/DisplaySettings.h @@ -0,0 +1,105 @@ +/** +* 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 "Module.h" +#include "utils.h" +#include "AbstractPlugin.h" +#include "libIBus.h" +#include "irMgr.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 DisplaySettings : public AbstractPlugin { + private: + typedef Core::JSON::String JString; + typedef Core::JSON::ArrayType JStringArray; + typedef Core::JSON::Boolean JBool; + + // We do not allow this plugin to be copied !! + DisplaySettings(const DisplaySettings&) = delete; + DisplaySettings& operator=(const DisplaySettings&) = delete; + + //Begin methods + uint32_t getConnectedVideoDisplays(const JsonObject& parameters, JsonObject& response); + uint32_t getConnectedAudioPorts(const JsonObject& parameters, JsonObject& response); + uint32_t getSupportedResolutions(const JsonObject& parameters, JsonObject& response); + uint32_t getSupportedVideoDisplays(const JsonObject& parameters, JsonObject& response); + uint32_t getSupportedTvResolutions(const JsonObject& parameters, JsonObject& response); + uint32_t getSupportedSettopResolutions(const JsonObject& parameters, JsonObject& response); + uint32_t getSupportedAudioPorts(const JsonObject& parameters, JsonObject& response); + uint32_t getSupportedAudioModes(const JsonObject& parameters, JsonObject& response); + uint32_t getZoomSetting(const JsonObject& parameters, JsonObject& response); + uint32_t setZoomSetting(const JsonObject& parameters, JsonObject& response); + uint32_t getCurrentResolution(const JsonObject& parameters, JsonObject& response); + uint32_t setCurrentResolution(const JsonObject& parameters, JsonObject& response); + uint32_t getSoundMode(const JsonObject& parameters, JsonObject& response); + uint32_t setSoundMode(const JsonObject& parameters, JsonObject& response); + uint32_t readEDID(const JsonObject& parameters, JsonObject& response); + uint32_t readHostEDID(const JsonObject& parameters, JsonObject& response); + uint32_t getActiveInput(const JsonObject& parameters, JsonObject& response); + uint32_t getTvHDRSupport(const JsonObject& parameters, JsonObject& response); + uint32_t getSettopHDRSupport(const JsonObject& parameters, JsonObject& response); + uint32_t setVideoPortStatusInStandby(const JsonObject& parameters, JsonObject& response); + uint32_t getVideoPortStatusInStandby(const JsonObject& parameters, JsonObject& response); + uint32_t getCurrentOutputSettings(const JsonObject& parameters, JsonObject& response); + //End methods + + //Begin events + void resolutionPreChange(); + void resolutionChanged(int width, int height); + void zoomSettingUpdated(const string& zoomSetting); + void activeInputChanged(bool activeInput); + void connectedVideoDisplaysUpdated(int hdmiHotPlugEvent); + //End events + public: + DisplaySettings(); + virtual ~DisplaySettings(); + //IPlugin methods + virtual const string Initialize(PluginHost::IShell* service) override; + virtual void Deinitialize(PluginHost::IShell* service) override; + private: + void InitializeIARM(); + void DeinitializeIARM(); + static void ResolutionPreChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + static void ResolutionPostChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + static void DisplResolutionHandler(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 getConnectedVideoDisplaysHelper(std::vector& connectedDisplays); + public: + static DisplaySettings* _instance; + + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/DisplaySettings/DisplaySettings.json b/DisplaySettings/DisplaySettings.json new file mode 100644 index 0000000000..f2090e66d3 --- /dev/null +++ b/DisplaySettings/DisplaySettings.json @@ -0,0 +1,8 @@ +{ + "locator":"libWPEFrameworkDisplaySettings.so", + "classname":"DisplaySettings", + "precondition":[ + "Platform" + ], + "autostart":true +} \ No newline at end of file diff --git a/DisplaySettings/Module.cpp b/DisplaySettings/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/DisplaySettings/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/DisplaySettings/Module.h b/DisplaySettings/Module.h new file mode 100644 index 0000000000..69b2e7bfe2 --- /dev/null +++ b/DisplaySettings/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 DisplaySettings +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/DisplaySettings/README.md b/DisplaySettings/README.md new file mode 100644 index 0000000000..82950ec5cc --- /dev/null +++ b/DisplaySettings/README.md @@ -0,0 +1,19 @@ +----------------- +Build: + +bitbake thunder-plugins + +----------------- +Test: + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.DisplaySettings.1.getSupportedResolutions"}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.DisplaySettings.1.getSupportedTvResolutions"}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.DisplaySettings.1.getConnectedAudioPorts"}' http://127.0.0.1:9998/jsonrpc; + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.DisplaySettings.1.getSupportedAudioPorts"}' http://127.0.0.1:9998/jsonrpc; + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.DisplaySettings.1.getSupportedAudioModes", "params":{"audioPort":"HDMI0"}}' http://127.0.0.1:9998/jsonrpc; + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.DisplaySettings.1.getSoundMode", "params":{"videoDisplay":"HDMI0"}}' http://127.0.0.1:9998/jsonrpc; diff --git a/DisplaySettings/cmake/FindDS.cmake b/DisplaySettings/cmake/FindDS.cmake new file mode 100644 index 0000000000..caacbfb99a --- /dev/null +++ b/DisplaySettings/cmake/FindDS.cmake @@ -0,0 +1,33 @@ +# - 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_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/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/DisplaySettings/cmake/FindIARMBus.cmake b/DisplaySettings/cmake/FindIARMBus.cmake new file mode 100644 index 0000000000..775a33121b --- /dev/null +++ b/DisplaySettings/cmake/FindIARMBus.cmake @@ -0,0 +1,28 @@ +# - 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(IARMBUS_INCLUDE_DIRS NAMES libIARM.h PATH_SUFFIXES rdk/iarmbus) +find_path(IARMIR_INCLUDE_DIRS NAMES irMgr.h PATH_SUFFIXES rdk/iarmmgrs/ir) + +set(IARMBUS_LIBRARIES ${IARMBUS_LIBRARIES} CACHE PATH "Path to IARMBus library") +set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS}) +set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} 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/FrameRate/CMakeLists.txt b/FrameRate/CMakeLists.txt new file mode 100644 index 0000000000..4c45655ca6 --- /dev/null +++ b/FrameRate/CMakeLists.txt @@ -0,0 +1,22 @@ +set(PLUGIN_NAME FrameRate) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + FrameRate.cpp + Module.cpp + ../helpers/tptimer.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +target_include_directories(${MODULE_NAME} PRIVATE ../helpers) + +target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/FrameRate/FrameRate.config b/FrameRate/FrameRate.config new file mode 100644 index 0000000000..45b8850a4e --- /dev/null +++ b/FrameRate/FrameRate.config @@ -0,0 +1,4 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "com.comcast.FrameRate") + diff --git a/FrameRate/FrameRate.cpp b/FrameRate/FrameRate.cpp new file mode 100644 index 0000000000..a9986bf293 --- /dev/null +++ b/FrameRate/FrameRate.cpp @@ -0,0 +1,267 @@ +/** +* 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 "FrameRate.h" + +#include "utils.h" + +// Methods +#define METHOD_SET_COLLECTION_FREQUENCY "setCollectionFrequency" +#define METHOD_START_FPS_COLLECTION "startFpsCollection" +#define METHOD_STOP_FPS_COLLECTION "stopFpsCollection" +#define METHOD_UPDATE_FPS_COLLECTION "updateFps" + +// Events +#define EVENT_FPS_UPDATE "onFpsEvent" + +//Defines +#define DEFAULT_FPS_COLLECTION_TIME_IN_MILLISECONDS 10000 +#define MINIMUM_FPS_COLLECTION_TIME_IN_MILLISECONDS 100 +#define DEFAULT_MIN_FPS_VALUE 60 +#define DEFAULT_MAX_FPS_VALUE -1 + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(FrameRate, 1, 0); + + FrameRate* FrameRate::_instance = nullptr; + + FrameRate::FrameRate() + : AbstractPlugin() + { + LOGINFO(); + FrameRate::_instance = this; + + Register(METHOD_SET_COLLECTION_FREQUENCY, &FrameRate::setCollectionFrequencyWrapper, this); + Register(METHOD_START_FPS_COLLECTION, &FrameRate::startFpsCollectionWrapper, this); + Register(METHOD_STOP_FPS_COLLECTION, &FrameRate::stopFpsCollectionWrapper, this); + Register(METHOD_UPDATE_FPS_COLLECTION, &FrameRate::updateFpsWrapper, this); + + m_reportFpsTimer.connect( std::bind( &FrameRate::onReportFpsTimer, this ) ); + } + + FrameRate::~FrameRate() + { + LOGINFO(); + FrameRate::_instance = nullptr; + } + + uint32_t FrameRate::setCollectionFrequencyWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + int fpsFrequencyInMilliseconds = DEFAULT_FPS_COLLECTION_TIME_IN_MILLISECONDS; + if (parameters.HasLabel("frequency")) + { + fpsFrequencyInMilliseconds = std::stod(parameters["frequency"].String()); + } + setCollectionFrequency(fpsFrequencyInMilliseconds); + + returnResponse(true); + } + + uint32_t FrameRate::startFpsCollectionWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + returnResponse(startFpsCollection()); + } + + uint32_t FrameRate::stopFpsCollectionWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + returnResponse(stopFpsCollection()); + } + + uint32_t FrameRate::updateFpsWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + if (!parameters.HasLabel("newFpsValue")) + { + returnResponse(false); + } + + updateFps(parameters["newFpsValue"].Number()); + + returnResponse(true); + } + + /** + * @brief This function is used to get the amount of collection interval per milliseconds. + * + * @return Integer value of Amount of milliseconds per collection interval . + */ + int FrameRate::getCollectionFrequency() + { + return m_fpsCollectionFrequencyInMs; + } + + /** + * @brief This function is used to set the amount of collection interval per milliseconds. + * + * @param[in] frequencyInMs Amount of milliseconds per collection interval. + * @ingroup SERVMGR_ABSFRAMERATE_API + */ + void FrameRate::setCollectionFrequency(int frequencyInMs) + { + m_fpsCollectionFrequencyInMs = frequencyInMs; + } + + /** + * @brief This function is used to start the fps collection. Stop the fps timer before + * start the fps collection frequency. Fps collection frequency is updated to minimum fps + * collection time if the fps collection frequency is less than the minimum fps collection time + * and start the fps timer. + * + * @return true on success else false if there was an error. + * @ingroup SERVMGR_ABSFRAMERATE_API + */ + bool FrameRate::startFpsCollection() + { + if (m_fpsCollectionInProgress) + { + return false; + } + if (m_reportFpsTimer.isActive()) + { + m_reportFpsTimer.stop(); + } + m_minFpsValue = DEFAULT_MIN_FPS_VALUE; + m_maxFpsValue = DEFAULT_MAX_FPS_VALUE; + m_totalFpsValues = 0; + m_numberOfFpsUpdates = 0; + m_fpsCollectionInProgress = true; + int fpsCollectionFrequency = m_fpsCollectionFrequencyInMs; + if (fpsCollectionFrequency < MINIMUM_FPS_COLLECTION_TIME_IN_MILLISECONDS) + { + fpsCollectionFrequency = MINIMUM_FPS_COLLECTION_TIME_IN_MILLISECONDS; + } + m_reportFpsTimer.start(fpsCollectionFrequency); + enableFpsCollection(); + return true; + } + + /** + * @brief This function is used to stops the fps collection. Stop the fps timer before disable the + * fps collection. If the number of fps updates is greater than 0, update the fps collection by + * passing the minimum fps, maximum fps and average fps values and disable the fps collection. + * + * @return true on success or false if there was an error. + * @ingroup SERVMGR_ABSFRAMERATE_API + */ + bool FrameRate::stopFpsCollection() + { + if (m_reportFpsTimer.isActive()) + { + m_reportFpsTimer.stop(); + } + if (m_fpsCollectionInProgress) + { + m_fpsCollectionInProgress = false; + int averageFps = -1; + int minFps = -1; + int maxFps = -1; + if (m_numberOfFpsUpdates > 0) + { + averageFps = (m_totalFpsValues / m_numberOfFpsUpdates); + minFps = m_minFpsValue; + maxFps = m_maxFpsValue; + fpsCollectionUpdate(averageFps, minFps, maxFps); + } + disableFpsCollection(); + } + return true; + } + + /** + * @brief This function is used to update the FPS value. + * + * @param[in] newFpsValue Latest amount of milliseconds per collection interval. + * @ingroup SERVMGR_ABSFRAMERATE_API + */ + void FrameRate::updateFps(int newFpsValue) + { + if (newFpsValue > m_maxFpsValue) + { + m_maxFpsValue = newFpsValue; + } + if (newFpsValue < m_minFpsValue) + { + m_minFpsValue = newFpsValue; + } + m_totalFpsValues += newFpsValue; + m_numberOfFpsUpdates++; + m_lastFpsValue = newFpsValue; + } + + void FrameRate::fpsCollectionUpdate( int averageFps, int minFps, int maxFps ) + { + JsonObject params; + params["average"] = averageFps; + params["min"] = minFps; + params["max"] = maxFps; + + sendNotify(EVENT_FPS_UPDATE, params); + } + + void FrameRate::onReportFpsTimer() + { + std::lock_guard guard(m_callMutex); + + int averageFps = -1; + int minFps = -1; + int maxFps = -1; + if (m_numberOfFpsUpdates > 0) + { + averageFps = (m_totalFpsValues / m_numberOfFpsUpdates); + minFps = m_minFpsValue; + maxFps = m_maxFpsValue; + } + fpsCollectionUpdate(averageFps, minFps, maxFps); + if (m_lastFpsValue >= 0) + { + // store the last fps value just in case there are no updates + m_minFpsValue = m_lastFpsValue; + m_maxFpsValue = m_lastFpsValue; + m_totalFpsValues = m_lastFpsValue; + m_numberOfFpsUpdates = 1; + } + else + { + m_minFpsValue = DEFAULT_MIN_FPS_VALUE; + m_maxFpsValue = DEFAULT_MAX_FPS_VALUE; + m_totalFpsValues = 0; + m_numberOfFpsUpdates = 0; + } + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/FrameRate/FrameRate.h b/FrameRate/FrameRate.h new file mode 100644 index 0000000000..1dce86004c --- /dev/null +++ b/FrameRate/FrameRate.h @@ -0,0 +1,94 @@ +/** +* 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 "tptimer.h" + +#include "Module.h" +#include "utils.h" +#include "AbstractPlugin.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 FrameRate : public AbstractPlugin { + private: + + // We do not allow this plugin to be copied !! + FrameRate(const FrameRate&) = delete; + FrameRate& operator=(const FrameRate&) = delete; + + //Begin methods + uint32_t setCollectionFrequencyWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t startFpsCollectionWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t stopFpsCollectionWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t updateFpsWrapper(const JsonObject& parameters, JsonObject& response); + //End methods + + int getCollectionFrequency(); + void setCollectionFrequency(int frequencyInMs); + bool startFpsCollection(); + bool stopFpsCollection(); + void updateFps(int newFpsValue); + + void fpsCollectionUpdate( int averageFps, int minFps, int maxFps ); + + virtual void enableFpsCollection() {} + virtual void disableFpsCollection() {} + + void onReportFpsTimer(); + void onReportFpsTimerTest(); + + public: + FrameRate(); + virtual ~FrameRate(); + + public: + static FrameRate* _instance; + private: + int m_fpsCollectionFrequencyInMs; + int m_minFpsValue; + int m_maxFpsValue; + int m_totalFpsValues; + int m_numberOfFpsUpdates; + bool m_fpsCollectionInProgress; + //QTimer m_reportFpsTimer; + TpTimer m_reportFpsTimer; + int m_lastFpsValue; + + std::mutex m_callMutex; + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/FrameRate/Module.cpp b/FrameRate/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/FrameRate/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/FrameRate/Module.h b/FrameRate/Module.h new file mode 100644 index 0000000000..83626a1078 --- /dev/null +++ b/FrameRate/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 FrameRate +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/FrameRate/README.md b/FrameRate/README.md new file mode 100644 index 0000000000..4abe16c481 --- /dev/null +++ b/FrameRate/README.md @@ -0,0 +1,17 @@ +----------------- +Build: + +bitbake wpeframework-service-plugins + +or + +bitbake thunder-plugins + +----------------- +Test: + +curl -d '{"jsonrpc":"2.0","id":"3","params": {"frequency":1000},"method": "com.comcast.FrameRate.1.setCollectionFrequency"}' http://127.0.0.1:9998/jsonrpc +curl -d '{"jsonrpc":"2.0","id":"3","params": {"newFpsValue":60},"method": "com.comcast.FrameRate.1.updateFps"}' http://127.0.0.1:9998/jsonrpc +curl -d '{"jsonrpc":"2.0","id":"3","params": {"newFpsValue":30},"method": "com.comcast.FrameRate.1.updateFps"}' http://127.0.0.1:9998/jsonrpc +curl -d '{"jsonrpc":"2.0","id":"3","method": "com.comcast.FrameRate.1.startFpsCollection"}' http://127.0.0.1:9998/jsonrpc +curl -d '{"jsonrpc":"2.0","id":"3","method": "com.comcast.FrameRate.1.stopFpsCollection"}' http://127.0.0.1:9998/jsonrpc diff --git a/FrontPanel/CMakeLists.txt b/FrontPanel/CMakeLists.txt new file mode 100644 index 0000000000..ccf207f46b --- /dev/null +++ b/FrontPanel/CMakeLists.txt @@ -0,0 +1,35 @@ +set(PLUGIN_NAME FrontPanel) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + FrontPanel.cpp + Module.cpp + ../helpers/frontpanel.cpp + ../helpers/powerstate.cpp +) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +find_package(DS) +if (DS_FOUND) + find_package(IARMBus) + add_definitions(-DDS_FOUND) + target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) + target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) + target_include_directories(${MODULE_NAME} PRIVATE ../helpers) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${DS_LIBRARIES}) +# target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${DS_LIBRARIES}) +else (DS_FOUND) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +endif(DS_FOUND) + +#target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/FrontPanel/FrontPanel.config b/FrontPanel/FrontPanel.config new file mode 100644 index 0000000000..ce1d35e44a --- /dev/null +++ b/FrontPanel/FrontPanel.config @@ -0,0 +1,3 @@ +set (autostart false) +set (preconditions Platform) +set (callsign "org.rdk.FrontPanel") diff --git a/FrontPanel/FrontPanel.cpp b/FrontPanel/FrontPanel.cpp new file mode 100644 index 0000000000..437a051e26 --- /dev/null +++ b/FrontPanel/FrontPanel.cpp @@ -0,0 +1,907 @@ +/** +* 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 "FrontPanel.h" +#include "frontpanel.h" +#include + +#include "frontPanelIndicator.hpp" +#include "frontPanelConfig.hpp" +#include "frontPanelTextDisplay.hpp" + +#include "libIBus.h" +#include "rdk/iarmmgrs-hal/pwrMgr.h" + +#include "utils.h" + +#define SERVICE_NAME "FrontPanelService" +#define METHOD_FP_SET_BRIGHTNESS "setBrightness" +#define METHOD_FP_GET_BRIGHTNESS "getBrightness" +#define METHOD_FP_POWER_LED_ON "powerLedOn" +#define METHOD_FP_POWER_LED_OFF "powerLedOff" +#define METHOD_CLOCK_SET_BRIGHTNESS "setClockBrightness" +#define METHOD_CLOCK_GET_BRIGHTNESS "getClockBrightness" +#define METHOD_GET_FRONT_PANEL_LIGHTS "getFrontPanelLights" +#define METHOD_FP_GET_PREFERENCES "getPreferences" +#define METHOD_FP_SET_PREFERENCES "setPreferences" +#define METHOD_FP_SET_LED "setLED" +#define METHOD_FP_SET_BLINK "setBlink" +#define METHOD_FP_SET_24_HOUR_CLOCK "set24HourClock" +#define METHOD_FP_IS_24_HOUR_CLOCK "is24HourClock" +#define METHOD_FP_SET_CLOCKTESTPATTERN "setClockTestPattern" + +#define DATA_LED "data_led" +#define RECORD_LED "record_led" +#ifdef CLOCK_BRIGHTNESS_ENABLED +#define CLOCK_LED "clock_led" +#define TEXT_LED "Text" +#endif + +#ifdef USE_EXTENDED_ALL_SEGMENTS_TEXT_PATTERN +#define ALL_SEGMENTS_TEXT_PATTERN "88:88" +#else +#define ALL_SEGMENTS_TEXT_PATTERN "8888" +#endif + +#define DEFAULT_TEXT_PATTERN_UPDATE_INTERVAL 5 + +namespace +{ + + struct Mapping + { + const char *IArmBusName; + const char *SvcManagerName; + }; + + static struct Mapping name_mappings[] = { + { "Record" , "record_led"}, + { "Message" , "data_led"}, + { "Power" , "power_led"}, + { "Text" , "clock_led"}, + // TODO: add your mappings here + // { , }, + { 0, 0} + }; + + string svc2iarm(const string &name) + { + const char *s = name.c_str(); + + int i = 0; + while (name_mappings[i].SvcManagerName) + { + if (strcmp(s, name_mappings[i].SvcManagerName) == 0) + return name_mappings[i].IArmBusName; + i++; + } + return name; + } + + string iarm2svc(const string &name) + { + const char *s = name.c_str(); + + int i = 0; + while (name_mappings[i].IArmBusName) + { + if (strcmp(s, name_mappings[i].IArmBusName) == 0) + return name_mappings[i].SvcManagerName; + i++; + } + return name; + } + + JsonObject getFrontPanelIndicatorInfo(device::FrontPanelIndicator &indicator) + { + JsonObject returnResult; + int levels=0, min=0, max=0; + JsonObject indicatorInfo; + string range; + + indicator.getBrightnessLevels(levels, min, max); + range = (levels <=2)?"boolean":"int"; + indicatorInfo["range"] = range; + + indicatorInfo["min"] = JsonValue(min); + indicatorInfo["max"] = JsonValue(max); + + if (range == ("int")) + { + indicatorInfo["step"] = JsonValue((max-min)/levels); + } + JsonArray availableColors; + device::List colorsList = indicator.getSupportedColors(); + for (uint j = 0; j < colorsList.size(); j++) + { + // todo - device setting support needed to convert color into a string value + // and then add to the availableColors list + } + if (availableColors.Length() > 0) + { + indicatorInfo["colors"] = availableColors; + } + + indicatorInfo["colorMode"] = indicator.getColorMode(); + return indicatorInfo; + } +} + +namespace WPEFramework +{ + + namespace Plugin + { + SERVICE_REGISTRATION(FrontPanel, 1, 0); + + FrontPanel* FrontPanel::_instance = nullptr; + + static Core::TimerType patternUpdateTimer(64 * 1024, "PatternUpdateTimer"); + int FrontPanel::m_savedClockBrightness = -1; + int FrontPanel::m_LedDisplayPatternUpdateTimerInterval = DEFAULT_TEXT_PATTERN_UPDATE_INTERVAL; + + FrontPanel::FrontPanel() + : AbstractPlugin() + , m_iarmConnected(false) + , m_updateTimer(this) + { + LOGINFO(); + FrontPanel::_instance = this; + + registerMethod(METHOD_FP_SET_BRIGHTNESS, &FrontPanel::setBrightnessWrapper, this); + registerMethod(METHOD_FP_GET_BRIGHTNESS, &FrontPanel::getBrightnessWrapper, this); + registerMethod(METHOD_FP_POWER_LED_ON, &FrontPanel::powerLedOnWrapper, this); + registerMethod(METHOD_FP_POWER_LED_OFF, &FrontPanel::powerLedOffWrapper, this); + registerMethod(METHOD_CLOCK_SET_BRIGHTNESS, &FrontPanel::setClockBrightnessWrapper, this); + registerMethod(METHOD_CLOCK_GET_BRIGHTNESS, &FrontPanel::getClockBrightnessWrapper, this); + registerMethod(METHOD_GET_FRONT_PANEL_LIGHTS, &FrontPanel::getFrontPanelLightsWrapper, this); + registerMethod(METHOD_FP_GET_PREFERENCES, &FrontPanel::getPreferencesWrapper, this); + registerMethod(METHOD_FP_SET_PREFERENCES, &FrontPanel::setPreferencesWrapper, this); + registerMethod(METHOD_FP_SET_LED, &FrontPanel::setLEDWrapper, this); + registerMethod(METHOD_FP_SET_BLINK, &FrontPanel::setBlinkWrapper, this); + registerMethod(METHOD_FP_SET_24_HOUR_CLOCK, &FrontPanel::set24HourClockWrapper, this); + registerMethod(METHOD_FP_IS_24_HOUR_CLOCK, &FrontPanel::is24HourClockWrapper, this); + registerMethod(METHOD_FP_SET_CLOCKTESTPATTERN, &FrontPanel::setClockTestPatternWrapper, this); + + InitializeIARM(); + + CFrontPanel::instance()->start(); + CFrontPanel::instance()->addEventObserver(this); + loadPreferences(); + } + + FrontPanel::~FrontPanel() + { + LOGINFO(); + FrontPanel::_instance = nullptr; + + { + std::lock_guard lock(m_updateTimerMutex); + m_runUpdateTimer = false; + } + patternUpdateTimer.Revoke(m_updateTimer); + + DeinitializeIARM(); + } + + const void FrontPanel::InitializeIARM() + { + LOGINFO(); + + int isRegistered; + IARM_Result_t res = IARM_Bus_IsConnected("Front_Panel" , &isRegistered); + if(res != IARM_RESULT_SUCCESS) + { + IARM_CHECK( IARM_Bus_Init("Front_Panel") ); + IARM_CHECK( IARM_Bus_Connect() ); + m_iarmConnected = true; + } + } + + //TODO(MROLLINS) - we need to install crash handler to ensure DeinitializeIARM gets called + void FrontPanel::DeinitializeIARM() + { + LOGINFO(); + + if (m_iarmConnected) + { + m_iarmConnected = false; + IARM_Result_t res; + IARM_CHECK( IARM_Bus_Disconnect() ); + IARM_CHECK( IARM_Bus_Term() ); + } + } + + 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); + LOGINFO("%s: result json %s\n", __FUNCTION__, json.c_str()); + } + + /** + * @brief sets the brightness of the specified LED. Brightness must be a value support by + * the LED and the value of the brightness for this led must be persisted. + * + * @param[in] brightness Brightness value. + * + * @return Returns the result which will be true when the call to set brightness succeeded. + * @ingroup SERVMGR_FRONTPANEL_API + */ + bool FrontPanel::setBrightness( int brightness ) + { + bool ok; + ok = CFrontPanel::instance()->setBrightness(brightness); + return ok; + } + + uint32_t FrontPanel::setBrightnessWrapper(const JsonObject& parameters, JsonObject& response) + { + CFrontPanel::instance()->stopBlinkTimer(); + int brightness = -1; + bool ok = false; + + if (!parameters.HasLabel("brightness")) + { + LOGERR("Parameter 'brightness' wasn't passed"); + returnResponse(ok); + } + + getNumberParameter("brightness", brightness); + + if (parameters.HasLabel("index")) + { + /* frontpanel_3 */ + if (parameters.HasLabel("index")) + { + string fp_ind; + fp_ind = svc2iarm(parameters["index"].String()); + LOGWARN("FP calling setBrightness of %s", fp_ind.c_str()); + + if (brightness >= 0) + { + LOGWARN("FP calling setBrightness of %s to %d", fp_ind.c_str(), brightness); +#ifdef CLOCK_BRIGHTNESS_ENABLED + if (TEXT_LED == fp_ind) + { + setClockBrightness(int(brightness)); + ok = true; + } + else +#endif + { + try + { + device::FrontPanelIndicator::getInstance(fp_ind.c_str()).setBrightness(int(brightness)); + ok = true; + } + catch (...) + { + ok = false; + } + } + } + } + } + else + { + + if (brightness >= 0 && brightness <= 100) + { + LOGWARN("calling setBrightness"); + ok = setBrightness(brightness); + } + else + { + LOGWARN("Invalid brightnessLevel passed to method setBrightness CallMethod"); + } + } + + returnResponse(ok); + } + + /** + * @brief Gets the brightness value of the specified LED. + * + * @return brightness Integer. + */ + int FrontPanel::getBrightness() + { + int brightness = -1; + brightness = CFrontPanel::instance()->getBrightness(); + return brightness; + } + + /** + * @brief Gets the brightness of the specified LED. + * + * @param[in] argList List of arguments (Not used). + * + * @return Returns a ServiceParams object containing brightness value and function result. + * @ingroup SERVMGR_FRONTPANEL_API + */ + uint32_t FrontPanel::getBrightnessWrapper(const JsonObject& parameters, JsonObject& response) + { + int brightness = -1; + bool ok = false; + LOGWARN("calling getBrightness"); + + if (parameters.HasLabel("index")) + { + string fp_ind; + fp_ind = svc2iarm(parameters["index"].String()); + LOGWARN("FP3 calling getBrightness of %s", fp_ind.c_str()); +#ifdef CLOCK_BRIGHTNESS_ENABLED + if (TEXT_LED == fp_ind) + { + brightness = getClockBrightness(); + } + else +#endif + try + { + brightness = device::FrontPanelIndicator::getInstance(fp_ind.c_str()).getBrightness(); + } + catch (...) + { + LOGWARN("Exception thrown from ds while calling getBrightness"); + } + } + else + brightness = getBrightness(); + + response["brightness"] = brightness; + ok = brightness >= 0 ? true : false; + + returnResponse(ok); + } + + /** + * @brief This function is used to switches ON the particular LED. The LED must be powere ON + * prior to setting its brightness. It is done by invoking the powerOnLed function of CFrontPanel. + * + * @param[in] fp_indicator Possible enum values are "0"-clock, "1"-message, "2"-power, "3"-record, + * "4"-remote etc. + * + * @return true if the LED is switches ON successfully else false. + */ + bool FrontPanel::powerLedOn(frontPanelIndicator fp_indicator) + { + return CFrontPanel::instance()->powerOnLed(fp_indicator); + } + + uint32_t FrontPanel::powerLedOnWrapper(const JsonObject& parameters, JsonObject& response ) + { + string fp_ind; + bool ok = false; + + if (parameters.HasLabel("index")) + fp_ind = parameters["index"].String(); + if (fp_ind.compare(DATA_LED) == 0) + { + LOGWARN("calling powerOnLed"); + ok = powerLedOn(FRONT_PANEL_INDICATOR_MESSAGE); + } + else if (fp_ind.compare(RECORD_LED) == 0) + { + LOGWARN("calling powerOnLed"); + ok = powerLedOn(FRONT_PANEL_INDICATOR_RECORD); + } + returnResponse(ok); + } + + /** + * @brief This function is used to switches OFF the particular LED. It is done by invoking + * the powerOffLed function of CFrontPanel. + * + * @param[in] fp_indicator Possible enum values are "0"-clock, "1"-message, "2"-power, "3"-record, + * "4"-remote etc. + * + * @return true if the LED is switches OFF successfully else false. + */ + bool FrontPanel::powerLedOff(frontPanelIndicator fp_indicator) + { + bool ok; + ok = CFrontPanel::instance()->powerOffLed(fp_indicator); + return ok; + } + + uint32_t FrontPanel::powerLedOffWrapper(const JsonObject& parameters, JsonObject& response) + { + string fp_ind; + bool ok = false; + + if (parameters.HasLabel("index")) + fp_ind = parameters["index"].String(); + if (fp_ind.compare(DATA_LED) == 0) + { + LOGWARN("calling powerOffLed"); + ok = powerLedOff(FRONT_PANEL_INDICATOR_MESSAGE); + } + else if (fp_ind.compare(RECORD_LED) == 0) + { + LOGWARN("calling powerOffLed"); + ok = powerLedOff(FRONT_PANEL_INDICATOR_RECORD); + } + returnResponse(ok); + } + + bool FrontPanel::setClockBrightness(int brightness ) + { +#ifdef CLOCK_BRIGHTNESS_ENABLED + bool ok; + ok = CFrontPanel::instance()->setClockBrightness(brightness); + return ok; +#else + return false; +#endif + } + + uint32_t FrontPanel::setClockBrightnessWrapper(const JsonObject& parameters, JsonObject& response) + { + bool ok = false; + +#ifdef CLOCK_BRIGHTNESS_ENABLED + int brightness = -1; + + if (parameters.HasLabel("brightness")) + getNumberParameter("brightness", brightness); + + if (brightness >= 0 && brightness <= 100) + { + LOGWARN("calling setClockBrightness"); + ok = setClockBrightness(brightness); + } + else + { + LOGWARN("Invalid brightnessLevel passed to method setBrightness CallMethod"); + } +#else + LOGWARN("No operation for setClockBrightness"); +#endif + + + returnResponse(ok); + } + + + /** + * @brief get the clock brightness of the specified LED. Brightness must be a value support by the + * LED and the value of the brightness for this led must be persisted. + * + * @return The brightness integer value if clock brightness enable macro is true else it will return -1. + */ + int FrontPanel::getClockBrightness() + { +#ifdef CLOCK_BRIGHTNESS_ENABLED + int brightness = -1; + brightness = CFrontPanel::instance()->getClockBrightness(); + return brightness; +#else + return -1; +#endif + } + + uint32_t FrontPanel::getClockBrightnessWrapper(const JsonObject& parameters, JsonObject& response) + { + bool ok = false; +#ifdef CLOCK_BRIGHTNESS_ENABLED + int brightness = -1; + LOGWARN("calling getClockBrightness"); + brightness = getClockBrightness(); + if (0 <= brightness) + ok = true; + response["brightness"] = brightness; +#else + LOGWARN("No operation for getClockBrightness"); +#endif + returnResponse(ok); + } + + /** + * @brief getFrontPanelLights This returns an object containing attributes of front panel + * light: success, supportedLights, and supportedLightsInfo. + * supportedLights defines the LED lights that can be controlled through the Front Panel API. + * supportedLightsInfo defines a hash of objects describing each LED light. + * success - false if the supported lights info was unable to be determined. + * + * @return Returns a list of front panel lights parameter. + * @ingroup SERVMGR_FRONTPANEL_API + */ + std::vector FrontPanel::getFrontPanelLights() + { + std::vector lights; + device::List fpIndicators = device::FrontPanelConfig::getInstance().getIndicators(); + for (uint i = 0; i < fpIndicators.size(); i++) + { + string IndicatorNameIarm = fpIndicators.at(i).getName(); + string MappedName = iarm2svc(IndicatorNameIarm); + if (MappedName != IndicatorNameIarm) lights.push_back(MappedName); + } +#ifdef CLOCK_BRIGHTNESS_ENABLED + try + { + device::List fpTextDisplays = device::FrontPanelConfig::getInstance().getTextDisplays(); + for (uint i = 0; i < fpTextDisplays.size(); i++) + { + string TextDisplayNameIarm = fpTextDisplays.at(i).getName(); + string MappedName = iarm2svc(TextDisplayNameIarm); + if (MappedName != TextDisplayNameIarm) + { + lights.push_back(MappedName); + } + } + } + catch (...) + { + LOGERR("Exception while getFrontPanelLights"); + } +#endif + return lights; + } + + /** + * @brief getFrontPanelLightsInfo This returns an object containing attributes of front + * panel light: success, supportedLights, and supportedLightsInfo. + * supportedLightsInfo defines a hash of objects describing each LED light properties such as + * -"range" Determines the types of values that can be expected in min and max value. + * -"min" The minimum value is equivalent to off i.e "0". + * -"max" The maximum value is when the LED is on i.e "1" and at its brightest. + * -"step" The step or interval between the min and max values supported by the LED. + * -"colorMode" Defines enum of "0" LED's color cannot be changed, "1" LED can be set to any color + * (using rgb-hex code),"2" LED can be set to an enumeration of colors as specified by the + * supportedColors property. + * + * @return Returns a serviceParams list of front panel lights info. + */ + JsonObject FrontPanel::getFrontPanelLightsInfo() + { + JsonObject returnResult; + JsonObject indicatorInfo; + string IndicatorNameIarm, MappedName; + + device::List fpIndicators = device::FrontPanelConfig::getInstance().getIndicators(); + for (uint i = 0; i < fpIndicators.size(); i++) + { + IndicatorNameIarm = fpIndicators.at(i).getName(); + MappedName = iarm2svc(IndicatorNameIarm); + if (MappedName != IndicatorNameIarm) + { + indicatorInfo = getFrontPanelIndicatorInfo(fpIndicators.at(i)); + returnResult[MappedName.c_str()] = indicatorInfo; + } + } + +#ifdef CLOCK_BRIGHTNESS_ENABLED + try + { + indicatorInfo = getFrontPanelIndicatorInfo(device::FrontPanelConfig::getInstance().getTextDisplay(0)); + returnResult[CLOCK_LED] = indicatorInfo; + } + catch (...) + { + LOGERR("Exception while getFrontPanelLightsInfo"); + } +#endif + return returnResult; + } + + + uint32_t FrontPanel::getFrontPanelLightsWrapper(const JsonObject& parameters, JsonObject& response) + { + /*CID 17850 removing logically dead code */ + + LOGWARN("sending getFrontPanelLights"); + setResponseArray(response, "supportedLights", getFrontPanelLights()); + response["supportedLightsInfo"] = getFrontPanelLightsInfo(); + returnResponse(true); + } + + + /** + * @brief Returns the preferences object as stored in setPreferences. + * + * @return Attribute key value pair list. + */ + JsonObject FrontPanel::getPreferences() + { + return CFrontPanel::instance()->getPreferences(); + } + + /** + * @brief This method stores the preferences into persistent storage. + * It does not change the colour of any LEDs. It invoking the setPreferences + * method of cFrontPanel class to set the preference data. + * + * @param[in] preferences Key value pair of preferences data. + * + * @return Returns the success code of underlying method. + */ + void FrontPanel::setPreferences(const JsonObject& preferences) + { + CFrontPanel::instance()->setPreferences(preferences); + } + + void FrontPanel::loadPreferences() + { + CFrontPanel::instance()->loadPreferences(); + } + + uint32_t FrontPanel::getPreferencesWrapper(const JsonObject& parameters, JsonObject& response) + { + response["preferences"] = getPreferences(); + returnResponse(true); + } + + /** + * @brief This method stores the preferences into persistent storage. + * It does not change the color of any LEDs. The preferences object is not validated. + * It is up to the client of this API to ensure that preference values are valid. + * + * @param[in] argList List of preferences. + * @return Returns the success code of underlying method. + * @ingroup SERVMGR_FRONTPANEL_API + */ + uint32_t FrontPanel::setPreferencesWrapper(const JsonObject& parameters, JsonObject& response) + { + bool success = false; + + if (parameters.HasLabel("preferences")) + { + JsonObject preferences = parameters["preferences"].Object(); + setPreferences(preferences); + success = true; + } + returnResponse(success); + } + + /** + * @brief Sets the brightness and color properties of the specified LED. + * The supported properties of the info object passed in will be determined by the color + * mode of the LED. If the colorMode of an LED is 0 color values will be ignored. If the + * brightness of the LED is unspecified or value = -1, then the persisted or default + * value for the system is used. + * + * @param[in] properties Key value pair of properties data. + * + * @return Returns success value of the helper method, returns false in case of failure. + */ + bool FrontPanel::setLED(const JsonObject& properties) + { + bool success = false; + success = CFrontPanel::instance()->setLED(properties); + return success; + } + + /** + * @brief Specifies a blinking pattern for an LED. This method returns immediately, but starts + * a process of iterating through each element in the array and lighting the LED with the specified + * brightness and color (if applicable) for the given duration (in milliseconds). + * + * @param[in] blinkInfo Object containing Indicator name, blink pattern and duration. + * @ingroup SERVMGR_FRONTPANEL_API + */ + void FrontPanel::setBlink(const JsonObject& blinkInfo) + { + CFrontPanel::instance()->setBlink(blinkInfo); + } + + /** + * @brief Specifies the 24 hour clock format. + * + * @param[in] is24Hour true if 24 hour clock format. + * @ingroup SERVMGR_FRONTPANEL_API + */ + void FrontPanel::set24HourClock(bool is24Hour) + { + CFrontPanel::instance()->set24HourClock(is24Hour); + } + + /** + * @brief Get the 24 hour clock format. + * + * @return true if 24 hour clock format is used. + * @ingroup SERVMGR_FRONTPANEL_API + */ + bool FrontPanel::is24HourClock() + { + bool is24Hour = false; + is24Hour = CFrontPanel::instance()->is24HourClock(); + return is24Hour; + } + + + /** + * @brief Enable or disable showing test pattern 88:88 on stbs with clock displays. + * + * @param[in] show true to show pattern, false to restore display to default behavior, usual it's clock. + * @param[in] interval (optional) interval in seconds to check and update LED display with pattern, when it's overridden by external API. + * from 1 to 60 seconds. 0 and other outbound values mean that timer isn't used and isn't activated by this call. + * Optionally the timer is enabled for 5 seconds interval. + * @return true if method succeeded. + * @ingroup SERVMGR_FRONTPANEL_API + */ + void FrontPanel::setClockTestPattern(bool show) + { + #ifdef CLOCK_BRIGHTNESS_ENABLED + device::FrontPanelTextDisplay& display = device::FrontPanelConfig::getInstance().getTextDisplay("Text"); + + if (show) + { + if (m_LedDisplayPatternUpdateTimerInterval > 0 && m_LedDisplayPatternUpdateTimerInterval < 61) + { + { + std::lock_guard lock(m_updateTimerMutex); + m_runUpdateTimer = true; + } + patternUpdateTimer.Schedule(Core::Time::Now().Add(m_LedDisplayPatternUpdateTimerInterval * 1000), m_updateTimer); + + LOGWARN("%s: LED FP display update timer activated with interval %ds", __FUNCTION__, m_LedDisplayPatternUpdateTimerInterval); + } + else + { + LOGWARN("%s: LED FP display update timer didn't used for interval value %d. To activate it, interval should be in bound of values from 1 till 60" + , __FUNCTION__, m_LedDisplayPatternUpdateTimerInterval); + + { + std::lock_guard lock(m_updateTimerMutex); + m_runUpdateTimer = false; + } + patternUpdateTimer.Revoke(m_updateTimer); + } + + if (-1 == m_savedClockBrightness) + { + m_savedClockBrightness = getClockBrightness(); + LOGWARN("%s: brightness of LED FP display %d was saved", __FUNCTION__, m_savedClockBrightness); + } + + display.setMode(1); //Set Front Panel Display to Text Mode + display.setText(ALL_SEGMENTS_TEXT_PATTERN); + setClockBrightness(100); + LOGWARN("%s: pattern " ALL_SEGMENTS_TEXT_PATTERN " activated on LED FP display with max brightness", __FUNCTION__); + } + else + { + { + std::lock_guard lock(m_updateTimerMutex); + m_runUpdateTimer = false; + } + patternUpdateTimer.Revoke(m_updateTimer); + + display.setMode(0);//Set Front Panel Display to Default Mode + display.setText(" "); + LOGWARN("%s: pattern " ALL_SEGMENTS_TEXT_PATTERN " deactivated on LED FP display", __FUNCTION__); + + if (-1 != m_savedClockBrightness) + { + setClockBrightness(m_savedClockBrightness); + LOGWARN("%s: brightness %d of LED FP display restored", __FUNCTION__, m_savedClockBrightness); + m_savedClockBrightness = -1; + } + } + #else + LOGWARN("%s: disabled for this platform", __FUNCTION__); + #endif + } + + + + + uint32_t FrontPanel::setLEDWrapper(const JsonObject& parameters, JsonObject& response) + { + bool success = false; + + /*if (parameters.HasLabel("properties")) + { + JsonObject properties = parameters["properties"].Object(); + success = setLED(properties); + }*/ + success = setLED(parameters); + returnResponse(success); + } + + uint32_t FrontPanel::setBlinkWrapper(const JsonObject& parameters, JsonObject& response) + { + bool success = false; + + if (parameters.HasLabel("blinkInfo")) + { + JsonObject blinkInfo = parameters["blinkInfo"].Object(); + setBlink(blinkInfo); + success = true; + } + returnResponse(success); + } + + uint32_t FrontPanel::set24HourClockWrapper(const JsonObject& parameters, JsonObject& response) + { + bool success = false; + + if (parameters.HasLabel("is24Hour")) + { + bool is24Hour = false; + getBoolParameter("is24Hour", is24Hour ); + set24HourClock(is24Hour); + success = true; + } + returnResponse(success); + } + + uint32_t FrontPanel::is24HourClockWrapper(const JsonObject& parameters, JsonObject& response) + { + bool is24Hour = is24HourClock(); + response["is24Hour"] = is24Hour; + returnResponse(true); + } + + uint32_t FrontPanel::setClockTestPatternWrapper(const JsonObject& parameters, JsonObject& response) + { + if (!parameters.HasLabel("show")) + { + LOGWARN("'show' parameter wasn't passed"); + returnResponse(false); + } + + bool show = false; + getBoolParameter("show", show); + + m_LedDisplayPatternUpdateTimerInterval = DEFAULT_TEXT_PATTERN_UPDATE_INTERVAL; + if (parameters.HasLabel("timerInterval")) + getNumberParameter("timerInterval", m_LedDisplayPatternUpdateTimerInterval); + + setClockTestPattern(show); + + returnResponse(true); + } + + void FrontPanel::updateLedTextPattern() + { + LOGWARN("%s: override FP LED display with text pattern " ALL_SEGMENTS_TEXT_PATTERN, __FUNCTION__); + + if (getClockBrightness() != 100) + { + setClockBrightness(100); + } + + device::FrontPanelConfig::getInstance().getTextDisplay("Text").setText(ALL_SEGMENTS_TEXT_PATTERN); + LOGWARN("%s: LED display updated by pattern " ALL_SEGMENTS_TEXT_PATTERN, __FUNCTION__); + + { + std::lock_guard lock(m_updateTimerMutex); + if (m_runUpdateTimer) + patternUpdateTimer.Schedule(Core::Time::Now().Add(m_LedDisplayPatternUpdateTimerInterval * 1000), m_updateTimer); + } + } + + uint64_t TestPatternInfo::Timed(const uint64_t scheduledTime) + { + uint64_t result = 0; + m_frontPanel->updateLedTextPattern(); + return(result); + } + + + } // namespace Plugin +} // namespace WPEFramework diff --git a/FrontPanel/FrontPanel.h b/FrontPanel/FrontPanel.h new file mode 100644 index 0000000000..678f8dde6c --- /dev/null +++ b/FrontPanel/FrontPanel.h @@ -0,0 +1,148 @@ +/** +* 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 "Module.h" + +#include "utils.h" +#include "AbstractPlugin.h" + +#include "frontpanel.h" + +#define DATA_LED "data_led" +#define RECORD_LED "record_led" +#ifdef CLOCK_BRIGHTNESS_ENABLED +#define CLOCK_LED "clock_led" +#define TEXT_LED "Text" +#endif + +namespace WPEFramework { + + namespace Plugin { + + class TestPatternInfo + { + private: + TestPatternInfo() = delete; + TestPatternInfo& operator=(const TestPatternInfo& RHS) = delete; + + public: + TestPatternInfo(FrontPanel* fp) + : m_frontPanel(fp) + { + } + TestPatternInfo(const TestPatternInfo& copy) + : m_frontPanel(copy.m_frontPanel) + { + } + ~TestPatternInfo() {} + + inline bool operator==(const TestPatternInfo& RHS) const + { + return(m_frontPanel == RHS.m_frontPanel); + } + + public: + uint64_t Timed(const uint64_t scheduledTime); + + private: + FrontPanel* m_frontPanel; + }; + + + // 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 FrontPanel : public AbstractPlugin { + private: + // We do not allow this plugin to be copied !! + FrontPanel(const FrontPanel&) = delete; + FrontPanel& operator=(const FrontPanel&) = delete; + + bool setBrightness(int brightness); + int getBrightness(); + bool powerLedOn(frontPanelIndicator fp_indicator); + bool powerLedOff(frontPanelIndicator fp_indicator); + bool setClockBrightness(int brightness); + int getClockBrightness(); + std::vector getFrontPanelLights(); + JsonObject getFrontPanelLightsInfo(); + JsonObject getPreferences(); + void setPreferences(const JsonObject& preferences); + bool setLED(const JsonObject& properties); + void setBlink(const JsonObject& blinkInfo); + void set24HourClock(bool is24Hour); + bool is24HourClock(); + void setClockTestPattern(bool show); + + void loadPreferences(); + + //Begin methods + uint32_t setBrightnessWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getBrightnessWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t powerLedOnWrapper(const JsonObject& parameters, JsonObject& response ); + uint32_t powerLedOffWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setClockBrightnessWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getClockBrightnessWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getFrontPanelLightsWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getPreferencesWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setPreferencesWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setLEDWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setBlinkWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t set24HourClockWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t is24HourClockWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setClockTestPatternWrapper(const JsonObject& parameters, JsonObject& response); + //End methods + + public: + FrontPanel(); + virtual ~FrontPanel(); + + void updateLedTextPattern(); + + private: + const void InitializeIARM(); + void DeinitializeIARM(); + + public: + static FrontPanel* _instance; + private: + bool m_iarmConnected; + static int m_savedClockBrightness; + static int m_LedDisplayPatternUpdateTimerInterval; + + TestPatternInfo m_updateTimer; + bool m_runUpdateTimer; + std::mutex m_updateTimerMutex; + + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/FrontPanel/FrontPanel.json b/FrontPanel/FrontPanel.json new file mode 100644 index 0000000000..4e439a4bdf --- /dev/null +++ b/FrontPanel/FrontPanel.json @@ -0,0 +1,8 @@ +{ + "locator":"libWPEFrameworkFrontPanel.so", + "classname":"FrontPanel", + "precondition":[ + "Platform" + ], + "autostart":true +} \ No newline at end of file diff --git a/FrontPanel/Module.cpp b/FrontPanel/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/FrontPanel/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/FrontPanel/Module.h b/FrontPanel/Module.h new file mode 100644 index 0000000000..a4e2eb022e --- /dev/null +++ b/FrontPanel/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 FrontPanel +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/FrontPanel/README.md b/FrontPanel/README.md new file mode 100644 index 0000000000..700c570822 --- /dev/null +++ b/FrontPanel/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": "FrontPanel.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/FrontPanel/cmake/FindDS.cmake b/FrontPanel/cmake/FindDS.cmake new file mode 100644 index 0000000000..caacbfb99a --- /dev/null +++ b/FrontPanel/cmake/FindDS.cmake @@ -0,0 +1,33 @@ +# - 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_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/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/FrontPanel/cmake/FindIARMBus.cmake b/FrontPanel/cmake/FindIARMBus.cmake new file mode 100644 index 0000000000..c0e0571e17 --- /dev/null +++ b/FrontPanel/cmake/FindIARMBus.cmake @@ -0,0 +1,29 @@ +# - 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(IARMBUS_INCLUDE_DIRS NAMES libIARM.h PATH_SUFFIXES rdk/iarmbus) +find_path(IARMIR_INCLUDE_DIRS NAMES irMgr.h PATH_SUFFIXES rdk/iarmmgrs/ir) +find_path(IARMPWR_INCLUDE_DIRS NAMES pwrMgr.h PATH_SUFFIXES rdk/iarmmgrs-hal) + +set(IARMBUS_LIBRARIES ${IARMBUS_LIBRARIES} CACHE PATH "Path to IARMBus library") +set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${IARMPWR_INCLUDE_DIRS}) +set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${IARMPWR_INCLUDE_DIRS} 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/HdcpProfile/CMakeLists.txt b/HdcpProfile/CMakeLists.txt new file mode 100644 index 0000000000..796e4fa33a --- /dev/null +++ b/HdcpProfile/CMakeLists.txt @@ -0,0 +1,26 @@ +set(PLUGIN_NAME HdcpProfile) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + HdcpProfile.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +find_package(DS) +find_package(IARMBus) + +target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) +target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) + +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/HdcpProfile/HdcpProfile.config b/HdcpProfile/HdcpProfile.config new file mode 100644 index 0000000000..8966c8bd30 --- /dev/null +++ b/HdcpProfile/HdcpProfile.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "com.comcast.HdcpProfile") diff --git a/HdcpProfile/HdcpProfile.cpp b/HdcpProfile/HdcpProfile.cpp new file mode 100644 index 0000000000..265e27c7af --- /dev/null +++ b/HdcpProfile/HdcpProfile.cpp @@ -0,0 +1,266 @@ +/** +* 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 "HdcpProfile.h" + +#include "videoOutputPort.hpp" +#include "videoOutputPortConfig.hpp" +#include "dsMgr.h" + +#include "utils.h" + +#define HDMI_HOT_PLUG_EVENT_CONNECTED 0 +#define HDMI_HOT_PLUG_EVENT_DISCONNECTED 1 + +#define HDCP_PROFILE_METHOD_GET_HDCP_STATUS "getHDCPStatus" +#define HDCP_PROFILE_METHOD_GET_SETTOP_HDCP_SUPPORT "getSettopHDCPSupport" +#define HDCP_PROFILE_METHOD_SET_HDCPPROFILE "setHDCPProfile" +#define HDCP_PROFILE_METHOD_GET_HDCPPROFILE "getHDCPProfile" + +#define HDCP_PROFILE_EVT_ON_DISPLAY_CONNECTION_CHANGED "onDisplayConnectionChanged" + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(HdcpProfile, 1, 0); + + HdcpProfile* HdcpProfile::_instance = nullptr; + + HdcpProfile::HdcpProfile() + : AbstractPlugin() + { + LOGINFO(); + HdcpProfile::_instance = this; + + InitializeIARM(); + + registerMethod(HDCP_PROFILE_METHOD_GET_HDCP_STATUS, &HdcpProfile::getHDCPStatusWrapper, this); + registerMethod(HDCP_PROFILE_METHOD_GET_SETTOP_HDCP_SUPPORT, &HdcpProfile::getSettopHDCPSupportWrapper, this); + } + + HdcpProfile::~HdcpProfile() + { + LOGINFO(); + HdcpProfile::_instance = nullptr; + + DeinitializeIARM(); + } + + void HdcpProfile::InitializeIARM() + { + LOGINFO(); + + int isRegistered; + IARM_Result_t res = IARM_Bus_IsConnected("HdcpProfile" , &isRegistered); + if(res != IARM_RESULT_SUCCESS) + { + IARM_CHECK( IARM_Bus_Init("HdcpProfile") ); + IARM_CHECK( IARM_Bus_Connect() ); + m_iarmConnected = true; + } + + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, dsHdmiEventHandler) ); + } + + //TODO(MROLLINS) - we need to install crash handler to ensure DeinitializeIARM gets called + void HdcpProfile::DeinitializeIARM() + { + LOGINFO(); + + if (m_iarmConnected) + { + m_iarmConnected = false; + IARM_Result_t res; + + IARM_CHECK( IARM_Bus_UnRegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG) ); + + IARM_CHECK( IARM_Bus_Disconnect() ); + IARM_CHECK( IARM_Bus_Term() ); + } + } + + uint32_t HdcpProfile::getHDCPStatusWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + response["HDCPStatus"] = getHDCPStatus(); + returnResponse(true); + } + + uint32_t HdcpProfile::getSettopHDCPSupportWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + device::VideoOutputPort vPort = device::VideoOutputPortConfig::getInstance().getPort("HDMI0"); + dsHdcpProtocolVersion_t hdcpProtocol = (dsHdcpProtocolVersion_t)vPort.getHDCPProtocol(); + + if(hdcpProtocol == dsHDCP_VERSION_2X) + { + response["supportedHDCPVersion"] = "2.2"; + LOGWARN("supportedHDCPVersion :2.2"); + } + else + { + response["supportedHDCPVersion"] = "1.4"; + LOGWARN("supportedHDCPVersion :1.4"); + } + + response["isHDCPSupported"] = true; + + returnResponse(true); + } + + JsonObject HdcpProfile::getHDCPStatus() + { + LOGINFO(); + + JsonObject hdcpStatus; + + bool isConnected = false; + bool isHDCPCompliant = false; + bool isHDCPEnabled = true; + dsHdcpProtocolVersion_t hdcpProtocol = dsHDCP_VERSION_MAX; + dsHdcpProtocolVersion_t hdcpReceiverProtocol = dsHDCP_VERSION_MAX; + dsHdcpProtocolVersion_t hdcpCurrentProtocol = dsHDCP_VERSION_MAX; + + try + { + device::VideoOutputPort vPort = device::VideoOutputPortConfig::getInstance().getPort("HDMI0"); + isConnected = vPort.isDisplayConnected(); + hdcpProtocol = (dsHdcpProtocolVersion_t)vPort.getHDCPProtocol(); + if(isConnected) + { + isHDCPCompliant = (vPort.getHDCPStatus() == dsHDCP_STATUS_AUTHENTICATED); + isHDCPEnabled = vPort.isContentProtected(); + hdcpReceiverProtocol = (dsHdcpProtocolVersion_t)vPort.getHDCPReceiverProtocol(); + hdcpCurrentProtocol = (dsHdcpProtocolVersion_t)vPort.getHDCPCurrentProtocol(); + } + else + { + isHDCPCompliant = false; + isHDCPEnabled = false; + } + } + catch (const std::exception e) + { + LOGWARN("DS exception caught from %s\r\n", __FUNCTION__); + } + + hdcpStatus["isConnected"] = isConnected; + hdcpStatus["isHDCPCompliant"] = isHDCPCompliant; + hdcpStatus["isHDCPEnabled"] = isHDCPEnabled; + if(hdcpProtocol == dsHDCP_VERSION_2X) + { + hdcpStatus["supportedHDCPVersion"] = "2.2"; + } + else + { + hdcpStatus["supportedHDCPVersion"] = "1.4"; + } + + if(hdcpReceiverProtocol == dsHDCP_VERSION_2X) + { + hdcpStatus["receiverHDCPVersion"] = "2.2"; + } + else + { + hdcpStatus["receiverHDCPVersion"] = "1.4"; + } + + if(hdcpCurrentProtocol == dsHDCP_VERSION_2X) + { + hdcpStatus["currentHDCPVersion"] = "2.2"; + } + else + { + hdcpStatus["currentHDCPVersion"] = "1.4"; + } + + logHdcpStatus("Request", hdcpStatus); + return hdcpStatus; + } + + void HdcpProfile::onHdmiOutputHotPlug(int connectStatus) + { + LOGINFO(); + + if (HDMI_HOT_PLUG_EVENT_CONNECTED == connectStatus) + LOGWARN(" %s Status : %d \n",__FUNCTION__, connectStatus); + + JsonObject status = getHDCPStatus(); + JsonObject params; + params["HDCPStatus"] = status; + sendNotify(HDCP_PROFILE_EVT_ON_DISPLAY_CONNECTION_CHANGED, params); + + logHdcpStatus("Hotplug", status); + return; + } + + void HdcpProfile::logHdcpStatus (const char *trigger, const JsonObject& status) + { + LOGWARN("[%s]-HDCPStatus::isConnected : %s", trigger, status["isConnected"].Boolean() ? "true" : "false"); + LOGWARN("[%s]-HDCPStatus::isHDCPEnabled: %s", trigger, status["isHDCPEnabled"].Boolean() ? "true" : "false"); + LOGWARN("[%s]-HDCPStatus::isHDCPCompliant: %s", trigger, status["isHDCPCompliant"].Boolean() ? "true" : "false"); + LOGWARN("[%s]-HDCPStatus::supportedHDCPVersion: %s", trigger, status["supportedHDCPVersion"].String().c_str()); + LOGWARN("[%s]-HDCPStatus::receiverHDCPVersion: %s", trigger, status["receiverHDCPVersion"].String().c_str()); + LOGWARN("[%s]-HDCPStatus::currentHDCPVersion %s", trigger, status["currentHDCPVersion"].String().c_str()); + } + + void HdcpProfile::onHdmiOutputHDCPStatusEvent(int hdcpStatus) + { + LOGINFO(); + + JsonObject status = getHDCPStatus(); + JsonObject params; + params["HDCPStatus"] = status; + sendNotify(HDCP_PROFILE_EVT_ON_DISPLAY_CONNECTION_CHANGED, params); + + logHdcpStatus("AuthRslt", status); + return; + } + + void HdcpProfile::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + LOGINFO(); + + if(!HdcpProfile::_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); + + HdcpProfile::_instance->onHdmiOutputHotPlug(hdmi_hotplug_event); + } + else if (IARM_BUS_DSMGR_EVENT_HDCP_STATUS == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + int hdcpStatus = eventData->data.hdmi_hdcp.hdcpStatus; + LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDCP_STATUS event data:%d \r\n", hdcpStatus); + HdcpProfile::_instance->onHdmiOutputHDCPStatusEvent(hdcpStatus); + + } + } + + } // namespace Plugin +} // namespace WPEFramework + diff --git a/HdcpProfile/HdcpProfile.h b/HdcpProfile/HdcpProfile.h new file mode 100644 index 0000000000..a68d4af885 --- /dev/null +++ b/HdcpProfile/HdcpProfile.h @@ -0,0 +1,78 @@ +/** +* 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 "utils.h" +#include "AbstractPlugin.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 HdcpProfile : public AbstractPlugin { + private: + + // We do not allow this plugin to be copied !! + HdcpProfile(const HdcpProfile&) = delete; + HdcpProfile& operator=(const HdcpProfile&) = delete; + + void InitializeIARM(); + void DeinitializeIARM(); + + //Begin methods + uint32_t getHDCPStatusWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getSettopHDCPSupportWrapper(const JsonObject& parameters, JsonObject& response); + + //End methods + + JsonObject getHDCPStatus(); + void onHdmiOutputHotPlug(int connectStatus); + void onHdmiOutputHDCPStatusEvent(int); + void logHdcpStatus (const char *trigger, const JsonObject& status); + static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + + public: + HdcpProfile(); + virtual ~HdcpProfile(); + + void terminate(); + + static HdcpProfile* _instance; + private: + bool m_iarmConnected; + }; + } // namespace Plugin +} // namespace WPEFramework + diff --git a/HdcpProfile/Module.cpp b/HdcpProfile/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/HdcpProfile/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/HdcpProfile/Module.h b/HdcpProfile/Module.h new file mode 100644 index 0000000000..37209a3b5d --- /dev/null +++ b/HdcpProfile/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 HdcpProfile +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/HdcpProfile/README.md b/HdcpProfile/README.md new file mode 100644 index 0000000000..3ef1f1cf8c --- /dev/null +++ b/HdcpProfile/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": "HdcpProfile.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/HdmiCec/CMakeLists.txt b/HdmiCec/CMakeLists.txt new file mode 100644 index 0000000000..1cede0443f --- /dev/null +++ b/HdmiCec/CMakeLists.txt @@ -0,0 +1,28 @@ +set(PLUGIN_NAME HdmiCec) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + HdmiCec.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} ) + + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/HdmiCec/HdmiCec.config b/HdmiCec/HdmiCec.config new file mode 100644 index 0000000000..4fc953a283 --- /dev/null +++ b/HdmiCec/HdmiCec.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "com.comcast.HdmiCec") diff --git a/HdmiCec/HdmiCec.cpp b/HdmiCec/HdmiCec.cpp new file mode 100644 index 0000000000..41c7dad555 --- /dev/null +++ b/HdmiCec/HdmiCec.cpp @@ -0,0 +1,619 @@ +/** +* 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.h" + + +#include "ccec/Connection.hpp" +#include "ccec/CECFrame.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 "websocket/URL.h" + +#include "utils.h" + +#define HDMICEC_METHOD_SET_ENABLED "setEnabled" +#define HDMICEC_METHOD_GET_ENABLED "getEnabled" +#define HDMICEC_METHOD_GET_CEC_ADDRESSES "getCECAddresses" +#define HDMICEC_METHOD_SEND_MESSAGE "sendMessage" + +#define HDMICEC_EVENT_ON_DEVICES_CHANGED "onDevicesChanged" +#define HDMICEC_EVENT_ON_MESSAGE "onMessage" +#define HDMICEC_EVENT_ON_HDMI_HOT_PLUG "onHdmiHotPlug" +#define HDMICEC_EVENT_ON_CEC_ADDRESS_CHANGE "cecAddressesChanged" + +#define PHYSICAL_ADDR_CHANGED 1 +#define LOGICAL_ADDR_CHANGED 2 +#define DEV_TYPE_TUNER 1 + +#define HDMI_HOT_PLUG_EVENT_CONNECTED 0 + +#if defined(HAS_PERSISTENT_IN_HDD) +#define CEC_SETTING_ENABLED_FILE "/tmp/mnt/diska3/persistent/ds/cecData.json" +#elif defined(HAS_PERSISTENT_IN_FLASH) +#define CEC_SETTING_ENABLED_FILE "/opt/persistent/ds/cecData.json" +#else +#define CEC_SETTING_ENABLED_FILE "/opt/ds/cecData.json" +#endif + +#define CEC_SETTING_ENABLED "cecEnabled" + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(HdmiCec, 1, 0); + + HdmiCec* HdmiCec::_instance = nullptr; + + static int libcecInitStatus = 0; + + HdmiCec::HdmiCec() + : AbstractPlugin() + { + LOGINFO(); + HdmiCec::_instance = this; + + InitializeIARM(); + + registerMethod(HDMICEC_METHOD_SET_ENABLED, &HdmiCec::setEnabledWrapper, this); + registerMethod(HDMICEC_METHOD_GET_ENABLED, &HdmiCec::getEnabledWrapper, this); + registerMethod(HDMICEC_METHOD_GET_CEC_ADDRESSES, &HdmiCec::getCECAddressesWrapper, this); + registerMethod(HDMICEC_METHOD_SEND_MESSAGE, &HdmiCec::sendMessageWrapper, this); + + physicalAddress = 0x0F0F0F0F; + + logicalAddressDeviceType = "None"; + logicalAddress = 0xFF; + + loadSettings(); + if (cecSettingEnabled) + { + setEnabled(cecSettingEnabled); + } + else + { + setEnabled(false); + persistSettings(false); + } + } + + HdmiCec::~HdmiCec() + { + LOGINFO(); + HdmiCec::_instance = nullptr; + + DeinitializeIARM(); + + } + + const void HdmiCec::InitializeIARM() + { + LOGINFO(); + + int isRegistered; + IARM_Result_t res = IARM_Bus_IsConnected("HdmiCec" , &isRegistered); + if(res != IARM_RESULT_SUCCESS) + { + IARM_CHECK( IARM_Bus_Init("HdmiCec") ); + IARM_CHECK( IARM_Bus_Connect() ); + m_iarmConnected = true; + } + + //IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_CECHOST_NAME, IARM_BUS_CECHost_EVENT_DEVICESTATUSCHANGE,cecDeviceStatusEventHandler) ); // It didn't do anything in original service + 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) ); + } + + //TODO(MROLLINS) - we need to install crash handler to ensure DeinitializeIARM gets called + void HdmiCec::DeinitializeIARM() + { + LOGINFO(); + + if (m_iarmConnected) + { + m_iarmConnected = false; + IARM_Result_t res; + + //IARM_CHECK( IARM_Bus_UnRegisterEventHandler(IARM_BUS_CECHOST_NAME, IARM_BUS_CECHost_EVENT_DEVICESTATUSCHANGE) ); + IARM_CHECK( IARM_Bus_UnRegisterEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED) ); + IARM_CHECK( IARM_Bus_UnRegisterEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_STATUS_UPDATED) ); + IARM_CHECK( IARM_Bus_UnRegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG) ); + + IARM_CHECK( IARM_Bus_Disconnect() ); + IARM_CHECK( IARM_Bus_Term() ); + } + } + + void HdmiCec::cecMgrEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + LOGINFO(); + + if(!HdmiCec::_instance) + return; + + if( !strcmp(owner, IARM_BUS_CECMGR_NAME)) + { + switch (eventId) + { + case IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED: + { + HdmiCec::_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::_instance->cecStatusUpdated(evtData); + } + } + break; + default: + /*Do nothing*/ + break; + } + } + } + + void HdmiCec::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + LOGINFO(); + + if(!HdmiCec::_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::_instance->onHdmiHotPlug(hdmi_hotplug_event); + } + } + + void HdmiCec::onCECDaemonInit() + { + LOGINFO(); + + if(true == getEnabled()) + { + setEnabled(false); + setEnabled(true); + } + else + { + /*Do nothing as CEC is not already enabled*/ + } + } + + void HdmiCec::cecStatusUpdated(void *evtStatus) + { + LOGINFO(); + + IARM_Bus_CECMgr_Status_Updated_Param_t *evtData = (IARM_Bus_CECMgr_Status_Updated_Param_t *)evtStatus; + if(evtData) + { + try{ + getPhysicalAddress(); + + unsigned int logicalAddr = evtData->logicalAddress; + std::string logicalAddrDeviceType = DeviceType(LogicalAddress(evtData->logicalAddress).getType()).toString().c_str(); + + LOGWARN("cecLogicalAddressUpdated: logical address updated: %d , saved : %d ", logicalAddr, logicalAddress); + if (logicalAddr != logicalAddress || logicalAddrDeviceType != logicalAddressDeviceType) + { + logicalAddress = logicalAddr; + logicalAddressDeviceType = logicalAddrDeviceType; + cecAddressesChanged(LOGICAL_ADDR_CHANGED); + } + } + catch (const std::exception e) + { + LOGWARN("CEC exception caught from cecStatusUpdated"); + } + + delete evtData; + } + return; + } + + void HdmiCec::onHdmiHotPlug(int connectStatus) + { + LOGINFO(); + + if (HDMI_HOT_PLUG_EVENT_CONNECTED == connectStatus) + { + LOGWARN("onHdmiHotPlug Status : %d ", connectStatus); + getPhysicalAddress(); + getLogicalAddress(); + } + return; + } + + uint32_t HdmiCec::setEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + bool enabled = false; + + if (parameters.HasLabel("enabled")) + { + getBoolParameter("enabled", enabled); + } + else + { + returnResponse(false); + } + + setEnabled(enabled); + returnResponse(true); + } + + uint32_t HdmiCec::getEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + response["enabled"] = getEnabled(); + returnResponse(true); + } + + uint32_t HdmiCec::getCECAddressesWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + response["CECAddresses"] = getCECAddresses(); + + returnResponse(true); + } + + uint32_t HdmiCec::sendMessageWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + std::string message; + + if (parameters.HasLabel("message")) + { + message = parameters["message"].String(); + } + else + { + returnResponse(false); + } + + sendMessage(message); + returnResponse(true); + } + + bool HdmiCec::loadSettings() + { + Core::File file; + file = CEC_SETTING_ENABLED_FILE; + + file.Open(); + JsonObject parameters; + parameters.FromFile(file); + + file.Close(); + + getBoolParameter(CEC_SETTING_ENABLED, cecSettingEnabled); + + return cecSettingEnabled; + } + + void HdmiCec::persistSettings(bool enableStatus) + { + Core::File file; + file = CEC_SETTING_ENABLED_FILE; + + file.Open(false); + if (!file.IsOpen()) + file.Create(); + + JsonObject cecSetting; + cecSetting[CEC_SETTING_ENABLED] = enableStatus; + + cecSetting.ToFile(file); + + file.Close(); + + return; + } + + void HdmiCec::setEnabled(bool enabled) + { + LOGWARN("Entered setEnabled "); + + if (cecSettingEnabled != enabled) + { + persistSettings(enabled); + } + if(true == enabled) + { + CECEnable(); + } + else + { + CECDisable(); + } + return; + } + + void HdmiCec::CECEnable(void) + { + LOGWARN("Entered CECEnable"); + if (cecEnableStatus) + { + LOGWARN("CEC Already Enabled"); + return; + } + + if(0 == libcecInitStatus) + { + try + { + LibCCEC::getInstance().init(); + } + catch (const std::exception e) + { + LOGWARN("CEC exception caught from CECEnable"); + } + } + libcecInitStatus++; + + smConnection = new Connection(LogicalAddress::UNREGISTERED,false,"ServiceManager::Connection::"); + smConnection->open(); + smConnection->addFrameListener(this); + + //Acquire CEC Addresses + getPhysicalAddress(); + getLogicalAddress(); + + cecEnableStatus = true; + return; + } + + void HdmiCec::CECDisable(void) + { + LOGWARN("Entered CECDisable "); + + if(!cecEnableStatus) + { + LOGWARN("CEC Already Disabled "); + return; + } + + if (smConnection != NULL) + { + smConnection->close(); + delete smConnection; + smConnection = NULL; + } + cecEnableStatus = false; + + if(1 == libcecInitStatus) + { + LibCCEC::getInstance().term(); + } + + libcecInitStatus--; + + return; + } + + + void HdmiCec::getPhysicalAddress() + { + LOGINFO("Entered getPhysicalAddress "); + + uint32_t physAddress = 0x0F0F0F0F; + + try { + LibCCEC::getInstance().getPhysicalAddress(&physAddress); + + LOGINFO("getPhysicalAddress: physicalAddress: %x %x %x %x ", (physAddress >> 24) & 0xFF, (physAddress >> 16) & 0xFF, (physAddress >> 8) & 0xFF, (physAddress) & 0xFF); + if (physAddress != physicalAddress) + { + physicalAddress = physAddress; + cecAddressesChanged(PHYSICAL_ADDR_CHANGED); + } + } + catch (const std::exception e) + { + LOGWARN("DS exception caught from getPhysicalAddress"); + } + return; + } + + void HdmiCec::getLogicalAddress() + { + LOGINFO("Entered getLogicalAddress "); + + try{ + int addr = LibCCEC::getInstance().getLogicalAddress(DEV_TYPE_TUNER); + + std::string logicalAddrDeviceType = DeviceType(LogicalAddress(addr).getType()).toString().c_str(); + + LOGWARN("logical address obtained is %d , saved logical address is %d ", addr, logicalAddress); + + if ((int)logicalAddress != addr || logicalAddressDeviceType != logicalAddrDeviceType) + + { + logicalAddress = addr; + logicalAddressDeviceType = logicalAddrDeviceType; + cecAddressesChanged(LOGICAL_ADDR_CHANGED); + } + } + catch (const std::exception e) + { + LOGWARN("CEC exception caught from getLogicalAddress "); + } + + return; + } + + bool HdmiCec::getEnabled() + { + LOGWARN("Entered getEnabled "); + if(true == cecEnableStatus) + return true; + else + return false; + } + + void HdmiCec::setName(std::string name) + { + //SVCLOG_WARN("%s \r\n",__FUNCTION__); + return; + } + + std::string HdmiCec::getName() + { + //SVCLOG_WARN("%s \r\n",__FUNCTION__); + IARM_Result_t ret = IARM_RESULT_INVALID_STATE; + if (ret != IARM_RESULT_SUCCESS) + { + LOGWARN("getName :: IARM_BUS_CEC_HOST_GetOSDName failed "); + return "STB"; + } + + return "STB"; + } + + JsonObject HdmiCec::getCECAddresses() + { + JsonObject CECAddress; + LOGINFO("Entered getCECAddresses "); + + JsonArray pa; + pa.Add((physicalAddress >> 24) & 0xff); + pa.Add((physicalAddress >> 16) & 0xff); + pa.Add((physicalAddress >> 8) & 0xff); + pa.Add( physicalAddress & 0xff); + + CECAddress["physicalAddress"] = pa; + + JsonObject logical; + logical["deviceType"] = logicalAddressDeviceType; + logical["logicalAddress"] = logicalAddress; + + JsonArray logicalArray; + logicalArray.Add(logical); + + CECAddress["logicalAddresses"] = logicalArray; + LOGWARN("getCECAddresses: physicalAddress from QByteArray : %x %x %x %x ", (physicalAddress >> 24) & 0xFF, (physicalAddress >> 16) & 0xFF, (physicalAddress >> 8) & 0xFF, (physicalAddress) & 0xFF); + LOGWARN("getCECAddresses: logical address: %x ", logicalAddress); + + return CECAddress; + } + + void HdmiCec::sendMessage(std::string message) + { + LOGINFO("sendMessage "); + + if(true == cecEnableStatus) + { + std::vector buf; + buf.resize(message.size()); + + uint16_t decodedLen = Core::URL::Base64Decode(message.c_str(), message.size(), (uint8_t*)buf.data(), buf.size()); + CECFrame frame = CECFrame((const uint8_t *)buf.data(), decodedLen); + // SVCLOG_WARN("Frame to be sent from servicemanager in %s \n",__FUNCTION__); + // frame.hexDump(); + smConnection->sendAsync(frame); + } + else + LOGWARN("cecEnableStatus=false"); + return; + } + + void HdmiCec::cecAddressesChanged(int changeStatus) + { + LOGINFO(); + + JsonObject params; + JsonObject CECAddresses; + + LOGWARN(" cecAddressesChanged Change Status : %d ", changeStatus); + if(PHYSICAL_ADDR_CHANGED == changeStatus) + { + CECAddresses["physicalAddress"] = physicalAddress; + } + else if(LOGICAL_ADDR_CHANGED == changeStatus) + { + CECAddresses["logicalAddresses"] = logicalAddress; + } + else + { + //Do Nothing + } + + params["CECAddresses"] = CECAddresses; + LOGWARN(" cecAddressesChanged send : %s ", HDMICEC_EVENT_ON_CEC_ADDRESS_CHANGE); + + sendNotify(HDMICEC_EVENT_ON_CEC_ADDRESS_CHANGE, params); + + return; + } + + void HdmiCec::notify(const CECFrame &in) const + { + LOGINFO("Inside notify "); + size_t length; + const uint8_t *input_frameBuf = NULL; + CECFrame Frame = in; + // SVCLOG_WARN("Frame received by servicemanager is \n"); + // Frame.hexDump(); + Frame.getBuffer(&input_frameBuf,&length); + + std::vector buf; + buf.resize(length * 2); + + uint16_t encodedLen = Core::URL::Base64Encode(input_frameBuf, length, buf.data(), buf.size()); + buf[encodedLen] = 0; + + (const_cast(this))->onMessage(buf.data()); + return; + } + + void HdmiCec::onMessage( const char *message ) + { + JsonObject params; + params["message"] = message; + sendNotify(HDMICEC_EVENT_ON_MESSAGE, params); + } + + } // namespace Plugin +} // namespace WPEFramework + + + diff --git a/HdmiCec/HdmiCec.h b/HdmiCec/HdmiCec.h new file mode 100644 index 0000000000..62114a9fab --- /dev/null +++ b/HdmiCec/HdmiCec.h @@ -0,0 +1,110 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2019 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#include +#include "ccec/FrameListener.hpp" +#include "ccec/Connection.hpp" + +#include "libIBus.h" + +#undef Assert // this define from Connection.hpp conflicts with WPEFramework + +#include "Module.h" +#include "utils.h" +#include "AbstractPlugin.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 HdmiCec : public AbstractPlugin, public FrameListener { + private: + + // We do not allow this plugin to be copied !! + HdmiCec(const HdmiCec&) = delete; + HdmiCec& operator=(const HdmiCec&) = delete; + + //Begin methods + uint32_t setEnabledWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getEnabledWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getCECAddressesWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendMessageWrapper(const JsonObject& parameters, JsonObject& response); + //End methods + + + public: + HdmiCec(); + virtual ~HdmiCec(); + + public: + static HdmiCec* _instance; + private: + bool m_iarmConnected; + std::string logicalAddressDeviceType; + unsigned int logicalAddress; + unsigned int physicalAddress; + bool cecSettingEnabled; + bool cecEnableStatus; + Connection *smConnection; + + 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 setEnabled(bool enabled); + void CECEnable(void); + void CECDisable(void); + void getPhysicalAddress(); + void getLogicalAddress(); + bool getEnabled(); + void setName(std::string name); + std::string getName(); + JsonObject getCECAddresses(); + void sendMessage(std::string message); + void cecAddressesChanged(int changeStatus); + + void notify(const CECFrame &in) const; + void onMessage(const char *message); + + }; + } // namespace Plugin +} // namespace WPEFramework + + diff --git a/HdmiCec/Module.cpp b/HdmiCec/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/HdmiCec/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/Module.h b/HdmiCec/Module.h new file mode 100644 index 0000000000..e0d6532738 --- /dev/null +++ b/HdmiCec/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 HdmiCec +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/HdmiCec/README.md b/HdmiCec/README.md new file mode 100644 index 0000000000..228d4f6a37 --- /dev/null +++ b/HdmiCec/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": "HdmiCec.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/HdmiInput/CMakeLists.txt b/HdmiInput/CMakeLists.txt new file mode 100644 index 0000000000..4e694e19fa --- /dev/null +++ b/HdmiInput/CMakeLists.txt @@ -0,0 +1,29 @@ +set(PLUGIN_NAME HdmiInput) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + HdmiInput.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +list(APPEND CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") + +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) + +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.config b/HdmiInput/HdmiInput.config new file mode 100644 index 0000000000..85809727f2 --- /dev/null +++ b/HdmiInput/HdmiInput.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "com.comcast.HdmiInput") diff --git a/HdmiInput/HdmiInput.cpp b/HdmiInput/HdmiInput.cpp new file mode 100644 index 0000000000..bec75e9c95 --- /dev/null +++ b/HdmiInput/HdmiInput.cpp @@ -0,0 +1,214 @@ +/** +* 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 "utils.h" + +#include "hdmiIn.hpp" + +#include "dsMgr.h" + +#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_EVENT_ON_DEVICES_CHANGED "onDevicesChanged" + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(HdmiInput, 1, 0); + + HdmiInput* HdmiInput::_instance = nullptr; + + HdmiInput::HdmiInput() + : AbstractPlugin() + , m_iarmConnected(false) + { + LOGINFO(); + HdmiInput::_instance = this; + + InitializeIARM(); + + 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); + } + + HdmiInput::~HdmiInput() + { + LOGINFO(); + HdmiInput::_instance = nullptr; + + DeinitializeIARM(); + } + + void HdmiInput::InitializeIARM() + { + LOGINFO(); + + int isRegistered; + IARM_Result_t res = IARM_Bus_IsConnected("HdmiInput" , &isRegistered); + if(res != IARM_RESULT_SUCCESS) + { + IARM_CHECK( IARM_Bus_Init("HdmiInput") ); + IARM_CHECK( IARM_Bus_Connect() ); + m_iarmConnected = true; + } + + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); + } + + //TODO(MROLLINS) - we need to install crash handler to ensure DeinitializeIARM gets called + void HdmiInput::DeinitializeIARM() + { + LOGINFO(); + + if (m_iarmConnected) + { + m_iarmConnected = false; + IARM_Result_t res; + + IARM_CHECK( IARM_Bus_UnRegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG) ); + + IARM_CHECK( IARM_Bus_Disconnect() ); + IARM_CHECK( IARM_Bus_Term() ); + } + } + + uint32_t HdmiInput::getHDMIInputDevicesWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + response["devices"] = getHDMIInputDevices(); + + returnResponse(true); + } + + uint32_t HdmiInput::writeEDIDWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + 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) + { + LOGINFO(); + + response["name"] = readEDID(); + + 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() + { + return "HdmiInputEDIDStub"; + } + + /** + * @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); + } + + void HdmiInput::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + LOGINFO(); + + 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); + } + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/HdmiInput/HdmiInput.h b/HdmiInput/HdmiInput.h new file mode 100644 index 0000000000..8dc26e8a7f --- /dev/null +++ b/HdmiInput/HdmiInput.h @@ -0,0 +1,80 @@ +/** +* 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 "utils.h" +#include "AbstractPlugin.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 HdmiInput : public AbstractPlugin { + private: + + // We do not allow this plugin to be copied !! + HdmiInput(const HdmiInput&) = delete; + HdmiInput& operator=(const HdmiInput&) = delete; + + void InitializeIARM(); + void DeinitializeIARM(); + + //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); + //End methods + + JsonArray getHDMIInputDevices(); + void writeEDID(int deviceId, std::string message); + std::string readEDID(); + + void hdmiInputHotplug( int input , int connect); + static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + + public: + HdmiInput(); + virtual ~HdmiInput(); + + void terminate(); + + public: + static HdmiInput* _instance; + + private: + bool m_iarmConnected; + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/HdmiInput/Module.cpp b/HdmiInput/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /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 0000000000..1fd03e9436 --- /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 HdmiInput +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/HdmiInput/README.md b/HdmiInput/README.md new file mode 100644 index 0000000000..998e3280d8 --- /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 0000000000..70df45d567 --- /dev/null +++ b/HdmiInput/cmake/FindDS.cmake @@ -0,0 +1,41 @@ +# - 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/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 0000000000..e2250b0d29 --- /dev/null +++ b/HdmiInput/cmake/FindIARMBus.cmake @@ -0,0 +1,27 @@ +# - 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/LICENSE b/LICENSE new file mode 100644 index 0000000000..c94c89cc05 --- /dev/null +++ b/LICENSE @@ -0,0 +1,218 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + +-------------------------------------------------------------------------- + +The BSD-2 License: +-------------- +Copyright + +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 HOLDERS AND 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 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. + +-------------------------------------------------------------------------- + diff --git a/LoggingPreferences/CMakeLists.txt b/LoggingPreferences/CMakeLists.txt new file mode 100644 index 0000000000..80479b8787 --- /dev/null +++ b/LoggingPreferences/CMakeLists.txt @@ -0,0 +1,30 @@ +set(PLUGIN_NAME LoggingPreferences) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + LoggingPreferences.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +target_include_directories(${MODULE_NAME} PRIVATE ../helpers) + +find_package(DS) +if (DS_FOUND) + find_package(IARMBus) + add_definitions(-DDS_FOUND) + target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) + target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${DS_LIBRARIES}) +else (DS_FOUND) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +endif(DS_FOUND) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/LoggingPreferences/LoggingPreferences.config b/LoggingPreferences/LoggingPreferences.config new file mode 100644 index 0000000000..54e04e8e5c --- /dev/null +++ b/LoggingPreferences/LoggingPreferences.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "org.rdk.LoggingPreferences") diff --git a/LoggingPreferences/LoggingPreferences.cpp b/LoggingPreferences/LoggingPreferences.cpp new file mode 100644 index 0000000000..7c0746d660 --- /dev/null +++ b/LoggingPreferences/LoggingPreferences.cpp @@ -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. +**/ + +#include "LoggingPreferences.h" +#include + +using namespace std; + +namespace WPEFramework { + + namespace Plugin { + + SERVICE_REGISTRATION(LoggingPreferences, 1, 0); + + LoggingPreferences* LoggingPreferences::_instance = nullptr; + + LoggingPreferences::LoggingPreferences() + : AbstractPlugin() + { + LOGINFO("ctor"); + LoggingPreferences::_instance = this; + registerMethod("isKeystrokeMaskEnabled", &LoggingPreferences::isKeystrokeMaskEnabled, this); + registerMethod("setKeystrokeMaskEnabled", &LoggingPreferences::setKeystrokeMaskEnabled, this); + } + + LoggingPreferences::~LoggingPreferences() + { + LOGINFO("dtor"); + LoggingPreferences::_instance = nullptr; + } + + const string LoggingPreferences::Initialize(PluginHost::IShell* /* service */) + { + LOGINFO(); + InitializeIARM(); + return ""; + } + + void LoggingPreferences::Deinitialize(PluginHost::IShell* /* service */) + { + LOGINFO(); + DeinitializeIARM(); + } + + void LoggingPreferences::InitializeIARM() + { + LOGINFO(); + IARM_Result_t res; + IARM_CHECK( IARM_Bus_Init("LoggingPreferences") ); + IARM_CHECK( IARM_Bus_Connect() ); + } + + void LoggingPreferences::DeinitializeIARM() + { + LOGINFO(); + IARM_Result_t res; + IARM_CHECK( IARM_Bus_Disconnect() ); + IARM_CHECK( IARM_Bus_Term() ); + } + + //Begin methods + uint32_t LoggingPreferences::isKeystrokeMaskEnabled(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + IARM_BUS_SYSMGR_KEYCodeLoggingInfo_Param_t param; + IARM_Result_t res = IARM_Bus_Call(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_API_GetKeyCodeLoggingPref, (void *)¶m, sizeof(param)); + if(res != IARM_RESULT_SUCCESS) + { + LOGERR("IARM call failed with status %d while reading preferences", res); + returnResponse(false); + } + + response["keystrokeMaskEnabled"] = !!param.logStatus; + returnResponse(true); + } + uint32_t LoggingPreferences::setKeystrokeMaskEnabled(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + returnIfBooleanParamNotFound(parameters, "keystrokeMaskEnabled"); + + IARM_BUS_SYSMGR_KEYCodeLoggingInfo_Param_t params; + IARM_Result_t res = IARM_Bus_Call(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_API_GetKeyCodeLoggingPref, (void *)¶ms, sizeof(params)); + if (res != IARM_RESULT_SUCCESS) + { + LOGERR("IARM call failed with status %d while reading preferences", res); + returnResponse(false); + } + + bool enabled = parameters["keystrokeMaskEnabled"].Boolean(); + + if (enabled != params.logStatus) + { + params = { enabled ? 1 : 0 }; + IARM_Result_t res = IARM_Bus_Call(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_API_SetKeyCodeLoggingPref, (void *)¶ms, sizeof(params)); + if (res != IARM_RESULT_SUCCESS) + { + LOGERR("IARM call failed with status %d while setting preferences", res); + returnResponse(false); + } + + onKeystrokeMaskEnabledChange(enabled); + } + else + { + LOGWARN("Keystroke mask already %s", enabled ? "enabled" : "disabled"); + } + + returnResponse(true); + } + //End methods + + //Begin events + void LoggingPreferences::onKeystrokeMaskEnabledChange(bool enabled) + { + JsonObject params; + params["keystrokeMaskEnabled"] = enabled; + sendNotify("onKeystrokeMaskEnabledChange", params); + } + //End events + + } // namespace Plugin +} // namespace WPEFramework diff --git a/LoggingPreferences/LoggingPreferences.h b/LoggingPreferences/LoggingPreferences.h new file mode 100644 index 0000000000..ec22e345db --- /dev/null +++ b/LoggingPreferences/LoggingPreferences.h @@ -0,0 +1,65 @@ +/** +* 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 "Module.h" +#include "libIBus.h" +#include "irMgr.h" + +#include "utils.h" +#include "AbstractPlugin.h" + +namespace WPEFramework { + + namespace Plugin { + + class LoggingPreferences : public AbstractPlugin { + private: + + LoggingPreferences(const LoggingPreferences&) = delete; + LoggingPreferences& operator=(const LoggingPreferences&) = delete; + + //Begin methods + uint32_t isKeystrokeMaskEnabled(const JsonObject& parameters, JsonObject& response); + uint32_t setKeystrokeMaskEnabled(const JsonObject& parameters, JsonObject& response); + //End methods + + //Begin events + void onKeystrokeMaskEnabledChange(bool enabled); + //End events + + public: + LoggingPreferences(); + virtual ~LoggingPreferences(); + + //IPlugin methods + virtual const string Initialize(PluginHost::IShell* service) override; + virtual void Deinitialize(PluginHost::IShell* service) override; + + private: + void InitializeIARM(); + void DeinitializeIARM(); + + public: + static LoggingPreferences* _instance; + + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/LoggingPreferences/Module.cpp b/LoggingPreferences/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/LoggingPreferences/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/LoggingPreferences/Module.h b/LoggingPreferences/Module.h new file mode 100644 index 0000000000..e75fc12fd0 --- /dev/null +++ b/LoggingPreferences/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 LoggingPreferences +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/LoggingPreferences/README.md b/LoggingPreferences/README.md new file mode 100644 index 0000000000..503cf8c7da --- /dev/null +++ b/LoggingPreferences/README.md @@ -0,0 +1,15 @@ +----------------- +Build: + +bitbake thunder-plugins + +----------------- +Test: + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.LoggingPreferences.1.setKeystrokeMaskEnabled", "params":{"keystrokeMaskEnabled":false}}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.LoggingPreferences.1.isKeystrokeMaskEnabled"}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.LoggingPreferences.1.setKeystrokeMaskEnabled", "params":{"keystrokeMaskEnabled":true}}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.LoggingPreferences.1.isKeystrokeMaskEnabled"}' http://127.0.0.1:9998/jsonrpc \ No newline at end of file diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000000..50eaef213a --- /dev/null +++ b/NOTICE @@ -0,0 +1,5 @@ +Copyright 2018 RDK Management +Licensed under the Apache License, Version 2.0 + +Copyright (C) 2012 Raphael Kubo da Costa +Licensed under the BSD-2 license diff --git a/Proxies/CMakeLists.txt b/Proxies/CMakeLists.txt new file mode 100644 index 0000000000..2685b200b2 --- /dev/null +++ b/Proxies/CMakeLists.txt @@ -0,0 +1,32 @@ +set(PLUGIN_NAME Proxies) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) +find_package(GLIB REQUIRED) + +add_library(${MODULE_NAME} SHARED + Proxies.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +find_library(GLIB_LIBRARY NAMES glib-2.0 ) + +target_include_directories(${MODULE_NAME} + PRIVATE + ../helpers + ${GLIB_INCLUDE_DIRS} +) + +target_link_libraries(${MODULE_NAME} + PRIVATE + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${GLIB_LIBRARIES} +) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/Proxies/Module.cpp b/Proxies/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/Proxies/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/Proxies/Module.h b/Proxies/Module.h new file mode 100644 index 0000000000..b6a1487231 --- /dev/null +++ b/Proxies/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 Proxies +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/Proxies/Proxies.config b/Proxies/Proxies.config new file mode 100644 index 0000000000..48ebd3ccf5 --- /dev/null +++ b/Proxies/Proxies.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "org.rdk.Proxies") diff --git a/Proxies/Proxies.cpp b/Proxies/Proxies.cpp new file mode 100644 index 0000000000..43dc28c0d7 --- /dev/null +++ b/Proxies/Proxies.cpp @@ -0,0 +1,222 @@ +/** +* 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 "Proxies.h" + +#include +#include +#include +#include + +#define PROXIES_CONFIGURATION_PATH "/opt/apps/common" +#define PROXIES_CONFIGURATION_FILE PROXIES_CONFIGURATION_PATH "/proxies.conf" + +using namespace std; + +namespace WPEFramework { + + namespace Plugin { + + SERVICE_REGISTRATION(Proxies, 1, 0); + + Proxies* Proxies::_instance = nullptr; + + Proxies::Proxies() + : AbstractPlugin() + { + LOGINFO("ctor"); + Proxies::_instance = this; + registerMethod("getProxy", &Proxies::getProxy, this); + registerMethod("setProxy", &Proxies::setProxy, this); + } + + Proxies::~Proxies() + { + LOGINFO("dtor"); + Proxies::_instance = nullptr; + } + + //Begin methods + uint32_t Proxies::getProxy(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + returnIfStringParamNotFound(parameters, "name"); + + string name = parameters["name"].String(); + + if (regex_search(name, regex("[^A-Za-z0-9_-]+"))) + { + LOGERR("Proxy name '%s' has not allowed symbols and should have only letters, numbers, underscores and hyphens", name.c_str()); + returnResponse(false); + } + + if (!createKeyFileIfNotExists()) + { + returnResponse(false); + } + + GKeyFile * proxies_conf_file = g_key_file_new(); + if(!proxies_conf_file) + { + LOGERR("Failed to g_key_file_new()"); + returnResponse(false); + } + + GError * error = nullptr; + if(!g_key_file_load_from_file(proxies_conf_file, PROXIES_CONFIGURATION_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) + { + LOGERR("Failed to load from file '%s': %s", PROXIES_CONFIGURATION_FILE, error->message); + returnResponse(false); + } + + gchar * group = g_key_file_get_start_group(proxies_conf_file); + + if (group == nullptr) + { + LOGERR("Unable to read group 'Proxies' from file '%s'", PROXIES_CONFIGURATION_FILE); + returnResponse(false); + } + + if(0 != strcmp(group, "Proxies")) + { + LOGERR("No group 'Proxies' in file '%s'", PROXIES_CONFIGURATION_FILE); + g_free(group); + g_key_file_free(proxies_conf_file); + returnResponse(false); + } + + gchar * uri = g_key_file_get_string(proxies_conf_file, group, name.c_str(), &error); + g_free(group); + + response["uri"] = NULL == uri ? "" : string(uri); + g_free(uri); + + g_key_file_free(proxies_conf_file); + returnResponse(true); + } + + uint32_t Proxies::setProxy(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + returnIfStringParamNotFound(parameters, "name"); + returnIfStringParamNotFound(parameters, "uri"); + + string name = parameters["name"].String(); + + if (name.length() == 0) + { + LOGERR("Proxy name should not be empty"); + returnResponse(false); + } + + if (regex_search(name, regex("[^A-Za-z0-9_-]+"))) + { + LOGERR("Proxy name '%s' has not allowed symbols and should have only letters, numbers, underscores and hyphens", name.c_str()); + returnResponse(false); + } + + string uri = parameters["uri"].String(); + + int uriLength = uri.length(); + if (uriLength > 255) + { + LOGERR("Length of proxy uri '%s' is %d, but should be less than 256", uri.c_str(), uri.length()); + returnResponse(false); + } + + if (!createKeyFileIfNotExists()) + { + returnResponse(false); + } + + GKeyFile * proxies_conf_file = g_key_file_new(); + if(!proxies_conf_file) + { + LOGERR("Failed to g_key_file_new()"); + returnResponse(false); + } + + GError * error = nullptr; + if(!g_key_file_load_from_file(proxies_conf_file, PROXIES_CONFIGURATION_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) + { + LOGERR("Failed to load from file '%s': %s", PROXIES_CONFIGURATION_FILE, error->message); + returnResponse(false); + } + + gchar * group = g_key_file_get_start_group(proxies_conf_file); + if(0 != strcmp(group, "Proxies")) + { + LOGERR("No group 'Proxies' in file '%s'", PROXIES_CONFIGURATION_FILE); + g_free(group); + g_key_file_free(proxies_conf_file); + returnResponse(false); + } + + if (0 == uriLength) + { + g_key_file_remove_key(proxies_conf_file, group, (gchar *)name.c_str(), &error); + + gsize length; + gchar * str = g_key_file_to_data(proxies_conf_file, &length, &error); + g_file_set_contents(PROXIES_CONFIGURATION_FILE, str, length, &error); + g_free(str); + g_free(group); + g_key_file_free(proxies_conf_file); + + LOGWARN("Proxy with name '%s' has been removed from '%s' file, if it was there", name.c_str(), PROXIES_CONFIGURATION_FILE); + returnResponse(true); + } + + g_key_file_set_string(proxies_conf_file, group, (gchar *)name.c_str(), (gchar *)uri.c_str()); + + gsize length; + gchar * str = g_key_file_to_data(proxies_conf_file, &length, &error); + g_file_set_contents(PROXIES_CONFIGURATION_FILE, str, length, &error); + g_free(str); + g_free(group); + g_key_file_free(proxies_conf_file); + + returnResponse(true); + } + //End methods + + //Begin events + //End events + + bool Proxies::createKeyFileIfNotExists() + { + if (0 != access(PROXIES_CONFIGURATION_FILE, F_OK)) + { + g_mkdir_with_parents(PROXIES_CONFIGURATION_PATH, 0755); + FILE * confFile = fopen(PROXIES_CONFIGURATION_FILE, "w"); + if (confFile == NULL) + { + LOGERR("Can't create empty file '%s'", PROXIES_CONFIGURATION_FILE); + return false; + } + + fprintf(confFile, "[Proxies]"); + fclose(confFile); + } + + return true; + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/Proxies/Proxies.h b/Proxies/Proxies.h new file mode 100644 index 0000000000..39dfc79485 --- /dev/null +++ b/Proxies/Proxies.h @@ -0,0 +1,57 @@ +/** +* 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 "Module.h" + +#include "utils.h" +#include "AbstractPlugin.h" + +namespace WPEFramework { + + namespace Plugin { + + class Proxies : public AbstractPlugin { + private: + + Proxies(const Proxies&) = delete; + Proxies& operator=(const Proxies&) = delete; + + //Begin methods + uint32_t getProxy(const JsonObject& parameters, JsonObject& response); + uint32_t setProxy(const JsonObject& parameters, JsonObject& response); + //End methods + + //Begin events + //End events + + public: + Proxies(); + virtual ~Proxies(); + + private: + bool createKeyFileIfNotExists(); + + public: + static Proxies* _instance; + + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/Proxies/README.md b/Proxies/README.md new file mode 100644 index 0000000000..a879c7c229 --- /dev/null +++ b/Proxies/README.md @@ -0,0 +1,12 @@ +### Proxies thunder plugin + +--- +Test commands: + +curl -d '{"jsonrpc":"2.0","id":"1","method": "org.rdk.Proxies.1.setProxy", "params":{"name":"uri4", "uri":"https://abc.com:123/def/ghi?a=b&c=d#jkl"}}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"1","method": "org.rdk.Proxies.1.getProxy", "params":{"name":"uri4"}}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"1","method": "org.rdk.Proxies.1.setProxy", "params":{"name":"uri4", "uri":"https://xyz.com:123/def/ghi?a=b&c=d#jkl"}}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"1","method": "org.rdk.Proxies.1.getProxy", "params":{"name":"uri4"}}' http://127.0.0.1:9998/jsonrpc diff --git a/StateObserver/CMakeLists.txt b/StateObserver/CMakeLists.txt new file mode 100644 index 0000000000..79bf0b2772 --- /dev/null +++ b/StateObserver/CMakeLists.txt @@ -0,0 +1,29 @@ +set(PLUGIN_NAME StateObserver) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +set(PLUGIN_STATEOBSERVER_AUTOSTART true CACHE STRING "Automatically start StateObserver plugin") + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + StateObserver.cpp + Module.cpp) + +add_subdirectory(test) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +list(APPEND CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") + + +find_package(IARMBus) +target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) +target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} cjson) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/StateObserver/Module.cpp b/StateObserver/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/StateObserver/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/StateObserver/Module.h b/StateObserver/Module.h new file mode 100644 index 0000000000..1d3299f80d --- /dev/null +++ b/StateObserver/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 StateObserver +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/StateObserver/README.md b/StateObserver/README.md new file mode 100644 index 0000000000..e785d449c1 --- /dev/null +++ b/StateObserver/README.md @@ -0,0 +1,103 @@ +StateObserver +=============== +***@mainpage StateObserver*** + +This plugin provides the interface to get the value of various device properties and set up event listeners +to be notified when the state of the device changes. + + +**API's:** +- getValues +- registerListeners +- unregisterListeners +- getApiVersionNumber +- setApiVersionNumber +- getName + +## Build: +``` +bitbake thunder-plugins +``` + +>Note: Below listed curl requests contains sample values for testing purposes only. + + +### getValues : +This API takes a property or an array of properties as input and returns the state and error values of the same.Returns the property values and a success true or false. +``` +Request:(example) +curl -d '{"jsonrpc":"2.0","id":"3","method": "com.comcast.StateObserver.1.getValues" ,"params":{"PropertyNames":["com.comcast.channel_map","com.comcast.tune_ready"]}}' http://127.0.0.1:9998/jsonrpc +Response: +{"jsonrpc":"2.0","id":3,"result":{"properties":[{"PropertyName":"com.comcast.channel_map","state":2},{"PropertyName":"com.comcast.tune_ready","state":1}],"success":true}} +``` + + + +### registerListeners : +This API is used to register listeners to a properties so that any state change occurring in these registered properties will be notified.These properties will be added to a registered properties list. +It internally calls the getValues API and hence it returns current value of those properties. +``` +Request:(example) +curl -d '{"jsonrpc":"2.0","id":"3","method": "com.comcast.StateObserver.1.registerListeners" ,"params":{"PropertyNames":["com.comcast.channel_map"]}}' http://127.0.0.1:9998/jsonrpc +Response: +{"jsonrpc":"2.0","id":3,"result":{"properties":[{"PropertyName":"com.comcast.channel_map","state":2}],"success":true}} +``` + +### unregisterListeners : +Unregisters the listeners allocated to the properties.The properties will be removed from the registered properties list. +``` +Request:(example) +curl -d '{"jsonrpc":"2.0","id":"3","method": "com.comcast.StateObserver.1.unregisterListeners" ,"params":{"PropertyNames":["com.comcast.channel_map"]}}' http://127.0.0.1:9998/jsonrpc +Response: + {"jsonrpc":"2.0","id":3,"result":{"success":true}} +``` + +### getApiVersionNumber : +This API is used to get the api verison number. +``` +Request: +curl -d '{"jsonrpc":"2.0","id":"3","method": "com.comcast.StateObserver.1.getApiVersionNumber"}' http://127.0.0.1:9998/jsonrpc +Response: +{"jsonrpc":"2.0","id":3,"result":{"version":1,"success":true}} +``` + +### setApiVersionNumber : +This API is used to set the api verison number. +``` +Request: +curl -d '{"jsonrpc":"2.0","id":"3","method": "com.comcast.StateObserver.1.setApiVersionNumber","params":{"version":"2"}}' http://127.0.0.1:9998/jsonrpc +Response: +{"jsonrpc":"2.0","id":3,"result":{"success":true}} +``` + +### getName : +This API is used to get the plugin name. +``` +Request: +curl -d '{"jsonrpc":"2.0","id":"3","method": "com.comcast.StateObserver.1.getName"}' http://127.0.0.1:9998/jsonrpc +Response: +{"jsonrpc":"2.0","id":3,"result":{"Name":"com.comcast.stateObserver","success":true}} +``` + + +## Return Values: +Property state values are returned in the json response. +If any error is present in the property that also is passed in the response: + +PROPERTY | ERROR CODES | +-------------------------------|------------ | +com.comcast.channel_map | RDK-03005 | +com.comcast.card.disconnected | RDK-03007 | +com.comcast.cmac | RDK-03002 | +com.comcast.time_source | RDK-03006 | +com.comcast.estb_ip | RDK-03009 | +com.comcast.ecm_ip | RDK-03004 | +com.comcast.dsg_ca_tunnel | RDK-03003 | +com.comcast.cable_card | RDK-03001 | + + +Along with property values ,success value is also passed in the response .If its true it indicates API executed correctly and if its false it indicates +API failure. + + + diff --git a/StateObserver/StateObserver.config b/StateObserver/StateObserver.config new file mode 100644 index 0000000000..a0ecb7eb27 --- /dev/null +++ b/StateObserver/StateObserver.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "com.comcast.StateObserver") diff --git a/StateObserver/StateObserver.cpp b/StateObserver/StateObserver.cpp new file mode 100644 index 0000000000..8541833974 --- /dev/null +++ b/StateObserver/StateObserver.cpp @@ -0,0 +1,1053 @@ +/** +* 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. +**/ + +/* + * If not stated otherwise in this file or this component's license file the + * following copyright and licenses apply: + * + * Copyright 2018 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * @file StateObserver.cpp + * @brief Thunder Plugin based Implementation for StateObserver service API's (RDK-25848). + */ + +/** + @mainpage StateObserver + + */ + +#include +#include +#include +#include +#include + +#include "StateObserver.h" +#include "libIARM.h" +#include "libIBus.h" +#include "iarmUtil.h" +#include "sysMgr.h" + + +#define STATEOBSERVER_MAJOR_VERSION 1 +#define STATEOBSERVER_MINOR_VERSION 0 +#define DEBUG_INFO 0 + +namespace WPEFramework { + + namespace Plugin { + /* + *Register StateObserver module as wpeframework plugin + **/ + SERVICE_REGISTRATION(StateObserver, STATEOBSERVER_MAJOR_VERSION, STATEOBSERVER_MINOR_VERSION); + + StateObserver* StateObserver::_instance = nullptr; + + const string StateObserver::STATE_OBSERVER_PLUGIN_NAME = "com.comcast.stateObserver"; + + const string StateObserver::EVT_STATE_OBSERVER_PROPERTY_CHANGED = "propertyChanged"; + + std::vector registeredPropertyNames; + + + StateObserver::StateObserver() + : AbstractPlugin() + , m_apiVersionNumber((uint32_t)-1) + , m_iarmConnected(false) + { + LOGINFO(); + + StateObserver::_instance = this; + Register("getValues", &StateObserver::getValues, this); + Register("registerListeners", &StateObserver::registerListeners, this); + Register("unregisterListeners", &StateObserver::unregisterListeners, this); + Register("setApiVersionNumber", &StateObserver::setApiVersionNumberWrapper, this); + Register("getApiVersionNumber", &StateObserver::getApiVersionNumberWrapper, this); + Register("getName", &StateObserver::getNameWrapper, this); + setApiVersionNumber(1); + } + + StateObserver::~StateObserver() + { + LOGINFO(); + StateObserver::_instance = nullptr; + //Unregister all the APIs + } + + const string StateObserver::Initialize(PluginHost::IShell* /* service */) + { + LOGINFO(); + InitializeIARM(); + + // On success return empty, to indicate there is no error text. + return (string()); + } + + void StateObserver::Deinitialize(PluginHost::IShell* /* service */) + { + LOGINFO(); + DeinitializeIARM(); + } + + void StateObserver::InitializeIARM() + { + LOGINFO("initializing IARM bus...\n"); + int isRegistered; + IARM_Result_t res = IARM_Bus_IsConnected(IARM_BUS_SYSMGR_NAME , &isRegistered); + if(res != IARM_RESULT_SUCCESS) + { + IARM_CHECK( IARM_Bus_Init(IARM_BUS_SYSMGR_NAME) ); + IARM_CHECK( IARM_Bus_Connect() ); + m_iarmConnected = true; + } + + //Register iarm event handler + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE, onReportStateObserverEvents) ); + } + + void StateObserver::DeinitializeIARM() + { + LOGINFO("disconnecting from IARM Bus...\n"); + if (m_iarmConnected) + { + IARM_Result_t res; + m_iarmConnected = false; + IARM_CHECK( IARM_Bus_UnRegisterEventHandler(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE) ); + IARM_CHECK( IARM_Bus_Disconnect() ); + IARM_CHECK( IARM_Bus_Term() ); + } + } + + /** + * @brief This function is used to get the state observer plugin name. The state observer + * plugin name is "com.comcast.stateObserver" . + * + * @return String of the state observer plugin name. + */ + string StateObserver::getName() + { + return StateObserver::STATE_OBSERVER_PLUGIN_NAME; + } + + /** + * @brief This function is a wrapper function for getName function used to get the state observer + * plugin name. The state observer plugin name is "com.comcast.stateObserver". + * + * @param[out] String of the state observer plugin name. + * + * @return Core::ERROR_NONE + */ + uint32_t StateObserver::getNameWrapper(const JsonObject& parameters, JsonObject& response) + { + response["Name"]= StateObserver::STATE_OBSERVER_PLUGIN_NAME; + returnResponse(true); + } + + + /** + * @brief This function is used to get the version number of the state observer Plugin. + * + * @return version number of API integer value. + */ + unsigned int StateObserver::getApiVersionNumber() + { + return m_apiVersionNumber; + } + + + /** + * @brief This function is the wrapper used to get the version number of the state observer + * Plugin. + * + * param[out] The API Version Number. + * + * @return Core::ERROR_NONE + */ + uint32_t StateObserver::getApiVersionNumberWrapper(const JsonObject& parameters, JsonObject& response) + { + response["version"] = m_apiVersionNumber; + returnResponse(true); + } + + /** + * @brief This function is used to set the version number of the state observer Plugin. + * + * @param apiVersionNumber Integer variable of API version value. + */ + void StateObserver::setApiVersionNumber(unsigned int apiVersionNumber) + { + m_apiVersionNumber = apiVersionNumber; + } + + /** + * @brief This function is the wrapper used to get the version number of the state observer + * Plugin. + * + * @param[in] Api version number + * + * @return Core::ERROR_NONE + */ + uint32_t StateObserver::setApiVersionNumberWrapper(const JsonObject& parameters, JsonObject& response) + { + if (parameters.HasLabel("version")) + { + getNumberParameter("version", m_apiVersionNumber); + returnResponse(true); + } + + returnResponse(false); + } + + + /** + * @brief This function is used to get the values of the various device properties. + * + * param[in] Array of property names whose values needs to be fetched. + * + * param[out] state and error values of the properties + * + * @return Core::ERROR_NONE + * + *Request example: curl -d '{"jsonrpc":"2.0","id":"3","method": "StateObserver.1.getValues" ,"params":{"PropertyNames":["com.comcast.channel_map"]}}' http://127.0.0.1:9998/jsonrpc + *Response success:{"jsonrpc":"2.0","id":3,"result":{"properties":[{"PropertyName":"com.comcast.channel_map","state":2}],"success":true}} + *Response failure:{"jsonrpc":"2.0","id":3,"result":{"success":false}} + */ + uint32_t StateObserver::getValues(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + bool ret=false; + string json; + parameters.ToString(json); + LOGINFO("INPUT STR %s\n",json.c_str()); + cJSON *root; + root=cJSON_Parse(json.c_str()); + if( root ==NULL) + { + LOGWARN("not able to parse json request \n"); + returnResponse(ret); + } + cJSON *items=cJSON_GetObjectItem(root,"PropertyNames"); + if( items == NULL) + { + LOGWARN("not able to fetch property names from request \n"); + returnResponse(ret); + } + int arrsize=cJSON_GetArraySize(items); + if(arrsize!=0) + { + ret=true; + cJSON *elem; + int i; + std::vector pname; + for(i=0;ivaluestring); + string prop_str =elem->valuestring; + pname.push_back(prop_str); + } + getVal(pname,response); + } + returnResponse(ret); + } + + + /** + * @brief This function retrieves the values of the properties using IARM. + * + * param[in] pname vector of strings having the names of the properties whose value needs to be fetched. + * + * param[out] The state and error values of the properties. + * + */ + + void StateObserver::getVal(std::vector pname,JsonObject& response) + { + LOGINFO(); + static bool checkForStandalone = true; + static bool stbStandAloneMode = false; + if (checkForStandalone) + { + char *env_var= getenv("SERVICE_MANAGER_STANDALONE_MODE"); + if ( env_var ) + { + int v= atoi(env_var); + LOGWARN("standalone mode value %d", v); + if (v == 1) + { + stbStandAloneMode = true; + LOGWARN("standalone mode enabled"); + } + } + checkForStandalone = false; + } + IARM_Bus_SYSMgr_GetSystemStates_Param_t param; + IARM_Bus_Call(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_API_GetSystemStates, ¶m, sizeof(param)); + JsonArray response_arr; + for( std::vector::iterator it = pname.begin(); it!= pname.end(); ++it ) + { + string err_str="none"; + JsonObject devProp; + if(*it == SYSTEM_CHANNEL_MAP) + { + int channelMapState = param.channel_map.state; + int channelMapError = param.channel_map.error; + if (stbStandAloneMode) + { + LOGINFO("stand alone mode true\n"); + channelMapState = 2; + channelMapError = 0; + } + devProp["PropertyName"]=SYSTEM_CHANNEL_MAP; + devProp["state"]=channelMapState; + if(channelMapError == 1) + { + err_str="RDK-03005"; + } + devProp["error"]=err_str; + response_arr.Add(devProp); + } + + else if(*it == SYSTEM_CARD_DISCONNECTED) + { + int systemCardState = param.disconnect_mgr_state.state; + int systemCardError = param.disconnect_mgr_state.error; + if (stbStandAloneMode) + { + systemCardState = 0; + systemCardError = 0; + } + devProp["PropertyName"]=SYSTEM_CARD_DISCONNECTED; + devProp["state"]=systemCardState; + if(systemCardError==1) + { + err_str = "RDK-03007"; + } + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_TUNE_READY) + { + int tuneReadyState = param.TuneReadyStatus.state; + if (stbStandAloneMode) + { + tuneReadyState = 1; + } + devProp["PropertyName"]=SYSTEM_TUNE_READY; + devProp["state"]=tuneReadyState; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_EXIT_OK) + { + devProp["PropertyName"]=SYSTEM_EXIT_OK; + devProp["state"]=param.exit_ok_key_sequence.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it ==SYSTEM_CMAC ) + { + devProp["PropertyName"]=SYSTEM_CMAC ; + devProp["state"]=param.cmac.state; + if(param.cmac.error == 1) + { + err_str = "RDK-03002"; + } + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it ==SYSTEM_MOTO_ENTITLEMENT ) + { + devProp["PropertyName"]=SYSTEM_MOTO_ENTITLEMENT; + devProp["state"]=param.card_moto_entitlements.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_DAC_INIT_TIMESTAMP) + { + devProp["PropertyName"]=SYSTEM_DAC_INIT_TIMESTAMP; + string dac_init_str(param.dac_init_timestamp.payload); + devProp["state"]=dac_init_str; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_CARD_SERIAL_NO ) + { + string card_serial_str(param.card_serial_no.payload); + devProp["PropertyName"]=SYSTEM_CARD_SERIAL_NO; + devProp["state"]=card_serial_str; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_STB_SERIAL_NO ) + { + string stb_string(param.stb_serial_no.payload); + devProp["PropertyName"]=SYSTEM_STB_SERIAL_NO; + devProp["state"]=stb_string; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it ==SYSTEM_ECM_MAC ) + { + string ecm_mac_str(param.ecm_mac.payload); + devProp["PropertyName"]=SYSTEM_ECM_MAC; + devProp["state"]=ecm_mac_str; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_MOTO_HRV_RX) + { + devProp["PropertyName"]=SYSTEM_MOTO_HRV_RX; + devProp["state"]=param.card_moto_hrv_rx.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_CARD_CISCO_STATUS ) + { + LOGINFO("property SYSTEM_CARD_CISCO_STATUS \n"); + devProp["PropertyName"]=SYSTEM_CARD_CISCO_STATUS; + devProp["state"]=param.card_cisco_status.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_VIDEO_PRESENTING) + { + devProp["PropertyName"]=SYSTEM_VIDEO_PRESENTING; + devProp["state"]=param.video_presenting.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_HDMI_OUT ) + { + devProp["PropertyName"]=SYSTEM_HDMI_OUT; + devProp["state"]=param.hdmi_out.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_HDCP_ENABLED ) + { + devProp["PropertyName"]=SYSTEM_HDCP_ENABLED; + devProp["state"]=param.hdcp_enabled.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_HDMI_EDID_READ ) + { + devProp["PropertyName"]=SYSTEM_HDMI_EDID_READ; + devProp["state"]=param.hdmi_edid_read.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_FIRMWARE_DWNLD ) + { + devProp["PropertyName"]=SYSTEM_FIRMWARE_DWNLD; + devProp["state"]=param.firmware_download.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_TIME_SOURCE) + { + devProp["PropertyName"]=SYSTEM_TIME_SOURCE; + devProp["state"]=param.time_source.state; + if(param.time_source.error == 1) + { + err_str = "RDK-03006"; + } + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_TIME_ZONE) + { + devProp["PropertyName"]=SYSTEM_TIME_ZONE; + devProp["state"]=param.time_zone_available.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_CA_SYSTEM) + { + devProp["PropertyName"]=SYSTEM_CA_SYSTEM; + devProp["state"]=param.ca_system.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_ESTB_IP) + { + devProp["PropertyName"]=SYSTEM_ESTB_IP; + devProp["state"]=param.estb_ip.state; + if(param.estb_ip.error == 1) + { + err_str = "RDK-03009"; + } + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_ECM_IP) + { + devProp["PropertyName"]=SYSTEM_ECM_IP; + devProp["state"]=param.ecm_ip.state; + if(param.ecm_ip.error == 1) + { + err_str = "RDK-03004"; + } + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_LAN_IP) + { + devProp["PropertyName"]=SYSTEM_LAN_IP; + devProp["state"]=param.lan_ip.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_DOCSIS) + { + devProp["PropertyName"]=SYSTEM_DOCSIS; + devProp["state"]=param.docsis.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_DSG_CA_TUNNEL) + { + devProp["PropertyName"]=SYSTEM_DSG_CA_TUNNEL; + devProp["state"]=param.dsg_ca_tunnel.state; + if(param.dsg_ca_tunnel.error == 1) + { + err_str = "RDK-03003"; + } + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_CABLE_CARD ) + { + devProp["PropertyName"]=SYSTEM_CABLE_CARD; + devProp["state"]=param.cable_card.state; + if(param.cable_card.error == 1) + { + err_str = "RDK-03001"; + } + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_VOD_AD) + { + devProp["PropertyName"]=SYSTEM_VOD_AD; + devProp["state"]=param.vod_ad.state; + devProp["error"]=err_str; + response_arr.Add(devProp); + } + else if(*it == SYSTEM_IP_MODE) + { + int ipState=param.ip_mode.state; + int ipError=param.ip_mode.error; + devProp["PropertyName"]=SYSTEM_IP_MODE; + devProp["state"]=ipState; + devProp["error"]=ipError; + response_arr.Add(devProp); + } + + else + { + LOGINFO("Invalid property Name\n"); + string res="Invalid property Name"; + devProp["PropertyName"] = *it; + devProp["error"]=res; + response_arr.Add(devProp); + } + + } + + response["properties"]=response_arr; + #if(DEBUG_INFO) + string json_str; + response.ToString(json_str); + LOGINFO("json array of properties is %s\n",json_str.c_str()); + #endif + } + + + /** + * @brief This function registers Listeners to properties.It adds the properties to a registered properties list. + * + * param[in] Names of the property. + * + * param[out] Returns the state and error values of the properties. + * + * @return Core::ERROR_NONE + *Request example: curl -d '{"jsonrpc":"2.0","id":"3","method": "StateObserver.1.registerListeners" ,"params":{"PropertyNames":["com.comcast.channel_map"]}}' http://127.0.0.1:9998/jsonrpc + *Response success:{"jsonrpc":"2.0","id":3,"result":{"properties":[{"PropertyName":"com.comcast.channel_map","state":2}],"success":true}} + *Response failure:{"jsonrpc":"2.0","id":3,"result":{"success":false}} + */ + uint32_t StateObserver::registerListeners(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + bool ret=false; + string json; + parameters.ToString(json); + cJSON *root; + root=cJSON_Parse(json.c_str()); + if( root ==NULL) + { + LOGWARN("not able to parse json request \n"); + returnResponse(ret); + } + cJSON *items=cJSON_GetObjectItem(root,"PropertyNames"); + if( items == NULL) + { + LOGWARN("not able to fetch property names from request \n"); + returnResponse(ret); + } + int arrsize=cJSON_GetArraySize(items); + if(arrsize!=0) + { + ret=true; + cJSON *elem; + int i; + std::vector pname; + for(i=0;ivaluestring; + pname.push_back(prop_str); + } + + for( std::vector::iterator it = pname.begin(); it!= pname.end(); ++it ) + { + if (std::find(registeredPropertyNames.begin(), registeredPropertyNames.end(), *it) == registeredPropertyNames.end()) + { + LOGINFO("prop being added to listeners %s",*it); + registeredPropertyNames.push_back(*it); + } + } + getVal(pname,response); + } + returnResponse(ret); + } + + + /** + * @brief This function unregisters Listeners to properties.It removes the properties from a registered properties list. + * + * param[in] Names of the property. + * + * param[out] Returns the sucess true/false. + * + * @return Core::ERROR_NONE + *Request example: curl -d '{"jsonrpc":"2.0","id":"3","method": "StateObserver.1.unregisterListeners" ,"params":{"PropertyNames":["com.comcast.channel_map"]}}' http://127.0.0.1:9998/jsonrpc + *Response success:{"jsonrpc":"2.0","id":3,"result":{"success":true}} + *Response failure:{"jsonrpc":"2.0","id":3,"result":{"success":false}} + */ + uint32_t StateObserver::unregisterListeners(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + bool ret=false; + string json; + parameters.ToString(json); + cJSON *root; + root=cJSON_Parse(json.c_str()); + if( root ==NULL) + { + LOGWARN("not able to parse json request \n"); + returnResponse(ret); + } + cJSON *items=cJSON_GetObjectItem(root,"PropertyNames"); + if( items == NULL) + { + LOGWARN("not able to fetch property names from request \n"); + returnResponse(ret); + } + int arrsize=cJSON_GetArraySize(items); + if(arrsize!=0) + { + ret=true; + cJSON *elem; + int i; + std::vector pname; + for(i=0;ivaluestring; + pname.push_back(prop_str); + } + for( std::vector::iterator it = pname.begin(); it!= pname.end(); ++it ) + { + std::vector::iterator itr=std::find(registeredPropertyNames.begin(), registeredPropertyNames.end(), *it); + if(itr!=registeredPropertyNames.end()) + { + //property found hence remove it + LOGINFO("prop being removed %s",*it); + registeredPropertyNames.erase(itr); + } + } + } + returnResponse(ret); + } + + /** + * @brief This function is an event handler for property change event. + * + */ + void StateObserver::onReportStateObserverEvents(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + IARM_Bus_SYSMgr_GetSystemStates_Param_t systemStates; + JsonObject params; + int state=0; + int error=0; + + /* Only handle state events */ + if (eventId != IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE) + { + LOGWARN(" No need handle other events.."); + } + else + { + LOGINFO(" Property changed event received "); + IARM_Bus_SYSMgr_EventData_t *sysEventData = (IARM_Bus_SYSMgr_EventData_t*)data; + IARM_Bus_SYSMgr_SystemState_t stateId = sysEventData->data.systemStates.stateId; + state = sysEventData->data.systemStates.state; + error = sysEventData->data.systemStates.error; + char* payload=sysEventData->data.systemStates.payload; + #if(DEBUG_INFO) + LOGINFO("stateId is %d state is %d error is %d \n",stateId,state,error); + LOGINFO("payload is %s\n",payload); + #endif + switch(stateId) + { + + case IARM_BUS_SYSMGR_SYSSTATE_TUNEREADY: + systemStates.TuneReadyStatus.state = state; + systemStates.TuneReadyStatus.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_TUNE_READY,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_CHANNELMAP: + { + systemStates.channel_map.state = state; + systemStates.channel_map.error = error; + memcpy( systemStates.channel_map.payload, payload, sizeof( systemStates.channel_map.payload ) ); + systemStates.channel_map.payload[ sizeof( systemStates.channel_map.payload ) - 1] = 0; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_CHANNEL_MAP,state,error); + string payload_str(payload); + params["payload"].FromString(payload_str); + break; + } + + case IARM_BUS_SYSMGR_SYSSTATE_DISCONNECTMGR: + systemStates.disconnect_mgr_state.state = state; + systemStates.disconnect_mgr_state.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_CARD_DISCONNECTED,state,error); + break; + + + case IARM_BUS_SYSMGR_SYSSTATE_EXIT_OK : + systemStates.exit_ok_key_sequence.state = state; + systemStates.exit_ok_key_sequence.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_EXIT_OK,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_CMAC : + systemStates.cmac.state = state; + systemStates.cmac.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_CMAC,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_MOTO_ENTITLEMENT : + systemStates.card_moto_entitlements.state = state; + systemStates.card_moto_entitlements.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_MOTO_ENTITLEMENT,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_MOTO_HRV_RX : + systemStates.card_moto_hrv_rx.state = state; + systemStates.card_moto_hrv_rx.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_MOTO_HRV_RX,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_DAC_INIT_TIMESTAMP : + { + systemStates.dac_init_timestamp.state = state; + systemStates.dac_init_timestamp.error = error; + strncpy(systemStates.dac_init_timestamp.payload,payload,strlen(payload)); + systemStates.dac_init_timestamp.payload[strlen(payload)]='\0'; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_DAC_INIT_TIMESTAMP,state,error); + string payload_str(payload); + params["payload"].FromString(payload_str); + break; + } + + case IARM_BUS_SYSMGR_SYSSTATE_CABLE_CARD_SERIAL_NO: + { + systemStates.card_serial_no.error =error; + strncpy(systemStates.card_serial_no.payload,payload,strlen(payload)); + systemStates.card_serial_no.payload[strlen(payload)]='\0'; + params["PropertyName"]=SYSTEM_CARD_SERIAL_NO; + params["error"]=error; + string payload_str(payload); + params["payload"].FromString(payload_str); + break; + } + + case IARM_BUS_SYSMGR_SYSSTATE_STB_SERIAL_NO: + { + systemStates.stb_serial_no.error =error; + strncpy(systemStates.stb_serial_no.payload,payload,strlen(payload)); + systemStates.stb_serial_no.payload[strlen(payload)]='\0'; + params["PropertyName"]=SYSTEM_STB_SERIAL_NO; + params["error"]=error; + string payload_str(payload); + params["payload"].FromString(payload_str); + break; + } + + case IARM_BUS_SYSMGR_SYSSTATE_CARD_CISCO_STATUS : + systemStates.card_cisco_status.state = state; + systemStates.card_cisco_status.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_CARD_CISCO_STATUS,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_VIDEO_PRESENTING : + systemStates.video_presenting.state = state; + systemStates.video_presenting.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_VIDEO_PRESENTING,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_HDMI_OUT : + systemStates.hdmi_out.state = state; + systemStates.hdmi_out.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_HDMI_OUT,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_HDCP_ENABLED : + systemStates.hdcp_enabled.state = state; + systemStates.hdcp_enabled.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_HDCP_ENABLED,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_HDMI_EDID_READ : + systemStates.hdmi_edid_read.state = state; + systemStates.hdmi_edid_read.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_HDMI_EDID_READ,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_FIRMWARE_DWNLD : + systemStates.firmware_download.state = state; + systemStates.firmware_download.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_FIRMWARE_DWNLD,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_TIME_SOURCE : + systemStates.time_source.state = state; + systemStates.time_source.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_TIME_SOURCE,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_TIME_ZONE : + { + systemStates.time_zone_available.state = state; + systemStates.time_zone_available.error = error; + memcpy( systemStates.time_zone_available.payload, payload, sizeof( systemStates.time_zone_available.payload ) ); + systemStates.time_zone_available.payload[ sizeof( systemStates.time_zone_available.payload ) - 1] = 0; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_TIME_ZONE,state,error); + string payload_str(payload); + params["payload"].FromString(payload_str); + break; + } + + case IARM_BUS_SYSMGR_SYSSTATE_CA_SYSTEM : + systemStates.ca_system.state = state; + systemStates.ca_system.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_CA_SYSTEM,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_ESTB_IP : + systemStates.estb_ip.state = state; + systemStates.estb_ip.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_ESTB_IP,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_ECM_IP : + systemStates.ecm_ip.state = state; + systemStates.ecm_ip.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_ECM_IP,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_LAN_IP : + systemStates.lan_ip.state = state; + systemStates.lan_ip.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_LAN_IP,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_DOCSIS : + systemStates.docsis.state = state; + systemStates.docsis.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_DOCSIS,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_DSG_CA_TUNNEL : + systemStates.dsg_ca_tunnel.state = state; + systemStates.dsg_ca_tunnel.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_DSG_CA_TUNNEL,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_CABLE_CARD : + systemStates.cable_card.state = state; + systemStates.cable_card.error = error; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_CABLE_CARD,state,error); + break; + + case IARM_BUS_SYSMGR_SYSSTATE_VOD_AD : + { + systemStates.vod_ad.state = state; + systemStates.vod_ad.error = error; + memcpy( systemStates.vod_ad.payload, payload, sizeof( systemStates.vod_ad.payload ) ); + systemStates.vod_ad.payload[ sizeof( systemStates.vod_ad.payload ) -1 ] =0; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_VOD_AD,state,error); + string payload_str(payload); + params["payload"].FromString(payload_str); + break; + } + + case IARM_BUS_SYSMGR_SYSSTATE_ECM_MAC: + { + systemStates.ecm_mac.error =error; + strncpy(systemStates.ecm_mac.payload,payload,strlen(payload)); + systemStates.ecm_mac.payload[strlen(payload)]='\0'; + params["PropertyName"]=SYSTEM_ECM_MAC; + params["error"]=error; + string payload_str(payload); + params["payload"].FromString(payload_str); + break; + } + + case IARM_BUS_SYSMGR_SYSSTATE_IP_MODE: + { + systemStates.ip_mode.state=state; + systemStates.ip_mode.error =error; + strncpy(systemStates.ip_mode.payload,payload,strlen(payload)); + systemStates.ip_mode.payload[strlen(payload)]='\0'; + if(StateObserver::_instance) + StateObserver::_instance->setProp(params,SYSTEM_IP_MODE,state,error); + string payload_str(payload); + params["payload"].FromString(payload_str); + break; + } + default: + break; + } + + //notify the params + if(StateObserver::_instance) + { + #if(DEBUG_INFO) + LOGINFO("calling notify event\n"); + string json; + params.ToString(json); + LOGINFO("NOTIFY json is %s\n",json.c_str()); + #endif + StateObserver::_instance->notify(EVT_STATE_OBSERVER_PROPERTY_CHANGED,params); + } + } + } + + /** + * @brief This function sends a notification whenever a change in properties value occurs. + * + * param[in] Property change event name. + * + * param[out] Notification about change in property. + * + */ + void StateObserver::notify(string eventname, JsonObject& params) + { + string property_name=params["PropertyName"].String(); + if(std::find(registeredPropertyNames.begin(), registeredPropertyNames.end(), property_name) != registeredPropertyNames.end()) + { + LOGINFO("calling send notify\n"); + #if(DEBUG_INFO) + string json_str; + params.ToString(json_str); + LOGINFO("send notify request %s \n",json_str.c_str()); + #endif + //property added in registeredProperty list hence call sendNotify + sendNotify(eventname, params); + } + } + + /** + * @brief This function sets the state and error values to the json object. + * + * param[in] propName Name of property. + * param[in] state state of property. + * param[in] error error of property. + * + * param[out] JsonObject Property's values in a JsonObject. + * + */ + void StateObserver::setProp(JsonObject& params,string propName,int state,int error) + { + string property(propName); + params["PropertyName"]=property; + params["state"]=state; + params["error"]=error; + #if(DEBUG_INFO) + string json; + params.ToString(json); + LOGINFO("setProp Constructed json is %s\n",json.c_str()); + #endif + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/StateObserver/StateObserver.h b/StateObserver/StateObserver.h new file mode 100644 index 0000000000..c9d43fd7a8 --- /dev/null +++ b/StateObserver/StateObserver.h @@ -0,0 +1,178 @@ +/** +* 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. +**/ + +/* + * If not stated otherwise in this file or this component's license file the + * following copyright and licenses apply: + * + * Copyright 2018 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * @file StateObserver.h + * @brief Thunder Plugin based Implementation for StateObserver service API's (RDK-25848). + */ + + /** + @mainpage StateObserver + */ + +#pragma once + +#ifndef STATEOBSERVER_H +#define STATEOBSERVER_H +#include + +#include "Module.h" +#include "libIBus.h" +#include "utils.h" +#include "utils.h" +#include "AbstractPlugin.h" + +//State Observer Properties +const string SYSTEM_EXIT_OK = "com.comcast.exit-ok_key_sequence"; +const string SYSTEM_CHANNEL_MAP = "com.comcast.channel_map"; +const string SYSTEM_CARD_DISCONNECTED = "com.comcast.card.disconnected"; +const string SYSTEM_TUNE_READY = "com.comcast.tune_ready"; +const string SYSTEM_CMAC = "com.comcast.cmac"; +const string SYSTEM_MOTO_ENTITLEMENT = "com.comcast.card.moto.entitlements"; +const string SYSTEM_MOTO_HRV_RX = "com.comcast.card.moto.hrv_rx"; +const string SYSTEM_DAC_INIT_TIMESTAMP = "com.comcast.card.moto.dac_init_timestamp"; +const string SYSTEM_CARD_CISCO_STATUS = "com.comcast.card.cisco.status"; +const string SYSTEM_VIDEO_PRESENTING = "com.comcast.video_presenting"; +const string SYSTEM_HDMI_OUT = "com.comcast.hdmi_out"; +const string SYSTEM_HDCP_ENABLED = "com.comcast.hdcp_enabled"; +const string SYSTEM_HDMI_EDID_READ = "com.comcast.hdmi_edid_read"; +const string SYSTEM_FIRMWARE_DWNLD = "com.comcast.firmware_download"; +const string SYSTEM_TIME_SOURCE = "com.comcast.time_source"; +const string SYSTEM_TIME_ZONE = "com.comcast.time_zone_available"; +const string SYSTEM_CA_SYSTEM = "com.comcast.ca_system"; +const string SYSTEM_ESTB_IP = "com.comcast.estb_ip"; +const string SYSTEM_ECM_IP = "com.comcast.ecm_ip"; +const string SYSTEM_ECM_MAC = "com.comcast.ecm_mac"; +const string SYSTEM_LAN_IP = "com.comcast.lan_ip"; +const string SYSTEM_MOCA = "com.comcast.moca"; +const string SYSTEM_DOCSIS = "com.comcast.docsis"; +const string SYSTEM_DSG_BROADCAST_CHANNEL = "com.comcast.dsg_broadcast_tunnel"; +const string SYSTEM_DSG_CA_TUNNEL = "com.comcast.dsg_ca_tunnel"; +const string SYSTEM_CABLE_CARD = "com.comcast.cable_card"; +const string SYSTEM_CABLE_CARD_DWNLD = "com.comcast.cable_card_download"; +const string SYSTEM_CVR_SUBSYSTEM = "com.comcast.cvr_subsystem"; +const string SYSTEM_DOWNLOAD = "com.comcast.download"; +const string SYSTEM_VOD_AD = "com.comcast.vod_ad"; +const string SYSTEM_CARD_SERIAL_NO = "com.comcast.card.serial.no"; +const string SYSTEM_STB_SERIAL_NO = "com.comcast.stb.serial.no"; +const string SYSTEM_RF_CONNECTED = "com.comcast.rf_connected"; +const string SYSTEM_IP_MODE = "com.comcast.ip_mode"; + +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. + + /** + * @brief This class provides the interface to get the value of various device properties + * and set up event listeners to be notified when the state of the device changes. + * + */ + + class StateObserver : public AbstractPlugin { + public: + static const string STATE_OBSERVER_PLUGIN_NAME; + static const string EVT_STATE_OBSERVER_PROPERTY_CHANGED; + + + private: + typedef Core::JSON::String JString; + typedef Core::JSON::ArrayType JStringArray; + typedef Core::JSON::Boolean JBool; + + // We do not allow this plugin to be copied !! + StateObserver(const StateObserver&) = delete; + StateObserver& operator=(const StateObserver&) = delete; + + //Begin methods + uint32_t getValues(const JsonObject& parameters, JsonObject& response); + uint32_t registerListeners(const JsonObject& parameters, JsonObject& response); + uint32_t unregisterListeners(const JsonObject& parameters, JsonObject& response); + uint32_t setApiVersionNumberWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getApiVersionNumberWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getNameWrapper(const JsonObject& parameters, JsonObject& response); + void getVal(std::vector pname,JsonObject& response); + void InitializeIARM(); + void DeinitializeIARM(); + //End methods + + + virtual string getName(); + virtual unsigned int getApiVersionNumber(); + void setApiVersionNumber(unsigned int apiVersionNumber); + + //Begin events + //End events + public: + StateObserver(); + virtual ~StateObserver(); + //IPlugin methods + virtual const string Initialize(PluginHost::IShell* service) override; + virtual void Deinitialize(PluginHost::IShell* service) override; + static void onReportStateObserverEvents(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + void notify(std::string eventname, JsonObject& param); + void setProp(JsonObject& params,std::string propName,int state,int error); + + public: + static StateObserver* _instance; + private: + uint32_t m_apiVersionNumber; + bool m_iarmConnected; + }; + + } // namespace Plugin +} // namespace WPEFramework + + +#endif //STATEOBSERVER_H + + + + diff --git a/StateObserver/test/CMakeLists.txt b/StateObserver/test/CMakeLists.txt new file mode 100644 index 0000000000..3252b55a3a --- /dev/null +++ b/StateObserver/test/CMakeLists.txt @@ -0,0 +1,16 @@ +find_package(jsonrpc REQUIRED) + + add_executable(STOBSThunderClient STOBSThunderClient.cpp) + + set_target_properties(STOBSThunderClient PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES + ) + + target_link_libraries(STOBSThunderClient + PRIVATE + jsonrpc::jsonrpc + ) + + install(TARGETS STOBSThunderClient DESTINATION bin) + diff --git a/StateObserver/test/Module.h b/StateObserver/test/Module.h new file mode 100644 index 0000000000..bbb3d7b039 --- /dev/null +++ b/StateObserver/test/Module.h @@ -0,0 +1,28 @@ +/** +* 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 JSONRPC_Test +#endif + +#include +#include + diff --git a/StateObserver/test/STOBSThunderClient.cpp b/StateObserver/test/STOBSThunderClient.cpp new file mode 100644 index 0000000000..019ff919cd --- /dev/null +++ b/StateObserver/test/STOBSThunderClient.cpp @@ -0,0 +1,234 @@ +/** +* 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 +#include +#include +#include +#include +#include +#include "Module.h" + +using namespace std; +using namespace WPEFramework; + +JSONRPC::Client* remoteObject = NULL; +void showMenu() +{ + cout<<"Enter your choice\n"; + cout<<"1.getValues\n"; + cout<<"2.registerListeners\n"; + cout<<"3.unregisterListeners\n"; + cout<<"4.getName\n"; + cout<<"5.getApiVersionNumber\n"; + cout<<"6.setApiVersionNumber\n"; +} + + +int main(int argc, char** argv) +{ + int choice; + JsonObject result; + JsonObject param; + uint32_t ret; + int size; + int i; + string req; + + + Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); + if(NULL == remoteObject) { + remoteObject = new JSONRPC::Client(_T("StateObserver.1"), _T("")); + while(1) + { + showMenu(); + cin>>choice; + switch(choice) + { + case 1: + { + cout<<"Enter the number of properties\n"; + cin>>size; + string pName[size]; + cout<<"Enter the properties whose value is required\n"; + for(i=0;i>pName[i]; + } + //To create the json format request string + req="[\"" + pName[0] +"\""; + i=1; + while(iInvoke(1000, _T("getValues"), param, result); + if (result["success"].Boolean()) + { + string resp=result["properties"].String(); + cout<<"StateObserver the response properties value is "<>size; + string pName[size]; + cout<<"Enter the properties which needs to be registered\n"; + for(i=0;i>pName[i]; + } + //To create the json format request string + req="[\"" + pName[0] +"\""; + i=1; + while(iInvoke(1000, _T("registerListeners"), param, result); + if (result["success"].Boolean()) + { + string resp=result["properties"].String(); + cout<<"StateObserver the response properties value is "<>size; + string pName[size]; + cout<<"Enter the properties which needs to be unregistered\n"; + for(i=0;i>pName[i]; + } + //To create the json format request string + req="[\"" + pName[0] +"\""; + i=1; + while(iInvoke(1000, _T("unregisterListeners"), param, result); + if (result["success"].Boolean()) + { + cout<<"StateObserver unregister listeners call Success\n"; + } + else + { + cout<<"StateObserver unregister Listeners call failed \n"; + } + } + break; + + case 4: + { + cout<<"getName API\n"; + ret = remoteObject->Invoke(1000, _T("getName"), param, result); + if (result["success"].Boolean()) + { + string pluginName=result["Name"].String(); + cout<<"getName Api plugin is "<Invoke(1000, _T("getApiVersionNumber"), param, result); + if (result["success"].Boolean()) + { + string version=result["version"].String(); + cout<<"getApiVersionNumber Api plugin version is "<>version; + string ver="\"" + std::to_string(version) + "\""; + param["version"].FromString(ver); + ret = remoteObject->Invoke(1000, _T("setApiVersionNumber"), param, result); + if (result["success"].Boolean()) + { + cout<<"StateObserver setApiVersionNumber call Success\n"; + } + else + { + cout<<"StateObserver setApiVersionNumber call failed \n"; + } + } + break; + + default: + + break; + } + + cout<<"to continue press y to quit press any other key \n"; + char c; + cin>>c; + if(c=='y') + continue; + else + break; + + } + } + + +} diff --git a/Timer/CMakeLists.txt b/Timer/CMakeLists.txt new file mode 100644 index 0000000000..ead5c4613b --- /dev/null +++ b/Timer/CMakeLists.txt @@ -0,0 +1,28 @@ +set(PLUGIN_NAME Timer) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + Timer.cpp + Module.cpp + ../helpers/tptimer.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +list(APPEND CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") + + +find_package(IARMBus) + +target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) + +target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES}) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/Timer/Module.cpp b/Timer/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/Timer/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/Timer/Module.h b/Timer/Module.h new file mode 100644 index 0000000000..f58fe7ee6a --- /dev/null +++ b/Timer/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 Timer +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/Timer/README.md b/Timer/README.md new file mode 100644 index 0000000000..e7c141163a --- /dev/null +++ b/Timer/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": "Traceoute.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/Timer/Timer.config b/Timer/Timer.config new file mode 100644 index 0000000000..3ef2075e0e --- /dev/null +++ b/Timer/Timer.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "org.rdk.Timer") diff --git a/Timer/Timer.cpp b/Timer/Timer.cpp new file mode 100644 index 0000000000..7e54636e85 --- /dev/null +++ b/Timer/Timer.cpp @@ -0,0 +1,481 @@ +/** +* 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 "Timer.h" + + +#if defined(USE_IARMBUS) || defined(USE_IARM_BUS) +#include "libIBus.h" +#include "ccec/drivers/CecIARMBusMgr.h" +#endif + +#include "utils.h" + +// Methods +#define TIMER_METHOD_START_TIMER "startTimer" +#define TIMER_METHOD_CANCEL "cancel" +#define TIMER_METHOD_SUSPEND "suspend" +#define TIMER_METHOD_RESUME "resume" +#define TIMER_METHOD_GET_TIMER_STATUS "getTimerStatus" +#define TIMER_METHOD_GET_TIMERS "getTimers" + +// Events +#define TIMER_EVT_TIMER_EXPIRED "timerExpired" +#define TIMER_EVT_TIMER_EXPIRY_REMINDER "timerExpiryReminder" + +#define TIMER_ACCURACY 0.001 // 10 milliseconds + +static const char* stateStrings[] = { + "", + "RUNNING", + "SUSPENDED", + "CANCELED", + "EXPIRED" +}; + +static const char* modeStrings[] = { + "GENERIC", + "SLEEP", + "WAKE" +}; + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(Timer, 1, 0); + + Timer* Timer::_instance = nullptr; + + Timer::Timer() + : AbstractPlugin() + { + LOGINFO(); + Timer::_instance = this; + + registerMethod(TIMER_METHOD_START_TIMER, &Timer::startTimerWrapper, this); + registerMethod(TIMER_METHOD_CANCEL, &Timer::cancelWrapper, this); + registerMethod(TIMER_METHOD_SUSPEND, &Timer::suspendWrapper, this); + registerMethod(TIMER_METHOD_RESUME, &Timer::resumeWrapper, this); + registerMethod(TIMER_METHOD_GET_TIMER_STATUS, &Timer::getTimerStatusWrapper, this); + registerMethod(TIMER_METHOD_GET_TIMERS, &Timer::getTimersWrapper, this); + + m_timer.setSingleShot(true); + m_timer.connect(std::bind(&Timer::onTimerCallback, this)); + } + + Timer::~Timer() + { + LOGINFO(); + Timer::_instance = nullptr; + } + + bool Timer::checkTimers() + { + LOGINFO(); + + double minTimeout = 100000; + for (auto it = m_runningItems.cbegin(); it != m_runningItems.cend(); ++it) + { + int timerId = *it; + if (timerId < 0 || timerId >= m_timerItems.size()) + { + LOGERR("Internal error: wrong timerId"); + continue; + } + if (m_timerItems[timerId].state != RUNNING) + { + LOGERR("Internal error: timer %d has wrong state", timerId); + continue; + } + + std::chrono::duration elapsed = std::chrono::system_clock::now() - m_timerItems[timerId].lastExpired; + double timeout = m_timerItems[timerId].interval - elapsed.count(); + + if (!m_timerItems[timerId].reminderSent && m_timerItems[timerId].remindBefore > TIMER_ACCURACY) + { + if (timeout > m_timerItems[timerId].remindBefore) + { + timeout -= m_timerItems[timerId].remindBefore; + } + else + { + sendTimerExpiryReminder(timerId); + m_timerItems[timerId].reminderSent = true; + } + } + + if (timeout < minTimeout) + minTimeout = timeout; + } + + if (minTimeout < TIMER_ACCURACY) + minTimeout = TIMER_ACCURACY; + + if (minTimeout < 100000) + m_timer.start(int(minTimeout * 1000)); + } + + void Timer::startTimer(int timerId) + { + m_runningItems.push_back(timerId); + m_timerItems[timerId].state = RUNNING; + + m_timerItems[timerId].lastExpired = std::chrono::system_clock::now(); + m_timerItems[timerId].lastExpiryReminder = std::chrono::system_clock::now(); + m_timerItems[timerId].reminderSent = false; + + checkTimers(); + } + + bool Timer::cancelTimer(int timerId) + { + m_timerItems[timerId].state = CANCELED; + + auto it = std::find(m_runningItems.begin(), m_runningItems.end(), timerId); + if (m_runningItems.end() != it) + { + m_runningItems.erase(it); + m_timer.stop(); + checkTimers(); + return true; + } + + return false; + } + + bool Timer::suspendTimer(int timerId) + { + m_timerItems[timerId].state = SUSPENDED; + + auto it = std::find(m_runningItems.begin(), m_runningItems.end(), timerId); + if (m_runningItems.end() != it) + { + m_runningItems.erase(it); + m_timer.stop(); + checkTimers(); + return true; + } + + return false; + } + + void Timer::onTimerCallback() + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + std::list itemsToDelete; + + for (auto it = m_runningItems.cbegin(); it != m_runningItems.cend(); ++it) + { + int timerId = *it; + if (timerId < 0 || timerId >= m_timerItems.size()) + { + LOGERR("Internal error: wrong timerId"); + continue; + } + if (m_timerItems[timerId].state != RUNNING) + { + LOGERR("Internal error: timer %d has wrong state", timerId); + continue; + } + + std::chrono::duration elapsed = std::chrono::system_clock::now() - m_timerItems[timerId].lastExpired; + double timeout = m_timerItems[timerId].interval - elapsed.count(); + + if (!m_timerItems[timerId].reminderSent && m_timerItems[timerId].remindBefore > TIMER_ACCURACY) + { + if (timeout < m_timerItems[timerId].remindBefore + TIMER_ACCURACY) + { + sendTimerExpiryReminder(timerId); + m_timerItems[timerId].reminderSent = true; + } + } + + if (timeout <= TIMER_ACCURACY) + { + sendTimerExpired(timerId); + + m_timerItems[timerId].lastExpired = std::chrono::system_clock::now(); + + if (m_timerItems[timerId].repeatInterval > 0) + { + m_timerItems[timerId].interval = m_timerItems[timerId].repeatInterval; + } + else + { + m_timerItems[timerId].state = EXPIRED; + itemsToDelete.push_back(timerId); + } + + m_timerItems[timerId].reminderSent = false; + } + } + + for (auto delIt = itemsToDelete.cbegin(); delIt != itemsToDelete.cend(); ++delIt) + { + auto it = std::find(m_runningItems.begin(), m_runningItems.end(), *delIt); + if (m_runningItems.end() != it) + m_runningItems.erase(it); + + } + + checkTimers(); + } + + void Timer::getTimerStatus(int timerId, JsonObject& output, bool writeTimerId) + { + if (writeTimerId) + output["timerId"] = timerId; + + output["state"] = stateStrings[m_timerItems[timerId].state]; + output["mode"] = modeStrings[m_timerItems[timerId].mode]; + + std::chrono::duration elapsed = std::chrono::system_clock::now() - m_timerItems[timerId].lastExpired; + double timeRemaining = m_timerItems[timerId].interval - elapsed.count(); + + char buf[256]; + + snprintf(buf, sizeof(buf), "%.3f", timeRemaining); + output["timeRemaining"] = (const char *)buf; + + snprintf(buf, sizeof(buf), "%.3f", m_timerItems[timerId].repeatInterval); + output["repeatInterval"] = (const char *)buf; + + snprintf(buf, sizeof(buf), "%.3f", m_timerItems[timerId].remindBefore); + output["remindBefore"] = (const char *)buf; + } + + uint32_t Timer::startTimerWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + if (!parameters.HasLabel("interval")) + { + LOGERR("\"interval\" parameter is required"); + returnResponse(false); + } + + TimerItem item; + + item.state = INITIAL; + item.interval = std::stod(parameters["interval"].String()); + + item.mode = GENERIC; + if (parameters.HasLabel("mode")) + { + if (parameters["mode"].String() == "SLEEP") + item.mode = SLEEP; + else if (parameters["mode"].String() == "WAKE") + item.mode = WAKE; + } + + item.repeatInterval = parameters.HasLabel("repeatInterval") ? std::stod(parameters["repeatInterval"].String()) : 0.0; + item.remindBefore = parameters.HasLabel("remindBefore") ? std::stod(parameters["remindBefore"].String()) : 0.0; + + m_timerItems.push_back(item); + + startTimer(m_timerItems.size() - 1); + response["timerId"] = m_timerItems.size() - 1; + + returnResponse(true); + } + + uint32_t Timer::cancelWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + if (!parameters.HasLabel("timerId")) + { + LOGERR("\"timerId\" parameter is required"); + returnResponse(false); + } + + int timerId; + getNumberParameter("timerId", timerId); + + if (timerId >=0 && timerId < m_timerItems.size()) + { + if (CANCELED != m_timerItems[timerId].state) + { + returnResponse(cancelTimer(timerId)); + } + + LOGERR("timer %d is already canceled", timerId); + returnResponse(false); + } + + LOGERR("Bad timerId"); + returnResponse(false); + } + + uint32_t Timer::suspendWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + if (!parameters.HasLabel("timerId")) + { + LOGERR("\"timerId\" parameter is required"); + returnResponse(false); + } + + int timerId; + getNumberParameter("timerId", timerId); + + if (timerId >=0 && timerId < m_timerItems.size()) + { + if (RUNNING == m_timerItems[timerId].state) + { + returnResponse(suspendTimer(timerId)); + } + + LOGERR("timer %d is not in running state", timerId); + returnResponse(false); + } + + LOGERR("Bad timerId"); + returnResponse(false); + } + + uint32_t Timer::resumeWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + if (!parameters.HasLabel("timerId")) + { + LOGERR("\"timerId\" parameter is required"); + returnResponse(false); + } + + int timerId; + getNumberParameter("timerId", timerId); + + if (timerId >=0 && timerId < m_timerItems.size()) + { + if (SUSPENDED == m_timerItems[timerId].state) + { + startTimer(timerId); + returnResponse(true); + } + + LOGERR("timer %d is not in suspended state", timerId); + returnResponse(false); + } + + LOGERR("Bad timerId"); + returnResponse(false); + } + + uint32_t Timer::getTimerStatusWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + if (!parameters.HasLabel("timerId")) + { + LOGERR("\"timerId\" parameter is required"); + returnResponse(false); + } + + int timerId; + getNumberParameter("timerId", timerId); + + if (timerId >= 0 && timerId < m_timerItems.size()) + { + getTimerStatus(timerId, response); + } + else + { + LOGERR("Wrong timerId"); + returnResponse(false); + } + + returnResponse(true); + } + + uint32_t Timer::getTimersWrapper(const JsonObject& parameters, JsonObject& response) + { + std::lock_guard guard(m_callMutex); + + LOGINFO(); + + JsonArray timers; + for (int n = 0; n < m_timerItems.size(); n++) + { + JsonObject timer; + getTimerStatus(n, timer, true); + timers.Add(timer); + } + + response["timers"] = timers; + + returnResponse(true); + } + + void Timer::sendTimerExpired(int timerId) + { +#if defined(USE_IARMBUS) || defined(USE_IARM_BUS) + if (SLEEP == m_timerItems[timerId].mode || WAKE == m_timerItems[timerId].mode) + { + // Taken from power iarm manager + IARM_Bus_CECMgr_Send_Param_t dataToSend; + unsigned char buf[] = {0x30, 0x36}; //standby msg, from TUNER to TV + + if (WAKE == m_timerItems[timerId].mode) + buf[1] = 0x4; // Image On instead of Standby + + memset(&dataToSend, 0, sizeof(dataToSend)); + dataToSend.length = sizeof(buf); + memcpy(dataToSend.data, buf, dataToSend.length); + LOGINFO("Timer send CEC %s", SLEEP == m_timerItems[timerId].mode ? "Standby" : "Wake"); + IARM_Bus_Call(IARM_BUS_CECMGR_NAME,IARM_BUS_CECMGR_API_Send,(void *)&dataToSend, sizeof(dataToSend)); + } +#endif + JsonObject params; + params["timerId"] = timerId; + params["mode"] = modeStrings[m_timerItems[timerId].mode]; + params["status"] = 0; + sendNotify(TIMER_EVT_TIMER_EXPIRED, params); + } + + void Timer::sendTimerExpiryReminder(int timerId) + { + JsonObject params; + params["timerId"] = timerId; + params["mode"] = modeStrings[m_timerItems[timerId].mode]; + + std::chrono::duration elapsed = std::chrono::system_clock::now() - m_timerItems[timerId].lastExpired; + + params["timeRemaining"] = (int)(m_timerItems[timerId].interval - elapsed.count() + 0.5); + sendNotify(TIMER_EVT_TIMER_EXPIRY_REMINDER, params); + } + } // namespace Plugin +} // namespace WPEFramework + diff --git a/Timer/Timer.h b/Timer/Timer.h new file mode 100644 index 0000000000..424f524f75 --- /dev/null +++ b/Timer/Timer.h @@ -0,0 +1,115 @@ +/** +* 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 "Module.h" +#include "utils.h" +#include "AbstractPlugin.h" + + +#include "tptimer.h" + +namespace WPEFramework { + + namespace Plugin { + + enum TimerState { + INITIAL, + RUNNING, + SUSPENDED, + CANCELED, + EXPIRED, + }; + + enum TimerMode { + GENERIC, + SLEEP, + WAKE, + }; + + struct TimerItem { + TimerState state; + double interval; + TimerMode mode; + double repeatInterval; + double remindBefore; + std::chrono::system_clock::time_point lastExpired; + std::chrono::system_clock::time_point lastExpiryReminder; + bool reminderSent; + }; + + // 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 Timer : public AbstractPlugin { + private: + + // We do not allow this plugin to be copied !! + Timer(const Timer&) = delete; + Timer& operator=(const Timer&) = delete; + + //Begin methods + uint32_t startTimerWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t cancelWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t suspendWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t resumeWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getTimerStatusWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getTimersWrapper(const JsonObject& parameters, JsonObject& response); + //End methods + + //Begin events + void sendTimerExpired(int timerId); + void sendTimerExpiryReminder(int timerId); + //End events + + bool checkTimers(); + + void startTimer(int timerId); + bool cancelTimer(int timerId); + bool suspendTimer(int timerId); + + void onTimerCallback(); + void getTimerStatus(int timerId, JsonObject& output, bool writeTimerId = false); + + public: + Timer(); + virtual ~Timer(); + + public: + static Timer* _instance; + private: + TpTimer m_timer; + std::vector m_timerItems; + std::list m_runningItems; + std::mutex m_callMutex; + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/UserPreferences/CMakeLists.txt b/UserPreferences/CMakeLists.txt new file mode 100644 index 0000000000..5fc91bacd7 --- /dev/null +++ b/UserPreferences/CMakeLists.txt @@ -0,0 +1,30 @@ +set(PLUGIN_NAME UserPreferences) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + UserPreferences.cpp + Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +target_include_directories(${MODULE_NAME} PRIVATE ../helpers) + +find_package(DS) +if (DS_FOUND) + find_package(IARMBus) + add_definitions(-DDS_FOUND) + target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) + target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${DS_LIBRARIES}) +else (DS_FOUND) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +endif(DS_FOUND) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/UserPreferences/Module.cpp b/UserPreferences/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/UserPreferences/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/UserPreferences/Module.h b/UserPreferences/Module.h new file mode 100644 index 0000000000..d86b05f546 --- /dev/null +++ b/UserPreferences/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 UserPreferences +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/UserPreferences/README.md b/UserPreferences/README.md new file mode 100644 index 0000000000..fafb6730ff --- /dev/null +++ b/UserPreferences/README.md @@ -0,0 +1,15 @@ +----------------- +Build: + +bitbake thunder-plugins + +----------------- +Test: + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.UserPreferences.1.setUILanguage", "params": {"language": "UP_LANG1"}}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.UserPreferences.1.getUILanguage", "params": {"language": "UP_LANG1"}}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.UserPreferences.1.setUILanguage", "params": {"language": "UP_LANG2"}}' http://127.0.0.1:9998/jsonrpc + +curl -d '{"jsonrpc":"2.0","id":"3","method": "org.rdk.UserPreferences.1.getUILanguage", "params": {"language": "UP_LANG2"}}' http://127.0.0.1:9998/jsonrpc \ No newline at end of file diff --git a/UserPreferences/UserPreferences.config b/UserPreferences/UserPreferences.config new file mode 100644 index 0000000000..d80be49b05 --- /dev/null +++ b/UserPreferences/UserPreferences.config @@ -0,0 +1,3 @@ +set (autostart true) +set (preconditions Platform) +set (callsign "org.rdk.UserPreferences") diff --git a/UserPreferences/UserPreferences.cpp b/UserPreferences/UserPreferences.cpp new file mode 100644 index 0000000000..0a038a76ae --- /dev/null +++ b/UserPreferences/UserPreferences.cpp @@ -0,0 +1,71 @@ +/** +* 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 "UserPreferences.h" +#include "utils.h" + +using namespace std; + +namespace WPEFramework { + + namespace Plugin { + + SERVICE_REGISTRATION(UserPreferences, 1, 0); + + UserPreferences* UserPreferences::_instance = nullptr; + + UserPreferences::UserPreferences() + : AbstractPlugin() + , _language("") + { + LOGINFO("ctor"); + UserPreferences::_instance = this; + registerMethod("getUILanguage", &UserPreferences::getUILanguage, this); + registerMethod("setUILanguage", &UserPreferences::setUILanguage, this); + } + + UserPreferences::~UserPreferences() + { + LOGINFO("dtor"); + UserPreferences::_instance = nullptr; + } + + //Begin methods + uint32_t UserPreferences::getUILanguage(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + response["language"] = _language; + returnResponse(true); + } + + uint32_t UserPreferences::setUILanguage(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + returnIfStringParamNotFound(parameters, "language"); + _language = parameters["language"].String(); + returnResponse(true); + } + //End methods + + //Begin events + //End events + + } // namespace Plugin +} // namespace WPEFramework diff --git a/UserPreferences/UserPreferences.h b/UserPreferences/UserPreferences.h new file mode 100644 index 0000000000..09182219ca --- /dev/null +++ b/UserPreferences/UserPreferences.h @@ -0,0 +1,56 @@ +/** +* 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 "Module.h" +#include "utils.h" +#include "AbstractPlugin.h" + +namespace WPEFramework { + namespace Plugin { + + class UserPreferences : public AbstractPlugin { + private: + + UserPreferences(const UserPreferences&) = delete; + UserPreferences& operator=(const UserPreferences&) = delete; + + //Begin methods + uint32_t getUILanguage(const JsonObject& parameters, JsonObject& response); + uint32_t setUILanguage(const JsonObject& parameters, JsonObject& response); + //End methods + + //Begin events + //End events + + public: + UserPreferences(); + virtual ~UserPreferences(); + + + public: + static UserPreferences* _instance; + + private: + string _language; + + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/Warehouse/CMakeLists.txt b/Warehouse/CMakeLists.txt new file mode 100644 index 0000000000..2a13223eb2 --- /dev/null +++ b/Warehouse/CMakeLists.txt @@ -0,0 +1,39 @@ +set(PLUGIN_NAME Warehouse) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) + +add_library(${MODULE_NAME} SHARED + Warehouse.cpp + Module.cpp + ../helpers/frontpanel.cpp + ../helpers/powerstate.cpp +) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +find_package(DS) +if (DS_FOUND) + find_package(IARMBus) + add_definitions(-DDS_FOUND) + target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) + target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) + target_include_directories(${MODULE_NAME} PRIVATE ../helpers) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${DS_LIBRARIES}) +# target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${DS_LIBRARIES}) +else (DS_FOUND) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +endif(DS_FOUND) + + +#find_package(IARMBus) + +#target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) +#target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES}) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/Warehouse/Module.cpp b/Warehouse/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/Warehouse/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/Warehouse/Module.h b/Warehouse/Module.h new file mode 100644 index 0000000000..46d3ae2521 --- /dev/null +++ b/Warehouse/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 Warehouse +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/Warehouse/README.md b/Warehouse/README.md new file mode 100644 index 0000000000..96c72d2925 --- /dev/null +++ b/Warehouse/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": "Warehouse.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/Warehouse/Warehouse.config b/Warehouse/Warehouse.config new file mode 100644 index 0000000000..b8fc44c603 --- /dev/null +++ b/Warehouse/Warehouse.config @@ -0,0 +1,3 @@ +set (autostart false) +set (preconditions Platform) +set (callsign "org.rdk.Warehouse") diff --git a/Warehouse/Warehouse.cpp b/Warehouse/Warehouse.cpp new file mode 100644 index 0000000000..07b0bee0b5 --- /dev/null +++ b/Warehouse/Warehouse.cpp @@ -0,0 +1,569 @@ +/** +* 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 "Warehouse.h" + +#include +#include + +#include + +#if defined(USE_IARMBUS) || defined(USE_IARM_BUS) +#include "libIBus.h" +#include "sysMgr.h" +#include "pwrMgr.h" +#endif + +#include "utils.h" + +#include "frontpanel.h" + +#define WAREHOUSE_METHOD_RESET_DEVICE "resetDevice" +#define WAREHOUSE_METHOD_GET_DEVICE_INFO "getDeviceInfo" +#define WAREHOUSE_METHOD_GET_VERSION "getVersion" +#define WAREHOUSE_METHOD_SET_FRONT_PANEL_STATE "setFrontPanelState" +#define WAREHOUSE_METHOD_INTERNAL_RESET "internalReset" +#define WAREHOUSE_METHOD_LIGHT_RESET "lightReset" + +#define WAREHOUSE_EVT_DEVICE_INFO_RETRIEVED "deviceInfoRetrieved" +#define WAREHOUSE_EVT_RESET_DONE "resetDone" + +#define HOSTS_FILE "/etc/warehouseHosts.conf" +#define DEFAULT_CNAME_TAIL ".warehouse.ccp.xcal.tv" + +#define PARAM_SUCCESS "success" +#define PARAM_ERROR "error" + +#define DEVICE_INFO_SCRIPT "sh /lib/rdk/getDeviceDetails.sh read" +#define VERSION_FILE_NAME "/version.txt" + +#define LIGHT_RESET_SCRIPT "rm -rf /opt/netflix/* SD_CARD_MOUNT_PATH/netflix/* XDG_DATA_HOME/* XDG_CACHE_HOME/* XDG_CACHE_HOME/../.sparkStorage/ /opt/QT/home/data/* /opt/hn_service_settings.conf /opt/apps/common/proxies.conf /opt/lib/bluetooth" +#define INTERNAL_RESET_SCRIPT "rm -rf /opt/drm /opt/www/whitebox /opt/www/authService && /rebootNow.sh -s WarehouseService &" + +#define FRONT_PANEL_NONE -1 +#define FRONT_PANEL_INPROGRESS 1 +#define FRONT_PANEL_FAILED 3 +#define FRONT_PANEL_INTERVAL 5000 + + +namespace WPEFramework +{ + namespace Plugin + { +#ifdef HAS_FRONT_PANEL + static Core::TimerType ledTimer(64 * 1024, "LedTimer"); +#endif + SERVICE_REGISTRATION(Warehouse, 1, 0); + + Warehouse* Warehouse::_instance = nullptr; + + Warehouse::Warehouse() + : AbstractPlugin() +#ifdef HAS_FRONT_PANEL + , m_ledTimer(this) +#endif + { + LOGINFO(); + Warehouse::_instance = this; + + registerMethod(WAREHOUSE_METHOD_RESET_DEVICE, &Warehouse::resetDeviceWrapper, this); + registerMethod(WAREHOUSE_METHOD_GET_DEVICE_INFO, &Warehouse::getDeviceInfoWrapper, this); + registerMethod(WAREHOUSE_METHOD_GET_VERSION, &Warehouse::getDeviceInfoWrapper, this); + registerMethod(WAREHOUSE_METHOD_SET_FRONT_PANEL_STATE, &Warehouse::setFrontPanelStateWrapper, this); + registerMethod(WAREHOUSE_METHOD_INTERNAL_RESET, &Warehouse::internalResetWrapper, this); + registerMethod(WAREHOUSE_METHOD_LIGHT_RESET, &Warehouse::lightResetWrapper, this); + } + + Warehouse::~Warehouse() + { + LOGINFO(); + Warehouse::_instance = nullptr; + + if (m_resetThread.joinable()) + m_resetThread.join(); + } + + /** + * @brief This function is used to write the client name in the host file if + * the string list is empty by default ".warehouse.ccp.xcal.tv" will write in + * to the host file. + * + * @return Attribute of string value list. + */ + std::vector Warehouse::getAllowedCNameTails() + { + std::vector cnameTails; + std::ifstream file(HOSTS_FILE); + + LOGWARN("%s: attempt to open file '%s' for read mode with result %s", __FUNCTION__ + , HOSTS_FILE, file.good() ? "sucess" : "failure"); + + std::string line; + + while(std::getline(file, line)) + { + cnameTails.push_back(line); + } + + if (cnameTails.size() == 0) + cnameTails.push_back(DEFAULT_CNAME_TAIL); + + return cnameTails; + } + + /** + * @brief Creates a new task for resetting the device. + * An event will be dispatched after reset is done by notifying success code. + * @ingroup SERVMGR_WAREHOUSE_API + */ + void Warehouse::resetDevice() + { + resetDevice(false); + } + +#if defined(USE_IARMBUS) || defined(USE_IARM_BUS) + static void WareHouseResetIARM(Warehouse *wh, bool suppressReboot) + { + IARM_Bus_PWRMgr_WareHouseReset_Param_t whParam; + whParam.suppressReboot = suppressReboot; + IARM_Result_t err = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_WareHouseReset, &whParam, sizeof(whParam)); + + bool ok = err == IARM_RESULT_SUCCESS; + JsonObject params; + + params[PARAM_SUCCESS] = ok; + + if (!ok) + params[PARAM_ERROR] = "Reset failed"; + + string json; + params.ToString(json); + LOGINFO("Notify %s %s\n", WAREHOUSE_EVT_RESET_DONE, json.c_str()); + wh->Notify(WAREHOUSE_EVT_RESET_DONE, params); + } + + static bool RunScriptIARM(const std::string& script, std::string& error) + { + IARM_Bus_SYSMgr_RunScript_t runScriptParam; + runScriptParam.return_value = -1; + size_t len = sizeof(runScriptParam.script_path)/sizeof(char); + if(script.length() > (len - 1)) + { + std::stringstream errorss; + errorss << "Length of script greater than allowed limit of " << len << "."; + error = errorss.str(); + + LOGWARN("%s", error.c_str()); + return false; + } + + strcpy(runScriptParam.script_path, script.c_str()); + IARM_Bus_Call(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_API_RunScript, &runScriptParam, sizeof(runScriptParam)); + bool ok = runScriptParam.return_value == 0; + + std::stringstream message; + message << "script returned: " << runScriptParam.return_value; + + LOGINFO("%s", message.str().c_str()); + if (!ok) + error = message.str(); + return ok; + } +#endif + + void Warehouse::resetDevice(bool suppressReboot) + { +#if defined(USE_IARMBUS) || defined(USE_IARM_BUS) + + LOGWARN("Received request to terminate CoPilot"); + + if (m_resetThread.joinable()) + m_resetThread.join(); + + m_resetThread = std::thread(WareHouseResetIARM, this, suppressReboot); +#else + + JsonObject params; + + bool ok = false; + params[PARAM_SUCCESS] = ok; + + if (!ok) + params[PARAM_ERROR] = "No IARMBUS"; + + sendNotify(WAREHOUSE_EVT_RESET_DONE, params); +#endif + } + + /** + * @brief Returns a hash of properties for STB Device Information. + * This includes values for the following keys (uses /lib/rdk/getDeviceDetails.sh): + * Software version, IP and MAC of ecm, estb, moca etc. + * @ingroup SERVMGR_WAREHOUSE_API + */ + void Warehouse::getDeviceInfo(JsonObject ¶ms) + { + char buf[256]; + + FILE *p = popen(DEVICE_INFO_SCRIPT, "r"); + + if(!p) + { + LOGWARN("failed to run %s:%s", DEVICE_INFO_SCRIPT, strerror(errno)); + return; + } + + std::string res; + while(fgets(buf, sizeof(buf), p) != NULL) + res += buf; + + int errCode = pclose(p); + + if (0 != errCode) + { + params[PARAM_SUCCESS] = false; + params[PARAM_ERROR] = (const char *)strerror(errno); + } + + LOGINFO("'%s' returned: %s", DEVICE_INFO_SCRIPT, res.c_str()); + + std::stringstream ss(res); + std::string line; + while(std::getline(ss, line)) + { + size_t eq = line.find_first_of("="); + + if (std::string::npos != eq) + { + std::string key = line.substr(0, eq); + std::string value = line.substr(eq + 1); + + params[key.c_str()] = value; + + // some tweaks for backward compatibility + if (key == "imageVersion") + { + params["version"] = value; + params["software_version"] = value; + } + else if (key == "cableCardVersion") + params["cable_card_firmware_version"] = value; + } + } + } + +#ifdef HAS_FRONT_PANEL + static bool SetFrontPanelLights(int state, int iteration) + { + bool ledData = false; + bool ledRecord = false; + int ledBrightness = 100; + if (state == FRONT_PANEL_INPROGRESS) + { + // i 0 1 2 3 4 5 6 7 8 + // DA 1 1 1 1 0 0 0 0 1 + // RE 0 0 0 0 1 1 1 1 0 + // BR 100 75 50 25 0 25 50 75 100 + ledData = (iteration / 4) % 2 == 0; + ledRecord = !ledData; + ledBrightness = abs(100 - 25 * (iteration % 8)); + } + else if (state == FRONT_PANEL_FAILED) + { + // i 0 1 2 + // DA 1 0 1 + // RE 0 1 0 + // BR 100 100 100 + ledData = iteration % 2 == 0; + ledRecord = !ledData; + ledBrightness = 100; + } + LOGINFO("SetFrontPanelLights set Brightness=%d (LEDs: Data=%d Record=%d)", + ledBrightness, ledData?1:0, ledRecord?1:0); + CFrontPanel* helper = CFrontPanel::instance(); + bool didSet = false; + if (ledData) + didSet |= helper->powerOnLed(FRONT_PANEL_INDICATOR_MESSAGE); + else + didSet |= helper->powerOffLed(FRONT_PANEL_INDICATOR_MESSAGE); + if (ledRecord) + didSet |= helper->powerOnLed(FRONT_PANEL_INDICATOR_RECORD); + else + didSet |= helper->powerOffLed(FRONT_PANEL_INDICATOR_RECORD); + didSet |= helper->setBrightness(ledBrightness); + return didSet; + } +#endif + + /** + * @brief set the state of the front panel LEDs to indicate the download state of the STB + * software image. Possible state values: NONE, DOWNLOAD IN PROGRESS, DOWNLOAD FAILED. + * + * @param[in] state Integer value of front panel state to set. + * + * @return Returns true when all LED states set successfully, else returns false. + * @ingroup SERVMGR_WAREHOUSE_API + */ + void Warehouse::setFrontPanelState(int state, JsonObject& response) + { +#ifdef HAS_FRONT_PANEL + if (state != FRONT_PANEL_NONE && + state != FRONT_PANEL_INPROGRESS && + state != FRONT_PANEL_FAILED) + { + LOGERR("FrontPanelState incorrect state %d", state); + response[PARAM_SUCCESS] = false; + response[PARAM_ERROR] = "incorrect state"; + } + else + { + ledTimer.Revoke(m_ledTimer); + bool didSet = SetFrontPanelLights(state, 0); + LOGINFO("FrontPanelState %s to %d", didSet ? "set" : "not set", state); + response[PARAM_SUCCESS] = didSet; + if (!didSet) + { + response[PARAM_ERROR] = "front panel not set"; + } + else if (state != FRONT_PANEL_NONE) + { + LOGINFO("Triggering FrontPanel update by timer"); + m_ledTimerIteration = 1; + m_ledState = state; + ledTimer.Schedule(Core::Time::Now().Add(FRONT_PANEL_INTERVAL), m_ledTimer); + } + } +#else + LOGERR("FrontPanel unsupported"); + response[PARAM_SUCCESS] = false; + response[PARAM_ERROR] = "unsupported"; +#endif + } + + void Warehouse::internalReset(JsonObject& response) + { + bool isProd = false; + + if (0 == access(VERSION_FILE_NAME, R_OK)) + { + std::ifstream file(VERSION_FILE_NAME); + + LOGWARN("%s: attempt to open file '%s' for read mode with result %s", __FUNCTION__ + , VERSION_FILE_NAME, file.good() ? "sucess" : "failure"); + + std::string line; + while(std::getline(file, line)) + { + if (line.find("imagename:") != std::string::npos) + { + isProd = line.find("PROD") != std::string::npos; + break; + } + } + } + + if (isProd) + { + response[PARAM_SUCCESS] = false; + response[PARAM_ERROR] = "version is PROD"; + } + else + { +#if defined(USE_IARMBUS) || defined(USE_IARM_BUS) + std::string error; + bool ok = RunScriptIARM(INTERNAL_RESET_SCRIPT, error); + response[PARAM_SUCCESS] = ok; + if (!ok) + response[PARAM_ERROR] = error; +#else + response[PARAM_SUCCESS] = false; + response[PARAM_ERROR] = "No IARMBUS"; +#endif + } + } + + void Warehouse::lightReset(JsonObject& response) + { +#if defined(USE_IARMBUS) || defined(USE_IARM_BUS) + + std::string script(LIGHT_RESET_SCRIPT); + regex_t rx; + regcomp(&rx, "(\\s+)([A-Z_][0-9A-Z_]*)(\\S*)", REG_EXTENDED); + regmatch_t rm[4]; + + int pos = 0; + while (regexec(&rx, script.c_str() + pos, 4, rm, 0) == REG_NOERROR) + { + std::string var = script.substr(pos + rm[2].rm_so, rm[2].rm_eo - rm[2].rm_so); + std::string replace; + const char *envVar = getenv(var.c_str()); + + std::string scmp; + if ("SD_CARD_MOUNT_PATH" == var && (!envVar || 0 == *envVar)) + { + + FILE *p = popen("cat /proc/mounts | grep mmcblk0p1 | awk '{print $2}' ", "r"); + + if(!p) + { + LOGWARN("failed to run script to get SD_CARD_MOUNT_PATH"); + } + else + { + char buf[256]; + while(fgets(buf, sizeof(buf), p) != NULL) + scmp += buf; + + scmp.erase(0, scmp.find_first_not_of(" \n\r\t")); + scmp.erase(scmp.find_last_not_of(" \n\r\t") + 1); + + envVar = scmp.c_str(); + pclose(p); + } + } + + if (envVar && *envVar) + { + replace += envVar; + replace += script.substr(pos + rm[3].rm_so, rm[3].rm_eo - rm[3].rm_so); + if (replace.size() > 0) + { + if ('/' == replace[0]) + { + size_t nr = replace.find_first_not_of('/'); + if (string::npos != nr && '*' != replace[nr]) // Check if that is not root dir + replace = script.substr(pos + rm[1].rm_so, rm[1].rm_eo - rm[1].rm_so) + replace; + else + replace = ""; + } + else + replace = script.substr(pos + rm[1].rm_so, rm[1].rm_eo - rm[1].rm_so) + replace; + } + } + script.replace(pos + rm[0].rm_so, rm[0].rm_eo - rm[0].rm_so, replace); + pos += rm[0].rm_so + replace.size(); + } + + LOGWARN("lightReset: %s", script.c_str()); + + std::string error; + bool ok = RunScriptIARM(script, error); + response[PARAM_SUCCESS] = ok; + if (ok) + { + LOGWARN("lightReset succeeded"); + } + else + { + LOGERR("lightReset failed. %s", error.c_str()); + response[PARAM_ERROR] = error; + } +#else + LOGERR("lightReset failed: No IARMBUS"); + response[PARAM_SUCCESS] = false; + response[PARAM_ERROR] = "No IARMBUS"; +#endif + } + + uint32_t Warehouse::resetDeviceWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + bool suppressReboot = false; + if (parameters.HasLabel("suppressReboot")) + { + getBoolParameter("suppressReboot", suppressReboot); + } + + resetDevice(suppressReboot); + + response["PARAM_SUCCESS"] = true; + returnResponse(true); + } + + uint32_t Warehouse::getDeviceInfoWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + JsonObject deviceInfo; + getDeviceInfo(deviceInfo); + + response["deviceInfo"] = deviceInfo; + response["PARAM_SUCCESS"] = true; + returnResponse(true); + } + + uint32_t Warehouse::setFrontPanelStateWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + int state = 0; + if (parameters.HasLabel("state")) + getNumberParameter("state", state); + + setFrontPanelState(state, response); + return Core::ERROR_NONE; + } + + uint32_t Warehouse::internalResetWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + if (parameters.HasLabel("passPhrase") && parameters["passPhrase"].String() == "FOR TEST PURPOSES ONLY") + { + internalReset(response); + return (Core::ERROR_NONE); + } + else + { + response[PARAM_SUCCESS] = false; + response[PARAM_ERROR] = "incorrect pass phrase"; + returnResponse(false); + } + } + + uint32_t Warehouse::lightResetWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO(); + + lightReset(response); + return Core::ERROR_NONE; + } + + +#ifdef HAS_FRONT_PANEL + void Warehouse::onSetFrontPanelStateTimer() + { + SetFrontPanelLights(m_ledState, m_ledTimerIteration); + ++m_ledTimerIteration; + ledTimer.Schedule(Core::Time::Now().Add(FRONT_PANEL_INTERVAL), m_ledTimer); + } + + uint64_t LedInfo::Timed(const uint64_t scheduledTime) + { + LOGINFO(); + uint64_t result = 0; + m_warehouse->onSetFrontPanelStateTimer(); + return(result); + } +#endif + + + } // namespace Plugin +} // namespace WPEFramework diff --git a/Warehouse/Warehouse.h b/Warehouse/Warehouse.h new file mode 100644 index 0000000000..b3986020a7 --- /dev/null +++ b/Warehouse/Warehouse.h @@ -0,0 +1,125 @@ +/** +* 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 "Module.h" +#include "utils.h" +#include "AbstractPlugin.h" + +namespace WPEFramework { + + namespace Plugin { + +#ifdef HAS_FRONT_PANEL + class Warehouse; + class LedInfo + { + private: + LedInfo() = delete; + LedInfo& operator=(const LedInfo& RHS) = delete; + + public: + LedInfo(Warehouse* wh) + : m_warehouse(wh) + { + } + LedInfo(const LedInfo& copy) + : m_warehouse(copy.m_warehouse) + { + } + ~LedInfo() {} + + inline bool operator==(const LedInfo& RHS) const + { + return(m_warehouse == RHS.m_warehouse); + } + + public: + uint64_t Timed(const uint64_t scheduledTime); + + private: + Warehouse* m_warehouse; + }; +#endif + + // 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 Warehouse : public AbstractPlugin { + private: + + // We do not allow this plugin to be copied !! + Warehouse(const Warehouse&) = delete; + Warehouse& operator=(const Warehouse&) = delete; + + void resetDevice(); + void resetDevice(bool suppressReboot); + std::vector getAllowedCNameTails(); + void setFrontPanelState(int state, JsonObject& response); + void internalReset(JsonObject& response); + void lightReset(JsonObject& response); + + //Begin methods + uint32_t setApiVersionNumberWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getApiVersionNumberWrapper(const JsonObject& parameters, JsonObject& response); + + uint32_t resetDeviceWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getDeviceInfoWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setFrontPanelStateWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t internalResetWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t lightResetWrapper(const JsonObject& parameters, JsonObject& response); + //End methods + + public: + Warehouse(); + virtual ~Warehouse(); + + void onSetFrontPanelStateTimer(); + + public: + static Warehouse* _instance; + private: + void getDeviceInfo(JsonObject ¶ms); + + //TODO/FIXME -- these are carried over from ServiceManager FrontPanel - we need to munge this around to support the Thunder plugin version number + uint32_t getApiVersionNumber(); + void setApiVersionNumber(uint32_t apiVersionNumber); + + std::thread m_resetThread; + +#ifdef HAS_FRONT_PANEL + LedInfo m_ledTimer; + int m_ledTimerIteration; + int m_ledState; +#endif + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/Warehouse/Warehouse.json b/Warehouse/Warehouse.json new file mode 100644 index 0000000000..d19e573a91 --- /dev/null +++ b/Warehouse/Warehouse.json @@ -0,0 +1,8 @@ +{ + "locator":"libWPEFrameworkWarehouse.so", + "classname":"Warehouse", + "precondition":[ + "Platform" + ], + "autostart":true +} \ No newline at end of file diff --git a/Warehouse/cmake/FindDS.cmake b/Warehouse/cmake/FindDS.cmake new file mode 100644 index 0000000000..caacbfb99a --- /dev/null +++ b/Warehouse/cmake/FindDS.cmake @@ -0,0 +1,33 @@ +# - 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_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/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/Warehouse/cmake/FindIARMBus.cmake b/Warehouse/cmake/FindIARMBus.cmake new file mode 100644 index 0000000000..9ec0f8e577 --- /dev/null +++ b/Warehouse/cmake/FindIARMBus.cmake @@ -0,0 +1,33 @@ +# - 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(IARMBUS_INCLUDE_DIRS NAMES libIARM.h PATH_SUFFIXES rdk/iarmbus) +#find_path(IARMIR_INCLUDE_DIRS NAMES irMgr.h PATH_SUFFIXES rdk/iarmmgrs/ir) +find_path(IARMIR_INCLUDE_DIRS NAMES sysMgr.h PATH_SUFFIXES rdk/iarmmgrs/sysmgr) +find_path(IARMPWR_INCLUDE_DIRS NAMES pwrMgr.h PATH_SUFFIXES rdk/iarmmgrs-hal) + +set(IARMBUS_LIBRARIES ${IARMBUS_LIBRARIES} CACHE PATH "Path to IARMBus library") +set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${IARMPWR_INCLUDE_DIRS}) +set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${IARMPWR_INCLUDE_DIRS} CACHE PATH "Path to IARMBus include") + + +if (DS_FOUND) +endif (DS_FOUND) + +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/broadcom.cmake b/broadcom.cmake new file mode 100644 index 0000000000..66eb5bcaf3 --- /dev/null +++ b/broadcom.cmake @@ -0,0 +1,320 @@ +########################################################################## +# 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. +########################################################################### + + +# Broadcom specifics +message("Building for Broadcom...") + +add_definitions (-DPLATFORM_BROADCOM) +add_definitions (-DUSE_SOUND_PLAYER) + + +#DeadCodeStrip(DCS)...forRNG150sizereduction +add_definitions (-DENABLE_DCS_BUILD_FLAGS) + +add_definitions (-DUSE_IARM) +option(USE_IARM "USE_IARM" ON) +add_definitions (-DUSE_DEVICE_SETTINGS_SERVICE) +add_definitions (-DHAS_API_SYSTEM) +add_definitions (-DCROSS_COMPILED_FOR_DEVICE) +add_definitions (-DHAS_API_HOME_NETWORKING) +#add_definitions (-DHAS_API_QAM_METADATA) +add_definitions (-DNEXUS_NSC_SUPPORT) +add_definitions (-DRDK_USE_NXCLIENT) +add_definitions (-DHAS_API_POWERSTATE) +add_definitions (-DDISABLE_PRE_RES_CHANGE_EVENTS) +add_definitions (-DHAS_API_APPLICATION) +add_definitions (-DHAS_API_PING) +add_definitions (-DHAS_API_HDCP_COMPLIANCE) +add_definitions (-DHAS_API_DOWNLOADS) + +# Enabling image caching for all broadcom devices +add_definitions (-DHAS_API_DEVICEPROVISIONING) + +if (BUILD_DONT_SET_POWER_BRIGHTNESS) + message("Building with dont set power brightness") + add_definitions (-DBUILD_DONT_SET_POWER_BRIGHTNESS) + add_definitions (-DDONT_SET_POWER_BRIGHTNESS) +endif() + +if (BUILD_ENABLE_HDCP) + message("Building with hdcp profile") + add_definitions (-DBUILD_ENABLE_HDCP) + add_definitions (-DENABLE_HDCP_PROFILE) +endif() + +if (BUILD_ENABLE_LEGACY_HDCP_PROFILE) + message("Building with hdcp profile 0 and 1") + add_definitions (-DBUILD_ENABLE_LEGACY_HDCP_PROFILE) + add_definitions (-DENABLE_HDCP_PROFILE_0_1) +endif() + +if (BUILD_DISABLE_HOME_NETWORKING_V2) + message("Building with hn2 disabled") + add_definitions (-DBUILD_DISABLE_HOME_NETWORKING_V2) + add_definitions (-DDISABLE_API_HOME_NETWORKING_2) +endif() + +if (BUILD_DBUS) + message("Building for DBUS") + + add_definitions (-DBUILD_DBUS) + option(BUILD_DBUS "BUILD_DBUS" ON) + add_definitions (-DIARM_USE_DBUS) + option(IARM_USE_DBUS "IARM_USE_DBUS" ON) +# LIBS += -ldbus-1 +endif() + +if (BUILD_ENABLE_THERMAL_PROTECTION) +add_definitions (-DBUILD_ENABLE_THERMAL_PROTECTION) + add_definitions (-DENABLE_THERMAL_PROTECTION) +endif() + +if (BUILD_XG1) + message("Building for XG1") + add_definitions (-DBUILD_XG1) + + add_definitions (-DUSE_LSB) + add_definitions (-DHAS_STATE_OBSERVER) + add_definitions (-DDONT_SET_POWER_BRIGHTNESS) + add_definitions (-DUSE_COMMON_XG1_XI3) + add_definitions (-DHAS_FRONT_PANEL) + option(HAS_FRONT_PANEL "HAS_FRONT_PANEL" ON) + add_definitions (-DRF4CE_API) + + if(NOT OEM_VENDOR_CISCO) + message ("Building for non-CISCO platforms") + add_definitions (-DHAS_FRONT_PANEL_MOTO) + else() + add_definitions (-DKILL_IF_FROZEN_AFTER_EXIT) + endif() + + add_definitions (-DMSO_PAIRING) + add_definitions (-DENABLE_MSOPAIRING_4) + add_definitions (-DENABLE_MSOPAIRING_5) + add_definitions (-DENABLE_MSOPAIRING_6) + add_definitions (-DENABLE_VREX_SERVICE) + #add_definitions (-DENABLE_UPDATE_MANAGER_SERVICE) + add_definitions (-DENABLE_REMOTE_ACTION_MAPPING_SERVICE) + add_definitions (-DUSE_UNIFIED_RF4CE_MGR_API_4) + add_definitions (-DENABLE_CONTROL_SERVICE) + add_definitions (-DENABLE_FRONT_PANEL_API_V4) + + add_definitions (-DUSE_UPNP_DISCOVERY) + add_definitions (-DENABLE_VREX_SERVICE) + + # added for Arris Xone + if (USE_IARM) + add_definitions (-DUSE_IARM_BUS) + option(USE_IARM_BUS "USE_IARM_BUS" ON) + endif() + + if (BUILD_QAM) + message("Building for QAM on XG1") + add_definitions (-DHAS_QAM) + endif() + + if (USE_IARM_BUS) + add_definitions (-DMSO_PAIRING) + add_definitions (-DENABLE_MSOPAIRING_4) + add_definitions (-DENABLE_MSOPAIRING_5) + add_definitions (-DENABLE_MSOPAIRING_6) + add_definitions (-DENABLE_VREX_SERVICE) + #add_definitions (-DENABLE_UPDATE_MANAGER_SERVICE) + add_definitions (-DENABLE_REMOTE_ACTION_MAPPING_SERVICE) + add_definitions (-DUSE_UNIFIED_RF4CE_MGR_API_4) + add_definitions (-DENABLE_CONTROL_SERVICE) + add_definitions (-DHAS_FRONT_PANEL) + option(HAS_FRONT_PANEL "HAS_FRONT_PANEL" ON) + add_definitions (-DUSE_DS) + add_definitions (-DUSE_DISPLAY_SETTINGS) + endif() + + if (HAS_FRONT_PANEL) + add_definitions (-DCLOCK_BRIGHTNESS_ENABLED) + endif() +endif() + +if (BUILD_XG1V3) + message("Building for XG1v3") + add_definitions (-DBUILD_XG1V3) + + add_definitions (-DUSE_COMMON_XG1_XI3) + + add_definitions (-DENABLE_FRONT_PANEL_API_VERSION_3) + add_definitions (-DCLOCK_BRIGHTNESS_ENABLED) + add_definitions (-DUSE_UPNP_DISCOVERY) + add_definitions (-DDONT_SET_POWER_BRIGHTNESS) + add_definitions (-DUSE_LSB) + add_definitions (-DHAS_STATE_OBSERVER) + add_definitions (-DENABLE_VREX_SERVICE) + #add_definitions (-DENABLE_UPDATE_MANAGER_SERVICE) + add_definitions (-DENABLE_REMOTE_ACTION_MAPPING_SERVICE) + add_definitions (-DENABLE_CONTROL_SERVICE) + add_definitions (-DRF4CE_API) + add_definitions (-DENABLE_FRONT_PANEL_API_V4) + + # added for Iarmbus support + if (USE_IARM) + add_definitions (-DUSE_IARM_BUS) + option(USE_IARM_BUS "USE_IARM_BUS" ON) + add_definitions (-DUSE_DISPLAY_SETTINGS) + endif() + + if (USE_IARM_BUS) + add_definitions (-DMSO_PAIRING) + add_definitions (-DENABLE_MSOPAIRING_4) + add_definitions (-DENABLE_MSOPAIRING_5) + add_definitions (-DENABLE_MSOPAIRING_6) + add_definitions (-DENABLE_VREX_SERVICE) + #add_definitions (-DENABLE_UPDATE_MANAGER_SERVICE) + add_definitions (-DENABLE_REMOTE_ACTION_MAPPING_SERVICE) + add_definitions (-DENABLE_CONTROL_SERVICE) + add_definitions (-DHAS_FRONT_PANEL) + option(HAS_FRONT_PANEL "HAS_FRONT_PANEL" ON) + add_definitions (-DUSE_DS) + endif() +endif() + +if (BUILD_XG2) + message("Building for XG2") + add_definitions (-DBUILD_XG2) + + # Dead Code Strip (DCS) ... for xg2v2 size reduction + add_definitions (-DENABLE_DCS_BUILD_FLAGS) + + add_definitions (-DENABLE_FRONT_PANEL_API_V4) + add_definitions (-DUSE_COMMON_XG1_XI3) + add_definitions (-DUSE_UPNP_DISCOVERY) + + add_definitions (-DDONT_SET_POWER_BRIGHTNESS) + add_definitions (-DUSE_LSB) + add_definitions (-DHAS_STATE_OBSERVER) + add_definitions (-DENABLE_VREX_SERVICE) + #add_definitions (-DENABLE_UPDATE_MANAGER_SERVICE) + add_definitions (-DENABLE_REMOTE_ACTION_MAPPING_SERVICE) + add_definitions (-DENABLE_CONTROL_SERVICE) + + # added for Iarmbus support + if (USE_IARM) + add_definitions (-DUSE_IARM_BUS) + option(USE_IARM_BUS "USE_IARM_BUS" ON) + add_definitions (-DUSE_DISPLAY_SETTINGS) + add_definitions (-DUSE_TSB_SETTINGS) + endif() + + if (USE_IARM_BUS) + add_definitions (-DMSO_PAIRING) + add_definitions (-DENABLE_MSOPAIRING_4) + add_definitions (-DENABLE_MSOPAIRING_5) + add_definitions (-DENABLE_MSOPAIRING_6) + add_definitions (-DHAS_FRONT_PANEL) + option(HAS_FRONT_PANEL "HAS_FRONT_PANEL" ON) + add_definitions (-DUSE_DS) + add_definitions (-DENABLE_VREX_SERVICE) + #add_definitions (-DENABLE_UPDATE_MANAGER_SERVICE) + + add_definitions (-DENABLE_REMOTE_ACTION_MAPPING_SERVICE) + add_definitions (-DENABLE_CONTROL_SERVICE) + endif() + + if (OEM_VENDOR_SAMSUNG) + add_definitions (-DUSE_IARMBUS) + add_definitions (-DUSE_GENERIC_MSO_PAIRING) + endif() + + add_definitions (-DRF4CE_API) +endif() + +if (BUILD_XI3) + message("Building for XI3") + add_definitions (-DBUILD_XI3) + #To enable dlna Mimetype only for Xi3 builds + + add_definitions (-DENABLE_DEEP_SLEEP) + add_definitions (-DUSE_COMMON_XG1_XI3) + add_definitions (-DUSE_UIMAF) + + if (USE_IARM) + add_definitions (-DUSE_IARM_BUS) + option(USE_IARM_BUS "USE_IARM_BUS" ON) + add_definitions (-DUSE_DISPLAY_SETTINGS) + add_definitions (-DUSE_TSB_SETTINGS) + endif() + + add_definitions (-DMSO_PAIRING) + add_definitions (-DENABLE_VREX_SERVICE) + #add_definitions (-DENABLE_UPDATE_MANAGER_SERVICE) + add_definitions (-DENABLE_REMOTE_ACTION_MAPPING_SERVICE) + add_definitions (-DENABLE_CONTROL_SERVICE) + add_definitions (-DMSO_PAIRING_ENABLE_LOS) + add_definitions (-DENABLE_MSOPAIRING_4) + add_definitions (-DENABLE_MSOPAIRING_5) + add_definitions (-DENABLE_MSOPAIRING_6) + add_definitions (-DHAS_FRONT_PANEL) + option(HAS_FRONT_PANEL "HAS_FRONT_PANEL" ON) + add_definitions (-DENABLE_FRONT_PANEL_API_V4) + #add_definitions (-DHAS_STATE_OBSERVER) + add_definitions (-DUSE_DS) + add_definitions (-DENABLE_GET_SET_APIVERSION) + add_definitions (-DUSE_UPNP_DISCOVERY) + add_definitions (-DUSE_TR_69) + add_definitions (-DENABLE_VREX_SERVICE) + add_definitions (-DRF4CE_API) + add_definitions (-DHAS_STATE_OBSERVER) +endif() + +if(SCREEN_CAPTURE) + if(NOT DISABLE_SCREEN_CAPTURE) + message("Yocto Broadcom build: Building Broadcom NEXUS specific screen capturing") + add_definitions (-DPLATFORM_SCREEN_CAPTURE) + endif() +endif() + +if(DEFINES,USE_COMMON_XG1_XI3) + add_definitions (-DHAS_API_AVINPUT) + add_definitions (-DUSE_AVINPUT) + add_definitions (-DQT_GUI_LIB) + add_definitions (-DQT_NO_QWS_CURSOR) + add_definitions (-DQT_NETWORK_LIB) + add_definitions (-DQT_SHARED) + add_definitions (-DQT_CORE_LIB) + add_definitions (-DQT_NO_DEBUG) + add_definitions (-DMSO_PAIRING_ENABLE_LOS) + add_definitions (-DDISABLE_API_HOME_NETWORKING_2) + add_definitions (-DDISABLE_WEBKIT_WIDGETS) + add_definitions (-DENABLE_GET_SET_APIVERSION) +endif() + + + # Front panel support +#if(HAS_FRONT_PANEL) +# if(HAS_RDK_SET_STATE) +# SOURCES += ../../platform/broadcom/src/helpers/frontpanel_rdk.cpp +# endif() + +# if (HAS_FRONT_PANEL_MOTO) +# CONFIG += no_smart_library_merge +# INCLUDEPATH += "${COMBINED_ROOT}/ri/mpe_os/platforms/broadcom/bcm97425/mfrlibs" +# endif() +#endif() + + +# SNMP MIB support + diff --git a/cmake/FindAC.cmake b/cmake/FindAC.cmake new file mode 100644 index 0000000000..23d3f404bb --- /dev/null +++ b/cmake/FindAC.cmake @@ -0,0 +1,26 @@ +# - Try to find Audio Capture Mgr +# Once done this will define +# AC_FOUND - System has audiocapturemgr +# AC_INCLUDE_DIRS - The audiocapturemgr include directories +# AC_LIBRARIES - The libraries needed to use audiocapturemgr +# AC_FLAGS - The flags needed to use audiocapturemgr +# + +find_package(PkgConfig) + +find_library(AC_LIBRARIES NAMES audiocapturemgr) +find_path(AC_INCLUDE_DIRS NAMES audiocapturemgr_iarm.h PATH_SUFFIXES audiocapturemgr) + +set(AC_LIBRARIES ${AC_LIBRARIES} CACHE PATH "Path to audiocapturemgr library") +set(AC_INCLUDE_DIRS ${AC_INCLUDE_DIRS} ) +set(AC_INCLUDE_DIRS ${AC_INCLUDE_DIRS} CACHE PATH "Path to audiocapturemgr include") + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(AC DEFAULT_MSG AC_INCLUDE_DIRS AC_LIBRARIES) + +mark_as_advanced( + AC_FOUND + AC_INCLUDE_DIRS + AC_LIBRARIES + AC_LIBRARY_DIRS + AC_FLAGS) diff --git a/cmake/FindCEC.cmake b/cmake/FindCEC.cmake new file mode 100644 index 0000000000..e3641d6e54 --- /dev/null +++ b/cmake/FindCEC.cmake @@ -0,0 +1,35 @@ +# - 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(CEC_LIBRARIES NAMES RCEC) +find_library(CEC_IARM_LIBRARIES NAMES RCECIARMBusHal) +find_library(OSAL_LIBRARIES NAMES RCECOSHal) + +find_path(CEC_INCLUDE_DIRS NAMES ccec/Connection.hpp PATH_SUFFIXES ccec/include) +find_path(OSAL_INCLUDE_DIRS NAMES osal/Mutex.hpp PATH_SUFFIXES osal/include) +find_path(CEC_HOST_INCLUDE_DIRS NAMES ccec/host/RDK.hpp PATH_SUFFIXES host/include) +find_path(CEC_IARM_INCLUDE_DIRS NAMES ccec/drivers/iarmbus/CecIARMBusMgr.h PATH_SUFFIXES ccec/drivers/include) + +set(CEC_LIBRARIES "-Wl,--no-as-needed" ${CEC_LIBRARIES} ${CEC_IARM_LIBRARIES} ${OSAL_LIBRARIES} "-Wl,--as-needed") + +set(CEC_LIBRARIES ${CEC_LIBRARIES} CACHE PATH "Path to CEC library") + +set(CEC_INCLUDE_DIRS ${CEC_INCLUDE_DIRS} ${OSAL_INCLUDE_DIRS} ${CEC_HOST_INCLUDE_DIRS} ${CEC_IARM_INCLUDE_DIRS}) +set(CEC_INCLUDE_DIRS ${CEC_INCLUDE_DIRS} CACHE PATH "Path to CEC include") + +include(FindPackageHandleStandardArgs) +#FIND_PACKAGE_HANDLE_STANDARD_ARGS(IARMBUS DEFAULT_MSG IARMBUS_INCLUDE_DIRS IARMBUS_LIBRARIES) + +mark_as_advanced( + CEC_FOUND + CEC_INCLUDE_DIRS + CEC_LIBRARIES + CEC_LIBRARY_DIRS + CEC_FLAGS) diff --git a/cmake/FindCTRLM.cmake b/cmake/FindCTRLM.cmake new file mode 100644 index 0000000000..7386b21c7a --- /dev/null +++ b/cmake/FindCTRLM.cmake @@ -0,0 +1,19 @@ +# - Try to find ControlManager +# Once done this will define +# CTRLM_FOUND - System has ControlManager +# CTRLM_INCLUDE_DIRS - The ControlManager include directories +# + +find_package(PkgConfig) + +find_path(CTRLM_INCLUDE_DIRS NAMES ctrlm_ipc.h) + +set(CTRLM_INCLUDE_DIRS ${CTRLM_INCLUDE_DIRS}) +set(CTRLM_INCLUDE_DIRS ${CTRLM_INCLUDE_DIRS} CACHE PATH "Path to ControlManager include") + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(CTRLM DEFAULT_MSG CTRLM_INCLUDE_DIRS) + +mark_as_advanced( + CTRLM_FOUND + CTRLM_INCLUDE_DIRS) diff --git a/cmake/FindCurl.cmake b/cmake/FindCurl.cmake new file mode 100644 index 0000000000..60b821897c --- /dev/null +++ b/cmake/FindCurl.cmake @@ -0,0 +1,16 @@ +# - Try to find curl + +find_package(PkgConfig) + +find_library(CURL_LIBRARY NAMES curl) + +set(CURL_LIBRARY ${CURL_LIBRARY} CACHE PATH "Path to curl library") + +include(FindPackageHandleStandardArgs) + +mark_as_advanced( + CURL_FOUND + CURL_INCLUDE_DIRS + CURL_LIBRARIES + CURL_LIBRARY_DIRS + CURL_FLAGS) diff --git a/cmake/FindDS.cmake b/cmake/FindDS.cmake new file mode 100644 index 0000000000..caacbfb99a --- /dev/null +++ b/cmake/FindDS.cmake @@ -0,0 +1,33 @@ +# - 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_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/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/cmake/FindGLIB.cmake b/cmake/FindGLIB.cmake new file mode 100644 index 0000000000..93d3ec5479 --- /dev/null +++ b/cmake/FindGLIB.cmake @@ -0,0 +1,122 @@ +# - Try to find Glib and its components (gio, gobject etc) +# Once done, this will define +# +# GLIB_FOUND - system has Glib +# GLIB_INCLUDE_DIRS - the Glib include directories +# GLIB_LIBRARIES - link these to use Glib +# +# Optionally, the COMPONENTS keyword can be passed to find_package() +# and Glib components can be looked for. Currently, the following +# components can be used, and they define the following variables if +# found: +# +# gio: GLIB_GIO_LIBRARIES +# gobject: GLIB_GOBJECT_LIBRARIES +# gmodule: GLIB_GMODULE_LIBRARIES +# gthread: GLIB_GTHREAD_LIBRARIES +# +# Note that the respective _INCLUDE_DIR variables are not set, since +# all headers are in the same directory as GLIB_INCLUDE_DIRS. +# +# Copyright (C) 2012 Raphael Kubo da Costa +# +# 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. + +find_package(PkgConfig) +pkg_check_modules(PC_GLIB QUIET glib-2.0) + +find_library(GLIB_LIBRARIES + NAMES glib-2.0 + HINTS ${PC_GLIB_LIBDIR} + ${PC_GLIB_LIBRARY_DIRS} +) + +# Files in glib's main include path may include glibconfig.h, which, +# for some odd reason, is normally in $LIBDIR/glib-2.0/include. +get_filename_component(_GLIB_LIBRARY_DIR ${GLIB_LIBRARIES} PATH) +find_path(GLIBCONFIG_INCLUDE_DIR + NAMES glibconfig.h + HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${_GLIB_LIBRARY_DIR} + ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} + PATH_SUFFIXES glib-2.0/include +) + +find_path(GLIB_INCLUDE_DIR + NAMES glib.h + HINTS ${PC_GLIB_INCLUDEDIR} + ${PC_GLIB_INCLUDE_DIRS} + PATH_SUFFIXES glib-2.0 +) + +set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR}) + +# Version detection +if (EXISTS "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h") + file(READ "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" GLIBCONFIG_H_CONTENTS) + string(REGEX MATCH "#define GLIB_MAJOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") + set(GLIB_VERSION_MAJOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "#define GLIB_MINOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") + set(GLIB_VERSION_MINOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "#define GLIB_MICRO_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") + set(GLIB_VERSION_MICRO "${CMAKE_MATCH_1}") + set(GLIB_VERSION "${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR}.${GLIB_VERSION_MICRO}") +endif () + +# Additional Glib components. We only look for libraries, as not all of them +# have corresponding headers and all headers are installed alongside the main +# glib ones. +foreach (_component ${GLIB_FIND_COMPONENTS}) + if (${_component} STREQUAL "gio") + find_library(GLIB_GIO_LIBRARIES NAMES gio-2.0 HINTS ${_GLIB_LIBRARY_DIR}) + set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GIO_LIBRARIES) + elseif (${_component} STREQUAL "gobject") + find_library(GLIB_GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${_GLIB_LIBRARY_DIR}) + set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GOBJECT_LIBRARIES) + elseif (${_component} STREQUAL "gmodule") + find_library(GLIB_GMODULE_LIBRARIES NAMES gmodule-2.0 HINTS ${_GLIB_LIBRARY_DIR}) + set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GMODULE_LIBRARIES) + elseif (${_component} STREQUAL "gthread") + find_library(GLIB_GTHREAD_LIBRARIES NAMES gthread-2.0 HINTS ${_GLIB_LIBRARY_DIR}) + set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GTHREAD_LIBRARIES) + elseif (${_component} STREQUAL "gio-unix") + # gio-unix is compiled as part of the gio library, but the include paths + # are separate from the shared glib ones. Since this is currently only used + # by WebKitGTK+ we don't go to extraordinary measures beyond pkg-config. + pkg_check_modules(GIO_UNIX QUIET gio-unix-2.0) + endif () +endforeach () + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLIB REQUIRED_VARS GLIB_INCLUDE_DIRS GLIB_LIBRARIES ${ADDITIONAL_REQUIRED_VARS} + VERSION_VAR GLIB_VERSION) + +mark_as_advanced( + GLIBCONFIG_INCLUDE_DIR + GLIB_GIO_LIBRARIES + GLIB_GIO_UNIX_LIBRARIES + GLIB_GMODULE_LIBRARIES + GLIB_GOBJECT_LIBRARIES + GLIB_GTHREAD_LIBRARIES + GLIB_INCLUDE_DIR + GLIB_INCLUDE_DIRS + GLIB_LIBRARIES +) diff --git a/cmake/FindIARMBus.cmake b/cmake/FindIARMBus.cmake new file mode 100644 index 0000000000..c0e0571e17 --- /dev/null +++ b/cmake/FindIARMBus.cmake @@ -0,0 +1,29 @@ +# - 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(IARMBUS_INCLUDE_DIRS NAMES libIARM.h PATH_SUFFIXES rdk/iarmbus) +find_path(IARMIR_INCLUDE_DIRS NAMES irMgr.h PATH_SUFFIXES rdk/iarmmgrs/ir) +find_path(IARMPWR_INCLUDE_DIRS NAMES pwrMgr.h PATH_SUFFIXES rdk/iarmmgrs-hal) + +set(IARMBUS_LIBRARIES ${IARMBUS_LIBRARIES} CACHE PATH "Path to IARMBus library") +set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${IARMPWR_INCLUDE_DIRS}) +set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${IARMPWR_INCLUDE_DIRS} 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/cmake/FindNopoll.cmake b/cmake/FindNopoll.cmake new file mode 100644 index 0000000000..3f9fd1e9bb --- /dev/null +++ b/cmake/FindNopoll.cmake @@ -0,0 +1,16 @@ +# - Try to find RDK Storage Manager library +# Once done this will define +# NOPOLL_FOUND - System has Nopoll +# NOPOLL_LIBRARIES - The libraries needed to use Nopoll + +find_package(PkgConfig) + +find_path(NOPOLL_INCLUDE_DIRS NAMES nopoll.h PATH_SUFFIXES nopoll) +#find_path(NOPOLL_INCLUDE_DIRS NAMES libIARM.h PATH_SUFFIXES rdk/iarmbus) + +find_library(NOPOLL_LIBRARIES NAMES nopoll) + +mark_as_advanced( + NOPOLL_FOUND + NOPOLL_INCLUDE_DIRS + NOPOLL_LIBRARIES) \ No newline at end of file diff --git a/cmake/FindRDKStorageManager.cmake b/cmake/FindRDKStorageManager.cmake new file mode 100644 index 0000000000..6acfb9031c --- /dev/null +++ b/cmake/FindRDKStorageManager.cmake @@ -0,0 +1,12 @@ +# - Try to find RDK Storage Manager library +# Once done this will define +# RDK_SM_FOUND - System has DS +# RDK_SM_LIBRARIES - The libraries needed to use DS + +find_package(PkgConfig) + +find_library(RDK_SM_LIBRARIES NAMES rdkstmgr) + +mark_as_advanced( + RDK_SM_FOUND + RDK_SM_LIBRARIES) \ No newline at end of file diff --git a/cmake/FindTTS.cmake b/cmake/FindTTS.cmake new file mode 100644 index 0000000000..40d795683f --- /dev/null +++ b/cmake/FindTTS.cmake @@ -0,0 +1,25 @@ +# - Try to find Display Settings library +# Once done this will define +# TTS_INCLUDE_DIRS - The TTS include directories +# TTS_LIBRARIES - The libraries needed to use TTS +# + +find_package(PkgConfig) +find_library(TTS_LIBRARIES NAMES TTSClient) +find_path(TTS_INCLUDE_DIRS NAMES TTSCommon.h) +find_path(TTSC_INCLUDE_DIRS NAMES TTSClient.h) + +set(TTS_LIBRARIES ${TTS_LIBRARIES} CACHE PATH "Path to TTSClient") +set(TTS_INCLUDE_DIRS ${TTS_INCLUDE_DIRS} CACHE PATH "Path to TTS include") +set(TTSC_INCLUDE_DIRS ${TTSC_INCLUDE_DIRS} CACHE PATH "Path to TTSClient include") + + + +include(FindPackageHandleStandardArgs) + +mark_as_advanced( + TTS_INCLUDE_DIRS + TTSC_INCLUDE_DIRS + TTS_LIBRARIES) + + diff --git a/helpers/AbstractPlugin.h b/helpers/AbstractPlugin.h new file mode 100644 index 0000000000..53376101b4 --- /dev/null +++ b/helpers/AbstractPlugin.h @@ -0,0 +1,107 @@ +/** +* 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 "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 AbstractPlugin : public PluginHost::IPlugin, public PluginHost::JSONRPC { + private: + + // We do not allow this plugin to be copied !! + AbstractPlugin(const AbstractPlugin&) = delete; + AbstractPlugin& operator=(const AbstractPlugin&) = delete; + + //Begin methods + virtual uint32_t getQuirks(const JsonObject& parameters, JsonObject& response) + { + JsonArray array; + response["quirks"] = array; + returnResponse(true); + } + //End methods + + protected: + template + void registerMethod(const string& methodName, const METHOD& method, REALOBJECT* objectPtr) + { + Register(methodName, method, objectPtr); + m_registeredMethods.push_back(methodName); + } + + public: + AbstractPlugin() : PluginHost::JSONRPC() + { + LOGINFO(); + + registerMethod("getQuirks", &AbstractPlugin::getQuirks, this); + } + + virtual ~AbstractPlugin() + { + LOGINFO(); + + for (auto& i : m_registeredMethods) { Unregister(i); } + } + + //Build QueryInterface implementation, specifying all possible interfaces to be returned. + BEGIN_INTERFACE_MAP(MODULE_NAME) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + END_INTERFACE_MAP + + //IPlugin methods + virtual const string Initialize(PluginHost::IShell* service) + { + LOGINFO(); + // On success return empty, to indicate there is no error text. + return(string()); + } + + virtual void Deinitialize(PluginHost::IShell* service) + { + LOGINFO(); + } + + virtual string Information() const + { + // No additional info to report. + return(string()); + } + private: + std::vector m_registeredMethods; + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/helpers/StateObserverHelper.h b/helpers/StateObserverHelper.h new file mode 100644 index 0000000000..c47c4fd2af --- /dev/null +++ b/helpers/StateObserverHelper.h @@ -0,0 +1,59 @@ +/** +* 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. +**/ + +#ifndef __STATE_OBSERVER_HELPER_H__ +#define __STATE_OBSERVER_HELPER_H__ + +#define SYSTEM_EXIT_OK "com.comcast.exit-ok_key_sequence" +#define SYSTEM_CHANNEL_MAP "com.comcast.channel_map" +#define SYSTEM_CARD_DISCONNECTED "com.comcast.card.disconnected" +#define SYSTEM_TUNE_READY "com.comcast.tune_ready" +#define SYSTEM_MINI_DIAGNOSTICS "com.comcast.miniDiagnosticsEnabled" +#define SYSTEM_CMAC "com.comcast.cmac" +#define SYSTEM_MOTO_ENTITLEMENT "com.comcast.card.moto.entitlements" +#define SYSTEM_MOTO_HRV_RX "com.comcast.card.moto.hrv_rx" +#define SYSTEM_DAC_INIT_TIMESTAMP "com.comcast.card.moto.dac_init_timestamp" +#define SYSTEM_CARD_CISCO_STATUS "com.comcast.card.cisco.status" +#define SYSTEM_VIDEO_PRESENTING "com.comcast.video_presenting" +#define SYSTEM_HDMI_OUT "com.comcast.hdmi_out" +#define SYSTEM_HDCP_ENABLED "com.comcast.hdcp_enabled" +#define SYSTEM_HDMI_EDID_READ "com.comcast.hdmi_edid_read" +#define SYSTEM_FIRMWARE_DWNLD "com.comcast.firmware_download" +#define SYSTEM_TIME_SOURCE "com.comcast.time_source" +#define SYSTEM_TIME_ZONE "com.comcast.time_zone_available" +#define SYSTEM_CA_SYSTEM "com.comcast.ca_system" +#define SYSTEM_ESTB_IP "com.comcast.estb_ip" +#define SYSTEM_ECM_IP "com.comcast.ecm_ip" +#define SYSTEM_ECM_MAC "com.comcast.ecm_mac" +#define SYSTEM_LAN_IP "com.comcast.lan_ip" +#define SYSTEM_MOCA "com.comcast.moca" +#define SYSTEM_DOCSIS "com.comcast.docsis" +#define SYSTEM_DSG_BROADCAST_CHANNEL "com.comcast.dsg_broadcast_tunnel" +#define SYSTEM_DSG_CA_TUNNEL "com.comcast.dsg_ca_tunnel" +#define SYSTEM_CABLE_CARD "com.comcast.cable_card" +#define SYSTEM_CABLE_CARD_DWNLD "com.comcast.cable_card_download" +#define SYSTEM_CVR_SUBSYSTEM "com.comcast.cvr_subsystem" +#define SYSTEM_DOWNLOAD "com.comcast.download" +#define SYSTEM_VOD_AD "com.comcast.vod_ad" +#define SYSTEM_CARD_SERIAL_NO "com.comcast.card.serial.no" +#define SYSTEM_STB_SERIAL_NO "com.comcast.stb.serial.no" +#define SYSTEM_RF_CONNECTED "com.comcast.rf_connected" +#define SYSTEM_IP_MODE "com.comcast.ip_mode" + +#endif /* __STATE_OBSERVER_HELPER_H__ */ diff --git a/helpers/SystemServicesHelper.cpp b/helpers/SystemServicesHelper.cpp new file mode 100644 index 0000000000..33dd32182c --- /dev/null +++ b/helpers/SystemServicesHelper.cpp @@ -0,0 +1,608 @@ +/** +* 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 +#include +#include +#include +#include +#include + +#include "utils.h" +#include "SystemServicesHelper.h" + +/* Helper Functions */ +using namespace std; + +std::map ErrCodeMap = { + {SysSrv_OK, "Processed Successfully"}, + {SysSrv_MethodNotFound, "Method not found"}, + {SysSrv_UnSupportedFormat, "Unsupported or malformed format"}, + {SysSrv_FileNotPresent, "Expected file not found"}, + {SysSrv_FileAccessFailed, "File access failed"}, + {SysSrv_FileContentUnsupported, "Unsupported file content"}, + {SysSrv_Unexpected, "Unexpected error"}, + {SysSrv_SupportNotAvailable, "Support not available/enabled"}, + {SysSrv_LibcurlError, "LIbCurl service error"}, + {SysSrv_DynamicMemoryAllocationFailed, "Dynamic Memory Allocation Failed"} +}; + +std::string getErrorDescription(int errCode) +{ + std::string errMsg = "Unexpected Error"; + + auto it = ErrCodeMap.find(errCode); + if (ErrCodeMap.end() != it) { + errMsg = it->second; + } + return errMsg; +} + +bool fileExists(const char *pFileName) +{ + struct stat fileStat; + int32_t eRetval = E_NOK; + if (stat(pFileName, &fileStat) == 0) { + eRetval = E_OK; + } + if (S_ISREG(fileStat.st_mode)) { + eRetval = E_OK; + } + return ((eRetval == E_OK)? true: false); +} + +std::string dirnameOf(const std::string& fname) +{ + size_t pos = fname.find_last_of("/"); + return (std::string::npos == pos) ? "" : fname.substr(0, pos+1); +} + +/*** + * @brief : Used to check if directory exists + * @param1[in] : Complete file name with path + * @param2[in] : Destination string to be filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool dirExists(std::string fname) +{ + bool status = false; + struct stat sb; + if (stat((dirnameOf(fname)).c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) { + status = true; + } else { + // Do nothing. + } + return status; +} + +/*** + * @brief : Used to read file contents into a string + * @param1[in] : Complete file name with path + * @param2[in] : Destination string to be filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool readFromFile(const char* filename, string &content) +{ + bool retStatus = false; + + if (!fileExists(filename)) { + return retStatus; + } + + ifstream ifile(filename, ios::in); + if (ifile.is_open()) { + std::getline(ifile, content); + ifile.close(); + retStatus = true; + } else { + retStatus = false; + } + + return retStatus; +} + +namespace WPEFramework { + namespace Plugin { + /*** + * @brief : Used to construct response with module error status. + * @param1[in] : Error Code + * @param2[out]: "response" JSON Object which is returned by the API + with updated module error status. + */ + void populateResponseWithError(int errorCode, JsonObject& response) + { + if (errorCode) { + LOGWARN("Method %s failed; reason : %s\n", __FUNCTION__, + getErrorDescription(errorCode).c_str()); + response["SysSrv_Status"] = static_cast(errorCode); + response["errorMessage"] = getErrorDescription(errorCode); + } + } + + string caseInsensitive(string str7) + { + string status = "ERROR"; + regex r("model=([^\r\n]*)\n?", + std::regex_constants::ECMAScript | std::regex_constants::icase); + regex r1("model_number=([^\r\n]*)\n?", + std::regex_constants::ECMAScript | std::regex_constants::icase); + smatch match; + + if (regex_search(str7, match, r) == true) { + status = match.str(1); + } else if (regex_search(str7, match, r1) == true) { + status = match.str(1); + } else { + // Do nothing + ; + } + return status; + } + + string ltrim(const string& s) + { + const string WHITESPACE = " \n\r\t\f\v"; + size_t start = s.find_first_not_of(WHITESPACE); + return (start == string::npos) ? "" : s.substr(start); + } + + string rtrim(const string& s) + { + const string WHITESPACE = " \n\r\t\f\v"; + size_t end = s.find_last_not_of(WHITESPACE); + return (end == string::npos) ? "" : s.substr(0, end + 1); + } + + string trim(const string& s) + { + return rtrim(ltrim(s)); + } + + string getModel() + { + const char * pipeName = "PATH=${PATH}:/sbin:/usr/sbin /lib/rdk/getDeviceDetails.sh read"; + FILE* pipe = popen(pipeName, "r"); + LOGWARN("%s: opened pipe for command '%s', with result %s : %s\n", + __FUNCTION__ , pipeName, pipe ? "sucess" : "failure", strerror(errno)); + if (!pipe) { + LOGERR("%s: SERVICEMANAGER_FILE_ERROR: Can't open pipe for command '%s' for read mode: %s\n" + , __FUNCTION__, pipeName, strerror(errno)); + return "ERROR"; + } + + char buffer[128] = {'\0'}; + string result; + + while (!feof(pipe)) { + if (fgets(buffer, 128, pipe) != NULL) { + result += buffer; + } + } + pclose(pipe); + + string tri = caseInsensitive(result); + string ret = tri.c_str(); + ret = trim(ret); + LOGWARN("%s: ret=%s\n", __FUNCTION__, ret.c_str()); + return ret; + } + + string convertCase(string str) + { + std::string bufferString = str; + transform(bufferString.begin(), bufferString.end(), + bufferString.begin(), ::toupper); + LOGWARN("%s: after transform to upper :%s\n", __FUNCTION__, + bufferString.c_str()); + return bufferString; + } + + bool convert(string str3, string firm) + { + LOGWARN("INSIDE CONVERT\n"); + bool status = false; + string firmware = convertCase(firm); + string str = firmware.c_str(); + size_t found = str.find(str3); + if (found != string::npos) { + status = true; + } else { + status = false; + } + return status; + } + } //namespace Plugin +} //namespace WPEFramework + +/*** + * @brief : Used to construct JSON response from Vector. + * @param1[in] : Destination JSON response buffer + * @param2[in] : JSON "Key" + * @param3[in] : Source Vector. + * @return : ; TRUE if operation success; else FALSE. + */ +void setJSONResponseArray(JsonObject& response, const char* key, + const vector& items) +{ + JsonArray arr; + + for (auto& i : items) { + arr.Add(JsonValue(i)); + } + response[key] = arr; +} + +/*** + * @brief : Used to read file contents into a vector + * @param1[in] : Complete file name with path + * @param2[out] : Destination string object filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool getFileContent(std::string fileName, std::string& fileContent) +{ + std::ifstream inFile(fileName.c_str(), ios::in); + if (!inFile.is_open()) return false; + + std::stringstream buffer; + buffer << inFile.rdbuf(); + fileContent = buffer.str(); + inFile.close(); + + return true; +} + +/*** + * @brief : Used to read file contents into a vector + * @param1[in] : Complete file name with path + * @param2[in] : Destination vector buffer to be filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool getFileContent(std::string fileName, std::vector & vecOfStrs) +{ + bool retStatus = false; + std::ifstream inFile(fileName.c_str(), ios::in); + + if (!inFile.is_open()) + return retStatus; + + std::string line; + retStatus = true; + while (std::getline(inFile, line)) { + if (line.size() > 0) { + vecOfStrs.push_back(line); + } + } + inFile.close(); + return retStatus; +} + +/*** + * @brief : Used to read file contents into a C char array/buffer + * @param1[in] : Complete file name with path + * @param2[in] : Destination C char buffer to be filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool getFileContentToCharBuffer(std::string fileName, char* pBuffer) +{ + bool retStat = false; + long numbytes = 0; + std::string str; + std::ifstream inFile(fileName.c_str()); + + if (!inFile.is_open()) { + return retStat; + } + + numbytes = inFile.tellg(); + fprintf(stdout, "getFileContentToCharBuffer : numbytes = %ld\n", numbytes); + + std::strcpy(pBuffer, str.c_str()); + while (std::getline(inFile, str)) { + std::strcat(pBuffer, str.c_str()); + if (!inFile.eof()) { + std::strcat(pBuffer, "\n"); + } + } + retStat = true; + inFile.close(); + + return retStat; +} + +/*** + * @brief : Used to search for files in the given directory + * @param1[in] : Directory on which the search has to be performed + * @param2[in] : Filter for the search command + * @return : >; Vector of file names. + */ +std::vector searchAndGetFilesList(std::string path, std::string filter) +{ + int retStat = -1; + char buff[4096 + 1]; + std::string command,totalStr; + std::vector FileList; + + memset(buff, 0, 4096); + command = "find "+path+" -iname "+filter+" > /tmp/tempBuffer.dat"; + retStat = system(command.c_str()); + fprintf(stdout, "searchAndGetFilesList : retStat = %d\n", retStat); + getFileContent("/tmp/tempBuffer.dat", FileList); + + return FileList; +} + +/*** + * @brief : compare two C string case insensitively + * @param1[in] : c string 1 + * @param2[in] : c string 2 + * @return : ; 0 is strings are same, some number if strings are different. + */ +int strcicmp(char const *a, char const *b) +{ + int d = -1; + for (;; a++, b++) { + d = tolower((unsigned char)*a) - tolower((unsigned char)*b); + if (d != 0 || !*a) { + return d; + } + } + return -1; +} + +/** + * @brief : To find case insensitive substring in a given string. + * @param1[in] : Haystack buffer + * @param2[in] : Needle to be searched in Haystack + * @return : ; TRUE if match found; else FALSE. + */ +bool findCaseInsensitive(std::string data, std::string toSearch, size_t pos) +{ + /* Convert case to same type (lowercase). */ + std::transform(data.begin(), data.end(), data.begin(), ::tolower); + std::transform(toSearch.begin(), toSearch.end(), toSearch.begin(), ::tolower); + return ((data.find(toSearch, pos) != std::string::npos)? true : false); +} + +/*** + * @brief : To retrieve Xconf version of URL to override + * @return : string + */ +string getXconfOverrideUrl(void) +{ + string xconfUrl = ""; + vector lines; + + if (!fileExists(XCONF_OVERRIDE_FILE)) { + return xconfUrl; + } + + if (getFileContent(XCONF_OVERRIDE_FILE, lines)) { + if (lines.size()) { + for (int i = 0; i < (int)lines.size(); ++i) { + string line = lines.at(i); + if (!line.rfind("#", 0)) { + xconfUrl = line; + } + } + } + } + return xconfUrl; +} + +/*** + * @brief : To retrieve TimeZone + * @return : string; TimeZone + */ +string getTimeZoneDSTHelper(void) +{ + string timeZone = ""; + vector lines; + + if (!fileExists(TZ_FILE)) { + return timeZone; + } + + if (getFileContent(TZ_FILE, lines)) { + if (lines.size() > 0) { + timeZone = lines.front(); + } + } + + return timeZone; +} + +/*** + * @brief : To retrieve system time in requested format + * @param1[in] : requested format conversion info + * @return : string; + */ +string currentDateTimeUtc(const char *fmt) +{ + char timeStringBuffer[128] = {0}; + time_t rawTime = time(0); + struct tm *gmt = gmtime(&rawTime); + + if (fmt) { + strftime(timeStringBuffer, sizeof(timeStringBuffer), fmt, gmt); + } else { + strftime(timeStringBuffer, sizeof(timeStringBuffer), + "%a %B %e %I:%M:%S %Z %Y", gmt); + } + + std::string utcDateTime(timeStringBuffer); + return utcDateTime; +} + +/*** + * @brief : To construct url encoded from string passed + * @param1[in] : string; url to be encoded + * @return : string; encoded url + */ +std::string url_encode(std::string urlIn) +{ + std::string retval = ""; + CURL *c_url = NULL; + + if (!urlIn.length()) + return retval; + + c_url = curl_easy_init(); + if (c_url) { + char *encoded = curl_easy_escape(c_url, urlIn.c_str(), urlIn.length()); + retval = encoded; + curl_free(encoded); + curl_easy_cleanup(c_url); + } + return retval; +} + +/*** + * @brief : Execute shell script and get response + * @param1[in] : script to be executed with args + * @return : string; response. + */ +std::string cRunScript(const char *cmd) +{ + std::string totalStr = ""; + FILE *pipe = NULL; + char buff[1024] = {'\0'}; + + if ((pipe = popen(cmd, "r"))) { + memset(buff, 0, sizeof(buff)); + while (fgets(buff, sizeof(buff), pipe)) { + totalStr += buff; + memset(buff, 0, sizeof(buff)); + } + pclose(pipe); + } else { + /* popen failed. */ + } + return totalStr; +} + +/** + * @brief : curl write handler + */ +size_t writeCurlResponse(void *ptr, size_t size, size_t nmemb, std::string stream) +{ + size_t realsize = size * nmemb; + std::string temp(static_cast(ptr), realsize); + stream.append(temp); + return realsize; +} + +/*** + * @brief : extract mac address value to each key + * @param1[in] : the entire string from which makc addresses can be extracted + * @param2[in] : Key to each mac address + * @param2[out]: mac address value to each key + */ +void findMacInString(std::string totalStr, std::string macId, std::string& mac) +{ + const std::regex re("^([0-9A-F]{2}[:]){5}([0-9A-F]{2})$"); + std::size_t found = totalStr.find(macId); + mac = totalStr.substr(found + macId.length(), 17); + std::string defMac = "00:00:00:00:00:00"; + if (!std::regex_match(mac, re)) { + mac = defMac; + } +} + +/** + * @brief Used to create/remove XREConnection Retention status file. + * @return true if status file updation is success; else false. + */ +uint32_t enableXREConnectionRetentionHelper(bool enable) +{ + uint32_t result = SysSrv_Unexpected; + + if (enable) { + if (!fileExists(RECEIVER_STANDBY_PREFS)) { + FILE *fp = NULL; + if ((fp = fopen(RECEIVER_STANDBY_PREFS, "w"))) { + fclose(fp); + result = SysSrv_OK; + } else { + return SysSrv_FileAccessFailed; + } + } else { + /* Nothing To Do. */ + ; + } + } else { + if (fileExists(RECEIVER_STANDBY_PREFS)) { + remove(RECEIVER_STANDBY_PREFS); + result = SysSrv_OK ; + } else { + /* Nothing To Do. */ + ; + } + } + return result; +} + +std::string stringTodate(char *pBuffer) +{ + std::string str = ""; + struct tm result; + + if (strptime(pBuffer, "%Y-%m-%d %H:%M:%S", &result) == NULL) { + return str; + } else { + char tempBuff[128] = {'\0'}; + + strftime(tempBuff, sizeof(tempBuff), "%a %d %b %Y %H:%M:%S AP UTC", &result); + str = tempBuff; + } + return str; +} + +/** + * @brief Used to used to remove characters from string. + * @param1[in] : The string that has to striped of the given characters + * @param2[in] : char pointer too character arrya that contains all the + * characters to be removed + * @param2[out]: String striped of given characters + */ +void removeCharsFromString(string &str, const char *charsToRemove) +{ + for ( unsigned int i = 0; i < strlen(charsToRemove); ++i ) + { + str.erase( remove(str.begin(), str.end(), charsToRemove[i]), str.end() ); + } +} + +/** + * @brief : Curl API assistance function + */ +size_t curl_write(void *ptr, size_t size, size_t nmemb, void *stream) +{ + struct write_result *result = (struct write_result *)stream; + /* Will we overflow on this write? */ + if (result->pos + size * nmemb >= CURL_BUFFER_SIZE - 1) { + return -1; + } + /* Copy curl's stream buffer into our own buffer */ + memcpy(result->data + result->pos, ptr, size * nmemb); + /* Advance the position */ + result->pos += size * nmemb; + + return size * nmemb; +} + diff --git a/helpers/SystemServicesHelper.h b/helpers/SystemServicesHelper.h new file mode 100644 index 0000000000..638b2b753a --- /dev/null +++ b/helpers/SystemServicesHelper.h @@ -0,0 +1,289 @@ +/** +* 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. +**/ + +#ifndef __SYSTEM_SERVICE_HELPER_H__ +#define __SYSTEM_SERVICE_HELPER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +/* Status-keeper files */ +#define SYSTEM_SERVICE_REBOOT_INFO_FILE "/opt/persistent/reboot.info" +#define SYSTEM_SERVICE_PREVIOUS_REBOOT_INFO_FILE "/opt/persistent/previousreboot.info" +#define SYSTEM_SERVICE_HARD_POWER_INFO_FILE "/opt/persistent/hardpower.info" + +#define SYSTEM_UP_TIME_FILE "/proc/uptime" +#define MOCA_FILE "/opt/enablemoca" +#define VERSION_FILE_NAME "/version.txt" +#define SYSTEM_SERVICE_SETTINGS_FILE "/opt/system_service_settings.conf" +#define SYSTEM_SERVICE_TEMP_FILE "/tmp/system_service_temp.conf" +#define FWDNLDSTATUS_FILE_NAME "/opt/fwdnldstatus.txt" +#define REBOOT_INFO_LOG_FILE "/opt/logs/rebootInfo.log" +#define STANDBY_REASON_FILE "/opt/standbyReason.txt" +#define TMP_SERIAL_NUMBER_FILE "/tmp/.STB_SER_NO" +#define WAREHOUSE_MODE_FILE "/opt/warehouse_mode_active" +#define PREVIOUS_REBOOT_INFO2_ONE_CALL_FILE "/tmp/previousRebootInfoOneCall" +#define MILESTONES_LOG_FILE "/opt/logs/rdk_milestones.log" +#define RECEIVER_STANDBY_PREFS "/tmp/retainConnection" +#define TZ_REGEX "^[0-9a-zA-Z/-+_]*$" +#define PREVIOUS_KEYPRESS_INFO_FILE "/opt/persistent/previouskeypress.info" +#define XCONF_OVERRIDE_FILE "/opt/swupdate.conf" +#define URL_XCONF "http://xconf.xcal.tv/xconf/swu/stb" +#define TZ_FILE "/opt/persistent/timeZoneDST" + +#define MODE_TIMER_UPDATE_INTERVAL 1000 +#define CURL_BUFFER_SIZE (64 * 1024) /* 256kB */ + +#define IARM_BUS_PWRMGR_NAME "PWRMgr" /*!< Power manager IARM bus name */ +#define IARM_BUS_PWRMGR_API_SetDeepSleepTimeOut "SetDeepSleepTimeOut" /*!< Sets the timeout for deep sleep*/ + +#define MODE_NORMAL "NORMAL" +#define MODE_EAS "EAS" +#define MODE_WAREHOUSE "WAREHOUSE" + +#define CAT_DWNLDPROGRESSFILE_AND_GET_INFO "cat /opt/curl_progress | tr -s '\r' '\n' | tail -n 1 | sed 's/^ *//g' | tr -s ' ' | cut -d ' ' -f3" + +enum eRetval { E_NOK = -1, + E_OK }; + +enum SysSrv_ErrorCode { + SysSrv_OK = 0, + SysSrv_MethodNotFound, + SysSrv_UnSupportedFormat, + SysSrv_FileNotPresent, + SysSrv_FileAccessFailed, + SysSrv_FileContentUnsupported, + SysSrv_Unexpected, + SysSrv_SupportNotAvailable, + SysSrv_LibcurlError, + SysSrv_DynamicMemoryAllocationFailed +}; + +enum FirmwareUpdateState { + FirmwareUpdateStateUninitialized = 0, + FirmwareUpdateStateRequesting, + FirmwareUpdateStateDownloading, + FirmwareUpdateStateFailed, + FirmwareUpdateStateDownloadComplete, + FirmwareUpdateStateValidationComplete, + FirmwareUpdateStatePreparingReboot, +}; + +const string GZ_STATUS = "/opt/gzenabled"; + +/* Used as CURL Data buffer */ +struct write_result { + char *data; + int pos; +}; + +/* Forward Declaration */ +uint32_t enableXREConnectionRetentionHelper(bool); + +/* Helper Functions */ +using namespace std; + +/** + * @brief : To map the error code with matching error message. + * @param1[in] : error code of type SysSrv_ErrorCode. + * @return : string; error message. + */ +std::string getErrorDescription(int errCode); + +/** + * @brief : To check the existance of a file. + * @param1[in] : file name with absolute path. + * @return : ; true if file present, else false. + */ +bool fileExists(const char *pFileName); + +std::string dirnameOf(const std::string& fname); + +/*** + * @brief : Used to check if directory exists + * @param1[in] : Complete file name with path + * @param2[in] : Destination string to be filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool dirExists(std::string fname); + +/*** + * @brief : Used to read file contents into a string + * @param1[in] : Complete file name with path + * @param2[in] : Destination string to be filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool readFromFile(const char* filename, string &content); + +namespace WPEFramework { + namespace Plugin { + /*** + * @brief : Used to construct response with module error status. + * @param1[in] : Error Code + * @param2[out]: "response" JSON Object which is returned by the API + with updated module error status. + */ + void populateResponseWithError(int errorCode, JsonObject& response); + string caseInsensitive(string str7); + string ltrim(const string& s); + string rtrim(const string& s); + string trim(const string& s); + string getModel(); + string convertCase(string str); + bool convert(string str3,string firm); + } //namespace Plugin +} //namespace WPEFramework + +/*** + * @brief : Used to construct JSON response from Vector. + * @param1[in] : Destination JSON response buffer + * @param2[in] : JSON "Key" + * @param3[in] : Source Vector. + * @return : ; TRUE if operation success; else FALSE. + */ +void setJSONResponseArray(JsonObject& response, const char* key, + const vector& items); + +/*** + * @brief : Used to read file contents into a vector + * @param1[in] : Complete file name with path + * @param2[out] : Destination string object filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool getFileContent(std::string fileName, std::string& fileContent); + +/*** + * @brief : Used to read file contents into a vector + * @param1[in] : Complete file name with path + * @param2[in] : Destination vector buffer to be filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool getFileContent(std::string fileName, std::vector & vecOfStrs); + +/*** + * @brief : Used to read file contents into a C char array/buffer + * @param1[in] : Complete file name with path + * @param2[in] : Destination C char buffer to be filled with file contents + * @return : ; TRUE if operation success; else FALSE. + */ +bool getFileContentToCharBuffer(std::string fileName, char *pBuffer); + +/*** + * @brief : Used to search for files in the given directory + * @param1[in] : Directory on which the search has to be performed + * @param2[in] : Filter for the search command + * @return : >; Vector of file names. + */ +std::vector searchAndGetFilesList(std::string path, std::string filter); + +/*** + * @brief : compare two C string case insensitively + * @param1[in] : c string 1 + * @param2[in] : c string 2 + * @return : ; 0 is strings are same, some number if strings are different. + */ +int strcicmp(char const *a, char const *b); + +/** + * @brief : To find case insensitive substring in a given string. + * @param1[in] : Haystack buffer + * @param2[in] : Needle to be searched in Haystack + * @return : ; TRUE if match found; else FALSE. + */ +bool findCaseInsensitive(std::string data, std::string toSearch, size_t pos = 0); + +/*** + * @brief : To retrieve Xconf version of URL to override + * @return : string + */ +string getXconfOverrideUrl(void); + +/*** + * @brief : To retrieve TimeZone + * @return : string; TimeZone + */ +string getTimeZoneDSTHelper(void); + +/*** + * @brief : To retrieve system time in requested format + * @param1[in] : requested format conversion info + * @return : string; + */ +string currentDateTimeUtc(const char *fmt); + +/*** + * @brief : To construct url encoded from string passed + * @param1[in] : string; url to be encoded + * @return : string; encoded url + */ +std::string url_encode(std::string urlIn); + +/*** + * @brief : Execute shell script and get response + * @param1[in] : script to be executed with args + * @return : string; response. + */ +std::string cRunScript(const char *cmd); + +/*** + * @brief : To retrieve model details + * @return : string + */ +std::string getModel(void); + +/** + * @brief : CURL write handle call back. + * @reference : + */ +size_t writeCurlResponse(void *ptr, size_t size, size_t nmemb, std::string stream); + +/*** + * @brief : extract mac address value to each key + * @param1[in] : the entire string from which makc addresses can be extracted + * @param2[in] : Key to each mac address + * @param2[out]: mac address value to each key + */ +void findMacInString(std::string totalStr, std::string macId, std::string& mac); + +std::string stringTodate(char *pBuffer); + +/** + * @brief Used to used to remove characters from string. + * @param1[in] : The string that has to striped of the given characters + * @param2[in] : char pointer too character arrya that contains all the + * characters to be removed + * @param2[out]: String striped of given characters + */ +void removeCharsFromString(string &str, const char* charsToRemove); + +/** + * @brief Curl write request callback handler. + */ +size_t curl_write(void *ptr, size_t size, size_t nmemb, void *stream); + +#endif /* __SYSTEM_SERVICE_HELPER_H__ */ + diff --git a/helpers/TTSServicesCommon.h b/helpers/TTSServicesCommon.h new file mode 100644 index 0000000000..034164ac35 --- /dev/null +++ b/helpers/TTSServicesCommon.h @@ -0,0 +1,81 @@ +/** +* 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 "TTSCommon.h" +#include "utils.h" + +#define API_VERSION_NUMBER 1 +namespace WPEFramework { + namespace Plugin { + /* @brief : Used to log TTS Response from functions.. + * @param[in] : "X" - TTS_Error returned by the function + * + * @param[out] : "response" - The json object, which is return by the Api. + * Sets the value of response["TTS_Status"]. + */ + void logResponse(TTS::TTS_Error X, JsonObject& response) + { + response["TTS_Status"] = static_cast(X); + switch (X){ + case (TTS::TTS_OK): + LOGINFO("%s api operational success with TTS_OK code = %d", __func__, X); + break; + case (TTS::TTS_FAIL): + LOGINFO("%s api failed with TTS_FAIL error code = %d", __func__, X); + break; + case (TTS::TTS_NOT_ENABLED): + LOGINFO("%s api failed with TTS_NOT_ENABLED error code = %d", __func__, X); + break; + case (TTS::TTS_CREATE_SESSION_DUPLICATE): + LOGINFO("%s api failed with TTS_CREATE_SESSION_DUPLICATE error code = %d", __func__, X); + break; + case (TTS::TTS_EMPTY_APPID_INPUT): + LOGINFO("%s api failed with TTS_EMPTY_APPID_INPUT error code = %d", __func__, X); + break; + case (TTS::TTS_RESOURCE_BUSY): + LOGINFO("%s api failed with TTS_RESOURCE_BUSY error code = %d", __func__, X); + break; + case (TTS::TTS_NO_SESSION_FOUND): + LOGINFO("%s api failed with TTS_NO_SESSION_FOUND error code = %d", __func__, X); + break; + case (TTS::TTS_NESTED_CLAIM_REQUEST): + LOGINFO("%s api failed with TTS_NESTED_CLAIM_REQUEST error code = %d", __func__, X); + break; + case (TTS::TTS_INVALID_CONFIGURATION): + LOGINFO("%s api failed with TTS_INVALID_CONFIGURATION error code = %d", __func__, X); + break; + case (TTS::TTS_SESSION_NOT_ACTIVE): + LOGINFO("%s api failed with TTS_SESSION_NOT_ACTIVE error code = %d", __func__, X); + break; + case (TTS::TTS_APP_NOT_FOUND): + LOGINFO("%s api failed with TTS_APP_NOT_FOUND error code = %d", __func__, X); + break; + case (TTS::TTS_POLICY_VIOLATION): + LOGINFO("%s api failed with TTS_POLICY_VIOLATION error code = %d", __func__, X); + break; + default: + LOGINFO("%s api failed with unknow error code = %d", __func__, X); + response["TTS_Status"] = static_cast(TTS::TTS_FAIL); + } + } + }//namespace Plugin +}//namespace WPEFramework + + diff --git a/helpers/abstractservice.h b/helpers/abstractservice.h new file mode 100644 index 0000000000..cfefad83e4 --- /dev/null +++ b/helpers/abstractservice.h @@ -0,0 +1,62 @@ +/** +* 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 + + +class AbstractService +{ +public: + AbstractService() + { + m_lastError = StatusOk; + } + +public: + enum Status + { + StatusOk, + StatusFailure, + StatusInvalidArgument, + StatusInvalidState, + StatusMethodNotFound + }; + + void setLastError(Status statusCode, const std::string& statusMessage = std::string()) + { + m_lastError = statusCode; + m_lastErrorDescription = statusMessage; + } + + Status getLastError() + { + return m_lastError; + } + + std::string getLastErrorDescription() + { + return m_lastErrorDescription; + } + +private: + Status m_lastError; + std::string m_lastErrorDescription; +}; diff --git a/helpers/cSettings.cpp b/helpers/cSettings.cpp new file mode 100644 index 0000000000..33474a734b --- /dev/null +++ b/helpers/cSettings.cpp @@ -0,0 +1,194 @@ +/** +* 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 +#include +#include "cSettings.h" +#include "SystemServicesHelper.h" + +/*** + * @brief : Constructor. + * @return : nil. + */ +cSettings::cSettings(std::string file) +{ + filename = file; + readFromFile(); +} + +/*** + * @brief : Destructor. + * @return : nil. + */ +cSettings::~cSettings() +{ + ; +} + +/*** + * @brief : Initialise the jsonobject from a given conf file. + * @return : False if file couldn't be accessed, else True. + */ +bool cSettings::readFromFile() +{ + bool retStatus = false; + std::string content; + if (!fileExists(filename.c_str())) { + return retStatus; + } + fstream ifile(filename,ios::in); + if (ifile) { + while (!ifile.eof()) { + std::getline(ifile,content); + size_t pos = content.find_last_of("="); + if (std::string::npos != pos) { + data[(content.substr(0, pos).c_str())] = content.substr(pos+1,std::string::npos); + } + retStatus = true; + } + } else { + //Do nothing. + } + return retStatus; +} + +/*** + * @brief : Update new inserts into the json object onto file. + * @return : False if timer thread couldn't be started. + */ +bool cSettings::writeToFile() +{ + bool status = false; + + if (fileExists(filename.c_str())) { + ofstream ofile; + ofile.open(filename.c_str(),ios::out); + if (ofile) { + JsonObject::Iterator iterator = data.Variants(); + while (iterator.Next()) { + if (!data[iterator.Label()].String().empty()) { + ofile << iterator.Label() << "=" << data[iterator.Label()].String() << endl; + } else { + continue; + } + } + status = true; + ofile.close(); + } else { + status = false; + } + } + return status; +} + +/*** + * @brief : Get value of given key. + * @param1[in] : key + * @return : the value to the corresponding key + */ +JsonValue cSettings::getValue(std::string key) +{ + return data.Get(key.c_str()); +} + +/*** + * @brief : Set value of given key. + * @param1[in] : key + * @param2[in] : value + * @return : True if setvalue successfull, else False + */ +bool cSettings::setValue(std::string key,std::string value) +{ + data[key.c_str()] = value; + return writeToFile(); +} + +/*** + * @brief : Set value of given key. + * @param1[in] : key + * @param2[in] : value + * @return : True if setvalue successfull, else False + */ +bool cSettings::setValue(std::string key,int value) +{ + data[key.c_str()] = value; + return writeToFile(); +} + +/*** + * @brief : Set value of given key. + * @param1[in] : key + * @param2[in] : value + * @return : True if setvalue successfull, else False + */ +bool cSettings::setValue(std::string key,bool value) +{ + data[key.c_str()] = value; + return writeToFile(); +} + +/*** + * @brief : Check if a particular key is set. + * @param1[in] : key + * @return : True if key is already set, else False + */ +bool cSettings::contains(std::string key) +{ + bool resp = false; + if (data.HasLabel(key.c_str())) { + if (data[key.c_str()].String().empty()) { + resp = false; + } else { + resp = true; + } + } else { + resp = false; + } + return resp; +} + +/*** + * @brief : Remove a particular key-value pair. + * @param1[in] : key + * @return : True if key is key-value pair removed, else False + */ +bool cSettings::remove(std::string key) +{ + bool status = false; + /* + * Noticed that there is an error with the Remove function. + * work around is to assign a null value to the key and handle it + * accordingly. + */ + data[key.c_str()] = ""; + data.Remove(key.c_str()); + if (!contains(key)) { + if (writeToFile()) { + status = true; + } else { + status = false; + } + } + else { + status = false; + } + return status; +} + diff --git a/helpers/cSettings.h b/helpers/cSettings.h new file mode 100644 index 0000000000..99905f5819 --- /dev/null +++ b/helpers/cSettings.h @@ -0,0 +1,99 @@ +/** +* 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 +#include +#include + +using namespace std; + +class cSettings { + std::string filename; + JsonObject data; + public: + /*** + * @brief : Constructor. + * @return : nil. + */ + cSettings(std::string file); + + /*** + * @brief : Destructor. + * @return : nil. + */ + ~cSettings(); + + /*** + * @brief : Get value of given key. + * @param1[in] : key + * @return : the value to the corresponding key + */ + JsonValue getValue(std::string key); + + /*** + * @brief : Set value of given key. + * @param1[in] : key + * @param2[in] : value + * @return : True if setvalue successfull, else False + */ + bool setValue(std::string key,std::string value); + + /*** + * @brief : Set value of given key. + * @param1[in] : key + * @param2[in] : value + * @return : True if setvalue successfull, else False + */ + bool setValue(std::string key,int value); + + /*** + * @brief : Set value of given key. + * @param1[in] : key + * @param2[in] : value + * @return : True if setvalue successfull, else False + */ + bool setValue(std::string key,bool value); + + /*** + * @brief : Check if a particular key is set. + * @param1[in] : key + * @return : True if key is already set, else False + */ + bool contains(std::string key); + + /*** + * @brief : Remove a particular key-value pair. + * @param1[in] : key + * @return : True if key is key-value pair removed, else False + */ + bool remove(std::string key); + + /*** + * @brief : Update new inserts into the json object onto file. + * @return : False if timer thread couldn't be started. + */ + bool writeToFile(); + + /*** + * @brief : Initialise the jsonobject from a given conf file. + * @return : False if file couldn't be accessed, else True. + */ + bool readFromFile(); +}; + diff --git a/helpers/cTimer.cpp b/helpers/cTimer.cpp new file mode 100644 index 0000000000..30a99223f4 --- /dev/null +++ b/helpers/cTimer.cpp @@ -0,0 +1,83 @@ +/** +* 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 "cTimer.h" + +/*** + * @brief : Constructor. + * @return : nil. + */ +cTimer::cTimer() +{ + clear = false; + interval = 0; +} + +/*** + * @brief : Destructor. + * @return : nil. + */ +cTimer::~cTimer() +{ + this->clear = true; +} + +/*** + * @brief : start timer thread. + * @return : False if timer thread couldn't be started. + */ +bool cTimer::start() +{ + if (interval <= 0 && callBack_function == NULL) { + return false; + } + this->clear = false; + std::thread timerThread([=]() { + while (true) { + if (this->clear) return; + std::this_thread::sleep_for(std::chrono::milliseconds(interval)); + if (this->clear) return; + this->callBack_function(); + } + }); + timerThread.detach(); + return true; +} + +/*** + * @brief : stop timer thread. + * @return : nil + */ +void cTimer::stop() +{ + this->clear = true; +} + +/*** + * @brief : Set interval in which the given function should be invoked. + * @param1[in] : function which has to be invoked on timed intervals + * @param2[in] : timer interval val. + * @return : nil + */ +void cTimer::setInterval(void (*function)(), int val) +{ + this->callBack_function = function; + this->interval = val; +} + diff --git a/helpers/cTimer.h b/helpers/cTimer.h new file mode 100644 index 0000000000..7c73455ef4 --- /dev/null +++ b/helpers/cTimer.h @@ -0,0 +1,63 @@ +/** +* 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 +#include + +using namespace std; + +class cTimer{ + private: + bool clear; + int interval; + void (*callBack_function)(); + public: + /*** + * @brief : Constructor. + * @return : nil. + */ + cTimer(); + + /*** + * @brief : Destructor. + * @return : nil. + */ + ~cTimer(); + + /*** + * @brief : start timer thread. + * @return : False if timer thread couldn't be started. + */ + bool start(); + + /*** + * @brief : stop timer thread. + * @return : nil + */ + void stop(); + + /*** + * @brief : Set interval in which the given function should be invoked. + * @param1[in] : function which has to be invoked on timed intervals + * @param2[in] : timer interval val. + * @return : nil + */ + void setInterval(void (*function)(), int val); +}; + diff --git a/helpers/frontpanel.cpp b/helpers/frontpanel.cpp new file mode 100644 index 0000000000..5226d43fe6 --- /dev/null +++ b/helpers/frontpanel.cpp @@ -0,0 +1,773 @@ +/** +* 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. +**/ + +/* + * If not stated otherwise in this file or this component's Licenses.txt file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + + +/** +* @defgroup servicemanager +* @{ +* @defgroup src +* @{ +**/ + +//#define USE_DS //TODO - this was defined in servicemanager.pro for all STB builds. Not sure where to put it except here for now +//#define HAS_API_POWERSTATE + +#include "frontpanel.h" +#ifdef USE_DS + #include "frontPanelConfig.hpp" + #include "frontPanelTextDisplay.hpp" + #include "manager.hpp" +#endif + +#include +#include +#include +#include + +#include "utils.h" + +#if defined(HAS_API_POWERSTATE) + #include "powerstate.h" +#endif + +#define FP_SETTINGS_FILE_JSON "/opt/fp_service_preferences.json" + +/* +Requirement now + Ability to get/set Led brightness + Ability to power off/on a led + +*/ + +namespace WPEFramework +{ + + namespace Plugin + { + CFrontPanel* CFrontPanel::s_instance = NULL; + static int globalLedBrightness = 100; +#ifdef CLOCK_BRIGHTNESS_ENABLED + static int clockBrightness = 100; +#endif + static int initDone = 0; + static bool isMessageLedOn = false; + static bool isRecordLedOn = false; +#ifdef CLOCK_BRIGHTNESS_ENABLED + static bool isClockOn; +#endif + static bool powerStatus = false; //Check how this works on xi3 and rng's + static bool started = false; + static int m_numberOfBlinks = 0; + static int m_maxNumberOfBlinkRepeats = 0; + static int m_currentBlinkListIndex = 0; + static std::vector m_lights; + static device::List fpIndicators; + + static Core::TimerType blinkTimer(64 * 1024, "BlinkTimer"); + + namespace + { + + struct Mapping + { + const char *IArmBusName; + const char *SvcManagerName; + }; + + static struct Mapping name_mappings[] = { + { "Record" , "record_led"}, + { "Message" , "data_led"}, + { "Power" , "power_led"}, + // TODO: add your mappings here + // { , }, + { 0, 0} + }; + + std::string svc2iarm(const std::string &name) + { + const char *s = name.c_str(); + + int i = 0; + while (name_mappings[i].SvcManagerName) + { + if (strcmp(s, name_mappings[i].SvcManagerName) == 0) + return name_mappings[i].IArmBusName; + i++; + } + return name; + } + } + + CFrontPanel::CFrontPanel() + : m_blinkTimer(this) + , mFrontPanelHelper(new FrontPanelHelper()) + { + } + + CFrontPanel* CFrontPanel::instance() + { + if (!initDone) + { + if (!s_instance) + s_instance = new CFrontPanel; + +#ifdef USE_DS + try + { + LOGINFO("Front panel init"); + fpIndicators = device::FrontPanelConfig::getInstance().getIndicators(); + + for (uint i = 0; i < fpIndicators.size(); i++) + { + std::string IndicatorNameIarm = fpIndicators.at(i).getName(); + + auto it = std::find(m_lights.begin(), m_lights.end(), IndicatorNameIarm); + if (m_lights.end() == it) + { + m_lights.push_back(IndicatorNameIarm); + } + } + +#if defined(HAS_API_POWERSTATE) + std::string powerState = CPowerState::instance()->getPowerState(); + + LOGINFO("Front panel instance powerState: %s", powerState.c_str()); + //if (powerState.compare("ON", Qt::CaseInsensitive) == 0) + if (powerState == "ON") + powerStatus = true; +#endif +#ifdef CLOCK_BRIGHTNESS_ENABLED + clockBrightness = device::FrontPanelTextDisplay::getInstance("Text").getTextBrightness(); + device::FrontPanelTextDisplay::getInstance("Text").setTextBrightness(clockBrightness); +#endif + globalLedBrightness = device::FrontPanelIndicator::getInstance("Power").getBrightness(); + LOGINFO("Power light brightness, %d, power status %d", globalLedBrightness, powerStatus); + + for (uint i = 0; i < fpIndicators.size(); i++) + { + LOGWARN("Initializing light %s", fpIndicators.at(i).getName().c_str()); + if (powerStatus) + device::FrontPanelIndicator::getInstance(fpIndicators.at(i).getName()).setBrightness(globalLedBrightness); + + device::FrontPanelIndicator::getInstance(fpIndicators.at(i).getName()).setState(false); + } + + if (powerStatus) + device::FrontPanelIndicator::getInstance("Power").setState(true); + + } + catch (...) + { + LOGERR("Exception Caught during [CFrontPanel::instance]\r\n"); + } + initDone=1; +#endif + } + + return s_instance; + } + + bool CFrontPanel::start() + { + LOGWARN("Front panel start"); + try + { + if (powerStatus) + device::FrontPanelIndicator::getInstance("Power").setState(true); + + device::List fpIndicators = device::FrontPanelConfig::getInstance().getIndicators(); + for (uint i = 0; i < fpIndicators.size(); i++) + { + std::string IndicatorNameIarm = fpIndicators.at(i).getName(); + + auto it = std::find(m_lights.begin(), m_lights.end(), IndicatorNameIarm); + if (m_lights.end() == it) + m_lights.push_back(IndicatorNameIarm); + } + } + catch (...) + { + LOGERR("Frontpanel Exception Caught during [%s]\r\n", __func__); + } + if (!started) + { + m_numberOfBlinks = 0; + m_maxNumberOfBlinkRepeats = 0; + m_currentBlinkListIndex = 0; + started = true; + } + return true; + } + + bool CFrontPanel::stop() + { + stopBlinkTimer(); + return true; + } + + void CFrontPanel::setPowerStatus(bool bPowerStatus) + { + powerStatus = bPowerStatus; + } + + std::string CFrontPanel::getLastError() + { + return lastError_; + } + + void CFrontPanel::addEventObserver(FrontPanel* o) + { + + auto it = std::find(observers_.begin(), observers_.end(), o); + + if (observers_.end() == it) + observers_.push_back(o); + } + + void CFrontPanel::removeEventObserver(FrontPanel* o) + { + observers_.remove(o); + } + + bool CFrontPanel::setBrightness(int fp_brightness) + { + stopBlinkTimer(); + globalLedBrightness = fp_brightness; + + try + { + for (uint i = 0; i < fpIndicators.size(); i++) + { + device::FrontPanelIndicator::getInstance(fpIndicators.at(i).getName()).setBrightness(globalLedBrightness); + } + } + catch (...) + { + LOGERR("Frontpanel Exception Caught during [%s]\r\n",__func__); + } + + powerOnLed(FRONT_PANEL_INDICATOR_ALL); + return true; + } + + int CFrontPanel::getBrightness() + { + try + { + globalLedBrightness = device::FrontPanelIndicator::getInstance("Power").getBrightness(); + LOGWARN("Power light brightness, %d\n", globalLedBrightness); + } + catch (...) + { + LOGERR("Frontpanel Exception Caught during [%s]\r\n", __func__); + } + + return globalLedBrightness; + } + +#ifdef CLOCK_BRIGHTNESS_ENABLED + bool CFrontPanel::setClockBrightness(int brightness) + { + clockBrightness = brightness; + powerOnLed(FRONT_PANEL_INDICATOR_CLOCK); + return true; + } + + int CFrontPanel::getClockBrightness() + { + try + { + clockBrightness = device::FrontPanelTextDisplay::getInstance("Text").getTextBrightness(); + } + catch (...) + { + LOGERR("FrontPanel Exception Caught during [%s]\r\n", __func__); + } + + return clockBrightness; + } +#endif + + bool CFrontPanel::powerOnLed(frontPanelIndicator fp_indicator) + { + try + { + if (powerStatus) + { + switch (fp_indicator) + { + case FRONT_PANEL_INDICATOR_CLOCK: +#ifdef CLOCK_BRIGHTNESS_ENABLED + isClockOn = true; + device::FrontPanelTextDisplay::getInstance("Text").setTextBrightness(clockBrightness); +#endif + break; + case FRONT_PANEL_INDICATOR_MESSAGE: + isMessageLedOn = true; + device::FrontPanelIndicator::getInstance("Message").setState(true); + break; + case FRONT_PANEL_INDICATOR_RECORD: + isRecordLedOn = true; + device::FrontPanelIndicator::getInstance("Record").setState(true); + break; + case FRONT_PANEL_INDICATOR_REMOTE: + device::FrontPanelIndicator::getInstance("Remote").setState(true); + break; + case FRONT_PANEL_INDICATOR_RFBYPASS: + device::FrontPanelIndicator::getInstance("RfByPass").setState(true); + break; + case FRONT_PANEL_INDICATOR_ALL: + if (isMessageLedOn) + device::FrontPanelIndicator::getInstance("Message").setState(true); + if (isRecordLedOn) + device::FrontPanelIndicator::getInstance("Record").setState(true); + device::FrontPanelIndicator::getInstance("Power").setState(true); + break; + case FRONT_PANEL_INDICATOR_POWER: + LOGWARN("CFrontPanel::powerOnLed() - FRONT_PANEL_INDICATOR_POWER not handled"); + break; + } + } + } + catch (...) + { + LOGERR("FrontPanel Exception Caught during [%s]\r\n", __func__); + return false; + } + return true; + } + + bool CFrontPanel::powerOffLed(frontPanelIndicator fp_indicator) + { + try + { + switch (fp_indicator) + { + case FRONT_PANEL_INDICATOR_CLOCK: +#ifdef CLOCK_BRIGHTNESS_ENABLED + isClockOn = false; + device::FrontPanelTextDisplay::getInstance("Text").setTextBrightness(0); +#endif + break; + case FRONT_PANEL_INDICATOR_MESSAGE: + isMessageLedOn = false; + device::FrontPanelIndicator::getInstance("Message").setState(false); + break; + case FRONT_PANEL_INDICATOR_RECORD: + isRecordLedOn = false; + device::FrontPanelIndicator::getInstance("Record").setState(false); + break; + case FRONT_PANEL_INDICATOR_REMOTE: + device::FrontPanelIndicator::getInstance("Remote").setState(false); + break; + case FRONT_PANEL_INDICATOR_RFBYPASS: + device::FrontPanelIndicator::getInstance("RfByPass").setState(false); + break; + case FRONT_PANEL_INDICATOR_ALL: + for (uint i = 0; i < fpIndicators.size(); i++) + { + //LOGWARN("powerOffLed for Indicator %s", QString::fromStdString(fpIndicators.at(i).getName()).toUtf8().constData()); + LOGWARN("powerOffLed for Indicator %s", fpIndicators.at(i).getName().c_str()); + device::FrontPanelIndicator::getInstance(fpIndicators.at(i).getName()).setState(false); + } + break; + case FRONT_PANEL_INDICATOR_POWER: + LOGWARN("CFrontPanel::powerOffLed() - FRONT_PANEL_INDICATOR_POWER not handled"); + break; + } + } + catch (...) + { + LOGERR("FrontPanel Exception Caught during [%s]\r\n", __func__); + return false; + } + return true; + } + + + bool CFrontPanel::remoteLedOn() + { + try + { + auto it = std::find(m_lights.begin(), m_lights.end(), "Remote"); + + if (m_lights.end() != it) + { + device::FrontPanelIndicator::getInstance("Remote").setState(true); + } +#ifndef USE_LEDMGR + else + { + int powerBrightness = device::FrontPanelIndicator::getInstance("Power").getBrightness(); + if (powerBrightness > 0) + { + int adjustedBrightness = powerBrightness + 30; + if (adjustedBrightness > 100) + device::FrontPanelIndicator::getInstance("Power").setBrightness(100, false); + else + device::FrontPanelIndicator::getInstance("Power").setBrightness(adjustedBrightness, false); + } + } +#endif + } + catch (...) + { + LOGERR("FrontPanel Exception Caught in remoteLedOn"); + return false; + } + return true; + } + + + bool CFrontPanel::remoteLedOff() + { + try + { + auto it = std::find(m_lights.begin(), m_lights.end(), "Remote"); + + if (m_lights.end() != it) + { + device::FrontPanelIndicator::getInstance("Remote").setState(false); + } +#ifndef USE_LEDMGR + else + { + device::FrontPanelIndicator::getInstance("Power").setBrightness((device::FrontPanelIndicator::getInstance("Power").getBrightness()), false); + } +#endif + } + catch (...) + { + LOGERR("FrontPanel Exception Caught in remoteLedOff"); + return false; + } + return true; + } + + + + bool CFrontPanel::powerOffAllLed() + { + powerOffLed(FRONT_PANEL_INDICATOR_ALL); + return true; + } + + bool CFrontPanel::powerOnAllLed() + { + powerOnLed(FRONT_PANEL_INDICATOR_ALL); + return true; + } + + bool CFrontPanel::setLED(const JsonObject& parameters) + { + stopBlinkTimer(); + bool success = false; + string ledIndicator = svc2iarm(parameters["ledIndicator"].String()); + int brightness = -1; + + if (parameters.HasLabel("brightness")) + //brightness = properties["brightness"].Number(); + getNumberParameter("brightness", brightness); + + unsigned int color = 0; + if (parameters.HasLabel("color")) //color mode 2 + { + string colorString = parameters["color"].String(); + try + { + device::FrontPanelIndicator::getInstance(ledIndicator.c_str()).setColor(device::FrontPanelIndicator::Color::getInstance(colorString.c_str()), false); + success = true; + } + catch (...) + { + success = false; + } + } + else if (parameters.HasLabel("red")) //color mode 1 + { + unsigned int red,green,blue; + + getNumberParameter("red", red); + getNumberParameter("green", green); + getNumberParameter("blue", blue); + + color = (red << 16) | (green << 8) | blue; + try + { + device::FrontPanelIndicator::getInstance(ledIndicator.c_str()).setColor(color); + success = true; + } + catch (...) + { + success = false; + } + } + + LOGWARN("setLed ledIndicator: %s brightness: %d", parameters["ledIndicator"].String().c_str(), brightness); + try + { + if (brightness == -1) + brightness = device::FrontPanelIndicator::getInstance(ledIndicator.c_str()).getBrightness(); + + device::FrontPanelIndicator::getInstance(ledIndicator.c_str()).setBrightness(brightness, false); + success = true; + } + catch (...) + { + success = false; + } + return success; + } + + void CFrontPanel::setBlink(const JsonObject& blinkInfo) + { + stopBlinkTimer(); + m_blinkList.clear(); + string ledIndicator = svc2iarm(blinkInfo["ledIndicator"].String()); + int iterations; + getNumberParameterObject(blinkInfo, "iterations", iterations); + JsonArray patternList = blinkInfo["pattern"].Array(); + for (int i = 0; i < patternList.Length(); i++) + { + JsonObject frontPanelBlinkHash = patternList[i].Object(); + FrontPanelBlinkInfo frontPanelBlinkInfo; + frontPanelBlinkInfo.ledIndicator = ledIndicator; + int brightness = -1; + if (frontPanelBlinkHash.HasLabel("brightness")) + getNumberParameterObject(blinkInfo, "brightness", brightness); + + int duration; + getNumberParameterObject(blinkInfo, "duration", duration); + LOGWARN("setBlink ledIndicator: %s iterations: %d brightness: %d duration: %d", ledIndicator.c_str(), iterations, brightness, duration); + frontPanelBlinkInfo.brightness = brightness; + frontPanelBlinkInfo.durationInMs = duration; + frontPanelBlinkInfo.colorValue = 0; + if (frontPanelBlinkHash.HasLabel("color")) //color mode 2 + { + string color = frontPanelBlinkHash["color"].String(); + frontPanelBlinkInfo.colorName = color; + frontPanelBlinkInfo.colorMode = 2; + } + else if (frontPanelBlinkHash.HasLabel("red")) //color mode 1 + { + unsigned int red,green,blue; + + getNumberParameterObject(blinkInfo, "red", red); + getNumberParameterObject(blinkInfo, "green", green); + getNumberParameterObject(blinkInfo, "blue", blue); + + frontPanelBlinkInfo.colorValue = (red << 16) | (green << 8) | blue; + frontPanelBlinkInfo.colorMode = 1; + } + else + { + frontPanelBlinkInfo.colorMode = 0; + } + m_blinkList.push_back(frontPanelBlinkInfo); + } + startBlinkTimer(iterations); + } + + JsonObject CFrontPanel::getPreferences() + { + return m_preferencesHash; + } + + void CFrontPanel::setPreferences(const JsonObject& preferences) + { + m_preferencesHash = preferences; + + Core::File file; + file = FP_SETTINGS_FILE_JSON; + + file.Open(false); + if (!file.IsOpen()) + file.Create(); + + m_preferencesHash.ToFile(file); + + file.Close(); + } + + void CFrontPanel::loadPreferences() + { + m_preferencesHash.Clear(); + + Core::File file; + file = FP_SETTINGS_FILE_JSON; + + file.Open(); + m_preferencesHash.FromFile(file); + + file.Close(); + } + + void CFrontPanel::startBlinkTimer(int numberOfBlinkRepeats) + { + LOGWARN("startBlinkTimer numberOfBlinkRepeats: %d m_blinkList.length : %d", numberOfBlinkRepeats, m_blinkList.size()); + stopBlinkTimer(); + m_numberOfBlinks = 0; + m_maxNumberOfBlinkRepeats = numberOfBlinkRepeats; + m_currentBlinkListIndex = 0; + if (m_blinkList.size() > 0) + { + FrontPanelBlinkInfo blinkInfo = m_blinkList.at(0); + setBlinkLed(blinkInfo); + blinkTimer.Schedule(Core::Time::Now().Add(blinkInfo.durationInMs), m_blinkTimer); + } + } + + void CFrontPanel::stopBlinkTimer() + { + blinkTimer.Revoke(m_blinkTimer); + } + + void CFrontPanel::setBlinkLed(FrontPanelBlinkInfo blinkInfo) + { + std::string ledIndicator = blinkInfo.ledIndicator; + int brightness = blinkInfo.brightness; + try + { + if (brightness == -1) + brightness = device::FrontPanelIndicator::getInstance(ledIndicator.c_str()).getBrightness(); + + device::FrontPanelIndicator::getInstance(ledIndicator.c_str()).setBrightness(brightness, false); + if (blinkInfo.colorMode == 1) + { + device::FrontPanelIndicator::getInstance(ledIndicator.c_str()).setColor(blinkInfo.colorValue, false); + } + else if (blinkInfo.colorMode == 2) + { + device::FrontPanelIndicator::getInstance(ledIndicator.c_str()).setColor(device::FrontPanelIndicator::Color::getInstance(blinkInfo.colorName.c_str()), false); + } + } + catch (...) + { + LOGWARN("Exception caught in setBlinkLed"); + } + } + + void CFrontPanel::onBlinkTimer() + { + m_currentBlinkListIndex++; + bool blinkAgain = true; + if ((size_t)m_currentBlinkListIndex >= m_blinkList.size()) + { + blinkAgain = false; + m_currentBlinkListIndex = 0; + m_numberOfBlinks++; + if (m_maxNumberOfBlinkRepeats < 0 || m_numberOfBlinks <= m_maxNumberOfBlinkRepeats) + { + blinkAgain = true; + } + } + if (blinkAgain) + { + FrontPanelBlinkInfo blinkInfo = m_blinkList.at(m_currentBlinkListIndex); + setBlinkLed(blinkInfo); + blinkTimer.Schedule(Core::Time::Now().Add(blinkInfo.durationInMs), m_blinkTimer); + } + + //if not blink again then the led color should stay on the LAST element in the array as stated in the spec + } + + void CFrontPanel::set24HourClock(bool is24Hour) + { + try + { + int newFormat = is24Hour ? device::FrontPanelTextDisplay::kModeClock24Hr : device::FrontPanelTextDisplay::kModeClock12Hr; + device::FrontPanelTextDisplay &textDisplay = device::FrontPanelConfig::getInstance().getTextDisplay("Text"); + int currentFormat = textDisplay.getCurrentTimeFormat(); + LOGINFO("set24HourClock - Before setting %d - Time zone read from DS is %d", newFormat, currentFormat); + textDisplay.setTimeFormat(newFormat); + currentFormat = textDisplay.getCurrentTimeFormat(); + LOGINFO("set24HourClock - After setting %d - Time zone read from DS is %d", newFormat, currentFormat); + } + catch (...) + { + LOGERR("Exception Caught during set24HourClock"); + } + } + + bool CFrontPanel::is24HourClock() + { + bool is24Hour = false; + try + { + device::FrontPanelTextDisplay &textDisplay = device::FrontPanelConfig::getInstance().getTextDisplay("Text"); + int currentFormat = textDisplay.getCurrentTimeFormat(); + LOGINFO("is24HourClock - Time zone read from DS is %d", currentFormat); + is24Hour = currentFormat == device::FrontPanelTextDisplay::kModeClock24Hr; + } + catch (...) + { + LOGERR("Exception Caught during is24HourClock"); + } + return is24Hour; + } + + void FrontPanelHelper::setRemoteLedState(bool state) + { + LOGINFO("setRemoteLedState state: %d", state); +#ifdef USE_RFBYPASS_LED_KEYPRESS + if (state) + CFrontPanel::instance()->powerOnLed(FRONT_PANEL_INDICATOR_RFBYPASS); + else + CFrontPanel::instance()->powerOffLed(FRONT_PANEL_INDICATOR_RFBYPASS); +#else + if (state) + CFrontPanel::instance()->remoteLedOn(); + else + CFrontPanel::instance()->remoteLedOff(); +#endif + } + + uint64_t BlinkInfo::Timed(const uint64_t scheduledTime) + { + + uint64_t result = 0; + m_frontPanel->onBlinkTimer(); + return(result); + } + + } +} + +/** @} */ +/** @} */ diff --git a/helpers/frontpanel.h b/helpers/frontpanel.h new file mode 100644 index 0000000000..d7603ed5c0 --- /dev/null +++ b/helpers/frontpanel.h @@ -0,0 +1,180 @@ +/** +* 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. +**/ + +/* + * If not stated otherwise in this file or this component's Licenses.txt file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + + +/** +* @defgroup servicemanager +* @{ +* @defgroup include +* @{ +**/ + + +#ifndef FRONTPANEL_H +#define FRONTPANEL_H + +#include +#include +#include + +#include + +namespace WPEFramework +{ + + namespace Plugin + { + + class FrontPanel; + class FrontPanelHelper; + class CFrontPanel; + + class BlinkInfo + { + private: + BlinkInfo() = delete; + BlinkInfo& operator=(const BlinkInfo& RHS) = delete; + + public: + BlinkInfo(CFrontPanel* fp) + : m_frontPanel(fp) + { + } + BlinkInfo(const BlinkInfo& copy) + : m_frontPanel(copy.m_frontPanel) + { + } + ~BlinkInfo() {} + + inline bool operator==(const BlinkInfo& RHS) const + { + return(m_frontPanel == RHS.m_frontPanel); + } + + public: + uint64_t Timed(const uint64_t scheduledTime); + + private: + CFrontPanel* m_frontPanel; + }; + + + typedef struct _FrontPanelBlinkInfo + { + std::string ledIndicator; + std::string colorName; + unsigned int colorValue; + int brightness; + int durationInMs; + int colorMode; + } FrontPanelBlinkInfo; + + typedef enum _frontPanelIndicator + { + FRONT_PANEL_INDICATOR_CLOCK, + FRONT_PANEL_INDICATOR_MESSAGE, + FRONT_PANEL_INDICATOR_POWER, + FRONT_PANEL_INDICATOR_RECORD, + FRONT_PANEL_INDICATOR_REMOTE, + FRONT_PANEL_INDICATOR_RFBYPASS, + FRONT_PANEL_INDICATOR_ALL + } frontPanelIndicator; + + class CFrontPanel + { + public: + static CFrontPanel* instance(); + bool start(); + bool stop(); + std::string getLastError(); + void addEventObserver(FrontPanel* o); + void removeEventObserver(FrontPanel* o); + bool setBrightness(int fp_brighness); + int getBrightness(); +#ifdef CLOCK_BRIGHTNESS_ENABLED + bool setClockBrightness(int brightness); + int getClockBrightness(); +#endif + bool powerOffLed(frontPanelIndicator fp_indicator); + bool powerOnLed(frontPanelIndicator fp_indicator); + bool powerOffAllLed(); + bool powerOnAllLed(); + void setPowerStatus(bool powerStatus); + JsonObject getPreferences(); + void setPreferences(const JsonObject& preferences); + bool setLED(const JsonObject& blinkInfo); + void setBlink(const JsonObject& blinkInfo); + void loadPreferences(); + void stopBlinkTimer(); + bool remoteLedOn(); + bool remoteLedOff(); + void set24HourClock(bool is24Hour); + bool is24HourClock(); + + void onBlinkTimer(); + + private: + CFrontPanel(); + static CFrontPanel* s_instance; + void startBlinkTimer(int numberOfBlinkRepeats); + void setBlinkLed(FrontPanelBlinkInfo blinkInfo); + JsonObject m_preferencesHash; // is this needed + + BlinkInfo m_blinkTimer; + std::vector m_blinkList; + std::list observers_; + + std::string lastError_; + FrontPanelHelper* mFrontPanelHelper; + }; + + class FrontPanelHelper + { + void setRemoteLedState(bool state); + }; + + } // namespace Plugin +} // namespace WPEFramework + + +#endif + + +/** @} */ +/** @} */ diff --git a/helpers/powerstate.cpp b/helpers/powerstate.cpp new file mode 100644 index 0000000000..259615b987 --- /dev/null +++ b/helpers/powerstate.cpp @@ -0,0 +1,136 @@ +/** +* 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. +**/ + +/* +########################################################################## +# 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. +########################################################################## +*/ + +/** +* @defgroup servicemanager +* @{ +* @defgroup src +* @{ +**/ + + +#include "powerstate.h" +#include + +#ifdef __cplusplus +extern "C" { +#include "libIBus.h" +#include "pwrMgr.h" +} +#endif + +static CPowerState s_instance; + +CPowerState* CPowerState::instance() +{ + return &s_instance; +} + +bool CPowerState::start() +{ + return true; +} + +bool CPowerState::stop() +{ + return true; +} + +bool CPowerState::setPowerState(std::string powerState) +{ + IARM_Bus_PWRMgr_SetPowerState_Param_t param; + //if (powerState.compare("standby", Qt::CaseInsensitive) == 0) + if (powerState == "STANDBY") + { + param.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY; + } + //else if (powerState.compare("on", Qt::CaseInsensitive) == 0) + else if (powerState == "ON") + { + param.newState = IARM_BUS_PWRMGR_POWERSTATE_ON; + } + //else if (powerState.compare("DEEP_SLEEP", Qt::CaseInsensitive) == 0) + else if (powerState == "DEEP_SLEEP") + { + param.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; + } + //else if (powerState.compare("LIGHT_SLEEP", Qt::CaseInsensitive) == 0) + else if (powerState == "LIGHT_SLEEP") + { + /* Treat Light sleep as Standby */ + //param.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_LIGHT_SLEEP; + param.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY; + } + else + { + /* powerState can be one of "ON" or "STANDBY". */ + return false; + } + + IARM_Result_t res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_SetPowerState, + (void *)¶m, sizeof(param)); + + if(res == IARM_RESULT_SUCCESS) + return true; + else + return false; +} + +std::string CPowerState::getPowerState() +{ + std::string currentState = "UNKNOWN"; + IARM_Bus_PWRMgr_GetPowerState_Param_t param; + IARM_Result_t res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_GetPowerState, + (void *)¶m, sizeof(param)); + + if (res == IARM_RESULT_SUCCESS) { + if (param.curState == IARM_BUS_PWRMGR_POWERSTATE_ON) + currentState = "ON"; + else if ((param.curState == IARM_BUS_PWRMGR_POWERSTATE_STANDBY) || + (param.curState == IARM_BUS_PWRMGR_POWERSTATE_STANDBY_LIGHT_SLEEP) || + (param.curState == IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP) ) + currentState = "STANDBY"; + } + + return currentState; +} + +/** @} */ +/** @} */ diff --git a/helpers/powerstate.h b/helpers/powerstate.h new file mode 100644 index 0000000000..9e67c5c862 --- /dev/null +++ b/helpers/powerstate.h @@ -0,0 +1,71 @@ +/** +* 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. +**/ + +/* +########################################################################## +# 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. +########################################################################## +*/ + +/** +* @defgroup servicemanager +* @{ +* @defgroup include +* @{ +**/ + + +#ifndef POWERSTATE_H +#define POWERSTATE_H + +#include + +class SystemService; + +class CPowerState +{ +public: + static CPowerState* instance(); + + bool start(); + bool stop(); + bool setPowerState(std::string powerState); + std::string getPowerState(); +}; + +#endif + + +/** @} */ +/** @} */ diff --git a/helpers/thermonitor.cpp b/helpers/thermonitor.cpp new file mode 100644 index 0000000000..6392261db8 --- /dev/null +++ b/helpers/thermonitor.cpp @@ -0,0 +1,159 @@ +/** +* 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. +**/ + +/* +########################################################################## +# 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. +########################################################################## + + */ + +/** + * @defgroup servicemanager + * @{ + * @defgroup src + * @{ + **/ +#include +#include +#include + +#include "thermonitor.h" +#include "utils.h" +#include "libIARM.h" + +#include "libIBus.h" +#include "pwrMgr.h" + +/** +Requirement: a generic IARMBus thermal monitoring class +api to get coretemperature and notifications when thresholds are crossed. + */ + + +namespace WPEFramework { + namespace Plugin { + + static CThermalMonitor s_instance; + + CThermalMonitor * CThermalMonitor::instance() + { + LOGWARN("%s: Requested thermal manager instance.\n", __FUNCTION__); + return &s_instance; + } + + void CThermalMonitor::addEventObserver(WPEFramework::Plugin::SystemServices* service) + { + LOGINFO(); + } + + void CThermalMonitor::removeEventObserver(WPEFramework::Plugin::SystemServices* service) + { + LOGWARN("%s: Removing event observer for temperature threshold change.", __FUNCTION__); + } + + bool CThermalMonitor::getCoreTemperature(float& temperature) const + { + temperature = 0; + bool result = false; + IARM_Bus_PWRMgr_GetThermalState_Param_t param; + + IARM_Result_t res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, + IARM_BUS_PWRMGR_API_GetThermalState, (void *)¶m, sizeof(param)); + + if (res == IARM_RESULT_SUCCESS) { + temperature = param.curTemperature; + LOGWARN("Current core temperature is : %f ",temperature); + result = true; + } else { + LOGWARN("[%s] IARM Call failed.", __FUNCTION__); + } + + return result; + } + + bool CThermalMonitor::getCoreTempThresholds(float& high, float& critical) const + { + bool result = false; + IARM_Bus_PWRMgr_GetTempThresholds_Param_t param; + + IARM_Result_t res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, + IARM_BUS_PWRMGR_API_GetTemperatureThresholds, + (void *)¶m, + sizeof(param)); + + if (res == IARM_RESULT_SUCCESS) { + high = param.tempHigh; + critical = param.tempCritical; + LOGWARN("Got current temperature thresholds: high: %f, critical: %f", high, critical); + result = true; + } else { + high = critical = 0; + LOGWARN("[%s] IARM Call failed.", __FUNCTION__); + } + + return result; + } + + bool CThermalMonitor::setCoreTempThresholds(float high, float critical) const + { + bool result = false; + IARM_Bus_PWRMgr_SetTempThresholds_Param_t param; + param.tempHigh = high; + param.tempCritical = critical; + + IARM_Result_t res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, + IARM_BUS_PWRMGR_API_SetTemperatureThresholds, + (void *)¶m, + sizeof(param)); + + if (res == IARM_RESULT_SUCCESS) { + LOGWARN("Set new temperature thresholds: high: %f, critical: %f", high, critical); + result = true; + } else { + LOGWARN("[%s] IARM Call failed.", __FUNCTION__); + } + + return result; + } + + void CThermalMonitor::emitTemperatureThresholdChange(std::string thresholdType, bool isAboveThreshold, float temperature) + { + LOGWARN("emitTemperatureThresholdChange invoked."); + reportTemperatureThresholdChange(thresholdType, isAboveThreshold, temperature); + } + } +} +/** @} */ +/** @} */ diff --git a/helpers/thermonitor.h b/helpers/thermonitor.h new file mode 100644 index 0000000000..b7cc42aaea --- /dev/null +++ b/helpers/thermonitor.h @@ -0,0 +1,82 @@ +/** +* 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. +**/ + +/* +########################################################################## +# 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. +########################################################################## +*/ + +/** + * @defgroup servicemanager + * @{ + * @defgroup include + * @{ + **/ + + +#ifndef THERMALMONITOR_HPP +#define THERMALMONITOR_HPP + +#ifndef ENABLE_THERMAL_PROTECTION +#define ENABLE_THERMAL_PROTECTION +#endif + +#include "SystemServices.h" + +/** + * This class defines the functionalities for thermal monitoring. + **/ +namespace WPEFramework { + namespace Plugin { + + class CThermalMonitor { + public: + static CThermalMonitor* instance(); + + void addEventObserver(WPEFramework::Plugin::SystemServices* service); + void removeEventObserver(WPEFramework::Plugin::SystemServices* service); + + bool getCoreTemperature(float& temperature) const; + void emitTemperatureThresholdChange(std::string thresholdType, bool isAboveThreshold, float temperature); + bool getCoreTempThresholds(float& high, float& critical) const; + bool setCoreTempThresholds(float high, float critical) const; + void reportTemperatureThresholdChange(std::string thresholdType, bool isAboveThreshold, float temperature); + }; + } +} +#endif + +/** @} */ +/** @} */ diff --git a/helpers/tptimer.cpp b/helpers/tptimer.cpp new file mode 100644 index 0000000000..4dce7e1b8d --- /dev/null +++ b/helpers/tptimer.cpp @@ -0,0 +1,108 @@ +/** +* 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 "tptimer.h" + +namespace WPEFramework +{ + + namespace Plugin + { + WPEFramework::Core::TimerType& TpTimer::baseTimer = WPEFramework::Core::SingletonType < WPEFramework::Core::TimerType >::Instance(64 * 1024, "ThunderPluginBaseTimer"); + + TpTimer::TpTimer() : + m_timerJob(this) + , m_isActive(false) + , m_isSingleShot(false) + , m_intervalInMs(-1) + { + + } + + TpTimer::~TpTimer() + { + stop(); + } + + bool TpTimer::isActive() + { + return m_isActive; + } + + void TpTimer::stop() + { + baseTimer.Revoke(m_timerJob); + + m_isActive = false; + } + + void TpTimer::start() + { + baseTimer.Revoke(m_timerJob); + baseTimer.Schedule(Core::Time::Now().Add(m_intervalInMs), m_timerJob); + + m_isActive = true; + } + + void TpTimer::start(int msec) + { + setInterval(msec); + + start(); + } + + void TpTimer::setSingleShot(bool val) + { + m_isSingleShot = val; + } + + void TpTimer::setInterval(int msec) + { + m_intervalInMs = msec; + + //needs to restart timer? + } + + void TpTimer::connect(std::function< void() > callback) + { + onTimeoutCallback = callback; + } + + void TpTimer::Timed() + { + if(onTimeoutCallback != nullptr) + onTimeoutCallback(); + + //restart timer? + if(!m_isSingleShot) + start(); + else + m_isActive = false; + } + + uint64_t TpTimerJob::Timed(const uint64_t scheduledTime) + { + if(m_tptimer) + m_tptimer->Timed(); + + return 0; + } + } + +} diff --git a/helpers/tptimer.h b/helpers/tptimer.h new file mode 100644 index 0000000000..b406c36bb0 --- /dev/null +++ b/helpers/tptimer.h @@ -0,0 +1,90 @@ +/** +* 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. +**/ + +#ifndef TTIMER_H +#define TTIMER_H + +//#include +#include + +namespace WPEFramework +{ + + namespace Plugin + { + class TpTimer; + + class TpTimerJob + { + private: + TpTimerJob() = delete; + TpTimerJob& operator=(const TpTimerJob& RHS) = delete; + + public: + TpTimerJob(WPEFramework::Plugin::TpTimer* tpt) : m_tptimer(tpt) { } + TpTimerJob(const TpTimerJob& copy) : m_tptimer(copy.m_tptimer) { } + ~TpTimerJob() {} + + inline bool operator==(const TpTimerJob& RHS) const + { + return(m_tptimer == RHS.m_tptimer); + } + + public: + uint64_t Timed(const uint64_t scheduledTime); + + private: + WPEFramework::Plugin::TpTimer* m_tptimer; + }; + + class TpTimer + { + public: + TpTimer(); + ~TpTimer(); + + bool isActive(); + void stop(); + void start(); + void start(int msec); + void setSingleShot(bool val); + void setInterval(int msec); + + void connect(std::function< void() > callback); + + private: + + void Timed(); + + static WPEFramework::Core::TimerType& baseTimer; + TpTimerJob m_timerJob; + bool m_isActive; + bool m_isSingleShot; + int m_intervalInMs; + + std::function< void() > onTimeoutCallback; + + friend class TpTimerJob; + }; + } + +} + +#endif + diff --git a/helpers/upnpdiscoverymanager.cpp b/helpers/upnpdiscoverymanager.cpp new file mode 100644 index 0000000000..8c469e67b3 --- /dev/null +++ b/helpers/upnpdiscoverymanager.cpp @@ -0,0 +1,129 @@ +/** +* 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 "upnpdiscoverymanager.h" + +/* XUPNP Based Macros */ +#define _IARM_XUPNP_NAME "XUPnP" /*!< Method to Get the Xupnp Info */ +#define IARM_BUS_XUPNP_API_GetXUPNPDeviceInfo "GetXUPNPDeviceInfo" /*!< Method to Get the Xupnp Info */ + +using namespace std::placeholders; +static CUpnpDiscoveryManager s_instance; +std::function _postUPNPUpdateFuncPtr; + + +CUpnpDiscoveryManager* CUpnpDiscoveryManager::instance() +{ + return &s_instance; +} + +void CUpnpDiscoveryManager::start() +{ + if (!m_isActive) + { + m_isActive = true; + _postUPNPUpdateFuncPtr = std::bind(&CUpnpDiscoveryManager::saveUpdatedDiscoveredDevices, CUpnpDiscoveryManager::instance(), _1); + IARM_Bus_RegisterEventHandler(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_XUPNP_DATA_UPDATE, monitorUpnpEvents); + requestUpnpDeviceList(); + } +} + +void CUpnpDiscoveryManager::stop() +{ + if (m_isActive) + { + m_isActive = false; + IARM_Bus_UnRegisterEventHandler(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_XUPNP_DATA_UPDATE); + } +} + +void CUpnpDiscoveryManager::register_deviceupdate_cb (std::function< void () > callback) +{ + onDeviceUpdateCallback = callback; +// onDeviceUpdateCallback.push_back(std::make_shared> callback); +} + +JsonObject CUpnpDiscoveryManager::getDiscoveredDevices() +{ + if (m_isActive) + { + return m_upnpJSONResults; + } + return JsonObject(); +} + +void CUpnpDiscoveryManager::saveUpdatedDiscoveredDevices(JsonObject upnpJSONResults) +{ + if (m_isActive) + { + /* Update the member variable */ + m_upnpJSONResults = upnpJSONResults; + + /* Notify to listeners */ + if (onDeviceUpdateCallback != nullptr) + onDeviceUpdateCallback(); + } +} + +void CUpnpDiscoveryManager::requestUpnpDeviceList() +{ + IARM_Bus_SYSMgr_EventData_t eventData; + eventData.data.xupnpData.deviceInfoLength = 0; + IARM_Bus_BroadcastEvent(IARM_BUS_SYSMGR_NAME, (IARM_EventId_t)IARM_BUS_SYSMGR_EVENT_XUPNP_DATA_REQUEST,(void *)&eventData, sizeof(eventData)); +} + +void CUpnpDiscoveryManager::monitorUpnpEvents(const char *owner, IARM_EventId_t eventId, void *data, size_t len) +{ + if ((strcmp(owner, IARM_BUS_SYSMGR_NAME) == 0) && (eventId == IARM_BUS_SYSMGR_EVENT_XUPNP_DATA_UPDATE)) + { + IARM_Bus_SYSMgr_EventData_t *eventData = (IARM_Bus_SYSMgr_EventData_t*)data; + int messageLength = eventData->data.xupnpData.deviceInfoLength; + if (messageLength > 0) + { + char upnpResults[messageLength+1]; + IARM_Bus_SYSMGR_GetXUPNPDeviceInfo_Param_t *param = NULL; + IARM_Result_t ret = IARM_RESULT_IPCCORE_FAIL; + + /* Allocate enough to store the structure, the message and one more byte for the string termintor */ + IARM_Malloc(IARM_MEMTYPE_PROCESSLOCAL, sizeof(IARM_Bus_SYSMGR_GetXUPNPDeviceInfo_Param_t) + messageLength + 1, (void**)¶m); + param->bufLength = messageLength; + + ret = IARM_Bus_Call(_IARM_XUPNP_NAME,IARM_BUS_XUPNP_API_GetXUPNPDeviceInfo, (void *)param, sizeof(IARM_Bus_SYSMGR_GetXUPNPDeviceInfo_Param_t) + messageLength + 1); + + if(ret == IARM_RESULT_SUCCESS) + { + memcpy(upnpResults, ((char *)param + sizeof(IARM_Bus_SYSMGR_GetXUPNPDeviceInfo_Param_t)), param->bufLength); + upnpResults[param->bufLength] = '\0'; + IARM_Free(IARM_MEMTYPE_PROCESSLOCAL, param); + } + + /* Convert the message into JsonObject */ + if(ret == IARM_RESULT_SUCCESS) + { + JsonObject upnpJSONResults; + upnpJSONResults.FromString(std::string (upnpResults)); + + /* Notify the class */ + _postUPNPUpdateFuncPtr(upnpResults); + } + } + } +} + + diff --git a/helpers/upnpdiscoverymanager.h b/helpers/upnpdiscoverymanager.h new file mode 100644 index 0000000000..22c218bd64 --- /dev/null +++ b/helpers/upnpdiscoverymanager.h @@ -0,0 +1,65 @@ +/** +* 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. +**/ + +#ifndef UPNPDISCOVERYMANAGER_H +#define UPNPDISCOVERYMANAGER_H + +#include +#include +#include "utils.h" + +#ifdef __cplusplus +extern "C" { +#include "libIARM.h" +#include "libIBus.h" +#include "iarmUtil.h" +#include "libIARMCore.h" + +#include "sysMgr.h" +} +#endif + +//#include +#include + +class CUpnpDiscoveryManager +{ +public: + static CUpnpDiscoveryManager* instance(); + + void start(); + void stop(); + void register_deviceupdate_cb (std::function< void () > callback); + JsonObject getDiscoveredDevices(); +private: + std::function < void () > onDeviceUpdateCallback; + //std::vector>> onDeviceUpdateCallback; + + bool m_isActive; + JsonObject m_upnpJSONResults; + + void requestUpnpDeviceList(); + void saveUpdatedDiscoveredDevices(JsonObject upnpJSONResults); + static void monitorUpnpEvents(const char *owner, IARM_EventId_t eventId, void *data, size_t len); +}; + +#endif + + + diff --git a/helpers/utils.cpp b/helpers/utils.cpp new file mode 100644 index 0000000000..eed8517f84 --- /dev/null +++ b/helpers/utils.cpp @@ -0,0 +1,43 @@ +/** +* 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. +**/ + +/** + * Utility functions used in plugins. + * + */ + +#include "utils.h" + +// std +#include + +std::string Utils::formatIARMResult(IARM_Result_t result) +{ + switch (result) { + case IARM_RESULT_SUCCESS: return std::string("IARM_RESULT_SUCCESS [success]"); + case IARM_RESULT_INVALID_PARAM: return std::string("IARM_RESULT_INVALID_PARAM [invalid input parameter]"); + case IARM_RESULT_INVALID_STATE: return std::string("IARM_RESULT_INVALID_STATE [invalid state encountered]"); + case IARM_RESULT_IPCCORE_FAIL: return std::string("IARM_RESULT_IPCORE_FAIL [underlying IPC failure]"); + case IARM_RESULT_OOM: return std::string("IARM_RESULT_OOM [out of memory]"); + default: + std::ostringstream tmp; + tmp << result << " [unknown IARM_Result_t]"; + return tmp.str(); + } +} diff --git a/helpers/utils.h b/helpers/utils.h new file mode 100644 index 0000000000..e9dfb01ec0 --- /dev/null +++ b/helpers/utils.h @@ -0,0 +1,228 @@ +/** +* 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 "tracing/Logging.h" +#include + +// IARM +#include "rdk/iarmbus/libIARM.h" + +// std +#include + +#define UNUSED(expr)(void)(expr) +#define C_STR(x) (x).c_str() + +#define LOGINFO(fmt, ...) do { fprintf(stderr, "[%d] INFO [%s:%d] %s: " fmt "\n", (int)syscall(SYS_gettid), Core::FileNameOnly(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__); fflush(stderr); } while (0) +#define LOGWARN(fmt, ...) do { fprintf(stderr, "[%d] WARN [%s:%d] %s: " fmt "\n", (int)syscall(SYS_gettid), Core::FileNameOnly(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__); fflush(stderr); } while (0) +#define LOGERR(fmt, ...) do { fprintf(stderr, "[%d] ERROR [%s:%d] %s: " fmt "\n", (int)syscall(SYS_gettid), Core::FileNameOnly(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__); fflush(stderr); } while (0) + +#define LOGINFOMETHOD() { std::string json; parameters.ToString(json); LOGINFO( "params=%s", json.c_str() ); } +#define LOGTRACEMETHODFIN() do { std::string json; response.ToString(json); LOGINFO( "response=%s", json.c_str() ); } while (0) + +#define LOG_DEVICE_EXCEPTION0() LOGWARN("Exception caught: code=%d message=%s", err.getCode(), err.what()); +#define LOG_DEVICE_EXCEPTION1(param1) LOGWARN("Exception caught" #param1 "=%s code=%d message=%s", param1.c_str(), err.getCode(), err.what()); +#define LOG_DEVICE_EXCEPTION2(param1, param2) LOGWARN("Exception caught " #param1 "=%s " #param2 "=%s code=%d message=%s", param1.c_str(), param2.c_str(), err.getCode(), err.what()); + +//this set of macros are used in the method handlers to make the code more consistent and easier to read +#define vectorSet(v,s) \ + if (find(begin(v), end(v), s) == end(v)) \ + v.emplace_back(s); + +#define stringContains(s1,s2) \ + (search(s1.begin(), s1.end(), s2, s2+strlen(s2), \ + [](char c1, char c2){ \ + return toupper(c1) == toupper(c2); \ + }) != s1.end()) + +#define returnResponse(success) \ + response["success"] = success; \ + LOGTRACEMETHODFIN(); \ + return (Core::ERROR_NONE); + +#define returnIfWrongApiVersion(version)\ + if(m_apiVersionNumber < version)\ + {\ + LOGWARN("method %s not supported. version required=%u actual=%u", __FUNCTION__, version, m_apiVersionNumber);\ + returnResponse(false);\ + } + +#define returnIfParamNotFound(param, name)\ + if (!param.HasLabel(name))\ + {\ + LOGERR("No argument '%s'", name);\ + returnResponse(false);\ + } + +#define returnIfStringParamNotFound(param, name)\ + if (!param.HasLabel(name) || param[name].Content() != Core::JSON::Variant::type::STRING)\ + {\ + LOGERR("No argument '%s' or it has incorrect type", name);\ + returnResponse(false);\ + } + +#define returnIfBooleanParamNotFound(param, name)\ + if (!param.HasLabel(name) || param[name].Content() != Core::JSON::Variant::type::BOOLEAN)\ + {\ + LOGERR("No argument '%s' or it has incorrect type", name);\ + returnResponse(false);\ + } + +#define returnIfNumberParamNotFound(param, name)\ + if (!param.HasLabel(name) || param[name].Content() != Core::JSON::Variant::type::NUMBER)\ + {\ + LOGERR("No argument '%s' or it has incorrect type", name);\ + returnResponse(false);\ + } + +#define returnIfObjectParamNotFound(param, name)\ + if (!param.HasLabel(name) || param[name].Content() != Core::JSON::Variant::type::OBJECT)\ + {\ + LOGERR("No argument '%s' or it has incorrect type", name);\ + returnResponse(false);\ + } + +#define sendNotify(event,params)\ + std::string json;\ + params.ToString(json);\ + LOGINFO("Notify %s %s", event, json.c_str());\ + Notify(event,params); + +#define getNumberParameter(paramName, param) {\ + if (Core::JSON::Variant::type::NUMBER == parameters[paramName].Content()) \ + param = parameters[paramName].Number();\ + else\ + try { param = std::stoi( parameters[paramName].String()); }\ + catch (...) { param = 0; }\ +} + +#define getNumberParameterObject(parameters, paramName, param) {\ + if (Core::JSON::Variant::type::NUMBER == parameters[paramName].Content()) \ + param = parameters[paramName].Number();\ + else\ + try {param = std::stoi( parameters[paramName].String());}\ + catch (...) { param = 0; }\ +} + +#define getBoolParameter(paramName, param) {\ + if (Core::JSON::Variant::type::BOOLEAN == parameters[paramName].Content()) \ + param = parameters[paramName].Boolean();\ + else\ + param = parameters[paramName].String() == "true" || parameters[paramName].String() == "1";\ +} + +#define getStringParameter(paramName, param) {\ + if (Core::JSON::Variant::type::STRING == parameters[paramName].Content()) \ + param = parameters[paramName].String();\ +} + +#define IARM_CHECK(FUNC) \ + if ((res = FUNC) != IARM_RESULT_SUCCESS) { \ + LOGINFO("IARM %s: %s", #FUNC, \ + res == IARM_RESULT_INVALID_PARAM ? "invalid param" : ( \ + res == IARM_RESULT_INVALID_STATE ? "invalid state" : ( \ + res == IARM_RESULT_IPCCORE_FAIL ? "ipcore fail" : ( \ + res == IARM_RESULT_OOM ? "oom" : "unknown")))); \ + } else { \ + LOGINFO("IARM %s: success", #FUNC); \ + } + +namespace Utils +{ + namespace String + { + // locale-wise comparison + template + struct loc_equal { + explicit loc_equal( const std::locale& loc ) : loc_(loc) {} + bool operator()(charT ch1, charT ch2) { + return std::toupper(ch1, loc_) == std::toupper(ch2, loc_); + } + private: + const std::locale& loc_; + }; + + // Case-insensitive substring lookup. + // Returns the substring position or -1 + // Example: int pos = find_substr_ci(string, substring, std::locale()); + template + int find_substr_ci( const T& string, const T& substring, const std::locale& loc = std::locale() ) + { + typename T::const_iterator it = std::search( string.begin(), string.end(), + substring.begin(), substring.end(), loc_equal(loc) ); + if ( it != string.end() ) return it - string.begin(); + else return -1; // not found + } + + // Case-insensitive substring inclusion lookup. + // Example: if (Utils::String::contains(result, processName)) {..} + template + bool contains( const T& string, const T& substring, const std::locale& loc = std::locale() ) + { + int pos = find_substr_ci(string, substring, loc); + return pos != -1; + } + + // Case-insensitive substring inclusion lookup. + // Example: if(Utils::String::contains(tmp, "grep -i")) {..} + template + bool contains( const T& string, const char* c_substring, const std::locale& loc = std::locale() ) + { + std::string substring(c_substring); + int pos = find_substr_ci(string, substring, loc); + return pos != -1; + } + + // Case-insensitive string comparison + // returns true if the strings are equal, otherwise returns false + // Example: if (Utils::String::equal(line, provisionType)) {..} + template + bool equal(const T& string, const T& string2, const std::locale& loc = std::locale() ) + { + int pos = find_substr_ci(string, string2, loc); + bool res = (pos == 0) && (string.length() == string2.length()); + return res; + } + + // Case-insensitive string comparison + // returns true if the strings are equal, otherwise returns false + // Example: if(Utils::String::equal(line,"CRYPTANIUM")) {..} + template + bool equal(const T& string, const char* c_string2, const std::locale& loc = std::locale() ) + { + std::string string2(c_string2); + int pos = find_substr_ci(string, string2, loc); + bool res = (pos == 0) && (string.length() == string2.length()); + return res; + } + } + + /** + * @brief Format an IARM_Result_t value for error reporting. + * + * @param result The result of an IARM bus call. + * @return A corresponding string. + * + */ + std::string formatIARMResult(IARM_Result_t result); +} diff --git a/intel.cmake b/intel.cmake new file mode 100644 index 0000000000..c07f4871db --- /dev/null +++ b/intel.cmake @@ -0,0 +1,118 @@ +# Canmore specifics +add_definitions (-DPLATFORM_CANMORE) +#Uncomment this for IP Only + +add_definitions (-DUSE_DS) +option(USE_DS "USE_DS" ON) + +add_definitions (-DUSE_IARM_BUS) +option(USE_IARM_BUS "USE_IARM_BUS" ON) + +add_definitions (-DHAS_FRONT_PANEL) +option(HAS_FRONT_PANEL "HAS_FRONT_PANEL" ON) + +add_definitions (-DCLOCK_BRIGHTNESS_ENABLED) +option(CLOCK_BRIGHTNESS_ENABLED "CLOCK_BRIGHTNESS_ENABLED" ON) + +add_definitions (-DUSE_UPNP_DISCOVERY) +add_definitions (-DUSE_LSB) + + +if (BUILD_ENABLE_RFREMOTE_API) + message("Building with rf remote API") + add_definitions (-DBUILD_ENABLE_RFREMOTE_API) + add_definitions (-DHAS_API_RFREMOTE) +endif() + +if (BUILD_ENABLE_HDCP) + message("Building xre with hdcp profile") + add_definitions (-DBUILD_ENABLE_HDCP) + option(BUILD_ENABLE_HDCP "BUILD_ENABLE_HDCP" ON) + add_definitions (-DENABLE_HDCP_PROFILE) +endif() + +if (BUILD_X1) + message("Building for X1") + add_definitions (-DBUILD_X1) + add_definitions (-DSUPPORT_HOME_NETWORKING_V3) + + if (IP_VIDEO_ONLY) + message("Using IP video only") +# DEFINES -= PLATFORM_CANMORE + add_definitions (-DUSE_IP_VIDEO_ONLY) + add_definitions (-DUSE_TSB_SETTINGS) + add_definitions (-DENABLE_TSB_SETTING) + endif() + + if (BUILD_DELIA) + message("Building for Delia") + add_definitions (-DUSE_DS) + add_definitions (-DUSE_IARMBUS) + add_definitions (-DPLATFORM_INTEL_IP_ONLY) + add_definitions (-DDELIA_MODE) + add_definitions (-DUSE_DISPLAY_SETTINGS) + add_definitions (-DENABLE_EXIT_D_D_2_WEB_DIAGNOSTICS) + + if (BUILD_ENABLE_HDCP) + message("Building x1 xre with hdcp profile") + add_definitions (-DENABLE_HDCP_PROFILE) + endif() + if (BUILD_DBUS) + message("Building for DBUS") + add_definitions (-DIARM_USE_DBUS) + endif() + endif() + + add_definitions (-DMSO_PAIRING) + add_definitions (-DMSO_PAIRING_ENABLE_LOS) + add_definitions (-DRF4CE_API) + add_definitions (-DUSE_IARM) + add_definitions (-DHAS_SNAG_AUDIO) + add_definitions (-DHAS_STATE_OBSERVER) + add_definitions (-DENABLE_SERVICEPROXY_SYSTEM3_SYSTEM4) + add_definitions (-DENABLE_MSOPAIRING_4) + add_definitions (-DENABLE_MSOPAIRING_5) + add_definitions (-DENABLE_MSOPAIRING_6) + add_definitions (-DUSE_DISPLAY_SETTINGS) + add_definitions (-DUSE_THUNDER_DISPLAY_SETTINGS) + add_definitions (-DUSE_DEVICE_SETTINGS_SERVICE) + add_definitions (-DUSE_RFBYPASS_LED_KEYPRESS) + add_definitions (-DENABLE_VREX_SERVICE) + add_definitions (-DENABLE_REMOTE_ACTION_MAPPING_SERVICE) + add_definitions (-DENABLE_CONTROL_SERVICE) + add_definitions (-DUSE_UNIFIED_RF4CE_MGR_API_4) + add_definitions (-DENABLE_FRONT_PANEL_API_V4) +endif() + +if(PLATFORM_INTEL_IP_ONLY) + message("Building for IP Only...") + add_definitions (-DPLATFORM_INTEL_IP_ONLY) +else() + message("Building for Canmore...") + add_definitions (-DHAS_GMA) + add_definitions (-DHAS_QAM) +endif() + +#add_definitions (-DUSE_SOUND_PLAYER) + +#add_definitions (-DUSE_AVINPUT) +add_definitions (-DCROSS_COMPILED_FOR_DEVICE) +add_definitions (-DENABLE_GET_SET_APIVERSION) + +#!contains(DEFINES, USE_DS) { +# HEADERS += ../../platform/broadcom/include/rdk_fpd.h +#} + +add_definitions (-DHAS_API_RFREMOTE) +add_definitions (-DHAS_API_SYSTEM) +add_definitions (-DHAS_API_POWERSTATE) +add_definitions (-DHAS_API_AVINPUT) +add_definitions (-DHAS_API_HOME_NETWORKING) +add_definitions (-DHAS_API_APPLICATION) +add_definitions (-DHAS_API_PING) +add_definitions (-DHAS_API_HDCP_COMPLIANCE) + +add_definitions (-DHAS_API_DEVICEPROVISIONING) +#add_definitions (-DHAS_API_QAM_METADATA) +add_definitions (-DHAS_API_DOWNLOADS) + diff --git a/services.cmake b/services.cmake new file mode 100644 index 0000000000..876d997c4d --- /dev/null +++ b/services.cmake @@ -0,0 +1,223 @@ +# If not stated otherwise in this file or this component's Licenses.txt file the +# following copyright and licenses apply: +# +# Copyright 2016 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# features +# +#add_definitions (-DENABLE_MEMORYINFO_SERVICE) + +add_definitions (-DWAREHOUSE_API) +option(WAREHOUSE_API "WAREHOUSE_API" ON) + +#add_definitions (-DBROWSER_SETTINGS) +#add_definitions (-DSCREEN_CAPTURE) + +add_definitions (-DSLEEP_TIMER) +option(SLEEP_TIMER "SLEEP_TIMER" ON) + +add_definitions (-DHAS_TIMER) +option(HAS_TIMER "HAS_TIMER" ON) + +#add_definitions (-DENABLE_COOKIEJAR) +#add_definitions (-DENABLE_HEADERS2) +#add_definitions (-DENABLE_FRAME_RATE_SERVICE) +#add_definitions (-DUSE_USER_PREFERENCES_SERVICE) + +add_definitions (-DHAS_API_HDMI_INPUT) +option(HAS_API_HDMI_INPUT "HAS_API_HDMI_INPUT" ON) + +#add_definitions (-DHAS_RECEIVER_DIAGNOSTICS_SERVICE) +#add_definitions (-DHAS_LOGGING_PREFERENCES) +#add_definitions (-DHAS_API_APPLICATION) +#add_definitions (-DHAS_API_PING) +#add_definitions (-DHAS_API_HDCP_COMPLIANCE) +#add_definitions (-DHAS_API_DATA_CAPTURE) + +add_definitions (-DHAS_API_COPILOT) +option(HAS_API_COPILOT "HAS_API_COPILOT" ON) + +add_definitions (-DHAS_API_FRAME_RATE) +option(HAS_API_FRAME_RATE "HAS_API_FRAME_RATE" ON) + +add_definitions (-DHAS_API_STORAGE_MANAGER) +option(HAS_API_STORAGE_MANAGER "HAS_API_STORAGE_MANAGER" ON) + +#add_definitions (-DHAS_API_INTRUSION_DETECTION) +#add_definitions (-DHAS_API_LINEAR_SEGMENTED_ADVERTISING) +#add_definitions (-DHAS_API_VIDEO_APPLICATION_EVENTS) +#add_definitions (-DENABLE_GET_PROGRESS_BYPASS) +#add_definitions (-DENABLE_RDK_BROWSER2) + +add_definitions (-DHAS_API_DEVICEDIAGNOSTICS) +option(HAS_API_DEVICEDIAGNOSTICS "HAS_API_DEVICEDIAGNOSTICS" ON) + +#add_definitions (-DHAS_API_DEVICEPROVISIONING) + +add_definitions (-DENABLE_HDCP_PROFILE) +option(ENABLE_HDCP_PROFILE "ENABLE_HDCP_PROFILE" ON) + +add_definitions (-DHAS_ACTIVITY_MONITOR) +option(HAS_ACTIVITY_MONITOR "HAS_ACTIVITY_MONITOR" ON) + +#add_definitions (-DCLIENT_VERSION_STRING)=\\\"$(VERSION_FULL_VALUE)\\\" +#add_definitions (-DSTB_VERSION_STRING)=\\\"$(FULL_VERSION_NAME_VALUE)\\\" +#add_definitions (-DSTB_TIMESTAMP_STRING)=\\\"$(STB_TIMESTAMP_VALUE)\\\" + +#add_definitions (-DHAS_API_TTSSETTINGSSERVICE) +#add_definitions (-DHAS_API_TTSSESSIONSERVICE) +#add_definitions (-DHAS_API_TTSRESOURCESERVICE) +#add_definitions (-DHAS_API_CONTINUE_WATCHING) + +#add_definitions (-DHAS_API_PROXIES) +#add_definitions (-DHAS_API_XCASTSERVICE) +#add_definitions (-DENABLE_SYSTEM_5) +#add_definitions (-DENABLE_SYSTEM_6) +#add_definitions (-DENABLE_SYSTEM_7) +#add_definitions (-DENABLE_SYSTEM_8) +#add_definitions (-DENABLE_SYSTEM_9) +#add_definitions (-DENABLE_SYSTEM_10) +#add_definitions (-DENABLE_SYSTEM_11) +#add_definitions (-DENABLE_SYSTEM_12) +#add_definitions (-DENABLE_SYSTEM_13) +#add_definitions (-DENABLE_SYSTEM_14) +#add_definitions (-DENABLE_SYSTEM_15) +#add_definitions (-DENABLE_SYSTEM_16) +#add_definitions (-DENABLE_SYSTEM_17) + + +add_definitions (-DHAS_STATE_OBSERVER) +option(HAS_STATE_OBSERVER "HAS_STATE_OBSERVER" ON) + +add_definitions (-DDISABLE_WEBKIT_WIDGETS) + +add_definitions (-DENABLE_DEVICE_PROVISIONING) +option(DEVICE_PROVISIONING "DEVICE_PROVISIONING" ON) + +if (ENABLE_BLUETOOTH_CONTROL) + add_definitions (-DENABLE_BLUETOOTH_CONTROL) + add_definitions (-DHAS_API_BLUETOOTH) +endif() + +if(BUILD_ENABLE_TSB) + message("Building with TSB") + add_definitions (-DBUILD_ENABLE_TSB) + add_definitions (-DUSE_TSB_SETTINGS) + add_definitions (-DENABLE_TSB_SETTING) +endif() + +if (BUILD_ENABLE_CLOCK) + message("Building with clock support") + add_definitions (-DBUILD_ENABLE_CLOCK) + add_definitions (-DCLOCK_BRIGHTNESS_ENABLED) +endif() + +if (BUILD_ENABLE_MSO_PAIRING) + message("Building with MSO pairing") + add_definitions (-DBUILD_ENABLE_MSO_PAIRING) + add_definitions (-DMSO_PAIRING) +endif() + +if (BUILD_ENABLE_MSO_PAIRING_EXTENSIONS) + message("Building with MSO pairing extensions") + add_definitions (-DBUILD_ENABLE_MSO_PAIRING_EXTENSIONS) + add_definitions (-DMSO_PAIRING_ENABLE_LOS) + add_definitions (-DENABLE_MSOPAIRING_4) + add_definitions (-DENABLE_MSOPAIRING_5) +endif() + +if (BUILD_ENABLE_LATEST_FRONT_PANEL_API) + message("Building with the latest front panel api") + add_definitions (-DBUILD_ENABLE_LATEST_FRONT_PANEL_API) + add_definitions (-DENABLE_FRONT_PANEL_API_V4) +endif() + +if (BUILD_ENABLE_EXTENDED_ALL_SEGMENTS_TEXT_PATTERN) + add_definitions (-DUSE_EXTENDED_ALL_SEGMENTS_TEXT_PATTERN) +endif() + +if (BUILD_ENABLE_AV_INPUT) + message("Building with AV input support") + add_definitions (-DBUILD_ENABLE_AV_INPUT) + add_definitions (-DHAS_API_AVINPUT) + add_definitions (-DUSE_AVINPUT) +endif() + +if (BUILD_ENABLE_TR69) + message("Building with TR-69") + add_definitions (-DBUILD_ENABLE_TR69) + add_definitions (-DUSE_TR_69) +endif() + +if(BUILD_ENABLE_STORAGE_MANAGER) + message("Building with storage manager") + add_definitions (-DBUILD_ENABLE_STORAGE_MANAGER) + add_definitions (-DUSE_STORAGE_MANAGER_API) +endif() + +if(BUILD_REFACTORED_STORAGEMANAGER) + message("Building refactored storage manager - v2") + add_definitions (-DBUILD_REFACTORED_STORAGEMANAGER) + add_definitions (-DUSE_RDK_STORAGE_MANAGER_V2) +# LIBS += -L"${FSROOT}/usr/lib" -lrdkstmgr +endif() + +if(BUILD_ENABLE_VREX) + message("Building with VREX") + add_definitions (-DBUILD_ENABLE_VREX) + add_definitions (-DENABLE_VREX_SERVICE) +endif() + +if(BUILD_ENABLE_REMOTEACTIONMAPPING) + message("Building with RemoteActionMappingService") + add_definitions (-DBUILD_ENABLE_REMOTEACTIONMAPPING) + add_definitions (-DENABLE_REMOTE_ACTION_MAPPING_SERVICE) +endif() + +if(BUILD_ENABLE_CONTROL) + message("Building with ControlService") + add_definitions (-DBUILD_ENABLE_CONTROL) + add_definitions (-DENABLE_CONTROL_SERVICE) +endif() + +if(BUILD_DISABLE_WEBKIT_WIDGETS) + message("Building with webkit widgets disabled") + add_definitions (-DBUILD_DISABLE_WEBKIT_WIDGETS) + add_definitions (-DDISABLE_WEBKIT_WIDGETS) +endif() + +if(BUILD_ENABLE_WIFI_MANAGER) + message("Building with wifi manager") + add_definitions (-DBUILD_ENABLE_WIFI_MANAGER) + add_definitions (-DHAS_WIFI_MANAGER) +endif() + +if(BUILD_ENABLE_CEF) + message("Building with CEF") + add_definitions (-DBUILD_ENABLE_CEF) + add_definitions (-DUSE_CEF) +endif() + +if(BUILD_BROADCOM) + include(broadcom.cmake) +elseif(BUILD_INTEL) + include(intel.cmake) +endif() + + + + +