xref: /openbmc/phosphor-fan-presence/control/functor.hpp (revision eb639c575a7964b849117cc70b6102f17a2dc32a)
138a93a8aSMatthew Barth #pragma once
238a93a8aSMatthew Barth 
338a93a8aSMatthew Barth #include "types.hpp"
438a93a8aSMatthew Barth #include <phosphor-logging/log.hpp>
538a93a8aSMatthew Barth 
638a93a8aSMatthew Barth namespace phosphor
738a93a8aSMatthew Barth {
838a93a8aSMatthew Barth namespace fan
938a93a8aSMatthew Barth {
1038a93a8aSMatthew Barth namespace control
1138a93a8aSMatthew Barth {
1238a93a8aSMatthew Barth class Zone;
1338a93a8aSMatthew Barth 
1438a93a8aSMatthew Barth using namespace phosphor::logging;
1538a93a8aSMatthew Barth 
1638a93a8aSMatthew Barth /**
1738a93a8aSMatthew Barth  * @brief Create a handler function object
1838a93a8aSMatthew Barth  *
1938a93a8aSMatthew Barth  * @param[in] handler - The handler being created
2038a93a8aSMatthew Barth  *
2138a93a8aSMatthew Barth  * @return - The created handler function object
2238a93a8aSMatthew Barth  */
2338a93a8aSMatthew Barth template <typename T>
2438a93a8aSMatthew Barth auto make_handler(T&& handler)
2538a93a8aSMatthew Barth {
2638a93a8aSMatthew Barth     return Handler(std::forward<T>(handler));
2738a93a8aSMatthew Barth }
2838a93a8aSMatthew Barth 
2938a93a8aSMatthew Barth /**
3017d1fe23SMatthew Barth  * @brief Create an action function object
3117d1fe23SMatthew Barth  *
3217d1fe23SMatthew Barth  * @param[in] action - The action being created
3317d1fe23SMatthew Barth  *
3417d1fe23SMatthew Barth  * @return - The created action function object
3517d1fe23SMatthew Barth  */
3617d1fe23SMatthew Barth template <typename T>
3717d1fe23SMatthew Barth auto make_action(T&& action)
3817d1fe23SMatthew Barth {
3917d1fe23SMatthew Barth     return Action(std::forward<T>(action));
4017d1fe23SMatthew Barth }
4117d1fe23SMatthew Barth 
4217d1fe23SMatthew Barth /**
4338a93a8aSMatthew Barth  * @struct Property Changed
4438a93a8aSMatthew Barth  * @brief A match filter functor for Dbus property value changed signals
4538a93a8aSMatthew Barth  *
4638a93a8aSMatthew Barth  * @tparam T - The type of the property value
4738a93a8aSMatthew Barth  * @tparam U - The type of the handler
4838a93a8aSMatthew Barth  */
4938a93a8aSMatthew Barth template <typename T, typename U>
5038a93a8aSMatthew Barth struct PropertyChanged
5138a93a8aSMatthew Barth {
5238a93a8aSMatthew Barth     PropertyChanged() = delete;
5338a93a8aSMatthew Barth     ~PropertyChanged() = default;
5438a93a8aSMatthew Barth     PropertyChanged(const PropertyChanged&) = default;
5538a93a8aSMatthew Barth     PropertyChanged& operator=(const PropertyChanged&) = default;
5638a93a8aSMatthew Barth     PropertyChanged(PropertyChanged&&) = default;
5738a93a8aSMatthew Barth     PropertyChanged& operator=(PropertyChanged&&) = default;
5838a93a8aSMatthew Barth     PropertyChanged(const char* iface,
5938a93a8aSMatthew Barth                     const char* property,
6038a93a8aSMatthew Barth                     U&& handler) :
6138a93a8aSMatthew Barth         _iface(iface),
6238a93a8aSMatthew Barth         _property(property),
6338a93a8aSMatthew Barth         _handler(std::forward<U>(handler)) { }
6438a93a8aSMatthew Barth 
6538a93a8aSMatthew Barth     /** @brief Run signal handler function
6638a93a8aSMatthew Barth      *
6738a93a8aSMatthew Barth      * Extract the property from the PropertiesChanged
6838a93a8aSMatthew Barth      * message and run the handler function.
6938a93a8aSMatthew Barth      */
7038a93a8aSMatthew Barth     void operator()(sdbusplus::bus::bus&,
7138a93a8aSMatthew Barth                     sdbusplus::message::message& msg,
7238a93a8aSMatthew Barth                     Zone& zone) const
7338a93a8aSMatthew Barth     {
7438a93a8aSMatthew Barth         std::map<std::string, sdbusplus::message::variant<T>> properties;
7538a93a8aSMatthew Barth         const char* iface = nullptr;
7638a93a8aSMatthew Barth 
7738a93a8aSMatthew Barth         msg.read(iface);
7838a93a8aSMatthew Barth         if (!iface || strcmp(iface, _iface))
7938a93a8aSMatthew Barth         {
8038a93a8aSMatthew Barth             return;
8138a93a8aSMatthew Barth         }
8238a93a8aSMatthew Barth 
8338a93a8aSMatthew Barth         msg.read(properties);
8438a93a8aSMatthew Barth         auto it = properties.find(_property);
8538a93a8aSMatthew Barth         if (it == properties.cend())
8638a93a8aSMatthew Barth         {
8738a93a8aSMatthew Barth             log<level::ERR>("Unable to find property on interface",
8838a93a8aSMatthew Barth                             entry("PROPERTY=%s", _property),
8938a93a8aSMatthew Barth                             entry("INTERFACE=%s", _iface));
9038a93a8aSMatthew Barth             return;
9138a93a8aSMatthew Barth         }
9238a93a8aSMatthew Barth 
9338a93a8aSMatthew Barth         _handler(zone, std::forward<T>(it->second.template get<T>()));
9438a93a8aSMatthew Barth     }
9538a93a8aSMatthew Barth 
9638a93a8aSMatthew Barth private:
9738a93a8aSMatthew Barth     const char* _iface;
9838a93a8aSMatthew Barth     const char* _property;
9938a93a8aSMatthew Barth     U _handler;
10038a93a8aSMatthew Barth };
10138a93a8aSMatthew Barth 
10238a93a8aSMatthew Barth /**
10338a93a8aSMatthew Barth  * @brief Used to process a Dbus property changed signal event
10438a93a8aSMatthew Barth  *
10538a93a8aSMatthew Barth  * @param[in] iface - Sensor value interface
10638a93a8aSMatthew Barth  * @param[in] property - Sensor value property
10738a93a8aSMatthew Barth  * @param[in] handler - Handler function to perform
10838a93a8aSMatthew Barth  *
10938a93a8aSMatthew Barth  * @tparam T - The type of the property
11038a93a8aSMatthew Barth  * @tparam U - The type of the handler
11138a93a8aSMatthew Barth  */
11238a93a8aSMatthew Barth template <typename T, typename U>
11338a93a8aSMatthew Barth auto propertySignal(const char* iface,
11438a93a8aSMatthew Barth                     const char* property,
11538a93a8aSMatthew Barth                     U&& handler)
11638a93a8aSMatthew Barth {
11738a93a8aSMatthew Barth     return PropertyChanged<T, U>(iface, property, std::forward<U>(handler));
11838a93a8aSMatthew Barth }
11938a93a8aSMatthew Barth 
120*eb639c57SMatthew Barth /**
121*eb639c57SMatthew Barth  * @struct Interface Added
122*eb639c57SMatthew Barth  * @brief A match filter functor for Dbus interface added signals
123*eb639c57SMatthew Barth  *
124*eb639c57SMatthew Barth  * @tparam T - The type of the property value
125*eb639c57SMatthew Barth  * @tparam U - The type of the handler
126*eb639c57SMatthew Barth  */
127*eb639c57SMatthew Barth template <typename T, typename U>
128*eb639c57SMatthew Barth struct InterfaceAdded
129*eb639c57SMatthew Barth {
130*eb639c57SMatthew Barth     InterfaceAdded() = delete;
131*eb639c57SMatthew Barth     ~InterfaceAdded() = default;
132*eb639c57SMatthew Barth     InterfaceAdded(const InterfaceAdded&) = default;
133*eb639c57SMatthew Barth     InterfaceAdded& operator=(const InterfaceAdded&) = default;
134*eb639c57SMatthew Barth     InterfaceAdded(InterfaceAdded&&) = default;
135*eb639c57SMatthew Barth     InterfaceAdded& operator=(InterfaceAdded&&) = default;
136*eb639c57SMatthew Barth     InterfaceAdded(const char* path,
137*eb639c57SMatthew Barth                    const char* iface,
138*eb639c57SMatthew Barth                    const char* property,
139*eb639c57SMatthew Barth                    U&& handler) :
140*eb639c57SMatthew Barth         _path(path),
141*eb639c57SMatthew Barth         _iface(iface),
142*eb639c57SMatthew Barth         _property(property),
143*eb639c57SMatthew Barth         _handler(std::forward<U>(handler)) { }
144*eb639c57SMatthew Barth 
145*eb639c57SMatthew Barth     /** @brief Run signal handler function
146*eb639c57SMatthew Barth      *
147*eb639c57SMatthew Barth      * Extract the property from the InterfacesAdded
148*eb639c57SMatthew Barth      * message and run the handler function.
149*eb639c57SMatthew Barth      */
150*eb639c57SMatthew Barth     void operator()(sdbusplus::bus::bus&,
151*eb639c57SMatthew Barth                     sdbusplus::message::message& msg,
152*eb639c57SMatthew Barth                     Zone& zone) const
153*eb639c57SMatthew Barth     {
154*eb639c57SMatthew Barth         std::map<std::string,
155*eb639c57SMatthew Barth                  std::map<std::string,
156*eb639c57SMatthew Barth                           sdbusplus::message::variant<T>>> intfProp;
157*eb639c57SMatthew Barth         sdbusplus::message::object_path op;
158*eb639c57SMatthew Barth 
159*eb639c57SMatthew Barth         msg.read(op);
160*eb639c57SMatthew Barth         auto objPath = static_cast<const std::string&>(op).c_str();
161*eb639c57SMatthew Barth         if (!objPath || strcmp(objPath, _path))
162*eb639c57SMatthew Barth         {
163*eb639c57SMatthew Barth             // Object path does not match this handler's path
164*eb639c57SMatthew Barth             return;
165*eb639c57SMatthew Barth         }
166*eb639c57SMatthew Barth 
167*eb639c57SMatthew Barth         msg.read(intfProp);
168*eb639c57SMatthew Barth         auto itIntf = intfProp.find(_iface);
169*eb639c57SMatthew Barth         if (itIntf == intfProp.cend())
170*eb639c57SMatthew Barth         {
171*eb639c57SMatthew Barth             // Interface not found on this handler's path
172*eb639c57SMatthew Barth             return;
173*eb639c57SMatthew Barth         }
174*eb639c57SMatthew Barth         auto itProp = itIntf->second.find(_property);
175*eb639c57SMatthew Barth         if (itProp == itIntf->second.cend())
176*eb639c57SMatthew Barth         {
177*eb639c57SMatthew Barth             // Property not found on this handler's path
178*eb639c57SMatthew Barth             return;
179*eb639c57SMatthew Barth         }
180*eb639c57SMatthew Barth 
181*eb639c57SMatthew Barth         _handler(zone, std::forward<T>(itProp->second.template get<T>()));
182*eb639c57SMatthew Barth     }
183*eb639c57SMatthew Barth 
184*eb639c57SMatthew Barth private:
185*eb639c57SMatthew Barth     const char* _path;
186*eb639c57SMatthew Barth     const char* _iface;
187*eb639c57SMatthew Barth     const char* _property;
188*eb639c57SMatthew Barth     U _handler;
189*eb639c57SMatthew Barth };
190*eb639c57SMatthew Barth 
191*eb639c57SMatthew Barth /**
192*eb639c57SMatthew Barth  * @brief Used to process a Dbus interface added signal event
193*eb639c57SMatthew Barth  *
194*eb639c57SMatthew Barth  * @param[in] path - Object path
195*eb639c57SMatthew Barth  * @param[in] iface - Object interface
196*eb639c57SMatthew Barth  * @param[in] property - Object property
197*eb639c57SMatthew Barth  * @param[in] handler - Handler function to perform
198*eb639c57SMatthew Barth  *
199*eb639c57SMatthew Barth  * @tparam T - The type of the property
200*eb639c57SMatthew Barth  * @tparam U - The type of the handler
201*eb639c57SMatthew Barth  */
202*eb639c57SMatthew Barth template <typename T, typename U>
203*eb639c57SMatthew Barth auto objectSignal(const char* path,
204*eb639c57SMatthew Barth                   const char* iface,
205*eb639c57SMatthew Barth                   const char* property,
206*eb639c57SMatthew Barth                   U&& handler)
207*eb639c57SMatthew Barth {
208*eb639c57SMatthew Barth     return InterfaceAdded<T, U>(path,
209*eb639c57SMatthew Barth                                 iface,
210*eb639c57SMatthew Barth                                 property,
211*eb639c57SMatthew Barth                                 std::forward<U>(handler));
212*eb639c57SMatthew Barth }
213*eb639c57SMatthew Barth 
21438a93a8aSMatthew Barth } // namespace control
21538a93a8aSMatthew Barth } // namespace fan
21638a93a8aSMatthew Barth } // namespace phosphor
217