blob: edbe05f5c1779c0a2b407905a363b54f866f0e39 [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;
Jayashree-D9f6d4fd2021-04-13 18:27:22 +053049static constexpr float pollRateDefault = 1; // in seconds
James Feist6ef20402019-01-07 16:45:08 -080050
Vijay Khemka682a5cb2019-07-18 17:34:03 -070051static constexpr const char* sensorPathPrefix = "/xyz/openbmc_project/sensors/";
52
James Feist6ef20402019-01-07 16:45:08 -080053using IpmbMethodType =
54 std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>;
55
James Feistf7e2c5d2019-02-13 17:27:51 -080056boost::container::flat_map<std::string, std::unique_ptr<IpmbSensor>> sensors;
57
James Feist0d4f2bd2019-03-05 13:15:40 -080058std::unique_ptr<boost::asio::deadline_timer> initCmdTimer;
59
James Feist6ef20402019-01-07 16:45:08 -080060IpmbSensor::IpmbSensor(std::shared_ptr<sdbusplus::asio::connection>& conn,
61 boost::asio::io_service& io,
62 const std::string& sensorName,
63 const std::string& sensorConfiguration,
64 sdbusplus::asio::object_server& objectServer,
65 std::vector<thresholds::Threshold>&& thresholdData,
Anoop S832a2c62020-11-20 19:21:22 +000066 uint8_t deviceAddress, uint8_t hostSMbusIndex,
Jayashree-D9f6d4fd2021-04-13 18:27:22 +053067 const float pollRate, std::string& sensorTypeName) :
James Feist6ef20402019-01-07 16:45:08 -080068 Sensor(boost::replace_all_copy(sensorName, " ", "_"),
James Feist930fcde2019-05-28 12:58:43 -070069 std::move(thresholdData), sensorConfiguration,
Bruce Lee1263c3d2021-06-04 15:16:33 +080070 "xyz.openbmc_project.Configuration.ExitAirTemp", false,
71 ipmbMaxReading, ipmbMinReading, conn, PowerState::on),
Anoop S832a2c62020-11-20 19:21:22 +000072 deviceAddress(deviceAddress), hostSMbusIndex(hostSMbusIndex),
Jayashree-D9f6d4fd2021-04-13 18:27:22 +053073 sensorPollMs(static_cast<int>(pollRate * 1000)), objectServer(objectServer),
74 waitTimer(io)
James Feist6ef20402019-01-07 16:45:08 -080075{
Vijay Khemka682a5cb2019-07-18 17:34:03 -070076 std::string dbusPath = sensorPathPrefix + sensorTypeName + "/" + name;
77
James Feist6ef20402019-01-07 16:45:08 -080078 sensorInterface = objectServer.add_interface(
Vijay Khemka682a5cb2019-07-18 17:34:03 -070079 dbusPath, "xyz.openbmc_project.Sensor.Value");
James Feist6ef20402019-01-07 16:45:08 -080080
81 if (thresholds::hasWarningInterface(thresholds))
82 {
83 thresholdInterfaceWarning = objectServer.add_interface(
Vijay Khemka682a5cb2019-07-18 17:34:03 -070084 dbusPath, "xyz.openbmc_project.Sensor.Threshold.Warning");
James Feist6ef20402019-01-07 16:45:08 -080085 }
86 if (thresholds::hasCriticalInterface(thresholds))
87 {
88 thresholdInterfaceCritical = objectServer.add_interface(
Vijay Khemka682a5cb2019-07-18 17:34:03 -070089 dbusPath, "xyz.openbmc_project.Sensor.Threshold.Critical");
James Feist6ef20402019-01-07 16:45:08 -080090 }
James Feist2adc95c2019-09-30 14:55:28 -070091 association = objectServer.add_interface(dbusPath, association::interface);
James Feist6ef20402019-01-07 16:45:08 -080092}
93
94IpmbSensor::~IpmbSensor()
95{
96 waitTimer.cancel();
97 objectServer.remove_interface(thresholdInterfaceWarning);
98 objectServer.remove_interface(thresholdInterfaceCritical);
99 objectServer.remove_interface(sensorInterface);
James Feist078f2322019-03-08 11:09:05 -0800100 objectServer.remove_interface(association);
James Feist6ef20402019-01-07 16:45:08 -0800101}
102
Zev Weiss6b6891c2021-04-22 02:46:21 -0500103std::string IpmbSensor::getSubTypeUnits(void)
104{
105 switch (subType)
106 {
107 case IpmbSubType::temp:
108 return sensor_paths::unitDegreesC;
109 case IpmbSubType::curr:
110 return sensor_paths::unitAmperes;
111 case IpmbSubType::power:
112 return sensor_paths::unitWatts;
113 case IpmbSubType::volt:
114 return sensor_paths::unitVolts;
115 case IpmbSubType::util:
116 return sensor_paths::unitPercent;
117 default:
118 throw std::runtime_error("Invalid sensor type");
119 }
120}
121
James Feist6ef20402019-01-07 16:45:08 -0800122void IpmbSensor::init(void)
123{
James Feist6ef20402019-01-07 16:45:08 -0800124 loadDefaults();
Zev Weiss6b6891c2021-04-22 02:46:21 -0500125 setInitialProperties(dbusConnection, getSubTypeUnits());
James Feist6ef20402019-01-07 16:45:08 -0800126 if (initCommand)
127 {
James Feistf7e2c5d2019-02-13 17:27:51 -0800128 runInitCmd();
129 }
130 read();
131}
132
133void IpmbSensor::runInitCmd()
134{
135 if (initCommand)
136 {
James Feist6ef20402019-01-07 16:45:08 -0800137 dbusConnection->async_method_call(
138 [this](boost::system::error_code ec,
139 const IpmbMethodType& response) {
140 const int& status = std::get<0>(response);
141
142 if (ec || status)
143 {
144 std::cerr
145 << "Error setting init command for device: " << name
146 << "\n";
147 }
James Feist6ef20402019-01-07 16:45:08 -0800148 },
149 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
150 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
151 "sendRequest", commandAddress, netfn, lun, *initCommand, initData);
152 }
James Feist6ef20402019-01-07 16:45:08 -0800153}
154
155void IpmbSensor::loadDefaults()
156{
157 if (type == IpmbType::meSensor)
158 {
159 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200160 netfn = ipmi::sensor::netFn;
161 command = ipmi::sensor::getSensorReading;
James Feist6ef20402019-01-07 16:45:08 -0800162 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700163 readingFormat = ReadingFormat::byte0;
James Feist6ef20402019-01-07 16:45:08 -0800164 }
165 else if (type == IpmbType::PXE1410CVR)
166 {
167 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200168 netfn = ipmi::me_bridge::netFn;
169 command = ipmi::me_bridge::sendRawPmbus;
170 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700171 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000172 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
173 deviceAddress, 0x00, 0x00, 0x00, 0x00,
174 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700175 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000176 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
177 deviceAddress, 0x00, 0x00, 0x00, 0x00,
178 0x02, 0x00, 0x00, 0x00};
Jayashree-D37322572021-03-19 17:40:56 +0530179 readingFormat = ReadingFormat::linearElevenBit;
James Feist6ef20402019-01-07 16:45:08 -0800180 }
181 else if (type == IpmbType::IR38363VR)
182 {
183 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200184 netfn = ipmi::me_bridge::netFn;
185 command = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700186 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000187 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
188 deviceAddress, 00, 0x00, 0x00, 0x00,
189 0x01, 0x02, 0x8D};
James Feistd7ae29a2020-06-25 15:42:46 -0700190 readingFormat = ReadingFormat::elevenBitShift;
James Feist6ef20402019-01-07 16:45:08 -0800191 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700192 else if (type == IpmbType::ADM1278HSC)
193 {
194 commandAddress = meAddress;
195 switch (subType)
196 {
197 case IpmbSubType::temp:
198 case IpmbSubType::curr:
199 uint8_t snsNum;
200 if (subType == IpmbSubType::temp)
Ed Tanous8a57ec02020-10-09 12:46:52 -0700201 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700202 snsNum = 0x8d;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700203 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700204 else
Ed Tanous8a57ec02020-10-09 12:46:52 -0700205 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700206 snsNum = 0x8c;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700207 }
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200208 netfn = ipmi::me_bridge::netFn;
209 command = ipmi::me_bridge::sendRawPmbus;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700210 commandData = {0x57, 0x01, 0x00, 0x86, deviceAddress,
211 0x00, 0x00, 0x01, 0x02, snsNum};
James Feistd7ae29a2020-06-25 15:42:46 -0700212 readingFormat = ReadingFormat::elevenBit;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700213 break;
214 case IpmbSubType::power:
215 case IpmbSubType::volt:
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200216 netfn = ipmi::sensor::netFn;
217 command = ipmi::sensor::getSensorReading;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700218 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700219 readingFormat = ReadingFormat::byte0;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700220 break;
221 default:
222 throw std::runtime_error("Invalid sensor type");
223 }
224 }
James Feist6ef20402019-01-07 16:45:08 -0800225 else if (type == IpmbType::mpsVR)
226 {
227 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200228 netfn = ipmi::me_bridge::netFn;
229 command = ipmi::me_bridge::sendRawPmbus;
230 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700231 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000232 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
233 deviceAddress, 0x00, 0x00, 0x00, 0x00,
234 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700235 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000236 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
237 deviceAddress, 0x00, 0x00, 0x00, 0x00,
238 0x02, 0x00, 0x00, 0x00};
James Feistd7ae29a2020-06-25 15:42:46 -0700239 readingFormat = ReadingFormat::byte3;
James Feist6ef20402019-01-07 16:45:08 -0800240 }
241 else
242 {
243 throw std::runtime_error("Invalid sensor type");
244 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200245
246 if (subType == IpmbSubType::util)
247 {
248 // Utilization need to be scaled to percent
249 maxValue = 100;
250 minValue = 0;
251 }
James Feist6ef20402019-01-07 16:45:08 -0800252}
253
254void IpmbSensor::checkThresholds(void)
255{
James Feist6ef20402019-01-07 16:45:08 -0800256 thresholds::checkThresholds(this);
257}
258
James Feist961bf092020-07-01 16:38:12 -0700259bool IpmbSensor::processReading(const std::vector<uint8_t>& data, double& resp)
James Feistd7ae29a2020-06-25 15:42:46 -0700260{
261
262 switch (readingFormat)
263 {
264 case (ReadingFormat::byte0):
James Feiste4a970d2020-08-19 11:21:58 -0700265 {
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200266 if (command == ipmi::sensor::getSensorReading &&
267 !ipmi::sensor::isValid(data))
James Feistcf4238e2020-07-28 16:40:03 -0700268 {
269 return false;
270 }
James Feist961bf092020-07-01 16:38:12 -0700271 resp = data[0];
272 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700273 }
James Feistd7ae29a2020-06-25 15:42:46 -0700274 case (ReadingFormat::byte3):
James Feiste4a970d2020-08-19 11:21:58 -0700275 {
James Feistd7ae29a2020-06-25 15:42:46 -0700276 if (data.size() < 4)
277 {
James Feist961bf092020-07-01 16:38:12 -0700278 if (!errCount)
279 {
280 std::cerr << "Invalid data length returned for " << name
281 << "\n";
282 }
283 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700284 }
James Feist961bf092020-07-01 16:38:12 -0700285 resp = data[3];
286 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700287 }
James Feistd7ae29a2020-06-25 15:42:46 -0700288 case (ReadingFormat::elevenBit):
James Feiste4a970d2020-08-19 11:21:58 -0700289 {
James Feistd7ae29a2020-06-25 15:42:46 -0700290 if (data.size() < 5)
291 {
James Feist961bf092020-07-01 16:38:12 -0700292 if (!errCount)
293 {
294 std::cerr << "Invalid data length returned for " << name
295 << "\n";
296 }
297 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700298 }
299
James Feiste4a970d2020-08-19 11:21:58 -0700300 int16_t value = ((data[4] << 8) | data[3]);
James Feiste4a970d2020-08-19 11:21:58 -0700301 resp = value;
James Feist961bf092020-07-01 16:38:12 -0700302 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700303 }
James Feistd7ae29a2020-06-25 15:42:46 -0700304 case (ReadingFormat::elevenBitShift):
James Feiste4a970d2020-08-19 11:21:58 -0700305 {
James Feistd7ae29a2020-06-25 15:42:46 -0700306 if (data.size() < 5)
307 {
James Feist961bf092020-07-01 16:38:12 -0700308 if (!errCount)
309 {
310 std::cerr << "Invalid data length returned for " << name
311 << "\n";
312 }
313 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700314 }
315
James Feist961bf092020-07-01 16:38:12 -0700316 resp = ((data[4] << 8) | data[3]) >> 3;
317 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700318 }
Jayashree-D37322572021-03-19 17:40:56 +0530319 case (ReadingFormat::linearElevenBit):
320 {
321 if (data.size() < 5)
322 {
323 if (!errCount)
324 {
325 std::cerr << "Invalid data length returned for " << name
326 << "\n";
327 }
328 return false;
329 }
330
331 int16_t value = ((data[4] << 8) | data[3]);
332 constexpr const size_t shift = 16 - 11; // 11bit into 16bit
333 value <<= shift;
334 value >>= shift;
335 resp = value;
336 return true;
337 }
James Feistd7ae29a2020-06-25 15:42:46 -0700338 default:
339 throw std::runtime_error("Invalid reading type");
340 }
341}
342
James Feist6ef20402019-01-07 16:45:08 -0800343void IpmbSensor::read(void)
344{
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530345 waitTimer.expires_from_now(boost::posix_time::milliseconds(sensorPollMs));
James Feist6ef20402019-01-07 16:45:08 -0800346 waitTimer.async_wait([this](const boost::system::error_code& ec) {
347 if (ec == boost::asio::error::operation_aborted)
348 {
349 return; // we're being canceled
350 }
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200351 if (!readingStateGood())
James Feist6ef20402019-01-07 16:45:08 -0800352 {
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200353 updateValue(std::numeric_limits<double>::quiet_NaN());
James Feist6ef20402019-01-07 16:45:08 -0800354 read();
355 return;
356 }
357 dbusConnection->async_method_call(
358 [this](boost::system::error_code ec,
359 const IpmbMethodType& response) {
360 const int& status = std::get<0>(response);
361 if (ec || status)
362 {
James Feist961bf092020-07-01 16:38:12 -0700363 incrementError();
James Feist6ef20402019-01-07 16:45:08 -0800364 read();
365 return;
366 }
367 const std::vector<uint8_t>& data = std::get<5>(response);
368 if constexpr (debug)
369 {
370 std::cout << name << ": ";
371 for (size_t d : data)
372 {
373 std::cout << d << " ";
374 }
375 std::cout << "\n";
376 }
James Feistd7ae29a2020-06-25 15:42:46 -0700377 if (data.empty())
James Feist6ef20402019-01-07 16:45:08 -0800378 {
James Feist961bf092020-07-01 16:38:12 -0700379 incrementError();
James Feistd7ae29a2020-06-25 15:42:46 -0700380 read();
381 return;
James Feist6ef20402019-01-07 16:45:08 -0800382 }
James Feist961bf092020-07-01 16:38:12 -0700383
384 double value = 0;
385
386 if (!processReading(data, value))
387 {
388 incrementError();
389 read();
390 return;
391 }
Ed Tanous8a57ec02020-10-09 12:46:52 -0700392
393 // rawValue only used in debug logging
394 // up to 5th byte in data are used to derive value
395 size_t end = std::min(sizeof(uint64_t), data.size());
396 uint64_t rawData = 0;
397 for (size_t i = 0; i < end; i++)
Zhikui Rend3da1282020-09-11 17:02:01 -0700398 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700399 reinterpret_cast<uint8_t*>(&rawData)[i] = data[i];
Zhikui Rend3da1282020-09-11 17:02:01 -0700400 }
Ed Tanous8a57ec02020-10-09 12:46:52 -0700401 rawValue = static_cast<double>(rawData);
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700402
403 /* Adjust value as per scale and offset */
404 value = (value * scaleVal) + offsetVal;
James Feist6ef20402019-01-07 16:45:08 -0800405 updateValue(value);
406 read();
407 },
408 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
409 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
410 "sendRequest", commandAddress, netfn, lun, command, commandData);
411 });
412}
413void createSensors(
414 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
415 boost::container::flat_map<std::string, std::unique_ptr<IpmbSensor>>&
416 sensors,
417 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
418{
419 if (!dbusConnection)
420 {
421 std::cerr << "Connection not created\n";
422 return;
423 }
424 dbusConnection->async_method_call(
425 [&](boost::system::error_code ec, const ManagedObjectType& resp) {
426 if (ec)
427 {
428 std::cerr << "Error contacting entity manager\n";
429 return;
430 }
431 for (const auto& pathPair : resp)
432 {
433 for (const auto& entry : pathPair.second)
434 {
435 if (entry.first != configInterface)
436 {
437 continue;
438 }
439 std::string name =
440 loadVariant<std::string>(entry.second, "Name");
441
442 std::vector<thresholds::Threshold> sensorThresholds;
443 if (!parseThresholdsFromConfig(pathPair.second,
444 sensorThresholds))
445 {
446 std::cerr << "error populating thresholds for " << name
447 << "\n";
448 }
449 uint8_t deviceAddress =
450 loadVariant<uint8_t>(entry.second, "Address");
451
452 std::string sensorClass =
453 loadVariant<std::string>(entry.second, "Class");
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530454
Anoop S832a2c62020-11-20 19:21:22 +0000455 uint8_t hostSMbusIndex = hostSMbusIndexDefault;
456 auto findSmType = entry.second.find("HostSMbusIndex");
457 if (findSmType != entry.second.end())
458 {
459 hostSMbusIndex = std::visit(
460 VariantToUnsignedIntVisitor(), findSmType->second);
461 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700462
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530463 float pollRate = pollRateDefault;
464 auto findPollRate = entry.second.find("PollRate");
465 if (findPollRate != entry.second.end())
466 {
467 pollRate = std::visit(VariantToFloatVisitor(),
468 findPollRate->second);
469 if (pollRate <= 0.0f)
470 {
471 pollRate = pollRateDefault;
472 }
473 }
474
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700475 /* Default sensor type is "temperature" */
476 std::string sensorTypeName = "temperature";
477 auto findType = entry.second.find("SensorType");
478 if (findType != entry.second.end())
479 {
480 sensorTypeName = std::visit(VariantToStringVisitor(),
481 findType->second);
482 }
483
James Feist6ef20402019-01-07 16:45:08 -0800484 auto& sensor = sensors[name];
485 sensor = std::make_unique<IpmbSensor>(
486 dbusConnection, io, name, pathPair.first, objectServer,
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700487 std::move(sensorThresholds), deviceAddress,
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530488 hostSMbusIndex, pollRate, sensorTypeName);
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700489
490 /* Initialize scale and offset value */
491 sensor->scaleVal = 1;
492 sensor->offsetVal = 0;
493
494 auto findScaleVal = entry.second.find("ScaleValue");
495 if (findScaleVal != entry.second.end())
496 {
497 sensor->scaleVal = std::visit(VariantToDoubleVisitor(),
498 findScaleVal->second);
499 }
500
501 auto findOffsetVal = entry.second.find("OffsetValue");
502 if (findOffsetVal != entry.second.end())
503 {
504 sensor->offsetVal = std::visit(VariantToDoubleVisitor(),
505 findOffsetVal->second);
506 }
James Feist6ef20402019-01-07 16:45:08 -0800507
James Feistfc94b212019-02-06 16:14:51 -0800508 auto findPowerState = entry.second.find("PowerState");
509
510 if (findPowerState != entry.second.end())
511 {
512 std::string powerState = std::visit(
513 VariantToStringVisitor(), findPowerState->second);
514
515 setReadState(powerState, sensor->readState);
516 }
517
James Feist6ef20402019-01-07 16:45:08 -0800518 if (sensorClass == "PxeBridgeTemp")
519 {
520 sensor->type = IpmbType::PXE1410CVR;
521 }
522 else if (sensorClass == "IRBridgeTemp")
523 {
524 sensor->type = IpmbType::IR38363VR;
525 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700526 else if (sensorClass == "HSCBridge")
527 {
528 sensor->type = IpmbType::ADM1278HSC;
529 }
James Feist6ef20402019-01-07 16:45:08 -0800530 else if (sensorClass == "MpsBridgeTemp")
531 {
532 sensor->type = IpmbType::mpsVR;
533 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200534 else if (sensorClass == "METemp" ||
535 sensorClass == "MESensor")
James Feist6ef20402019-01-07 16:45:08 -0800536 {
537 sensor->type = IpmbType::meSensor;
538 }
539 else
540 {
541 std::cerr << "Invalid class " << sensorClass << "\n";
542 continue;
543 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700544
545 if (sensorTypeName == "voltage")
546 {
547 sensor->subType = IpmbSubType::volt;
548 }
549 else if (sensorTypeName == "power")
550 {
551 sensor->subType = IpmbSubType::power;
552 }
553 else if (sensorTypeName == "current")
554 {
555 sensor->subType = IpmbSubType::curr;
556 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200557 else if (sensorTypeName == "utilization")
558 {
559 sensor->subType = IpmbSubType::util;
560 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700561 else
562 {
563 sensor->subType = IpmbSubType::temp;
564 }
James Feist6ef20402019-01-07 16:45:08 -0800565 sensor->init();
566 }
567 }
568 },
569 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
570 "GetManagedObjects");
571}
572
James Feistf7e2c5d2019-02-13 17:27:51 -0800573void reinitSensors(sdbusplus::message::message& message)
574{
James Feist0d4f2bd2019-03-05 13:15:40 -0800575 constexpr const size_t reinitWaitSeconds = 2;
James Feistf7e2c5d2019-02-13 17:27:51 -0800576 std::string objectName;
James Feist52497fd2019-06-07 13:01:33 -0700577 boost::container::flat_map<std::string, std::variant<std::string>> values;
James Feistf7e2c5d2019-02-13 17:27:51 -0800578 message.read(objectName, values);
James Feist0d4f2bd2019-03-05 13:15:40 -0800579
James Feist52497fd2019-06-07 13:01:33 -0700580 auto findStatus = values.find(power::property);
581 if (findStatus != values.end())
James Feistf7e2c5d2019-02-13 17:27:51 -0800582 {
James Feist52497fd2019-06-07 13:01:33 -0700583 bool powerStatus = boost::ends_with(
Thu Ba Nguyen585d3a02021-07-20 20:25:15 +0700584 std::get<std::string>(findStatus->second), ".Running");
James Feistf7e2c5d2019-02-13 17:27:51 -0800585 if (powerStatus)
586 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800587 if (!initCmdTimer)
James Feistf7e2c5d2019-02-13 17:27:51 -0800588 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800589 // this should be impossible
590 return;
James Feistf7e2c5d2019-02-13 17:27:51 -0800591 }
James Feist0d4f2bd2019-03-05 13:15:40 -0800592 // we seem to send this command too fast sometimes, wait before
593 // sending
594 initCmdTimer->expires_from_now(
595 boost::posix_time::seconds(reinitWaitSeconds));
596
597 initCmdTimer->async_wait([](const boost::system::error_code ec) {
598 if (ec == boost::asio::error::operation_aborted)
599 {
600 return; // we're being canceled
601 }
602
603 for (const auto& sensor : sensors)
604 {
605 if (sensor.second)
606 {
607 sensor.second->runInitCmd();
608 }
609 }
610 });
James Feistf7e2c5d2019-02-13 17:27:51 -0800611 }
612 }
613}
614
James Feistb6c0b912019-07-09 12:21:44 -0700615int main()
James Feist6ef20402019-01-07 16:45:08 -0800616{
617
618 boost::asio::io_service io;
619 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
620 systemBus->request_name("xyz.openbmc_project.IpmbSensor");
621 sdbusplus::asio::object_server objectServer(systemBus);
James Feist6ef20402019-01-07 16:45:08 -0800622
James Feist0d4f2bd2019-03-05 13:15:40 -0800623 initCmdTimer = std::make_unique<boost::asio::deadline_timer>(io);
624
James Feist6ef20402019-01-07 16:45:08 -0800625 io.post([&]() { createSensors(io, objectServer, sensors, systemBus); });
626
627 boost::asio::deadline_timer configTimer(io);
628
629 std::function<void(sdbusplus::message::message&)> eventHandler =
James Feistb6c0b912019-07-09 12:21:44 -0700630 [&](sdbusplus::message::message&) {
James Feist6ef20402019-01-07 16:45:08 -0800631 configTimer.expires_from_now(boost::posix_time::seconds(1));
632 // create a timer because normally multiple properties change
633 configTimer.async_wait([&](const boost::system::error_code& ec) {
634 if (ec == boost::asio::error::operation_aborted)
635 {
636 return; // we're being canceled
637 }
638 createSensors(io, objectServer, sensors, systemBus);
639 if (sensors.empty())
640 {
641 std::cout << "Configuration not detected\n";
642 }
643 });
644 };
645
James Feistf7e2c5d2019-02-13 17:27:51 -0800646 sdbusplus::bus::match::match configMatch(
James Feist6ef20402019-01-07 16:45:08 -0800647 static_cast<sdbusplus::bus::bus&>(*systemBus),
648 "type='signal',member='PropertiesChanged',path_namespace='" +
649 std::string(inventoryPath) + "',arg0namespace='" + configInterface +
650 "'",
651 eventHandler);
652
James Feistf7e2c5d2019-02-13 17:27:51 -0800653 sdbusplus::bus::match::match powerChangeMatch(
654 static_cast<sdbusplus::bus::bus&>(*systemBus),
James Feist52497fd2019-06-07 13:01:33 -0700655 "type='signal',interface='" + std::string(properties::interface) +
656 "',path='" + std::string(power::path) + "',arg0='" +
657 std::string(power::interface) + "'",
James Feistf7e2c5d2019-02-13 17:27:51 -0800658 reinitSensors);
659
Bruce Lee1263c3d2021-06-04 15:16:33 +0800660 setupManufacturingModeMatch(*systemBus);
James Feist6ef20402019-01-07 16:45:08 -0800661 io.run();
Zhikui Rene76a5a62021-07-09 15:16:32 -0700662 return 0;
James Feist6ef20402019-01-07 16:45:08 -0800663}