Add fan pwm interface target

The current daemon only supports RPM-based fan control, whereas the
hwmon interface for PWM is often present.  This implements the Fan
Control PWM dbus interface.

This CL is not the complete solution, but if mixed with a follow-on CL
that does this, I think it'll be ideal.  For instance, this assumes the
pwm number matches, whereas the other CL lets you specify the
corresponding PWM target for the fan.

Change-Id: I23aaa0619cdefba0a004ac0d26dc6b928e78f1e8
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/fan_pwm.cpp b/fan_pwm.cpp
new file mode 100644
index 0000000..04cb1b5
--- /dev/null
+++ b/fan_pwm.cpp
@@ -0,0 +1,63 @@
+#include "env.hpp"
+#include "fan_pwm.hpp"
+#include "hwmon.hpp"
+#include "sensorset.hpp"
+#include "sysfs.hpp"
+
+#include <phosphor-logging/elog-errors.hpp>
+#include <xyz/openbmc_project/Control/Device/error.hpp>
+
+#include <experimental/filesystem>
+#include <string>
+
+using namespace phosphor::logging;
+
+namespace hwmon
+{
+
+uint64_t FanPwm::target(uint64_t value)
+{
+    auto curValue = FanPwmObject::target();
+    using namespace std::literals;
+
+    if (curValue != value)
+    {
+        std::string empty;
+        //Write target out to sysfs
+        try {
+            ioAccess.write(
+                value,
+                type,
+                id,
+                empty,
+                sysfs::hwmonio::retries,
+                sysfs::hwmonio::delay);
+        }
+        catch (const std::system_error& e)
+        {
+            using namespace sdbusplus::xyz::openbmc_project::Control::
+                Device::Error;
+            report<WriteFailure>(
+                    xyz::openbmc_project::Control::Device::
+                        WriteFailure::CALLOUT_ERRNO(e.code().value()),
+                    xyz::openbmc_project::Control::Device::
+                        WriteFailure::CALLOUT_DEVICE_PATH(devPath.c_str()));
+
+            auto file = sysfs::make_sysfs_path(
+                    ioAccess.path(),
+                    type,
+                    id,
+                    empty);
+
+            log<level::INFO>("Logging failing sysfs file",
+                    phosphor::logging::entry("FILE=%s", file.c_str()));
+
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    return FanPwmObject::target(value);
+}
+
+} // namespace hwmon
+