12a28c936SMatt Spinler #pragma once 22a28c936SMatt Spinler 32a28c936SMatt Spinler #include "dbus_types.hpp" 42a28c936SMatt Spinler 52a28c936SMatt Spinler #include <sdbusplus/bus/match.hpp> 62a28c936SMatt Spinler 72a28c936SMatt Spinler namespace openpower::pels 82a28c936SMatt Spinler { 92a28c936SMatt Spinler 102a28c936SMatt Spinler namespace match_rules = sdbusplus::bus::match::rules; 112a28c936SMatt Spinler 122a28c936SMatt Spinler /** 132a28c936SMatt Spinler * @class DBusWatcher 142a28c936SMatt Spinler * 152a28c936SMatt Spinler * The base class for the PropertyWatcher and InterfaceWatcher classes. 162a28c936SMatt Spinler */ 172a28c936SMatt Spinler class DBusWatcher 182a28c936SMatt Spinler { 192a28c936SMatt Spinler public: 202a28c936SMatt Spinler DBusWatcher() = delete; 212a28c936SMatt Spinler virtual ~DBusWatcher() = default; 222a28c936SMatt Spinler DBusWatcher(const DBusWatcher&) = default; 232a28c936SMatt Spinler DBusWatcher& operator=(const DBusWatcher&) = default; 242a28c936SMatt Spinler DBusWatcher(DBusWatcher&&) = default; 252a28c936SMatt Spinler DBusWatcher& operator=(DBusWatcher&&) = default; 262a28c936SMatt Spinler 272a28c936SMatt Spinler /** 282a28c936SMatt Spinler * @brief Constructor 292a28c936SMatt Spinler * 302a28c936SMatt Spinler * @param[in] path - The D-Bus path that will be watched 312a28c936SMatt Spinler * @param[in] interface - The D-Bus interface that will be watched 322a28c936SMatt Spinler */ DBusWatcher(const std::string & path,const std::string & interface)332a28c936SMatt Spinler DBusWatcher(const std::string& path, const std::string& interface) : 342a28c936SMatt Spinler _path(path), _interface(interface) 352544b419SPatrick Williams {} 362a28c936SMatt Spinler 372a28c936SMatt Spinler protected: 382a28c936SMatt Spinler /** 392a28c936SMatt Spinler * @brief The D-Bus path 402a28c936SMatt Spinler */ 412a28c936SMatt Spinler std::string _path; 422a28c936SMatt Spinler 432a28c936SMatt Spinler /** 442a28c936SMatt Spinler * @brief The D-Bus interface 452a28c936SMatt Spinler */ 462a28c936SMatt Spinler std::string _interface; 472a28c936SMatt Spinler 482a28c936SMatt Spinler /** 492a28c936SMatt Spinler * @brief The match objects for the propertiesChanged and 502a28c936SMatt Spinler * interfacesAdded signals. 512a28c936SMatt Spinler */ 522a28c936SMatt Spinler std::vector<sdbusplus::bus::match_t> _matches; 532a28c936SMatt Spinler }; 542a28c936SMatt Spinler 552a28c936SMatt Spinler /** 562a28c936SMatt Spinler * @class PropertyWatcher 572a28c936SMatt Spinler * 582a28c936SMatt Spinler * This class allows the user to be kept up to data with a D-Bus 592a28c936SMatt Spinler * property's value. It does this by calling a user specified function 602a28c936SMatt Spinler * that is passed the variant that contains the property's value when: 612a28c936SMatt Spinler * 622a28c936SMatt Spinler * 1) The property is read when the class is constructed, if 632a28c936SMatt Spinler * the property is on D-Bus at the time. 642a28c936SMatt Spinler * 2) The property changes (via a property changed signal). 652a28c936SMatt Spinler * 3) An interfacesAdded signal is received with that property. 662a28c936SMatt Spinler * 672a28c936SMatt Spinler * The DataInterface class is used to access D-Bus, and is a template 682a28c936SMatt Spinler * to avoid any circular include issues as that class is one of the 692a28c936SMatt Spinler * users of this one. 702a28c936SMatt Spinler */ 712a28c936SMatt Spinler template <typename DataIface> 722a28c936SMatt Spinler class PropertyWatcher : public DBusWatcher 732a28c936SMatt Spinler { 742a28c936SMatt Spinler public: 752a28c936SMatt Spinler PropertyWatcher() = delete; 762a28c936SMatt Spinler ~PropertyWatcher() = default; 772a28c936SMatt Spinler PropertyWatcher(const PropertyWatcher&) = delete; 782a28c936SMatt Spinler PropertyWatcher& operator=(const PropertyWatcher&) = delete; 792a28c936SMatt Spinler PropertyWatcher(PropertyWatcher&&) = delete; 802a28c936SMatt Spinler PropertyWatcher& operator=(PropertyWatcher&&) = delete; 812a28c936SMatt Spinler 822a28c936SMatt Spinler using PropertySetFunc = std::function<void(const DBusValue&)>; 832a28c936SMatt Spinler 842a28c936SMatt Spinler /** 852a28c936SMatt Spinler * @brief Constructor 862a28c936SMatt Spinler * 872a28c936SMatt Spinler * Reads the property if it is on D-Bus, and sets up the match 882a28c936SMatt Spinler * objects for the propertiesChanged and interfacesAdded signals. 892a28c936SMatt Spinler * 902a28c936SMatt Spinler * @param[in] bus - The sdbusplus bus object 912a28c936SMatt Spinler * @param[in] path - The D-Bus path of the property 922a28c936SMatt Spinler * @param[in] interface - The D-Bus interface that contains the property 932a28c936SMatt Spinler * @param[in] propertyName - The property name 94c1746f6aSMatt Spinler * @param[in] service - The D-Bus service to use for the property read. 95c1746f6aSMatt Spinler * Can be empty to look it up instead. 962a28c936SMatt Spinler * @param[in] dataIface - The DataInterface object 972a28c936SMatt Spinler * @param[in] func - The callback used any time the property is read 982a28c936SMatt Spinler */ PropertyWatcher(sdbusplus::bus_t & bus,const std::string & path,const std::string & interface,const std::string & propertyName,const std::string & service,const DataIface & dataIface,PropertySetFunc func)9945e83521SPatrick Williams PropertyWatcher(sdbusplus::bus_t& bus, const std::string& path, 1002a28c936SMatt Spinler const std::string& interface, 101c1746f6aSMatt Spinler const std::string& propertyName, const std::string& service, 102c1746f6aSMatt Spinler const DataIface& dataIface, PropertySetFunc func) : 103*075c7923SPatrick Williams DBusWatcher(path, interface), _name(propertyName), _setFunc(func) 1042a28c936SMatt Spinler { 1052a28c936SMatt Spinler _matches.emplace_back( 1062a28c936SMatt Spinler bus, match_rules::propertiesChanged(_path, _interface), 1072a28c936SMatt Spinler std::bind(std::mem_fn(&PropertyWatcher::propChanged), this, 1082a28c936SMatt Spinler std::placeholders::_1)); 1092a28c936SMatt Spinler 1102a28c936SMatt Spinler _matches.emplace_back( 1112a28c936SMatt Spinler bus, 1122a28c936SMatt Spinler match_rules::interfacesAdded() + match_rules::argNpath(0, _path), 1132a28c936SMatt Spinler std::bind(std::mem_fn(&PropertyWatcher::interfaceAdded), this, 1142a28c936SMatt Spinler std::placeholders::_1)); 11551e927ccSMatt Spinler 11651e927ccSMatt Spinler try 11751e927ccSMatt Spinler { 11851e927ccSMatt Spinler read(dataIface, service); 11951e927ccSMatt Spinler } 12045e83521SPatrick Williams catch (const sdbusplus::exception_t& e) 12151e927ccSMatt Spinler { 12251e927ccSMatt Spinler // Path doesn't exist now 12351e927ccSMatt Spinler } 1242a28c936SMatt Spinler } 1252a28c936SMatt Spinler 1262a28c936SMatt Spinler /** 127c1746f6aSMatt Spinler * @brief Constructor 128c1746f6aSMatt Spinler * 129c1746f6aSMatt Spinler * Reads the property if it is on D-Bus, and sets up the match 130c1746f6aSMatt Spinler * objects for the propertiesChanged and interfacesAdded signals. 131c1746f6aSMatt Spinler * 132c1746f6aSMatt Spinler * Unlike the other constructor, this contructor doesn't take the 133c1746f6aSMatt Spinler * service to use for the property read so it will look it up with 134c1746f6aSMatt Spinler * an ObjectMapper GetObject call. 135c1746f6aSMatt Spinler * 136c1746f6aSMatt Spinler * @param[in] bus - The sdbusplus bus object 137c1746f6aSMatt Spinler * @param[in] path - The D-Bus path of the property 138c1746f6aSMatt Spinler * @param[in] interface - The D-Bus interface that contains the property 139c1746f6aSMatt Spinler * @param[in] propertyName - The property name 140c1746f6aSMatt Spinler * @param[in] dataIface - The DataInterface object 141c1746f6aSMatt Spinler * @param[in] func - The callback used any time the property is read 142c1746f6aSMatt Spinler */ PropertyWatcher(sdbusplus::bus_t & bus,const std::string & path,const std::string & interface,const std::string & propertyName,const DataIface & dataIface,PropertySetFunc func)14345e83521SPatrick Williams PropertyWatcher(sdbusplus::bus_t& bus, const std::string& path, 144c1746f6aSMatt Spinler const std::string& interface, 145c1746f6aSMatt Spinler const std::string& propertyName, const DataIface& dataIface, 146c1746f6aSMatt Spinler PropertySetFunc func) : 147c1746f6aSMatt Spinler PropertyWatcher(bus, path, interface, propertyName, "", dataIface, func) 1482544b419SPatrick Williams {} 149c1746f6aSMatt Spinler 150c1746f6aSMatt Spinler /** 1512a28c936SMatt Spinler * @brief Reads the property on D-Bus, and calls 1522a28c936SMatt Spinler * the user defined function with the value. 1532a28c936SMatt Spinler * 154c1746f6aSMatt Spinler * If the passed in service is empty, look up the service to use. 155c1746f6aSMatt Spinler * 1562a28c936SMatt Spinler * @param[in] dataIface - The DataInterface object 157c1746f6aSMatt Spinler * @param[in] service - The D-Bus service to make the getProperty 158c1746f6aSMatt Spinler * call with, if not empty 1592a28c936SMatt Spinler */ read(const DataIface & dataIface,std::string service)160c1746f6aSMatt Spinler void read(const DataIface& dataIface, std::string service) 1612a28c936SMatt Spinler { 162c1746f6aSMatt Spinler if (service.empty()) 163c1746f6aSMatt Spinler { 164c1746f6aSMatt Spinler service = dataIface.getService(_path, _interface); 165c1746f6aSMatt Spinler } 166c1746f6aSMatt Spinler 1672a28c936SMatt Spinler if (!service.empty()) 1682a28c936SMatt Spinler { 1692a28c936SMatt Spinler DBusValue value; 1702a28c936SMatt Spinler dataIface.getProperty(service, _path, _interface, _name, value); 1712a28c936SMatt Spinler 1722a28c936SMatt Spinler _setFunc(value); 1732a28c936SMatt Spinler } 1742a28c936SMatt Spinler } 1752a28c936SMatt Spinler 1762a28c936SMatt Spinler /** 1772a28c936SMatt Spinler * @brief The propertiesChanged callback 1782a28c936SMatt Spinler * 1792a28c936SMatt Spinler * Calls the user defined function with the property value 1802a28c936SMatt Spinler * 1812a28c936SMatt Spinler * @param[in] msg - The sdbusplus message object 1822a28c936SMatt Spinler */ propChanged(sdbusplus::message_t & msg)18345e83521SPatrick Williams void propChanged(sdbusplus::message_t& msg) 1842a28c936SMatt Spinler { 1852a28c936SMatt Spinler DBusInterface interface; 1862a28c936SMatt Spinler DBusPropertyMap properties; 1872a28c936SMatt Spinler 1882a28c936SMatt Spinler msg.read(interface, properties); 1892a28c936SMatt Spinler 1902a28c936SMatt Spinler auto prop = properties.find(_name); 1912a28c936SMatt Spinler if (prop != properties.end()) 1922a28c936SMatt Spinler { 1932a28c936SMatt Spinler _setFunc(prop->second); 1942a28c936SMatt Spinler } 1952a28c936SMatt Spinler } 1962a28c936SMatt Spinler 1972a28c936SMatt Spinler /** 1982a28c936SMatt Spinler * @brief The interfacesAdded callback 1992a28c936SMatt Spinler * 2002a28c936SMatt Spinler * Calls the user defined function with the property value 2012a28c936SMatt Spinler * 2022a28c936SMatt Spinler * @param[in] msg - The sdbusplus message object 2032a28c936SMatt Spinler */ interfaceAdded(sdbusplus::message_t & msg)20445e83521SPatrick Williams void interfaceAdded(sdbusplus::message_t& msg) 2052a28c936SMatt Spinler { 2062a28c936SMatt Spinler sdbusplus::message::object_path path; 2072a28c936SMatt Spinler DBusInterfaceMap interfaces; 2082a28c936SMatt Spinler 2092a28c936SMatt Spinler msg.read(path, interfaces); 2102a28c936SMatt Spinler 2112a28c936SMatt Spinler auto iface = interfaces.find(_interface); 2122a28c936SMatt Spinler if (iface != interfaces.end()) 2132a28c936SMatt Spinler { 2142a28c936SMatt Spinler auto prop = iface->second.find(_name); 2152a28c936SMatt Spinler if (prop != iface->second.end()) 2162a28c936SMatt Spinler { 2172a28c936SMatt Spinler _setFunc(prop->second); 2182a28c936SMatt Spinler } 2192a28c936SMatt Spinler } 2202a28c936SMatt Spinler } 2212a28c936SMatt Spinler 2222a28c936SMatt Spinler private: 2232a28c936SMatt Spinler /** 2242a28c936SMatt Spinler * @brief The D-Bus property name 2252a28c936SMatt Spinler */ 2262a28c936SMatt Spinler std::string _name; 2272a28c936SMatt Spinler 2282a28c936SMatt Spinler /** 2292a28c936SMatt Spinler * @brief The function that will be called any time the 2302a28c936SMatt Spinler * property is read. 2312a28c936SMatt Spinler */ 2322a28c936SMatt Spinler PropertySetFunc _setFunc; 2332a28c936SMatt Spinler }; 2342a28c936SMatt Spinler 2352a28c936SMatt Spinler /** 2362a28c936SMatt Spinler * @class InterfaceWatcher 2372a28c936SMatt Spinler * 2382a28c936SMatt Spinler * This class allows the user to be kept up to data with a D-Bus 2392a28c936SMatt Spinler * interface's properties.. It does this by calling a user specified 2402a28c936SMatt Spinler * function that is passed a map of the D-Bus property names and values 2412a28c936SMatt Spinler * on that interface when: 2422a28c936SMatt Spinler * 2432a28c936SMatt Spinler * 1) The interface is read when the class is constructed, if 2442a28c936SMatt Spinler * the interface is on D-Bus at the time. 2452a28c936SMatt Spinler * 2) The interface has a property that changes (via a property changed signal). 2462a28c936SMatt Spinler * 3) An interfacesAdded signal is received. 2472a28c936SMatt Spinler * 2482a28c936SMatt Spinler * The DataInterface class is used to access D-Bus, and is a template 2492a28c936SMatt Spinler * to avoid any circular include issues as that class is one of the 2502a28c936SMatt Spinler * users of this one. 2512a28c936SMatt Spinler */ 2522a28c936SMatt Spinler template <typename DataIface> 2532a28c936SMatt Spinler class InterfaceWatcher : public DBusWatcher 2542a28c936SMatt Spinler { 2552a28c936SMatt Spinler public: 2562a28c936SMatt Spinler InterfaceWatcher() = delete; 2572a28c936SMatt Spinler ~InterfaceWatcher() = default; 2582a28c936SMatt Spinler InterfaceWatcher(const InterfaceWatcher&) = delete; 2592a28c936SMatt Spinler InterfaceWatcher& operator=(const InterfaceWatcher&) = delete; 2602a28c936SMatt Spinler InterfaceWatcher(InterfaceWatcher&&) = delete; 2612a28c936SMatt Spinler InterfaceWatcher& operator=(InterfaceWatcher&&) = delete; 2622a28c936SMatt Spinler 2632a28c936SMatt Spinler using InterfaceSetFunc = std::function<void(const DBusPropertyMap&)>; 2642a28c936SMatt Spinler 2652a28c936SMatt Spinler /** 2662a28c936SMatt Spinler * @brief Constructor 2672a28c936SMatt Spinler * 2682a28c936SMatt Spinler * Reads all properties on the interface if it is on D-Bus, 2692a28c936SMatt Spinler * and sets up the match objects for the propertiesChanged 2702a28c936SMatt Spinler * and interfacesAdded signals. 2712a28c936SMatt Spinler * 2722a28c936SMatt Spinler * @param[in] bus - The sdbusplus bus object 2732a28c936SMatt Spinler * @param[in] path - The D-Bus path of the property 2742a28c936SMatt Spinler * @param[in] interface - The D-Bus interface that contains the property 2752a28c936SMatt Spinler * @param[in] dataIface - The DataInterface object 2762a28c936SMatt Spinler * @param[in] func - The callback used any time the property is read 2772a28c936SMatt Spinler */ InterfaceWatcher(sdbusplus::bus_t & bus,const std::string & path,const std::string & interface,const DataIface & dataIface,InterfaceSetFunc func)27845e83521SPatrick Williams InterfaceWatcher(sdbusplus::bus_t& bus, const std::string& path, 2792a28c936SMatt Spinler const std::string& interface, const DataIface& dataIface, 2802a28c936SMatt Spinler InterfaceSetFunc func) : 281*075c7923SPatrick Williams DBusWatcher(path, interface), _setFunc(func) 2822a28c936SMatt Spinler { 2832a28c936SMatt Spinler _matches.emplace_back( 2842a28c936SMatt Spinler bus, match_rules::propertiesChanged(_path, _interface), 2852a28c936SMatt Spinler std::bind(std::mem_fn(&InterfaceWatcher::propChanged), this, 2862a28c936SMatt Spinler std::placeholders::_1)); 2872a28c936SMatt Spinler 2882a28c936SMatt Spinler _matches.emplace_back( 2892a28c936SMatt Spinler bus, 2902a28c936SMatt Spinler match_rules::interfacesAdded() + match_rules::argNpath(0, _path), 2912a28c936SMatt Spinler std::bind(std::mem_fn(&InterfaceWatcher::interfaceAdded), this, 2922a28c936SMatt Spinler std::placeholders::_1)); 29351e927ccSMatt Spinler 29451e927ccSMatt Spinler try 29551e927ccSMatt Spinler { 29651e927ccSMatt Spinler read(dataIface); 29751e927ccSMatt Spinler } 29845e83521SPatrick Williams catch (const sdbusplus::exception_t& e) 29951e927ccSMatt Spinler { 30051e927ccSMatt Spinler // Path doesn't exist now 30151e927ccSMatt Spinler } 3022a28c936SMatt Spinler } 3032a28c936SMatt Spinler 3042a28c936SMatt Spinler /** 3052a28c936SMatt Spinler * @brief Reads the interface's properties on D-Bus, and 3062a28c936SMatt Spinler * calls the the user defined function with the property map. 3072a28c936SMatt Spinler * 3082a28c936SMatt Spinler * @param[in] dataIface - The DataInterface object 3092a28c936SMatt Spinler */ read(const DataIface & dataIface)3102a28c936SMatt Spinler void read(const DataIface& dataIface) 3112a28c936SMatt Spinler { 3122a28c936SMatt Spinler auto service = dataIface.getService(_path, _interface); 3132a28c936SMatt Spinler if (!service.empty()) 3142a28c936SMatt Spinler { 315*075c7923SPatrick Williams auto properties = 316*075c7923SPatrick Williams dataIface.getAllProperties(service, _path, _interface); 3172a28c936SMatt Spinler 3182a28c936SMatt Spinler _setFunc(properties); 3192a28c936SMatt Spinler } 3202a28c936SMatt Spinler } 3212a28c936SMatt Spinler 3222a28c936SMatt Spinler /** 3232a28c936SMatt Spinler * @brief The propertiesChanged callback 3242a28c936SMatt Spinler * 3252a28c936SMatt Spinler * Calls the user defined function with the property map. Only the 3262a28c936SMatt Spinler * properties that changed will be in the map. 3272a28c936SMatt Spinler * 3282a28c936SMatt Spinler * @param[in] msg - The sdbusplus message object 3292a28c936SMatt Spinler */ propChanged(sdbusplus::message_t & msg)33045e83521SPatrick Williams void propChanged(sdbusplus::message_t& msg) 3312a28c936SMatt Spinler { 3322a28c936SMatt Spinler DBusInterface interface; 3332a28c936SMatt Spinler DBusPropertyMap properties; 3342a28c936SMatt Spinler 3352a28c936SMatt Spinler msg.read(interface, properties); 3362a28c936SMatt Spinler 3372a28c936SMatt Spinler _setFunc(properties); 3382a28c936SMatt Spinler } 3392a28c936SMatt Spinler 3402a28c936SMatt Spinler /** 3412a28c936SMatt Spinler * @brief The interfacesAdded callback 3422a28c936SMatt Spinler * 3432a28c936SMatt Spinler * Calls the user defined function with the property map 3442a28c936SMatt Spinler * 3452a28c936SMatt Spinler * @param[in] msg - The sdbusplus message object 3462a28c936SMatt Spinler */ interfaceAdded(sdbusplus::message_t & msg)34745e83521SPatrick Williams void interfaceAdded(sdbusplus::message_t& msg) 3482a28c936SMatt Spinler { 3492a28c936SMatt Spinler sdbusplus::message::object_path path; 3502a28c936SMatt Spinler DBusInterfaceMap interfaces; 3512a28c936SMatt Spinler 3522a28c936SMatt Spinler msg.read(path, interfaces); 3532a28c936SMatt Spinler 3542a28c936SMatt Spinler auto iface = interfaces.find(_interface); 3552a28c936SMatt Spinler if (iface != interfaces.end()) 3562a28c936SMatt Spinler { 3572a28c936SMatt Spinler _setFunc(iface->second); 3582a28c936SMatt Spinler } 3592a28c936SMatt Spinler } 3602a28c936SMatt Spinler 3612a28c936SMatt Spinler private: 3622a28c936SMatt Spinler /** 3632a28c936SMatt Spinler * @brief The function that will be called any time the 3642a28c936SMatt Spinler * interface is read. 3652a28c936SMatt Spinler */ 3662a28c936SMatt Spinler InterfaceSetFunc _setFunc; 3672a28c936SMatt Spinler }; 3682a28c936SMatt Spinler 3692a28c936SMatt Spinler } // namespace openpower::pels 370