xref: /openbmc/phosphor-fan-presence/control/functor.hpp (revision d5cfdbe0240f9a5cb0d29fa6e384ad19b2b32cf3)
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;
165a302576SMatthew Barth using namespace sdbusplus::bus::match;
1738a93a8aSMatthew Barth using namespace phosphor::logging;
18336f18a5SMatthew Barth using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
19336f18a5SMatthew Barth                                 Error::InternalFailure;
2038a93a8aSMatthew Barth 
2138a93a8aSMatthew Barth /**
2238a93a8aSMatthew Barth  * @brief Create a handler function object
2338a93a8aSMatthew Barth  *
2438a93a8aSMatthew Barth  * @param[in] handler - The handler being created
2538a93a8aSMatthew Barth  *
2638a93a8aSMatthew Barth  * @return - The created handler function object
2738a93a8aSMatthew Barth  */
2838a93a8aSMatthew Barth template <typename T>
2938a93a8aSMatthew Barth auto make_handler(T&& handler)
3038a93a8aSMatthew Barth {
3138a93a8aSMatthew Barth     return Handler(std::forward<T>(handler));
3238a93a8aSMatthew Barth }
3338a93a8aSMatthew Barth 
3438a93a8aSMatthew Barth /**
3517d1fe23SMatthew Barth  * @brief Create an action function object
3617d1fe23SMatthew Barth  *
3717d1fe23SMatthew Barth  * @param[in] action - The action being created
3817d1fe23SMatthew Barth  *
3917d1fe23SMatthew Barth  * @return - The created action function object
4017d1fe23SMatthew Barth  */
4117d1fe23SMatthew Barth template <typename T>
4217d1fe23SMatthew Barth auto make_action(T&& action)
4317d1fe23SMatthew Barth {
4417d1fe23SMatthew Barth     return Action(std::forward<T>(action));
4517d1fe23SMatthew Barth }
4617d1fe23SMatthew Barth 
4717d1fe23SMatthew Barth /**
4838a93a8aSMatthew Barth  * @struct Property Changed
4938a93a8aSMatthew Barth  * @brief A match filter functor for Dbus property value changed signals
5038a93a8aSMatthew Barth  *
5138a93a8aSMatthew Barth  * @tparam T - The type of the property value
5238a93a8aSMatthew Barth  * @tparam U - The type of the handler
5338a93a8aSMatthew Barth  */
5438a93a8aSMatthew Barth template <typename T, typename U>
5538a93a8aSMatthew Barth struct PropertyChanged
5638a93a8aSMatthew Barth {
5738a93a8aSMatthew Barth     PropertyChanged() = delete;
5838a93a8aSMatthew Barth     ~PropertyChanged() = default;
5938a93a8aSMatthew Barth     PropertyChanged(const PropertyChanged&) = default;
6038a93a8aSMatthew Barth     PropertyChanged& operator=(const PropertyChanged&) = default;
6138a93a8aSMatthew Barth     PropertyChanged(PropertyChanged&&) = default;
6238a93a8aSMatthew Barth     PropertyChanged& operator=(PropertyChanged&&) = default;
63336f18a5SMatthew Barth     PropertyChanged(const char* path,
64336f18a5SMatthew Barth                     const char* iface,
6538a93a8aSMatthew Barth                     const char* property,
6638a93a8aSMatthew Barth                     U&& handler) :
67336f18a5SMatthew Barth         _path(path),
6838a93a8aSMatthew Barth         _iface(iface),
6938a93a8aSMatthew Barth         _property(property),
7038a93a8aSMatthew Barth         _handler(std::forward<U>(handler)) { }
7138a93a8aSMatthew Barth 
7238a93a8aSMatthew Barth     /** @brief Run signal handler function
7338a93a8aSMatthew Barth      *
7438a93a8aSMatthew Barth      * Extract the property from the PropertiesChanged
75336f18a5SMatthew Barth      * message (or read the property when the message is null)
76336f18a5SMatthew Barth      * and run the handler function.
7738a93a8aSMatthew Barth      */
78336f18a5SMatthew Barth     void operator()(sdbusplus::bus::bus& bus,
7938a93a8aSMatthew Barth                     sdbusplus::message::message& msg,
8038a93a8aSMatthew Barth                     Zone& zone) const
8138a93a8aSMatthew Barth     {
82336f18a5SMatthew Barth         if (msg)
83336f18a5SMatthew Barth         {
8438a93a8aSMatthew Barth             std::map<std::string, sdbusplus::message::variant<T>> properties;
85*d5cfdbe0SMatthew Barth             std::string iface;
8638a93a8aSMatthew Barth 
8738a93a8aSMatthew Barth             msg.read(iface);
88*d5cfdbe0SMatthew Barth             if (iface != _iface)
8938a93a8aSMatthew Barth             {
9038a93a8aSMatthew Barth                 return;
9138a93a8aSMatthew Barth             }
9238a93a8aSMatthew Barth 
9338a93a8aSMatthew Barth             msg.read(properties);
9438a93a8aSMatthew Barth             auto it = properties.find(_property);
9538a93a8aSMatthew Barth             if (it == properties.cend())
9638a93a8aSMatthew Barth             {
9738a93a8aSMatthew Barth                 log<level::ERR>("Unable to find property on interface",
9838a93a8aSMatthew Barth                                 entry("PROPERTY=%s", _property),
9938a93a8aSMatthew Barth                                 entry("INTERFACE=%s", _iface));
10038a93a8aSMatthew Barth                 return;
10138a93a8aSMatthew Barth             }
10238a93a8aSMatthew Barth 
10338a93a8aSMatthew Barth             _handler(zone, std::forward<T>(it->second.template get<T>()));
10438a93a8aSMatthew Barth         }
105336f18a5SMatthew Barth         else
106336f18a5SMatthew Barth         {
107336f18a5SMatthew Barth             try
108336f18a5SMatthew Barth             {
109336f18a5SMatthew Barth                 auto val = util::SDBusPlus::getProperty<T>(bus,
110336f18a5SMatthew Barth                                                            _path,
111336f18a5SMatthew Barth                                                            _iface,
112336f18a5SMatthew Barth                                                            _property);
113336f18a5SMatthew Barth                 _handler(zone, std::forward<T>(val));
114336f18a5SMatthew Barth             }
115336f18a5SMatthew Barth             catch (const InternalFailure& ife)
116336f18a5SMatthew Barth             {
117336f18a5SMatthew Barth                 // Property will not be used unless a property changed
118336f18a5SMatthew Barth                 // signal message is received for this property.
119336f18a5SMatthew Barth                 log<level::INFO>(
120336f18a5SMatthew Barth                     "Property not used, unless PropertyChanged signal received",
121336f18a5SMatthew Barth                     entry("PATH=%s", _path),
122336f18a5SMatthew Barth                     entry("INTERFACE=%s", _iface),
123336f18a5SMatthew Barth                     entry("PROPERTY=%s", _property));
124336f18a5SMatthew Barth             }
125336f18a5SMatthew Barth         }
126336f18a5SMatthew Barth     }
12738a93a8aSMatthew Barth 
12838a93a8aSMatthew Barth private:
129336f18a5SMatthew Barth     const char* _path;
13038a93a8aSMatthew Barth     const char* _iface;
13138a93a8aSMatthew Barth     const char* _property;
13238a93a8aSMatthew Barth     U _handler;
13338a93a8aSMatthew Barth };
13438a93a8aSMatthew Barth 
13538a93a8aSMatthew Barth /**
13638a93a8aSMatthew Barth  * @brief Used to process a Dbus property changed signal event
13738a93a8aSMatthew Barth  *
138336f18a5SMatthew Barth  * @param[in] path - Object path
139336f18a5SMatthew Barth  * @param[in] iface - Object interface
140336f18a5SMatthew Barth  * @param[in] property - Object property
14138a93a8aSMatthew Barth  * @param[in] handler - Handler function to perform
14238a93a8aSMatthew Barth  *
14338a93a8aSMatthew Barth  * @tparam T - The type of the property
14438a93a8aSMatthew Barth  * @tparam U - The type of the handler
14538a93a8aSMatthew Barth  */
14638a93a8aSMatthew Barth template <typename T, typename U>
147336f18a5SMatthew Barth auto propertySignal(const char* path,
148336f18a5SMatthew Barth                     const char* iface,
14938a93a8aSMatthew Barth                     const char* property,
15038a93a8aSMatthew Barth                     U&& handler)
15138a93a8aSMatthew Barth {
152336f18a5SMatthew Barth     return PropertyChanged<T, U>(path,
153336f18a5SMatthew Barth                                  iface,
154336f18a5SMatthew Barth                                  property,
155336f18a5SMatthew Barth                                  std::forward<U>(handler));
15638a93a8aSMatthew Barth }
15738a93a8aSMatthew Barth 
158eb639c57SMatthew Barth /**
159eb639c57SMatthew Barth  * @struct Interface Added
160eb639c57SMatthew Barth  * @brief A match filter functor for Dbus interface added signals
161eb639c57SMatthew Barth  *
162eb639c57SMatthew Barth  * @tparam T - The type of the property value
163eb639c57SMatthew Barth  * @tparam U - The type of the handler
164eb639c57SMatthew Barth  */
165eb639c57SMatthew Barth template <typename T, typename U>
166eb639c57SMatthew Barth struct InterfaceAdded
167eb639c57SMatthew Barth {
168eb639c57SMatthew Barth     InterfaceAdded() = delete;
169eb639c57SMatthew Barth     ~InterfaceAdded() = default;
170eb639c57SMatthew Barth     InterfaceAdded(const InterfaceAdded&) = default;
171eb639c57SMatthew Barth     InterfaceAdded& operator=(const InterfaceAdded&) = default;
172eb639c57SMatthew Barth     InterfaceAdded(InterfaceAdded&&) = default;
173eb639c57SMatthew Barth     InterfaceAdded& operator=(InterfaceAdded&&) = default;
174eb639c57SMatthew Barth     InterfaceAdded(const char* path,
175eb639c57SMatthew Barth                    const char* iface,
176eb639c57SMatthew Barth                    const char* property,
177eb639c57SMatthew Barth                    U&& handler) :
178eb639c57SMatthew Barth         _path(path),
179eb639c57SMatthew Barth         _iface(iface),
180eb639c57SMatthew Barth         _property(property),
181eb639c57SMatthew Barth         _handler(std::forward<U>(handler)) { }
182eb639c57SMatthew Barth 
183eb639c57SMatthew Barth     /** @brief Run signal handler function
184eb639c57SMatthew Barth      *
185eb639c57SMatthew Barth      * Extract the property from the InterfacesAdded
186eb639c57SMatthew Barth      * message and run the handler function.
187eb639c57SMatthew Barth      */
188eb639c57SMatthew Barth     void operator()(sdbusplus::bus::bus&,
189eb639c57SMatthew Barth                     sdbusplus::message::message& msg,
190eb639c57SMatthew Barth                     Zone& zone) const
191eb639c57SMatthew Barth     {
192336f18a5SMatthew Barth         if (msg)
193336f18a5SMatthew Barth         {
194eb639c57SMatthew Barth             std::map<std::string,
195eb639c57SMatthew Barth                      std::map<std::string,
196eb639c57SMatthew Barth                               sdbusplus::message::variant<T>>> intfProp;
197eb639c57SMatthew Barth             sdbusplus::message::object_path op;
198eb639c57SMatthew Barth 
199eb639c57SMatthew Barth             msg.read(op);
200*d5cfdbe0SMatthew Barth             if (static_cast<const std::string&>(op) != _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 
2548fa02dabSMatthew Barth /**
2558fa02dabSMatthew Barth  * @struct Name Owner Changed
2568fa02dabSMatthew Barth  * @brief A match filter functor for Dbus name owner changed signals
2578fa02dabSMatthew Barth  *
2588fa02dabSMatthew Barth  * @tparam U - The type of the handler
2598fa02dabSMatthew Barth  */
2608fa02dabSMatthew Barth template <typename U>
2618fa02dabSMatthew Barth struct NameOwnerChanged
2628fa02dabSMatthew Barth {
2638fa02dabSMatthew Barth     NameOwnerChanged() = delete;
2648fa02dabSMatthew Barth     ~NameOwnerChanged() = default;
2658fa02dabSMatthew Barth     NameOwnerChanged(const NameOwnerChanged&) = default;
2668fa02dabSMatthew Barth     NameOwnerChanged& operator=(const NameOwnerChanged&) = default;
2678fa02dabSMatthew Barth     NameOwnerChanged(NameOwnerChanged&&) = default;
2688fa02dabSMatthew Barth     NameOwnerChanged& operator=(NameOwnerChanged&&) = default;
2698fa02dabSMatthew Barth     NameOwnerChanged(const char* path,
2708fa02dabSMatthew Barth                      const char* iface,
2718fa02dabSMatthew Barth                      U&& handler) :
2728fa02dabSMatthew Barth         _path(path),
2738fa02dabSMatthew Barth         _iface(iface),
2748fa02dabSMatthew Barth         _handler(std::forward<U>(handler)) { }
2758fa02dabSMatthew Barth 
2768fa02dabSMatthew Barth     /** @brief Run signal handler function
2778fa02dabSMatthew Barth      *
2788fa02dabSMatthew Barth      * Extract the name owner from the NameOwnerChanged
2798fa02dabSMatthew Barth      * message (or read the name owner when the message is null)
2808fa02dabSMatthew Barth      * and run the handler function.
2818fa02dabSMatthew Barth      */
2828fa02dabSMatthew Barth     void operator()(sdbusplus::bus::bus& bus,
2838fa02dabSMatthew Barth                     sdbusplus::message::message& msg,
2848fa02dabSMatthew Barth                     Zone& zone) const
2858fa02dabSMatthew Barth     {
2865a302576SMatthew Barth         std::string name;
2875a302576SMatthew Barth         bool hasOwner = false;
2888fa02dabSMatthew Barth         if (msg)
2898fa02dabSMatthew Barth         {
2905a302576SMatthew Barth             // Handle NameOwnerChanged signals
2915a302576SMatthew Barth             msg.read(name);
2925a302576SMatthew Barth 
2935a302576SMatthew Barth             std::string oldOwn;
2945a302576SMatthew Barth             msg.read(oldOwn);
2955a302576SMatthew Barth 
2965a302576SMatthew Barth             std::string newOwn;
2975a302576SMatthew Barth             msg.read(newOwn);
2985a302576SMatthew Barth             if (!newOwn.empty())
2995a302576SMatthew Barth             {
3005a302576SMatthew Barth                 hasOwner = true;
3015a302576SMatthew Barth             }
3028fa02dabSMatthew Barth         }
3038fa02dabSMatthew Barth         else
3048fa02dabSMatthew Barth         {
3055a302576SMatthew Barth             try
3065a302576SMatthew Barth             {
3075a302576SMatthew Barth                 // Initialize NameOwnerChanged data store with service name
3085a302576SMatthew Barth                 name = util::SDBusPlus::getService(bus,
3095a302576SMatthew Barth                                                    _path,
3105a302576SMatthew Barth                                                    _iface);
3115a302576SMatthew Barth                 hasOwner = util::SDBusPlus::callMethodAndRead<bool>(
3125a302576SMatthew Barth                         bus,
3135a302576SMatthew Barth                         "org.freedesktop.DBus",
3145a302576SMatthew Barth                         "/org/freedesktop/DBus",
3155a302576SMatthew Barth                         "org.freedesktop.DBus",
3165a302576SMatthew Barth                         "NameHasOwner",
3175a302576SMatthew Barth                         name);
3188fa02dabSMatthew Barth             }
3195a302576SMatthew Barth             catch (const InternalFailure& ife)
3205a302576SMatthew Barth             {
3215a302576SMatthew Barth                 // Failed to get service name owner state
3225a302576SMatthew Barth                 hasOwner = false;
3235a302576SMatthew Barth             }
3245a302576SMatthew Barth         }
3255a302576SMatthew Barth 
3265a302576SMatthew Barth         _handler(zone, name, hasOwner);
3278fa02dabSMatthew Barth     }
3288fa02dabSMatthew Barth 
3298fa02dabSMatthew Barth private:
3308fa02dabSMatthew Barth     const char* _path;
3318fa02dabSMatthew Barth     const char* _iface;
3328fa02dabSMatthew Barth     U _handler;
3338fa02dabSMatthew Barth };
3348fa02dabSMatthew Barth 
3358fa02dabSMatthew Barth /**
3368fa02dabSMatthew Barth  * @brief Used to process a Dbus name owner changed signal event
3378fa02dabSMatthew Barth  *
3388fa02dabSMatthew Barth  * @param[in] path - Object path
3398fa02dabSMatthew Barth  * @param[in] iface - Object interface
3408fa02dabSMatthew Barth  * @param[in] handler - Handler function to perform
3418fa02dabSMatthew Barth  *
3428fa02dabSMatthew Barth  * @tparam U - The type of the handler
3438fa02dabSMatthew Barth  *
3448fa02dabSMatthew Barth  * @return - The NameOwnerChanged signal struct
3458fa02dabSMatthew Barth  */
3468fa02dabSMatthew Barth template <typename U>
3478fa02dabSMatthew Barth auto ownerSignal(const char* path,
3488fa02dabSMatthew Barth                  const char* iface,
3498fa02dabSMatthew Barth                  U&& handler)
3508fa02dabSMatthew Barth {
3518fa02dabSMatthew Barth     return NameOwnerChanged<U>(path,
3528fa02dabSMatthew Barth                                iface,
3538fa02dabSMatthew Barth                                std::forward<U>(handler));
3548fa02dabSMatthew Barth }
3558fa02dabSMatthew Barth 
35638a93a8aSMatthew Barth } // namespace control
35738a93a8aSMatthew Barth } // namespace fan
35838a93a8aSMatthew Barth } // namespace phosphor
359