1 #pragma once 2 3 #include "types.hpp" 4 #include <phosphor-logging/log.hpp> 5 6 namespace phosphor 7 { 8 namespace fan 9 { 10 namespace control 11 { 12 class Zone; 13 14 using namespace phosphor::logging; 15 16 /** 17 * @brief Create a handler function object 18 * 19 * @param[in] handler - The handler being created 20 * 21 * @return - The created handler function object 22 */ 23 template <typename T> 24 auto make_handler(T&& handler) 25 { 26 return Handler(std::forward<T>(handler)); 27 } 28 29 /** 30 * @brief Create an action function object 31 * 32 * @param[in] action - The action being created 33 * 34 * @return - The created action function object 35 */ 36 template <typename T> 37 auto make_action(T&& action) 38 { 39 return Action(std::forward<T>(action)); 40 } 41 42 /** 43 * @struct Property Changed 44 * @brief A match filter functor for Dbus property value changed signals 45 * 46 * @tparam T - The type of the property value 47 * @tparam U - The type of the handler 48 */ 49 template <typename T, typename U> 50 struct PropertyChanged 51 { 52 PropertyChanged() = delete; 53 ~PropertyChanged() = default; 54 PropertyChanged(const PropertyChanged&) = default; 55 PropertyChanged& operator=(const PropertyChanged&) = default; 56 PropertyChanged(PropertyChanged&&) = default; 57 PropertyChanged& operator=(PropertyChanged&&) = default; 58 PropertyChanged(const char* iface, 59 const char* property, 60 U&& handler) : 61 _iface(iface), 62 _property(property), 63 _handler(std::forward<U>(handler)) { } 64 65 /** @brief Run signal handler function 66 * 67 * Extract the property from the PropertiesChanged 68 * message and run the handler function. 69 */ 70 void operator()(sdbusplus::bus::bus&, 71 sdbusplus::message::message& msg, 72 Zone& zone) const 73 { 74 std::map<std::string, sdbusplus::message::variant<T>> properties; 75 const char* iface = nullptr; 76 77 msg.read(iface); 78 if (!iface || strcmp(iface, _iface)) 79 { 80 return; 81 } 82 83 msg.read(properties); 84 auto it = properties.find(_property); 85 if (it == properties.cend()) 86 { 87 log<level::ERR>("Unable to find property on interface", 88 entry("PROPERTY=%s", _property), 89 entry("INTERFACE=%s", _iface)); 90 return; 91 } 92 93 _handler(zone, std::forward<T>(it->second.template get<T>())); 94 } 95 96 private: 97 const char* _iface; 98 const char* _property; 99 U _handler; 100 }; 101 102 /** 103 * @brief Used to process a Dbus property changed signal event 104 * 105 * @param[in] iface - Sensor value interface 106 * @param[in] property - Sensor value property 107 * @param[in] handler - Handler function to perform 108 * 109 * @tparam T - The type of the property 110 * @tparam U - The type of the handler 111 */ 112 template <typename T, typename U> 113 auto propertySignal(const char* iface, 114 const char* property, 115 U&& handler) 116 { 117 return PropertyChanged<T, U>(iface, property, std::forward<U>(handler)); 118 } 119 120 /** 121 * @struct Interface Added 122 * @brief A match filter functor for Dbus interface added signals 123 * 124 * @tparam T - The type of the property value 125 * @tparam U - The type of the handler 126 */ 127 template <typename T, typename U> 128 struct InterfaceAdded 129 { 130 InterfaceAdded() = delete; 131 ~InterfaceAdded() = default; 132 InterfaceAdded(const InterfaceAdded&) = default; 133 InterfaceAdded& operator=(const InterfaceAdded&) = default; 134 InterfaceAdded(InterfaceAdded&&) = default; 135 InterfaceAdded& operator=(InterfaceAdded&&) = default; 136 InterfaceAdded(const char* path, 137 const char* iface, 138 const char* property, 139 U&& handler) : 140 _path(path), 141 _iface(iface), 142 _property(property), 143 _handler(std::forward<U>(handler)) { } 144 145 /** @brief Run signal handler function 146 * 147 * Extract the property from the InterfacesAdded 148 * message and run the handler function. 149 */ 150 void operator()(sdbusplus::bus::bus&, 151 sdbusplus::message::message& msg, 152 Zone& zone) const 153 { 154 std::map<std::string, 155 std::map<std::string, 156 sdbusplus::message::variant<T>>> intfProp; 157 sdbusplus::message::object_path op; 158 159 msg.read(op); 160 auto objPath = static_cast<const std::string&>(op).c_str(); 161 if (!objPath || strcmp(objPath, _path)) 162 { 163 // Object path does not match this handler's path 164 return; 165 } 166 167 msg.read(intfProp); 168 auto itIntf = intfProp.find(_iface); 169 if (itIntf == intfProp.cend()) 170 { 171 // Interface not found on this handler's path 172 return; 173 } 174 auto itProp = itIntf->second.find(_property); 175 if (itProp == itIntf->second.cend()) 176 { 177 // Property not found on this handler's path 178 return; 179 } 180 181 _handler(zone, std::forward<T>(itProp->second.template get<T>())); 182 } 183 184 private: 185 const char* _path; 186 const char* _iface; 187 const char* _property; 188 U _handler; 189 }; 190 191 /** 192 * @brief Used to process a Dbus interface added signal event 193 * 194 * @param[in] path - Object path 195 * @param[in] iface - Object interface 196 * @param[in] property - Object property 197 * @param[in] handler - Handler function to perform 198 * 199 * @tparam T - The type of the property 200 * @tparam U - The type of the handler 201 */ 202 template <typename T, typename U> 203 auto objectSignal(const char* path, 204 const char* iface, 205 const char* property, 206 U&& handler) 207 { 208 return InterfaceAdded<T, U>(path, 209 iface, 210 property, 211 std::forward<U>(handler)); 212 } 213 214 } // namespace control 215 } // namespace fan 216 } // namespace phosphor 217