1 #pragma once
2 
3 #include <chrono>
4 #include <sdbusplus/bus.hpp>
5 #include <sdbusplus/server.hpp>
6 #include "event.hpp"
7 #include "timer.hpp"
8 
9 namespace phosphor
10 {
11 namespace fan
12 {
13 namespace monitor
14 {
15 
16 class Fan;
17 
18 constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
19 
20 /**
21  * The mode fan monitor will run in:
22  *   - init - only do the initialization steps
23  *   - monitor - run normal monitoring algorithm
24  */
25 enum class Mode
26 {
27     init,
28     monitor
29 };
30 
31 /**
32  * The mode that the timer is running in:
33  *   - func - Transition to functional state timer
34  *   - nonfunc - Transition to nonfunctional state timer
35  */
36 enum class TimerMode
37 {
38     func,
39     nonfunc
40 };
41 
42 /**
43  * @class TachSensor
44  *
45  * This class represents the sensor that reads a tach value.
46  * It may also support a Target, which is the property used to
47  * set a speed.  Since it doesn't necessarily have a Target, it
48  * won't for sure know if it is running too slow, so it leaves
49  * that determination to other code.
50  *
51  * This class has a parent Fan object that knows about all
52  * sensors for that fan.
53  */
54 class TachSensor
55 {
56     public:
57 
58         TachSensor() = delete;
59         TachSensor(const TachSensor&) = delete;
60         // TachSensor is not moveable since the this pointer is used as systemd
61         // callback context.
62         TachSensor(TachSensor&&) = delete;
63         TachSensor& operator=(const TachSensor&) = delete;
64         TachSensor& operator=(TachSensor&&) = delete;
65         ~TachSensor() = default;
66 
67         /**
68          * @brief Constructor
69          *
70          * @param[in] mode - mode of fan monitor
71          * @param[in] bus - the dbus object
72          * @param[in] fan - the parent fan object
73          * @param[in] id - the id of the sensor
74          * @param[in] hasTarget - if the sensor supports
75          *                        setting the speed
76          * @param[in] funcDelay - Delay to mark functional
77          * @param[in] interface - the interface of the target
78          * @param[in] factor - the factor of the sensor target
79          * @param[in] offset - the offset of the sensor target
80          * @param[in] timeout - Normal timeout value to use
81          * @param[in] events - sd_event pointer
82          */
83         TachSensor(Mode mode,
84                    sdbusplus::bus::bus& bus,
85                    Fan& fan,
86                    const std::string& id,
87                    bool hasTarget,
88                    size_t funcDelay,
89                    const std::string& interface,
90                    size_t factor,
91                    size_t offset,
92                    size_t timeout,
93                    phosphor::fan::event::EventPtr& events);
94 
95         /**
96          * @brief Returns the target speed value
97          */
98         uint64_t getTarget() const;
99 
100         /**
101          * @brief Returns the input speed value
102          */
103         inline int64_t getInput() const
104         {
105             return _tachInput;
106         }
107 
108         /**
109          * @brief Returns true if sensor has a target
110          */
111         inline bool hasTarget() const
112         {
113             return _hasTarget;
114         }
115 
116         /**
117          * @brief Returns the interface of the sensor target
118          */
119         inline std::string getInterface() const
120         {
121             return _interface;
122         }
123 
124         /**
125          * @brief Returns the factor of the sensor target
126          */
127         inline size_t getFactor() const
128         {
129             return _factor;
130         }
131 
132         /**
133          * @brief Returns the offset of the sensor target
134          */
135         inline size_t getOffset() const
136         {
137             return _offset;
138         }
139 
140         /**
141          * Returns true if the hardware behind this
142          * sensor is considered working OK/functional.
143          */
144         inline bool functional() const
145         {
146             return _functional;
147         }
148 
149         /**
150          * Set the functional status and update inventory to match
151          */
152         void setFunctional(bool functional);
153 
154         /**
155          * @brief Says if the timer is running or not
156          *
157          * @return bool - if timer is currently running
158          */
159         inline bool timerRunning()
160         {
161             return _timer.running();
162         }
163 
164         /**
165          * @brief Stops the timer when the given mode differs and starts
166          * the associated timer for the mode given if not already running
167          *
168          * @param[in] mode - mode of timer to start
169          */
170         void startTimer(TimerMode mode);
171 
172         /**
173          * @brief Stops the timer
174          */
175         inline void stopTimer()
176         {
177             _timer.stop();
178         }
179 
180         /**
181          * @brief Return the given timer mode's delay time
182          *
183          * @param[in] mode - mode of timer to get delay time for
184          */
185         std::chrono::microseconds getDelay(TimerMode mode);
186 
187         /**
188          * Returns the sensor name
189          */
190         inline const std::string& name() const
191         {
192             return _name;
193         };
194 
195     private:
196 
197         /**
198          * @brief Returns the match string to use for matching
199          *        on a properties changed signal.
200          */
201         std::string getMatchString(const std::string& interface);
202 
203         /**
204          * @brief Reads the Target property and stores in _tachTarget.
205          *        Also calls Fan::tachChanged().
206          *
207          * @param[in] msg - the dbus message
208          */
209         void handleTargetChange(sdbusplus::message::message& msg);
210 
211         /**
212          * @brief Reads the Value property and stores in _tachInput.
213          *        Also calls Fan::tachChanged().
214          *
215          * @param[in] msg - the dbus message
216          */
217         void handleTachChange(sdbusplus::message::message& msg);
218 
219         /**
220          * @brief Updates the Functional property in the inventory
221          *        for this tach sensor based on the value passed in.
222          *
223          * @param[in] functional - If the Functional property should
224          *                         be set to true or false.
225          */
226         void updateInventory(bool functional);
227 
228         /**
229          * @brief the dbus object
230          */
231         sdbusplus::bus::bus& _bus;
232 
233         /**
234          * @brief Reference to the parent Fan object
235          */
236         Fan& _fan;
237 
238         /**
239          * @brief The name of the sensor, including the full path
240          *
241          * For example /xyz/openbmc_project/sensors/fan_tach/fan0
242          */
243         const std::string _name;
244 
245         /**
246          * @brief The inventory name of the sensor, including the full path
247          */
248         const std::string _invName;
249 
250         /**
251          * @brief If functional (not too slow).  The parent
252          *        fan object sets this.
253          */
254         bool _functional;
255 
256         /**
257          * @brief If the sensor has a Target property (can set speed)
258          */
259         const bool _hasTarget;
260 
261         /**
262          * @brief Amount of time to delay updating to functional
263          */
264         const size_t _funcDelay;
265 
266         /**
267          * @brief The interface that the target implements
268          */
269         const std::string _interface;
270 
271         /**
272          * @brief The factor of target to get fan rpm
273          */
274         const size_t _factor;
275 
276         /**
277          * @brief The offset of target to get fan rpm
278          */
279         const size_t _offset;
280 
281         /**
282          * @brief The input speed, from the Value dbus property
283          */
284         int64_t _tachInput = 0;
285 
286         /**
287          * @brief The current target speed, from the Target dbus property
288          *        (if applicable)
289          */
290         uint64_t _tachTarget = 0;
291 
292         /**
293          * @brief The timeout value to use
294          */
295         const size_t _timeout;
296 
297         /**
298          * @brief Mode that current timer is in
299          */
300         TimerMode _timerMode;
301 
302         /**
303          * The timer object
304          */
305         phosphor::fan::util::Timer _timer;
306 
307         /**
308          * @brief The match object for the Value properties changed signal
309          */
310         std::unique_ptr<sdbusplus::server::match::match> tachSignal;
311 
312         /**
313          * @brief The match object for the Target properties changed signal
314          */
315         std::unique_ptr<sdbusplus::server::match::match> targetSignal;
316 };
317 
318 }
319 }
320 }
321