1 /**
2  * Copyright © 2020 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "manager.hpp"
18 
19 #include "utility.hpp"
20 
21 #include <sdbusplus/bus.hpp>
22 
23 #include <chrono>
24 #include <variant>
25 
26 namespace phosphor
27 {
28 namespace power
29 {
30 namespace regulators
31 {
32 
33 Manager::Manager(sdbusplus::bus::bus& bus, const sdeventplus::Event& event) :
34     ManagerObject(bus, objPath, true), bus(bus), eventLoop(event), fileName("")
35 {
36     // Subscribe to interfacesAdded signal for filename property
37     std::unique_ptr<sdbusplus::server::match::match> matchPtr =
38         std::make_unique<sdbusplus::server::match::match>(
39             bus,
40             sdbusplus::bus::match::rules::interfacesAdded(sysDbusObj).c_str(),
41             std::bind(std::mem_fn(&Manager::signalHandler), this,
42                       std::placeholders::_1));
43     signals.emplace_back(std::move(matchPtr));
44 
45     // Attempt to get the filename property from dbus
46     setFileName(getFileNameDbus());
47 
48     if (!fileName.empty())
49     {
50         // TODO Load & parse JSON configuration data file
51     }
52 
53     // Obtain dbus service name
54     bus.request_name(busName);
55 }
56 
57 void Manager::configure()
58 {
59     // TODO Configuration errors that should halt poweron,
60     // throw InternalFailure exception (or similar) to
61     // fail the call(busctl) to this method
62 }
63 
64 void Manager::monitor(bool enable)
65 {
66     if (enable)
67     {
68         Timer timer(eventLoop, std::bind(&Manager::timerExpired, this));
69         // Set timer as a repeating 1sec timer
70         timer.restart(std::chrono::milliseconds(1000));
71         timers.emplace_back(std::move(timer));
72     }
73     else
74     {
75         // Delete all timers to disable monitoring
76         timers.clear();
77     }
78 }
79 
80 void Manager::timerExpired()
81 {
82     // TODO Analyze, refresh sensor status, and
83     // collect/update telemetry for each regulator
84 }
85 
86 void Manager::sighupHandler(sdeventplus::source::Signal& /*sigSrc*/,
87                             const struct signalfd_siginfo* /*sigInfo*/)
88 {
89     // TODO Reload and process the configuration data
90 }
91 
92 void Manager::signalHandler(sdbusplus::message::message& msg)
93 {
94     if (msg)
95     {
96         sdbusplus::message::object_path op;
97         msg.read(op);
98         if (static_cast<const std::string&>(op) != sysDbusPath)
99         {
100             // Object path does not match the path
101             return;
102         }
103 
104         // An interfacesAdded signal returns a dictionary of interface
105         // names to a dictionary of properties and their values
106         // https://dbus.freedesktop.org/doc/dbus-specification.html
107         std::map<std::string, std::map<std::string, std::variant<std::string>>>
108             intfProp;
109         msg.read(intfProp);
110         auto itIntf = intfProp.find(sysDbusIntf);
111         if (itIntf == intfProp.cend())
112         {
113             // Interface not found on the path
114             return;
115         }
116         auto itProp = itIntf->second.find(sysDbusProp);
117         if (itProp == itIntf->second.cend())
118         {
119             // Property not found on the interface
120             return;
121         }
122         // Set fileName and call parse json function
123         setFileName(std::get<std::string>(itProp->second));
124         // TODO Load & parse JSON configuration data file
125     }
126 }
127 
128 const std::string Manager::getFileNameDbus()
129 {
130     std::string fileName = "";
131     using namespace phosphor::power::util;
132 
133     try
134     {
135         // Do not log an error when service or property are not found
136         auto service = getService(sysDbusPath, sysDbusIntf, bus, false);
137         if (!service.empty())
138         {
139             getProperty(sysDbusIntf, sysDbusProp, sysDbusPath, service, bus,
140                         fileName);
141         }
142     }
143     catch (const sdbusplus::exception::SdBusError&)
144     {
145         // File name property not available on dbus
146         fileName = "";
147     }
148 
149     return fileName;
150 }
151 
152 } // namespace regulators
153 } // namespace power
154 } // namespace phosphor
155