blob: 590ca80c2b8c6ba0759de6e15edab93f11fb4a6a [file] [log] [blame]
Patrick Venture863b9242018-03-08 08:29:23 -08001/**
2 * Copyright 2017 Google Inc.
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
17#include <cstring>
18#include <iostream>
19#include <libconfig.h++>
20#include <map>
21#include <memory>
22
23/* Configuration. */
24#include "conf.hpp"
25
26#include "interfaces.hpp"
27#include "manager.hpp"
28#include "util.hpp"
29
30#include "dbus/dbuspassive.hpp"
31#include "notimpl/readonly.hpp"
32#include "notimpl/writeonly.hpp"
33#include "sysfs/sysfsread.hpp"
34#include "sensors/manager.hpp"
35#include "sensors/host.hpp"
36#include "sensors/pluggable.hpp"
37#include "sysfs/sysfswrite.hpp"
38
39
40static constexpr bool deferSignals = true;
41
42std::shared_ptr<SensorManager> BuildSensors(
43 std::map<std::string, struct sensor>& Config)
44{
45 auto mgmr = std::make_shared<SensorManager>();
46 auto& HostSensorBus = mgmr->getHostBus();
47 auto& PassiveListeningBus = mgmr->getPassiveBus();
48
49 for (auto& it : Config)
50 {
51 std::unique_ptr<ReadInterface> ri;
52 std::unique_ptr<WriteInterface> wi;
53
54 std::string name = it.first;
55 struct sensor* info = &it.second;
56
57 std::cerr << "Sensor: " << name << " " << info->type << " ";
58 std::cerr << info->readpath << " " << info->writepath << "\n";
59
60 IOInterfaceType rtype = GetReadInterfaceType(info->readpath);
61 IOInterfaceType wtype = GetWriteInterfaceType(info->writepath);
62
63 // fan sensors can be ready any way and written others.
64 // fan sensors are the only sensors this is designed to write.
65 // Nothing here should be write-only, although, in theory a fan could be.
66 // I'm just not sure how that would fit together.
67 // TODO(venture): It should check with the ObjectMapper to check if
68 // that sensor exists on the Dbus.
69 switch (rtype)
70 {
71 case IOInterfaceType::DBUSPASSIVE:
72 ri = std::make_unique<DbusPassive>(
73 PassiveListeningBus,
74 info->type,
75 name);
76 break;
77 case IOInterfaceType::EXTERNAL:
78 // These are a special case for read-only.
79 break;
80 case IOInterfaceType::SYSFS:
81 ri = std::make_unique<SysFsRead>(info->readpath);
82 break;
83 default:
84 ri = std::make_unique<WriteOnly>();
85 break;
86 }
87
88 if (info->type == "fan")
89 {
90 switch (wtype)
91 {
92 case IOInterfaceType::SYSFS:
93 if (info->max > 0)
94 {
95 wi = std::make_unique<SysFsWritePercent>(
96 info->writepath,
97 info->min,
98 info->max);
99 }
100 else
101 {
102 wi = std::make_unique<SysFsWrite>(
103 info->writepath,
104 info->min,
105 info->max);
106 }
107
108 break;
109 default:
110 wi = std::make_unique<ReadOnlyNoExcept>();
111 break;
112 }
113
114 auto sensor = std::make_unique<PluggableSensor>(
115 name,
116 info->timeout,
117 std::move(ri),
118 std::move(wi));
119 mgmr->addSensor(info->type, name, std::move(sensor));
120 }
121 else if (info->type == "temp" || info->type == "margin")
122 {
123 // These sensors are read-only, but only for this application
124 // which only writes to fan sensors.
125 std::cerr << info->type << " readpath: " << info->readpath << "\n";
126
127 if (IOInterfaceType::EXTERNAL == rtype)
128 {
129 std::cerr << "Creating HostSensor: " << name
130 << " path: " << info->readpath << "\n";
131
132 /*
133 * The reason we handle this as a HostSensor is because it's
134 * not quite pluggable; but maybe it could be.
135 */
136 auto sensor = HostSensor::CreateTemp(
137 name,
138 info->timeout,
139 HostSensorBus,
140 info->readpath.c_str(),
141 deferSignals);
142 mgmr->addSensor(info->type, name, std::move(sensor));
143 }
144 else
145 {
146 wi = std::make_unique<ReadOnlyNoExcept>();
147 auto sensor = std::make_unique<PluggableSensor>(
148 name,
149 info->timeout,
150 std::move(ri),
151 std::move(wi));
152 mgmr->addSensor(info->type, name, std::move(sensor));
153 }
154 }
155 }
156
157 return mgmr;
158}
159
160/*
161 * If there's a configuration file, we build from that, and it requires special
162 * parsing. I should just ditch the compile-time version to reduce the
163 * probability of sync bugs.
164 */
165std::shared_ptr<SensorManager> BuildSensorsFromConfig(std::string& path)
166{
167 using namespace libconfig;
168
169 std::map<std::string, struct sensor> config;
170 Config cfg;
171
172 std::cerr << "entered BuildSensorsFromConfig\n";
173
174 /* The load was modeled after the example source provided. */
175 try
176 {
177 cfg.readFile(path.c_str());
178 }
179 catch (const FileIOException& fioex)
180 {
181 std::cerr << "I/O error while reading file: " << fioex.what() << std::endl;
182 throw;
183 }
184 catch (const ParseException& pex)
185 {
186 std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
187 << " - " << pex.getError() << std::endl;
188 throw;
189 }
190
191 try
192 {
193 const Setting& root = cfg.getRoot();
194
195 /* Grab the list of sensors and create them all */
196 const Setting& sensors = root["sensors"];
197 int count = sensors.getLength();
198
199 for (int i = 0; i < count; ++i)
200 {
201 const Setting& sensor = sensors[i];
202
203 std::string name;
204 struct sensor thisOne;
205
206 /* Not a super fan of using this library for run-time configuration. */
207 name = sensor.lookup("name").c_str();
208 thisOne.type = sensor.lookup("type").c_str();
209 thisOne.readpath = sensor.lookup("readpath").c_str();
210 thisOne.writepath = sensor.lookup("writepath").c_str();
211
212 /* TODO: Document why this is wonky. The library probably doesn't
213 * like int64_t
214 */
215 int min = sensor.lookup("min");
216 thisOne.min = static_cast<int64_t>(min);
217 int max = sensor.lookup("max");
218 thisOne.max = static_cast<int64_t>(max);
219 int timeout = sensor.lookup("timeout");
220 thisOne.timeout = static_cast<int64_t>(timeout);
221
222 // leaving for verification for now. and yea the above is
223 // necessary.
224 std::cerr << "min: " << min
225 << " max: " << max
226 << " savedmin: " << thisOne.min
227 << " savedmax: " << thisOne.max
228 << " timeout: " << thisOne.timeout
229 << std::endl;
230
231 config[name] = thisOne;
232 }
233 }
234 catch (const SettingTypeException &setex)
235 {
236 std::cerr << "Setting '" << setex.getPath()
237 << "' type exception!" << std::endl;
238 throw;
239 }
240 catch (const SettingNotFoundException& snex)
241 {
242 std::cerr << "Setting not found!" << std::endl;
243 throw;
244 }
245
246 return BuildSensors(config);
247}
248