summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--control/functor.hpp109
-rw-r--r--control/handlers.hpp35
-rw-r--r--control/types.hpp18
-rw-r--r--control/zone.cpp36
-rw-r--r--control/zone.hpp50
5 files changed, 247 insertions, 1 deletions
diff --git a/control/functor.hpp b/control/functor.hpp
new file mode 100644
index 0000000..f2f3a78
--- /dev/null
+++ b/control/functor.hpp
@@ -0,0 +1,109 @@
+#pragma once
+
+#include "types.hpp"
+#include <phosphor-logging/log.hpp>
+
+namespace phosphor
+{
+namespace fan
+{
+namespace control
+{
+class Zone;
+
+using namespace phosphor::logging;
+
+/**
+ * @brief Create a handler function object
+ *
+ * @param[in] handler - The handler being created
+ *
+ * @return - The created handler function object
+ */
+template <typename T>
+auto make_handler(T&& handler)
+{
+ return Handler(std::forward<T>(handler));
+}
+
+/**
+ * @struct Property Changed
+ * @brief A match filter functor for Dbus property value changed signals
+ *
+ * @tparam T - The type of the property value
+ * @tparam U - The type of the handler
+ */
+template <typename T, typename U>
+struct PropertyChanged
+{
+ PropertyChanged() = delete;
+ ~PropertyChanged() = default;
+ PropertyChanged(const PropertyChanged&) = default;
+ PropertyChanged& operator=(const PropertyChanged&) = default;
+ PropertyChanged(PropertyChanged&&) = default;
+ PropertyChanged& operator=(PropertyChanged&&) = default;
+ PropertyChanged(const char* iface,
+ const char* property,
+ U&& handler) :
+ _iface(iface),
+ _property(property),
+ _handler(std::forward<U>(handler)) { }
+
+ /** @brief Run signal handler function
+ *
+ * Extract the property from the PropertiesChanged
+ * message and run the handler function.
+ */
+ void operator()(sdbusplus::bus::bus&,
+ sdbusplus::message::message& msg,
+ Zone& zone) const
+ {
+ std::map<std::string, sdbusplus::message::variant<T>> properties;
+ const char* iface = nullptr;
+
+ msg.read(iface);
+ if (!iface || strcmp(iface, _iface))
+ {
+ return;
+ }
+
+ msg.read(properties);
+ auto it = properties.find(_property);
+ if (it == properties.cend())
+ {
+ log<level::ERR>("Unable to find property on interface",
+ entry("PROPERTY=%s", _property),
+ entry("INTERFACE=%s", _iface));
+ return;
+ }
+
+ _handler(zone, std::forward<T>(it->second.template get<T>()));
+ }
+
+private:
+ const char* _iface;
+ const char* _property;
+ U _handler;
+};
+
+/**
+ * @brief Used to process a Dbus property changed signal event
+ *
+ * @param[in] iface - Sensor value interface
+ * @param[in] property - Sensor value property
+ * @param[in] handler - Handler function to perform
+ *
+ * @tparam T - The type of the property
+ * @tparam U - The type of the handler
+ */
+template <typename T, typename U>
+auto propertySignal(const char* iface,
+ const char* property,
+ U&& handler)
+{
+ return PropertyChanged<T, U>(iface, property, std::forward<U>(handler));
+}
+
+} // namespace control
+} // namespace fan
+} // namespace phosphor
diff --git a/control/handlers.hpp b/control/handlers.hpp
new file mode 100644
index 0000000..0503c53
--- /dev/null
+++ b/control/handlers.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+namespace phosphor
+{
+namespace fan
+{
+namespace control
+{
+namespace handler
+{
+
+/**
+ * @brief A handler function to set/update a property
+ * @details Sets or updates a property's value determined by a combination of
+ * an object's path and property names
+ *
+ * @param[in] path - Object's path name
+ * @param[in] property - Object's property name
+ *
+ * @return Lambda function
+ * A lambda function to set/update the property value
+ */
+template <typename T>
+auto setProperty(const char* path, const char* property)
+{
+ return [=](auto& zone, T&& arg)
+ {
+ zone.setPropertyValue(path, property, std::forward<T>(arg));
+ };
+}
+
+} // namespace handler
+} // namespace control
+} // namespace fan
+} // namespace phosphor
diff --git a/control/types.hpp b/control/types.hpp
index e4c3725..bbbac61 100644
--- a/control/types.hpp
+++ b/control/types.hpp
@@ -10,6 +10,8 @@ namespace fan
namespace control
{
+class Zone;
+
//Placeholder. Conditions are completely TBD.
using Condition = bool;
@@ -17,12 +19,26 @@ constexpr auto fanNamePos = 0;
constexpr auto sensorListPos = 1;
using FanDefinition = std::tuple<std::string, std::vector<std::string>>;
+using Handler = std::function<void(sdbusplus::bus::bus&,
+ sdbusplus::message::message&,
+ Zone&)>;
+
+constexpr auto signaturePos = 0;
+constexpr auto handlerObjPos = 1;
+using PropertyChange = std::tuple<std::string, Handler>;
+using SetSpeedEvent = std::vector<PropertyChange>;
+
+constexpr auto zoneObjPos = 0;
+using SignalEvent = std::tuple<Zone*, Handler>;
+
constexpr auto zoneNumPos = 0;
constexpr auto fullSpeedPos = 1;
constexpr auto fanListPos = 2;
+constexpr auto setSpeedEventsPos = 3;
using ZoneDefinition = std::tuple<size_t,
unsigned int,
- std::vector<FanDefinition>>;
+ std::vector<FanDefinition>,
+ std::vector<SetSpeedEvent>>;
constexpr auto conditionListPos = 0;
constexpr auto zoneListPos = 1;
diff --git a/control/zone.cpp b/control/zone.cpp
index 1e50060..28b81f9 100644
--- a/control/zone.cpp
+++ b/control/zone.cpp
@@ -35,6 +35,22 @@ Zone::Zone(sdbusplus::bus::bus& bus,
{
_fans.emplace_back(std::make_unique<Fan>(bus, def));
}
+
+ // Setup signal trigger for property changes
+ for (auto& event : std::get<setSpeedEventsPos>(def))
+ {
+ for (auto& prop : event)
+ {
+ _signalEvents.emplace_back(
+ std::make_unique<SignalEvent>(this,
+ std::get<handlerObjPos>(prop)
+ ));
+ _matches.emplace_back(bus,
+ std::get<signaturePos>(prop).c_str(),
+ signalHandler,
+ _signalEvents.back().get());
+ }
+ }
}
@@ -46,6 +62,26 @@ void Zone::setSpeed(uint64_t speed)
}
}
+int Zone::signalHandler(sd_bus_message* msg,
+ void* data,
+ sd_bus_error* err)
+{
+ auto sdbpMsg = sdbusplus::message::message(msg);
+ auto& signalEvent = *static_cast<SignalEvent*>(data);
+ std::get<zoneObjPos>(signalEvent)->handleEvent(
+ sdbpMsg,
+ std::get<handlerObjPos>(signalEvent));
+ return 0;
+}
+
+void Zone::handleEvent(sdbusplus::message::message& msg,
+ const Handler& handler)
+{
+ // Handle the callback
+ handler(_bus, msg, *this);
+}
+
+
}
}
}
diff --git a/control/zone.hpp b/control/zone.hpp
index 985a46d..601c002 100644
--- a/control/zone.hpp
+++ b/control/zone.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <vector>
#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server.hpp>
#include "fan.hpp"
#include "types.hpp"
@@ -56,6 +57,20 @@ class Zone
}
}
+ /**
+ * @brief Sets a given object's property value
+ *
+ * @param[in] object - Name of the object containing the property
+ * @param[in] property - Property name
+ * @param[in] value - Property value
+ */
+ void setPropertyValue(const char* object,
+ const char* property,
+ bool value)
+ {
+ _properties[object][property] = value;
+ };
+
private:
/**
@@ -77,6 +92,41 @@ class Zone
* The vector of fans in this zone
*/
std::vector<std::unique_ptr<Fan>> _fans;
+
+ /**
+ * @brief Map of object property values
+ */
+ std::map<std::string, std::map<std::string, bool>> _properties;
+
+ /**
+ * @brief List of signal event arguments
+ */
+ std::vector<std::unique_ptr<SignalEvent>> _signalEvents;
+
+ /**
+ * @brief list of Dbus matches for callbacks
+ */
+ std::vector<sdbusplus::server::match::match> _matches;
+
+ /**
+ * @brief Dbus signal change handler
+ *
+ * @param[in] msg - Data associated with the subscribed signal
+ * @param[in] data - Pointer to the event sensor's data
+ * @param[in] err - Contains any sdbus error reference if occurred
+ */
+ static int signalHandler(sd_bus_message* msg,
+ void* data,
+ sd_bus_error* err);
+
+ /**
+ * @brief Envokes the assigned handler and action
+ *
+ * @param[in] msg - Expanded sdbusplus message data
+ * @param[in] eventData - The event's data
+ */
+ void handleEvent(sdbusplus::message::message& msg,
+ const Handler& handler);
};
}
OpenPOWER on IntegriCloud