xref: /openbmc/phosphor-fan-presence/control/functor.hpp (revision 8fa02dabe17db9761086d77c390ceb281e2936c9)
138a93a8aSMatthew Barth #pragma once
238a93a8aSMatthew Barth 
338a93a8aSMatthew Barth #include "types.hpp"
4336f18a5SMatthew Barth #include "sdbusplus.hpp"
538a93a8aSMatthew Barth #include <phosphor-logging/log.hpp>
638a93a8aSMatthew Barth 
738a93a8aSMatthew Barth namespace phosphor
838a93a8aSMatthew Barth {
938a93a8aSMatthew Barth namespace fan
1038a93a8aSMatthew Barth {
1138a93a8aSMatthew Barth namespace control
1238a93a8aSMatthew Barth {
1338a93a8aSMatthew Barth class Zone;
1438a93a8aSMatthew Barth 
15336f18a5SMatthew Barth using namespace phosphor::fan;
1638a93a8aSMatthew Barth using namespace phosphor::logging;
17336f18a5SMatthew Barth using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
18336f18a5SMatthew Barth                                 Error::InternalFailure;
1938a93a8aSMatthew Barth 
2038a93a8aSMatthew Barth /**
2138a93a8aSMatthew Barth  * @brief Create a handler function object
2238a93a8aSMatthew Barth  *
2338a93a8aSMatthew Barth  * @param[in] handler - The handler being created
2438a93a8aSMatthew Barth  *
2538a93a8aSMatthew Barth  * @return - The created handler function object
2638a93a8aSMatthew Barth  */
2738a93a8aSMatthew Barth template <typename T>
2838a93a8aSMatthew Barth auto make_handler(T&& handler)
2938a93a8aSMatthew Barth {
3038a93a8aSMatthew Barth     return Handler(std::forward<T>(handler));
3138a93a8aSMatthew Barth }
3238a93a8aSMatthew Barth 
3338a93a8aSMatthew Barth /**
3417d1fe23SMatthew Barth  * @brief Create an action function object
3517d1fe23SMatthew Barth  *
3617d1fe23SMatthew Barth  * @param[in] action - The action being created
3717d1fe23SMatthew Barth  *
3817d1fe23SMatthew Barth  * @return - The created action function object
3917d1fe23SMatthew Barth  */
4017d1fe23SMatthew Barth template <typename T>
4117d1fe23SMatthew Barth auto make_action(T&& action)
4217d1fe23SMatthew Barth {
4317d1fe23SMatthew Barth     return Action(std::forward<T>(action));
4417d1fe23SMatthew Barth }
4517d1fe23SMatthew Barth 
4617d1fe23SMatthew Barth /**
4738a93a8aSMatthew Barth  * @struct Property Changed
4838a93a8aSMatthew Barth  * @brief A match filter functor for Dbus property value changed signals
4938a93a8aSMatthew Barth  *
5038a93a8aSMatthew Barth  * @tparam T - The type of the property value
5138a93a8aSMatthew Barth  * @tparam U - The type of the handler
5238a93a8aSMatthew Barth  */
5338a93a8aSMatthew Barth template <typename T, typename U>
5438a93a8aSMatthew Barth struct PropertyChanged
5538a93a8aSMatthew Barth {
5638a93a8aSMatthew Barth     PropertyChanged() = delete;
5738a93a8aSMatthew Barth     ~PropertyChanged() = default;
5838a93a8aSMatthew Barth     PropertyChanged(const PropertyChanged&) = default;
5938a93a8aSMatthew Barth     PropertyChanged& operator=(const PropertyChanged&) = default;
6038a93a8aSMatthew Barth     PropertyChanged(PropertyChanged&&) = default;
6138a93a8aSMatthew Barth     PropertyChanged& operator=(PropertyChanged&&) = default;
62336f18a5SMatthew Barth     PropertyChanged(const char* path,
63336f18a5SMatthew Barth                     const char* iface,
6438a93a8aSMatthew Barth                     const char* property,
6538a93a8aSMatthew Barth                     U&& handler) :
66336f18a5SMatthew Barth         _path(path),
6738a93a8aSMatthew Barth         _iface(iface),
6838a93a8aSMatthew Barth         _property(property),
6938a93a8aSMatthew Barth         _handler(std::forward<U>(handler)) { }
7038a93a8aSMatthew Barth 
7138a93a8aSMatthew Barth     /** @brief Run signal handler function
7238a93a8aSMatthew Barth      *
7338a93a8aSMatthew Barth      * Extract the property from the PropertiesChanged
74336f18a5SMatthew Barth      * message (or read the property when the message is null)
75336f18a5SMatthew Barth      * and run the handler function.
7638a93a8aSMatthew Barth      */
77336f18a5SMatthew Barth     void operator()(sdbusplus::bus::bus& bus,
7838a93a8aSMatthew Barth                     sdbusplus::message::message& msg,
7938a93a8aSMatthew Barth                     Zone& zone) const
8038a93a8aSMatthew Barth     {
81336f18a5SMatthew Barth         if (msg)
82336f18a5SMatthew Barth         {
8338a93a8aSMatthew Barth             std::map<std::string, sdbusplus::message::variant<T>> properties;
8438a93a8aSMatthew Barth             const char* iface = nullptr;
8538a93a8aSMatthew Barth 
8638a93a8aSMatthew Barth             msg.read(iface);
8738a93a8aSMatthew Barth             if (!iface || strcmp(iface, _iface))
8838a93a8aSMatthew Barth             {
8938a93a8aSMatthew Barth                 return;
9038a93a8aSMatthew Barth             }
9138a93a8aSMatthew Barth 
9238a93a8aSMatthew Barth             msg.read(properties);
9338a93a8aSMatthew Barth             auto it = properties.find(_property);
9438a93a8aSMatthew Barth             if (it == properties.cend())
9538a93a8aSMatthew Barth             {
9638a93a8aSMatthew Barth                 log<level::ERR>("Unable to find property on interface",
9738a93a8aSMatthew Barth                                 entry("PROPERTY=%s", _property),
9838a93a8aSMatthew Barth                                 entry("INTERFACE=%s", _iface));
9938a93a8aSMatthew Barth                 return;
10038a93a8aSMatthew Barth             }
10138a93a8aSMatthew Barth 
10238a93a8aSMatthew Barth             _handler(zone, std::forward<T>(it->second.template get<T>()));
10338a93a8aSMatthew Barth         }
104336f18a5SMatthew Barth         else
105336f18a5SMatthew Barth         {
106336f18a5SMatthew Barth             try
107336f18a5SMatthew Barth             {
108336f18a5SMatthew Barth                 auto val = util::SDBusPlus::getProperty<T>(bus,
109336f18a5SMatthew Barth                                                            _path,
110336f18a5SMatthew Barth                                                            _iface,
111336f18a5SMatthew Barth                                                            _property);
112336f18a5SMatthew Barth                 _handler(zone, std::forward<T>(val));
113336f18a5SMatthew Barth             }
114336f18a5SMatthew Barth             catch (const InternalFailure& ife)
115336f18a5SMatthew Barth             {
116336f18a5SMatthew Barth                 // Property will not be used unless a property changed
117336f18a5SMatthew Barth                 // signal message is received for this property.
118336f18a5SMatthew Barth                 log<level::INFO>(
119336f18a5SMatthew Barth                     "Property not used, unless PropertyChanged signal received",
120336f18a5SMatthew Barth                     entry("PATH=%s", _path),
121336f18a5SMatthew Barth                     entry("INTERFACE=%s", _iface),
122336f18a5SMatthew Barth                     entry("PROPERTY=%s", _property));
123336f18a5SMatthew Barth             }
124336f18a5SMatthew Barth         }
125336f18a5SMatthew Barth     }
12638a93a8aSMatthew Barth 
12738a93a8aSMatthew Barth private:
128336f18a5SMatthew Barth     const char* _path;
12938a93a8aSMatthew Barth     const char* _iface;
13038a93a8aSMatthew Barth     const char* _property;
13138a93a8aSMatthew Barth     U _handler;
13238a93a8aSMatthew Barth };
13338a93a8aSMatthew Barth 
13438a93a8aSMatthew Barth /**
13538a93a8aSMatthew Barth  * @brief Used to process a Dbus property changed signal event
13638a93a8aSMatthew Barth  *
137336f18a5SMatthew Barth  * @param[in] path - Object path
138336f18a5SMatthew Barth  * @param[in] iface - Object interface
139336f18a5SMatthew Barth  * @param[in] property - Object property
14038a93a8aSMatthew Barth  * @param[in] handler - Handler function to perform
14138a93a8aSMatthew Barth  *
14238a93a8aSMatthew Barth  * @tparam T - The type of the property
14338a93a8aSMatthew Barth  * @tparam U - The type of the handler
14438a93a8aSMatthew Barth  */
14538a93a8aSMatthew Barth template <typename T, typename U>
146336f18a5SMatthew Barth auto propertySignal(const char* path,
147336f18a5SMatthew Barth                     const char* iface,
14838a93a8aSMatthew Barth                     const char* property,
14938a93a8aSMatthew Barth                     U&& handler)
15038a93a8aSMatthew Barth {
151336f18a5SMatthew Barth     return PropertyChanged<T, U>(path,
152336f18a5SMatthew Barth                                  iface,
153336f18a5SMatthew Barth                                  property,
154336f18a5SMatthew Barth                                  std::forward<U>(handler));
15538a93a8aSMatthew Barth }
15638a93a8aSMatthew Barth 
157eb639c57SMatthew Barth /**
158eb639c57SMatthew Barth  * @struct Interface Added
159eb639c57SMatthew Barth  * @brief A match filter functor for Dbus interface added signals
160eb639c57SMatthew Barth  *
161eb639c57SMatthew Barth  * @tparam T - The type of the property value
162eb639c57SMatthew Barth  * @tparam U - The type of the handler
163eb639c57SMatthew Barth  */
164eb639c57SMatthew Barth template <typename T, typename U>
165eb639c57SMatthew Barth struct InterfaceAdded
166eb639c57SMatthew Barth {
167eb639c57SMatthew Barth     InterfaceAdded() = delete;
168eb639c57SMatthew Barth     ~InterfaceAdded() = default;
169eb639c57SMatthew Barth     InterfaceAdded(const InterfaceAdded&) = default;
170eb639c57SMatthew Barth     InterfaceAdded& operator=(const InterfaceAdded&) = default;
171eb639c57SMatthew Barth     InterfaceAdded(InterfaceAdded&&) = default;
172eb639c57SMatthew Barth     InterfaceAdded& operator=(InterfaceAdded&&) = default;
173eb639c57SMatthew Barth     InterfaceAdded(const char* path,
174eb639c57SMatthew Barth                    const char* iface,
175eb639c57SMatthew Barth                    const char* property,
176eb639c57SMatthew Barth                    U&& handler) :
177eb639c57SMatthew Barth         _path(path),
178eb639c57SMatthew Barth         _iface(iface),
179eb639c57SMatthew Barth         _property(property),
180eb639c57SMatthew Barth         _handler(std::forward<U>(handler)) { }
181eb639c57SMatthew Barth 
182eb639c57SMatthew Barth     /** @brief Run signal handler function
183eb639c57SMatthew Barth      *
184eb639c57SMatthew Barth      * Extract the property from the InterfacesAdded
185eb639c57SMatthew Barth      * message and run the handler function.
186eb639c57SMatthew Barth      */
187eb639c57SMatthew Barth     void operator()(sdbusplus::bus::bus&,
188eb639c57SMatthew Barth                     sdbusplus::message::message& msg,
189eb639c57SMatthew Barth                     Zone& zone) const
190eb639c57SMatthew Barth     {
191336f18a5SMatthew Barth         if (msg)
192336f18a5SMatthew Barth         {
193eb639c57SMatthew Barth             std::map<std::string,
194eb639c57SMatthew Barth                      std::map<std::string,
195eb639c57SMatthew Barth                               sdbusplus::message::variant<T>>> intfProp;
196eb639c57SMatthew Barth             sdbusplus::message::object_path op;
197eb639c57SMatthew Barth 
198eb639c57SMatthew Barth             msg.read(op);
199eb639c57SMatthew Barth             auto objPath = static_cast<const std::string&>(op).c_str();
200eb639c57SMatthew Barth             if (!objPath || strcmp(objPath, _path))
201eb639c57SMatthew Barth             {
202eb639c57SMatthew Barth                 // Object path does not match this handler's path
203eb639c57SMatthew Barth                 return;
204eb639c57SMatthew Barth             }
205eb639c57SMatthew Barth 
206eb639c57SMatthew Barth             msg.read(intfProp);
207eb639c57SMatthew Barth             auto itIntf = intfProp.find(_iface);
208eb639c57SMatthew Barth             if (itIntf == intfProp.cend())
209eb639c57SMatthew Barth             {
210eb639c57SMatthew Barth                 // Interface not found on this handler's path
211eb639c57SMatthew Barth                 return;
212eb639c57SMatthew Barth             }
213eb639c57SMatthew Barth             auto itProp = itIntf->second.find(_property);
214eb639c57SMatthew Barth             if (itProp == itIntf->second.cend())
215eb639c57SMatthew Barth             {
216eb639c57SMatthew Barth                 // Property not found on this handler's path
217eb639c57SMatthew Barth                 return;
218eb639c57SMatthew Barth             }
219eb639c57SMatthew Barth 
220eb639c57SMatthew Barth             _handler(zone, std::forward<T>(itProp->second.template get<T>()));
221eb639c57SMatthew Barth         }
222336f18a5SMatthew Barth     }
223eb639c57SMatthew Barth 
224eb639c57SMatthew Barth private:
225eb639c57SMatthew Barth     const char* _path;
226eb639c57SMatthew Barth     const char* _iface;
227eb639c57SMatthew Barth     const char* _property;
228eb639c57SMatthew Barth     U _handler;
229eb639c57SMatthew Barth };
230eb639c57SMatthew Barth 
231eb639c57SMatthew Barth /**
232eb639c57SMatthew Barth  * @brief Used to process a Dbus interface added signal event
233eb639c57SMatthew Barth  *
234eb639c57SMatthew Barth  * @param[in] path - Object path
235eb639c57SMatthew Barth  * @param[in] iface - Object interface
236eb639c57SMatthew Barth  * @param[in] property - Object property
237eb639c57SMatthew Barth  * @param[in] handler - Handler function to perform
238eb639c57SMatthew Barth  *
239eb639c57SMatthew Barth  * @tparam T - The type of the property
240eb639c57SMatthew Barth  * @tparam U - The type of the handler
241eb639c57SMatthew Barth  */
242eb639c57SMatthew Barth template <typename T, typename U>
243eb639c57SMatthew Barth auto objectSignal(const char* path,
244eb639c57SMatthew Barth                   const char* iface,
245eb639c57SMatthew Barth                   const char* property,
246eb639c57SMatthew Barth                   U&& handler)
247eb639c57SMatthew Barth {
248eb639c57SMatthew Barth     return InterfaceAdded<T, U>(path,
249eb639c57SMatthew Barth                                 iface,
250eb639c57SMatthew Barth                                 property,
251eb639c57SMatthew Barth                                 std::forward<U>(handler));
252eb639c57SMatthew Barth }
253eb639c57SMatthew Barth 
254*8fa02dabSMatthew Barth /**
255*8fa02dabSMatthew Barth  * @struct Name Owner Changed
256*8fa02dabSMatthew Barth  * @brief A match filter functor for Dbus name owner changed signals
257*8fa02dabSMatthew Barth  *
258*8fa02dabSMatthew Barth  * @tparam U - The type of the handler
259*8fa02dabSMatthew Barth  */
260*8fa02dabSMatthew Barth template <typename U>
261*8fa02dabSMatthew Barth struct NameOwnerChanged
262*8fa02dabSMatthew Barth {
263*8fa02dabSMatthew Barth     NameOwnerChanged() = delete;
264*8fa02dabSMatthew Barth     ~NameOwnerChanged() = default;
265*8fa02dabSMatthew Barth     NameOwnerChanged(const NameOwnerChanged&) = default;
266*8fa02dabSMatthew Barth     NameOwnerChanged& operator=(const NameOwnerChanged&) = default;
267*8fa02dabSMatthew Barth     NameOwnerChanged(NameOwnerChanged&&) = default;
268*8fa02dabSMatthew Barth     NameOwnerChanged& operator=(NameOwnerChanged&&) = default;
269*8fa02dabSMatthew Barth     NameOwnerChanged(const char* path,
270*8fa02dabSMatthew Barth                      const char* iface,
271*8fa02dabSMatthew Barth                      U&& handler) :
272*8fa02dabSMatthew Barth         _path(path),
273*8fa02dabSMatthew Barth         _iface(iface),
274*8fa02dabSMatthew Barth         _handler(std::forward<U>(handler)) { }
275*8fa02dabSMatthew Barth 
276*8fa02dabSMatthew Barth     /** @brief Run signal handler function
277*8fa02dabSMatthew Barth      *
278*8fa02dabSMatthew Barth      * Extract the name owner from the NameOwnerChanged
279*8fa02dabSMatthew Barth      * message (or read the name owner when the message is null)
280*8fa02dabSMatthew Barth      * and run the handler function.
281*8fa02dabSMatthew Barth      */
282*8fa02dabSMatthew Barth     void operator()(sdbusplus::bus::bus& bus,
283*8fa02dabSMatthew Barth                     sdbusplus::message::message& msg,
284*8fa02dabSMatthew Barth                     Zone& zone) const
285*8fa02dabSMatthew Barth     {
286*8fa02dabSMatthew Barth         if (msg)
287*8fa02dabSMatthew Barth         {
288*8fa02dabSMatthew Barth             // TODO Handle NameOwnerChanged signals
289*8fa02dabSMatthew Barth         }
290*8fa02dabSMatthew Barth         else
291*8fa02dabSMatthew Barth         {
292*8fa02dabSMatthew Barth             // TODO Initialize NameOwnerChanged data store with service names
293*8fa02dabSMatthew Barth         }
294*8fa02dabSMatthew Barth     }
295*8fa02dabSMatthew Barth 
296*8fa02dabSMatthew Barth private:
297*8fa02dabSMatthew Barth     const char* _path;
298*8fa02dabSMatthew Barth     const char* _iface;
299*8fa02dabSMatthew Barth     U _handler;
300*8fa02dabSMatthew Barth };
301*8fa02dabSMatthew Barth 
302*8fa02dabSMatthew Barth /**
303*8fa02dabSMatthew Barth  * @brief Used to process a Dbus name owner changed signal event
304*8fa02dabSMatthew Barth  *
305*8fa02dabSMatthew Barth  * @param[in] path - Object path
306*8fa02dabSMatthew Barth  * @param[in] iface - Object interface
307*8fa02dabSMatthew Barth  * @param[in] handler - Handler function to perform
308*8fa02dabSMatthew Barth  *
309*8fa02dabSMatthew Barth  * @tparam U - The type of the handler
310*8fa02dabSMatthew Barth  *
311*8fa02dabSMatthew Barth  * @return - The NameOwnerChanged signal struct
312*8fa02dabSMatthew Barth  */
313*8fa02dabSMatthew Barth template <typename U>
314*8fa02dabSMatthew Barth auto ownerSignal(const char* path,
315*8fa02dabSMatthew Barth                  const char* iface,
316*8fa02dabSMatthew Barth                  U&& handler)
317*8fa02dabSMatthew Barth {
318*8fa02dabSMatthew Barth     return NameOwnerChanged<U>(path,
319*8fa02dabSMatthew Barth                                iface,
320*8fa02dabSMatthew Barth                                std::forward<U>(handler));
321*8fa02dabSMatthew Barth }
322*8fa02dabSMatthew Barth 
32338a93a8aSMatthew Barth } // namespace control
32438a93a8aSMatthew Barth } // namespace fan
32538a93a8aSMatthew Barth } // namespace phosphor
326