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