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  * @class TachSensor
22  *
23  * This class represents the sensor that reads a tach value.
24  * It may also support a Target, which is the property used to
25  * set a speed.  Since it doesn't necessarily have a Target, it
26  * won't for sure know if it is running too slow, so it leaves
27  * that determination to other code.
28  *
29  * This class has a parent Fan object that knows about all
30  * sensors for that fan.
31  */
32 class TachSensor
33 {
34     public:
35 
36         TachSensor() = delete;
37         TachSensor(const TachSensor&) = delete;
38         // TachSensor is not moveable since the this pointer is used as systemd
39         // callback context.
40         TachSensor(TachSensor&&) = delete;
41         TachSensor& operator=(const TachSensor&) = delete;
42         TachSensor& operator=(TachSensor&&) = delete;
43         ~TachSensor() = default;
44 
45         /**
46          * @brief Constructor
47          *
48          * @param[in] bus - the dbus object
49          * @param[in] fan - the parent fan object
50          * @param[in] id - the id of the sensor
51          * @param[in] hasTarget - if the sensor supports
52          *                        setting the speed
53          * @param[in] timeout - Normal timeout value to use
54          * @param[in] events - sd_event pointer
55          */
56         TachSensor(sdbusplus::bus::bus& bus,
57                    Fan& fan,
58                    const std::string& id,
59                    bool hasTarget,
60                    size_t timeout,
61                    phosphor::fan::event::EventPtr& events);
62 
63         /**
64          * @brief Returns the target speed value
65          */
66         inline uint64_t getTarget() const
67         {
68             return _tachTarget;
69         }
70 
71         /**
72          * @brief Returns the input speed value
73          */
74         inline int64_t getInput() const
75         {
76             return _tachInput;
77         }
78 
79         /**
80          * @brief Returns true if sensor has a target
81          */
82         inline bool hasTarget() const
83         {
84             return _hasTarget;
85         }
86 
87         /**
88          * Returns true if the hardware behind this
89          * sensor is considered working OK/functional.
90          */
91         inline bool functional() const
92         {
93             return _functional;
94         }
95 
96         /**
97          * Sets functional status
98          */
99         inline void setFunctional(bool functional)
100         {
101             _functional = functional;
102         }
103 
104         /**
105          * @brief Says if the timer is running or not
106          *
107          * @return bool - if timer is currently running
108          */
109         inline bool timerRunning()
110         {
111             return _timer.running();
112         }
113 
114         /**
115          * @brief Starts the timer for the amount of time
116          *        specified in the constructor
117          */
118         inline void startTimer()
119         {
120             _timer.start(
121                     getTimeout(),
122                     phosphor::fan::util::Timer::TimerType::oneshot);
123         }
124 
125         /**
126          * @brief Stops the timer
127          */
128         inline void stopTimer()
129         {
130             _timer.stop();
131         }
132 
133         /**
134          * @brief Returns the timeout value to use for the sensor
135          */
136         std::chrono::microseconds getTimeout();
137 
138         /**
139          * Returns the sensor name
140          */
141         inline const std::string& name() const
142         {
143             return _name;
144         };
145 
146     private:
147 
148         /**
149          * @brief Returns the match string to use for matching
150          *        on a properties changed signal.
151          */
152         std::string getMatchString(const std::string& interface);
153 
154         /**
155          * @brief Reads the Target property and stores in _tachTarget.
156          *        Also calls Fan::tachChanged().
157          *
158          * @param[in] msg - the dbus message
159          */
160         void handleTargetChange(sdbusplus::message::message& msg);
161 
162         /**
163          * @brief Reads the Value property and stores in _tachInput.
164          *        Also calls Fan::tachChanged().
165          *
166          * @param[in] msg - the dbus message
167          */
168         void handleTachChange(sdbusplus::message::message& msg);
169 
170 
171         /**
172          * @brief the dbus object
173          */
174         sdbusplus::bus::bus& _bus;
175 
176         /**
177          * @brief Reference to the parent Fan object
178          */
179         Fan& _fan;
180 
181         /**
182          * @brief The name of the sensor, including the full path
183          *
184          * For example /xyz/openbmc_project/sensors/fan_tach/fan0
185          */
186         const std::string _name;
187 
188         /**
189          * @brief If functional (not too slow).  The parent
190          *        fan object sets this.
191          */
192         bool _functional = true;
193 
194         /**
195          * @brief If the sensor has a Target property (can set speed)
196          */
197         const bool _hasTarget;
198 
199         /**
200          * @brief The input speed, from the Value dbus property
201          */
202         int64_t _tachInput = 0;
203 
204         /**
205          * @brief The current target speed, from the Target dbus property
206          *        (if applicable)
207          */
208         uint64_t _tachTarget = 0;
209 
210         /**
211          * @brief The timeout value to use
212          */
213         const size_t _timeout;
214 
215         /**
216          * The timer object
217          */
218         phosphor::fan::util::Timer _timer;
219 
220         /**
221          * @brief The match object for the Value properties changed signal
222          */
223         std::unique_ptr<sdbusplus::server::match::match> tachSignal;
224 
225         /**
226          * @brief The match object for the Target properties changed signal
227          */
228         std::unique_ptr<sdbusplus::server::match::match> targetSignal;
229 };
230 
231 }
232 }
233 }
234