summaryrefslogtreecommitdiffstats
path: root/targets.hpp
blob: ecef77b0c8d73a4434d02439e8ba72baf16e3466 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#pragma once

#include <experimental/filesystem>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <xyz/openbmc_project/Sensor/Device/error.hpp>
#include "fan_speed.hpp"
#include "fan_pwm.hpp"

enum class targetType
{
    DEFAULT,
    RPM,
    PWM
};

static constexpr auto RPM_TARGET = "RPM";
static constexpr auto PWM_TARGET = "PWM";

/** @class Targets
 *  @brief Target type traits.
 *
 *  @tparam T - The target type.
 */
template <typename T>
struct Targets
{
    static void fail()
    {
        static_assert(sizeof(Targets) == -1, "Unsupported Target type");
    }
};

/**@brief Targets specialization for fan speed. */
template <>
struct Targets<hwmon::FanSpeed>
{
    static constexpr InterfaceType type = InterfaceType::FAN_SPEED;
};

template <>
struct Targets<hwmon::FanPwm>
{
    static constexpr InterfaceType type = InterfaceType::FAN_PWM;
};

/** @brief addTarget
 *
 *  Creates the target type interface
 *
 *  @tparam T - The target type
 *
 *  @param[in] sensor - A sensor type and name
 *  @param[in] ioAccess - hwmon sysfs access object
 *  @param[in] devPath - The /sys/devices sysfs path
 *  @param[in] info - The sdbusplus server connection and interfaces
 *
 *  @return A shared pointer to the target interface object
 *          Will be empty if no interface was created
 */
template <typename T>
std::shared_ptr<T> addTarget(const SensorSet::key_type& sensor,
                             const sysfs::hwmonio::HwmonIO& ioAccess,
                             const std::string& devPath,
                             ObjectInfo& info)
{
    std::shared_ptr<T> target;
    namespace fs = std::experimental::filesystem;
    static constexpr bool deferSignals = true;

    auto& bus = *std::get<sdbusplus::bus::bus*>(info);
    auto& obj = std::get<Object>(info);
    auto& objPath = std::get<std::string>(info);
    auto type = Targets<T>::type;

    // Check if target sysfs file exists
    std::string sysfsFullPath;
    std::string targetName = sensor.first;
    std::string targetId = sensor.second;
    std::string entry = hwmon::entry::target;

    using namespace std::literals;
    const std::string pwm = "pwm"s;
    const std::string empty = ""s;

    if (InterfaceType::FAN_PWM == type)
    {
        targetName = pwm;
        // If PWM_TARGET is set, use the specified pwm id
        auto id = getEnv("PWM_TARGET", sensor);
        if (!id.empty())
        {
            targetId = id;
        }
        entry = empty;
    }

    sysfsFullPath = sysfs::make_sysfs_path(ioAccess.path(),
                                           targetName,
                                           targetId,
                                           entry);
    if (fs::exists(sysfsFullPath))
    {
        uint32_t targetSpeed = 0;

        try
        {
            targetSpeed = ioAccess.read(
                targetName,
                targetId,
                entry,
                sysfs::hwmonio::retries,
                sysfs::hwmonio::delay);
        }
        catch (const std::system_error& e)
        {
            using namespace phosphor::logging;
            using namespace sdbusplus::xyz::openbmc_project::
                Sensor::Device::Error;
            using metadata = xyz::openbmc_project::Sensor::
                Device::ReadFailure;

            report<ReadFailure>(
                    metadata::CALLOUT_ERRNO(e.code().value()),
                    metadata::CALLOUT_DEVICE_PATH(devPath.c_str()));

            log<level::INFO>("Logging failing sysfs file",
                    phosphor::logging::entry(
                            "FILE=%s", sysfsFullPath.c_str()));
        }

        target = std::make_shared<T>(ioAccess.path(),
                                     devPath,
                                     targetId,
                                     bus,
                                     objPath.c_str(),
                                     deferSignals,
                                     targetSpeed);
        obj[type] = target;
    }

    return target;
}
OpenPOWER on IntegriCloud