blob: 0615c86d25a270d0e59f4eb49f9739690e0654f9 [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
Jayashree Dhanapal56678082022-01-04 17:27:20 +053079 for (const auto& threshold : thresholds)
James Feist6ef20402019-01-07 16:45:08 -080080 {
Jayashree Dhanapal56678082022-01-04 17:27:20 +053081 std::string interface = thresholds::getInterface(threshold.level);
82 thresholdInterfaces[static_cast<size_t>(threshold.level)] =
83 objectServer.add_interface(dbusPath, interface);
James Feist6ef20402019-01-07 16:45:08 -080084 }
James Feist2adc95c2019-09-30 14:55:28 -070085 association = objectServer.add_interface(dbusPath, association::interface);
James Feist6ef20402019-01-07 16:45:08 -080086}
87
88IpmbSensor::~IpmbSensor()
89{
90 waitTimer.cancel();
Jayashree Dhanapal56678082022-01-04 17:27:20 +053091 for (const auto& iface : thresholdInterfaces)
92 {
93 objectServer.remove_interface(iface);
94 }
James Feist6ef20402019-01-07 16:45:08 -080095 objectServer.remove_interface(sensorInterface);
James Feist078f2322019-03-08 11:09:05 -080096 objectServer.remove_interface(association);
James Feist6ef20402019-01-07 16:45:08 -080097}
98
Zev Weiss6b6891c2021-04-22 02:46:21 -050099std::string IpmbSensor::getSubTypeUnits(void)
100{
101 switch (subType)
102 {
103 case IpmbSubType::temp:
104 return sensor_paths::unitDegreesC;
105 case IpmbSubType::curr:
106 return sensor_paths::unitAmperes;
107 case IpmbSubType::power:
108 return sensor_paths::unitWatts;
109 case IpmbSubType::volt:
110 return sensor_paths::unitVolts;
111 case IpmbSubType::util:
112 return sensor_paths::unitPercent;
113 default:
114 throw std::runtime_error("Invalid sensor type");
115 }
116}
117
James Feist6ef20402019-01-07 16:45:08 -0800118void IpmbSensor::init(void)
119{
James Feist6ef20402019-01-07 16:45:08 -0800120 loadDefaults();
Andrei Kartashev39287412022-02-04 16:04:47 +0300121 setInitialProperties(getSubTypeUnits());
James Feist6ef20402019-01-07 16:45:08 -0800122 if (initCommand)
123 {
James Feistf7e2c5d2019-02-13 17:27:51 -0800124 runInitCmd();
125 }
126 read();
127}
128
129void IpmbSensor::runInitCmd()
130{
131 if (initCommand)
132 {
James Feist6ef20402019-01-07 16:45:08 -0800133 dbusConnection->async_method_call(
134 [this](boost::system::error_code ec,
135 const IpmbMethodType& response) {
136 const int& status = std::get<0>(response);
137
138 if (ec || status)
139 {
140 std::cerr
141 << "Error setting init command for device: " << name
142 << "\n";
143 }
James Feist6ef20402019-01-07 16:45:08 -0800144 },
145 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
146 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
147 "sendRequest", commandAddress, netfn, lun, *initCommand, initData);
148 }
James Feist6ef20402019-01-07 16:45:08 -0800149}
150
151void IpmbSensor::loadDefaults()
152{
153 if (type == IpmbType::meSensor)
154 {
155 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200156 netfn = ipmi::sensor::netFn;
157 command = ipmi::sensor::getSensorReading;
James Feist6ef20402019-01-07 16:45:08 -0800158 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700159 readingFormat = ReadingFormat::byte0;
James Feist6ef20402019-01-07 16:45:08 -0800160 }
161 else if (type == IpmbType::PXE1410CVR)
162 {
163 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200164 netfn = ipmi::me_bridge::netFn;
165 command = ipmi::me_bridge::sendRawPmbus;
166 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700167 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000168 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
169 deviceAddress, 0x00, 0x00, 0x00, 0x00,
170 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700171 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000172 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
173 deviceAddress, 0x00, 0x00, 0x00, 0x00,
174 0x02, 0x00, 0x00, 0x00};
Jayashree-D37322572021-03-19 17:40:56 +0530175 readingFormat = ReadingFormat::linearElevenBit;
James Feist6ef20402019-01-07 16:45:08 -0800176 }
177 else if (type == IpmbType::IR38363VR)
178 {
179 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200180 netfn = ipmi::me_bridge::netFn;
181 command = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700182 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000183 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
184 deviceAddress, 00, 0x00, 0x00, 0x00,
185 0x01, 0x02, 0x8D};
James Feistd7ae29a2020-06-25 15:42:46 -0700186 readingFormat = ReadingFormat::elevenBitShift;
James Feist6ef20402019-01-07 16:45:08 -0800187 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700188 else if (type == IpmbType::ADM1278HSC)
189 {
190 commandAddress = meAddress;
Ed Tanousa771f6a2022-01-14 09:36:51 -0800191 uint8_t snsNum = 0;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700192 switch (subType)
193 {
194 case IpmbSubType::temp:
195 case IpmbSubType::curr:
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700196 if (subType == IpmbSubType::temp)
Ed Tanous8a57ec02020-10-09 12:46:52 -0700197 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700198 snsNum = 0x8d;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700199 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700200 else
Ed Tanous8a57ec02020-10-09 12:46:52 -0700201 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700202 snsNum = 0x8c;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700203 }
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200204 netfn = ipmi::me_bridge::netFn;
205 command = ipmi::me_bridge::sendRawPmbus;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700206 commandData = {0x57, 0x01, 0x00, 0x86, deviceAddress,
207 0x00, 0x00, 0x01, 0x02, snsNum};
James Feistd7ae29a2020-06-25 15:42:46 -0700208 readingFormat = ReadingFormat::elevenBit;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700209 break;
210 case IpmbSubType::power:
211 case IpmbSubType::volt:
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200212 netfn = ipmi::sensor::netFn;
213 command = ipmi::sensor::getSensorReading;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700214 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700215 readingFormat = ReadingFormat::byte0;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700216 break;
217 default:
218 throw std::runtime_error("Invalid sensor type");
219 }
220 }
James Feist6ef20402019-01-07 16:45:08 -0800221 else if (type == IpmbType::mpsVR)
222 {
223 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200224 netfn = ipmi::me_bridge::netFn;
225 command = ipmi::me_bridge::sendRawPmbus;
226 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700227 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000228 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
229 deviceAddress, 0x00, 0x00, 0x00, 0x00,
230 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700231 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000232 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
233 deviceAddress, 0x00, 0x00, 0x00, 0x00,
234 0x02, 0x00, 0x00, 0x00};
James Feistd7ae29a2020-06-25 15:42:46 -0700235 readingFormat = ReadingFormat::byte3;
James Feist6ef20402019-01-07 16:45:08 -0800236 }
237 else
238 {
239 throw std::runtime_error("Invalid sensor type");
240 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200241
242 if (subType == IpmbSubType::util)
243 {
244 // Utilization need to be scaled to percent
245 maxValue = 100;
246 minValue = 0;
247 }
James Feist6ef20402019-01-07 16:45:08 -0800248}
249
250void IpmbSensor::checkThresholds(void)
251{
James Feist6ef20402019-01-07 16:45:08 -0800252 thresholds::checkThresholds(this);
253}
254
James Feist961bf092020-07-01 16:38:12 -0700255bool IpmbSensor::processReading(const std::vector<uint8_t>& data, double& resp)
James Feistd7ae29a2020-06-25 15:42:46 -0700256{
257
258 switch (readingFormat)
259 {
260 case (ReadingFormat::byte0):
James Feiste4a970d2020-08-19 11:21:58 -0700261 {
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200262 if (command == ipmi::sensor::getSensorReading &&
263 !ipmi::sensor::isValid(data))
James Feistcf4238e2020-07-28 16:40:03 -0700264 {
265 return false;
266 }
James Feist961bf092020-07-01 16:38:12 -0700267 resp = data[0];
268 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700269 }
James Feistd7ae29a2020-06-25 15:42:46 -0700270 case (ReadingFormat::byte3):
James Feiste4a970d2020-08-19 11:21:58 -0700271 {
James Feistd7ae29a2020-06-25 15:42:46 -0700272 if (data.size() < 4)
273 {
James Feist961bf092020-07-01 16:38:12 -0700274 if (!errCount)
275 {
276 std::cerr << "Invalid data length returned for " << name
277 << "\n";
278 }
279 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700280 }
James Feist961bf092020-07-01 16:38:12 -0700281 resp = data[3];
282 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700283 }
James Feistd7ae29a2020-06-25 15:42:46 -0700284 case (ReadingFormat::elevenBit):
James Feiste4a970d2020-08-19 11:21:58 -0700285 {
James Feistd7ae29a2020-06-25 15:42:46 -0700286 if (data.size() < 5)
287 {
James Feist961bf092020-07-01 16:38:12 -0700288 if (!errCount)
289 {
290 std::cerr << "Invalid data length returned for " << name
291 << "\n";
292 }
293 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700294 }
295
James Feiste4a970d2020-08-19 11:21:58 -0700296 int16_t value = ((data[4] << 8) | data[3]);
James Feiste4a970d2020-08-19 11:21:58 -0700297 resp = value;
James Feist961bf092020-07-01 16:38:12 -0700298 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700299 }
James Feistd7ae29a2020-06-25 15:42:46 -0700300 case (ReadingFormat::elevenBitShift):
James Feiste4a970d2020-08-19 11:21:58 -0700301 {
James Feistd7ae29a2020-06-25 15:42:46 -0700302 if (data.size() < 5)
303 {
James Feist961bf092020-07-01 16:38:12 -0700304 if (!errCount)
305 {
306 std::cerr << "Invalid data length returned for " << name
307 << "\n";
308 }
309 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700310 }
311
James Feist961bf092020-07-01 16:38:12 -0700312 resp = ((data[4] << 8) | data[3]) >> 3;
313 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700314 }
Jayashree-D37322572021-03-19 17:40:56 +0530315 case (ReadingFormat::linearElevenBit):
316 {
317 if (data.size() < 5)
318 {
319 if (!errCount)
320 {
321 std::cerr << "Invalid data length returned for " << name
322 << "\n";
323 }
324 return false;
325 }
326
327 int16_t value = ((data[4] << 8) | data[3]);
328 constexpr const size_t shift = 16 - 11; // 11bit into 16bit
329 value <<= shift;
330 value >>= shift;
331 resp = value;
332 return true;
333 }
James Feistd7ae29a2020-06-25 15:42:46 -0700334 default:
335 throw std::runtime_error("Invalid reading type");
336 }
337}
338
James Feist6ef20402019-01-07 16:45:08 -0800339void IpmbSensor::read(void)
340{
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530341 waitTimer.expires_from_now(boost::posix_time::milliseconds(sensorPollMs));
James Feist6ef20402019-01-07 16:45:08 -0800342 waitTimer.async_wait([this](const boost::system::error_code& ec) {
343 if (ec == boost::asio::error::operation_aborted)
344 {
345 return; // we're being canceled
346 }
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200347 if (!readingStateGood())
James Feist6ef20402019-01-07 16:45:08 -0800348 {
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200349 updateValue(std::numeric_limits<double>::quiet_NaN());
James Feist6ef20402019-01-07 16:45:08 -0800350 read();
351 return;
352 }
353 dbusConnection->async_method_call(
354 [this](boost::system::error_code ec,
355 const IpmbMethodType& response) {
356 const int& status = std::get<0>(response);
357 if (ec || status)
358 {
James Feist961bf092020-07-01 16:38:12 -0700359 incrementError();
James Feist6ef20402019-01-07 16:45:08 -0800360 read();
361 return;
362 }
363 const std::vector<uint8_t>& data = std::get<5>(response);
364 if constexpr (debug)
365 {
366 std::cout << name << ": ";
367 for (size_t d : data)
368 {
369 std::cout << d << " ";
370 }
371 std::cout << "\n";
372 }
James Feistd7ae29a2020-06-25 15:42:46 -0700373 if (data.empty())
James Feist6ef20402019-01-07 16:45:08 -0800374 {
James Feist961bf092020-07-01 16:38:12 -0700375 incrementError();
James Feistd7ae29a2020-06-25 15:42:46 -0700376 read();
377 return;
James Feist6ef20402019-01-07 16:45:08 -0800378 }
James Feist961bf092020-07-01 16:38:12 -0700379
380 double value = 0;
381
382 if (!processReading(data, value))
383 {
384 incrementError();
385 read();
386 return;
387 }
Ed Tanous8a57ec02020-10-09 12:46:52 -0700388
389 // rawValue only used in debug logging
390 // up to 5th byte in data are used to derive value
391 size_t end = std::min(sizeof(uint64_t), data.size());
392 uint64_t rawData = 0;
393 for (size_t i = 0; i < end; i++)
Zhikui Rend3da1282020-09-11 17:02:01 -0700394 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700395 reinterpret_cast<uint8_t*>(&rawData)[i] = data[i];
Zhikui Rend3da1282020-09-11 17:02:01 -0700396 }
Ed Tanous8a57ec02020-10-09 12:46:52 -0700397 rawValue = static_cast<double>(rawData);
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700398
399 /* Adjust value as per scale and offset */
400 value = (value * scaleVal) + offsetVal;
James Feist6ef20402019-01-07 16:45:08 -0800401 updateValue(value);
402 read();
403 },
404 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
405 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
406 "sendRequest", commandAddress, netfn, lun, command, commandData);
407 });
408}
409void createSensors(
410 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
411 boost::container::flat_map<std::string, std::unique_ptr<IpmbSensor>>&
412 sensors,
413 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
414{
415 if (!dbusConnection)
416 {
417 std::cerr << "Connection not created\n";
418 return;
419 }
420 dbusConnection->async_method_call(
421 [&](boost::system::error_code ec, const ManagedObjectType& resp) {
422 if (ec)
423 {
424 std::cerr << "Error contacting entity manager\n";
425 return;
426 }
427 for (const auto& pathPair : resp)
428 {
429 for (const auto& entry : pathPair.second)
430 {
431 if (entry.first != configInterface)
432 {
433 continue;
434 }
435 std::string name =
436 loadVariant<std::string>(entry.second, "Name");
437
438 std::vector<thresholds::Threshold> sensorThresholds;
439 if (!parseThresholdsFromConfig(pathPair.second,
440 sensorThresholds))
441 {
442 std::cerr << "error populating thresholds for " << name
443 << "\n";
444 }
445 uint8_t deviceAddress =
446 loadVariant<uint8_t>(entry.second, "Address");
447
448 std::string sensorClass =
449 loadVariant<std::string>(entry.second, "Class");
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530450
Anoop S832a2c62020-11-20 19:21:22 +0000451 uint8_t hostSMbusIndex = hostSMbusIndexDefault;
452 auto findSmType = entry.second.find("HostSMbusIndex");
453 if (findSmType != entry.second.end())
454 {
455 hostSMbusIndex = std::visit(
456 VariantToUnsignedIntVisitor(), findSmType->second);
457 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700458
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530459 float pollRate = pollRateDefault;
460 auto findPollRate = entry.second.find("PollRate");
461 if (findPollRate != entry.second.end())
462 {
463 pollRate = std::visit(VariantToFloatVisitor(),
464 findPollRate->second);
465 if (pollRate <= 0.0f)
466 {
467 pollRate = pollRateDefault;
468 }
469 }
470
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700471 /* Default sensor type is "temperature" */
472 std::string sensorTypeName = "temperature";
473 auto findType = entry.second.find("SensorType");
474 if (findType != entry.second.end())
475 {
476 sensorTypeName = std::visit(VariantToStringVisitor(),
477 findType->second);
478 }
479
James Feist6ef20402019-01-07 16:45:08 -0800480 auto& sensor = sensors[name];
481 sensor = std::make_unique<IpmbSensor>(
482 dbusConnection, io, name, pathPair.first, objectServer,
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700483 std::move(sensorThresholds), deviceAddress,
Jayashree-D9f6d4fd2021-04-13 18:27:22 +0530484 hostSMbusIndex, pollRate, sensorTypeName);
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700485
486 /* Initialize scale and offset value */
487 sensor->scaleVal = 1;
488 sensor->offsetVal = 0;
489
490 auto findScaleVal = entry.second.find("ScaleValue");
491 if (findScaleVal != entry.second.end())
492 {
493 sensor->scaleVal = std::visit(VariantToDoubleVisitor(),
494 findScaleVal->second);
495 }
496
497 auto findOffsetVal = entry.second.find("OffsetValue");
498 if (findOffsetVal != entry.second.end())
499 {
500 sensor->offsetVal = std::visit(VariantToDoubleVisitor(),
501 findOffsetVal->second);
502 }
James Feist6ef20402019-01-07 16:45:08 -0800503
James Feistfc94b212019-02-06 16:14:51 -0800504 auto findPowerState = entry.second.find("PowerState");
505
506 if (findPowerState != entry.second.end())
507 {
508 std::string powerState = std::visit(
509 VariantToStringVisitor(), findPowerState->second);
510
511 setReadState(powerState, sensor->readState);
512 }
513
James Feist6ef20402019-01-07 16:45:08 -0800514 if (sensorClass == "PxeBridgeTemp")
515 {
516 sensor->type = IpmbType::PXE1410CVR;
517 }
518 else if (sensorClass == "IRBridgeTemp")
519 {
520 sensor->type = IpmbType::IR38363VR;
521 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700522 else if (sensorClass == "HSCBridge")
523 {
524 sensor->type = IpmbType::ADM1278HSC;
525 }
James Feist6ef20402019-01-07 16:45:08 -0800526 else if (sensorClass == "MpsBridgeTemp")
527 {
528 sensor->type = IpmbType::mpsVR;
529 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200530 else if (sensorClass == "METemp" ||
531 sensorClass == "MESensor")
James Feist6ef20402019-01-07 16:45:08 -0800532 {
533 sensor->type = IpmbType::meSensor;
534 }
535 else
536 {
537 std::cerr << "Invalid class " << sensorClass << "\n";
538 continue;
539 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700540
541 if (sensorTypeName == "voltage")
542 {
543 sensor->subType = IpmbSubType::volt;
544 }
545 else if (sensorTypeName == "power")
546 {
547 sensor->subType = IpmbSubType::power;
548 }
549 else if (sensorTypeName == "current")
550 {
551 sensor->subType = IpmbSubType::curr;
552 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200553 else if (sensorTypeName == "utilization")
554 {
555 sensor->subType = IpmbSubType::util;
556 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700557 else
558 {
559 sensor->subType = IpmbSubType::temp;
560 }
James Feist6ef20402019-01-07 16:45:08 -0800561 sensor->init();
562 }
563 }
564 },
565 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
566 "GetManagedObjects");
567}
568
James Feistf7e2c5d2019-02-13 17:27:51 -0800569void reinitSensors(sdbusplus::message::message& message)
570{
James Feist0d4f2bd2019-03-05 13:15:40 -0800571 constexpr const size_t reinitWaitSeconds = 2;
James Feistf7e2c5d2019-02-13 17:27:51 -0800572 std::string objectName;
James Feist52497fd2019-06-07 13:01:33 -0700573 boost::container::flat_map<std::string, std::variant<std::string>> values;
James Feistf7e2c5d2019-02-13 17:27:51 -0800574 message.read(objectName, values);
James Feist0d4f2bd2019-03-05 13:15:40 -0800575
James Feist52497fd2019-06-07 13:01:33 -0700576 auto findStatus = values.find(power::property);
577 if (findStatus != values.end())
James Feistf7e2c5d2019-02-13 17:27:51 -0800578 {
James Feist52497fd2019-06-07 13:01:33 -0700579 bool powerStatus = boost::ends_with(
Thu Ba Nguyen585d3a02021-07-20 20:25:15 +0700580 std::get<std::string>(findStatus->second), ".Running");
James Feistf7e2c5d2019-02-13 17:27:51 -0800581 if (powerStatus)
582 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800583 if (!initCmdTimer)
James Feistf7e2c5d2019-02-13 17:27:51 -0800584 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800585 // this should be impossible
586 return;
James Feistf7e2c5d2019-02-13 17:27:51 -0800587 }
James Feist0d4f2bd2019-03-05 13:15:40 -0800588 // we seem to send this command too fast sometimes, wait before
589 // sending
590 initCmdTimer->expires_from_now(
591 boost::posix_time::seconds(reinitWaitSeconds));
592
593 initCmdTimer->async_wait([](const boost::system::error_code ec) {
594 if (ec == boost::asio::error::operation_aborted)
595 {
596 return; // we're being canceled
597 }
598
599 for (const auto& sensor : sensors)
600 {
601 if (sensor.second)
602 {
603 sensor.second->runInitCmd();
604 }
605 }
606 });
James Feistf7e2c5d2019-02-13 17:27:51 -0800607 }
608 }
609}
610
James Feistb6c0b912019-07-09 12:21:44 -0700611int main()
James Feist6ef20402019-01-07 16:45:08 -0800612{
613
614 boost::asio::io_service io;
615 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
616 systemBus->request_name("xyz.openbmc_project.IpmbSensor");
617 sdbusplus::asio::object_server objectServer(systemBus);
James Feist6ef20402019-01-07 16:45:08 -0800618
James Feist0d4f2bd2019-03-05 13:15:40 -0800619 initCmdTimer = std::make_unique<boost::asio::deadline_timer>(io);
620
James Feist6ef20402019-01-07 16:45:08 -0800621 io.post([&]() { createSensors(io, objectServer, sensors, systemBus); });
622
623 boost::asio::deadline_timer configTimer(io);
624
625 std::function<void(sdbusplus::message::message&)> eventHandler =
James Feistb6c0b912019-07-09 12:21:44 -0700626 [&](sdbusplus::message::message&) {
James Feist6ef20402019-01-07 16:45:08 -0800627 configTimer.expires_from_now(boost::posix_time::seconds(1));
628 // create a timer because normally multiple properties change
629 configTimer.async_wait([&](const boost::system::error_code& ec) {
630 if (ec == boost::asio::error::operation_aborted)
631 {
632 return; // we're being canceled
633 }
634 createSensors(io, objectServer, sensors, systemBus);
635 if (sensors.empty())
636 {
637 std::cout << "Configuration not detected\n";
638 }
639 });
640 };
641
James Feistf7e2c5d2019-02-13 17:27:51 -0800642 sdbusplus::bus::match::match configMatch(
James Feist6ef20402019-01-07 16:45:08 -0800643 static_cast<sdbusplus::bus::bus&>(*systemBus),
644 "type='signal',member='PropertiesChanged',path_namespace='" +
645 std::string(inventoryPath) + "',arg0namespace='" + configInterface +
646 "'",
647 eventHandler);
648
James Feistf7e2c5d2019-02-13 17:27:51 -0800649 sdbusplus::bus::match::match powerChangeMatch(
650 static_cast<sdbusplus::bus::bus&>(*systemBus),
James Feist52497fd2019-06-07 13:01:33 -0700651 "type='signal',interface='" + std::string(properties::interface) +
652 "',path='" + std::string(power::path) + "',arg0='" +
653 std::string(power::interface) + "'",
James Feistf7e2c5d2019-02-13 17:27:51 -0800654 reinitSensors);
655
Bruce Lee1263c3d2021-06-04 15:16:33 +0800656 setupManufacturingModeMatch(*systemBus);
James Feist6ef20402019-01-07 16:45:08 -0800657 io.run();
Zhikui Rene76a5a62021-07-09 15:16:32 -0700658 return 0;
James Feist6ef20402019-01-07 16:45:08 -0800659}