blob: daaa1b7f441b1f0a47e6bafd0f0b5477f4b23efe [file] [log] [blame]
Matthew Barth38a93a82017-05-11 14:12:27 -05001#pragma once
2
3#include "types.hpp"
Matthew Barth336f18a2017-09-26 09:15:56 -05004#include "sdbusplus.hpp"
Matthew Barth38a93a82017-05-11 14:12:27 -05005#include <phosphor-logging/log.hpp>
6
7namespace phosphor
8{
9namespace fan
10{
11namespace control
12{
13class Zone;
14
Matthew Barth336f18a2017-09-26 09:15:56 -050015using namespace phosphor::fan;
Matthew Barth38a93a82017-05-11 14:12:27 -050016using namespace phosphor::logging;
Matthew Barth336f18a2017-09-26 09:15:56 -050017using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
18 Error::InternalFailure;
Matthew Barth38a93a82017-05-11 14:12:27 -050019
20/**
21 * @brief Create a handler function object
22 *
23 * @param[in] handler - The handler being created
24 *
25 * @return - The created handler function object
26 */
27template <typename T>
28auto make_handler(T&& handler)
29{
30 return Handler(std::forward<T>(handler));
31}
32
33/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050034 * @brief Create an action function object
35 *
36 * @param[in] action - The action being created
37 *
38 * @return - The created action function object
39 */
40template <typename T>
41auto make_action(T&& action)
42{
43 return Action(std::forward<T>(action));
44}
45
46/**
Matthew Barth38a93a82017-05-11 14:12:27 -050047 * @struct Property Changed
48 * @brief A match filter functor for Dbus property value changed signals
49 *
50 * @tparam T - The type of the property value
51 * @tparam U - The type of the handler
52 */
53template <typename T, typename U>
54struct PropertyChanged
55{
56 PropertyChanged() = delete;
57 ~PropertyChanged() = default;
58 PropertyChanged(const PropertyChanged&) = default;
59 PropertyChanged& operator=(const PropertyChanged&) = default;
60 PropertyChanged(PropertyChanged&&) = default;
61 PropertyChanged& operator=(PropertyChanged&&) = default;
Matthew Barth336f18a2017-09-26 09:15:56 -050062 PropertyChanged(const char* path,
63 const char* iface,
Matthew Barth38a93a82017-05-11 14:12:27 -050064 const char* property,
65 U&& handler) :
Matthew Barth336f18a2017-09-26 09:15:56 -050066 _path(path),
Matthew Barth38a93a82017-05-11 14:12:27 -050067 _iface(iface),
68 _property(property),
69 _handler(std::forward<U>(handler)) { }
70
71 /** @brief Run signal handler function
72 *
73 * Extract the property from the PropertiesChanged
Matthew Barth336f18a2017-09-26 09:15:56 -050074 * message (or read the property when the message is null)
75 * and run the handler function.
Matthew Barth38a93a82017-05-11 14:12:27 -050076 */
Matthew Barth336f18a2017-09-26 09:15:56 -050077 void operator()(sdbusplus::bus::bus& bus,
Matthew Barth38a93a82017-05-11 14:12:27 -050078 sdbusplus::message::message& msg,
79 Zone& zone) const
80 {
Matthew Barth336f18a2017-09-26 09:15:56 -050081 if (msg)
Matthew Barth38a93a82017-05-11 14:12:27 -050082 {
Matthew Barth336f18a2017-09-26 09:15:56 -050083 std::map<std::string, sdbusplus::message::variant<T>> properties;
84 const char* iface = nullptr;
Matthew Barth38a93a82017-05-11 14:12:27 -050085
Matthew Barth336f18a2017-09-26 09:15:56 -050086 msg.read(iface);
87 if (!iface || strcmp(iface, _iface))
88 {
89 return;
90 }
91
92 msg.read(properties);
93 auto it = properties.find(_property);
94 if (it == properties.cend())
95 {
96 log<level::ERR>("Unable to find property on interface",
97 entry("PROPERTY=%s", _property),
98 entry("INTERFACE=%s", _iface));
99 return;
100 }
101
102 _handler(zone, std::forward<T>(it->second.template get<T>()));
103 }
104 else
Matthew Barth38a93a82017-05-11 14:12:27 -0500105 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500106 try
107 {
108 auto val = util::SDBusPlus::getProperty<T>(bus,
109 _path,
110 _iface,
111 _property);
112 _handler(zone, std::forward<T>(val));
113 }
114 catch (const InternalFailure& ife)
115 {
116 // Property will not be used unless a property changed
117 // signal message is received for this property.
118 log<level::INFO>(
119 "Property not used, unless PropertyChanged signal received",
120 entry("PATH=%s", _path),
121 entry("INTERFACE=%s", _iface),
122 entry("PROPERTY=%s", _property));
123 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500124 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500125 }
126
127private:
Matthew Barth336f18a2017-09-26 09:15:56 -0500128 const char* _path;
Matthew Barth38a93a82017-05-11 14:12:27 -0500129 const char* _iface;
130 const char* _property;
131 U _handler;
132};
133
134/**
135 * @brief Used to process a Dbus property changed signal event
136 *
Matthew Barth336f18a2017-09-26 09:15:56 -0500137 * @param[in] path - Object path
138 * @param[in] iface - Object interface
139 * @param[in] property - Object property
Matthew Barth38a93a82017-05-11 14:12:27 -0500140 * @param[in] handler - Handler function to perform
141 *
142 * @tparam T - The type of the property
143 * @tparam U - The type of the handler
144 */
145template <typename T, typename U>
Matthew Barth336f18a2017-09-26 09:15:56 -0500146auto propertySignal(const char* path,
147 const char* iface,
Matthew Barth38a93a82017-05-11 14:12:27 -0500148 const char* property,
149 U&& handler)
150{
Matthew Barth336f18a2017-09-26 09:15:56 -0500151 return PropertyChanged<T, U>(path,
152 iface,
153 property,
154 std::forward<U>(handler));
Matthew Barth38a93a82017-05-11 14:12:27 -0500155}
156
Matthew Bartheb639c52017-08-04 09:43:11 -0500157/**
158 * @struct Interface Added
159 * @brief A match filter functor for Dbus interface added signals
160 *
161 * @tparam T - The type of the property value
162 * @tparam U - The type of the handler
163 */
164template <typename T, typename U>
165struct InterfaceAdded
166{
167 InterfaceAdded() = delete;
168 ~InterfaceAdded() = default;
169 InterfaceAdded(const InterfaceAdded&) = default;
170 InterfaceAdded& operator=(const InterfaceAdded&) = default;
171 InterfaceAdded(InterfaceAdded&&) = default;
172 InterfaceAdded& operator=(InterfaceAdded&&) = default;
173 InterfaceAdded(const char* path,
174 const char* iface,
175 const char* property,
176 U&& handler) :
177 _path(path),
178 _iface(iface),
179 _property(property),
180 _handler(std::forward<U>(handler)) { }
181
182 /** @brief Run signal handler function
183 *
184 * Extract the property from the InterfacesAdded
185 * message and run the handler function.
186 */
187 void operator()(sdbusplus::bus::bus&,
188 sdbusplus::message::message& msg,
189 Zone& zone) const
190 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500191 if (msg)
Matthew Bartheb639c52017-08-04 09:43:11 -0500192 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500193 std::map<std::string,
194 std::map<std::string,
195 sdbusplus::message::variant<T>>> intfProp;
196 sdbusplus::message::object_path op;
Matthew Bartheb639c52017-08-04 09:43:11 -0500197
Matthew Barth336f18a2017-09-26 09:15:56 -0500198 msg.read(op);
199 auto objPath = static_cast<const std::string&>(op).c_str();
200 if (!objPath || strcmp(objPath, _path))
201 {
202 // Object path does not match this handler's path
203 return;
204 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500205
Matthew Barth336f18a2017-09-26 09:15:56 -0500206 msg.read(intfProp);
207 auto itIntf = intfProp.find(_iface);
208 if (itIntf == intfProp.cend())
209 {
210 // Interface not found on this handler's path
211 return;
212 }
213 auto itProp = itIntf->second.find(_property);
214 if (itProp == itIntf->second.cend())
215 {
216 // Property not found on this handler's path
217 return;
218 }
219
220 _handler(zone, std::forward<T>(itProp->second.template get<T>()));
221 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500222 }
223
224private:
225 const char* _path;
226 const char* _iface;
227 const char* _property;
228 U _handler;
229};
230
231/**
232 * @brief Used to process a Dbus interface added signal event
233 *
234 * @param[in] path - Object path
235 * @param[in] iface - Object interface
236 * @param[in] property - Object property
237 * @param[in] handler - Handler function to perform
238 *
239 * @tparam T - The type of the property
240 * @tparam U - The type of the handler
241 */
242template <typename T, typename U>
243auto objectSignal(const char* path,
244 const char* iface,
245 const char* property,
246 U&& handler)
247{
248 return InterfaceAdded<T, U>(path,
249 iface,
250 property,
251 std::forward<U>(handler));
252}
253
Matthew Barth38a93a82017-05-11 14:12:27 -0500254} // namespace control
255} // namespace fan
256} // namespace phosphor