blob: 2d40dc35014f4e9421d9132f40105dadddcc7eed [file] [log] [blame]
James Feist6ef20402019-01-07 16:45:08 -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*/
16
Ed Tanous8a57ec02020-10-09 12:46:52 -070017#include <IpmbSensor.hpp>
18#include <Utils.hpp>
19#include <VariantVisitors.hpp>
James Feist6ef20402019-01-07 16:45:08 -080020#include <boost/algorithm/string/predicate.hpp>
21#include <boost/algorithm/string/replace.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070022#include <boost/container/flat_map.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
James Feist6ef20402019-01-07 16:45:08 -080027#include <chrono>
Ed Tanous8a57ec02020-10-09 12:46:52 -070028#include <cmath>
Patrick Venture96e97db2019-10-31 13:44:38 -070029#include <functional>
James Feist6ef20402019-01-07 16:45:08 -080030#include <iostream>
31#include <limits>
Patrick Venture96e97db2019-10-31 13:44:38 -070032#include <memory>
James Feist6ef20402019-01-07 16:45:08 -080033#include <numeric>
Patrick Venture96e97db2019-10-31 13:44:38 -070034#include <string>
35#include <tuple>
36#include <variant>
James Feist6ef20402019-01-07 16:45:08 -080037#include <vector>
38
39constexpr const bool debug = false;
40
41constexpr const char* configInterface =
42 "xyz.openbmc_project.Configuration.IpmbSensor";
43static constexpr double ipmbMaxReading = 0xFF;
44static constexpr double ipmbMinReading = 0;
45
46static constexpr uint8_t meAddress = 1;
47static constexpr uint8_t lun = 0;
Anoop S832a2c62020-11-20 19:21:22 +000048static constexpr uint8_t hostSMbusIndexDefault = 0x03;
James Feist6ef20402019-01-07 16:45:08 -080049
Vijay Khemka682a5cb2019-07-18 17:34:03 -070050static constexpr const char* sensorPathPrefix = "/xyz/openbmc_project/sensors/";
51
James Feist6ef20402019-01-07 16:45:08 -080052using IpmbMethodType =
53 std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>;
54
James Feistf7e2c5d2019-02-13 17:27:51 -080055boost::container::flat_map<std::string, std::unique_ptr<IpmbSensor>> sensors;
56
James Feist0d4f2bd2019-03-05 13:15:40 -080057std::unique_ptr<boost::asio::deadline_timer> initCmdTimer;
58
James Feist6ef20402019-01-07 16:45:08 -080059IpmbSensor::IpmbSensor(std::shared_ptr<sdbusplus::asio::connection>& conn,
60 boost::asio::io_service& io,
61 const std::string& sensorName,
62 const std::string& sensorConfiguration,
63 sdbusplus::asio::object_server& objectServer,
64 std::vector<thresholds::Threshold>&& thresholdData,
Anoop S832a2c62020-11-20 19:21:22 +000065 uint8_t deviceAddress, uint8_t hostSMbusIndex,
66 std::string& sensorTypeName) :
James Feist6ef20402019-01-07 16:45:08 -080067 Sensor(boost::replace_all_copy(sensorName, " ", "_"),
James Feist930fcde2019-05-28 12:58:43 -070068 std::move(thresholdData), sensorConfiguration,
69 "xyz.openbmc_project.Configuration.ExitAirTemp", ipmbMaxReading,
James Feiste3338522020-09-15 15:40:30 -070070 ipmbMinReading, conn, PowerState::on),
Anoop S832a2c62020-11-20 19:21:22 +000071 deviceAddress(deviceAddress), hostSMbusIndex(hostSMbusIndex),
72 objectServer(objectServer), waitTimer(io)
James Feist6ef20402019-01-07 16:45:08 -080073{
Vijay Khemka682a5cb2019-07-18 17:34:03 -070074 std::string dbusPath = sensorPathPrefix + sensorTypeName + "/" + name;
75
James Feist6ef20402019-01-07 16:45:08 -080076 sensorInterface = objectServer.add_interface(
Vijay Khemka682a5cb2019-07-18 17:34:03 -070077 dbusPath, "xyz.openbmc_project.Sensor.Value");
James Feist6ef20402019-01-07 16:45:08 -080078
79 if (thresholds::hasWarningInterface(thresholds))
80 {
81 thresholdInterfaceWarning = objectServer.add_interface(
Vijay Khemka682a5cb2019-07-18 17:34:03 -070082 dbusPath, "xyz.openbmc_project.Sensor.Threshold.Warning");
James Feist6ef20402019-01-07 16:45:08 -080083 }
84 if (thresholds::hasCriticalInterface(thresholds))
85 {
86 thresholdInterfaceCritical = objectServer.add_interface(
Vijay Khemka682a5cb2019-07-18 17:34:03 -070087 dbusPath, "xyz.openbmc_project.Sensor.Threshold.Critical");
James Feist6ef20402019-01-07 16:45:08 -080088 }
James Feist2adc95c2019-09-30 14:55:28 -070089 association = objectServer.add_interface(dbusPath, association::interface);
James Feist6ef20402019-01-07 16:45:08 -080090}
91
92IpmbSensor::~IpmbSensor()
93{
94 waitTimer.cancel();
95 objectServer.remove_interface(thresholdInterfaceWarning);
96 objectServer.remove_interface(thresholdInterfaceCritical);
97 objectServer.remove_interface(sensorInterface);
James Feist078f2322019-03-08 11:09:05 -080098 objectServer.remove_interface(association);
James Feist6ef20402019-01-07 16:45:08 -080099}
100
101void IpmbSensor::init(void)
102{
James Feist6ef20402019-01-07 16:45:08 -0800103 loadDefaults();
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200104 setInitialProperties(dbusConnection);
James Feist6ef20402019-01-07 16:45:08 -0800105 if (initCommand)
106 {
James Feistf7e2c5d2019-02-13 17:27:51 -0800107 runInitCmd();
108 }
109 read();
110}
111
112void IpmbSensor::runInitCmd()
113{
114 if (initCommand)
115 {
James Feist6ef20402019-01-07 16:45:08 -0800116 dbusConnection->async_method_call(
117 [this](boost::system::error_code ec,
118 const IpmbMethodType& response) {
119 const int& status = std::get<0>(response);
120
121 if (ec || status)
122 {
123 std::cerr
124 << "Error setting init command for device: " << name
125 << "\n";
126 }
James Feist6ef20402019-01-07 16:45:08 -0800127 },
128 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
129 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
130 "sendRequest", commandAddress, netfn, lun, *initCommand, initData);
131 }
James Feist6ef20402019-01-07 16:45:08 -0800132}
133
134void IpmbSensor::loadDefaults()
135{
136 if (type == IpmbType::meSensor)
137 {
138 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200139 netfn = ipmi::sensor::netFn;
140 command = ipmi::sensor::getSensorReading;
James Feist6ef20402019-01-07 16:45:08 -0800141 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700142 readingFormat = ReadingFormat::byte0;
James Feist6ef20402019-01-07 16:45:08 -0800143 }
144 else if (type == IpmbType::PXE1410CVR)
145 {
146 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200147 netfn = ipmi::me_bridge::netFn;
148 command = ipmi::me_bridge::sendRawPmbus;
149 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700150 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000151 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
152 deviceAddress, 0x00, 0x00, 0x00, 0x00,
153 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700154 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000155 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
156 deviceAddress, 0x00, 0x00, 0x00, 0x00,
157 0x02, 0x00, 0x00, 0x00};
Jayashree-D37322572021-03-19 17:40:56 +0530158 readingFormat = ReadingFormat::linearElevenBit;
James Feist6ef20402019-01-07 16:45:08 -0800159 }
160 else if (type == IpmbType::IR38363VR)
161 {
162 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200163 netfn = ipmi::me_bridge::netFn;
164 command = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700165 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000166 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
167 deviceAddress, 00, 0x00, 0x00, 0x00,
168 0x01, 0x02, 0x8D};
James Feistd7ae29a2020-06-25 15:42:46 -0700169 readingFormat = ReadingFormat::elevenBitShift;
James Feist6ef20402019-01-07 16:45:08 -0800170 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700171 else if (type == IpmbType::ADM1278HSC)
172 {
173 commandAddress = meAddress;
174 switch (subType)
175 {
176 case IpmbSubType::temp:
177 case IpmbSubType::curr:
178 uint8_t snsNum;
179 if (subType == IpmbSubType::temp)
Ed Tanous8a57ec02020-10-09 12:46:52 -0700180 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700181 snsNum = 0x8d;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700182 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700183 else
Ed Tanous8a57ec02020-10-09 12:46:52 -0700184 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700185 snsNum = 0x8c;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700186 }
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200187 netfn = ipmi::me_bridge::netFn;
188 command = ipmi::me_bridge::sendRawPmbus;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700189 commandData = {0x57, 0x01, 0x00, 0x86, deviceAddress,
190 0x00, 0x00, 0x01, 0x02, snsNum};
James Feistd7ae29a2020-06-25 15:42:46 -0700191 readingFormat = ReadingFormat::elevenBit;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700192 break;
193 case IpmbSubType::power:
194 case IpmbSubType::volt:
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200195 netfn = ipmi::sensor::netFn;
196 command = ipmi::sensor::getSensorReading;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700197 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700198 readingFormat = ReadingFormat::byte0;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700199 break;
200 default:
201 throw std::runtime_error("Invalid sensor type");
202 }
203 }
James Feist6ef20402019-01-07 16:45:08 -0800204 else if (type == IpmbType::mpsVR)
205 {
206 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200207 netfn = ipmi::me_bridge::netFn;
208 command = ipmi::me_bridge::sendRawPmbus;
209 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700210 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000211 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
212 deviceAddress, 0x00, 0x00, 0x00, 0x00,
213 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700214 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000215 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
216 deviceAddress, 0x00, 0x00, 0x00, 0x00,
217 0x02, 0x00, 0x00, 0x00};
James Feistd7ae29a2020-06-25 15:42:46 -0700218 readingFormat = ReadingFormat::byte3;
James Feist6ef20402019-01-07 16:45:08 -0800219 }
220 else
221 {
222 throw std::runtime_error("Invalid sensor type");
223 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200224
225 if (subType == IpmbSubType::util)
226 {
227 // Utilization need to be scaled to percent
228 maxValue = 100;
229 minValue = 0;
230 }
James Feist6ef20402019-01-07 16:45:08 -0800231}
232
233void IpmbSensor::checkThresholds(void)
234{
James Feist6ef20402019-01-07 16:45:08 -0800235 thresholds::checkThresholds(this);
236}
237
James Feist961bf092020-07-01 16:38:12 -0700238bool IpmbSensor::processReading(const std::vector<uint8_t>& data, double& resp)
James Feistd7ae29a2020-06-25 15:42:46 -0700239{
240
241 switch (readingFormat)
242 {
243 case (ReadingFormat::byte0):
James Feiste4a970d2020-08-19 11:21:58 -0700244 {
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200245 if (command == ipmi::sensor::getSensorReading &&
246 !ipmi::sensor::isValid(data))
James Feistcf4238e2020-07-28 16:40:03 -0700247 {
248 return false;
249 }
James Feist961bf092020-07-01 16:38:12 -0700250 resp = data[0];
251 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700252 }
James Feistd7ae29a2020-06-25 15:42:46 -0700253 case (ReadingFormat::byte3):
James Feiste4a970d2020-08-19 11:21:58 -0700254 {
James Feistd7ae29a2020-06-25 15:42:46 -0700255 if (data.size() < 4)
256 {
James Feist961bf092020-07-01 16:38:12 -0700257 if (!errCount)
258 {
259 std::cerr << "Invalid data length returned for " << name
260 << "\n";
261 }
262 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700263 }
James Feist961bf092020-07-01 16:38:12 -0700264 resp = data[3];
265 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700266 }
James Feistd7ae29a2020-06-25 15:42:46 -0700267 case (ReadingFormat::elevenBit):
James Feiste4a970d2020-08-19 11:21:58 -0700268 {
James Feistd7ae29a2020-06-25 15:42:46 -0700269 if (data.size() < 5)
270 {
James Feist961bf092020-07-01 16:38:12 -0700271 if (!errCount)
272 {
273 std::cerr << "Invalid data length returned for " << name
274 << "\n";
275 }
276 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700277 }
278
James Feiste4a970d2020-08-19 11:21:58 -0700279 int16_t value = ((data[4] << 8) | data[3]);
James Feiste4a970d2020-08-19 11:21:58 -0700280 resp = value;
James Feist961bf092020-07-01 16:38:12 -0700281 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700282 }
James Feistd7ae29a2020-06-25 15:42:46 -0700283 case (ReadingFormat::elevenBitShift):
James Feiste4a970d2020-08-19 11:21:58 -0700284 {
James Feistd7ae29a2020-06-25 15:42:46 -0700285 if (data.size() < 5)
286 {
James Feist961bf092020-07-01 16:38:12 -0700287 if (!errCount)
288 {
289 std::cerr << "Invalid data length returned for " << name
290 << "\n";
291 }
292 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700293 }
294
James Feist961bf092020-07-01 16:38:12 -0700295 resp = ((data[4] << 8) | data[3]) >> 3;
296 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700297 }
Jayashree-D37322572021-03-19 17:40:56 +0530298 case (ReadingFormat::linearElevenBit):
299 {
300 if (data.size() < 5)
301 {
302 if (!errCount)
303 {
304 std::cerr << "Invalid data length returned for " << name
305 << "\n";
306 }
307 return false;
308 }
309
310 int16_t value = ((data[4] << 8) | data[3]);
311 constexpr const size_t shift = 16 - 11; // 11bit into 16bit
312 value <<= shift;
313 value >>= shift;
314 resp = value;
315 return true;
316 }
James Feistd7ae29a2020-06-25 15:42:46 -0700317 default:
318 throw std::runtime_error("Invalid reading type");
319 }
320}
321
James Feist6ef20402019-01-07 16:45:08 -0800322void IpmbSensor::read(void)
323{
324 static constexpr size_t pollTime = 1; // in seconds
325
326 waitTimer.expires_from_now(boost::posix_time::seconds(pollTime));
327 waitTimer.async_wait([this](const boost::system::error_code& ec) {
328 if (ec == boost::asio::error::operation_aborted)
329 {
330 return; // we're being canceled
331 }
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200332 if (!readingStateGood())
James Feist6ef20402019-01-07 16:45:08 -0800333 {
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200334 updateValue(std::numeric_limits<double>::quiet_NaN());
James Feist6ef20402019-01-07 16:45:08 -0800335 read();
336 return;
337 }
338 dbusConnection->async_method_call(
339 [this](boost::system::error_code ec,
340 const IpmbMethodType& response) {
341 const int& status = std::get<0>(response);
342 if (ec || status)
343 {
James Feist961bf092020-07-01 16:38:12 -0700344 incrementError();
James Feist6ef20402019-01-07 16:45:08 -0800345 read();
346 return;
347 }
348 const std::vector<uint8_t>& data = std::get<5>(response);
349 if constexpr (debug)
350 {
351 std::cout << name << ": ";
352 for (size_t d : data)
353 {
354 std::cout << d << " ";
355 }
356 std::cout << "\n";
357 }
James Feistd7ae29a2020-06-25 15:42:46 -0700358 if (data.empty())
James Feist6ef20402019-01-07 16:45:08 -0800359 {
James Feist961bf092020-07-01 16:38:12 -0700360 incrementError();
James Feistd7ae29a2020-06-25 15:42:46 -0700361 read();
362 return;
James Feist6ef20402019-01-07 16:45:08 -0800363 }
James Feist961bf092020-07-01 16:38:12 -0700364
365 double value = 0;
366
367 if (!processReading(data, value))
368 {
369 incrementError();
370 read();
371 return;
372 }
Ed Tanous8a57ec02020-10-09 12:46:52 -0700373
374 // rawValue only used in debug logging
375 // up to 5th byte in data are used to derive value
376 size_t end = std::min(sizeof(uint64_t), data.size());
377 uint64_t rawData = 0;
378 for (size_t i = 0; i < end; i++)
Zhikui Rend3da1282020-09-11 17:02:01 -0700379 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700380 reinterpret_cast<uint8_t*>(&rawData)[i] = data[i];
Zhikui Rend3da1282020-09-11 17:02:01 -0700381 }
Ed Tanous8a57ec02020-10-09 12:46:52 -0700382 rawValue = static_cast<double>(rawData);
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700383
384 /* Adjust value as per scale and offset */
385 value = (value * scaleVal) + offsetVal;
James Feist6ef20402019-01-07 16:45:08 -0800386 updateValue(value);
387 read();
388 },
389 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
390 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
391 "sendRequest", commandAddress, netfn, lun, command, commandData);
392 });
393}
394void createSensors(
395 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
396 boost::container::flat_map<std::string, std::unique_ptr<IpmbSensor>>&
397 sensors,
398 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
399{
400 if (!dbusConnection)
401 {
402 std::cerr << "Connection not created\n";
403 return;
404 }
405 dbusConnection->async_method_call(
406 [&](boost::system::error_code ec, const ManagedObjectType& resp) {
407 if (ec)
408 {
409 std::cerr << "Error contacting entity manager\n";
410 return;
411 }
412 for (const auto& pathPair : resp)
413 {
414 for (const auto& entry : pathPair.second)
415 {
416 if (entry.first != configInterface)
417 {
418 continue;
419 }
420 std::string name =
421 loadVariant<std::string>(entry.second, "Name");
422
423 std::vector<thresholds::Threshold> sensorThresholds;
424 if (!parseThresholdsFromConfig(pathPair.second,
425 sensorThresholds))
426 {
427 std::cerr << "error populating thresholds for " << name
428 << "\n";
429 }
430 uint8_t deviceAddress =
431 loadVariant<uint8_t>(entry.second, "Address");
432
433 std::string sensorClass =
434 loadVariant<std::string>(entry.second, "Class");
Anoop S832a2c62020-11-20 19:21:22 +0000435 uint8_t hostSMbusIndex = hostSMbusIndexDefault;
436 auto findSmType = entry.second.find("HostSMbusIndex");
437 if (findSmType != entry.second.end())
438 {
439 hostSMbusIndex = std::visit(
440 VariantToUnsignedIntVisitor(), findSmType->second);
441 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700442
443 /* Default sensor type is "temperature" */
444 std::string sensorTypeName = "temperature";
445 auto findType = entry.second.find("SensorType");
446 if (findType != entry.second.end())
447 {
448 sensorTypeName = std::visit(VariantToStringVisitor(),
449 findType->second);
450 }
451
James Feist6ef20402019-01-07 16:45:08 -0800452 auto& sensor = sensors[name];
453 sensor = std::make_unique<IpmbSensor>(
454 dbusConnection, io, name, pathPair.first, objectServer,
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700455 std::move(sensorThresholds), deviceAddress,
Anoop S832a2c62020-11-20 19:21:22 +0000456 hostSMbusIndex, sensorTypeName);
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700457
458 /* Initialize scale and offset value */
459 sensor->scaleVal = 1;
460 sensor->offsetVal = 0;
461
462 auto findScaleVal = entry.second.find("ScaleValue");
463 if (findScaleVal != entry.second.end())
464 {
465 sensor->scaleVal = std::visit(VariantToDoubleVisitor(),
466 findScaleVal->second);
467 }
468
469 auto findOffsetVal = entry.second.find("OffsetValue");
470 if (findOffsetVal != entry.second.end())
471 {
472 sensor->offsetVal = std::visit(VariantToDoubleVisitor(),
473 findOffsetVal->second);
474 }
James Feist6ef20402019-01-07 16:45:08 -0800475
James Feistfc94b212019-02-06 16:14:51 -0800476 auto findPowerState = entry.second.find("PowerState");
477
478 if (findPowerState != entry.second.end())
479 {
480 std::string powerState = std::visit(
481 VariantToStringVisitor(), findPowerState->second);
482
483 setReadState(powerState, sensor->readState);
484 }
485
James Feist6ef20402019-01-07 16:45:08 -0800486 if (sensorClass == "PxeBridgeTemp")
487 {
488 sensor->type = IpmbType::PXE1410CVR;
489 }
490 else if (sensorClass == "IRBridgeTemp")
491 {
492 sensor->type = IpmbType::IR38363VR;
493 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700494 else if (sensorClass == "HSCBridge")
495 {
496 sensor->type = IpmbType::ADM1278HSC;
497 }
James Feist6ef20402019-01-07 16:45:08 -0800498 else if (sensorClass == "MpsBridgeTemp")
499 {
500 sensor->type = IpmbType::mpsVR;
501 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200502 else if (sensorClass == "METemp" ||
503 sensorClass == "MESensor")
James Feist6ef20402019-01-07 16:45:08 -0800504 {
505 sensor->type = IpmbType::meSensor;
506 }
507 else
508 {
509 std::cerr << "Invalid class " << sensorClass << "\n";
510 continue;
511 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700512
513 if (sensorTypeName == "voltage")
514 {
515 sensor->subType = IpmbSubType::volt;
516 }
517 else if (sensorTypeName == "power")
518 {
519 sensor->subType = IpmbSubType::power;
520 }
521 else if (sensorTypeName == "current")
522 {
523 sensor->subType = IpmbSubType::curr;
524 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200525 else if (sensorTypeName == "utilization")
526 {
527 sensor->subType = IpmbSubType::util;
528 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700529 else
530 {
531 sensor->subType = IpmbSubType::temp;
532 }
James Feist6ef20402019-01-07 16:45:08 -0800533 sensor->init();
534 }
535 }
536 },
537 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
538 "GetManagedObjects");
539}
540
James Feistf7e2c5d2019-02-13 17:27:51 -0800541void reinitSensors(sdbusplus::message::message& message)
542{
James Feist0d4f2bd2019-03-05 13:15:40 -0800543 constexpr const size_t reinitWaitSeconds = 2;
James Feistf7e2c5d2019-02-13 17:27:51 -0800544 std::string objectName;
James Feist52497fd2019-06-07 13:01:33 -0700545 boost::container::flat_map<std::string, std::variant<std::string>> values;
James Feistf7e2c5d2019-02-13 17:27:51 -0800546 message.read(objectName, values);
James Feist0d4f2bd2019-03-05 13:15:40 -0800547
James Feist52497fd2019-06-07 13:01:33 -0700548 auto findStatus = values.find(power::property);
549 if (findStatus != values.end())
James Feistf7e2c5d2019-02-13 17:27:51 -0800550 {
James Feist52497fd2019-06-07 13:01:33 -0700551 bool powerStatus = boost::ends_with(
552 std::get<std::string>(findStatus->second), "Running");
James Feistf7e2c5d2019-02-13 17:27:51 -0800553 if (powerStatus)
554 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800555 if (!initCmdTimer)
James Feistf7e2c5d2019-02-13 17:27:51 -0800556 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800557 // this should be impossible
558 return;
James Feistf7e2c5d2019-02-13 17:27:51 -0800559 }
James Feist0d4f2bd2019-03-05 13:15:40 -0800560 // we seem to send this command too fast sometimes, wait before
561 // sending
562 initCmdTimer->expires_from_now(
563 boost::posix_time::seconds(reinitWaitSeconds));
564
565 initCmdTimer->async_wait([](const boost::system::error_code ec) {
566 if (ec == boost::asio::error::operation_aborted)
567 {
568 return; // we're being canceled
569 }
570
571 for (const auto& sensor : sensors)
572 {
573 if (sensor.second)
574 {
575 sensor.second->runInitCmd();
576 }
577 }
578 });
James Feistf7e2c5d2019-02-13 17:27:51 -0800579 }
580 }
581}
582
James Feistb6c0b912019-07-09 12:21:44 -0700583int main()
James Feist6ef20402019-01-07 16:45:08 -0800584{
585
586 boost::asio::io_service io;
587 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
588 systemBus->request_name("xyz.openbmc_project.IpmbSensor");
589 sdbusplus::asio::object_server objectServer(systemBus);
James Feist6ef20402019-01-07 16:45:08 -0800590
James Feist0d4f2bd2019-03-05 13:15:40 -0800591 initCmdTimer = std::make_unique<boost::asio::deadline_timer>(io);
592
James Feist6ef20402019-01-07 16:45:08 -0800593 io.post([&]() { createSensors(io, objectServer, sensors, systemBus); });
594
595 boost::asio::deadline_timer configTimer(io);
596
597 std::function<void(sdbusplus::message::message&)> eventHandler =
James Feistb6c0b912019-07-09 12:21:44 -0700598 [&](sdbusplus::message::message&) {
James Feist6ef20402019-01-07 16:45:08 -0800599 configTimer.expires_from_now(boost::posix_time::seconds(1));
600 // create a timer because normally multiple properties change
601 configTimer.async_wait([&](const boost::system::error_code& ec) {
602 if (ec == boost::asio::error::operation_aborted)
603 {
604 return; // we're being canceled
605 }
606 createSensors(io, objectServer, sensors, systemBus);
607 if (sensors.empty())
608 {
609 std::cout << "Configuration not detected\n";
610 }
611 });
612 };
613
James Feistf7e2c5d2019-02-13 17:27:51 -0800614 sdbusplus::bus::match::match configMatch(
James Feist6ef20402019-01-07 16:45:08 -0800615 static_cast<sdbusplus::bus::bus&>(*systemBus),
616 "type='signal',member='PropertiesChanged',path_namespace='" +
617 std::string(inventoryPath) + "',arg0namespace='" + configInterface +
618 "'",
619 eventHandler);
620
James Feistf7e2c5d2019-02-13 17:27:51 -0800621 sdbusplus::bus::match::match powerChangeMatch(
622 static_cast<sdbusplus::bus::bus&>(*systemBus),
James Feist52497fd2019-06-07 13:01:33 -0700623 "type='signal',interface='" + std::string(properties::interface) +
624 "',path='" + std::string(power::path) + "',arg0='" +
625 std::string(power::interface) + "'",
James Feistf7e2c5d2019-02-13 17:27:51 -0800626 reinitSensors);
627
James Feist6ef20402019-01-07 16:45:08 -0800628 io.run();
629}