summaryrefslogtreecommitdiffstats
path: root/monitor/tach_sensor.cpp
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2017-04-27 14:21:48 -0500
committerMatt Spinler <spinler@us.ibm.com>2017-05-11 13:52:50 -0500
commitebaae6115ff5248d7f46d065ca96229c1f4e583d (patch)
tree2c8771ab9f47db9c3a07aceb5cb2bba533346ba8 /monitor/tach_sensor.cpp
parentabf8da369cb1e7094cc00295131502c73ed5cbc1 (diff)
downloadphosphor-fan-presence-ebaae6115ff5248d7f46d065ca96229c1f4e583d.tar.gz
phosphor-fan-presence-ebaae6115ff5248d7f46d065ca96229c1f4e583d.zip
Add dbus support to TachSensor
TachSensor will match on properties changed signals for the Value and Target properties. When these occur, it will load in those properties and then tell the Fan class there was a change. Also, TachSensor will read in the Target property during construction so it will have a valid value to check against right away. Change-Id: I2dc2cacf5804826c6b0e0ea91196cbdaa4d5b893 Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Diffstat (limited to 'monitor/tach_sensor.cpp')
-rw-r--r--monitor/tach_sensor.cpp190
1 files changed, 189 insertions, 1 deletions
diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp
index 3264ddf..c991bb6 100644
--- a/monitor/tach_sensor.cpp
+++ b/monitor/tach_sensor.cpp
@@ -25,7 +25,59 @@ namespace fan
namespace monitor
{
+constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
+constexpr auto FAN_SENSOR_CONTROL_INTF = "xyz.openbmc_project.Control.FanSpeed";
+constexpr auto FAN_SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
+constexpr auto FAN_TARGET_PROPERTY = "Target";
+constexpr auto FAN_VALUE_PROPERTY = "Value";
+
+
+/**
+ * @brief Helper function to read a property
+ *
+ * @param[in] interface - the interface the property is on
+ * @param[in] propertName - the name of the property
+ * @param[in] path - the dbus path
+ * @param[in] service - the dbus service
+ * @param[in] bus - the dbus object
+ * @param[out] value - filled in with the property value
+ */
+template<typename T>
+static void readProperty(const std::string& interface,
+ const std::string& propertyName,
+ const std::string& path,
+ const std::string& service,
+ sdbusplus::bus::bus& bus,
+ T& value)
+{
+ sdbusplus::message::variant<T> property;
+
+ try
+ {
+ auto method = bus.new_method_call(service.c_str(),
+ path.c_str(),
+ PROPERTY_INTF,
+ "Get");
+
+ method.append(interface, propertyName);
+
+ auto reply = bus.call(method);
+ if (reply.is_method_error())
+ {
+ throw std::runtime_error(
+ "Error in property get call for path " +
+ path);
+ }
+
+ reply.read(property);
+ value = sdbusplus::message::variant_ns::get<T>(property);
+ }
+ catch (std::exception& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+ }
+}
TachSensor::TachSensor(sdbusplus::bus::bus& bus,
@@ -40,7 +92,143 @@ TachSensor::TachSensor(sdbusplus::bus::bus& bus,
_hasTarget(hasTarget),
_timeout(timeout)
{
- //TODO
+ auto service = getService();
+
+ //Load in starting Target and Input values
+ readProperty(FAN_SENSOR_VALUE_INTF,
+ FAN_VALUE_PROPERTY,
+ _name,
+ service,
+ _bus,
+ _tachInput);
+
+ if (_hasTarget)
+ {
+ readProperty(FAN_SENSOR_CONTROL_INTF,
+ FAN_TARGET_PROPERTY,
+ _name,
+ service,
+ _bus,
+ _tachTarget);
+ }
+
+ auto match = getMatchString(FAN_SENSOR_VALUE_INTF);
+
+ tachSignal = std::make_unique<sdbusplus::server::match::match>(
+ _bus,
+ match.c_str(),
+ handleTachChangeSignal,
+ this);
+
+ if (_hasTarget)
+ {
+ match = getMatchString(FAN_SENSOR_CONTROL_INTF);
+
+ targetSignal = std::make_unique<sdbusplus::server::match::match>(
+ _bus,
+ match.c_str(),
+ handleTargetChangeSignal,
+ this);
+ }
+
+}
+
+
+//Can cache this value after openbmc/openbmc#1496 is resolved
+std::string TachSensor::getService()
+{
+ return phosphor::fan::util::getService(_name,
+ FAN_SENSOR_CONTROL_INTF,
+ _bus);
+}
+
+
+std::string TachSensor::getMatchString(const std::string& interface)
+{
+ return std::string("type='signal',"
+ "interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged',"
+ "arg0namespace='" + interface + "',"
+ "path='" + _name + "'");
+}
+
+
+int TachSensor::handleTachChangeSignal(sd_bus_message* msg,
+ void* usrData,
+ sd_bus_error* err)
+{
+ auto m = sdbusplus::message::message(msg);
+ static_cast<TachSensor*>(usrData)->handleTachChange(m, err);
+ return 0;
+}
+
+
+int TachSensor::handleTargetChangeSignal(sd_bus_message* msg,
+ void* usrData,
+ sd_bus_error* err)
+{
+ auto m = sdbusplus::message::message(msg);
+ static_cast<TachSensor*>(usrData)->handleTargetChange(m, err);
+ return 0;
+}
+
+
+/**
+ * @brief Reads a property from the input message and stores it in value.
+ * T is the value type.
+ *
+ * Note: This can only be called once per message.
+ *
+ * @param[in] msg - the dbus message that contains the data
+ * @param[in] interface - the interface the property is on
+ * @param[in] propertName - the name of the property
+ * @param[out] value - the value to store the property value in
+ */
+template<typename T>
+static void readPropertyFromMessage(sdbusplus::message::message& msg,
+ const std::string& interface,
+ const std::string& propertyName,
+ T& value)
+{
+ std::string sensor;
+ std::map<std::string, sdbusplus::message::variant<T>> data;
+ msg.read(sensor, data);
+
+ if (sensor.compare(interface) == 0)
+ {
+ auto propertyMap = data.find(propertyName);
+ if (propertyMap != data.end())
+ {
+ value = sdbusplus::message::variant_ns::get<T>(
+ propertyMap->second);
+ }
+ }
+}
+
+
+void TachSensor::handleTargetChange(sdbusplus::message::message& msg,
+ sd_bus_error* err)
+{
+ readPropertyFromMessage(msg,
+ FAN_SENSOR_CONTROL_INTF,
+ FAN_TARGET_PROPERTY,
+ _tachTarget);
+
+ //Check all tach sensors on the fan against the target
+ _fan.tachChanged();
+}
+
+
+void TachSensor::handleTachChange(sdbusplus::message::message& msg,
+ sd_bus_error* err)
+{
+ readPropertyFromMessage(msg,
+ FAN_SENSOR_VALUE_INTF,
+ FAN_VALUE_PROPERTY,
+ _tachInput);
+
+ //Check just this sensor against the target
+ _fan.tachChanged(*this);
}
OpenPOWER on IntegriCloud