1abf8da36SMatt Spinler #pragma once
2abf8da36SMatt Spinler 
3abf8da36SMatt Spinler #include <sdbusplus/bus.hpp>
4abf8da36SMatt Spinler #include <sdbusplus/server.hpp>
58fd879fbSWilliam A. Kennington III #include <sdeventplus/clock.hpp>
61cfc2f11SWilliam A. Kennington III #include <sdeventplus/event.hpp>
78fd879fbSWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp>
8abf8da36SMatt Spinler 
9177fe986SMatthew Barth #include <chrono>
10177fe986SMatthew Barth 
11abf8da36SMatt Spinler namespace phosphor
12abf8da36SMatt Spinler {
13abf8da36SMatt Spinler namespace fan
14abf8da36SMatt Spinler {
15abf8da36SMatt Spinler namespace monitor
16abf8da36SMatt Spinler {
17abf8da36SMatt Spinler 
18abf8da36SMatt Spinler class Fan;
19abf8da36SMatt Spinler 
2078689dd7SMatt Spinler constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
21abf8da36SMatt Spinler 
22abf8da36SMatt Spinler /**
230a9fe160SMatthew Barth  * The mode fan monitor will run in:
240a9fe160SMatthew Barth  *   - init - only do the initialization steps
250a9fe160SMatthew Barth  *   - monitor - run normal monitoring algorithm
260a9fe160SMatthew Barth  */
270a9fe160SMatthew Barth enum class Mode
280a9fe160SMatthew Barth {
290a9fe160SMatthew Barth     init,
300a9fe160SMatthew Barth     monitor
310a9fe160SMatthew Barth };
320a9fe160SMatthew Barth 
330a9fe160SMatthew Barth /**
343800ae71SMatthew Barth  * The mode that the timer is running in:
353800ae71SMatthew Barth  *   - func - Transition to functional state timer
363800ae71SMatthew Barth  *   - nonfunc - Transition to nonfunctional state timer
373800ae71SMatthew Barth  */
383800ae71SMatthew Barth enum class TimerMode
393800ae71SMatthew Barth {
403800ae71SMatthew Barth     func,
413800ae71SMatthew Barth     nonfunc
423800ae71SMatthew Barth };
433800ae71SMatthew Barth 
443800ae71SMatthew Barth /**
45*69f2f48eSJolie Ku  * The mode that the method is running in:
46*69f2f48eSJolie Ku  *   - time - Use a percentage based deviation
47*69f2f48eSJolie Ku  *   - count - Run up/down count fault detection
48*69f2f48eSJolie Ku  */
49*69f2f48eSJolie Ku enum MethodMode
50*69f2f48eSJolie Ku {
51*69f2f48eSJolie Ku     timebased = 0,
52*69f2f48eSJolie Ku     count
53*69f2f48eSJolie Ku };
54*69f2f48eSJolie Ku 
55*69f2f48eSJolie Ku /**
56abf8da36SMatt Spinler  * @class TachSensor
57abf8da36SMatt Spinler  *
58abf8da36SMatt Spinler  * This class represents the sensor that reads a tach value.
59abf8da36SMatt Spinler  * It may also support a Target, which is the property used to
60abf8da36SMatt Spinler  * set a speed.  Since it doesn't necessarily have a Target, it
61abf8da36SMatt Spinler  * won't for sure know if it is running too slow, so it leaves
62abf8da36SMatt Spinler  * that determination to other code.
63abf8da36SMatt Spinler  *
64abf8da36SMatt Spinler  * This class has a parent Fan object that knows about all
65abf8da36SMatt Spinler  * sensors for that fan.
66abf8da36SMatt Spinler  */
67abf8da36SMatt Spinler class TachSensor
68abf8da36SMatt Spinler {
69abf8da36SMatt Spinler   public:
70abf8da36SMatt Spinler     TachSensor() = delete;
71abf8da36SMatt Spinler     TachSensor(const TachSensor&) = delete;
72fa0766e3SBrad Bishop     // TachSensor is not moveable since the this pointer is used as systemd
73fa0766e3SBrad Bishop     // callback context.
74fa0766e3SBrad Bishop     TachSensor(TachSensor&&) = delete;
75abf8da36SMatt Spinler     TachSensor& operator=(const TachSensor&) = delete;
76fa0766e3SBrad Bishop     TachSensor& operator=(TachSensor&&) = delete;
77abf8da36SMatt Spinler     ~TachSensor() = default;
78abf8da36SMatt Spinler 
79abf8da36SMatt Spinler     /**
80abf8da36SMatt Spinler      * @brief Constructor
81abf8da36SMatt Spinler      *
820a9fe160SMatthew Barth      * @param[in] mode - mode of fan monitor
83abf8da36SMatt Spinler      * @param[in] bus - the dbus object
84abf8da36SMatt Spinler      * @param[in] fan - the parent fan object
85abf8da36SMatt Spinler      * @param[in] id - the id of the sensor
86abf8da36SMatt Spinler      * @param[in] hasTarget - if the sensor supports
87abf8da36SMatt Spinler      *                        setting the speed
889396bcc3SMatthew Barth      * @param[in] funcDelay - Delay to mark functional
8980f271b2SLei YU      * @param[in] interface - the interface of the target
908e5d197bSLei YU      * @param[in] factor - the factor of the sensor target
918e5d197bSLei YU      * @param[in] offset - the offset of the sensor target
92*69f2f48eSJolie Ku      * @param[in] method - the method of out of range
93*69f2f48eSJolie Ku      * @param[in] threshold - the threshold of counter method
94abf8da36SMatt Spinler      * @param[in] timeout - Normal timeout value to use
95f13b42e2SMatt Spinler      * @param[in] errorDelay - Delay in seconds before creating an error
96f13b42e2SMatt Spinler      *                         or std::nullopt if no errors.
97f13b42e2SMatt Spinler      *
981cfc2f11SWilliam A. Kennington III      * @param[in] event - Event loop reference
99abf8da36SMatt Spinler      */
100177fe986SMatthew Barth     TachSensor(Mode mode, sdbusplus::bus::bus& bus, Fan& fan,
101177fe986SMatthew Barth                const std::string& id, bool hasTarget, size_t funcDelay,
102177fe986SMatthew Barth                const std::string& interface, double factor, int64_t offset,
103*69f2f48eSJolie Ku                size_t method, size_t threshold, size_t timeout,
104*69f2f48eSJolie Ku                const std::optional<size_t>& errorDelay,
105f13b42e2SMatt Spinler                const sdeventplus::Event& event);
106abf8da36SMatt Spinler 
107abf8da36SMatt Spinler     /**
108abf8da36SMatt Spinler      * @brief Returns the target speed value
109abf8da36SMatt Spinler      */
110f552ea5cSMatthew Barth     uint64_t getTarget() const;
111abf8da36SMatt Spinler 
112abf8da36SMatt Spinler     /**
113abf8da36SMatt Spinler      * @brief Returns the input speed value
114abf8da36SMatt Spinler      */
1150891e3b3SMatthew Barth     inline double getInput() const
116abf8da36SMatt Spinler     {
117abf8da36SMatt Spinler         return _tachInput;
118abf8da36SMatt Spinler     }
119abf8da36SMatt Spinler 
120abf8da36SMatt Spinler     /**
121abf8da36SMatt Spinler      * @brief Returns true if sensor has a target
122abf8da36SMatt Spinler      */
123abf8da36SMatt Spinler     inline bool hasTarget() const
124abf8da36SMatt Spinler     {
125abf8da36SMatt Spinler         return _hasTarget;
126abf8da36SMatt Spinler     }
127abf8da36SMatt Spinler 
128abf8da36SMatt Spinler     /**
12980f271b2SLei YU      * @brief Returns the interface of the sensor target
13080f271b2SLei YU      */
13180f271b2SLei YU     inline std::string getInterface() const
13280f271b2SLei YU     {
13380f271b2SLei YU         return _interface;
13480f271b2SLei YU     }
13580f271b2SLei YU 
13680f271b2SLei YU     /**
1378e5d197bSLei YU      * @brief Returns the factor of the sensor target
1388e5d197bSLei YU      */
1395e7298c5SMatthew Barth     inline double getFactor() const
1408e5d197bSLei YU     {
1418e5d197bSLei YU         return _factor;
1428e5d197bSLei YU     }
1438e5d197bSLei YU 
1448e5d197bSLei YU     /**
1458e5d197bSLei YU      * @brief Returns the offset of the sensor target
1468e5d197bSLei YU      */
1474eac3cf9SLei YU     inline int64_t getOffset() const
1488e5d197bSLei YU     {
1498e5d197bSLei YU         return _offset;
1508e5d197bSLei YU     }
1518e5d197bSLei YU 
1528e5d197bSLei YU     /**
153*69f2f48eSJolie Ku      * @brief Returns the method of out of range
154*69f2f48eSJolie Ku      */
155*69f2f48eSJolie Ku     inline size_t getMethod() const
156*69f2f48eSJolie Ku     {
157*69f2f48eSJolie Ku         return _method;
158*69f2f48eSJolie Ku     }
159*69f2f48eSJolie Ku 
160*69f2f48eSJolie Ku     /**
161*69f2f48eSJolie Ku      * @brief Returns the threshold of count method
162*69f2f48eSJolie Ku      */
163*69f2f48eSJolie Ku     inline size_t getThreshold() const
164*69f2f48eSJolie Ku     {
165*69f2f48eSJolie Ku         return _threshold;
166*69f2f48eSJolie Ku     }
167*69f2f48eSJolie Ku 
168*69f2f48eSJolie Ku     /**
169*69f2f48eSJolie Ku      * Set the sensor faulted counter
170*69f2f48eSJolie Ku      */
171*69f2f48eSJolie Ku     void setCounter(bool count);
172*69f2f48eSJolie Ku 
173*69f2f48eSJolie Ku     /**
174*69f2f48eSJolie Ku      * @brief Returns the sensor faulted count
175*69f2f48eSJolie Ku      */
176*69f2f48eSJolie Ku     inline size_t getCounter() const
177*69f2f48eSJolie Ku     {
178*69f2f48eSJolie Ku         return _counter;
179*69f2f48eSJolie Ku     }
180*69f2f48eSJolie Ku 
181*69f2f48eSJolie Ku     /**
182abf8da36SMatt Spinler      * Returns true if the hardware behind this
183abf8da36SMatt Spinler      * sensor is considered working OK/functional.
184abf8da36SMatt Spinler      */
185abf8da36SMatt Spinler     inline bool functional() const
186abf8da36SMatt Spinler     {
187abf8da36SMatt Spinler         return _functional;
188abf8da36SMatt Spinler     }
189abf8da36SMatt Spinler 
190abf8da36SMatt Spinler     /**
191d199dcdfSMatthew Barth      * Set the functional status and update inventory to match
192abf8da36SMatt Spinler      */
193d199dcdfSMatthew Barth     void setFunctional(bool functional);
194abf8da36SMatt Spinler 
195a9406a77SMatt Spinler     /**
1966fa181c7SMatt Spinler      * @brief Says if the timer is running or not
1976fa181c7SMatt Spinler      *
1986fa181c7SMatt Spinler      * @return bool - if timer is currently running
199a9406a77SMatt Spinler      */
2006fa181c7SMatt Spinler     inline bool timerRunning()
201a9406a77SMatt Spinler     {
2028fd879fbSWilliam A. Kennington III         return _timer.isEnabled();
2036fa181c7SMatt Spinler     }
2046fa181c7SMatt Spinler 
2056fa181c7SMatt Spinler     /**
2063800ae71SMatthew Barth      * @brief Stops the timer when the given mode differs and starts
2073800ae71SMatthew Barth      * the associated timer for the mode given if not already running
2083800ae71SMatthew Barth      *
2093800ae71SMatthew Barth      * @param[in] mode - mode of timer to start
2106fa181c7SMatt Spinler      */
2113800ae71SMatthew Barth     void startTimer(TimerMode mode);
2126fa181c7SMatt Spinler 
2136fa181c7SMatt Spinler     /**
2146fa181c7SMatt Spinler      * @brief Stops the timer
2156fa181c7SMatt Spinler      */
2166fa181c7SMatt Spinler     inline void stopTimer()
2176fa181c7SMatt Spinler     {
2188fd879fbSWilliam A. Kennington III         _timer.setEnabled(false);
219a9406a77SMatt Spinler     }
220a9406a77SMatt Spinler 
221a9406a77SMatt Spinler     /**
2223800ae71SMatthew Barth      * @brief Return the given timer mode's delay time
2233800ae71SMatthew Barth      *
2243800ae71SMatthew Barth      * @param[in] mode - mode of timer to get delay time for
225a9406a77SMatt Spinler      */
2263800ae71SMatthew Barth     std::chrono::microseconds getDelay(TimerMode mode);
227a9406a77SMatt Spinler 
228ce75b511SMatt Spinler     /**
229ce75b511SMatt Spinler      * Returns the sensor name
230ce75b511SMatt Spinler      */
231ce75b511SMatt Spinler     inline const std::string& name() const
232ce75b511SMatt Spinler     {
233ce75b511SMatt Spinler         return _name;
234ce75b511SMatt Spinler     };
235ce75b511SMatt Spinler 
236f13b42e2SMatt Spinler     /**
237f13b42e2SMatt Spinler      * @brief Says if the error timer is running
238f13b42e2SMatt Spinler      *
239f13b42e2SMatt Spinler      * @return bool - If the timer is running
240f13b42e2SMatt Spinler      */
241f13b42e2SMatt Spinler     bool errorTimerRunning() const
242f13b42e2SMatt Spinler     {
243f13b42e2SMatt Spinler         if (_errorTimer && _errorTimer->isEnabled())
244f13b42e2SMatt Spinler         {
245f13b42e2SMatt Spinler             return true;
246f13b42e2SMatt Spinler         }
247f13b42e2SMatt Spinler         return false;
248f13b42e2SMatt Spinler     }
249f13b42e2SMatt Spinler 
250abf8da36SMatt Spinler   private:
251abf8da36SMatt Spinler     /**
252ebaae611SMatt Spinler      * @brief Returns the match string to use for matching
253ebaae611SMatt Spinler      *        on a properties changed signal.
254ebaae611SMatt Spinler      */
255ebaae611SMatt Spinler     std::string getMatchString(const std::string& interface);
256ebaae611SMatt Spinler 
257ebaae611SMatt Spinler     /**
258ebaae611SMatt Spinler      * @brief Reads the Target property and stores in _tachTarget.
259ebaae611SMatt Spinler      *        Also calls Fan::tachChanged().
260ebaae611SMatt Spinler      *
261ebaae611SMatt Spinler      * @param[in] msg - the dbus message
262ebaae611SMatt Spinler      */
263771659fcSBrad Bishop     void handleTargetChange(sdbusplus::message::message& msg);
264ebaae611SMatt Spinler 
265ebaae611SMatt Spinler     /**
266ebaae611SMatt Spinler      * @brief Reads the Value property and stores in _tachInput.
267ebaae611SMatt Spinler      *        Also calls Fan::tachChanged().
268ebaae611SMatt Spinler      *
269ebaae611SMatt Spinler      * @param[in] msg - the dbus message
270ebaae611SMatt Spinler      */
271771659fcSBrad Bishop     void handleTachChange(sdbusplus::message::message& msg);
272ebaae611SMatt Spinler 
2734d982856SMatthew Barth     /**
2744d982856SMatthew Barth      * @brief Updates the Functional property in the inventory
2754d982856SMatthew Barth      *        for this tach sensor based on the value passed in.
2764d982856SMatthew Barth      *
2774d982856SMatthew Barth      * @param[in] functional - If the Functional property should
2784d982856SMatthew Barth      *                         be set to true or false.
2794d982856SMatthew Barth      */
2804d982856SMatthew Barth     void updateInventory(bool functional);
281ebaae611SMatt Spinler 
282ebaae611SMatt Spinler     /**
283abf8da36SMatt Spinler      * @brief the dbus object
284abf8da36SMatt Spinler      */
285abf8da36SMatt Spinler     sdbusplus::bus::bus& _bus;
286abf8da36SMatt Spinler 
287abf8da36SMatt Spinler     /**
288abf8da36SMatt Spinler      * @brief Reference to the parent Fan object
289abf8da36SMatt Spinler      */
290abf8da36SMatt Spinler     Fan& _fan;
291abf8da36SMatt Spinler 
292abf8da36SMatt Spinler     /**
293abf8da36SMatt Spinler      * @brief The name of the sensor, including the full path
294abf8da36SMatt Spinler      *
295abf8da36SMatt Spinler      * For example /xyz/openbmc_project/sensors/fan_tach/fan0
296abf8da36SMatt Spinler      */
297abf8da36SMatt Spinler     const std::string _name;
298abf8da36SMatt Spinler 
299abf8da36SMatt Spinler     /**
3004d982856SMatthew Barth      * @brief The inventory name of the sensor, including the full path
3014d982856SMatthew Barth      */
3024d982856SMatthew Barth     const std::string _invName;
3034d982856SMatthew Barth 
3044d982856SMatthew Barth     /**
305abf8da36SMatt Spinler      * @brief If functional (not too slow).  The parent
306abf8da36SMatt Spinler      *        fan object sets this.
307abf8da36SMatt Spinler      */
308d199dcdfSMatthew Barth     bool _functional;
309abf8da36SMatt Spinler 
310abf8da36SMatt Spinler     /**
311abf8da36SMatt Spinler      * @brief If the sensor has a Target property (can set speed)
312abf8da36SMatt Spinler      */
313abf8da36SMatt Spinler     const bool _hasTarget;
314abf8da36SMatt Spinler 
315abf8da36SMatt Spinler     /**
3169396bcc3SMatthew Barth      * @brief Amount of time to delay updating to functional
3179396bcc3SMatthew Barth      */
3189396bcc3SMatthew Barth     const size_t _funcDelay;
3199396bcc3SMatthew Barth 
3209396bcc3SMatthew Barth     /**
32180f271b2SLei YU      * @brief The interface that the target implements
32280f271b2SLei YU      */
32380f271b2SLei YU     const std::string _interface;
32480f271b2SLei YU 
32580f271b2SLei YU     /**
3268e5d197bSLei YU      * @brief The factor of target to get fan rpm
3278e5d197bSLei YU      */
3285e7298c5SMatthew Barth     const double _factor;
3298e5d197bSLei YU 
3308e5d197bSLei YU     /**
3318e5d197bSLei YU      * @brief The offset of target to get fan rpm
3328e5d197bSLei YU      */
3334eac3cf9SLei YU     const int64_t _offset;
3348e5d197bSLei YU 
3358e5d197bSLei YU     /**
336*69f2f48eSJolie Ku      * @brief The method of out of range
337*69f2f48eSJolie Ku      */
338*69f2f48eSJolie Ku     const size_t _method;
339*69f2f48eSJolie Ku 
340*69f2f48eSJolie Ku     /**
341*69f2f48eSJolie Ku      * @brief The threshold for count method
342*69f2f48eSJolie Ku      */
343*69f2f48eSJolie Ku     const size_t _threshold;
344*69f2f48eSJolie Ku 
345*69f2f48eSJolie Ku     /**
346*69f2f48eSJolie Ku      * @brief The counter for count method
347*69f2f48eSJolie Ku      */
348*69f2f48eSJolie Ku     size_t _counter = 0;
349*69f2f48eSJolie Ku 
350*69f2f48eSJolie Ku     /**
351abf8da36SMatt Spinler      * @brief The input speed, from the Value dbus property
352abf8da36SMatt Spinler      */
3530891e3b3SMatthew Barth     double _tachInput = 0;
354abf8da36SMatt Spinler 
355abf8da36SMatt Spinler     /**
356abf8da36SMatt Spinler      * @brief The current target speed, from the Target dbus property
357abf8da36SMatt Spinler      *        (if applicable)
358abf8da36SMatt Spinler      */
359abf8da36SMatt Spinler     uint64_t _tachTarget = 0;
360abf8da36SMatt Spinler 
361abf8da36SMatt Spinler     /**
362abf8da36SMatt Spinler      * @brief The timeout value to use
363abf8da36SMatt Spinler      */
364abf8da36SMatt Spinler     const size_t _timeout;
365ebaae611SMatt Spinler 
366ebaae611SMatt Spinler     /**
3673800ae71SMatthew Barth      * @brief Mode that current timer is in
3683800ae71SMatthew Barth      */
3693800ae71SMatthew Barth     TimerMode _timerMode;
3703800ae71SMatthew Barth 
3713800ae71SMatthew Barth     /**
372a9406a77SMatt Spinler      * The timer object
373a9406a77SMatt Spinler      */
3748fd879fbSWilliam A. Kennington III     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _timer;
375a9406a77SMatt Spinler 
376a9406a77SMatt Spinler     /**
377ebaae611SMatt Spinler      * @brief The match object for the Value properties changed signal
378ebaae611SMatt Spinler      */
379ebaae611SMatt Spinler     std::unique_ptr<sdbusplus::server::match::match> tachSignal;
380ebaae611SMatt Spinler 
381ebaae611SMatt Spinler     /**
382ebaae611SMatt Spinler      * @brief The match object for the Target properties changed signal
383ebaae611SMatt Spinler      */
384ebaae611SMatt Spinler     std::unique_ptr<sdbusplus::server::match::match> targetSignal;
385f13b42e2SMatt Spinler 
386f13b42e2SMatt Spinler     /**
387f13b42e2SMatt Spinler      * @brief The number of seconds to wait between a sensor being set
388f13b42e2SMatt Spinler      *        to nonfunctional and creating an error for it.
389f13b42e2SMatt Spinler      *
390f13b42e2SMatt Spinler      * If std::nullopt, no errors will be created.
391f13b42e2SMatt Spinler      */
392f13b42e2SMatt Spinler     const std::optional<size_t> _errorDelay;
393f13b42e2SMatt Spinler 
394f13b42e2SMatt Spinler     /**
395f13b42e2SMatt Spinler      * @brief The timer that uses _errorDelay.  When it expires an error
396f13b42e2SMatt Spinler      *        will be created for a faulted fan sensor (rotor).
397f13b42e2SMatt Spinler      *
398f13b42e2SMatt Spinler      * If _errorDelay is std::nullopt, then this won't be created.
399f13b42e2SMatt Spinler      */
400f13b42e2SMatt Spinler     std::unique_ptr<
401f13b42e2SMatt Spinler         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
402f13b42e2SMatt Spinler         _errorTimer;
403abf8da36SMatt Spinler };
404abf8da36SMatt Spinler 
405177fe986SMatthew Barth } // namespace monitor
406177fe986SMatthew Barth } // namespace fan
407177fe986SMatthew Barth } // namespace phosphor
408