blob: dfba15fd14a6f076d0fb20089bc64b8edefd355a [file] [log] [blame]
Brad Bishope55ef3d2016-12-19 09:12:40 -05001/**
2 * Copyright © 2016 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 */
Brad Bishop4d9a35b2017-11-14 22:33:03 -050016#include <functional>
Brad Bishope55ef3d2016-12-19 09:12:40 -050017#include <iostream>
18#include <memory>
Brad Bishop9c7b6e02016-12-19 12:43:36 -050019#include <cstdlib>
Chiabing Leec923ce92017-09-06 15:58:26 +080020#include <string>
Patrick Venture1e6324f2017-06-01 14:07:05 -070021
22#include <phosphor-logging/elog-errors.hpp>
Matt Spinlerf9c83c42017-08-10 08:51:45 -050023#include "config.h"
Brad Bishope55ef3d2016-12-19 09:12:40 -050024#include "sensorset.hpp"
Brad Bishope55ef3d2016-12-19 09:12:40 -050025#include "hwmon.hpp"
26#include "sysfs.hpp"
Brad Bishopd499ca62016-12-19 09:24:50 -050027#include "mainloop.hpp"
Brad Bishopf3df6b42017-01-06 10:14:09 -050028#include "env.hpp"
Brad Bishope0b7d052017-01-06 15:30:23 -050029#include "thresholds.hpp"
Matthew Barthbf7b7b12017-03-07 15:46:59 -060030#include "targets.hpp"
Matthew Barth048ac872017-03-09 14:36:08 -060031#include "fan_speed.hpp"
Patrick Venture9331ab72018-01-29 09:48:47 -080032#include "fan_pwm.hpp"
Brad Bishope55ef3d2016-12-19 09:12:40 -050033
Patrick Venture1e6324f2017-06-01 14:07:05 -070034#include <xyz/openbmc_project/Sensor/Device/error.hpp>
35
36using namespace phosphor::logging;
37
Saqib Khan973886d2017-03-15 14:01:16 -050038// Initialization for Warning Objects
39decltype(Thresholds<WarningObject>::setLo) Thresholds<WarningObject>::setLo =
40 &WarningObject::warningLow;
41decltype(Thresholds<WarningObject>::setHi) Thresholds<WarningObject>::setHi =
42 &WarningObject::warningHigh;
43decltype(Thresholds<WarningObject>::getLo) Thresholds<WarningObject>::getLo =
44 &WarningObject::warningLow;
45decltype(Thresholds<WarningObject>::getHi) Thresholds<WarningObject>::getHi =
46 &WarningObject::warningHigh;
47decltype(Thresholds<WarningObject>::alarmLo) Thresholds<WarningObject>::alarmLo =
48 &WarningObject::warningAlarmLow;
49decltype(Thresholds<WarningObject>::alarmHi) Thresholds<WarningObject>::alarmHi =
50 &WarningObject::warningAlarmHigh;
51
52// Initialization for Critical Objects
53decltype(Thresholds<CriticalObject>::setLo) Thresholds<CriticalObject>::setLo =
54 &CriticalObject::criticalLow;
55decltype(Thresholds<CriticalObject>::setHi) Thresholds<CriticalObject>::setHi =
56 &CriticalObject::criticalHigh;
57decltype(Thresholds<CriticalObject>::getLo) Thresholds<CriticalObject>::getLo =
58 &CriticalObject::criticalLow;
59decltype(Thresholds<CriticalObject>::getHi) Thresholds<CriticalObject>::getHi =
60 &CriticalObject::criticalHigh;
61decltype(Thresholds<CriticalObject>::alarmLo) Thresholds<CriticalObject>::alarmLo =
62 &CriticalObject::criticalAlarmLow;
63decltype(Thresholds<CriticalObject>::alarmHi) Thresholds<CriticalObject>::alarmHi =
64 &CriticalObject::criticalAlarmHigh;
65
Chiabing Leec923ce92017-09-06 15:58:26 +080066// The gain and offset to adjust a value
67struct valueAdjust
68{
69 double gain = 1.0;
70 int offset = 0;
71};
72
73// Store the valueAdjust for sensors
74std::map<SensorSet::key_type, valueAdjust> sensorAdjusts;
75
Brad Bishop74aa4dd2017-01-06 09:50:31 -050076static constexpr auto typeAttrMap =
77{
78 // 1 - hwmon class
79 // 2 - unit
80 // 3 - sysfs scaling factor
81 std::make_tuple(
82 hwmon::type::ctemp,
83 ValueInterface::Unit::DegreesC,
Brad Bishopadd98512017-01-06 22:01:19 -050084 -3,
85 "temperature"),
Brad Bishop74aa4dd2017-01-06 09:50:31 -050086 std::make_tuple(
87 hwmon::type::cfan,
88 ValueInterface::Unit::RPMS,
Brad Bishopadd98512017-01-06 22:01:19 -050089 0,
90 "fan_tach"),
Brad Bishop74aa4dd2017-01-06 09:50:31 -050091 std::make_tuple(
92 hwmon::type::cvolt,
93 ValueInterface::Unit::Volts,
Brad Bishopadd98512017-01-06 22:01:19 -050094 -3,
95 "voltage"),
Brad Bishop5afe21a2017-01-06 20:44:05 -050096 std::make_tuple(
97 hwmon::type::ccurr,
98 ValueInterface::Unit::Amperes,
Brad Bishopadd98512017-01-06 22:01:19 -050099 -3,
100 "current"),
Brad Bishop5afe21a2017-01-06 20:44:05 -0500101 std::make_tuple(
102 hwmon::type::cenergy,
103 ValueInterface::Unit::Joules,
Brad Bishopadd98512017-01-06 22:01:19 -0500104 -6,
105 "energy"),
Brad Bishop5afe21a2017-01-06 20:44:05 -0500106 std::make_tuple(
107 hwmon::type::cpower,
108 ValueInterface::Unit::Watts,
Brad Bishopadd98512017-01-06 22:01:19 -0500109 -6,
110 "power"),
Brad Bishop74aa4dd2017-01-06 09:50:31 -0500111};
112
113auto getHwmonType(decltype(typeAttrMap)::const_reference attrs)
114{
115 return std::get<0>(attrs);
116}
117
118auto getUnit(decltype(typeAttrMap)::const_reference attrs)
119{
120 return std::get<1>(attrs);
121}
122
123auto getScale(decltype(typeAttrMap)::const_reference attrs)
124{
125 return std::get<2>(attrs);
126}
127
Brad Bishopadd98512017-01-06 22:01:19 -0500128auto getNamespace(decltype(typeAttrMap)::const_reference attrs)
129{
130 return std::get<3>(attrs);
131}
132
Brad Bishop951a79e2017-01-06 21:55:11 -0500133using AttributeIterator = decltype(*typeAttrMap.begin());
134using Attributes
135 = std::remove_cv<std::remove_reference<AttributeIterator>::type>::type;
136
137auto getAttributes(const std::string& type, Attributes& attributes)
138{
139 // *INDENT-OFF*
140 auto a = std::find_if(
141 typeAttrMap.begin(),
142 typeAttrMap.end(),
143 [&](const auto & e)
144 {
145 return type == getHwmonType(e);
146 });
147 // *INDENT-ON*
148
149 if (a == typeAttrMap.end())
150 {
151 return false;
152 }
153
154 attributes = *a;
155 return true;
156}
157
Matt Spinlerfee106b2017-11-29 15:18:05 -0600158int64_t adjustValue(const SensorSet::key_type& sensor, int64_t value)
Chiabing Leec923ce92017-09-06 15:58:26 +0800159{
Patrick Venturec1cece72017-11-07 12:09:49 -0800160// Because read doesn't have an out pointer to store errors.
161// let's assume negative values are errors if they have this
162// set.
163#ifdef NEGATIVE_ERRNO_ON_FAIL
164 if (value < 0)
165 {
166 return value;
167 }
168#endif
169
Chiabing Leec923ce92017-09-06 15:58:26 +0800170 const auto& it = sensorAdjusts.find(sensor);
171 if (it != sensorAdjusts.end())
172 {
173 // Adjust based on gain and offset
174 value = static_cast<decltype(value)>(
175 static_cast<double>(value) * it->second.gain
176 + it->second.offset);
177 }
178 return value;
179}
180
Brad Bishope9fdee02017-01-06 10:43:29 -0500181auto addValue(const SensorSet::key_type& sensor,
Brad Bishop751043e2017-08-29 11:13:46 -0400182 const std::string& devPath,
183 sysfs::hwmonio::HwmonIO& ioAccess,
Matthew Bartha23babd2018-03-16 10:03:27 -0500184 ObjectInfo& info,
185 bool isOCC = false)
Brad Bishope9fdee02017-01-06 10:43:29 -0500186{
Brad Bishop30dbcee2017-01-18 07:55:42 -0500187 static constexpr bool deferSignals = true;
188
Brad Bishope9fdee02017-01-06 10:43:29 -0500189 // Get the initial value for the value interface.
190 auto& bus = *std::get<sdbusplus::bus::bus*>(info);
191 auto& obj = std::get<Object>(info);
192 auto& objPath = std::get<std::string>(info);
193
Matt Spinlerfee106b2017-11-29 15:18:05 -0600194 int64_t val = 0;
Brad Bishop751043e2017-08-29 11:13:46 -0400195 try
196 {
197 // Retry for up to a second if device is busy
Brad Bishop754d38c2017-09-08 00:46:58 -0400198 // or has a transient error.
199 val = ioAccess.read(
Brad Bishop751043e2017-08-29 11:13:46 -0400200 sensor.first,
201 sensor.second,
Brad Bishop754d38c2017-09-08 00:46:58 -0400202 hwmon::entry::cinput,
203 sysfs::hwmonio::retries,
Matthew Bartha23babd2018-03-16 10:03:27 -0500204 sysfs::hwmonio::delay,
205 isOCC);
Brad Bishop751043e2017-08-29 11:13:46 -0400206 }
207 catch (const std::system_error& e)
208 {
209 using namespace sdbusplus::xyz::openbmc_project::Sensor::Device::Error;
210 report<ReadFailure>(
211 xyz::openbmc_project::Sensor::Device::
212 ReadFailure::CALLOUT_ERRNO(e.code().value()),
213 xyz::openbmc_project::Sensor::Device::
214 ReadFailure::CALLOUT_DEVICE_PATH(devPath.c_str()));
215
Matt Spinler9b65f762017-10-05 10:36:22 -0500216 auto file = sysfs::make_sysfs_path(
217 ioAccess.path(),
218 sensor.first,
219 sensor.second,
220 hwmon::entry::cinput);
221
222 log<level::INFO>("Logging failing sysfs file",
223 entry("FILE=%s", file.c_str()));
224
Brad Bishop751043e2017-08-29 11:13:46 -0400225 return static_cast<std::shared_ptr<ValueObject>>(nullptr);
Patrick Venture1e6324f2017-06-01 14:07:05 -0700226 }
227
Chiabing Leec923ce92017-09-06 15:58:26 +0800228 auto gain = getEnv("GAIN", sensor);
229 if (!gain.empty())
230 {
231 sensorAdjusts[sensor].gain = std::stod(gain);
232 }
233
234 auto offset = getEnv("OFFSET", sensor);
235 if (!offset.empty())
236 {
237 sensorAdjusts[sensor].offset = std::stoi(offset);
238 }
239
240 val = adjustValue(sensor, val);
241
Brad Bishop30dbcee2017-01-18 07:55:42 -0500242 auto iface = std::make_shared<ValueObject>(bus, objPath.c_str(), deferSignals);
Brad Bishope9fdee02017-01-06 10:43:29 -0500243 iface->value(val);
244
Brad Bishop951a79e2017-01-06 21:55:11 -0500245 Attributes attrs;
246 if (getAttributes(sensor.first, attrs))
Brad Bishope9fdee02017-01-06 10:43:29 -0500247 {
Brad Bishop951a79e2017-01-06 21:55:11 -0500248 iface->unit(getUnit(attrs));
249 iface->scale(getScale(attrs));
Brad Bishope9fdee02017-01-06 10:43:29 -0500250 }
251
James Feist7bd5fcf2018-01-22 16:14:28 -0800252 auto maxValue = getEnv("MAXVALUE", sensor);
253 if(!maxValue.empty())
254 {
255 iface->maxValue(std::stoll(maxValue));
256 }
257 auto minValue = getEnv("MINVALUE", sensor);
258 if(!minValue.empty())
259 {
260 iface->minValue(std::stoll(minValue));
261 }
262
Brad Bishope9fdee02017-01-06 10:43:29 -0500263 obj[InterfaceType::VALUE] = iface;
264 return iface;
265}
266
Brad Bishopb9e2b072016-12-19 13:47:10 -0500267MainLoop::MainLoop(
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500268 sdbusplus::bus::bus&& bus,
Brad Bishopb9e2b072016-12-19 13:47:10 -0500269 const std::string& path,
Brad Bishopf3aa9ae2017-08-25 09:56:02 -0400270 const std::string& devPath,
Brad Bishopb9e2b072016-12-19 13:47:10 -0500271 const char* prefix,
272 const char* root)
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500273 : _bus(std::move(bus)),
Brad Bishop03e87352017-03-07 00:12:22 -0500274 _manager(_bus, root),
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500275 _shutdown(false),
Brad Bishopb8740fc2017-02-24 23:38:37 -0500276 _hwmonRoot(),
277 _instance(),
Brad Bishopf3aa9ae2017-08-25 09:56:02 -0400278 _devPath(devPath),
Brad Bishopb9e2b072016-12-19 13:47:10 -0500279 _prefix(prefix),
Brad Bishop3c344d32017-01-05 11:48:39 -0500280 _root(root),
Brad Bishop751043e2017-08-29 11:13:46 -0400281 state(),
282 ioAccess(path)
Brad Bishopd499ca62016-12-19 09:24:50 -0500283{
Matthew Bartha23babd2018-03-16 10:03:27 -0500284 if (path.find("occ") != std::string::npos)
285 {
286 _isOCC = true;
287 }
288
Brad Bishopb8740fc2017-02-24 23:38:37 -0500289 std::string p = path;
290 while (!p.empty() && p.back() == '/')
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500291 {
Brad Bishopb8740fc2017-02-24 23:38:37 -0500292 p.pop_back();
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500293 }
Brad Bishopb8740fc2017-02-24 23:38:37 -0500294
295 auto n = p.rfind('/');
296 if (n != std::string::npos)
297 {
298 _instance.assign(p.substr(n + 1));
299 _hwmonRoot.assign(p.substr(0, n));
300 }
301
302 assert(!_instance.empty());
303 assert(!_hwmonRoot.empty());
Brad Bishopd499ca62016-12-19 09:24:50 -0500304}
305
306void MainLoop::shutdown() noexcept
307{
308 _shutdown = true;
309}
310
311void MainLoop::run()
Brad Bishope55ef3d2016-12-19 09:12:40 -0500312{
Matt Spinlera7e2c1e2018-02-23 12:18:19 -0600313 //If this device supports target speeds,
314 //check which type to use.
315 targetType fanTargetType = targetType::DEFAULT;
316 auto targetMode = getenv("TARGET_MODE");
317 if (targetMode)
318 {
319 std::string type{targetMode};
320 std::transform(type.begin(), type.end(), type.begin(), toupper);
321
322 if (type == RPM_TARGET)
323 {
324 fanTargetType = targetType::RPM;
325 }
326 else if (type == PWM_TARGET)
327 {
328 fanTargetType = targetType::PWM;
329 }
330 else
331 {
332 log<level::ERR>(
333 "Invalid TARGET_MODE env var found",
334 entry("TARGET_MODE=%s", targetMode),
335 entry("DEVPATH=%s", _devPath.c_str()));
336 }
337 }
338
Brad Bishope55ef3d2016-12-19 09:12:40 -0500339 // Check sysfs for available sensors.
Brad Bishop4db64422017-02-16 11:33:32 -0500340 auto sensors = std::make_unique<SensorSet>(_hwmonRoot + '/' + _instance);
Brad Bishope55ef3d2016-12-19 09:12:40 -0500341
Brad Bishop75b4ab82017-01-06 09:33:50 -0500342 for (auto& i : *sensors)
343 {
Tom Joseph1f8a9582017-06-12 20:10:59 +0530344 std::string label;
Matt Spinler4b68c4e2017-10-12 16:44:53 -0500345 std::string id;
Brad Bishopf3df6b42017-01-06 10:14:09 -0500346
Tom Joseph1f8a9582017-06-12 20:10:59 +0530347 /*
348 * Check if the value of the MODE_<item><X> env variable for the sensor
349 * is "label", then read the sensor number from the <item><X>_label
350 * file. The name of the DBUS object would be the value of the env
351 * variable LABEL_<item><sensorNum>. If the MODE_<item><X> env variable
Matt Spinler4b68c4e2017-10-12 16:44:53 -0500352 * doesn't exist, then the name of DBUS object is the value of the env
Tom Joseph1f8a9582017-06-12 20:10:59 +0530353 * variable LABEL_<item><X>.
354 */
355 auto mode = getEnv("MODE", i.first);
356 if (!mode.compare(hwmon::entry::label))
Brad Bishop73831cd2017-01-06 09:37:22 -0500357 {
Matt Spinler4b68c4e2017-10-12 16:44:53 -0500358 id = getIndirectID(
359 _hwmonRoot + '/' + _instance + '/', i.first);
360
361 if (id.empty())
Tom Joseph1f8a9582017-06-12 20:10:59 +0530362 {
363 continue;
364 }
365 }
Matt Spinler4b68c4e2017-10-12 16:44:53 -0500366
367 //In this loop, use the ID we looked up above if
368 //there was one, otherwise use the standard one.
369 id = (id.empty()) ? i.first.second : id;
370
371 // Ignore inputs without a label.
372 label = getEnv("LABEL", i.first.first, id);
373 if (label.empty())
Tom Joseph1f8a9582017-06-12 20:10:59 +0530374 {
Matt Spinler4b68c4e2017-10-12 16:44:53 -0500375 continue;
Brad Bishop73831cd2017-01-06 09:37:22 -0500376 }
377
Brad Bishopadd98512017-01-06 22:01:19 -0500378 Attributes attrs;
379 if (!getAttributes(i.first.first, attrs))
380 {
381 continue;
382 }
383
Brad Bishop075f7a22017-01-06 09:45:08 -0500384 std::string objectPath{_root};
Brad Bishopb8740fc2017-02-24 23:38:37 -0500385 objectPath.append(1, '/');
Brad Bishopadd98512017-01-06 22:01:19 -0500386 objectPath.append(getNamespace(attrs));
Brad Bishopb8740fc2017-02-24 23:38:37 -0500387 objectPath.append(1, '/');
Brad Bishop075f7a22017-01-06 09:45:08 -0500388 objectPath.append(label);
389
Brad Bishopf7426cf2017-01-06 15:36:43 -0500390 ObjectInfo info(&_bus, std::move(objectPath), Object());
Matthew Bartha23babd2018-03-16 10:03:27 -0500391 auto valueInterface = addValue(i.first, _devPath, ioAccess, info,
392 _isOCC);
Patrick Venture1e6324f2017-06-01 14:07:05 -0700393 if (!valueInterface)
394 {
Matt Spinlerf9c83c42017-08-10 08:51:45 -0500395#ifdef REMOVE_ON_FAIL
Patrick Venture1e6324f2017-06-01 14:07:05 -0700396 continue; /* skip adding this sensor for now. */
Matt Spinlerf9c83c42017-08-10 08:51:45 -0500397#else
398 exit(EXIT_FAILURE);
399#endif
Patrick Venture1e6324f2017-06-01 14:07:05 -0700400 }
Brad Bishope0b7d052017-01-06 15:30:23 -0500401 auto sensorValue = valueInterface->value();
Matt Spinlerccfc77b2017-10-12 16:49:24 -0500402 addThreshold<WarningObject>(i.first.first, id, sensorValue, info);
403 addThreshold<CriticalObject>(i.first.first, id, sensorValue, info);
Matt Spinlera3eb8e32017-10-12 16:42:49 -0500404
Matt Spinlera7e2c1e2018-02-23 12:18:19 -0600405 if ((fanTargetType == targetType::RPM) ||
406 (fanTargetType == targetType::DEFAULT))
Matt Spinler0a8de642017-05-11 10:59:39 -0500407 {
Matt Spinlera7e2c1e2018-02-23 12:18:19 -0600408 auto target = addTarget<hwmon::FanSpeed>(
409 i.first, ioAccess, _devPath, info);
410
411 if (target)
412 {
413 target->enable();
414 }
Matt Spinler0a8de642017-05-11 10:59:39 -0500415 }
Brad Bishop075f7a22017-01-06 09:45:08 -0500416
Matt Spinlera7e2c1e2018-02-23 12:18:19 -0600417 if ((fanTargetType == targetType::PWM) ||
418 (fanTargetType == targetType::DEFAULT))
419 {
420 addTarget<hwmon::FanPwm>(i.first, ioAccess, _devPath, info);
421 }
Patrick Venture9331ab72018-01-29 09:48:47 -0800422
Brad Bishop30dbcee2017-01-18 07:55:42 -0500423 // All the interfaces have been created. Go ahead
424 // and emit InterfacesAdded.
425 valueInterface->emit_object_added();
426
Brad Bishop075f7a22017-01-06 09:45:08 -0500427 auto value = std::make_tuple(
428 std::move(i.second),
429 std::move(label),
Brad Bishopf7426cf2017-01-06 15:36:43 -0500430 std::move(info));
Brad Bishop73831cd2017-01-06 09:37:22 -0500431
Brad Bishop75b4ab82017-01-06 09:33:50 -0500432 state[std::move(i.first)] = std::move(value);
433 }
434
Patrick Venture62503a42017-05-23 07:30:29 -0700435 /* If there are no sensors specified by labels, exit. */
436 if (0 == state.size())
437 {
438 return;
439 }
440
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500441 {
Brad Bishopb8740fc2017-02-24 23:38:37 -0500442 std::string busname{_prefix};
Brad Bishop4d9a35b2017-11-14 22:33:03 -0500443 busname.append(1, '-');
444 busname.append(
445 std::to_string(std::hash<decltype(_devPath)>{}(_devPath)));
446 busname.append(".Hwmon1");
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500447 _bus.request_name(busname.c_str());
448 }
449
Patrick Ventureab10f162017-05-22 09:44:50 -0700450 {
451 auto interval = getenv("INTERVAL");
452 if (interval)
453 {
454 _interval = strtoull(interval, NULL, 10);
455 }
456 }
457
Brad Bishope55ef3d2016-12-19 09:12:40 -0500458 // TODO: Issue#3 - Need to make calls to the dbus sensor cache here to
459 // ensure the objects all exist?
460
461 // Polling loop.
Brad Bishopd499ca62016-12-19 09:24:50 -0500462 while (!_shutdown)
Brad Bishope55ef3d2016-12-19 09:12:40 -0500463 {
Matt Spinlerf9c83c42017-08-10 08:51:45 -0500464#ifdef REMOVE_ON_FAIL
Patrick Venture1e6324f2017-06-01 14:07:05 -0700465 std::vector<SensorSet::key_type> destroy;
Matt Spinlerf9c83c42017-08-10 08:51:45 -0500466#endif
Brad Bishope55ef3d2016-12-19 09:12:40 -0500467 // Iterate through all the sensors.
Brad Bishop75b4ab82017-01-06 09:33:50 -0500468 for (auto& i : state)
Brad Bishope55ef3d2016-12-19 09:12:40 -0500469 {
Brad Bishop75b4ab82017-01-06 09:33:50 -0500470 auto& attrs = std::get<0>(i.second);
471 if (attrs.find(hwmon::entry::input) != attrs.end())
Brad Bishope55ef3d2016-12-19 09:12:40 -0500472 {
473 // Read value from sensor.
Matt Spinlerfee106b2017-11-29 15:18:05 -0600474 int64_t value;
Patrick Venture9331ab72018-01-29 09:48:47 -0800475 std::string input = hwmon::entry::cinput;
476 if (i.first.first == "pwm") {
477 input = "";
478 }
479
Patrick Venture1e6324f2017-06-01 14:07:05 -0700480 try
Brad Bishopdddb7152017-01-06 09:54:23 -0500481 {
Brad Bishop754d38c2017-09-08 00:46:58 -0400482 // Retry for up to a second if device is busy
483 // or has a transient error.
484
Brad Bishop751043e2017-08-29 11:13:46 -0400485 value = ioAccess.read(
486 i.first.first,
487 i.first.second,
Patrick Venture9331ab72018-01-29 09:48:47 -0800488 input,
Brad Bishop754d38c2017-09-08 00:46:58 -0400489 sysfs::hwmonio::retries,
Matthew Bartha23babd2018-03-16 10:03:27 -0500490 sysfs::hwmonio::delay,
491 _isOCC);
Brad Bishope0b7d052017-01-06 15:30:23 -0500492
Chiabing Leec923ce92017-09-06 15:58:26 +0800493 value = adjustValue(i.first, value);
494
Patrick Venture1e6324f2017-06-01 14:07:05 -0700495 auto& objInfo = std::get<ObjectInfo>(i.second);
496 auto& obj = std::get<Object>(objInfo);
497
498 for (auto& iface : obj)
Brad Bishope0b7d052017-01-06 15:30:23 -0500499 {
Patrick Venture1e6324f2017-06-01 14:07:05 -0700500 auto valueIface = std::shared_ptr<ValueObject>();
501 auto warnIface = std::shared_ptr<WarningObject>();
502 auto critIface = std::shared_ptr<CriticalObject>();
503
504 switch (iface.first)
505 {
506 case InterfaceType::VALUE:
507 valueIface = std::experimental::any_cast<std::shared_ptr<ValueObject>>
508 (iface.second);
509 valueIface->value(value);
510 break;
511 case InterfaceType::WARN:
512 checkThresholds<WarningObject>(iface.second, value);
513 break;
514 case InterfaceType::CRIT:
515 checkThresholds<CriticalObject>(iface.second, value);
516 break;
517 default:
518 break;
519 }
Brad Bishope0b7d052017-01-06 15:30:23 -0500520 }
Brad Bishopdddb7152017-01-06 09:54:23 -0500521 }
Brad Bishop751043e2017-08-29 11:13:46 -0400522 catch (const std::system_error& e)
Patrick Venture1e6324f2017-06-01 14:07:05 -0700523 {
Brad Bishop751043e2017-08-29 11:13:46 -0400524 using namespace sdbusplus::xyz::openbmc_project::
525 Sensor::Device::Error;
526 report<ReadFailure>(
527 xyz::openbmc_project::Sensor::Device::
528 ReadFailure::CALLOUT_ERRNO(e.code().value()),
529 xyz::openbmc_project::Sensor::Device::
530 ReadFailure::CALLOUT_DEVICE_PATH(
531 _devPath.c_str()));
Matt Spinler9b65f762017-10-05 10:36:22 -0500532
533 auto file = sysfs::make_sysfs_path(
534 ioAccess.path(),
535 i.first.first,
536 i.first.second,
537 hwmon::entry::cinput);
538
539 log<level::INFO>("Logging failing sysfs file",
540 entry("FILE=%s", file.c_str()));
541
Matt Spinlerf9c83c42017-08-10 08:51:45 -0500542#ifdef REMOVE_ON_FAIL
Patrick Venture1e6324f2017-06-01 14:07:05 -0700543 destroy.push_back(i.first);
Matt Spinlerf9c83c42017-08-10 08:51:45 -0500544#else
545 exit(EXIT_FAILURE);
546#endif
Patrick Venture1e6324f2017-06-01 14:07:05 -0700547 }
Brad Bishope55ef3d2016-12-19 09:12:40 -0500548 }
549 }
550
Matt Spinlerf9c83c42017-08-10 08:51:45 -0500551#ifdef REMOVE_ON_FAIL
Patrick Venture1e6324f2017-06-01 14:07:05 -0700552 for (auto& i : destroy)
553 {
554 state.erase(i);
555 }
Matt Spinlerf9c83c42017-08-10 08:51:45 -0500556#endif
Patrick Venture1e6324f2017-06-01 14:07:05 -0700557
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500558 // Respond to DBus
559 _bus.process_discard();
560
Brad Bishope55ef3d2016-12-19 09:12:40 -0500561 // Sleep until next interval.
Brad Bishope55ef3d2016-12-19 09:12:40 -0500562 // TODO: Issue#6 - Optionally look at polling interval sysfs entry.
Patrick Ventureab10f162017-05-22 09:44:50 -0700563 _bus.wait(_interval);
Brad Bishope55ef3d2016-12-19 09:12:40 -0500564
565 // TODO: Issue#7 - Should probably periodically check the SensorSet
566 // for new entries.
567 }
Brad Bishope55ef3d2016-12-19 09:12:40 -0500568}
569
570// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4