blob: 4a2c2c39700ffb13b71c473e95840266ca9edc7e [file] [log] [blame]
Patrick Venturee6206562018-03-08 15:36:53 -08001#pragma once
2
James Feist0c8223b2019-05-08 15:33:33 -07003#include "pid/ec/pid.hpp"
4
James Feist5ec20272019-07-10 11:59:57 -07005#include <phosphor-logging/log.hpp>
James Feist0c8223b2019-05-08 15:33:33 -07006#include <sdbusplus/bus.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -07007
8#include <limits>
Patrick Ventureda064282018-06-12 19:33:47 -07009#include <string>
10
Patrick Venturee6206562018-03-08 15:36:53 -080011/* This program assumes sensors use the Sensor.Value interface
12 * and for sensor->write() I only implemented sysfs as a type,
13 * but -- how would it know whether to use Control.FanSpeed or Control.FanPwm?
14 *
15 * One could get the interface list for the object and search for Control.*
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070016 * but, it needs to know the maximum, minimum. The only sensors it wants to
17 * write in this code base are Fans...
Patrick Venturee6206562018-03-08 15:36:53 -080018 */
19enum class IOInterfaceType
20{
21 NONE, // There is no interface.
22 EXTERNAL,
23 DBUSPASSIVE,
24 DBUSACTIVE, // This means for write that it needs to look up the interface.
25 SYSFS,
26 UNKNOWN
27};
28
29/* WriteInterfaceType is different because Dbusactive/passive. how to know... */
Patrick Venture7af157b2018-10-30 11:24:40 -070030IOInterfaceType getWriteInterfaceType(const std::string& path);
Patrick Venturee6206562018-03-08 15:36:53 -080031
Patrick Venture7af157b2018-10-30 11:24:40 -070032IOInterfaceType getReadInterfaceType(const std::string& path);
James Feist0c8223b2019-05-08 15:33:33 -070033
Yong Li298a95c2020-04-07 15:11:02 +080034void tryRestartControlLoops(void);
James Feist1fe08952019-05-07 09:17:16 -070035
James Feist0c8223b2019-05-08 15:33:33 -070036/*
37 * Given a configuration structure, fill out the information we use within the
38 * PID loop.
39 */
40void initializePIDStruct(ec::pid_info_t* info, const ec::pidinfo& initial);
41
42void dumpPIDStruct(ec::pid_info_t* info);
43
44struct SensorProperties
45{
46 int64_t scale;
47 double value;
48 double min;
49 double max;
50 std::string unit;
51};
52
53struct SensorThresholds
54{
55 double lowerThreshold = std::numeric_limits<double>::quiet_NaN();
56 double upperThreshold = std::numeric_limits<double>::quiet_NaN();
57};
58
59const std::string sensorintf = "xyz.openbmc_project.Sensor.Value";
60const std::string criticalThreshInf =
61 "xyz.openbmc_project.Sensor.Threshold.Critical";
62const std::string propertiesintf = "org.freedesktop.DBus.Properties";
63
64class DbusHelperInterface
65{
66 public:
67 virtual ~DbusHelperInterface() = default;
68
69 /** @brief Get the service providing the interface for the path.
70 *
71 * @warning Throws exception on dbus failure.
72 */
73 virtual std::string getService(sdbusplus::bus::bus& bus,
74 const std::string& intf,
75 const std::string& path) = 0;
76
77 /** @brief Get all Sensor.Value properties for a service and path.
78 *
79 * @param[in] bus - A bus to use for the call.
80 * @param[in] service - The service providing the interface.
81 * @param[in] path - The dbus path.
82 * @param[out] prop - A pointer to a properties struct to fill out.
83 *
84 * @warning Throws exception on dbus failure.
85 */
86 virtual void getProperties(sdbusplus::bus::bus& bus,
87 const std::string& service,
88 const std::string& path,
89 struct SensorProperties* prop) = 0;
90
91 /** @brief Get Critical Threshold current assert status
92 *
93 * @param[in] bus - A bus to use for the call.
94 * @param[in] service - The service providing the interface.
95 * @param[in] path - The dbus path.
96 */
97 virtual bool thresholdsAsserted(sdbusplus::bus::bus& bus,
98 const std::string& service,
99 const std::string& path) = 0;
100};
101
102class DbusHelper : public DbusHelperInterface
103{
104 public:
105 DbusHelper() = default;
106 ~DbusHelper() = default;
107 DbusHelper(const DbusHelper&) = default;
108 DbusHelper& operator=(const DbusHelper&) = default;
109 DbusHelper(DbusHelper&&) = default;
110 DbusHelper& operator=(DbusHelper&&) = default;
111
112 std::string getService(sdbusplus::bus::bus& bus, const std::string& intf,
113 const std::string& path) override;
114
115 void getProperties(sdbusplus::bus::bus& bus, const std::string& service,
116 const std::string& path,
117 struct SensorProperties* prop) override;
118
119 bool thresholdsAsserted(sdbusplus::bus::bus& bus,
120 const std::string& service,
121 const std::string& path) override;
James Feist5ec20272019-07-10 11:59:57 -0700122
123 template <typename T>
124 void getProperty(sdbusplus::bus::bus& bus, const std::string& service,
125 const std::string& path, const std::string& interface,
126 const std::string& propertyName, T& prop)
127 {
128 namespace log = phosphor::logging;
129
130 auto msg = bus.new_method_call(service.c_str(), path.c_str(),
131 propertiesintf.c_str(), "Get");
132
133 msg.append(interface, propertyName);
134
135 std::variant<T> result;
136 try
137 {
138 auto valueResponseMsg = bus.call(msg);
139 valueResponseMsg.read(result);
140 }
141 catch (const sdbusplus::exception::SdBusError& ex)
142 {
143 log::log<log::level::ERR>("Get Property Failed",
144 log::entry("WHAT=%s", ex.what()));
145 throw;
146 }
147
148 prop = std::get<T>(result);
149 }
James Feist0c8223b2019-05-08 15:33:33 -0700150};
151
152std::string getSensorPath(const std::string& type, const std::string& id);
153std::string getMatch(const std::string& type, const std::string& id);
154void scaleSensorReading(const double min, const double max, double& value);
155bool validType(const std::string& type);
156
157struct VariantToDoubleVisitor
158{
159 template <typename T>
160 std::enable_if_t<std::is_arithmetic<T>::value, double>
161 operator()(const T& t) const
162 {
163 return static_cast<double>(t);
164 }
165
166 template <typename T>
167 std::enable_if_t<!std::is_arithmetic<T>::value, double>
168 operator()(const T& t) const
169 {
170 throw std::invalid_argument("Cannot translate type to double");
171 }
172};
173
174/*
175 * Given a path that optionally has a glob portion, fill it out.
176 */
177std::string FixupPath(std::string original);