blob: eedf21ecc2e5d244bc3823cb814fe6705c21f846 [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>
Patrick Venture96e97db2019-10-31 13:44:38 -070021#include <boost/container/flat_map.hpp>
James Feist38fb5982020-05-28 10:09:54 -070022#include <sdbusplus/asio/connection.hpp>
23#include <sdbusplus/asio/object_server.hpp>
24#include <sdbusplus/bus/match.hpp>
25
James Feist6ef20402019-01-07 16:45:08 -080026#include <chrono>
Ed Tanous8a57ec02020-10-09 12:46:52 -070027#include <cmath>
Patrick Venture96e97db2019-10-31 13:44:38 -070028#include <functional>
James Feist6ef20402019-01-07 16:45:08 -080029#include <iostream>
30#include <limits>
Patrick Venture96e97db2019-10-31 13:44:38 -070031#include <memory>
James Feist6ef20402019-01-07 16:45:08 -080032#include <numeric>
Patrick Venture96e97db2019-10-31 13:44:38 -070033#include <string>
34#include <tuple>
35#include <variant>
James Feist6ef20402019-01-07 16:45:08 -080036#include <vector>
37
38constexpr const bool debug = false;
39
40constexpr const char* configInterface =
41 "xyz.openbmc_project.Configuration.IpmbSensor";
42static constexpr double ipmbMaxReading = 0xFF;
43static constexpr double ipmbMinReading = 0;
44
45static constexpr uint8_t meAddress = 1;
46static constexpr uint8_t lun = 0;
Anoop S832a2c62020-11-20 19:21:22 +000047static constexpr uint8_t hostSMbusIndexDefault = 0x03;
Jayashree-D9f6d4fd2021-04-13 18:27:22 +053048static constexpr float pollRateDefault = 1; // in seconds
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,
Jayashree-D9f6d4fd2021-04-13 18:27:22 +053066 const float pollRate, std::string& sensorTypeName) :
Zhikui Renda98f092021-11-01 09:41:08 -070067 Sensor(escapeName(sensorName), std::move(thresholdData),
68 sensorConfiguration, "xyz.openbmc_project.Configuration.ExitAirTemp",
69 false, false, ipmbMaxReading, ipmbMinReading, conn, PowerState::on),
Anoop S832a2c62020-11-20 19:21:22 +000070 deviceAddress(deviceAddress), hostSMbusIndex(hostSMbusIndex),
Jayashree-D9f6d4fd2021-04-13 18:27:22 +053071 sensorPollMs(static_cast<int>(pollRate * 1000)), objectServer(objectServer),
72 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
Zev Weiss6b6891c2021-04-22 02:46:21 -0500101std::string IpmbSensor::getSubTypeUnits(void)
102{
103 switch (subType)
104 {
105 case IpmbSubType::temp:
106 return sensor_paths::unitDegreesC;
107 case IpmbSubType::curr:
108 return sensor_paths::unitAmperes;
109 case IpmbSubType::power:
110 return sensor_paths::unitWatts;
111 case IpmbSubType::volt:
112 return sensor_paths::unitVolts;
113 case IpmbSubType::util:
114 return sensor_paths::unitPercent;
115 default:
116 throw std::runtime_error("Invalid sensor type");
117 }
118}
119
James Feist6ef20402019-01-07 16:45:08 -0800120void IpmbSensor::init(void)
121{
James Feist6ef20402019-01-07 16:45:08 -0800122 loadDefaults();
Zev Weiss6b6891c2021-04-22 02:46:21 -0500123 setInitialProperties(dbusConnection, getSubTypeUnits());
James Feist6ef20402019-01-07 16:45:08 -0800124 if (initCommand)
125 {
James Feistf7e2c5d2019-02-13 17:27:51 -0800126 runInitCmd();
127 }
128 read();
129}
130
131void IpmbSensor::runInitCmd()
132{
133 if (initCommand)
134 {
James Feist6ef20402019-01-07 16:45:08 -0800135 dbusConnection->async_method_call(
136 [this](boost::system::error_code ec,
137 const IpmbMethodType& response) {
138 const int& status = std::get<0>(response);
139
140 if (ec || status)
141 {
142 std::cerr
143 << "Error setting init command for device: " << name
144 << "\n";
145 }
James Feist6ef20402019-01-07 16:45:08 -0800146 },
147 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
148 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
149 "sendRequest", commandAddress, netfn, lun, *initCommand, initData);
150 }
James Feist6ef20402019-01-07 16:45:08 -0800151}
152
153void IpmbSensor::loadDefaults()
154{
155 if (type == IpmbType::meSensor)
156 {
157 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200158 netfn = ipmi::sensor::netFn;
159 command = ipmi::sensor::getSensorReading;
James Feist6ef20402019-01-07 16:45:08 -0800160 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700161 readingFormat = ReadingFormat::byte0;
James Feist6ef20402019-01-07 16:45:08 -0800162 }
163 else if (type == IpmbType::PXE1410CVR)
164 {
165 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200166 netfn = ipmi::me_bridge::netFn;
167 command = ipmi::me_bridge::sendRawPmbus;
168 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700169 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000170 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
171 deviceAddress, 0x00, 0x00, 0x00, 0x00,
172 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700173 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000174 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
175 deviceAddress, 0x00, 0x00, 0x00, 0x00,
176 0x02, 0x00, 0x00, 0x00};
Jayashree-D37322572021-03-19 17:40:56 +0530177 readingFormat = ReadingFormat::linearElevenBit;
James Feist6ef20402019-01-07 16:45:08 -0800178 }
179 else if (type == IpmbType::IR38363VR)
180 {
181 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200182 netfn = ipmi::me_bridge::netFn;
183 command = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700184 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000185 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
186 deviceAddress, 00, 0x00, 0x00, 0x00,
187 0x01, 0x02, 0x8D};
James Feistd7ae29a2020-06-25 15:42:46 -0700188 readingFormat = ReadingFormat::elevenBitShift;
James Feist6ef20402019-01-07 16:45:08 -0800189 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700190 else if (type == IpmbType::ADM1278HSC)
191 {
192 commandAddress = meAddress;
193 switch (subType)
194 {
195 case IpmbSubType::temp:
196 case IpmbSubType::curr:
197 uint8_t snsNum;
198 if (subType == IpmbSubType::temp)
Ed Tanous8a57ec02020-10-09 12:46:52 -0700199 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700200 snsNum = 0x8d;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700201 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700202 else
Ed Tanous8a57ec02020-10-09 12:46:52 -0700203 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700204 snsNum = 0x8c;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700205 }
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200206 netfn = ipmi::me_bridge::netFn;
207 command = ipmi::me_bridge::sendRawPmbus;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700208 commandData = {0x57, 0x01, 0x00, 0x86, deviceAddress,
209 0x00, 0x00, 0x01, 0x02, snsNum};
James Feistd7ae29a2020-06-25 15:42:46 -0700210 readingFormat = ReadingFormat::elevenBit;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700211 break;
212 case IpmbSubType::power:
213 case IpmbSubType::volt:
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200214 netfn = ipmi::sensor::netFn;
215 command = ipmi::sensor::getSensorReading;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700216 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700217 readingFormat = ReadingFormat::byte0;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700218 break;
219 default:
220 throw std::runtime_error("Invalid sensor type");
221 }
222 }
James Feist6ef20402019-01-07 16:45:08 -0800223 else if (type == IpmbType::mpsVR)
224 {
225 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200226 netfn = ipmi::me_bridge::netFn;
227 command = ipmi::me_bridge::sendRawPmbus;
228 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700229 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000230 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
231 deviceAddress, 0x00, 0x00, 0x00, 0x00,
232 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700233 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000234 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
235 deviceAddress, 0x00, 0x00, 0x00, 0x00,
236 0x02, 0x00, 0x00, 0x00};
James Feistd7ae29a2020-06-25 15:42:46 -0700237 readingFormat = ReadingFormat::byte3;
James Feist6ef20402019-01-07 16:45:08 -0800238 }
239 else
240 {
241 throw std::runtime_error("Invalid sensor type");
242 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200243
244 if (subType == IpmbSubType::util)
245 {
246 // Utilization need to be scaled to percent
247 maxValue = 100;
248 minValue = 0;
249 }
James Feist6ef20402019-01-07 16:45:08 -0800250}
251
252void IpmbSensor::checkThresholds(void)
253{
James Feist6ef20402019-01-07 16:45:08 -0800254 thresholds::checkThresholds(this);
255}
256
James Feist961bf092020-07-01 16:38:12 -0700257bool IpmbSensor::processReading(const std::vector<uint8_t>& data, double& resp)
James Feistd7ae29a2020-06-25 15:42:46 -0700258{
259
260 switch (readingFormat)
261 {
262 case (ReadingFormat::byte0):
James Feiste4a970d2020-08-19 11:21:58 -0700263 {
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200264 if (command == ipmi::sensor::getSensorReading &&
265 !ipmi::sensor::isValid(data))
James Feistcf4238e2020-07-28 16:40:03 -0700266 {
267 return false;
268 }
James Feist961bf092020-07-01 16:38:12 -0700269 resp = data[0];
270 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700271 }
James Feistd7ae29a2020-06-25 15:42:46 -0700272 case (ReadingFormat::byte3):
James Feiste4a970d2020-08-19 11:21:58 -0700273 {
James Feistd7ae29a2020-06-25 15:42:46 -0700274 if (data.size() < 4)
275 {
James Feist961bf092020-07-01 16:38:12 -0700276 if (!errCount)
277 {
278 std::cerr << "Invalid data length returned for " << name
279 << "\n";
280 }
281 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700282 }
James Feist961bf092020-07-01 16:38:12 -0700283 resp = data[3];
284 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700285 }
James Feistd7ae29a2020-06-25 15:42:46 -0700286 case (ReadingFormat::elevenBit):
James Feiste4a970d2020-08-19 11:21:58 -0700287 {
James Feistd7ae29a2020-06-25 15:42:46 -0700288 if (data.size() < 5)
289 {
James Feist961bf092020-07-01 16:38:12 -0700290 if (!errCount)
291 {
292 std::cerr << "Invalid data length returned for " << name
293 << "\n";
294 }
295 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700296 }
297
James Feiste4a970d2020-08-19 11:21:58 -0700298 int16_t value = ((data[4] << 8) | data[3]);
James Feiste4a970d2020-08-19 11:21:58 -0700299 resp = value;
James Feist961bf092020-07-01 16:38:12 -0700300 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700301 }
James Feistd7ae29a2020-06-25 15:42:46 -0700302 case (ReadingFormat::elevenBitShift):
James Feiste4a970d2020-08-19 11:21:58 -0700303 {
James Feistd7ae29a2020-06-25 15:42:46 -0700304 if (data.size() < 5)
305 {
James Feist961bf092020-07-01 16:38:12 -0700306 if (!errCount)
307 {
308 std::cerr << "Invalid data length returned for " << name
309 << "\n";
310 }
311 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700312 }
313
James Feist961bf092020-07-01 16:38:12 -0700314 resp = ((data[4] << 8) | data[3]) >> 3;
315 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700316 }
Jayashree-D37322572021-03-19 17:40:56 +0530317 case (ReadingFormat::linearElevenBit):
318 {
319 if (data.size() < 5)
320 {
321 if (!errCount)
322 {
323 std::cerr << "Invalid data length returned for " << name
324 << "\n";
325 }
326 return false;
327 }
328
329 int16_t value = ((data[4] << 8) | data[3]);
330 constexpr const size_t shift = 16 - 11; // 11bit into 16bit
331 value <<= shift;
332 value >>= shift;
333 resp = value;
334 return true;
335 }
James Feistd7ae29a2020-06-25 15:42:46 -0700336 default:
337 throw std::runtime_error("Invalid reading type");
338 }
339}
340
James Feist6ef20402019-01-07 16:45:08 -0800341void IpmbSensor::read(void)
342{
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530343 waitTimer.expires_from_now(boost::posix_time::milliseconds(sensorPollMs));
James Feist6ef20402019-01-07 16:45:08 -0800344 waitTimer.async_wait([this](const boost::system::error_code& ec) {
345 if (ec == boost::asio::error::operation_aborted)
346 {
347 return; // we're being canceled
348 }
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200349 if (!readingStateGood())
James Feist6ef20402019-01-07 16:45:08 -0800350 {
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200351 updateValue(std::numeric_limits<double>::quiet_NaN());
James Feist6ef20402019-01-07 16:45:08 -0800352 read();
353 return;
354 }
355 dbusConnection->async_method_call(
356 [this](boost::system::error_code ec,
357 const IpmbMethodType& response) {
358 const int& status = std::get<0>(response);
359 if (ec || status)
360 {
James Feist961bf092020-07-01 16:38:12 -0700361 incrementError();
James Feist6ef20402019-01-07 16:45:08 -0800362 read();
363 return;
364 }
365 const std::vector<uint8_t>& data = std::get<5>(response);
366 if constexpr (debug)
367 {
368 std::cout << name << ": ";
369 for (size_t d : data)
370 {
371 std::cout << d << " ";
372 }
373 std::cout << "\n";
374 }
James Feistd7ae29a2020-06-25 15:42:46 -0700375 if (data.empty())
James Feist6ef20402019-01-07 16:45:08 -0800376 {
James Feist961bf092020-07-01 16:38:12 -0700377 incrementError();
James Feistd7ae29a2020-06-25 15:42:46 -0700378 read();
379 return;
James Feist6ef20402019-01-07 16:45:08 -0800380 }
James Feist961bf092020-07-01 16:38:12 -0700381
382 double value = 0;
383
384 if (!processReading(data, value))
385 {
386 incrementError();
387 read();
388 return;
389 }
Ed Tanous8a57ec02020-10-09 12:46:52 -0700390
391 // rawValue only used in debug logging
392 // up to 5th byte in data are used to derive value
393 size_t end = std::min(sizeof(uint64_t), data.size());
394 uint64_t rawData = 0;
395 for (size_t i = 0; i < end; i++)
Zhikui Rend3da1282020-09-11 17:02:01 -0700396 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700397 reinterpret_cast<uint8_t*>(&rawData)[i] = data[i];
Zhikui Rend3da1282020-09-11 17:02:01 -0700398 }
Ed Tanous8a57ec02020-10-09 12:46:52 -0700399 rawValue = static_cast<double>(rawData);
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700400
401 /* Adjust value as per scale and offset */
402 value = (value * scaleVal) + offsetVal;
James Feist6ef20402019-01-07 16:45:08 -0800403 updateValue(value);
404 read();
405 },
406 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
407 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
408 "sendRequest", commandAddress, netfn, lun, command, commandData);
409 });
410}
411void createSensors(
412 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
413 boost::container::flat_map<std::string, std::unique_ptr<IpmbSensor>>&
414 sensors,
415 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
416{
417 if (!dbusConnection)
418 {
419 std::cerr << "Connection not created\n";
420 return;
421 }
422 dbusConnection->async_method_call(
423 [&](boost::system::error_code ec, const ManagedObjectType& resp) {
424 if (ec)
425 {
426 std::cerr << "Error contacting entity manager\n";
427 return;
428 }
429 for (const auto& pathPair : resp)
430 {
431 for (const auto& entry : pathPair.second)
432 {
433 if (entry.first != configInterface)
434 {
435 continue;
436 }
437 std::string name =
438 loadVariant<std::string>(entry.second, "Name");
439
440 std::vector<thresholds::Threshold> sensorThresholds;
441 if (!parseThresholdsFromConfig(pathPair.second,
442 sensorThresholds))
443 {
444 std::cerr << "error populating thresholds for " << name
445 << "\n";
446 }
447 uint8_t deviceAddress =
448 loadVariant<uint8_t>(entry.second, "Address");
449
450 std::string sensorClass =
451 loadVariant<std::string>(entry.second, "Class");
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530452
Anoop S832a2c62020-11-20 19:21:22 +0000453 uint8_t hostSMbusIndex = hostSMbusIndexDefault;
454 auto findSmType = entry.second.find("HostSMbusIndex");
455 if (findSmType != entry.second.end())
456 {
457 hostSMbusIndex = std::visit(
458 VariantToUnsignedIntVisitor(), findSmType->second);
459 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700460
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530461 float pollRate = pollRateDefault;
462 auto findPollRate = entry.second.find("PollRate");
463 if (findPollRate != entry.second.end())
464 {
465 pollRate = std::visit(VariantToFloatVisitor(),
466 findPollRate->second);
467 if (pollRate <= 0.0f)
468 {
469 pollRate = pollRateDefault;
470 }
471 }
472
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700473 /* Default sensor type is "temperature" */
474 std::string sensorTypeName = "temperature";
475 auto findType = entry.second.find("SensorType");
476 if (findType != entry.second.end())
477 {
478 sensorTypeName = std::visit(VariantToStringVisitor(),
479 findType->second);
480 }
481
James Feist6ef20402019-01-07 16:45:08 -0800482 auto& sensor = sensors[name];
483 sensor = std::make_unique<IpmbSensor>(
484 dbusConnection, io, name, pathPair.first, objectServer,
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700485 std::move(sensorThresholds), deviceAddress,
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530486 hostSMbusIndex, pollRate, sensorTypeName);
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700487
488 /* Initialize scale and offset value */
489 sensor->scaleVal = 1;
490 sensor->offsetVal = 0;
491
492 auto findScaleVal = entry.second.find("ScaleValue");
493 if (findScaleVal != entry.second.end())
494 {
495 sensor->scaleVal = std::visit(VariantToDoubleVisitor(),
496 findScaleVal->second);
497 }
498
499 auto findOffsetVal = entry.second.find("OffsetValue");
500 if (findOffsetVal != entry.second.end())
501 {
502 sensor->offsetVal = std::visit(VariantToDoubleVisitor(),
503 findOffsetVal->second);
504 }
James Feist6ef20402019-01-07 16:45:08 -0800505
James Feistfc94b212019-02-06 16:14:51 -0800506 auto findPowerState = entry.second.find("PowerState");
507
508 if (findPowerState != entry.second.end())
509 {
510 std::string powerState = std::visit(
511 VariantToStringVisitor(), findPowerState->second);
512
513 setReadState(powerState, sensor->readState);
514 }
515
James Feist6ef20402019-01-07 16:45:08 -0800516 if (sensorClass == "PxeBridgeTemp")
517 {
518 sensor->type = IpmbType::PXE1410CVR;
519 }
520 else if (sensorClass == "IRBridgeTemp")
521 {
522 sensor->type = IpmbType::IR38363VR;
523 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700524 else if (sensorClass == "HSCBridge")
525 {
526 sensor->type = IpmbType::ADM1278HSC;
527 }
James Feist6ef20402019-01-07 16:45:08 -0800528 else if (sensorClass == "MpsBridgeTemp")
529 {
530 sensor->type = IpmbType::mpsVR;
531 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200532 else if (sensorClass == "METemp" ||
533 sensorClass == "MESensor")
James Feist6ef20402019-01-07 16:45:08 -0800534 {
535 sensor->type = IpmbType::meSensor;
536 }
537 else
538 {
539 std::cerr << "Invalid class " << sensorClass << "\n";
540 continue;
541 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700542
543 if (sensorTypeName == "voltage")
544 {
545 sensor->subType = IpmbSubType::volt;
546 }
547 else if (sensorTypeName == "power")
548 {
549 sensor->subType = IpmbSubType::power;
550 }
551 else if (sensorTypeName == "current")
552 {
553 sensor->subType = IpmbSubType::curr;
554 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200555 else if (sensorTypeName == "utilization")
556 {
557 sensor->subType = IpmbSubType::util;
558 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700559 else
560 {
561 sensor->subType = IpmbSubType::temp;
562 }
James Feist6ef20402019-01-07 16:45:08 -0800563 sensor->init();
564 }
565 }
566 },
567 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
568 "GetManagedObjects");
569}
570
James Feistf7e2c5d2019-02-13 17:27:51 -0800571void reinitSensors(sdbusplus::message::message& message)
572{
James Feist0d4f2bd2019-03-05 13:15:40 -0800573 constexpr const size_t reinitWaitSeconds = 2;
James Feistf7e2c5d2019-02-13 17:27:51 -0800574 std::string objectName;
James Feist52497fd2019-06-07 13:01:33 -0700575 boost::container::flat_map<std::string, std::variant<std::string>> values;
James Feistf7e2c5d2019-02-13 17:27:51 -0800576 message.read(objectName, values);
James Feist0d4f2bd2019-03-05 13:15:40 -0800577
James Feist52497fd2019-06-07 13:01:33 -0700578 auto findStatus = values.find(power::property);
579 if (findStatus != values.end())
James Feistf7e2c5d2019-02-13 17:27:51 -0800580 {
James Feist52497fd2019-06-07 13:01:33 -0700581 bool powerStatus = boost::ends_with(
Thu Ba Nguyen585d3a02021-07-20 20:25:15 +0700582 std::get<std::string>(findStatus->second), ".Running");
James Feistf7e2c5d2019-02-13 17:27:51 -0800583 if (powerStatus)
584 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800585 if (!initCmdTimer)
James Feistf7e2c5d2019-02-13 17:27:51 -0800586 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800587 // this should be impossible
588 return;
James Feistf7e2c5d2019-02-13 17:27:51 -0800589 }
James Feist0d4f2bd2019-03-05 13:15:40 -0800590 // we seem to send this command too fast sometimes, wait before
591 // sending
592 initCmdTimer->expires_from_now(
593 boost::posix_time::seconds(reinitWaitSeconds));
594
595 initCmdTimer->async_wait([](const boost::system::error_code ec) {
596 if (ec == boost::asio::error::operation_aborted)
597 {
598 return; // we're being canceled
599 }
600
601 for (const auto& sensor : sensors)
602 {
603 if (sensor.second)
604 {
605 sensor.second->runInitCmd();
606 }
607 }
608 });
James Feistf7e2c5d2019-02-13 17:27:51 -0800609 }
610 }
611}
612
James Feistb6c0b912019-07-09 12:21:44 -0700613int main()
James Feist6ef20402019-01-07 16:45:08 -0800614{
615
616 boost::asio::io_service io;
617 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
618 systemBus->request_name("xyz.openbmc_project.IpmbSensor");
619 sdbusplus::asio::object_server objectServer(systemBus);
James Feist6ef20402019-01-07 16:45:08 -0800620
James Feist0d4f2bd2019-03-05 13:15:40 -0800621 initCmdTimer = std::make_unique<boost::asio::deadline_timer>(io);
622
James Feist6ef20402019-01-07 16:45:08 -0800623 io.post([&]() { createSensors(io, objectServer, sensors, systemBus); });
624
625 boost::asio::deadline_timer configTimer(io);
626
627 std::function<void(sdbusplus::message::message&)> eventHandler =
James Feistb6c0b912019-07-09 12:21:44 -0700628 [&](sdbusplus::message::message&) {
James Feist6ef20402019-01-07 16:45:08 -0800629 configTimer.expires_from_now(boost::posix_time::seconds(1));
630 // create a timer because normally multiple properties change
631 configTimer.async_wait([&](const boost::system::error_code& ec) {
632 if (ec == boost::asio::error::operation_aborted)
633 {
634 return; // we're being canceled
635 }
636 createSensors(io, objectServer, sensors, systemBus);
637 if (sensors.empty())
638 {
639 std::cout << "Configuration not detected\n";
640 }
641 });
642 };
643
James Feistf7e2c5d2019-02-13 17:27:51 -0800644 sdbusplus::bus::match::match configMatch(
James Feist6ef20402019-01-07 16:45:08 -0800645 static_cast<sdbusplus::bus::bus&>(*systemBus),
646 "type='signal',member='PropertiesChanged',path_namespace='" +
647 std::string(inventoryPath) + "',arg0namespace='" + configInterface +
648 "'",
649 eventHandler);
650
James Feistf7e2c5d2019-02-13 17:27:51 -0800651 sdbusplus::bus::match::match powerChangeMatch(
652 static_cast<sdbusplus::bus::bus&>(*systemBus),
James Feist52497fd2019-06-07 13:01:33 -0700653 "type='signal',interface='" + std::string(properties::interface) +
654 "',path='" + std::string(power::path) + "',arg0='" +
655 std::string(power::interface) + "'",
James Feistf7e2c5d2019-02-13 17:27:51 -0800656 reinitSensors);
657
Bruce Lee1263c3d2021-06-04 15:16:33 +0800658 setupManufacturingModeMatch(*systemBus);
James Feist6ef20402019-01-07 16:45:08 -0800659 io.run();
Zhikui Rene76a5a62021-07-09 15:16:32 -0700660 return 0;
James Feist6ef20402019-01-07 16:45:08 -0800661}