blob: fb0ede4e4c4161d09b5dc6e163c514d298e50c80 [file] [log] [blame]
James Feist139cb572018-09-10 15:26:18 -07001/*
2// Copyright (c) 2018 Intel 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
17#include <fcntl.h>
18#include <linux/peci-ioctl.h>
19
20#include <CPUSensor.hpp>
21#include <Utils.hpp>
22#include <VariantVisitors.hpp>
23#include <boost/algorithm/string/predicate.hpp>
24#include <boost/algorithm/string/replace.hpp>
25#include <boost/container/flat_set.hpp>
26#include <boost/date_time/posix_time/posix_time.hpp>
27#include <boost/process/child.hpp>
28#include <experimental/filesystem>
29#include <fstream>
30#include <regex>
31#include <sdbusplus/asio/connection.hpp>
32#include <sdbusplus/asio/object_server.hpp>
33
34static constexpr bool DEBUG = false;
35
36enum State
37{
38 OFF, // host powered down
39 ON, // host powered on
40 READY // host powered on and mem test passed - fully ready
41};
42
43struct CPUConfig
44{
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -070045 CPUConfig(const uint64_t& bus, const uint64_t& addr,
46 const std::string& name, const State& state) :
47 bus(bus),
48 addr(addr), name(name), state(state)
James Feist139cb572018-09-10 15:26:18 -070049 {
50 }
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -070051 int bus;
James Feist139cb572018-09-10 15:26:18 -070052 int addr;
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -070053 std::string name;
James Feist139cb572018-09-10 15:26:18 -070054 State state;
55
56 bool operator<(const CPUConfig& rhs) const
57 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -070058 return (name < rhs.name);
James Feist139cb572018-09-10 15:26:18 -070059 }
60};
61
Yoo, Jae Hyunf033e672018-10-17 12:07:54 -070062static constexpr const char* PECI_DEV = "/dev/peci-0";
James Feist139cb572018-09-10 15:26:18 -070063static constexpr const unsigned int RANK_NUM_MAX = 8;
64
65namespace fs = std::experimental::filesystem;
Yoo, Jae Hyun625429b2018-10-17 18:19:02 -070066namespace variant_ns = sdbusplus::message::variant_ns;
James Feist139cb572018-09-10 15:26:18 -070067static constexpr const char* CONFIG_PREFIX =
68 "xyz.openbmc_project.Configuration.";
69static constexpr std::array<const char*, 3> SENSOR_TYPES = {
70 "SkylakeCPU", "BroadwellCPU", "HaswellCPU"};
71
72const static std::regex ILLEGAL_NAME_REGEX("[^A-Za-z0-9_]");
73
Yoo, Jae Hyun60e14d32018-10-10 11:03:11 -070074bool createSensors(
James Feist139cb572018-09-10 15:26:18 -070075 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
76 boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>&
77 sensors,
78 boost::container::flat_set<CPUConfig>& configs,
79 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
80{
81 bool available = false;
82 for (CPUConfig cpu : configs)
83 {
84 if (cpu.state != State::OFF)
85 {
86 available = true;
87 break;
88 }
89 }
90 if (!available)
91 {
Yoo, Jae Hyun60e14d32018-10-10 11:03:11 -070092 return false;
James Feist139cb572018-09-10 15:26:18 -070093 }
94
95 // use new data the first time, then refresh
96 ManagedObjectType sensorConfigurations;
97 bool useCache = false;
98 for (const char* type : SENSOR_TYPES)
99 {
100 if (!getSensorConfiguration(CONFIG_PREFIX + std::string(type),
101 dbusConnection, sensorConfigurations,
102 useCache))
103 {
Yoo, Jae Hyun60e14d32018-10-10 11:03:11 -0700104 return false;
James Feist139cb572018-09-10 15:26:18 -0700105 }
106 useCache = true;
107 }
108
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700109 std::vector<fs::path> hwmonNamePaths;
James Feist139cb572018-09-10 15:26:18 -0700110 if (!find_files(fs::path(R"(/sys/bus/peci/devices)"),
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700111 R"(peci-\d+/\d+-.+/peci-.+/hwmon/hwmon\d+/name$)",
112 hwmonNamePaths, 1))
James Feist139cb572018-09-10 15:26:18 -0700113 {
114 std::cerr << "No CPU sensors in system\n";
Yoo, Jae Hyun60e14d32018-10-10 11:03:11 -0700115 return true;
James Feist139cb572018-09-10 15:26:18 -0700116 }
117
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700118 boost::container::flat_set<std::string> scannedDirectories;
119 boost::container::flat_set<std::string> createdSensors;
120
121 for (fs::path& hwmonNamePath : hwmonNamePaths)
James Feist139cb572018-09-10 15:26:18 -0700122 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700123 const std::string& pathStr = hwmonNamePath.string();
124 auto hwmonDirectory = hwmonNamePath.parent_path();
125
126 auto ret = scannedDirectories.insert(hwmonDirectory.string());
127 if (!ret.second)
James Feist139cb572018-09-10 15:26:18 -0700128 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700129 continue; // already searched this path
130 }
131
132 fs::path::iterator it = hwmonNamePath.begin();
133 std::advance(it, 6); // pick the 6th part for a PECI client device name
134 std::string deviceName = *it;
135 auto findHyphen = deviceName.find("-");
136 if (findHyphen == std::string::npos)
137 {
138 std::cerr << "found bad device " << deviceName << "\n";
James Feist139cb572018-09-10 15:26:18 -0700139 continue;
140 }
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700141 std::string busStr = deviceName.substr(0, findHyphen);
142 std::string addrStr = deviceName.substr(findHyphen + 1);
143
144 size_t bus = 0;
145 size_t addr = 0;
146 try
147 {
148 bus = std::stoi(busStr);
149 addr = std::stoi(addrStr, 0, 16);
150 }
151 catch (std::invalid_argument)
152 {
153 continue;
154 }
155
156 std::ifstream nameFile(hwmonNamePath);
157 if (!nameFile.good())
158 {
159 std::cerr << "Failure reading " << hwmonNamePath << "\n";
160 continue;
161 }
162 std::string hwmonName;
163 std::getline(nameFile, hwmonName);
James Feist139cb572018-09-10 15:26:18 -0700164 nameFile.close();
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700165 if (!hwmonName.size())
James Feist139cb572018-09-10 15:26:18 -0700166 {
167 // shouldn't have an empty name file
168 continue;
169 }
James Feist139cb572018-09-10 15:26:18 -0700170 if (DEBUG)
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700171 {
172 std::cout << "Checking: " << hwmonNamePath << ": " << hwmonName
173 << "\n";
174 }
James Feist139cb572018-09-10 15:26:18 -0700175
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700176 std::string sensorType;
James Feist139cb572018-09-10 15:26:18 -0700177 const SensorData* sensorData = nullptr;
178 const std::string* interfacePath = nullptr;
James Feist139cb572018-09-10 15:26:18 -0700179 const std::pair<std::string, boost::container::flat_map<
180 std::string, BasicVariantType>>*
181 baseConfiguration = nullptr;
James Feist139cb572018-09-10 15:26:18 -0700182
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700183 for (const std::pair<sdbusplus::message::object_path, SensorData>&
184 sensor : sensorConfigurations)
James Feist139cb572018-09-10 15:26:18 -0700185 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700186 sensorData = &(sensor.second);
187 for (const char* type : SENSOR_TYPES)
188 {
189 sensorType = CONFIG_PREFIX + std::string(type);
190 auto sensorBase = sensorData->find(sensorType);
191 if (sensorBase != sensorData->end())
192 {
193 baseConfiguration = &(*sensorBase);
194 break;
195 }
196 }
197 if (baseConfiguration == nullptr)
198 {
199 std::cerr << "error finding base configuration for" << hwmonName
200 << "\n";
201 continue;
202 }
203 auto configurationBus = baseConfiguration->second.find("Bus");
204 auto configurationAddress =
205 baseConfiguration->second.find("Address");
206
207 if (configurationBus == baseConfiguration->second.end() ||
208 configurationAddress == baseConfiguration->second.end())
209 {
210 std::cerr << "error finding bus or address in configuration";
211 continue;
212 }
213
214 if (sdbusplus::message::variant_ns::get<uint64_t>(
215 configurationBus->second) != bus ||
216 sdbusplus::message::variant_ns::get<uint64_t>(
217 configurationAddress->second) != addr)
218 {
219 continue;
220 }
221
222 interfacePath = &(sensor.first.str);
223 break;
224 }
225 if (interfacePath == nullptr)
226 {
227 std::cerr << "failed to find match for " << hwmonName << "\n";
James Feist139cb572018-09-10 15:26:18 -0700228 continue;
229 }
230
231 auto findCpuId = baseConfiguration->second.find("CpuID");
232 if (findCpuId == baseConfiguration->second.end())
233 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700234 std::cerr << "could not determine CPU ID for " << hwmonName << "\n";
James Feist139cb572018-09-10 15:26:18 -0700235 continue;
236 }
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700237 int cpuId =
238 variant_ns::visit(VariantToUnsignedIntVisitor(), findCpuId->second);
James Feist139cb572018-09-10 15:26:18 -0700239
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700240 auto directory = hwmonNamePath.parent_path();
James Feist139cb572018-09-10 15:26:18 -0700241 std::vector<fs::path> inputPaths;
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700242 if (!find_files(fs::path(directory), R"(temp\d+_input$)", inputPaths,
James Feist139cb572018-09-10 15:26:18 -0700243 0))
244 {
245 std::cerr << "No temperature sensors in system\n";
246 continue;
247 }
248
249 // iterate through all found temp sensors
250 for (auto& inputPath : inputPaths)
251 {
252 auto inputPathStr = inputPath.string();
253 auto labelPath =
254 boost::replace_all_copy(inputPathStr, "input", "label");
255 std::ifstream labelFile(labelPath);
256 if (!labelFile.good())
257 {
258 std::cerr << "Failure reading " << labelPath << "\n";
259 continue;
260 }
261 std::string label;
262 std::getline(labelFile, label);
263 labelFile.close();
264 std::string sensorName = label + " CPU" + std::to_string(cpuId);
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700265
266 auto findSensor = sensors.find(sensorName);
267 if (findSensor != sensors.end())
268 {
269 if (DEBUG)
270 {
271 std::cout << "Skipped: " << inputPath << ": " << sensorName
272 << " is already created\n";
273 }
274 continue;
275 }
276
James Feist139cb572018-09-10 15:26:18 -0700277 std::vector<thresholds::Threshold> sensorThresholds;
278 std::string labelHead = label.substr(0, label.find(" "));
Yoo, Jae Hyunac18e142018-10-09 16:38:58 -0700279 ParseThresholdsFromConfig(*sensorData, sensorThresholds,
280 &labelHead);
James Feist139cb572018-09-10 15:26:18 -0700281 if (!sensorThresholds.size())
282 {
283 if (!ParseThresholdsFromAttr(sensorThresholds, inputPathStr,
284 CPUSensor::SENSOR_SCALE_FACTOR))
285 {
Yoo, Jae Hyunac18e142018-10-09 16:38:58 -0700286 std::cerr << "error populating thresholds for "
287 << sensorName << "\n";
James Feist139cb572018-09-10 15:26:18 -0700288 }
289 }
290 sensors[sensorName] = std::make_unique<CPUSensor>(
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700291 inputPathStr, sensorType, objectServer, dbusConnection, io,
292 sensorName, std::move(sensorThresholds), *interfacePath);
293 createdSensors.insert(sensorName);
James Feist139cb572018-09-10 15:26:18 -0700294 if (DEBUG)
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700295 {
James Feist139cb572018-09-10 15:26:18 -0700296 std::cout << "Mapped: " << inputPath << " to " << sensorName
297 << "\n";
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700298 }
James Feist139cb572018-09-10 15:26:18 -0700299 }
300 }
Yoo, Jae Hyun60e14d32018-10-10 11:03:11 -0700301
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700302 if (createdSensors.size())
303 {
304 std::cout << "Sensor" << (createdSensors.size() == 1 ? " is" : "s are")
305 << " created\n";
306 }
Yoo, Jae Hyun5481fac2018-10-09 16:43:03 -0700307
Yoo, Jae Hyun60e14d32018-10-10 11:03:11 -0700308 return true;
James Feist139cb572018-09-10 15:26:18 -0700309}
310
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700311void exportDevice(const CPUConfig& config)
James Feist139cb572018-09-10 15:26:18 -0700312{
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700313 std::ostringstream hex;
314 hex << std::hex << config.addr;
315 const std::string& addrHexStr = hex.str();
316 std::string busStr = std::to_string(config.bus);
317
318 std::string parameters = "peci-client 0x" + addrHexStr;
319 std::string device = "/sys/bus/peci/devices/peci-" + busStr + "/new_device";
320
321 std::experimental::filesystem::path devicePath(device);
322 const std::string& dir = devicePath.parent_path().string();
323 for (const auto& path :
324 std::experimental::filesystem::directory_iterator(dir))
James Feist139cb572018-09-10 15:26:18 -0700325 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700326 if (!std::experimental::filesystem::is_directory(path))
James Feist139cb572018-09-10 15:26:18 -0700327 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700328 continue;
James Feist139cb572018-09-10 15:26:18 -0700329 }
330
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700331 const std::string& directoryName = path.path().filename();
332 if (boost::starts_with(directoryName, busStr) &&
333 boost::ends_with(directoryName, addrHexStr))
334 {
335 if (DEBUG)
336 {
337 std::cout << parameters << " on bus " << busStr
338 << " is already exported\n";
339 }
340 return;
341 }
James Feist139cb572018-09-10 15:26:18 -0700342 }
343
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700344 std::ofstream deviceFile(device);
345 if (!deviceFile.good())
James Feist139cb572018-09-10 15:26:18 -0700346 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700347 std::cerr << "Error writing " << device << "\n";
James Feist139cb572018-09-10 15:26:18 -0700348 return;
349 }
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700350 deviceFile << parameters;
351 deviceFile.close();
352
353 std::cout << parameters << " on bus " << busStr << " is exported\n";
James Feist139cb572018-09-10 15:26:18 -0700354}
355
356void detectCpu(boost::asio::deadline_timer& timer, boost::asio::io_service& io,
357 sdbusplus::asio::object_server& objectServer,
358 boost::container::flat_map<std::string,
359 std::unique_ptr<CPUSensor>>& sensors,
360 boost::container::flat_set<CPUConfig>& configs,
361 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
362{
363 auto file = open(PECI_DEV, O_RDWR);
364 if (file < 0)
365 {
366 std::cerr << "unable to open " << PECI_DEV << "\n";
367 std::exit(EXIT_FAILURE);
368 }
369
370 size_t rescanDelaySeconds = 0;
371 bool keepPinging = false;
372 for (CPUConfig& config : configs)
373 {
374 State state;
375 struct peci_ping_msg msg;
376 msg.addr = config.addr;
377 if (!ioctl(file, PECI_IOC_PING, &msg))
378 {
379 bool dimmReady = false;
380 for (unsigned int rank = 0; rank < RANK_NUM_MAX; rank++)
381 {
382 struct peci_rd_pkg_cfg_msg msg;
383 msg.addr = config.addr;
384 msg.index = MBX_INDEX_DDR_DIMM_TEMP;
385 msg.param = rank;
386 msg.rx_len = 4;
387 if (!ioctl(file, PECI_IOC_RD_PKG_CFG, &msg))
388 {
389 if (msg.pkg_config[0] || msg.pkg_config[1] ||
390 msg.pkg_config[2])
391 {
392 dimmReady = true;
393 break;
394 }
395 }
396 else
397 {
398 break;
399 }
400 }
Yoo, Jae Hyun5481fac2018-10-09 16:43:03 -0700401
James Feist139cb572018-09-10 15:26:18 -0700402 if (dimmReady)
403 {
404 state = State::READY;
405 }
406 else
407 {
408 state = State::ON;
409 }
410 }
411 else
412 {
413 state = State::OFF;
414 }
415
416 if (config.state != state)
417 {
418 if (config.state == State::OFF)
419 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700420 std::cout << config.name << " is detected\n";
421 exportDevice(config);
James Feist139cb572018-09-10 15:26:18 -0700422 }
Yoo, Jae Hyun5481fac2018-10-09 16:43:03 -0700423 if (state == State::READY)
424 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700425 std::cout << "DIMM(s) on " << config.name
Yoo, Jae Hyun5481fac2018-10-09 16:43:03 -0700426 << " is/are detected\n";
427 }
James Feist139cb572018-09-10 15:26:18 -0700428 config.state = state;
429 }
430
Yoo, Jae Hyun60e14d32018-10-10 11:03:11 -0700431 if (config.state != State::OFF)
432 {
433 if (config.state == State::ON)
434 {
435 rescanDelaySeconds = 1;
436 }
437 else
438 {
439 rescanDelaySeconds = 5;
440 }
441 }
442
443 if (config.state != State::READY)
James Feist139cb572018-09-10 15:26:18 -0700444 {
445 keepPinging = true;
446 }
447
448 if (DEBUG)
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700449 {
450 std::cout << config.name << ", state: " << config.state << "\n";
451 }
James Feist139cb572018-09-10 15:26:18 -0700452 }
453
454 close(file);
455
456 if (rescanDelaySeconds)
457 {
458 std::this_thread::sleep_for(std::chrono::seconds(rescanDelaySeconds));
Yoo, Jae Hyun60e14d32018-10-10 11:03:11 -0700459 if (!createSensors(io, objectServer, sensors, configs, dbusConnection))
460 {
461 keepPinging = true;
462 }
James Feist139cb572018-09-10 15:26:18 -0700463 }
464
465 if (keepPinging)
466 {
467 timer.expires_from_now(boost::posix_time::seconds(1));
468 timer.async_wait([&](const boost::system::error_code& ec) {
469 if (ec == boost::asio::error::operation_aborted)
470 {
471 /* we were canceled*/
472 return;
473 }
474 else if (ec)
475 {
476 std::cerr << "timer error\n";
477 return;
478 }
479 detectCpu(timer, io, objectServer, sensors, configs,
480 dbusConnection);
481 });
482 }
483}
484
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700485bool getCpuConfig(const std::shared_ptr<sdbusplus::asio::connection>& systemBus,
James Feist139cb572018-09-10 15:26:18 -0700486 boost::container::flat_set<CPUConfig>& configs)
487{
488 ManagedObjectType sensorConfigurations;
489 bool useCache = false;
490 // use new data the first time, then refresh
491 for (const char* type : SENSOR_TYPES)
492 {
493 if (!getSensorConfiguration(CONFIG_PREFIX + std::string(type),
494 systemBus, sensorConfigurations, useCache))
495 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700496 return false;
James Feist139cb572018-09-10 15:26:18 -0700497 }
498 useCache = true;
499 }
500
501 // check PECI client addresses and DT overlay names from CPU configuration
502 // before starting ping operation
503 for (const char* type : SENSOR_TYPES)
504 {
505 for (const std::pair<sdbusplus::message::object_path, SensorData>&
506 sensor : sensorConfigurations)
507 {
508 for (const std::pair<
509 std::string,
510 boost::container::flat_map<std::string, BasicVariantType>>&
511 config : sensor.second)
512 {
513 if ((CONFIG_PREFIX + std::string(type)) != config.first)
514 {
515 continue;
516 }
517
James Feist139cb572018-09-10 15:26:18 -0700518 auto findName = config.second.find("Name");
519 if (findName == config.second.end())
520 {
521 continue;
522 }
Yoo, Jae Hyun625429b2018-10-17 18:19:02 -0700523 std::string nameRaw = variant_ns::visit(
James Feist139cb572018-09-10 15:26:18 -0700524 VariantToStringVisitor(), findName->second);
525 std::string name =
526 std::regex_replace(nameRaw, ILLEGAL_NAME_REGEX, "_");
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700527
528 auto findBus = config.second.find("Bus");
529 if (findBus == config.second.end())
530 {
531 std::cerr << "Can't find 'Bus' setting in " << name << "\n";
532 continue;
533 }
534 uint64_t bus = variant_ns::visit(VariantToUnsignedIntVisitor(),
535 findBus->second);
536
537 auto findAddress = config.second.find("Address");
538 if (findAddress == config.second.end())
539 {
540 std::cerr << "Can't find 'Address' setting in " << name
541 << "\n";
542 continue;
543 }
544 uint64_t addr = variant_ns::visit(VariantToUnsignedIntVisitor(),
545 findAddress->second);
James Feist139cb572018-09-10 15:26:18 -0700546
547 if (DEBUG)
548 {
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700549 std::cout << "bus: " << bus << "\n";
James Feist139cb572018-09-10 15:26:18 -0700550 std::cout << "addr: " << addr << "\n";
551 std::cout << "name: " << name << "\n";
552 std::cout << "type: " << type << "\n";
James Feist139cb572018-09-10 15:26:18 -0700553 }
554
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700555 configs.emplace(bus, addr, name, State::OFF);
James Feist139cb572018-09-10 15:26:18 -0700556 }
557 }
558 }
Yoo, Jae Hyun5481fac2018-10-09 16:43:03 -0700559
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700560 if (configs.size())
561 {
562 std::cout << "CPU config" << (configs.size() == 1 ? " is" : "s are")
563 << " parsed\n";
564 return true;
565 }
566
567 return false;
James Feist139cb572018-09-10 15:26:18 -0700568}
569
570int main(int argc, char** argv)
571{
572 boost::asio::io_service io;
573 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
574 boost::container::flat_set<CPUConfig> configs;
575
576 systemBus->request_name("xyz.openbmc_project.CPUSensor");
577 sdbusplus::asio::object_server objectServer(systemBus);
578 boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>> sensors;
579 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
580 boost::asio::deadline_timer pingTimer(io);
James Feist139cb572018-09-10 15:26:18 -0700581 boost::asio::deadline_timer filterTimer(io);
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700582
583 filterTimer.expires_from_now(boost::posix_time::seconds(1));
584 filterTimer.async_wait([&](const boost::system::error_code& ec) {
585 if (ec == boost::asio::error::operation_aborted)
586 {
587 /* we were canceled*/
588 return;
589 }
590 else if (ec)
591 {
592 std::cerr << "timer error\n";
593 return;
594 }
595
596 if (getCpuConfig(systemBus, configs))
597 {
598 detectCpu(pingTimer, io, objectServer, sensors, configs, systemBus);
599 }
600 });
601
James Feist139cb572018-09-10 15:26:18 -0700602 std::function<void(sdbusplus::message::message&)> eventHandler =
603 [&](sdbusplus::message::message& message) {
604 if (message.is_method_error())
605 {
606 std::cerr << "callback method error\n";
607 return;
608 }
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700609
610 if (DEBUG)
611 {
612 std::cout << message.get_path() << " is changed\n";
613 }
614
James Feist139cb572018-09-10 15:26:18 -0700615 // this implicitly cancels the timer
616 filterTimer.expires_from_now(boost::posix_time::seconds(1));
James Feist139cb572018-09-10 15:26:18 -0700617 filterTimer.async_wait([&](const boost::system::error_code& ec) {
618 if (ec == boost::asio::error::operation_aborted)
619 {
620 /* we were canceled*/
621 return;
622 }
623 else if (ec)
624 {
625 std::cerr << "timer error\n";
626 return;
627 }
628
Jae Hyun Yooa8fa4d22018-10-22 15:24:29 -0700629 if (getCpuConfig(systemBus, configs))
James Feist139cb572018-09-10 15:26:18 -0700630 {
631 detectCpu(pingTimer, io, objectServer, sensors, configs,
632 systemBus);
633 }
634 });
635 };
636
637 for (const char* type : SENSOR_TYPES)
638 {
639 auto match = std::make_unique<sdbusplus::bus::match::match>(
640 static_cast<sdbusplus::bus::bus&>(*systemBus),
641 "type='signal',member='PropertiesChanged',path_namespace='" +
642 std::string(INVENTORY_PATH) + "',arg0namespace='" +
643 CONFIG_PREFIX + type + "'",
644 eventHandler);
645 matches.emplace_back(std::move(match));
646 }
647
648 io.run();
649}