blob: a59fc1ed484c46aa1a5a3b42bab82f17d6a840cf [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 */
16#include <iostream>
17#include <memory>
Brad Bishop9c7b6e02016-12-19 12:43:36 -050018#include <cstring>
19#include <cstdlib>
20#include <chrono>
Brad Bishop74aa4dd2017-01-06 09:50:31 -050021#include <algorithm>
Brad Bishope55ef3d2016-12-19 09:12:40 -050022#include "sensorset.hpp"
Brad Bishope55ef3d2016-12-19 09:12:40 -050023#include "hwmon.hpp"
24#include "sysfs.hpp"
Brad Bishopd499ca62016-12-19 09:24:50 -050025#include "mainloop.hpp"
Brad Bishopab795a12017-01-05 20:50:49 -050026#include "util.hpp"
Brad Bishopf3df6b42017-01-06 10:14:09 -050027#include "env.hpp"
Brad Bishope55ef3d2016-12-19 09:12:40 -050028
Brad Bishop9c7b6e02016-12-19 12:43:36 -050029using namespace std::literals::chrono_literals;
30
Brad Bishop74aa4dd2017-01-06 09:50:31 -050031static constexpr auto typeAttrMap =
32{
33 // 1 - hwmon class
34 // 2 - unit
35 // 3 - sysfs scaling factor
36 std::make_tuple(
37 hwmon::type::ctemp,
38 ValueInterface::Unit::DegreesC,
39 -3),
40 std::make_tuple(
41 hwmon::type::cfan,
42 ValueInterface::Unit::RPMS,
43 0),
44 std::make_tuple(
45 hwmon::type::cvolt,
46 ValueInterface::Unit::Volts,
47 -3),
48};
49
50auto getHwmonType(decltype(typeAttrMap)::const_reference attrs)
51{
52 return std::get<0>(attrs);
53}
54
55auto getUnit(decltype(typeAttrMap)::const_reference attrs)
56{
57 return std::get<1>(attrs);
58}
59
60auto getScale(decltype(typeAttrMap)::const_reference attrs)
61{
62 return std::get<2>(attrs);
63}
64
Brad Bishopb9e2b072016-12-19 13:47:10 -050065MainLoop::MainLoop(
Brad Bishop9c7b6e02016-12-19 12:43:36 -050066 sdbusplus::bus::bus&& bus,
Brad Bishopb9e2b072016-12-19 13:47:10 -050067 const std::string& path,
68 const char* prefix,
69 const char* root)
Brad Bishop9c7b6e02016-12-19 12:43:36 -050070 : _bus(std::move(bus)),
71 _manager(sdbusplus::server::manager::manager(_bus, root)),
72 _shutdown(false),
Brad Bishopb9e2b072016-12-19 13:47:10 -050073 _path(path),
74 _prefix(prefix),
Brad Bishop3c344d32017-01-05 11:48:39 -050075 _root(root),
76 state()
Brad Bishopd499ca62016-12-19 09:24:50 -050077{
Brad Bishop9c7b6e02016-12-19 12:43:36 -050078 if (_path.back() == '/')
79 {
80 _path.pop_back();
81 }
Brad Bishopd499ca62016-12-19 09:24:50 -050082}
83
84void MainLoop::shutdown() noexcept
85{
86 _shutdown = true;
87}
88
89void MainLoop::run()
Brad Bishope55ef3d2016-12-19 09:12:40 -050090{
91 // Check sysfs for available sensors.
Brad Bishopd499ca62016-12-19 09:24:50 -050092 auto sensors = std::make_unique<SensorSet>(_path);
Brad Bishope55ef3d2016-12-19 09:12:40 -050093
Brad Bishop75b4ab82017-01-06 09:33:50 -050094 for (auto& i : *sensors)
95 {
Brad Bishopf3df6b42017-01-06 10:14:09 -050096 // Get sensor configuration from the environment.
97
Brad Bishop73831cd2017-01-06 09:37:22 -050098 // Ignore inputs without a label.
Brad Bishopf3df6b42017-01-06 10:14:09 -050099 auto label = getEnv("LABEL", i.first);
Brad Bishop73831cd2017-01-06 09:37:22 -0500100 if (label.empty())
101 {
102 continue;
103 }
104
Brad Bishop47378502017-01-06 09:47:41 -0500105 // Get the initial value for the value interface.
106 auto sysfsPath = make_sysfs_path(
107 _path,
108 i.first.first,
109 i.first.second,
110 hwmon::entry::input);
111 int val = 0;
112 read_sysfs(sysfsPath, val);
113
Brad Bishop075f7a22017-01-06 09:45:08 -0500114 std::string objectPath{_root};
Brad Bishop075f7a22017-01-06 09:45:08 -0500115 objectPath.append("/");
116 objectPath.append(i.first.first);
117 objectPath.append("/");
118 objectPath.append(label);
119
Brad Bishopf7426cf2017-01-06 15:36:43 -0500120 ObjectInfo info(&_bus, std::move(objectPath), Object());
121 auto& o = std::get<Object>(info);
122
Brad Bishop075f7a22017-01-06 09:45:08 -0500123 auto iface = std::make_shared<ValueObject>(_bus, objectPath.c_str());
Brad Bishop47378502017-01-06 09:47:41 -0500124 iface->value(val);
Brad Bishop74aa4dd2017-01-06 09:50:31 -0500125
126 const auto& attrs = std::find_if(
127 typeAttrMap.begin(),
128 typeAttrMap.end(),
129 [&](const auto & e)
130 {
131 return i.first.first == getHwmonType(e);
132 });
133 if (attrs != typeAttrMap.end())
134 {
135 iface->unit(getUnit(*attrs));
136 iface->scale(getScale(*attrs));
137 }
138
Brad Bishop075f7a22017-01-06 09:45:08 -0500139 o.emplace(InterfaceType::VALUE, iface);
140
141 auto value = std::make_tuple(
142 std::move(i.second),
143 std::move(label),
Brad Bishopf7426cf2017-01-06 15:36:43 -0500144 std::move(info));
Brad Bishop73831cd2017-01-06 09:37:22 -0500145
Brad Bishop75b4ab82017-01-06 09:33:50 -0500146 state[std::move(i.first)] = std::move(value);
147 }
148
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500149 {
Brad Bishopab795a12017-01-05 20:50:49 -0500150 auto copy = std::unique_ptr<char, phosphor::utility::Free<char>>(strdup(
151 _path.c_str()));
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500152 auto busname = std::string(_prefix) + '.' + basename(copy.get());
153 _bus.request_name(busname.c_str());
154 }
155
Brad Bishope55ef3d2016-12-19 09:12:40 -0500156 // TODO: Issue#3 - Need to make calls to the dbus sensor cache here to
157 // ensure the objects all exist?
158
159 // Polling loop.
Brad Bishopd499ca62016-12-19 09:24:50 -0500160 while (!_shutdown)
Brad Bishope55ef3d2016-12-19 09:12:40 -0500161 {
162 // Iterate through all the sensors.
Brad Bishop75b4ab82017-01-06 09:33:50 -0500163 for (auto& i : state)
Brad Bishope55ef3d2016-12-19 09:12:40 -0500164 {
Brad Bishop75b4ab82017-01-06 09:33:50 -0500165 auto& attrs = std::get<0>(i.second);
166 if (attrs.find(hwmon::entry::input) != attrs.end())
Brad Bishope55ef3d2016-12-19 09:12:40 -0500167 {
168 // Read value from sensor.
169 int value = 0;
Brad Bishopd499ca62016-12-19 09:24:50 -0500170 read_sysfs(make_sysfs_path(_path,
Brad Bishope55ef3d2016-12-19 09:12:40 -0500171 i.first.first, i.first.second,
172 hwmon::entry::input),
173 value);
174
Brad Bishopf7426cf2017-01-06 15:36:43 -0500175 auto& objInfo = std::get<ObjectInfo>(i.second);
176 auto& obj = std::get<Object>(objInfo);
Brad Bishopdddb7152017-01-06 09:54:23 -0500177 auto iface = obj.find(InterfaceType::VALUE);
178
179 if (iface != obj.end())
180 {
181 auto realIface = std::experimental::any_cast<std::shared_ptr<ValueObject>>
182 (iface->second);
183 realIface->value(value);
184 }
Brad Bishope55ef3d2016-12-19 09:12:40 -0500185 }
186 }
187
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500188 // Respond to DBus
189 _bus.process_discard();
190
Brad Bishope55ef3d2016-12-19 09:12:40 -0500191 // Sleep until next interval.
192 // TODO: Issue#5 - Make this configurable.
193 // TODO: Issue#6 - Optionally look at polling interval sysfs entry.
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500194 _bus.wait((1000000us).count());
Brad Bishope55ef3d2016-12-19 09:12:40 -0500195
196 // TODO: Issue#7 - Should probably periodically check the SensorSet
197 // for new entries.
198 }
Brad Bishope55ef3d2016-12-19 09:12:40 -0500199}
200
201// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4