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