xref: /openbmc/phosphor-hwmon/sensor.hpp (revision c9d61613)
1 #pragma once
2 
3 #include "hwmonio.hpp"
4 #include "sensorset.hpp"
5 #include "types.hpp"
6 
7 #include <cerrno>
8 #include <future>
9 #include <gpioplus/handle.hpp>
10 #include <map>
11 #include <memory>
12 #include <optional>
13 #include <stdplus/handle/managed.hpp>
14 #include <unordered_set>
15 
16 namespace sensor
17 {
18 
19 using TimedoutMap = std::map<SensorSet::key_type, std::future<int64_t>>;
20 
21 struct valueAdjust
22 {
23     double gain = 1.0;
24     int offset = 0;
25     std::unordered_set<int> rmRCs;
26 };
27 
28 /** @brief Custom exception for async sensor reading timeout
29  */
30 struct AsyncSensorReadTimeOut : public std::system_error
31 {
32     AsyncSensorReadTimeOut() :
33         system_error(std::error_code(ETIMEDOUT, std::system_category()),
34                      "Async sensor read timed out")
35     {
36     }
37 };
38 
39 /** @class Sensor
40  *  @brief Sensor object based on a SensorSet container's key type
41  *  @details Sensor object to create and modify an associated device's sensor
42  *  attributes based on the key type of each sensor in the set provided by the
43  *  device.
44  */
45 class Sensor
46 {
47   public:
48     Sensor() = delete;
49     Sensor(const Sensor&) = delete;
50     Sensor(Sensor&&) = default;
51     Sensor& operator=(const Sensor&) = delete;
52     Sensor& operator=(Sensor&&) = default;
53     ~Sensor() = default;
54 
55     /**
56      * @brief Constructs Sensor object
57      *
58      * @param[in] sensor - A pair of sensor indentifiers
59      * @param[in] ioAccess - Hwmon sysfs access
60      * @param[in] devPath - Device sysfs path
61      */
62     explicit Sensor(const SensorSet::key_type& sensor,
63                     const hwmonio::HwmonIOInterface* ioAccess,
64                     const std::string& devPath);
65 
66     /**
67      * @brief Adds any sensor removal return codes for the sensor
68      * @details Add all return codes defined within a device's config file
69      * for the entire device or for the specific sensor.
70      *
71      * @param[in] rcList - List of return codes found for the sensor
72      */
73     void addRemoveRCs(const std::string& rcList);
74 
75     /**
76      * @brief Get the adjustments struct for the sensor
77      *
78      * @return - Sensor adjustment struct
79      */
80     inline const valueAdjust& getAdjusts() const
81     {
82         return _sensorAdjusts;
83     }
84 
85     /**
86      * @brief Adjusts a sensor value
87      * @details Adjusts the value given by any gain and/or offset defined
88      * for this sensor object and returns that adjusted value.
89      *
90      * @param[in] value - Value to be adjusted
91      *
92      * @return - Adjusted sensor value
93      */
94     SensorValueType adjustValue(SensorValueType value);
95 
96     /**
97      * @brief Add value interface and value property for sensor
98      * @details When a sensor has an associated input file, the Sensor.Value
99      * interface is added along with setting the Value property to the
100      * corresponding value found in the input file.
101      *
102      * @param[in] retryIO - Hwmon sysfs file retry constraints
103      *                      (number of and delay between)
104      * @param[in] info - Sensor object information
105      *
106      * @param[in] timedoutMap - Map to track timed out threads
107      *
108      * @return - Shared pointer to the value object
109      */
110     std::shared_ptr<ValueObject> addValue(const RetryIO& retryIO,
111                                           ObjectInfo& info,
112                                           TimedoutMap& timedoutMap);
113 
114     /**
115      * @brief Add status interface and functional property for sensor
116      * @details OperationalStatus interface is added and the Functional property
117      * is set depending on whether a fault file exists and if it does it will
118      * also depend on the content of the fault file. _hasFaultFile will also be
119      * set to true if fault file exists.
120      *
121      * @param[in] info - Sensor object information
122      *
123      * @return - Shared pointer to the status object
124      */
125     std::shared_ptr<StatusObject> addStatus(ObjectInfo& info);
126 
127     /**
128      * @brief Add Accuracy interface and accuracy property for sensor
129      * @details Accuracy interface is the accuracy range (+/-) of the sensor
130      * Value as a percentage, with a value between 0 and 100.
131      *
132      * @param[in] info     - Sensor object information
133      * @param[in] accuracy - The accuracy value for sensor readings
134      *
135      * @return - Shared pointer to the accuracy object
136      */
137     std::shared_ptr<AccuracyObject> addAccuracy(ObjectInfo& info,
138                                                 double accuracy);
139 
140     /**
141      * @brief Get the scale from the sensor.
142      *
143      * @return - Scale value
144      */
145     inline int64_t getScale(void) const
146     {
147         return _scale;
148     }
149 
150     /**
151      * @brief Get the GPIO handle from the sensor.
152      *
153      * @return - Pointer to the GPIO handle interface, can be nullptr.
154      */
155     inline const gpioplus::HandleInterface* getGpio(void) const
156     {
157         return _handle.get();
158     }
159 
160     /**
161      * @brief Get whether the sensor has a fault file or not.
162      *
163      * @return - Boolean on whether the sensor has a fault file
164      */
165     inline bool hasFaultFile(void) const
166     {
167         return _hasFaultFile;
168     }
169 
170   private:
171     /** @brief Sensor object's identifiers */
172     SensorSet::key_type _sensor;
173 
174     /** @brief Hwmon sysfs access. */
175     const hwmonio::HwmonIOInterface* _ioAccess;
176 
177     /** @brief Physical device sysfs path. */
178     const std::string& _devPath;
179 
180     /** @brief Structure for storing sensor adjustments */
181     valueAdjust _sensorAdjusts;
182 
183     /** @brief Optional pointer to GPIO handle. */
184     std::unique_ptr<gpioplus::HandleInterface> _handle;
185 
186     /** @brief sensor scale from configuration. */
187     int64_t _scale;
188 
189     /** @brief Tracks whether the sensor has a fault file or not. */
190     bool _hasFaultFile;
191 };
192 
193 /**
194  * @brief Locks the gpio represented by the handle
195  *
196  * @param[in] handle - The gpio handle to lock
197  */
198 void gpioLock(const gpioplus::HandleInterface*&& handle);
199 
200 /** @brief The type which is responsible for managing the lock */
201 using GpioLocker =
202     stdplus::Managed<const gpioplus::HandleInterface*>::Handle<gpioLock>;
203 
204 /**
205  * @brief Unlocks the gpio and creates a lock object to ensure
206  *        the gpio is locked again.
207  *
208  * @param[in] handle - The gpio handle to unlock and wrap
209  */
210 std::optional<GpioLocker> gpioUnlock(const gpioplus::HandleInterface* handle);
211 
212 /**
213  * @brief Asynchronously read a sensor with timeout defined by
214  *        ASYNC_READ_TIMEOUT environment variable
215  *
216  * @param[in] sensorSetKey - Sensor object's identifiers
217  * @param[in] ioAccess - Hwmon sysfs access
218  * @param[in] asyncTimeout - Async read timeout in milliseconds
219  * @param[in] timedoutMap - Map to track timed out threads
220  *
221  * (Params needed for HwmonIO::read)
222  * @param[in] type - The hwmon type (ex. temp).
223  * @param[in] id - The hwmon id (ex. 1).
224  * @param[in] sensor - The hwmon sensor (ex. input).
225  * @param[in] retries - The number of times to retry.
226  * @param[in] delay - The time to sleep between retry attempts.
227  *
228  * @return - SensorValueType read asynchronously, will throw if timed out
229  */
230 SensorValueType asyncRead(const SensorSet::key_type& sensorSetKey,
231                           const hwmonio::HwmonIOInterface* ioAccess,
232                           std::chrono::milliseconds asyncTimeout,
233                           TimedoutMap& timedoutMap, const std::string& type,
234                           const std::string& id, const std::string& sensor,
235                           const size_t retries,
236                           const std::chrono::milliseconds delay);
237 } // namespace sensor
238