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