blob: d1117751d99eef8a5d061bf223f505bfe1723162 [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 Weiss054aad82022-08-18 01:37:34 -070043 {"ADM1266", "ADM1272", "ADM1275", "ADM1278", "ADM1293",
44 "ADS7830", "BMR490", "DPS800", "INA219", "INA230",
Naresh Solankiadbcd7c2022-11-02 10:07:26 +010045 "IPSPS", "IR38060", "IR38164", "IR38263", "ISL68137",
46 "ISL68220", "ISL68223", "ISL69225", "ISL69243", "ISL69260",
47 "LM25066", "MAX16601", "MAX20710", "MAX20730", "MAX20734",
48 "MAX20796", "MAX34451", "MP2971", "MP2973", "MP5023",
49 "PLI1209BC", "pmbus", "PXE1610", "RAA228000", "RAA228228",
50 "RAA228620", "RAA229001", "RAA229004", "RAA229126", "TPS53679",
51 "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",
linchuyuan5cf66df2021-12-21 17:38:55 -080061 "bmr490",
Ed Tanousa2df7862021-12-07 16:30:27 -080062 "dps800",
63 "ina219",
64 "ina230",
65 "ipsps1",
Naresh Solankiadbcd7c2022-11-02 10:07:26 +010066 "ir38060",
67 "ir38164",
68 "ir38263",
Ed Tanousa2df7862021-12-07 16:30:27 -080069 "isl68137",
70 "isl68220",
71 "isl68223",
Khang Kieu51ad6672022-02-09 01:26:25 +000072 "isl69225",
Ed Tanousa2df7862021-12-07 16:30:27 -080073 "isl69243",
74 "isl69260",
75 "lm25066",
76 "max16601",
77 "max20710",
78 "max20730",
79 "max20734",
80 "max20796",
81 "max34451",
Shamim Alidccd1d42022-06-08 22:31:35 +053082 "mp2971",
83 "mp2973",
Howard Chiub58ac3a2021-12-07 17:12:56 +080084 "mp5023",
Naresh Solankiadbcd7c2022-11-02 10:07:26 +010085 "pli1209bc",
Ed Tanousa2df7862021-12-07 16:30:27 -080086 "pmbus",
87 "pxe1610",
88 "raa228000",
89 "raa228228",
Tom Tung75da5152021-11-24 09:38:07 +080090 "raa228620",
91 "raa229001",
Ed Tanousa2df7862021-12-07 16:30:27 -080092 "raa229004",
Zhikui Ren85fa3c62022-02-26 23:03:34 -080093 "raa229126",
Konstantin Aladyshev21e12c32022-10-19 18:56:10 +030094 "tps53679",
Ed Tanousa2df7862021-12-07 16:30:27 -080095 "tps546d24",
Naresh Solankiadbcd7c2022-11-02 10:07:26 +010096 "xdpe11280",
Ed Tanousa2df7862021-12-07 16:30:27 -080097 "xdpe12284"
98})};
99//clang-format on
Josh Lehan0830c7b2019-10-08 16:35:09 -0700100
Cheng C Yang209ec562019-03-12 16:37:44 +0800101namespace fs = std::filesystem;
102
Yong Libf8b1da2020-04-15 16:32:50 +0800103static boost::container::flat_map<std::string, std::shared_ptr<PSUSensor>>
Cheng C Yang916360b2019-05-07 18:47:16 +0800104 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800105static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
106 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +0800107static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
108 pwmSensors;
109static boost::container::flat_map<std::string, std::string> sensorTable;
110static boost::container::flat_map<std::string, PSUProperty> labelMatch;
111static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800112static boost::container::flat_map<std::string, std::vector<std::string>>
113 eventMatch;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800114static boost::container::flat_map<
115 std::string,
116 boost::container::flat_map<std::string, std::vector<std::string>>>
117 groupEventMatch;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800118static boost::container::flat_map<std::string, std::vector<std::string>>
119 limitEventMatch;
120
Josh Lehan74d9bd92019-10-31 08:51:58 -0700121static std::vector<PSUProperty> psuProperties;
122
Cheng C Yang58b2b532019-05-31 00:19:45 +0800123// Function CheckEvent will check each attribute from eventMatch table in the
124// sysfs. If the attributes exists in sysfs, then store the complete path
125// of the attribute into eventPathList.
126void checkEvent(
127 const std::string& directory,
128 const boost::container::flat_map<std::string, std::vector<std::string>>&
129 eventMatch,
130 boost::container::flat_map<std::string, std::vector<std::string>>&
131 eventPathList)
132{
133 for (const auto& match : eventMatch)
134 {
135 const std::vector<std::string>& eventAttrs = match.second;
136 const std::string& eventName = match.first;
137 for (const auto& eventAttr : eventAttrs)
138 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700139 std::string eventPath = directory;
140 eventPath += "/";
141 eventPath += eventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800142
143 std::ifstream eventFile(eventPath);
144 if (!eventFile.good())
145 {
146 continue;
147 }
148
149 eventPathList[eventName].push_back(eventPath);
150 }
151 }
152}
153
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800154// Check Group Events which contains more than one targets in each combine
155// events.
156void checkGroupEvent(
157 const std::string& directory,
158 const boost::container::flat_map<
159 std::string,
160 boost::container::flat_map<std::string, std::vector<std::string>>>&
161 groupEventMatch,
162 boost::container::flat_map<
163 std::string,
164 boost::container::flat_map<std::string, std::vector<std::string>>>&
165 groupEventPathList)
166{
167 for (const auto& match : groupEventMatch)
168 {
169 const std::string& groupEventName = match.first;
170 const boost::container::flat_map<std::string, std::vector<std::string>>
171 events = match.second;
172 boost::container::flat_map<std::string, std::vector<std::string>>
173 pathList;
174 for (const auto& match : events)
175 {
176 const std::string& eventName = match.first;
177 const std::vector<std::string>& eventAttrs = match.second;
178 for (const auto& eventAttr : eventAttrs)
179 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700180 std::string eventPath = directory;
181 eventPath += "/";
182 eventPath += eventAttr;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800183 std::ifstream eventFile(eventPath);
184 if (!eventFile.good())
185 {
186 continue;
187 }
188
189 pathList[eventName].push_back(eventPath);
190 }
191 }
192 groupEventPathList[groupEventName] = pathList;
193 }
194}
195
Cheng C Yang58b2b532019-05-31 00:19:45 +0800196// Function checkEventLimits will check all the psu related xxx_input attributes
197// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
198// xxx_min_alarm exist, then store the existing paths of the alarm attributes
199// to eventPathList.
200void checkEventLimits(
201 const std::string& sensorPathStr,
202 const boost::container::flat_map<std::string, std::vector<std::string>>&
203 limitEventMatch,
204 boost::container::flat_map<std::string, std::vector<std::string>>&
205 eventPathList)
206{
Lei YUa2c7cea2020-12-23 14:07:28 +0800207 auto attributePartPos = sensorPathStr.find_last_of('_');
208 if (attributePartPos == std::string::npos)
209 {
210 // There is no '_' in the string, skip it
211 return;
212 }
213 auto attributePart =
214 std::string_view(sensorPathStr).substr(attributePartPos + 1);
215 if (attributePart != "input")
216 {
217 // If the sensor is not xxx_input, skip it
218 return;
219 }
220
221 auto prefixPart = sensorPathStr.substr(0, attributePartPos + 1);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800222 for (const auto& limitMatch : limitEventMatch)
223 {
224 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
225 const std::string& eventName = limitMatch.first;
226 for (const auto& limitEventAttr : limitEventAttrs)
227 {
Lei YUa2c7cea2020-12-23 14:07:28 +0800228 auto limitEventPath = prefixPart + limitEventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800229 std::ifstream eventFile(limitEventPath);
230 if (!eventFile.good())
231 {
232 continue;
233 }
234 eventPathList[eventName].push_back(limitEventPath);
235 }
236 }
237}
Cheng C Yang916360b2019-05-07 18:47:16 +0800238
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530239static void
240 checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
241 const std::string& interfacePath,
242 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
243 sdbusplus::asio::object_server& objectServer,
244 const std::string& psuName)
Cheng C Yang916360b2019-05-07 18:47:16 +0800245{
Zev Weiss741f26e2022-08-12 18:21:02 -0700246 for (const auto& [pwmLabel, pwmName] : pwmTable)
Cheng C Yang916360b2019-05-07 18:47:16 +0800247 {
Zev Weiss741f26e2022-08-12 18:21:02 -0700248 if (pwmLabel != labelHead)
Cheng C Yang916360b2019-05-07 18:47:16 +0800249 {
250 continue;
251 }
252
253 const std::string& sensorPathStr = sensorPath.string();
254 const std::string& pwmPathStr =
255 boost::replace_all_copy(sensorPathStr, "input", "target");
256 std::ifstream pwmFile(pwmPathStr);
257 if (!pwmFile.good())
258 {
259 continue;
260 }
261
262 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
263 if (findPWMSensor != pwmSensors.end())
264 {
265 continue;
266 }
267
Zev Weissd8c293a2022-08-15 18:58:41 -0700268 std::string name = "Pwm_";
269 name += psuName;
270 name += "_";
Zev Weiss741f26e2022-08-12 18:21:02 -0700271 name += pwmName;
Zev Weissd8c293a2022-08-15 18:58:41 -0700272
273 std::string objPath = interfacePath;
274 objPath += "_";
Zev Weiss741f26e2022-08-12 18:21:02 -0700275 objPath += pwmName;
Zev Weissd8c293a2022-08-15 18:58:41 -0700276
Cheng C Yang916360b2019-05-07 18:47:16 +0800277 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
Zev Weissd8c293a2022-08-15 18:58:41 -0700278 name, pwmPathStr, dbusConnection, objectServer, objPath, "PSU");
Cheng C Yang916360b2019-05-07 18:47:16 +0800279 }
280}
281
Zhikui Ren23c96e72020-11-05 22:32:28 -0800282static void createSensorsCallback(
283 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
284 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
285 const ManagedObjectType& sensorConfigs,
286 const std::shared_ptr<boost::container::flat_set<std::string>>&
287 sensorsChanged)
Cheng C Yang209ec562019-03-12 16:37:44 +0800288{
Josh Lehan49cfba92019-10-08 16:50:42 -0700289 int numCreated = 0;
Zhikui Ren23c96e72020-11-05 22:32:28 -0800290 bool firstScan = sensorsChanged == nullptr;
Cheng C Yang209ec562019-03-12 16:37:44 +0800291
292 std::vector<fs::path> pmbusPaths;
293 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
294 {
295 std::cerr << "No PSU sensors in system\n";
296 return;
297 }
298
299 boost::container::flat_set<std::string> directories;
300 for (const auto& pmbusPath : pmbusPaths)
301 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800302 boost::container::flat_map<std::string, std::vector<std::string>>
303 eventPathList;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800304 boost::container::flat_map<
305 std::string,
306 boost::container::flat_map<std::string, std::vector<std::string>>>
307 groupEventPathList;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800308
309 std::ifstream nameFile(pmbusPath);
310 if (!nameFile.good())
311 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700312 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800313 continue;
314 }
315
316 std::string pmbusName;
317 std::getline(nameFile, pmbusName);
318 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700319
320 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
321 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800322 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700323 // To avoid this error message, add your driver name to
324 // the pmbusNames vector at the top of this file.
325 std::cerr << "Driver name " << pmbusName
326 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800327 continue;
328 }
329
Cheng C Yang209ec562019-03-12 16:37:44 +0800330 auto directory = pmbusPath.parent_path();
331
332 auto ret = directories.insert(directory.string());
333 if (!ret.second)
334 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700335 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800336 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800337 }
338
James Feistb6c0b912019-07-09 12:21:44 -0700339 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800340 std::string deviceName = fs::canonical(device).stem();
Ed Tanous8a57ec02020-10-09 12:46:52 -0700341 auto findHyphen = deviceName.find('-');
Cheng C Yang209ec562019-03-12 16:37:44 +0800342 if (findHyphen == std::string::npos)
343 {
344 std::cerr << "found bad device" << deviceName << "\n";
345 continue;
346 }
347 std::string busStr = deviceName.substr(0, findHyphen);
348 std::string addrStr = deviceName.substr(findHyphen + 1);
349
350 size_t bus = 0;
351 size_t addr = 0;
352
353 try
354 {
355 bus = std::stoi(busStr);
Ed Tanous8a57ec02020-10-09 12:46:52 -0700356 addr = std::stoi(addrStr, nullptr, 16);
Cheng C Yang209ec562019-03-12 16:37:44 +0800357 }
Patrick Williams26601e82021-10-06 12:43:25 -0500358 catch (const std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800359 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700360 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
361 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800362 continue;
363 }
364
Zev Weisse8b97ee2022-08-12 15:23:51 -0700365 const SensorBaseConfigMap* baseConfig = nullptr;
Cheng C Yang209ec562019-03-12 16:37:44 +0800366 const SensorData* sensorData = nullptr;
367 const std::string* interfacePath = nullptr;
368 const char* sensorType = nullptr;
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800369 size_t thresholdConfSize = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800370
Zev Weiss741f26e2022-08-12 18:21:02 -0700371 for (const auto& [path, cfgData] : sensorConfigs)
Cheng C Yang209ec562019-03-12 16:37:44 +0800372 {
Zev Weiss741f26e2022-08-12 18:21:02 -0700373 sensorData = &cfgData;
Cheng C Yang209ec562019-03-12 16:37:44 +0800374 for (const char* type : sensorTypes)
375 {
Zev Weiss054aad82022-08-18 01:37:34 -0700376 auto sensorBase = sensorData->find(configInterfaceName(type));
Cheng C Yang209ec562019-03-12 16:37:44 +0800377 if (sensorBase != sensorData->end())
378 {
Zev Weisse8b97ee2022-08-12 15:23:51 -0700379 baseConfig = &sensorBase->second;
Cheng C Yang209ec562019-03-12 16:37:44 +0800380 sensorType = type;
381 break;
382 }
383 }
384 if (baseConfig == nullptr)
385 {
386 std::cerr << "error finding base configuration for "
387 << deviceName << "\n";
388 continue;
389 }
390
Zev Weisse8b97ee2022-08-12 15:23:51 -0700391 auto configBus = baseConfig->find("Bus");
392 auto configAddress = baseConfig->find("Address");
Cheng C Yang209ec562019-03-12 16:37:44 +0800393
Zev Weisse8b97ee2022-08-12 15:23:51 -0700394 if (configBus == baseConfig->end() ||
395 configAddress == baseConfig->end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800396 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800397 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800398 continue;
399 }
400
Ed Tanousa771f6a2022-01-14 09:36:51 -0800401 const uint64_t* confBus = std::get_if<uint64_t>(&(configBus->second));
402 const uint64_t* confAddr = std::get_if<uint64_t>(&(configAddress->second));
403 if (confBus == nullptr || confAddr == nullptr)
Cheng C Yang58b2b532019-05-31 00:19:45 +0800404 {
405 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700406 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800407 continue;
408 }
409
410 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800411 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700412 std::cerr << "Configuration skipping " << *confBus << "-"
413 << *confAddr << " because not " << bus << "-" << addr
414 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800415 continue;
416 }
417
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800418 std::vector<thresholds::Threshold> confThresholds;
419 if (!parseThresholdsFromConfig(*sensorData, confThresholds))
420 {
Zhikui Ren85fa3c62022-02-26 23:03:34 -0800421 std::cerr << "error populating total thresholds\n";
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800422 }
423 thresholdConfSize = confThresholds.size();
424
Zev Weiss741f26e2022-08-12 18:21:02 -0700425 interfacePath = &path.str;
Cheng C Yang209ec562019-03-12 16:37:44 +0800426 break;
427 }
428 if (interfacePath == nullptr)
429 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700430 // To avoid this error message, add your export map entry,
431 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800432 std::cerr << "failed to find match for " << deviceName << "\n";
433 continue;
434 }
435
Zev Weisse8b97ee2022-08-12 15:23:51 -0700436 auto findPSUName = baseConfig->find("Name");
437 if (findPSUName == baseConfig->end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800438 {
439 std::cerr << "could not determine configuration name for "
440 << deviceName << "\n";
441 continue;
442 }
Ed Tanousa771f6a2022-01-14 09:36:51 -0800443 const std::string* psuName = std::get_if<std::string>(&(findPSUName->second));
444 if (psuName == nullptr)
Cheng C Yang58b2b532019-05-31 00:19:45 +0800445 {
446 std::cerr << "Cannot find psu name, invalid configuration\n";
447 continue;
448 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800449
450 // on rescans, only update sensors we were signaled by
451 if (!firstScan)
452 {
Zhikui Renda98f092021-11-01 09:41:08 -0700453 std::string psuNameStr = "/" + escapeName(*psuName);
Zhikui Ren23c96e72020-11-05 22:32:28 -0800454 auto it =
455 std::find_if(sensorsChanged->begin(), sensorsChanged->end(),
456 [psuNameStr](std::string& s) {
Zev Weiss6c106d62022-08-17 20:50:00 -0700457 return s.ends_with(psuNameStr);
Zhikui Ren23c96e72020-11-05 22:32:28 -0800458 });
459
460 if (it == sensorsChanged->end())
461 {
462 continue;
463 }
464 sensorsChanged->erase(it);
465 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800466 checkEvent(directory.string(), eventMatch, eventPathList);
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800467 checkGroupEvent(directory.string(), groupEventMatch,
468 groupEventPathList);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800469
Zev Weisse8b97ee2022-08-12 15:23:51 -0700470 PowerState readState = getPowerState(*baseConfig);
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000471
Vijay Khemka996bad12019-05-28 15:15:16 -0700472 /* Check if there are more sensors in the same interface */
473 int i = 1;
474 std::vector<std::string> psuNames;
475 do
476 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700477 // Individual string fields: Name, Name1, Name2, Name3, ...
Zhikui Renda98f092021-11-01 09:41:08 -0700478 psuNames.push_back(
479 escapeName(std::get<std::string>(findPSUName->second)));
Zev Weisse8b97ee2022-08-12 15:23:51 -0700480 findPSUName = baseConfig->find("Name" + std::to_string(i++));
481 } while (findPSUName != baseConfig->end());
Vijay Khemka996bad12019-05-28 15:15:16 -0700482
Cheng C Yange50345b2019-04-02 17:26:15 +0800483 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700484 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800485 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800486 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800487 continue;
488 }
489
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530490 /* read max value in sysfs for in, curr, power, temp, ... */
491 if (!findFiles(directory, R"(\w\d+_max$)", sensorPaths, 0))
492 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700493 if constexpr (debug)
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530494 {
495 std::cerr << "No max name in PSU \n";
496 }
497 }
498
Zev Weiss8569bf22022-10-11 15:37:44 -0700499 float pollRate = getPollRate(*baseConfig, PSUSensor::defaultSensorPoll);
Lei YU7170a232021-02-04 16:19:27 +0800500
Vijay Khemka996bad12019-05-28 15:15:16 -0700501 /* Find array of labels to be exposed if it is defined in config */
502 std::vector<std::string> findLabels;
Zev Weisse8b97ee2022-08-12 15:23:51 -0700503 auto findLabelObj = baseConfig->find("Labels");
504 if (findLabelObj != baseConfig->end())
Vijay Khemka996bad12019-05-28 15:15:16 -0700505 {
506 findLabels =
507 std::get<std::vector<std::string>>(findLabelObj->second);
508 }
509
Jason Ling5747fab2019-10-02 16:46:23 -0700510 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
511 std::smatch matches;
512
Cheng C Yange50345b2019-04-02 17:26:15 +0800513 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800514 {
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530515 bool maxLabel = false;
Cheng C Yange50345b2019-04-02 17:26:15 +0800516 std::string labelHead;
517 std::string sensorPathStr = sensorPath.string();
518 std::string sensorNameStr = sensorPath.filename();
Ed Tanous2049bd22022-07-09 07:20:26 -0700519 std::string sensorNameSubStr;
Jason Ling5747fab2019-10-02 16:46:23 -0700520 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
521 {
Josh Lehan06494452019-10-31 09:49:16 -0700522 // hwmon *_input filename without number:
523 // in, curr, power, temp, ...
Jason Ling5747fab2019-10-02 16:46:23 -0700524 sensorNameSubStr = matches[1];
525 }
526 else
527 {
Josh Lehan06494452019-10-31 09:49:16 -0700528 std::cerr << "Could not extract the alpha prefix from "
Jason Ling5747fab2019-10-02 16:46:23 -0700529 << sensorNameStr;
530 continue;
531 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800532
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530533 std::string labelPath;
534
535 /* find and differentiate _max and _input to replace "label" */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700536 size_t pos = sensorPathStr.find('_');
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530537 if (pos != std::string::npos)
538 {
539
540 std::string sensorPathStrMax = sensorPathStr.substr(pos);
Ed Tanous2049bd22022-07-09 07:20:26 -0700541 if (sensorPathStrMax == "_max")
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530542 {
543 labelPath =
544 boost::replace_all_copy(sensorPathStr, "max", "label");
545 maxLabel = true;
546 }
547 else
548 {
549 labelPath = boost::replace_all_copy(sensorPathStr, "input",
550 "label");
551 maxLabel = false;
552 }
553 }
554 else
555 {
556 continue;
557 }
558
Cheng C Yangecba9de2019-09-12 23:41:50 +0800559 std::ifstream labelFile(labelPath);
560 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800561 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700562 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800563 {
564 std::cerr << "Input file " << sensorPath
565 << " has no corresponding label file\n";
566 }
Josh Lehan06494452019-10-31 09:49:16 -0700567 // hwmon *_input filename with number:
568 // temp1, temp2, temp3, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700569 labelHead = sensorNameStr.substr(0, sensorNameStr.find('_'));
Cheng C Yang209ec562019-03-12 16:37:44 +0800570 }
571 else
572 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800573 std::string label;
574 std::getline(labelFile, label);
575 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800576 auto findSensor = sensors.find(label);
577 if (findSensor != sensors.end())
578 {
579 continue;
580 }
581
Josh Lehan06494452019-10-31 09:49:16 -0700582 // hwmon corresponding *_label file contents:
583 // vin1, vout1, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700584 labelHead = label.substr(0, label.find(' '));
Cheng C Yange50345b2019-04-02 17:26:15 +0800585 }
586
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530587 /* append "max" for labelMatch */
588 if (maxLabel)
589 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700590 labelHead.insert(0, "max");
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530591 }
592
Ed Tanous8a57ec02020-10-09 12:46:52 -0700593 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700594 {
595 std::cerr << "Sensor type=\"" << sensorNameSubStr
596 << "\" label=\"" << labelHead << "\"\n";
597 }
598
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530599 checkPWMSensor(sensorPath, labelHead, *interfacePath,
600 dbusConnection, objectServer, psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800601
Vijay Khemka996bad12019-05-28 15:15:16 -0700602 if (!findLabels.empty())
603 {
604 /* Check if this labelHead is enabled in config file */
605 if (std::find(findLabels.begin(), findLabels.end(),
606 labelHead) == findLabels.end())
607 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700608 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800609 {
610 std::cerr << "could not find " << labelHead
611 << " in the Labels list\n";
612 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700613 continue;
614 }
615 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800616
Cheng C Yange50345b2019-04-02 17:26:15 +0800617 auto findProperty = labelMatch.find(labelHead);
618 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800619 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700620 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700621 {
622 std::cerr << "Could not find matching default property for "
623 << labelHead << "\n";
624 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800625 continue;
626 }
627
Josh Lehan74d9bd92019-10-31 08:51:58 -0700628 // Protect the hardcoded labelMatch list from changes,
629 // by making a copy and modifying that instead.
630 // Avoid bleedthrough of one device's customizations to
631 // the next device, as each should be independently customizable.
632 psuProperties.push_back(findProperty->second);
633 auto psuProperty = psuProperties.rbegin();
634
635 // Use label head as prefix for reading from config file,
636 // example if temp1: temp1_Name, temp1_Scale, temp1_Min, ...
637 std::string keyName = labelHead + "_Name";
638 std::string keyScale = labelHead + "_Scale";
639 std::string keyMin = labelHead + "_Min";
640 std::string keyMax = labelHead + "_Max";
Jeff Line41d52f2021-04-07 19:38:51 +0800641 std::string keyOffset = labelHead + "_Offset";
Lotus Xucb5af732021-09-10 15:18:50 +0800642 std::string keyPowerState = labelHead + "_PowerState";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700643
644 bool customizedName = false;
Zev Weisse8b97ee2022-08-12 15:23:51 -0700645 auto findCustomName = baseConfig->find(keyName);
646 if (findCustomName != baseConfig->end())
Josh Lehan432d1ed2019-10-16 12:23:31 -0700647 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700648 try
649 {
650 psuProperty->labelTypeName = std::visit(
651 VariantToStringVisitor(), findCustomName->second);
652 }
Patrick Williams26601e82021-10-06 12:43:25 -0500653 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700654 {
655 std::cerr << "Unable to parse " << keyName << "\n";
656 continue;
657 }
658
659 // All strings are valid, including empty string
660 customizedName = true;
661 }
662
663 bool customizedScale = false;
Zev Weisse8b97ee2022-08-12 15:23:51 -0700664 auto findCustomScale = baseConfig->find(keyScale);
665 if (findCustomScale != baseConfig->end())
Josh Lehan74d9bd92019-10-31 08:51:58 -0700666 {
667 try
668 {
669 psuProperty->sensorScaleFactor = std::visit(
670 VariantToUnsignedIntVisitor(), findCustomScale->second);
671 }
Patrick Williams26601e82021-10-06 12:43:25 -0500672 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700673 {
674 std::cerr << "Unable to parse " << keyScale << "\n";
675 continue;
676 }
677
678 // Avoid later division by zero
679 if (psuProperty->sensorScaleFactor > 0)
680 {
681 customizedScale = true;
682 }
683 else
684 {
685 std::cerr << "Unable to accept " << keyScale << "\n";
686 continue;
687 }
688 }
689
Zev Weisse8b97ee2022-08-12 15:23:51 -0700690 auto findCustomMin = baseConfig->find(keyMin);
691 if (findCustomMin != baseConfig->end())
Josh Lehan74d9bd92019-10-31 08:51:58 -0700692 {
693 try
694 {
695 psuProperty->minReading = std::visit(
696 VariantToDoubleVisitor(), findCustomMin->second);
697 }
Patrick Williams26601e82021-10-06 12:43:25 -0500698 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700699 {
700 std::cerr << "Unable to parse " << keyMin << "\n";
701 continue;
702 }
703 }
704
Zev Weisse8b97ee2022-08-12 15:23:51 -0700705 auto findCustomMax = baseConfig->find(keyMax);
706 if (findCustomMax != baseConfig->end())
Josh Lehan74d9bd92019-10-31 08:51:58 -0700707 {
708 try
709 {
710 psuProperty->maxReading = std::visit(
711 VariantToDoubleVisitor(), findCustomMax->second);
712 }
Patrick Williams26601e82021-10-06 12:43:25 -0500713 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700714 {
715 std::cerr << "Unable to parse " << keyMax << "\n";
716 continue;
717 }
718 }
719
Zev Weisse8b97ee2022-08-12 15:23:51 -0700720 auto findCustomOffset = baseConfig->find(keyOffset);
721 if (findCustomOffset != baseConfig->end())
Jeff Line41d52f2021-04-07 19:38:51 +0800722 {
723 try
724 {
725 psuProperty->sensorOffset = std::visit(
726 VariantToDoubleVisitor(), findCustomOffset->second);
727 }
Patrick Williams26601e82021-10-06 12:43:25 -0500728 catch (const std::invalid_argument&)
Jeff Line41d52f2021-04-07 19:38:51 +0800729 {
730 std::cerr << "Unable to parse " << keyOffset << "\n";
731 continue;
732 }
733 }
734
Lotus Xucb5af732021-09-10 15:18:50 +0800735 // if we find label head power state set ,override the powerstate.
Zev Weisse8b97ee2022-08-12 15:23:51 -0700736 auto findPowerState = baseConfig->find(keyPowerState);
737 if (findPowerState != baseConfig->end())
Lotus Xucb5af732021-09-10 15:18:50 +0800738 {
739 std::string powerState = std::visit(VariantToStringVisitor(),
740 findPowerState->second);
741 setReadState(powerState, readState);
742 }
Josh Lehan74d9bd92019-10-31 08:51:58 -0700743 if (!(psuProperty->minReading < psuProperty->maxReading))
744 {
745 std::cerr << "Min must be less than Max\n";
746 continue;
747 }
748
749 // If the sensor name is being customized by config file,
750 // then prefix/suffix composition becomes not necessary,
751 // and in fact not wanted, because it gets in the way.
752 std::string psuNameFromIndex;
753 if (!customizedName)
754 {
755 /* Find out sensor name index for this label */
756 std::regex rgx("[A-Za-z]+([0-9]+)");
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500757 size_t nameIndex{0};
Josh Lehan74d9bd92019-10-31 08:51:58 -0700758 if (std::regex_search(labelHead, matches, rgx))
759 {
760 nameIndex = std::stoi(matches[1]);
761
762 // Decrement to preserve alignment, because hwmon
763 // human-readable filenames and labels use 1-based
764 // numbering, but the "Name", "Name1", "Name2", etc. naming
765 // convention (the psuNames vector) uses 0-based numbering.
766 if (nameIndex > 0)
767 {
768 --nameIndex;
769 }
770 }
771 else
772 {
773 nameIndex = 0;
774 }
775
776 if (psuNames.size() <= nameIndex)
777 {
778 std::cerr << "Could not pair " << labelHead
779 << " with a Name field\n";
780 continue;
781 }
782
783 psuNameFromIndex = psuNames[nameIndex];
784
Ed Tanous8a57ec02020-10-09 12:46:52 -0700785 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700786 {
787 std::cerr << "Sensor label head " << labelHead
788 << " paired with " << psuNameFromIndex
789 << " at index " << nameIndex << "\n";
790 }
Josh Lehan432d1ed2019-10-16 12:23:31 -0700791 }
792
Cheng C Yang58b2b532019-05-31 00:19:45 +0800793 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
794
Josh Lehan74d9bd92019-10-31 08:51:58 -0700795 // Similarly, if sensor scaling factor is being customized,
796 // then the below power-of-10 constraint becomes unnecessary,
797 // as config should be able to specify an arbitrary divisor.
798 unsigned int factor = psuProperty->sensorScaleFactor;
799 if (!customizedScale)
Vijay Khemka53ca4442019-07-23 11:03:55 -0700800 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700801 // Preserve existing usage of hardcoded labelMatch table below
802 factor = std::pow(10.0, factor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700803
Josh Lehan74d9bd92019-10-31 08:51:58 -0700804 /* Change first char of substring to uppercase */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700805 char firstChar =
806 static_cast<char>(std::toupper(sensorNameSubStr[0]));
Josh Lehan74d9bd92019-10-31 08:51:58 -0700807 std::string strScaleFactor =
808 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
809
810 // Preserve existing configs by accepting earlier syntax,
811 // example CurrScaleFactor, PowerScaleFactor, ...
Zev Weisse8b97ee2022-08-12 15:23:51 -0700812 auto findScaleFactor = baseConfig->find(strScaleFactor);
813 if (findScaleFactor != baseConfig->end())
Josh Lehan74d9bd92019-10-31 08:51:58 -0700814 {
815 factor = std::visit(VariantToIntVisitor(),
816 findScaleFactor->second);
817 }
818
Ed Tanous8a57ec02020-10-09 12:46:52 -0700819 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700820 {
821 std::cerr << "Sensor scaling factor " << factor
822 << " string " << strScaleFactor << "\n";
823 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700824 }
825
Vijay Khemka996bad12019-05-28 15:15:16 -0700826 std::vector<thresholds::Threshold> sensorThresholds;
Joshi, Mansi14f0ad82019-11-21 10:52:30 +0530827 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds,
828 &labelHead))
Cheng C Yange50345b2019-04-02 17:26:15 +0800829 {
James Feist17ab6e02019-06-25 12:28:13 -0700830 std::cerr << "error populating thresholds for "
831 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800832 }
833
Zev Weiss6b6891c2021-04-22 02:46:21 -0500834 auto findSensorUnit = sensorTable.find(sensorNameSubStr);
835 if (findSensorUnit == sensorTable.end())
Cheng C Yange50345b2019-04-02 17:26:15 +0800836 {
Jason Ling5747fab2019-10-02 16:46:23 -0700837 std::cerr << sensorNameSubStr
Josh Lehan06494452019-10-31 09:49:16 -0700838 << " is not a recognized sensor type\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800839 continue;
840 }
841
Ed Tanous8a57ec02020-10-09 12:46:52 -0700842 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700843 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700844 std::cerr << "Sensor properties: Name \""
845 << psuProperty->labelTypeName << "\" Scale "
846 << psuProperty->sensorScaleFactor << " Min "
847 << psuProperty->minReading << " Max "
Jeff Line41d52f2021-04-07 19:38:51 +0800848 << psuProperty->maxReading << " Offset "
849 << psuProperty->sensorOffset << "\n";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700850 }
851
852 std::string sensorName = psuProperty->labelTypeName;
853 if (customizedName)
854 {
855 if (sensorName.empty())
856 {
857 // Allow selective disabling of an individual sensor,
858 // by customizing its name to an empty string.
859 std::cerr << "Sensor disabled, empty string\n";
860 continue;
861 }
862 }
863 else
864 {
865 // Sensor name not customized, do prefix/suffix composition,
866 // preserving default behavior by using psuNameFromIndex.
867 sensorName =
868 psuNameFromIndex + " " + psuProperty->labelTypeName;
869 }
870
Ed Tanous8a57ec02020-10-09 12:46:52 -0700871 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700872 {
873 std::cerr << "Sensor name \"" << sensorName << "\" path \""
874 << sensorPathStr << "\" type \"" << sensorType
875 << "\"\n";
Josh Lehan49cfba92019-10-08 16:50:42 -0700876 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800877 // destruct existing one first if already created
878 sensors[sensorName] = nullptr;
Yong Libf8b1da2020-04-15 16:32:50 +0800879 sensors[sensorName] = std::make_shared<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800880 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800881 sensorName, std::move(sensorThresholds), *interfacePath,
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000882 readState, findSensorUnit->second, factor,
883 psuProperty->maxReading, psuProperty->minReading,
884 psuProperty->sensorOffset, labelHead, thresholdConfSize,
885 pollRate);
Yong Libf8b1da2020-04-15 16:32:50 +0800886 sensors[sensorName]->setupRead();
Josh Lehan74d9bd92019-10-31 08:51:58 -0700887 ++numCreated;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700888 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700889 {
890 std::cerr << "Created " << numCreated << " sensors so far\n";
891 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800892 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800893
894 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800895 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800896 combineEvents[*psuName + "OperationalStatus"] =
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000897 std::make_unique<PSUCombineEvent>(objectServer, dbusConnection, io,
898 *psuName, readState,
899 eventPathList, groupEventPathList,
900 "OperationalStatus", pollRate);
Cheng C Yang209ec562019-03-12 16:37:44 +0800901 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700902
Ed Tanous8a57ec02020-10-09 12:46:52 -0700903 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700904 {
905 std::cerr << "Created total of " << numCreated << " sensors\n";
906 }
Ed Tanous2049bd22022-07-09 07:20:26 -0700907 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800908
Zhikui Ren23c96e72020-11-05 22:32:28 -0800909void createSensors(
910 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
911 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
912 const std::shared_ptr<boost::container::flat_set<std::string>>&
913 sensorsChanged)
914{
915 auto getter = std::make_shared<GetSensorConfiguration>(
916 dbusConnection, [&io, &objectServer, &dbusConnection, sensorsChanged](
917 const ManagedObjectType& sensorConfigs) {
918 createSensorsCallback(io, objectServer, dbusConnection,
919 sensorConfigs, sensorsChanged);
920 });
921 getter->getConfiguration(
922 std::vector<std::string>(sensorTypes.begin(), sensorTypes.end()));
923}
924
Cheng C Yang916360b2019-05-07 18:47:16 +0800925void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800926{
Zev Weiss6b6891c2021-04-22 02:46:21 -0500927 sensorTable = {{"power", sensor_paths::unitWatts},
928 {"curr", sensor_paths::unitAmperes},
929 {"temp", sensor_paths::unitDegreesC},
930 {"in", sensor_paths::unitVolts},
931 {"fan", sensor_paths::unitRPMs}};
Cheng C Yange50345b2019-04-02 17:26:15 +0800932
Jeff Line41d52f2021-04-07 19:38:51 +0800933 labelMatch = {
934 {"pin", PSUProperty("Input Power", 3000, 0, 6, 0)},
Zhikui Ren85fa3c62022-02-26 23:03:34 -0800935 {"pin1", PSUProperty("Input Power", 3000, 0, 6, 0)},
936 {"pin2", PSUProperty("Input Power", 3000, 0, 6, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800937 {"pout1", PSUProperty("Output Power", 3000, 0, 6, 0)},
938 {"pout2", PSUProperty("Output Power", 3000, 0, 6, 0)},
939 {"pout3", PSUProperty("Output Power", 3000, 0, 6, 0)},
940 {"power1", PSUProperty("Output Power", 3000, 0, 6, 0)},
Zhikui Ren85fa3c62022-02-26 23:03:34 -0800941 {"power2", PSUProperty("Output Power", 3000, 0, 6, 0)},
942 {"power3", PSUProperty("Output Power", 3000, 0, 6, 0)},
943 {"power4", PSUProperty("Output Power", 3000, 0, 6, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800944 {"maxpin", PSUProperty("Max Input Power", 3000, 0, 6, 0)},
945 {"vin", PSUProperty("Input Voltage", 300, 0, 3, 0)},
946 {"maxvin", PSUProperty("Max Input Voltage", 300, 0, 3, 0)},
947 {"vout1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
948 {"vout2", PSUProperty("Output Voltage", 255, 0, 3, 0)},
949 {"vout3", PSUProperty("Output Voltage", 255, 0, 3, 0)},
950 {"vout4", PSUProperty("Output Voltage", 255, 0, 3, 0)},
951 {"vout5", PSUProperty("Output Voltage", 255, 0, 3, 0)},
952 {"vout6", PSUProperty("Output Voltage", 255, 0, 3, 0)},
953 {"vout7", PSUProperty("Output Voltage", 255, 0, 3, 0)},
954 {"vout8", PSUProperty("Output Voltage", 255, 0, 3, 0)},
955 {"vout9", PSUProperty("Output Voltage", 255, 0, 3, 0)},
956 {"vout10", PSUProperty("Output Voltage", 255, 0, 3, 0)},
957 {"vout11", PSUProperty("Output Voltage", 255, 0, 3, 0)},
958 {"vout12", PSUProperty("Output Voltage", 255, 0, 3, 0)},
959 {"vout13", PSUProperty("Output Voltage", 255, 0, 3, 0)},
960 {"vout14", PSUProperty("Output Voltage", 255, 0, 3, 0)},
961 {"vout15", PSUProperty("Output Voltage", 255, 0, 3, 0)},
962 {"vout16", PSUProperty("Output Voltage", 255, 0, 3, 0)},
963 {"vout17", PSUProperty("Output Voltage", 255, 0, 3, 0)},
964 {"vout18", PSUProperty("Output Voltage", 255, 0, 3, 0)},
965 {"vout19", PSUProperty("Output Voltage", 255, 0, 3, 0)},
966 {"vout20", PSUProperty("Output Voltage", 255, 0, 3, 0)},
967 {"vout21", PSUProperty("Output Voltage", 255, 0, 3, 0)},
968 {"vout22", PSUProperty("Output Voltage", 255, 0, 3, 0)},
969 {"vout23", PSUProperty("Output Voltage", 255, 0, 3, 0)},
970 {"vout24", PSUProperty("Output Voltage", 255, 0, 3, 0)},
971 {"vout25", PSUProperty("Output Voltage", 255, 0, 3, 0)},
972 {"vout26", PSUProperty("Output Voltage", 255, 0, 3, 0)},
973 {"vout27", PSUProperty("Output Voltage", 255, 0, 3, 0)},
974 {"vout28", PSUProperty("Output Voltage", 255, 0, 3, 0)},
975 {"vout29", PSUProperty("Output Voltage", 255, 0, 3, 0)},
976 {"vout30", PSUProperty("Output Voltage", 255, 0, 3, 0)},
977 {"vout31", PSUProperty("Output Voltage", 255, 0, 3, 0)},
978 {"vout32", PSUProperty("Output Voltage", 255, 0, 3, 0)},
979 {"vmon", PSUProperty("Auxiliary Input Voltage", 255, 0, 3, 0)},
Tim Chao6f379ce2022-02-24 11:08:09 +0800980 {"in0", PSUProperty("Output Voltage", 255, 0, 3, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800981 {"in1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
Tim Chao6f379ce2022-02-24 11:08:09 +0800982 {"in2", PSUProperty("Output Voltage", 255, 0, 3, 0)},
983 {"in3", PSUProperty("Output Voltage", 255, 0, 3, 0)},
984 {"in4", PSUProperty("Output Voltage", 255, 0, 3, 0)},
985 {"in5", PSUProperty("Output Voltage", 255, 0, 3, 0)},
986 {"in6", PSUProperty("Output Voltage", 255, 0, 3, 0)},
987 {"in7", PSUProperty("Output Voltage", 255, 0, 3, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800988 {"iin", PSUProperty("Input Current", 20, 0, 3, 0)},
Zhikui Ren85fa3c62022-02-26 23:03:34 -0800989 {"iin1", PSUProperty("Input Current", 20, 0, 3, 0)},
990 {"iin2", PSUProperty("Input Current", 20, 0, 3, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +0800991 {"iout1", PSUProperty("Output Current", 255, 0, 3, 0)},
992 {"iout2", PSUProperty("Output Current", 255, 0, 3, 0)},
993 {"iout3", PSUProperty("Output Current", 255, 0, 3, 0)},
994 {"iout4", PSUProperty("Output Current", 255, 0, 3, 0)},
995 {"iout5", PSUProperty("Output Current", 255, 0, 3, 0)},
996 {"iout6", PSUProperty("Output Current", 255, 0, 3, 0)},
997 {"iout7", PSUProperty("Output Current", 255, 0, 3, 0)},
998 {"iout8", PSUProperty("Output Current", 255, 0, 3, 0)},
999 {"iout9", PSUProperty("Output Current", 255, 0, 3, 0)},
1000 {"iout10", PSUProperty("Output Current", 255, 0, 3, 0)},
1001 {"iout11", PSUProperty("Output Current", 255, 0, 3, 0)},
1002 {"iout12", PSUProperty("Output Current", 255, 0, 3, 0)},
1003 {"iout13", PSUProperty("Output Current", 255, 0, 3, 0)},
1004 {"iout14", PSUProperty("Output Current", 255, 0, 3, 0)},
1005 {"curr1", PSUProperty("Output Current", 255, 0, 3, 0)},
Zhikui Ren85fa3c62022-02-26 23:03:34 -08001006 {"curr2", PSUProperty("Output Current", 255, 0, 3, 0)},
1007 {"curr3", PSUProperty("Output Current", 255, 0, 3, 0)},
1008 {"curr4", PSUProperty("Output Current", 255, 0, 3, 0)},
Jeff Line41d52f2021-04-07 19:38:51 +08001009 {"maxiout1", PSUProperty("Max Output Current", 255, 0, 3, 0)},
1010 {"temp1", PSUProperty("Temperature", 127, -128, 3, 0)},
1011 {"temp2", PSUProperty("Temperature", 127, -128, 3, 0)},
1012 {"temp3", PSUProperty("Temperature", 127, -128, 3, 0)},
1013 {"temp4", PSUProperty("Temperature", 127, -128, 3, 0)},
1014 {"temp5", PSUProperty("Temperature", 127, -128, 3, 0)},
1015 {"temp6", PSUProperty("Temperature", 127, -128, 3, 0)},
1016 {"maxtemp1", PSUProperty("Max Temperature", 127, -128, 3, 0)},
1017 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0, 0)},
1018 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +08001019
1020 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +08001021
1022 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
1023 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
1024
Cheng C Yang202a1ff2020-01-09 09:34:22 +08001025 eventMatch = {{"PredictiveFailure", {"power1_alarm"}},
1026 {"Failure", {"in2_alarm"}},
1027 {"ACLost", {"in1_beep"}},
1028 {"ConfigureError", {"in1_fault"}}};
1029
1030 groupEventMatch = {{"FanFault",
1031 {{"fan1", {"fan1_alarm", "fan1_fault"}},
1032 {"fan2", {"fan2_alarm", "fan2_fault"}}}}};
Cheng C Yang209ec562019-03-12 16:37:44 +08001033}
1034
James Feistb6c0b912019-07-09 12:21:44 -07001035int main()
Cheng C Yang209ec562019-03-12 16:37:44 +08001036{
1037 boost::asio::io_service io;
1038 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
1039
Ed Tanous14ed5e92022-07-12 15:50:23 -07001040 sdbusplus::asio::object_server objectServer(systemBus, true);
1041 objectServer.add_manager("/xyz/openbmc_project/sensors");
Zhikui Ren3fe3f542022-11-02 16:37:54 -07001042 objectServer.add_manager("/xyz/openbmc_project/control");
Cheng C Yang209ec562019-03-12 16:37:44 +08001043 systemBus->request_name("xyz.openbmc_project.PSUSensor");
Zhikui Ren23c96e72020-11-05 22:32:28 -08001044 auto sensorsChanged =
1045 std::make_shared<boost::container::flat_set<std::string>>();
Cheng C Yang209ec562019-03-12 16:37:44 +08001046
Cheng C Yang916360b2019-05-07 18:47:16 +08001047 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +08001048
Zhikui Ren23c96e72020-11-05 22:32:28 -08001049 io.post([&]() { createSensors(io, objectServer, systemBus, nullptr); });
Ed Tanous9b4a20e2022-09-06 08:47:11 -07001050 boost::asio::steady_timer filterTimer(io);
Patrick Williams92f8f512022-07-22 19:26:55 -05001051 std::function<void(sdbusplus::message_t&)> eventHandler =
1052 [&](sdbusplus::message_t& message) {
Cheng C Yang209ec562019-03-12 16:37:44 +08001053 if (message.is_method_error())
1054 {
1055 std::cerr << "callback method error\n";
1056 return;
1057 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001058 sensorsChanged->insert(message.get_path());
Ed Tanous9b4a20e2022-09-06 08:47:11 -07001059 filterTimer.expires_from_now(std::chrono::seconds(3));
Cheng C Yang209ec562019-03-12 16:37:44 +08001060 filterTimer.async_wait([&](const boost::system::error_code& ec) {
1061 if (ec == boost::asio::error::operation_aborted)
1062 {
1063 return;
1064 }
Ed Tanous8a57ec02020-10-09 12:46:52 -07001065 if (ec)
Cheng C Yang209ec562019-03-12 16:37:44 +08001066 {
1067 std::cerr << "timer error\n";
1068 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001069 createSensors(io, objectServer, systemBus, sensorsChanged);
Cheng C Yang209ec562019-03-12 16:37:44 +08001070 });
1071 };
1072
Zev Weiss214d9712022-08-12 12:54:31 -07001073 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
1074 setupPropertiesChangedMatches(*systemBus, sensorTypes, eventHandler);
Bruce Lee1263c3d2021-06-04 15:16:33 +08001075 setupManufacturingModeMatch(*systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001076 io.run();
1077}