blob: a5044daca4c4808c2ea1d43e4289092d7744cb7d [file] [log] [blame]
Matthew Barth38a93a82017-05-11 14:12:27 -05001#pragma once
2
3#include "types.hpp"
4#include <phosphor-logging/log.hpp>
5
6namespace phosphor
7{
8namespace fan
9{
10namespace control
11{
12class Zone;
13
14using namespace phosphor::logging;
15
16/**
17 * @brief Create a handler function object
18 *
19 * @param[in] handler - The handler being created
20 *
21 * @return - The created handler function object
22 */
23template <typename T>
24auto make_handler(T&& handler)
25{
26 return Handler(std::forward<T>(handler));
27}
28
29/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050030 * @brief Create an action function object
31 *
32 * @param[in] action - The action being created
33 *
34 * @return - The created action function object
35 */
36template <typename T>
37auto make_action(T&& action)
38{
39 return Action(std::forward<T>(action));
40}
41
42/**
Matthew Barth38a93a82017-05-11 14:12:27 -050043 * @struct Property Changed
44 * @brief A match filter functor for Dbus property value changed signals
45 *
46 * @tparam T - The type of the property value
47 * @tparam U - The type of the handler
48 */
49template <typename T, typename U>
50struct PropertyChanged
51{
52 PropertyChanged() = delete;
53 ~PropertyChanged() = default;
54 PropertyChanged(const PropertyChanged&) = default;
55 PropertyChanged& operator=(const PropertyChanged&) = default;
56 PropertyChanged(PropertyChanged&&) = default;
57 PropertyChanged& operator=(PropertyChanged&&) = default;
58 PropertyChanged(const char* iface,
59 const char* property,
60 U&& handler) :
61 _iface(iface),
62 _property(property),
63 _handler(std::forward<U>(handler)) { }
64
65 /** @brief Run signal handler function
66 *
67 * Extract the property from the PropertiesChanged
68 * message and run the handler function.
69 */
70 void operator()(sdbusplus::bus::bus&,
71 sdbusplus::message::message& msg,
72 Zone& zone) const
73 {
74 std::map<std::string, sdbusplus::message::variant<T>> properties;
75 const char* iface = nullptr;
76
77 msg.read(iface);
78 if (!iface || strcmp(iface, _iface))
79 {
80 return;
81 }
82
83 msg.read(properties);
84 auto it = properties.find(_property);
85 if (it == properties.cend())
86 {
87 log<level::ERR>("Unable to find property on interface",
88 entry("PROPERTY=%s", _property),
89 entry("INTERFACE=%s", _iface));
90 return;
91 }
92
93 _handler(zone, std::forward<T>(it->second.template get<T>()));
94 }
95
96private:
97 const char* _iface;
98 const char* _property;
99 U _handler;
100};
101
102/**
103 * @brief Used to process a Dbus property changed signal event
104 *
105 * @param[in] iface - Sensor value interface
106 * @param[in] property - Sensor value property
107 * @param[in] handler - Handler function to perform
108 *
109 * @tparam T - The type of the property
110 * @tparam U - The type of the handler
111 */
112template <typename T, typename U>
113auto propertySignal(const char* iface,
114 const char* property,
115 U&& handler)
116{
117 return PropertyChanged<T, U>(iface, property, std::forward<U>(handler));
118}
119
Matthew Bartheb639c52017-08-04 09:43:11 -0500120/**
121 * @struct Interface Added
122 * @brief A match filter functor for Dbus interface added signals
123 *
124 * @tparam T - The type of the property value
125 * @tparam U - The type of the handler
126 */
127template <typename T, typename U>
128struct InterfaceAdded
129{
130 InterfaceAdded() = delete;
131 ~InterfaceAdded() = default;
132 InterfaceAdded(const InterfaceAdded&) = default;
133 InterfaceAdded& operator=(const InterfaceAdded&) = default;
134 InterfaceAdded(InterfaceAdded&&) = default;
135 InterfaceAdded& operator=(InterfaceAdded&&) = default;
136 InterfaceAdded(const char* path,
137 const char* iface,
138 const char* property,
139 U&& handler) :
140 _path(path),
141 _iface(iface),
142 _property(property),
143 _handler(std::forward<U>(handler)) { }
144
145 /** @brief Run signal handler function
146 *
147 * Extract the property from the InterfacesAdded
148 * message and run the handler function.
149 */
150 void operator()(sdbusplus::bus::bus&,
151 sdbusplus::message::message& msg,
152 Zone& zone) const
153 {
154 std::map<std::string,
155 std::map<std::string,
156 sdbusplus::message::variant<T>>> intfProp;
157 sdbusplus::message::object_path op;
158
159 msg.read(op);
160 auto objPath = static_cast<const std::string&>(op).c_str();
161 if (!objPath || strcmp(objPath, _path))
162 {
163 // Object path does not match this handler's path
164 return;
165 }
166
167 msg.read(intfProp);
168 auto itIntf = intfProp.find(_iface);
169 if (itIntf == intfProp.cend())
170 {
171 // Interface not found on this handler's path
172 return;
173 }
174 auto itProp = itIntf->second.find(_property);
175 if (itProp == itIntf->second.cend())
176 {
177 // Property not found on this handler's path
178 return;
179 }
180
181 _handler(zone, std::forward<T>(itProp->second.template get<T>()));
182 }
183
184private:
185 const char* _path;
186 const char* _iface;
187 const char* _property;
188 U _handler;
189};
190
191/**
192 * @brief Used to process a Dbus interface added signal event
193 *
194 * @param[in] path - Object path
195 * @param[in] iface - Object interface
196 * @param[in] property - Object property
197 * @param[in] handler - Handler function to perform
198 *
199 * @tparam T - The type of the property
200 * @tparam U - The type of the handler
201 */
202template <typename T, typename U>
203auto objectSignal(const char* path,
204 const char* iface,
205 const char* property,
206 U&& handler)
207{
208 return InterfaceAdded<T, U>(path,
209 iface,
210 property,
211 std::forward<U>(handler));
212}
213
Matthew Barth38a93a82017-05-11 14:12:27 -0500214} // namespace control
215} // namespace fan
216} // namespace phosphor