xref: /openbmc/phosphor-fan-presence/control/functor.hpp (revision 38a93a8aa2feea7f4e785db6b4ff6d9e81f6020d)
1*38a93a8aSMatthew Barth #pragma once
2*38a93a8aSMatthew Barth 
3*38a93a8aSMatthew Barth #include "types.hpp"
4*38a93a8aSMatthew Barth #include <phosphor-logging/log.hpp>
5*38a93a8aSMatthew Barth 
6*38a93a8aSMatthew Barth namespace phosphor
7*38a93a8aSMatthew Barth {
8*38a93a8aSMatthew Barth namespace fan
9*38a93a8aSMatthew Barth {
10*38a93a8aSMatthew Barth namespace control
11*38a93a8aSMatthew Barth {
12*38a93a8aSMatthew Barth class Zone;
13*38a93a8aSMatthew Barth 
14*38a93a8aSMatthew Barth using namespace phosphor::logging;
15*38a93a8aSMatthew Barth 
16*38a93a8aSMatthew Barth /**
17*38a93a8aSMatthew Barth  * @brief Create a handler function object
18*38a93a8aSMatthew Barth  *
19*38a93a8aSMatthew Barth  * @param[in] handler - The handler being created
20*38a93a8aSMatthew Barth  *
21*38a93a8aSMatthew Barth  * @return - The created handler function object
22*38a93a8aSMatthew Barth  */
23*38a93a8aSMatthew Barth template <typename T>
24*38a93a8aSMatthew Barth auto make_handler(T&& handler)
25*38a93a8aSMatthew Barth {
26*38a93a8aSMatthew Barth     return Handler(std::forward<T>(handler));
27*38a93a8aSMatthew Barth }
28*38a93a8aSMatthew Barth 
29*38a93a8aSMatthew Barth /**
30*38a93a8aSMatthew Barth  * @struct Property Changed
31*38a93a8aSMatthew Barth  * @brief A match filter functor for Dbus property value changed signals
32*38a93a8aSMatthew Barth  *
33*38a93a8aSMatthew Barth  * @tparam T - The type of the property value
34*38a93a8aSMatthew Barth  * @tparam U - The type of the handler
35*38a93a8aSMatthew Barth  */
36*38a93a8aSMatthew Barth template <typename T, typename U>
37*38a93a8aSMatthew Barth struct PropertyChanged
38*38a93a8aSMatthew Barth {
39*38a93a8aSMatthew Barth     PropertyChanged() = delete;
40*38a93a8aSMatthew Barth     ~PropertyChanged() = default;
41*38a93a8aSMatthew Barth     PropertyChanged(const PropertyChanged&) = default;
42*38a93a8aSMatthew Barth     PropertyChanged& operator=(const PropertyChanged&) = default;
43*38a93a8aSMatthew Barth     PropertyChanged(PropertyChanged&&) = default;
44*38a93a8aSMatthew Barth     PropertyChanged& operator=(PropertyChanged&&) = default;
45*38a93a8aSMatthew Barth     PropertyChanged(const char* iface,
46*38a93a8aSMatthew Barth                     const char* property,
47*38a93a8aSMatthew Barth                     U&& handler) :
48*38a93a8aSMatthew Barth         _iface(iface),
49*38a93a8aSMatthew Barth         _property(property),
50*38a93a8aSMatthew Barth         _handler(std::forward<U>(handler)) { }
51*38a93a8aSMatthew Barth 
52*38a93a8aSMatthew Barth     /** @brief Run signal handler function
53*38a93a8aSMatthew Barth      *
54*38a93a8aSMatthew Barth      * Extract the property from the PropertiesChanged
55*38a93a8aSMatthew Barth      * message and run the handler function.
56*38a93a8aSMatthew Barth      */
57*38a93a8aSMatthew Barth     void operator()(sdbusplus::bus::bus&,
58*38a93a8aSMatthew Barth                     sdbusplus::message::message& msg,
59*38a93a8aSMatthew Barth                     Zone& zone) const
60*38a93a8aSMatthew Barth     {
61*38a93a8aSMatthew Barth         std::map<std::string, sdbusplus::message::variant<T>> properties;
62*38a93a8aSMatthew Barth         const char* iface = nullptr;
63*38a93a8aSMatthew Barth 
64*38a93a8aSMatthew Barth         msg.read(iface);
65*38a93a8aSMatthew Barth         if (!iface || strcmp(iface, _iface))
66*38a93a8aSMatthew Barth         {
67*38a93a8aSMatthew Barth             return;
68*38a93a8aSMatthew Barth         }
69*38a93a8aSMatthew Barth 
70*38a93a8aSMatthew Barth         msg.read(properties);
71*38a93a8aSMatthew Barth         auto it = properties.find(_property);
72*38a93a8aSMatthew Barth         if (it == properties.cend())
73*38a93a8aSMatthew Barth         {
74*38a93a8aSMatthew Barth             log<level::ERR>("Unable to find property on interface",
75*38a93a8aSMatthew Barth                             entry("PROPERTY=%s", _property),
76*38a93a8aSMatthew Barth                             entry("INTERFACE=%s", _iface));
77*38a93a8aSMatthew Barth             return;
78*38a93a8aSMatthew Barth         }
79*38a93a8aSMatthew Barth 
80*38a93a8aSMatthew Barth         _handler(zone, std::forward<T>(it->second.template get<T>()));
81*38a93a8aSMatthew Barth     }
82*38a93a8aSMatthew Barth 
83*38a93a8aSMatthew Barth private:
84*38a93a8aSMatthew Barth     const char* _iface;
85*38a93a8aSMatthew Barth     const char* _property;
86*38a93a8aSMatthew Barth     U _handler;
87*38a93a8aSMatthew Barth };
88*38a93a8aSMatthew Barth 
89*38a93a8aSMatthew Barth /**
90*38a93a8aSMatthew Barth  * @brief Used to process a Dbus property changed signal event
91*38a93a8aSMatthew Barth  *
92*38a93a8aSMatthew Barth  * @param[in] iface - Sensor value interface
93*38a93a8aSMatthew Barth  * @param[in] property - Sensor value property
94*38a93a8aSMatthew Barth  * @param[in] handler - Handler function to perform
95*38a93a8aSMatthew Barth  *
96*38a93a8aSMatthew Barth  * @tparam T - The type of the property
97*38a93a8aSMatthew Barth  * @tparam U - The type of the handler
98*38a93a8aSMatthew Barth  */
99*38a93a8aSMatthew Barth template <typename T, typename U>
100*38a93a8aSMatthew Barth auto propertySignal(const char* iface,
101*38a93a8aSMatthew Barth                     const char* property,
102*38a93a8aSMatthew Barth                     U&& handler)
103*38a93a8aSMatthew Barth {
104*38a93a8aSMatthew Barth     return PropertyChanged<T, U>(iface, property, std::forward<U>(handler));
105*38a93a8aSMatthew Barth }
106*38a93a8aSMatthew Barth 
107*38a93a8aSMatthew Barth } // namespace control
108*38a93a8aSMatthew Barth } // namespace fan
109*38a93a8aSMatthew Barth } // namespace phosphor
110