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