1 /*
2 // Copyright (c) 2018 Intel 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 "dbuswrite.hpp"
18
19 #include "dbushelper_interface.hpp"
20
21 #include <phosphor-logging/log.hpp>
22 #include <sdbusplus/bus.hpp>
23
24 #include <exception>
25 #include <iostream>
26 #include <memory>
27 #include <string>
28 #include <variant>
29
30 namespace pid_control
31 {
32
33 constexpr const char* pwmInterface = "xyz.openbmc_project.Control.FanPwm";
34
35 using namespace phosphor::logging;
36
createDbusWrite(const std::string & path,int64_t min,int64_t max,std::unique_ptr<DbusHelperInterface> helper)37 std::unique_ptr<WriteInterface> DbusWritePercent::createDbusWrite(
38 const std::string& path, int64_t min, int64_t max,
39 std::unique_ptr<DbusHelperInterface> helper)
40 {
41 std::string connectionName;
42
43 try
44 {
45 connectionName = helper->getService(pwmInterface, path);
46 }
47 catch (const std::exception& e)
48 {
49 return nullptr;
50 }
51
52 return std::make_unique<DbusWritePercent>(path, min, max, connectionName);
53 }
54
write(double value)55 void DbusWritePercent::write(double value)
56 {
57 return write(value, false, nullptr);
58 }
59
write(double value,bool force,int64_t * written)60 void DbusWritePercent::write(double value, bool force, int64_t* written)
61 {
62 double minimum = getMin();
63 double maximum = getMax();
64
65 double range = maximum - minimum;
66 double offset = range * value;
67 double ovalue = offset + minimum;
68
69 if (oldValue == static_cast<int64_t>(ovalue))
70 {
71 if (!force)
72 {
73 if (written)
74 {
75 *written = oldValue;
76 }
77 return;
78 }
79 }
80 auto writeBus = sdbusplus::bus::new_default();
81 auto mesg =
82 writeBus.new_method_call(connectionName.c_str(), path.c_str(),
83 "org.freedesktop.DBus.Properties", "Set");
84 mesg.append(pwmInterface, "Target",
85 std::variant<uint64_t>(static_cast<uint64_t>(ovalue)));
86
87 try
88 {
89 // TODO: if we don't use the reply, call_noreply()
90 auto resp = writeBus.call(mesg);
91 }
92 catch (const sdbusplus::exception_t& ex)
93 {
94 log<level::ERR>("Dbus Call Failure", entry("PATH=%s", path.c_str()),
95 entry("WHAT=%s", ex.what()));
96 }
97
98 oldValue = static_cast<int64_t>(ovalue);
99 if (written)
100 {
101 *written = oldValue;
102 }
103 return;
104 }
105
createDbusWrite(const std::string & path,int64_t min,int64_t max,std::unique_ptr<DbusHelperInterface> helper)106 std::unique_ptr<WriteInterface> DbusWrite::createDbusWrite(
107 const std::string& path, int64_t min, int64_t max,
108 std::unique_ptr<DbusHelperInterface> helper)
109 {
110 std::string connectionName;
111
112 try
113 {
114 connectionName = helper->getService(pwmInterface, path);
115 }
116 catch (const std::exception& e)
117 {
118 return nullptr;
119 }
120
121 return std::make_unique<DbusWrite>(path, min, max, connectionName);
122 }
123
write(double value)124 void DbusWrite::write(double value)
125 {
126 return write(value, false, nullptr);
127 }
128
write(double value,bool force,int64_t * written)129 void DbusWrite::write(double value, bool force, int64_t* written)
130 {
131 if (oldValue == static_cast<int64_t>(value))
132 {
133 if (!force)
134 {
135 if (written)
136 {
137 *written = oldValue;
138 }
139 return;
140 }
141 }
142 auto writeBus = sdbusplus::bus::new_default();
143 auto mesg =
144 writeBus.new_method_call(connectionName.c_str(), path.c_str(),
145 "org.freedesktop.DBus.Properties", "Set");
146 mesg.append(pwmInterface, "Target",
147 std::variant<uint64_t>(static_cast<uint64_t>(value)));
148
149 try
150 {
151 // TODO: consider call_noreplly
152 auto resp = writeBus.call(mesg);
153 }
154 catch (const sdbusplus::exception_t& ex)
155 {
156 log<level::ERR>("Dbus Call Failure", entry("PATH=%s", path.c_str()),
157 entry("WHAT=%s", ex.what()));
158 }
159
160 oldValue = static_cast<int64_t>(value);
161 if (written)
162 {
163 *written = oldValue;
164 }
165 return;
166 }
167
168 } // namespace pid_control
169