blob: b939ff16a7de6fbdecdba424889035f07905b8a2 [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
Andrew Jefferye73bd0a2023-01-25 10:39:57 +103017#include "IpmbSensor.hpp"
18
19#include "IpmbSDRSensor.hpp"
20#include "Utils.hpp"
21#include "VariantVisitors.hpp"
22
Patrick Venture96e97db2019-10-31 13:44:38 -070023#include <boost/container/flat_map.hpp>
James Feist38fb5982020-05-28 10:09:54 -070024#include <sdbusplus/asio/connection.hpp>
25#include <sdbusplus/asio/object_server.hpp>
26#include <sdbusplus/bus/match.hpp>
27
James Feist6ef20402019-01-07 16:45:08 -080028#include <chrono>
Ed Tanous8a57ec02020-10-09 12:46:52 -070029#include <cmath>
Patrick Venture96e97db2019-10-31 13:44:38 -070030#include <functional>
James Feist6ef20402019-01-07 16:45:08 -080031#include <iostream>
32#include <limits>
Patrick Venture96e97db2019-10-31 13:44:38 -070033#include <memory>
James Feist6ef20402019-01-07 16:45:08 -080034#include <numeric>
Patrick Venture96e97db2019-10-31 13:44:38 -070035#include <string>
36#include <tuple>
37#include <variant>
James Feist6ef20402019-01-07 16:45:08 -080038#include <vector>
39
40constexpr const bool debug = false;
41
Zev Weiss054aad82022-08-18 01:37:34 -070042constexpr const char* sensorType = "IpmbSensor";
Jayashree Dhanapal3746c552022-03-21 14:45:52 +053043constexpr const char* sdrInterface = "IpmbDevice";
44
James Feist6ef20402019-01-07 16:45:08 -080045static constexpr double ipmbMaxReading = 0xFF;
46static constexpr double ipmbMinReading = 0;
47
48static constexpr uint8_t meAddress = 1;
49static constexpr uint8_t lun = 0;
Anoop S832a2c62020-11-20 19:21:22 +000050static constexpr uint8_t hostSMbusIndexDefault = 0x03;
Jayashree Dhanapal6ee62942021-12-14 15:22:23 +053051static constexpr uint8_t ipmbBusIndexDefault = 0;
Jayashree-D9f6d4fd2021-04-13 18:27:22 +053052static constexpr float pollRateDefault = 1; // in seconds
James Feist6ef20402019-01-07 16:45:08 -080053
Vijay Khemka682a5cb2019-07-18 17:34:03 -070054static constexpr const char* sensorPathPrefix = "/xyz/openbmc_project/sensors/";
55
Vikash Chandola1f847972022-09-28 09:47:32 +000056boost::container::flat_map<std::string, std::shared_ptr<IpmbSensor>> sensors;
Jayashree Dhanapal3746c552022-03-21 14:45:52 +053057boost::container::flat_map<uint8_t, std::shared_ptr<IpmbSDRDevice>> sdrsensor;
James Feistf7e2c5d2019-02-13 17:27:51 -080058
Ed Tanous9b4a20e2022-09-06 08:47:11 -070059std::unique_ptr<boost::asio::steady_timer> initCmdTimer;
James Feist0d4f2bd2019-03-05 13:15:40 -080060
James Feist6ef20402019-01-07 16:45:08 -080061IpmbSensor::IpmbSensor(std::shared_ptr<sdbusplus::asio::connection>& conn,
Ed Tanous1f978632023-02-28 18:16:39 -080062 boost::asio::io_context& io,
James Feist6ef20402019-01-07 16:45:08 -080063 const std::string& sensorName,
64 const std::string& sensorConfiguration,
65 sdbusplus::asio::object_server& objectServer,
66 std::vector<thresholds::Threshold>&& thresholdData,
Anoop S832a2c62020-11-20 19:21:22 +000067 uint8_t deviceAddress, uint8_t hostSMbusIndex,
Jayashree-D9f6d4fd2021-04-13 18:27:22 +053068 const float pollRate, std::string& sensorTypeName) :
Zhikui Renda98f092021-11-01 09:41:08 -070069 Sensor(escapeName(sensorName), std::move(thresholdData),
Zev Weiss054aad82022-08-18 01:37:34 -070070 sensorConfiguration, "IpmbSensor", false, false, ipmbMaxReading,
71 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
Jayashree Dhanapal56678082022-01-04 17:27:20 +053081 for (const auto& threshold : thresholds)
James Feist6ef20402019-01-07 16:45:08 -080082 {
Jayashree Dhanapal56678082022-01-04 17:27:20 +053083 std::string interface = thresholds::getInterface(threshold.level);
84 thresholdInterfaces[static_cast<size_t>(threshold.level)] =
85 objectServer.add_interface(dbusPath, interface);
James Feist6ef20402019-01-07 16:45:08 -080086 }
James Feist2adc95c2019-09-30 14:55:28 -070087 association = objectServer.add_interface(dbusPath, association::interface);
James Feist6ef20402019-01-07 16:45:08 -080088}
89
90IpmbSensor::~IpmbSensor()
91{
92 waitTimer.cancel();
Jayashree Dhanapal56678082022-01-04 17:27:20 +053093 for (const auto& iface : thresholdInterfaces)
94 {
95 objectServer.remove_interface(iface);
96 }
James Feist6ef20402019-01-07 16:45:08 -080097 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
Ed Tanous2049bd22022-07-09 07:20:26 -0700101std::string IpmbSensor::getSubTypeUnits(void) const
Zev Weiss6b6891c2021-04-22 02:46:21 -0500102{
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();
Andrei Kartashev39287412022-02-04 16:04:47 +0300123 setInitialProperties(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
Vikash Chandola1f847972022-09-28 09:47:32 +0000131static void initCmdCb(const std::weak_ptr<IpmbSensor>& weakRef,
132 const boost::system::error_code& ec,
133 const IpmbMethodType& response)
134{
135 std::shared_ptr<IpmbSensor> self = weakRef.lock();
136 if (!self)
137 {
138 return;
139 }
140 const int& status = std::get<0>(response);
141 if (ec || (status != 0))
142 {
143 std::cerr << "Error setting init command for device: " << self->name
144 << "\n";
145 }
146}
147
James Feistf7e2c5d2019-02-13 17:27:51 -0800148void IpmbSensor::runInitCmd()
149{
Vikash Chandola1f847972022-09-28 09:47:32 +0000150 if (!initCommand)
James Feistf7e2c5d2019-02-13 17:27:51 -0800151 {
Vikash Chandola1f847972022-09-28 09:47:32 +0000152 return;
James Feist6ef20402019-01-07 16:45:08 -0800153 }
Vikash Chandola1f847972022-09-28 09:47:32 +0000154 dbusConnection->async_method_call(
155 [weakRef{weak_from_this()}](const boost::system::error_code& ec,
156 const IpmbMethodType& response) {
157 initCmdCb(weakRef, ec, response);
158 },
159 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
160 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
161 "sendRequest", commandAddress, netfn, lun, *initCommand, initData);
James Feist6ef20402019-01-07 16:45:08 -0800162}
163
164void IpmbSensor::loadDefaults()
165{
166 if (type == IpmbType::meSensor)
167 {
168 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200169 netfn = ipmi::sensor::netFn;
170 command = ipmi::sensor::getSensorReading;
James Feist6ef20402019-01-07 16:45:08 -0800171 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700172 readingFormat = ReadingFormat::byte0;
James Feist6ef20402019-01-07 16:45:08 -0800173 }
174 else if (type == IpmbType::PXE1410CVR)
175 {
176 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200177 netfn = ipmi::me_bridge::netFn;
178 command = ipmi::me_bridge::sendRawPmbus;
179 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700180 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000181 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
182 deviceAddress, 0x00, 0x00, 0x00, 0x00,
183 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700184 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000185 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
186 deviceAddress, 0x00, 0x00, 0x00, 0x00,
187 0x02, 0x00, 0x00, 0x00};
Jayashree-D37322572021-03-19 17:40:56 +0530188 readingFormat = ReadingFormat::linearElevenBit;
James Feist6ef20402019-01-07 16:45:08 -0800189 }
190 else if (type == IpmbType::IR38363VR)
191 {
192 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200193 netfn = ipmi::me_bridge::netFn;
194 command = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700195 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000196 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
197 deviceAddress, 00, 0x00, 0x00, 0x00,
198 0x01, 0x02, 0x8D};
James Feistd7ae29a2020-06-25 15:42:46 -0700199 readingFormat = ReadingFormat::elevenBitShift;
James Feist6ef20402019-01-07 16:45:08 -0800200 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700201 else if (type == IpmbType::ADM1278HSC)
202 {
203 commandAddress = meAddress;
Ed Tanousa771f6a2022-01-14 09:36:51 -0800204 uint8_t snsNum = 0;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700205 switch (subType)
206 {
207 case IpmbSubType::temp:
208 case IpmbSubType::curr:
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700209 if (subType == IpmbSubType::temp)
Ed Tanous8a57ec02020-10-09 12:46:52 -0700210 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700211 snsNum = 0x8d;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700212 }
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700213 else
Ed Tanous8a57ec02020-10-09 12:46:52 -0700214 {
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700215 snsNum = 0x8c;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700216 }
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200217 netfn = ipmi::me_bridge::netFn;
218 command = ipmi::me_bridge::sendRawPmbus;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700219 commandData = {0x57, 0x01, 0x00, 0x86, deviceAddress,
220 0x00, 0x00, 0x01, 0x02, snsNum};
James Feistd7ae29a2020-06-25 15:42:46 -0700221 readingFormat = ReadingFormat::elevenBit;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700222 break;
223 case IpmbSubType::power:
224 case IpmbSubType::volt:
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200225 netfn = ipmi::sensor::netFn;
226 command = ipmi::sensor::getSensorReading;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700227 commandData = {deviceAddress};
James Feistd7ae29a2020-06-25 15:42:46 -0700228 readingFormat = ReadingFormat::byte0;
Vijay Khemka682a5cb2019-07-18 17:34:03 -0700229 break;
230 default:
231 throw std::runtime_error("Invalid sensor type");
232 }
233 }
James Feist6ef20402019-01-07 16:45:08 -0800234 else if (type == IpmbType::mpsVR)
235 {
236 commandAddress = meAddress;
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200237 netfn = ipmi::me_bridge::netFn;
238 command = ipmi::me_bridge::sendRawPmbus;
239 initCommand = ipmi::me_bridge::sendRawPmbus;
James Feistd7ae29a2020-06-25 15:42:46 -0700240 // pmbus read temp
Anoop S832a2c62020-11-20 19:21:22 +0000241 commandData = {0x57, 0x01, 0x00, 0x16, hostSMbusIndex,
242 deviceAddress, 0x00, 0x00, 0x00, 0x00,
243 0x01, 0x02, 0x8d};
James Feistd7ae29a2020-06-25 15:42:46 -0700244 // goto page 0
Anoop S832a2c62020-11-20 19:21:22 +0000245 initData = {0x57, 0x01, 0x00, 0x14, hostSMbusIndex,
246 deviceAddress, 0x00, 0x00, 0x00, 0x00,
247 0x02, 0x00, 0x00, 0x00};
James Feistd7ae29a2020-06-25 15:42:46 -0700248 readingFormat = ReadingFormat::byte3;
James Feist6ef20402019-01-07 16:45:08 -0800249 }
250 else
251 {
252 throw std::runtime_error("Invalid sensor type");
253 }
Adrian Ambrożewicz45e92772020-06-04 13:59:55 +0200254
255 if (subType == IpmbSubType::util)
256 {
257 // Utilization need to be scaled to percent
258 maxValue = 100;
259 minValue = 0;
260 }
James Feist6ef20402019-01-07 16:45:08 -0800261}
262
263void IpmbSensor::checkThresholds(void)
264{
James Feist6ef20402019-01-07 16:45:08 -0800265 thresholds::checkThresholds(this);
266}
267
James Feist961bf092020-07-01 16:38:12 -0700268bool IpmbSensor::processReading(const std::vector<uint8_t>& data, double& resp)
James Feistd7ae29a2020-06-25 15:42:46 -0700269{
270
271 switch (readingFormat)
272 {
273 case (ReadingFormat::byte0):
James Feiste4a970d2020-08-19 11:21:58 -0700274 {
Adrian Ambrożewicz58e02ef2020-08-06 14:42:38 +0200275 if (command == ipmi::sensor::getSensorReading &&
276 !ipmi::sensor::isValid(data))
James Feistcf4238e2020-07-28 16:40:03 -0700277 {
278 return false;
279 }
James Feist961bf092020-07-01 16:38:12 -0700280 resp = data[0];
281 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700282 }
James Feistd7ae29a2020-06-25 15:42:46 -0700283 case (ReadingFormat::byte3):
James Feiste4a970d2020-08-19 11:21:58 -0700284 {
James Feistd7ae29a2020-06-25 15:42:46 -0700285 if (data.size() < 4)
286 {
Ed Tanous2049bd22022-07-09 07:20:26 -0700287 if (errCount == 0U)
James Feist961bf092020-07-01 16:38:12 -0700288 {
289 std::cerr << "Invalid data length returned for " << name
290 << "\n";
291 }
292 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700293 }
James Feist961bf092020-07-01 16:38:12 -0700294 resp = data[3];
295 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700296 }
James Feistd7ae29a2020-06-25 15:42:46 -0700297 case (ReadingFormat::elevenBit):
James Feiste4a970d2020-08-19 11:21:58 -0700298 {
James Feistd7ae29a2020-06-25 15:42:46 -0700299 if (data.size() < 5)
300 {
Ed Tanous2049bd22022-07-09 07:20:26 -0700301 if (errCount == 0U)
James Feist961bf092020-07-01 16:38:12 -0700302 {
303 std::cerr << "Invalid data length returned for " << name
304 << "\n";
305 }
306 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700307 }
308
James Feiste4a970d2020-08-19 11:21:58 -0700309 int16_t value = ((data[4] << 8) | data[3]);
James Feiste4a970d2020-08-19 11:21:58 -0700310 resp = value;
James Feist961bf092020-07-01 16:38:12 -0700311 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700312 }
James Feistd7ae29a2020-06-25 15:42:46 -0700313 case (ReadingFormat::elevenBitShift):
James Feiste4a970d2020-08-19 11:21:58 -0700314 {
James Feistd7ae29a2020-06-25 15:42:46 -0700315 if (data.size() < 5)
316 {
Ed Tanous2049bd22022-07-09 07:20:26 -0700317 if (errCount == 0U)
James Feist961bf092020-07-01 16:38:12 -0700318 {
319 std::cerr << "Invalid data length returned for " << name
320 << "\n";
321 }
322 return false;
James Feistd7ae29a2020-06-25 15:42:46 -0700323 }
324
James Feist961bf092020-07-01 16:38:12 -0700325 resp = ((data[4] << 8) | data[3]) >> 3;
326 return true;
James Feiste4a970d2020-08-19 11:21:58 -0700327 }
Jayashree-D37322572021-03-19 17:40:56 +0530328 case (ReadingFormat::linearElevenBit):
329 {
330 if (data.size() < 5)
331 {
Ed Tanous2049bd22022-07-09 07:20:26 -0700332 if (errCount == 0U)
Jayashree-D37322572021-03-19 17:40:56 +0530333 {
334 std::cerr << "Invalid data length returned for " << name
335 << "\n";
336 }
337 return false;
338 }
339
340 int16_t value = ((data[4] << 8) | data[3]);
341 constexpr const size_t shift = 16 - 11; // 11bit into 16bit
342 value <<= shift;
343 value >>= shift;
344 resp = value;
345 return true;
346 }
James Feistd7ae29a2020-06-25 15:42:46 -0700347 default:
348 throw std::runtime_error("Invalid reading type");
349 }
350}
351
Vikash Chandola1f847972022-09-28 09:47:32 +0000352void IpmbSensor::ipmbRequestCompletionCb(const boost::system::error_code& ec,
353 const IpmbMethodType& response)
354{
355 const int& status = std::get<0>(response);
356 if (ec || (status != 0))
357 {
358 incrementError();
359 read();
360 return;
361 }
362 const std::vector<uint8_t>& data = std::get<5>(response);
363 if constexpr (debug)
364 {
365 std::cout << name << ": ";
366 for (size_t d : data)
367 {
368 std::cout << d << " ";
369 }
370 std::cout << "\n";
371 }
372 if (data.empty())
373 {
374 incrementError();
375 read();
376 return;
377 }
378
379 double value = 0;
380
381 if (!processReading(data, value))
382 {
383 incrementError();
384 read();
385 return;
386 }
387
388 // rawValue only used in debug logging
389 // up to 5th byte in data are used to derive value
390 size_t end = std::min(sizeof(uint64_t), data.size());
391 uint64_t rawData = 0;
392 for (size_t i = 0; i < end; i++)
393 {
394 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
395 reinterpret_cast<uint8_t*>(&rawData)[i] = data[i];
396 }
397 rawValue = static_cast<double>(rawData);
398
399 /* Adjust value as per scale and offset */
400 value = (value * scaleVal) + offsetVal;
401 updateValue(value);
402 read();
403}
404
James Feist6ef20402019-01-07 16:45:08 -0800405void IpmbSensor::read(void)
406{
Ed Tanous9b4a20e2022-09-06 08:47:11 -0700407 waitTimer.expires_from_now(std::chrono::milliseconds(sensorPollMs));
Vikash Chandola1f847972022-09-28 09:47:32 +0000408 waitTimer.async_wait(
409 [weakRef{weak_from_this()}](const boost::system::error_code& ec) {
James Feist6ef20402019-01-07 16:45:08 -0800410 if (ec == boost::asio::error::operation_aborted)
411 {
412 return; // we're being canceled
413 }
Vikash Chandola1f847972022-09-28 09:47:32 +0000414 std::shared_ptr<IpmbSensor> self = weakRef.lock();
415 if (!self)
James Feist6ef20402019-01-07 16:45:08 -0800416 {
James Feist6ef20402019-01-07 16:45:08 -0800417 return;
418 }
Vikash Chandola1f847972022-09-28 09:47:32 +0000419 self->sendIpmbRequest();
James Feist6ef20402019-01-07 16:45:08 -0800420 });
421}
Jayashree Dhanapal84189752022-03-07 12:51:54 +0530422
Vikash Chandola1f847972022-09-28 09:47:32 +0000423void IpmbSensor::sendIpmbRequest()
424{
425 if (!readingStateGood())
426 {
427 updateValue(std::numeric_limits<double>::quiet_NaN());
428 read();
429 return;
430 }
431 dbusConnection->async_method_call(
432 [weakRef{weak_from_this()}](boost::system::error_code ec,
433 const IpmbMethodType& response) {
434 std::shared_ptr<IpmbSensor> self = weakRef.lock();
435 if (!self)
436 {
437 return;
438 }
439 self->ipmbRequestCompletionCb(ec, response);
440 },
441 "xyz.openbmc_project.Ipmi.Channel.Ipmb",
442 "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
443 "sendRequest", commandAddress, netfn, lun, command, commandData);
444}
445
Jayashree Dhanapal84189752022-03-07 12:51:54 +0530446bool IpmbSensor::sensorClassType(const std::string& sensorClass)
447{
448 if (sensorClass == "PxeBridgeTemp")
449 {
450 type = IpmbType::PXE1410CVR;
451 }
452 else if (sensorClass == "IRBridgeTemp")
453 {
454 type = IpmbType::IR38363VR;
455 }
456 else if (sensorClass == "HSCBridge")
457 {
458 type = IpmbType::ADM1278HSC;
459 }
460 else if (sensorClass == "MpsBridgeTemp")
461 {
462 type = IpmbType::mpsVR;
463 }
464 else if (sensorClass == "METemp" || sensorClass == "MESensor")
465 {
466 type = IpmbType::meSensor;
467 }
468 else
469 {
470 std::cerr << "Invalid class " << sensorClass << "\n";
471 return false;
472 }
473 return true;
474}
475
476void IpmbSensor::sensorSubType(const std::string& sensorTypeName)
477{
478 if (sensorTypeName == "voltage")
479 {
480 subType = IpmbSubType::volt;
481 }
482 else if (sensorTypeName == "power")
483 {
484 subType = IpmbSubType::power;
485 }
486 else if (sensorTypeName == "current")
487 {
488 subType = IpmbSubType::curr;
489 }
490 else if (sensorTypeName == "utilization")
491 {
492 subType = IpmbSubType::util;
493 }
494 else
495 {
496 subType = IpmbSubType::temp;
497 }
498}
499
500void IpmbSensor::parseConfigValues(const SensorBaseConfigMap& entry)
501{
502 auto findScaleVal = entry.find("ScaleValue");
503 if (findScaleVal != entry.end())
504 {
505 scaleVal = std::visit(VariantToDoubleVisitor(), findScaleVal->second);
506 }
507
508 auto findOffsetVal = entry.find("OffsetValue");
509 if (findOffsetVal != entry.end())
510 {
511 offsetVal = std::visit(VariantToDoubleVisitor(), findOffsetVal->second);
512 }
513
Zev Weissa4d27682022-07-19 15:30:36 -0700514 readState = getPowerState(entry);
Jayashree Dhanapal84189752022-03-07 12:51:54 +0530515}
516
James Feist6ef20402019-01-07 16:45:08 -0800517void createSensors(
Ed Tanous1f978632023-02-28 18:16:39 -0800518 boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
Vikash Chandola1f847972022-09-28 09:47:32 +0000519 boost::container::flat_map<std::string, std::shared_ptr<IpmbSensor>>&
James Feist6ef20402019-01-07 16:45:08 -0800520 sensors,
521 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
522{
523 if (!dbusConnection)
524 {
525 std::cerr << "Connection not created\n";
526 return;
527 }
528 dbusConnection->async_method_call(
529 [&](boost::system::error_code ec, const ManagedObjectType& resp) {
Ed Tanousbb679322022-05-16 16:10:00 -0700530 if (ec)
531 {
532 std::cerr << "Error contacting entity manager\n";
533 return;
534 }
Zev Weiss8ba551b2022-08-12 18:21:02 -0700535 for (const auto& [path, interfaces] : resp)
Ed Tanousbb679322022-05-16 16:10:00 -0700536 {
Zev Weiss8ba551b2022-08-12 18:21:02 -0700537 for (const auto& [intf, cfg] : interfaces)
James Feist6ef20402019-01-07 16:45:08 -0800538 {
Zev Weiss054aad82022-08-18 01:37:34 -0700539 if (intf != configInterfaceName(sensorType))
James Feist6ef20402019-01-07 16:45:08 -0800540 {
Ed Tanousbb679322022-05-16 16:10:00 -0700541 continue;
James Feist6ef20402019-01-07 16:45:08 -0800542 }
Zev Weiss8ba551b2022-08-12 18:21:02 -0700543 std::string name = loadVariant<std::string>(cfg, "Name");
Ed Tanousbb679322022-05-16 16:10:00 -0700544
545 std::vector<thresholds::Threshold> sensorThresholds;
Zev Weiss8ba551b2022-08-12 18:21:02 -0700546 if (!parseThresholdsFromConfig(interfaces, sensorThresholds))
Ed Tanousbb679322022-05-16 16:10:00 -0700547 {
548 std::cerr << "error populating thresholds for " << name
549 << "\n";
550 }
Zev Weiss8ba551b2022-08-12 18:21:02 -0700551 uint8_t deviceAddress = loadVariant<uint8_t>(cfg, "Address");
Ed Tanousbb679322022-05-16 16:10:00 -0700552
553 std::string sensorClass =
Zev Weiss8ba551b2022-08-12 18:21:02 -0700554 loadVariant<std::string>(cfg, "Class");
Ed Tanousbb679322022-05-16 16:10:00 -0700555
556 uint8_t hostSMbusIndex = hostSMbusIndexDefault;
Zev Weiss8ba551b2022-08-12 18:21:02 -0700557 auto findSmType = cfg.find("HostSMbusIndex");
558 if (findSmType != cfg.end())
Ed Tanousbb679322022-05-16 16:10:00 -0700559 {
560 hostSMbusIndex = std::visit(VariantToUnsignedIntVisitor(),
561 findSmType->second);
562 }
563
Zev Weiss8569bf22022-10-11 15:37:44 -0700564 float pollRate = getPollRate(cfg, pollRateDefault);
Ed Tanousbb679322022-05-16 16:10:00 -0700565
Jayashree Dhanapal6ee62942021-12-14 15:22:23 +0530566 uint8_t ipmbBusIndex = ipmbBusIndexDefault;
567 auto findBusType = cfg.find("Bus");
568 if (findBusType != cfg.end())
569 {
570 ipmbBusIndex = std::visit(VariantToUnsignedIntVisitor(),
571 findBusType->second);
572 std::cerr << "Ipmb Bus Index for " << name << " is "
573 << static_cast<int>(ipmbBusIndex) << "\n";
574 }
575
Ed Tanousbb679322022-05-16 16:10:00 -0700576 /* Default sensor type is "temperature" */
577 std::string sensorTypeName = "temperature";
Zev Weiss8ba551b2022-08-12 18:21:02 -0700578 auto findType = cfg.find("SensorType");
579 if (findType != cfg.end())
Ed Tanousbb679322022-05-16 16:10:00 -0700580 {
581 sensorTypeName =
582 std::visit(VariantToStringVisitor(), findType->second);
583 }
584
585 auto& sensor = sensors[name];
Vikash Chandola1f847972022-09-28 09:47:32 +0000586 sensor = nullptr;
587 sensor = std::make_shared<IpmbSensor>(
Zev Weiss8ba551b2022-08-12 18:21:02 -0700588 dbusConnection, io, name, path, objectServer,
Ed Tanousbb679322022-05-16 16:10:00 -0700589 std::move(sensorThresholds), deviceAddress, hostSMbusIndex,
590 pollRate, sensorTypeName);
591
Zev Weiss8ba551b2022-08-12 18:21:02 -0700592 sensor->parseConfigValues(cfg);
Ed Tanousbb679322022-05-16 16:10:00 -0700593 if (!(sensor->sensorClassType(sensorClass)))
594 {
595 continue;
596 }
597 sensor->sensorSubType(sensorTypeName);
598 sensor->init();
James Feist6ef20402019-01-07 16:45:08 -0800599 }
Ed Tanousbb679322022-05-16 16:10:00 -0700600 }
James Feist6ef20402019-01-07 16:45:08 -0800601 },
JeffLin2c5a1f22022-10-05 15:19:09 +0800602 entityManagerName, "/xyz/openbmc_project/inventory",
603 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
James Feist6ef20402019-01-07 16:45:08 -0800604}
605
Jayashree Dhanapal3746c552022-03-21 14:45:52 +0530606void sdrHandler(sdbusplus::message_t& message,
607 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
608{
609 std::string objectName;
610 SensorBaseConfigMap values;
611 message.read(objectName, values);
612
613 auto findBus = values.find("Bus");
614 if (findBus == values.end())
615 {
616 return;
617 }
618
619 uint8_t busIndex = loadVariant<uint8_t>(values, "Bus");
620
621 auto& sdrsen = sdrsensor[busIndex];
622 sdrsen = nullptr;
623 sdrsen = std::make_shared<IpmbSDRDevice>(dbusConnection, busIndex);
624 sdrsen->getSDRRepositoryInfo();
625}
626
Patrick Williams92f8f512022-07-22 19:26:55 -0500627void reinitSensors(sdbusplus::message_t& message)
James Feistf7e2c5d2019-02-13 17:27:51 -0800628{
James Feist0d4f2bd2019-03-05 13:15:40 -0800629 constexpr const size_t reinitWaitSeconds = 2;
James Feistf7e2c5d2019-02-13 17:27:51 -0800630 std::string objectName;
James Feist52497fd2019-06-07 13:01:33 -0700631 boost::container::flat_map<std::string, std::variant<std::string>> values;
James Feistf7e2c5d2019-02-13 17:27:51 -0800632 message.read(objectName, values);
James Feist0d4f2bd2019-03-05 13:15:40 -0800633
James Feist52497fd2019-06-07 13:01:33 -0700634 auto findStatus = values.find(power::property);
635 if (findStatus != values.end())
James Feistf7e2c5d2019-02-13 17:27:51 -0800636 {
Zev Weiss6c106d62022-08-17 20:50:00 -0700637 bool powerStatus =
638 std::get<std::string>(findStatus->second).ends_with(".Running");
James Feistf7e2c5d2019-02-13 17:27:51 -0800639 if (powerStatus)
640 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800641 if (!initCmdTimer)
James Feistf7e2c5d2019-02-13 17:27:51 -0800642 {
James Feist0d4f2bd2019-03-05 13:15:40 -0800643 // this should be impossible
644 return;
James Feistf7e2c5d2019-02-13 17:27:51 -0800645 }
James Feist0d4f2bd2019-03-05 13:15:40 -0800646 // we seem to send this command too fast sometimes, wait before
647 // sending
648 initCmdTimer->expires_from_now(
Ed Tanous9b4a20e2022-09-06 08:47:11 -0700649 std::chrono::seconds(reinitWaitSeconds));
James Feist0d4f2bd2019-03-05 13:15:40 -0800650
651 initCmdTimer->async_wait([](const boost::system::error_code ec) {
652 if (ec == boost::asio::error::operation_aborted)
653 {
654 return; // we're being canceled
655 }
656
Zev Weiss8ba551b2022-08-12 18:21:02 -0700657 for (const auto& [name, sensor] : sensors)
James Feist0d4f2bd2019-03-05 13:15:40 -0800658 {
Zev Weiss8ba551b2022-08-12 18:21:02 -0700659 if (sensor)
James Feist0d4f2bd2019-03-05 13:15:40 -0800660 {
Zev Weiss8ba551b2022-08-12 18:21:02 -0700661 sensor->runInitCmd();
James Feist0d4f2bd2019-03-05 13:15:40 -0800662 }
663 }
664 });
James Feistf7e2c5d2019-02-13 17:27:51 -0800665 }
666 }
667}
668
James Feistb6c0b912019-07-09 12:21:44 -0700669int main()
James Feist6ef20402019-01-07 16:45:08 -0800670{
671
Ed Tanous1f978632023-02-28 18:16:39 -0800672 boost::asio::io_context io;
James Feist6ef20402019-01-07 16:45:08 -0800673 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
Ed Tanous14ed5e92022-07-12 15:50:23 -0700674 sdbusplus::asio::object_server objectServer(systemBus, true);
675 objectServer.add_manager("/xyz/openbmc_project/sensors");
James Feist6ef20402019-01-07 16:45:08 -0800676 systemBus->request_name("xyz.openbmc_project.IpmbSensor");
James Feist6ef20402019-01-07 16:45:08 -0800677
Ed Tanous9b4a20e2022-09-06 08:47:11 -0700678 initCmdTimer = std::make_unique<boost::asio::steady_timer>(io);
James Feist0d4f2bd2019-03-05 13:15:40 -0800679
James Feist6ef20402019-01-07 16:45:08 -0800680 io.post([&]() { createSensors(io, objectServer, sensors, systemBus); });
681
Ed Tanous9b4a20e2022-09-06 08:47:11 -0700682 boost::asio::steady_timer configTimer(io);
James Feist6ef20402019-01-07 16:45:08 -0800683
Patrick Williams92f8f512022-07-22 19:26:55 -0500684 std::function<void(sdbusplus::message_t&)> eventHandler =
685 [&](sdbusplus::message_t&) {
Ed Tanous9b4a20e2022-09-06 08:47:11 -0700686 configTimer.expires_from_now(std::chrono::seconds(1));
Ed Tanousbb679322022-05-16 16:10:00 -0700687 // create a timer because normally multiple properties change
688 configTimer.async_wait([&](const boost::system::error_code& ec) {
689 if (ec == boost::asio::error::operation_aborted)
690 {
691 return; // we're being canceled
692 }
693 createSensors(io, objectServer, sensors, systemBus);
694 if (sensors.empty())
695 {
696 std::cout << "Configuration not detected\n";
697 }
698 });
699 };
James Feist6ef20402019-01-07 16:45:08 -0800700
Zev Weiss214d9712022-08-12 12:54:31 -0700701 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
702 setupPropertiesChangedMatches(
Zev Weiss054aad82022-08-18 01:37:34 -0700703 *systemBus, std::to_array<const char*>({sensorType}), eventHandler);
James Feist6ef20402019-01-07 16:45:08 -0800704
Patrick Williams92f8f512022-07-22 19:26:55 -0500705 sdbusplus::bus::match_t powerChangeMatch(
706 static_cast<sdbusplus::bus_t&>(*systemBus),
James Feist52497fd2019-06-07 13:01:33 -0700707 "type='signal',interface='" + std::string(properties::interface) +
708 "',path='" + std::string(power::path) + "',arg0='" +
709 std::string(power::interface) + "'",
James Feistf7e2c5d2019-02-13 17:27:51 -0800710 reinitSensors);
711
Jayashree Dhanapal3746c552022-03-21 14:45:52 +0530712 auto matchSignal = std::make_shared<sdbusplus::bus::match_t>(
713 static_cast<sdbusplus::bus_t&>(*systemBus),
714 "type='signal',member='PropertiesChanged',path_namespace='" +
715 std::string(inventoryPath) + "',arg0namespace='" +
716 configInterfaceName(sdrInterface) + "'",
717 [&systemBus](sdbusplus::message_t& msg) {
718 sdrHandler(msg, systemBus);
719 });
720
Bruce Lee1263c3d2021-06-04 15:16:33 +0800721 setupManufacturingModeMatch(*systemBus);
James Feist6ef20402019-01-07 16:45:08 -0800722 io.run();
Zhikui Rene76a5a62021-07-09 15:16:32 -0700723 return 0;
James Feist6ef20402019-01-07 16:45:08 -0800724}