blob: 0ec52bad7c23e34c16bcd2b86a2f1e7cffc85b77 [file] [log] [blame]
Matt Spinlerabf8da32017-04-27 14:08:45 -05001/**
2 * Copyright © 2017 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <phosphor-logging/log.hpp>
17#include "fan.hpp"
Brad Bishop2a58e2c2017-07-30 13:49:09 -040018#include "sdbusplus.hpp"
Matt Spinlerabf8da32017-04-27 14:08:45 -050019#include "tach_sensor.hpp"
20#include "../utility.hpp"
21
22namespace phosphor
23{
24namespace fan
25{
26namespace monitor
27{
28
29constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
Matt Spinlerebaae612017-04-27 14:21:48 -050030constexpr auto FAN_SENSOR_CONTROL_INTF = "xyz.openbmc_project.Control.FanSpeed";
31constexpr auto FAN_SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
32constexpr auto FAN_TARGET_PROPERTY = "Target";
33constexpr auto FAN_VALUE_PROPERTY = "Value";
34
35
36/**
37 * @brief Helper function to read a property
38 *
39 * @param[in] interface - the interface the property is on
40 * @param[in] propertName - the name of the property
41 * @param[in] path - the dbus path
Matt Spinlerebaae612017-04-27 14:21:48 -050042 * @param[in] bus - the dbus object
43 * @param[out] value - filled in with the property value
44 */
45template<typename T>
46static void readProperty(const std::string& interface,
47 const std::string& propertyName,
48 const std::string& path,
Matt Spinlerebaae612017-04-27 14:21:48 -050049 sdbusplus::bus::bus& bus,
50 T& value)
51{
Matt Spinlerebaae612017-04-27 14:21:48 -050052 try
53 {
Brad Bishop2a58e2c2017-07-30 13:49:09 -040054 value = util::SDBusPlus::getProperty<T>(bus,
55 path,
56 interface,
57 propertyName);
Matt Spinlerebaae612017-04-27 14:21:48 -050058 }
59 catch (std::exception& e)
60 {
61 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
62 }
63}
Matt Spinlerabf8da32017-04-27 14:08:45 -050064
65
66TachSensor::TachSensor(sdbusplus::bus::bus& bus,
67 Fan& fan,
68 const std::string& id,
69 bool hasTarget,
Matt Spinlera9406a72017-04-27 14:29:24 -050070 size_t timeout,
Matt Spinlere824f982017-05-11 10:07:55 -050071 phosphor::fan::event::EventPtr& events) :
Matt Spinlerabf8da32017-04-27 14:08:45 -050072 _bus(bus),
73 _fan(fan),
74 _name(FAN_SENSOR_PATH + id),
75 _hasTarget(hasTarget),
Matt Spinlera9406a72017-04-27 14:29:24 -050076 _timeout(timeout),
77 _timer(events, [this, &fan](){ fan.timerExpired(*this); })
Matt Spinlerabf8da32017-04-27 14:08:45 -050078{
Matt Spinlerebaae612017-04-27 14:21:48 -050079 //Load in starting Target and Input values
80 readProperty(FAN_SENSOR_VALUE_INTF,
81 FAN_VALUE_PROPERTY,
82 _name,
Matt Spinlerebaae612017-04-27 14:21:48 -050083 _bus,
84 _tachInput);
85
86 if (_hasTarget)
87 {
88 readProperty(FAN_SENSOR_CONTROL_INTF,
89 FAN_TARGET_PROPERTY,
90 _name,
Matt Spinlerebaae612017-04-27 14:21:48 -050091 _bus,
92 _tachTarget);
93 }
94
95 auto match = getMatchString(FAN_SENSOR_VALUE_INTF);
96
97 tachSignal = std::make_unique<sdbusplus::server::match::match>(
98 _bus,
99 match.c_str(),
100 handleTachChangeSignal,
101 this);
102
103 if (_hasTarget)
104 {
105 match = getMatchString(FAN_SENSOR_CONTROL_INTF);
106
107 targetSignal = std::make_unique<sdbusplus::server::match::match>(
108 _bus,
109 match.c_str(),
110 handleTargetChangeSignal,
111 this);
112 }
113
114}
115
116
Matt Spinlerebaae612017-04-27 14:21:48 -0500117std::string TachSensor::getMatchString(const std::string& interface)
118{
119 return std::string("type='signal',"
120 "interface='org.freedesktop.DBus.Properties',"
121 "member='PropertiesChanged',"
122 "arg0namespace='" + interface + "',"
123 "path='" + _name + "'");
124}
125
126
127int TachSensor::handleTachChangeSignal(sd_bus_message* msg,
128 void* usrData,
129 sd_bus_error* err)
130{
131 auto m = sdbusplus::message::message(msg);
132 static_cast<TachSensor*>(usrData)->handleTachChange(m, err);
133 return 0;
134}
135
136
137int TachSensor::handleTargetChangeSignal(sd_bus_message* msg,
138 void* usrData,
139 sd_bus_error* err)
140{
141 auto m = sdbusplus::message::message(msg);
142 static_cast<TachSensor*>(usrData)->handleTargetChange(m, err);
143 return 0;
144}
145
146
147/**
148 * @brief Reads a property from the input message and stores it in value.
149 * T is the value type.
150 *
151 * Note: This can only be called once per message.
152 *
153 * @param[in] msg - the dbus message that contains the data
154 * @param[in] interface - the interface the property is on
155 * @param[in] propertName - the name of the property
156 * @param[out] value - the value to store the property value in
157 */
158template<typename T>
159static void readPropertyFromMessage(sdbusplus::message::message& msg,
160 const std::string& interface,
161 const std::string& propertyName,
162 T& value)
163{
164 std::string sensor;
165 std::map<std::string, sdbusplus::message::variant<T>> data;
166 msg.read(sensor, data);
167
168 if (sensor.compare(interface) == 0)
169 {
170 auto propertyMap = data.find(propertyName);
171 if (propertyMap != data.end())
172 {
173 value = sdbusplus::message::variant_ns::get<T>(
174 propertyMap->second);
175 }
176 }
177}
178
179
180void TachSensor::handleTargetChange(sdbusplus::message::message& msg,
181 sd_bus_error* err)
182{
183 readPropertyFromMessage(msg,
184 FAN_SENSOR_CONTROL_INTF,
185 FAN_TARGET_PROPERTY,
186 _tachTarget);
187
188 //Check all tach sensors on the fan against the target
189 _fan.tachChanged();
190}
191
192
193void TachSensor::handleTachChange(sdbusplus::message::message& msg,
194 sd_bus_error* err)
195{
196 readPropertyFromMessage(msg,
197 FAN_SENSOR_VALUE_INTF,
198 FAN_VALUE_PROPERTY,
199 _tachInput);
200
201 //Check just this sensor against the target
202 _fan.tachChanged(*this);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500203}
204
205
Matt Spinlera9406a72017-04-27 14:29:24 -0500206std::chrono::microseconds TachSensor::getTimeout()
207{
208 using namespace std::chrono;
209
210 return duration_cast<microseconds>(seconds(_timeout));
211}
212
213
Matt Spinlerabf8da32017-04-27 14:08:45 -0500214}
215}
216}