blob: 38f92a76efa6a5a5783ce4aaa6cdc521fc7caf0f [file] [log] [blame]
Cheng C Yang209ec562019-03-12 16:37:44 +08001/*
2// Copyright (c) 2019 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*/
Josh Lehan0830c7b2019-10-08 16:35:09 -070016
Ed Tanous8a57ec02020-10-09 12:46:52 -070017#include <PSUEvent.hpp>
18#include <PSUSensor.hpp>
19#include <Utils.hpp>
Cheng C Yang209ec562019-03-12 16:37:44 +080020#include <boost/algorithm/string/replace.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070021#include <boost/container/flat_map.hpp>
Cheng C Yang209ec562019-03-12 16:37:44 +080022#include <boost/container/flat_set.hpp>
James Feist38fb5982020-05-28 10:09:54 -070023#include <sdbusplus/asio/connection.hpp>
24#include <sdbusplus/asio/object_server.hpp>
25#include <sdbusplus/bus/match.hpp>
26
27#include <array>
Josh Lehan74d9bd92019-10-31 08:51:58 -070028#include <cmath>
James Feist24f02f22019-04-15 11:05:39 -070029#include <filesystem>
Cheng C Yang209ec562019-03-12 16:37:44 +080030#include <fstream>
Patrick Venture96e97db2019-10-31 13:44:38 -070031#include <functional>
Cheng C Yang58b2b532019-05-31 00:19:45 +080032#include <iostream>
Cheng C Yang209ec562019-03-12 16:37:44 +080033#include <regex>
Patrick Venture96e97db2019-10-31 13:44:38 -070034#include <string>
Lei YUa2c7cea2020-12-23 14:07:28 +080035#include <string_view>
Patrick Venture96e97db2019-10-31 13:44:38 -070036#include <utility>
37#include <variant>
38#include <vector>
Cheng C Yang209ec562019-03-12 16:37:44 +080039
Ed Tanous8a57ec02020-10-09 12:46:52 -070040static constexpr bool debug = false;
Josh Lehan49cfba92019-10-08 16:50:42 -070041
Brandon Kim66558232021-11-09 16:53:08 -080042static constexpr auto sensorTypes{std::to_array<const char*>(
Zev Weissbc56cfb2022-11-21 16:40:09 -080043 {"ADM1266", "ADM1272", "ADM1275", "ADM1278", "ADM1293",
44 "ADS7830", "AHE50DC_FAN", "BMR490", "DPS800", "INA219",
45 "INA230", "IPSPS", "IR38060", "IR38164", "IR38263",
46 "ISL68137", "ISL68220", "ISL68223", "ISL69225", "ISL69243",
47 "ISL69260", "LM25066", "MAX16601", "MAX20710", "MAX20730",
48 "MAX20734", "MAX20796", "MAX34451", "MP2971", "MP2973",
49 "MP5023", "PLI1209BC", "pmbus", "PXE1610", "RAA228000",
50 "RAA228228", "RAA228620", "RAA229001", "RAA229004", "RAA229126",
51 "TPS53679", "TPS546D24", "XDPE11280", "XDPE12284"})};
Cheng C Yang209ec562019-03-12 16:37:44 +080052
Ed Tanousa2df7862021-12-07 16:30:27 -080053// clang-format off
54static constexpr auto pmbusNames{std::to_array<const char*>({
55 "adm1266",
56 "adm1272",
57 "adm1275",
58 "adm1278",
Zhikui Ren842e5432022-03-09 16:18:24 -080059 "adm1293",
Tim Chao6f379ce2022-02-24 11:08:09 +080060 "ads7830",
Zev Weissbc56cfb2022-11-21 16:40:09 -080061 "ahe50dc_fan",
linchuyuan5cf66df2021-12-21 17:38:55 -080062 "bmr490",
Ed Tanousa2df7862021-12-07 16:30:27 -080063 "dps800",
64 "ina219",
65 "ina230",
66 "ipsps1",
Naresh Solankiadbcd7c2022-11-02 10:07:26 +010067 "ir38060",
68 "ir38164",
69 "ir38263",
Ed Tanousa2df7862021-12-07 16:30:27 -080070 "isl68137",
71 "isl68220",
72 "isl68223",
Khang Kieu51ad6672022-02-09 01:26:25 +000073 "isl69225",
Ed Tanousa2df7862021-12-07 16:30:27 -080074 "isl69243",
75 "isl69260",
76 "lm25066",
77 "max16601",
78 "max20710",
79 "max20730",
80 "max20734",
81 "max20796",
82 "max34451",
Shamim Alidccd1d42022-06-08 22:31:35 +053083 "mp2971",
84 "mp2973",
Howard Chiub58ac3a2021-12-07 17:12:56 +080085 "mp5023",
Naresh Solankiadbcd7c2022-11-02 10:07:26 +010086 "pli1209bc",
Ed Tanousa2df7862021-12-07 16:30:27 -080087 "pmbus",
88 "pxe1610",
89 "raa228000",
90 "raa228228",
Tom Tung75da5152021-11-24 09:38:07 +080091 "raa228620",
92 "raa229001",
Ed Tanousa2df7862021-12-07 16:30:27 -080093 "raa229004",
Zhikui Ren85fa3c62022-02-26 23:03:34 -080094 "raa229126",
Konstantin Aladyshev21e12c32022-10-19 18:56:10 +030095 "tps53679",
Ed Tanousa2df7862021-12-07 16:30:27 -080096 "tps546d24",
Naresh Solankiadbcd7c2022-11-02 10:07:26 +010097 "xdpe11280",
Ed Tanousa2df7862021-12-07 16:30:27 -080098 "xdpe12284"
99})};
100//clang-format on
Josh Lehan0830c7b2019-10-08 16:35:09 -0700101
Cheng C Yang209ec562019-03-12 16:37:44 +0800102namespace fs = std::filesystem;
103
Yong Libf8b1da2020-04-15 16:32:50 +0800104static boost::container::flat_map<std::string, std::shared_ptr<PSUSensor>>
Cheng C Yang916360b2019-05-07 18:47:16 +0800105 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800106static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
107 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +0800108static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
109 pwmSensors;
110static boost::container::flat_map<std::string, std::string> sensorTable;
111static boost::container::flat_map<std::string, PSUProperty> labelMatch;
112static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800113static boost::container::flat_map<std::string, std::vector<std::string>>
114 eventMatch;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800115static boost::container::flat_map<
116 std::string,
117 boost::container::flat_map<std::string, std::vector<std::string>>>
118 groupEventMatch;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800119static boost::container::flat_map<std::string, std::vector<std::string>>
120 limitEventMatch;
121
Josh Lehan74d9bd92019-10-31 08:51:58 -0700122static std::vector<PSUProperty> psuProperties;
123
Cheng C Yang58b2b532019-05-31 00:19:45 +0800124// Function CheckEvent will check each attribute from eventMatch table in the
125// sysfs. If the attributes exists in sysfs, then store the complete path
126// of the attribute into eventPathList.
127void checkEvent(
128 const std::string& directory,
129 const boost::container::flat_map<std::string, std::vector<std::string>>&
130 eventMatch,
131 boost::container::flat_map<std::string, std::vector<std::string>>&
132 eventPathList)
133{
134 for (const auto& match : eventMatch)
135 {
136 const std::vector<std::string>& eventAttrs = match.second;
137 const std::string& eventName = match.first;
138 for (const auto& eventAttr : eventAttrs)
139 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700140 std::string eventPath = directory;
141 eventPath += "/";
142 eventPath += eventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800143
144 std::ifstream eventFile(eventPath);
145 if (!eventFile.good())
146 {
147 continue;
148 }
149
150 eventPathList[eventName].push_back(eventPath);
151 }
152 }
153}
154
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800155// Check Group Events which contains more than one targets in each combine
156// events.
157void checkGroupEvent(
158 const std::string& directory,
159 const boost::container::flat_map<
160 std::string,
161 boost::container::flat_map<std::string, std::vector<std::string>>>&
162 groupEventMatch,
163 boost::container::flat_map<
164 std::string,
165 boost::container::flat_map<std::string, std::vector<std::string>>>&
166 groupEventPathList)
167{
168 for (const auto& match : groupEventMatch)
169 {
170 const std::string& groupEventName = match.first;
171 const boost::container::flat_map<std::string, std::vector<std::string>>
172 events = match.second;
173 boost::container::flat_map<std::string, std::vector<std::string>>
174 pathList;
175 for (const auto& match : events)
176 {
177 const std::string& eventName = match.first;
178 const std::vector<std::string>& eventAttrs = match.second;
179 for (const auto& eventAttr : eventAttrs)
180 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700181 std::string eventPath = directory;
182 eventPath += "/";
183 eventPath += eventAttr;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800184 std::ifstream eventFile(eventPath);
185 if (!eventFile.good())
186 {
187 continue;
188 }
189
190 pathList[eventName].push_back(eventPath);
191 }
192 }
193 groupEventPathList[groupEventName] = pathList;
194 }
195}
196
Cheng C Yang58b2b532019-05-31 00:19:45 +0800197// Function checkEventLimits will check all the psu related xxx_input attributes
198// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
199// xxx_min_alarm exist, then store the existing paths of the alarm attributes
200// to eventPathList.
201void checkEventLimits(
202 const std::string& sensorPathStr,
203 const boost::container::flat_map<std::string, std::vector<std::string>>&
204 limitEventMatch,
205 boost::container::flat_map<std::string, std::vector<std::string>>&
206 eventPathList)
207{
Lei YUa2c7cea2020-12-23 14:07:28 +0800208 auto attributePartPos = sensorPathStr.find_last_of('_');
209 if (attributePartPos == std::string::npos)
210 {
211 // There is no '_' in the string, skip it
212 return;
213 }
214 auto attributePart =
215 std::string_view(sensorPathStr).substr(attributePartPos + 1);
216 if (attributePart != "input")
217 {
218 // If the sensor is not xxx_input, skip it
219 return;
220 }
221
222 auto prefixPart = sensorPathStr.substr(0, attributePartPos + 1);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800223 for (const auto& limitMatch : limitEventMatch)
224 {
225 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
226 const std::string& eventName = limitMatch.first;
227 for (const auto& limitEventAttr : limitEventAttrs)
228 {
Lei YUa2c7cea2020-12-23 14:07:28 +0800229 auto limitEventPath = prefixPart + limitEventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800230 std::ifstream eventFile(limitEventPath);
231 if (!eventFile.good())
232 {
233 continue;
234 }
235 eventPathList[eventName].push_back(limitEventPath);
236 }
237 }
238}
Cheng C Yang916360b2019-05-07 18:47:16 +0800239
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530240static void
241 checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
242 const std::string& interfacePath,
243 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
244 sdbusplus::asio::object_server& objectServer,
245 const std::string& psuName)
Cheng C Yang916360b2019-05-07 18:47:16 +0800246{
Zev Weiss741f26e2022-08-12 18:21:02 -0700247 for (const auto& [pwmLabel, pwmName] : pwmTable)
Cheng C Yang916360b2019-05-07 18:47:16 +0800248 {
Zev Weiss741f26e2022-08-12 18:21:02 -0700249 if (pwmLabel != labelHead)
Cheng C Yang916360b2019-05-07 18:47:16 +0800250 {
251 continue;
252 }
253
254 const std::string& sensorPathStr = sensorPath.string();
255 const std::string& pwmPathStr =
256 boost::replace_all_copy(sensorPathStr, "input", "target");
257 std::ifstream pwmFile(pwmPathStr);
258 if (!pwmFile.good())
259 {
260 continue;
261 }
262
263 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
264 if (findPWMSensor != pwmSensors.end())
265 {
266 continue;
267 }
268
Zev Weissd8c293a2022-08-15 18:58:41 -0700269 std::string name = "Pwm_";
270 name += psuName;
271 name += "_";
Zev Weiss741f26e2022-08-12 18:21:02 -0700272 name += pwmName;
Zev Weissd8c293a2022-08-15 18:58:41 -0700273
274 std::string objPath = interfacePath;
275 objPath += "_";
Zev Weiss741f26e2022-08-12 18:21:02 -0700276 objPath += pwmName;
Zev Weissd8c293a2022-08-15 18:58:41 -0700277
Cheng C Yang916360b2019-05-07 18:47:16 +0800278 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
Zev Weissd8c293a2022-08-15 18:58:41 -0700279 name, pwmPathStr, dbusConnection, objectServer, objPath, "PSU");
Cheng C Yang916360b2019-05-07 18:47:16 +0800280 }
281}
282
Zhikui Ren23c96e72020-11-05 22:32:28 -0800283static void createSensorsCallback(
284 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
285 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
286 const ManagedObjectType& sensorConfigs,
287 const std::shared_ptr<boost::container::flat_set<std::string>>&
288 sensorsChanged)
Cheng C Yang209ec562019-03-12 16:37:44 +0800289{
Josh Lehan49cfba92019-10-08 16:50:42 -0700290 int numCreated = 0;
Zhikui Ren23c96e72020-11-05 22:32:28 -0800291 bool firstScan = sensorsChanged == nullptr;
Cheng C Yang209ec562019-03-12 16:37:44 +0800292
293 std::vector<fs::path> pmbusPaths;
294 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
295 {
296 std::cerr << "No PSU sensors in system\n";
297 return;
298 }
299
300 boost::container::flat_set<std::string> directories;
301 for (const auto& pmbusPath : pmbusPaths)
302 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800303 boost::container::flat_map<std::string, std::vector<std::string>>
304 eventPathList;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800305 boost::container::flat_map<
306 std::string,
307 boost::container::flat_map<std::string, std::vector<std::string>>>
308 groupEventPathList;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800309
310 std::ifstream nameFile(pmbusPath);
311 if (!nameFile.good())
312 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700313 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800314 continue;
315 }
316
317 std::string pmbusName;
318 std::getline(nameFile, pmbusName);
319 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700320
321 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
322 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800323 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700324 // To avoid this error message, add your driver name to
325 // the pmbusNames vector at the top of this file.
326 std::cerr << "Driver name " << pmbusName
327 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800328 continue;
329 }
330
Cheng C Yang209ec562019-03-12 16:37:44 +0800331 auto directory = pmbusPath.parent_path();
332
333 auto ret = directories.insert(directory.string());
334 if (!ret.second)
335 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700336 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800337 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800338 }
339
James Feistb6c0b912019-07-09 12:21:44 -0700340 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800341 std::string deviceName = fs::canonical(device).stem();
Ed Tanous8a57ec02020-10-09 12:46:52 -0700342 auto findHyphen = deviceName.find('-');
Cheng C Yang209ec562019-03-12 16:37:44 +0800343 if (findHyphen == std::string::npos)
344 {
345 std::cerr << "found bad device" << deviceName << "\n";
346 continue;
347 }
348 std::string busStr = deviceName.substr(0, findHyphen);
349 std::string addrStr = deviceName.substr(findHyphen + 1);
350
351 size_t bus = 0;
352 size_t addr = 0;
353
354 try
355 {
356 bus = std::stoi(busStr);
Ed Tanous8a57ec02020-10-09 12:46:52 -0700357 addr = std::stoi(addrStr, nullptr, 16);
Cheng C Yang209ec562019-03-12 16:37:44 +0800358 }
Patrick Williams26601e82021-10-06 12:43:25 -0500359 catch (const std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800360 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700361 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
362 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800363 continue;
364 }
365
Zev Weisse8b97ee2022-08-12 15:23:51 -0700366 const SensorBaseConfigMap* baseConfig = nullptr;
Cheng C Yang209ec562019-03-12 16:37:44 +0800367 const SensorData* sensorData = nullptr;
368 const std::string* interfacePath = nullptr;
369 const char* sensorType = nullptr;
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800370 size_t thresholdConfSize = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800371
Zev Weiss741f26e2022-08-12 18:21:02 -0700372 for (const auto& [path, cfgData] : sensorConfigs)
Cheng C Yang209ec562019-03-12 16:37:44 +0800373 {
Zev Weiss741f26e2022-08-12 18:21:02 -0700374 sensorData = &cfgData;
Cheng C Yang209ec562019-03-12 16:37:44 +0800375 for (const char* type : sensorTypes)
376 {
Zev Weiss054aad82022-08-18 01:37:34 -0700377 auto sensorBase = sensorData->find(configInterfaceName(type));
Cheng C Yang209ec562019-03-12 16:37:44 +0800378 if (sensorBase != sensorData->end())
379 {
Zev Weisse8b97ee2022-08-12 15:23:51 -0700380 baseConfig = &sensorBase->second;
Cheng C Yang209ec562019-03-12 16:37:44 +0800381 sensorType = type;
382 break;
383 }
384 }
385 if (baseConfig == nullptr)
386 {
387 std::cerr << "error finding base configuration for "
388 << deviceName << "\n";
389 continue;
390 }
391
Zev Weisse8b97ee2022-08-12 15:23:51 -0700392 auto configBus = baseConfig->find("Bus");
393 auto configAddress = baseConfig->find("Address");
Cheng C Yang209ec562019-03-12 16:37:44 +0800394
Zev Weisse8b97ee2022-08-12 15:23:51 -0700395 if (configBus == baseConfig->end() ||
396 configAddress == baseConfig->end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800397 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800398 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800399 continue;
400 }
401
Ed Tanousa771f6a2022-01-14 09:36:51 -0800402 const uint64_t* confBus = std::get_if<uint64_t>(&(configBus->second));
403 const uint64_t* confAddr = std::get_if<uint64_t>(&(configAddress->second));
404 if (confBus == nullptr || confAddr == nullptr)
Cheng C Yang58b2b532019-05-31 00:19:45 +0800405 {
406 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700407 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800408 continue;
409 }
410
411 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800412 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700413 std::cerr << "Configuration skipping " << *confBus << "-"
414 << *confAddr << " because not " << bus << "-" << addr
415 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800416 continue;
417 }
418
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800419 std::vector<thresholds::Threshold> confThresholds;
420 if (!parseThresholdsFromConfig(*sensorData, confThresholds))
421 {
Zhikui Ren85fa3c62022-02-26 23:03:34 -0800422 std::cerr << "error populating total thresholds\n";
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800423 }
424 thresholdConfSize = confThresholds.size();
425
Zev Weiss741f26e2022-08-12 18:21:02 -0700426 interfacePath = &path.str;
Cheng C Yang209ec562019-03-12 16:37:44 +0800427 break;
428 }
429 if (interfacePath == nullptr)
430 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700431 // To avoid this error message, add your export map entry,
432 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800433 std::cerr << "failed to find match for " << deviceName << "\n";
434 continue;
435 }
436
Zev Weisse8b97ee2022-08-12 15:23:51 -0700437 auto findPSUName = baseConfig->find("Name");
438 if (findPSUName == baseConfig->end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800439 {
440 std::cerr << "could not determine configuration name for "
441 << deviceName << "\n";
442 continue;
443 }
Ed Tanousa771f6a2022-01-14 09:36:51 -0800444 const std::string* psuName = std::get_if<std::string>(&(findPSUName->second));
445 if (psuName == nullptr)
Cheng C Yang58b2b532019-05-31 00:19:45 +0800446 {
447 std::cerr << "Cannot find psu name, invalid configuration\n";
448 continue;
449 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800450
451 // on rescans, only update sensors we were signaled by
452 if (!firstScan)
453 {
Zhikui Renda98f092021-11-01 09:41:08 -0700454 std::string psuNameStr = "/" + escapeName(*psuName);
Zhikui Ren23c96e72020-11-05 22:32:28 -0800455 auto it =
456 std::find_if(sensorsChanged->begin(), sensorsChanged->end(),
457 [psuNameStr](std::string& s) {
Zev Weiss6c106d62022-08-17 20:50:00 -0700458 return s.ends_with(psuNameStr);
Zhikui Ren23c96e72020-11-05 22:32:28 -0800459 });
460
461 if (it == sensorsChanged->end())
462 {
463 continue;
464 }
465 sensorsChanged->erase(it);
466 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800467 checkEvent(directory.string(), eventMatch, eventPathList);
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800468 checkGroupEvent(directory.string(), groupEventMatch,
469 groupEventPathList);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800470
Zev Weisse8b97ee2022-08-12 15:23:51 -0700471 PowerState readState = getPowerState(*baseConfig);
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000472
Vijay Khemka996bad12019-05-28 15:15:16 -0700473 /* Check if there are more sensors in the same interface */
474 int i = 1;
475 std::vector<std::string> psuNames;
476 do
477 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700478 // Individual string fields: Name, Name1, Name2, Name3, ...
Zhikui Renda98f092021-11-01 09:41:08 -0700479 psuNames.push_back(
480 escapeName(std::get<std::string>(findPSUName->second)));
Zev Weisse8b97ee2022-08-12 15:23:51 -0700481 findPSUName = baseConfig->find("Name" + std::to_string(i++));
482 } while (findPSUName != baseConfig->end());
Vijay Khemka996bad12019-05-28 15:15:16 -0700483
Cheng C Yange50345b2019-04-02 17:26:15 +0800484 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700485 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800486 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800487 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800488 continue;
489 }
490
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530491 /* read max value in sysfs for in, curr, power, temp, ... */
492 if (!findFiles(directory, R"(\w\d+_max$)", sensorPaths, 0))
493 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700494 if constexpr (debug)
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530495 {
496 std::cerr << "No max name in PSU \n";
497 }
498 }
499
Zev Weiss8569bf22022-10-11 15:37:44 -0700500 float pollRate = getPollRate(*baseConfig, PSUSensor::defaultSensorPoll);
Lei YU7170a232021-02-04 16:19:27 +0800501
Vijay Khemka996bad12019-05-28 15:15:16 -0700502 /* Find array of labels to be exposed if it is defined in config */
503 std::vector<std::string> findLabels;
Zev Weisse8b97ee2022-08-12 15:23:51 -0700504 auto findLabelObj = baseConfig->find("Labels");
505 if (findLabelObj != baseConfig->end())
Vijay Khemka996bad12019-05-28 15:15:16 -0700506 {
507 findLabels =
508 std::get<std::vector<std::string>>(findLabelObj->second);
509 }
510
Jason Ling5747fab2019-10-02 16:46:23 -0700511 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
512 std::smatch matches;
513
Cheng C Yange50345b2019-04-02 17:26:15 +0800514 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800515 {
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530516 bool maxLabel = false;
Cheng C Yange50345b2019-04-02 17:26:15 +0800517 std::string labelHead;
518 std::string sensorPathStr = sensorPath.string();
519 std::string sensorNameStr = sensorPath.filename();
Ed Tanous2049bd22022-07-09 07:20:26 -0700520 std::string sensorNameSubStr;
Jason Ling5747fab2019-10-02 16:46:23 -0700521 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
522 {
Josh Lehan06494452019-10-31 09:49:16 -0700523 // hwmon *_input filename without number:
524 // in, curr, power, temp, ...
Jason Ling5747fab2019-10-02 16:46:23 -0700525 sensorNameSubStr = matches[1];
526 }
527 else
528 {
Josh Lehan06494452019-10-31 09:49:16 -0700529 std::cerr << "Could not extract the alpha prefix from "
Jason Ling5747fab2019-10-02 16:46:23 -0700530 << sensorNameStr;
531 continue;
532 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800533
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530534 std::string labelPath;
535
536 /* find and differentiate _max and _input to replace "label" */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700537 size_t pos = sensorPathStr.find('_');
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530538 if (pos != std::string::npos)
539 {
540
541 std::string sensorPathStrMax = sensorPathStr.substr(pos);
Ed Tanous2049bd22022-07-09 07:20:26 -0700542 if (sensorPathStrMax == "_max")
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530543 {
544 labelPath =
545 boost::replace_all_copy(sensorPathStr, "max", "label");
546 maxLabel = true;
547 }
548 else
549 {
550 labelPath = boost::replace_all_copy(sensorPathStr, "input",
551 "label");
552 maxLabel = false;
553 }
554 }
555 else
556 {
557 continue;
558 }
559
Cheng C Yangecba9de2019-09-12 23:41:50 +0800560 std::ifstream labelFile(labelPath);
561 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800562 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700563 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800564 {
565 std::cerr << "Input file " << sensorPath
566 << " has no corresponding label file\n";
567 }
Josh Lehan06494452019-10-31 09:49:16 -0700568 // hwmon *_input filename with number:
569 // temp1, temp2, temp3, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700570 labelHead = sensorNameStr.substr(0, sensorNameStr.find('_'));
Cheng C Yang209ec562019-03-12 16:37:44 +0800571 }
572 else
573 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800574 std::string label;
575 std::getline(labelFile, label);
576 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800577 auto findSensor = sensors.find(label);
578 if (findSensor != sensors.end())
579 {
580 continue;
581 }
582
Josh Lehan06494452019-10-31 09:49:16 -0700583 // hwmon corresponding *_label file contents:
584 // vin1, vout1, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700585 labelHead = label.substr(0, label.find(' '));
Cheng C Yange50345b2019-04-02 17:26:15 +0800586 }
587
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530588 /* append "max" for labelMatch */
589 if (maxLabel)
590 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700591 labelHead.insert(0, "max");
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530592 }
593
Ed Tanous8a57ec02020-10-09 12:46:52 -0700594 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700595 {
596 std::cerr << "Sensor type=\"" << sensorNameSubStr
597 << "\" label=\"" << labelHead << "\"\n";
598 }
599
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530600 checkPWMSensor(sensorPath, labelHead, *interfacePath,
601 dbusConnection, objectServer, psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800602
Vijay Khemka996bad12019-05-28 15:15:16 -0700603 if (!findLabels.empty())
604 {
605 /* Check if this labelHead is enabled in config file */
606 if (std::find(findLabels.begin(), findLabels.end(),
607 labelHead) == findLabels.end())
608 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700609 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800610 {
611 std::cerr << "could not find " << labelHead
612 << " in the Labels list\n";
613 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700614 continue;
615 }
616 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800617
Cheng C Yange50345b2019-04-02 17:26:15 +0800618 auto findProperty = labelMatch.find(labelHead);
619 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800620 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700621 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700622 {
623 std::cerr << "Could not find matching default property for "
624 << labelHead << "\n";
625 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800626 continue;
627 }
628
Josh Lehan74d9bd92019-10-31 08:51:58 -0700629 // Protect the hardcoded labelMatch list from changes,
630 // by making a copy and modifying that instead.
631 // Avoid bleedthrough of one device's customizations to
632 // the next device, as each should be independently customizable.
633 psuProperties.push_back(findProperty->second);
634 auto psuProperty = psuProperties.rbegin();
635
636 // Use label head as prefix for reading from config file,
637 // example if temp1: temp1_Name, temp1_Scale, temp1_Min, ...
638 std::string keyName = labelHead + "_Name";
639 std::string keyScale = labelHead + "_Scale";
640 std::string keyMin = labelHead + "_Min";
641 std::string keyMax = labelHead + "_Max";
Jeff Line41d52f2021-04-07 19:38:51 +0800642 std::string keyOffset = labelHead + "_Offset";
Lotus Xucb5af732021-09-10 15:18:50 +0800643 std::string keyPowerState = labelHead + "_PowerState";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700644
645 bool customizedName = false;
Zev Weisse8b97ee2022-08-12 15:23:51 -0700646 auto findCustomName = baseConfig->find(keyName);
647 if (findCustomName != baseConfig->end())
Josh Lehan432d1ed2019-10-16 12:23:31 -0700648 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700649 try
650 {
651 psuProperty->labelTypeName = std::visit(
652 VariantToStringVisitor(), findCustomName->second);
653 }
Patrick Williams26601e82021-10-06 12:43:25 -0500654 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700655 {
656 std::cerr << "Unable to parse " << keyName << "\n";
657 continue;
658 }
659
660 // All strings are valid, including empty string
661 customizedName = true;
662 }
663
664 bool customizedScale = false;
Zev Weisse8b97ee2022-08-12 15:23:51 -0700665 auto findCustomScale = baseConfig->find(keyScale);
666 if (findCustomScale != baseConfig->end())
Josh Lehan74d9bd92019-10-31 08:51:58 -0700667 {
668 try
669 {
670 psuProperty->sensorScaleFactor = std::visit(
671 VariantToUnsignedIntVisitor(), findCustomScale->second);
672 }
Patrick Williams26601e82021-10-06 12:43:25 -0500673 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700674 {
675 std::cerr << "Unable to parse " << keyScale << "\n";
676 continue;
677 }
678
679 // Avoid later division by zero
680 if (psuProperty->sensorScaleFactor > 0)
681 {
682 customizedScale = true;
683 }
684 else
685 {
686 std::cerr << "Unable to accept " << keyScale << "\n";
687 continue;
688 }
689 }
690
Zev Weisse8b97ee2022-08-12 15:23:51 -0700691 auto findCustomMin = baseConfig->find(keyMin);
692 if (findCustomMin != baseConfig->end())
Josh Lehan74d9bd92019-10-31 08:51:58 -0700693 {
694 try
695 {
696 psuProperty->minReading = std::visit(
697 VariantToDoubleVisitor(), findCustomMin->second);
698 }
Patrick Williams26601e82021-10-06 12:43:25 -0500699 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700700 {
701 std::cerr << "Unable to parse " << keyMin << "\n";
702 continue;
703 }
704 }
705
Zev Weisse8b97ee2022-08-12 15:23:51 -0700706 auto findCustomMax = baseConfig->find(keyMax);
707 if (findCustomMax != baseConfig->end())
Josh Lehan74d9bd92019-10-31 08:51:58 -0700708 {
709 try
710 {
711 psuProperty->maxReading = std::visit(
712 VariantToDoubleVisitor(), findCustomMax->second);
713 }
Patrick Williams26601e82021-10-06 12:43:25 -0500714 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700715 {
716 std::cerr << "Unable to parse " << keyMax << "\n";
717 continue;
718 }
719 }
720
Zev Weisse8b97ee2022-08-12 15:23:51 -0700721 auto findCustomOffset = baseConfig->find(keyOffset);
722 if (findCustomOffset != baseConfig->end())
Jeff Line41d52f2021-04-07 19:38:51 +0800723 {
724 try
725 {
726 psuProperty->sensorOffset = std::visit(
727 VariantToDoubleVisitor(), findCustomOffset->second);
728 }
Patrick Williams26601e82021-10-06 12:43:25 -0500729 catch (const std::invalid_argument&)
Jeff Line41d52f2021-04-07 19:38:51 +0800730 {
731 std::cerr << "Unable to parse " << keyOffset << "\n";
732 continue;
733 }
734 }
735
Lotus Xucb5af732021-09-10 15:18:50 +0800736 // if we find label head power state set ,override the powerstate.
Zev Weisse8b97ee2022-08-12 15:23:51 -0700737 auto findPowerState = baseConfig->find(keyPowerState);
738 if (findPowerState != baseConfig->end())
Lotus Xucb5af732021-09-10 15:18:50 +0800739 {
740 std::string powerState = std::visit(VariantToStringVisitor(),
741 findPowerState->second);
742 setReadState(powerState, readState);
743 }
Josh Lehan74d9bd92019-10-31 08:51:58 -0700744 if (!(psuProperty->minReading < psuProperty->maxReading))
745 {
746 std::cerr << "Min must be less than Max\n";
747 continue;
748 }
749
750 // If the sensor name is being customized by config file,
751 // then prefix/suffix composition becomes not necessary,
752 // and in fact not wanted, because it gets in the way.
753 std::string psuNameFromIndex;
754 if (!customizedName)
755 {
756 /* Find out sensor name index for this label */
757 std::regex rgx("[A-Za-z]+([0-9]+)");
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500758 size_t nameIndex{0};
Josh Lehan74d9bd92019-10-31 08:51:58 -0700759 if (std::regex_search(labelHead, matches, rgx))
760 {
761 nameIndex = std::stoi(matches[1]);
762
763 // Decrement to preserve alignment, because hwmon
764 // human-readable filenames and labels use 1-based
765 // numbering, but the "Name", "Name1", "Name2", etc. naming
766 // convention (the psuNames vector) uses 0-based numbering.
767 if (nameIndex > 0)
768 {
769 --nameIndex;
770 }
771 }
772 else
773 {
774 nameIndex = 0;
775 }
776
777 if (psuNames.size() <= nameIndex)
778 {
779 std::cerr << "Could not pair " << labelHead
780 << " with a Name field\n";
781 continue;
782 }
783
784 psuNameFromIndex = psuNames[nameIndex];
785
Ed Tanous8a57ec02020-10-09 12:46:52 -0700786 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700787 {
788 std::cerr << "Sensor label head " << labelHead
789 << " paired with " << psuNameFromIndex
790 << " at index " << nameIndex << "\n";
791 }
Josh Lehan432d1ed2019-10-16 12:23:31 -0700792 }
793
Cheng C Yang58b2b532019-05-31 00:19:45 +0800794 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
795
Josh Lehan74d9bd92019-10-31 08:51:58 -0700796 // Similarly, if sensor scaling factor is being customized,
797 // then the below power-of-10 constraint becomes unnecessary,
798 // as config should be able to specify an arbitrary divisor.
799 unsigned int factor = psuProperty->sensorScaleFactor;
800 if (!customizedScale)
Vijay Khemka53ca4442019-07-23 11:03:55 -0700801 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700802 // Preserve existing usage of hardcoded labelMatch table below
803 factor = std::pow(10.0, factor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700804
Josh Lehan74d9bd92019-10-31 08:51:58 -0700805 /* Change first char of substring to uppercase */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700806 char firstChar =
807 static_cast<char>(std::toupper(sensorNameSubStr[0]));
Josh Lehan74d9bd92019-10-31 08:51:58 -0700808 std::string strScaleFactor =
809 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
810
811 // Preserve existing configs by accepting earlier syntax,
812 // example CurrScaleFactor, PowerScaleFactor, ...
Zev Weisse8b97ee2022-08-12 15:23:51 -0700813 auto findScaleFactor = baseConfig->find(strScaleFactor);
814 if (findScaleFactor != baseConfig->end())
Josh Lehan74d9bd92019-10-31 08:51:58 -0700815 {
816 factor = std::visit(VariantToIntVisitor(),
817 findScaleFactor->second);
818 }
819
Ed Tanous8a57ec02020-10-09 12:46:52 -0700820 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700821 {
822 std::cerr << "Sensor scaling factor " << factor
823 << " string " << strScaleFactor << "\n";
824 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700825 }
826
Vijay Khemka996bad12019-05-28 15:15:16 -0700827 std::vector<thresholds::Threshold> sensorThresholds;
Joshi, Mansi14f0ad82019-11-21 10:52:30 +0530828 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds,
829 &labelHead))
Cheng C Yange50345b2019-04-02 17:26:15 +0800830 {
James Feist17ab6e02019-06-25 12:28:13 -0700831 std::cerr << "error populating thresholds for "
832 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800833 }
834
Zev Weiss6b6891c2021-04-22 02:46:21 -0500835 auto findSensorUnit = sensorTable.find(sensorNameSubStr);
836 if (findSensorUnit == sensorTable.end())
Cheng C Yange50345b2019-04-02 17:26:15 +0800837 {
Jason Ling5747fab2019-10-02 16:46:23 -0700838 std::cerr << sensorNameSubStr
Josh Lehan06494452019-10-31 09:49:16 -0700839 << " is not a recognized sensor type\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800840 continue;
841 }
842
Ed Tanous8a57ec02020-10-09 12:46:52 -0700843 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700844 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700845 std::cerr << "Sensor properties: Name \""
846 << psuProperty->labelTypeName << "\" Scale "
847 << psuProperty->sensorScaleFactor << " Min "
848 << psuProperty->minReading << " Max "
Jeff Line41d52f2021-04-07 19:38:51 +0800849 << psuProperty->maxReading << " Offset "
850 << psuProperty->sensorOffset << "\n";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700851 }
852
853 std::string sensorName = psuProperty->labelTypeName;
854 if (customizedName)
855 {
856 if (sensorName.empty())
857 {
858 // Allow selective disabling of an individual sensor,
859 // by customizing its name to an empty string.
860 std::cerr << "Sensor disabled, empty string\n";
861 continue;
862 }
863 }
864 else
865 {
866 // Sensor name not customized, do prefix/suffix composition,
867 // preserving default behavior by using psuNameFromIndex.
868 sensorName =
869 psuNameFromIndex + " " + psuProperty->labelTypeName;
870 }
871
Ed Tanous8a57ec02020-10-09 12:46:52 -0700872 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700873 {
874 std::cerr << "Sensor name \"" << sensorName << "\" path \""
875 << sensorPathStr << "\" type \"" << sensorType
876 << "\"\n";
Josh Lehan49cfba92019-10-08 16:50:42 -0700877 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800878 // destruct existing one first if already created
879 sensors[sensorName] = nullptr;
Yong Libf8b1da2020-04-15 16:32:50 +0800880 sensors[sensorName] = std::make_shared<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800881 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800882 sensorName, std::move(sensorThresholds), *interfacePath,
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000883 readState, findSensorUnit->second, factor,
884 psuProperty->maxReading, psuProperty->minReading,
885 psuProperty->sensorOffset, labelHead, thresholdConfSize,
886 pollRate);
Yong Libf8b1da2020-04-15 16:32:50 +0800887 sensors[sensorName]->setupRead();
Josh Lehan74d9bd92019-10-31 08:51:58 -0700888 ++numCreated;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700889 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700890 {
891 std::cerr << "Created " << numCreated << " sensors so far\n";
892 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800893 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800894
895 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800896 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800897 combineEvents[*psuName + "OperationalStatus"] =
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000898 std::make_unique<PSUCombineEvent>(objectServer, dbusConnection, io,
899 *psuName, readState,
900 eventPathList, groupEventPathList,
901 "OperationalStatus", pollRate);
Cheng C Yang209ec562019-03-12 16:37:44 +0800902 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700903
Ed Tanous8a57ec02020-10-09 12:46:52 -0700904 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700905 {
906 std::cerr << "Created total of " << numCreated << " sensors\n";
907 }
Ed Tanous2049bd22022-07-09 07:20:26 -0700908 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800909
Zhikui Ren23c96e72020-11-05 22:32:28 -0800910void createSensors(
911 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
912 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
913 const std::shared_ptr<boost::container::flat_set<std::string>>&
914 sensorsChanged)
915{
916 auto getter = std::make_shared<GetSensorConfiguration>(
917 dbusConnection, [&io, &objectServer, &dbusConnection, sensorsChanged](
918 const ManagedObjectType& sensorConfigs) {
919 createSensorsCallback(io, objectServer, dbusConnection,
920 sensorConfigs, sensorsChanged);
921 });
922 getter->getConfiguration(
923 std::vector<std::string>(sensorTypes.begin(), sensorTypes.end()));
924}
925
Cheng C Yang916360b2019-05-07 18:47:16 +0800926void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800927{
Zev Weiss6b6891c2021-04-22 02:46:21 -0500928 sensorTable = {{"power", sensor_paths::unitWatts},
929 {"curr", sensor_paths::unitAmperes},
930 {"temp", sensor_paths::unitDegreesC},
931 {"in", sensor_paths::unitVolts},
932 {"fan", sensor_paths::unitRPMs}};
Cheng C Yange50345b2019-04-02 17:26:15 +0800933
Jeff Line41d52f2021-04-07 19:38:51 +0800934 labelMatch = {
935 {"pin", PSUProperty("Input Power", 3000, 0, 6, 0)},
Zhikui Ren85fa3c62022-02-26 23:03:34 -0800936 {"pin1", PSUProperty("Input Power", 3000, 0, 6, 0)},
937 {"pin2", PSUProperty("Input Power", 3000, 0, 6, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800938 {"pout1", PSUProperty("Output Power", 3000, 0, 6, 0)},
939 {"pout2", PSUProperty("Output Power", 3000, 0, 6, 0)},
940 {"pout3", PSUProperty("Output Power", 3000, 0, 6, 0)},
941 {"power1", PSUProperty("Output Power", 3000, 0, 6, 0)},
Zhikui Ren85fa3c62022-02-26 23:03:34 -0800942 {"power2", PSUProperty("Output Power", 3000, 0, 6, 0)},
943 {"power3", PSUProperty("Output Power", 3000, 0, 6, 0)},
944 {"power4", PSUProperty("Output Power", 3000, 0, 6, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800945 {"maxpin", PSUProperty("Max Input Power", 3000, 0, 6, 0)},
946 {"vin", PSUProperty("Input Voltage", 300, 0, 3, 0)},
947 {"maxvin", PSUProperty("Max Input Voltage", 300, 0, 3, 0)},
948 {"vout1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
949 {"vout2", PSUProperty("Output Voltage", 255, 0, 3, 0)},
950 {"vout3", PSUProperty("Output Voltage", 255, 0, 3, 0)},
951 {"vout4", PSUProperty("Output Voltage", 255, 0, 3, 0)},
952 {"vout5", PSUProperty("Output Voltage", 255, 0, 3, 0)},
953 {"vout6", PSUProperty("Output Voltage", 255, 0, 3, 0)},
954 {"vout7", PSUProperty("Output Voltage", 255, 0, 3, 0)},
955 {"vout8", PSUProperty("Output Voltage", 255, 0, 3, 0)},
956 {"vout9", PSUProperty("Output Voltage", 255, 0, 3, 0)},
957 {"vout10", PSUProperty("Output Voltage", 255, 0, 3, 0)},
958 {"vout11", PSUProperty("Output Voltage", 255, 0, 3, 0)},
959 {"vout12", PSUProperty("Output Voltage", 255, 0, 3, 0)},
960 {"vout13", PSUProperty("Output Voltage", 255, 0, 3, 0)},
961 {"vout14", PSUProperty("Output Voltage", 255, 0, 3, 0)},
962 {"vout15", PSUProperty("Output Voltage", 255, 0, 3, 0)},
963 {"vout16", PSUProperty("Output Voltage", 255, 0, 3, 0)},
964 {"vout17", PSUProperty("Output Voltage", 255, 0, 3, 0)},
965 {"vout18", PSUProperty("Output Voltage", 255, 0, 3, 0)},
966 {"vout19", PSUProperty("Output Voltage", 255, 0, 3, 0)},
967 {"vout20", PSUProperty("Output Voltage", 255, 0, 3, 0)},
968 {"vout21", PSUProperty("Output Voltage", 255, 0, 3, 0)},
969 {"vout22", PSUProperty("Output Voltage", 255, 0, 3, 0)},
970 {"vout23", PSUProperty("Output Voltage", 255, 0, 3, 0)},
971 {"vout24", PSUProperty("Output Voltage", 255, 0, 3, 0)},
972 {"vout25", PSUProperty("Output Voltage", 255, 0, 3, 0)},
973 {"vout26", PSUProperty("Output Voltage", 255, 0, 3, 0)},
974 {"vout27", PSUProperty("Output Voltage", 255, 0, 3, 0)},
975 {"vout28", PSUProperty("Output Voltage", 255, 0, 3, 0)},
976 {"vout29", PSUProperty("Output Voltage", 255, 0, 3, 0)},
977 {"vout30", PSUProperty("Output Voltage", 255, 0, 3, 0)},
978 {"vout31", PSUProperty("Output Voltage", 255, 0, 3, 0)},
979 {"vout32", PSUProperty("Output Voltage", 255, 0, 3, 0)},
980 {"vmon", PSUProperty("Auxiliary Input Voltage", 255, 0, 3, 0)},
Tim Chao6f379ce2022-02-24 11:08:09 +0800981 {"in0", PSUProperty("Output Voltage", 255, 0, 3, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800982 {"in1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
Tim Chao6f379ce2022-02-24 11:08:09 +0800983 {"in2", PSUProperty("Output Voltage", 255, 0, 3, 0)},
984 {"in3", PSUProperty("Output Voltage", 255, 0, 3, 0)},
985 {"in4", PSUProperty("Output Voltage", 255, 0, 3, 0)},
986 {"in5", PSUProperty("Output Voltage", 255, 0, 3, 0)},
987 {"in6", PSUProperty("Output Voltage", 255, 0, 3, 0)},
988 {"in7", PSUProperty("Output Voltage", 255, 0, 3, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800989 {"iin", PSUProperty("Input Current", 20, 0, 3, 0)},
Zhikui Ren85fa3c62022-02-26 23:03:34 -0800990 {"iin1", PSUProperty("Input Current", 20, 0, 3, 0)},
991 {"iin2", PSUProperty("Input Current", 20, 0, 3, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800992 {"iout1", PSUProperty("Output Current", 255, 0, 3, 0)},
993 {"iout2", PSUProperty("Output Current", 255, 0, 3, 0)},
994 {"iout3", PSUProperty("Output Current", 255, 0, 3, 0)},
995 {"iout4", PSUProperty("Output Current", 255, 0, 3, 0)},
996 {"iout5", PSUProperty("Output Current", 255, 0, 3, 0)},
997 {"iout6", PSUProperty("Output Current", 255, 0, 3, 0)},
998 {"iout7", PSUProperty("Output Current", 255, 0, 3, 0)},
999 {"iout8", PSUProperty("Output Current", 255, 0, 3, 0)},
1000 {"iout9", PSUProperty("Output Current", 255, 0, 3, 0)},
1001 {"iout10", PSUProperty("Output Current", 255, 0, 3, 0)},
1002 {"iout11", PSUProperty("Output Current", 255, 0, 3, 0)},
1003 {"iout12", PSUProperty("Output Current", 255, 0, 3, 0)},
1004 {"iout13", PSUProperty("Output Current", 255, 0, 3, 0)},
1005 {"iout14", PSUProperty("Output Current", 255, 0, 3, 0)},
1006 {"curr1", PSUProperty("Output Current", 255, 0, 3, 0)},
Zhikui Ren85fa3c62022-02-26 23:03:34 -08001007 {"curr2", PSUProperty("Output Current", 255, 0, 3, 0)},
1008 {"curr3", PSUProperty("Output Current", 255, 0, 3, 0)},
1009 {"curr4", PSUProperty("Output Current", 255, 0, 3, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +08001010 {"maxiout1", PSUProperty("Max Output Current", 255, 0, 3, 0)},
1011 {"temp1", PSUProperty("Temperature", 127, -128, 3, 0)},
1012 {"temp2", PSUProperty("Temperature", 127, -128, 3, 0)},
1013 {"temp3", PSUProperty("Temperature", 127, -128, 3, 0)},
1014 {"temp4", PSUProperty("Temperature", 127, -128, 3, 0)},
1015 {"temp5", PSUProperty("Temperature", 127, -128, 3, 0)},
1016 {"temp6", PSUProperty("Temperature", 127, -128, 3, 0)},
1017 {"maxtemp1", PSUProperty("Max Temperature", 127, -128, 3, 0)},
1018 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0, 0)},
Zev Weissea2db482022-06-20 18:12:53 -07001019 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0, 0)},
1020 {"fan3", PSUProperty("Fan Speed 3", 30000, 0, 0, 0)},
1021 {"fan4", PSUProperty("Fan Speed 4", 30000, 0, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +08001022
Zev Weissea2db482022-06-20 18:12:53 -07001023 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"},
1024 {"fan3", "Fan_3"}, {"fan4", "Fan_4"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +08001025
1026 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
1027 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
1028
Cheng C Yang202a1ff2020-01-09 09:34:22 +08001029 eventMatch = {{"PredictiveFailure", {"power1_alarm"}},
1030 {"Failure", {"in2_alarm"}},
1031 {"ACLost", {"in1_beep"}},
1032 {"ConfigureError", {"in1_fault"}}};
1033
1034 groupEventMatch = {{"FanFault",
1035 {{"fan1", {"fan1_alarm", "fan1_fault"}},
Zev Weissea2db482022-06-20 18:12:53 -07001036 {"fan2", {"fan2_alarm", "fan2_fault"}},
1037 {"fan3", {"fan3_alarm", "fan3_fault"}},
1038 {"fan4", {"fan4_alarm", "fan4_fault"}}}}};
Cheng C Yang209ec562019-03-12 16:37:44 +08001039}
1040
James Feistb6c0b912019-07-09 12:21:44 -07001041int main()
Cheng C Yang209ec562019-03-12 16:37:44 +08001042{
1043 boost::asio::io_service io;
1044 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
1045
Ed Tanous14ed5e92022-07-12 15:50:23 -07001046 sdbusplus::asio::object_server objectServer(systemBus, true);
1047 objectServer.add_manager("/xyz/openbmc_project/sensors");
Zhikui Ren3fe3f542022-11-02 16:37:54 -07001048 objectServer.add_manager("/xyz/openbmc_project/control");
Cheng C Yang209ec562019-03-12 16:37:44 +08001049 systemBus->request_name("xyz.openbmc_project.PSUSensor");
Zhikui Ren23c96e72020-11-05 22:32:28 -08001050 auto sensorsChanged =
1051 std::make_shared<boost::container::flat_set<std::string>>();
Cheng C Yang209ec562019-03-12 16:37:44 +08001052
Cheng C Yang916360b2019-05-07 18:47:16 +08001053 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +08001054
Zhikui Ren23c96e72020-11-05 22:32:28 -08001055 io.post([&]() { createSensors(io, objectServer, systemBus, nullptr); });
Ed Tanous9b4a20e2022-09-06 08:47:11 -07001056 boost::asio::steady_timer filterTimer(io);
Patrick Williams92f8f512022-07-22 19:26:55 -05001057 std::function<void(sdbusplus::message_t&)> eventHandler =
1058 [&](sdbusplus::message_t& message) {
Cheng C Yang209ec562019-03-12 16:37:44 +08001059 if (message.is_method_error())
1060 {
1061 std::cerr << "callback method error\n";
1062 return;
1063 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001064 sensorsChanged->insert(message.get_path());
Ed Tanous9b4a20e2022-09-06 08:47:11 -07001065 filterTimer.expires_from_now(std::chrono::seconds(3));
Cheng C Yang209ec562019-03-12 16:37:44 +08001066 filterTimer.async_wait([&](const boost::system::error_code& ec) {
1067 if (ec == boost::asio::error::operation_aborted)
1068 {
1069 return;
1070 }
Ed Tanous8a57ec02020-10-09 12:46:52 -07001071 if (ec)
Cheng C Yang209ec562019-03-12 16:37:44 +08001072 {
1073 std::cerr << "timer error\n";
1074 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001075 createSensors(io, objectServer, systemBus, sensorsChanged);
Cheng C Yang209ec562019-03-12 16:37:44 +08001076 });
1077 };
1078
Zev Weiss214d9712022-08-12 12:54:31 -07001079 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
1080 setupPropertiesChangedMatches(*systemBus, sensorTypes, eventHandler);
Bruce Lee1263c3d2021-06-04 15:16:33 +08001081 setupManufacturingModeMatch(*systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001082 io.run();
1083}