blob: 62a4b8ba00e6c6963c3126de63f508e88bbb075f [file] [log] [blame]
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -05001#pragma once
2
Brandon Kim9cf85622019-06-19 12:05:08 -07003#include "config.h"
4
Patrick Venture46470a32018-09-07 19:26:25 -07005#include "sensorhandler.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07006
Vernon Mauerye08fbff2019-04-03 09:19:34 -07007#include <ipmid/api.hpp>
Vernon Mauery33250242019-03-12 16:49:26 -07008#include <ipmid/types.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -07009#include <ipmid/utils.hpp>
Tony Leec5324252019-10-31 17:24:16 +080010#include <phosphor-logging/elog-errors.hpp>
George Liu9b745a82024-07-19 09:09:36 +080011#include <phosphor-logging/lg2.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070012#include <sdbusplus/message/types.hpp>
Alexander Hansen653aec02025-11-14 13:38:08 +010013#include <xyz/openbmc_project/Sensor/Threshold/Critical/common.hpp>
14#include <xyz/openbmc_project/Sensor/Threshold/Warning/common.hpp>
Alexander Hansenf365c7f2025-11-14 12:08:34 +010015#include <xyz/openbmc_project/Sensor/Value/common.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070016
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050017#include <cmath>
18
Lei YU97140502021-09-17 13:49:43 +080019#ifdef FEATURE_SENSORS_CACHE
Lei YUa55e9ea2021-09-18 15:15:17 +080020
Lei YU97140502021-09-17 13:49:43 +080021extern ipmi::sensor::SensorCacheMap sensorCacheMap;
Lei YUa55e9ea2021-09-18 15:15:17 +080022
23// The signal's message type is 0x04 from DBus spec:
24// https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
25static constexpr auto msgTypeSignal = 0x04;
26
Lei YU97140502021-09-17 13:49:43 +080027#endif
28
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050029namespace ipmi
30{
31namespace sensor
32{
33
34using Assertion = uint16_t;
35using Deassertion = uint16_t;
36using AssertionSet = std::pair<Assertion, Deassertion>;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050037using Service = std::string;
38using Path = std::string;
39using Interface = std::string;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050040using ServicePath = std::pair<Path, Service>;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050041using Interfaces = std::vector<Interface>;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050042using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>;
Lei YU8e8152c2021-12-06 20:11:08 +080043using PropertyMap = ipmi::PropertyMap;
44
Alexander Hansenf365c7f2025-11-14 12:08:34 +010045using SensorValue = sdbusplus::common::xyz::openbmc_project::sensor::Value;
Alexander Hansen653aec02025-11-14 13:38:08 +010046using SensorThresholdWarning =
47 sdbusplus::common::xyz::openbmc_project::sensor::threshold::Warning;
48using SensorThresholdCritical =
49 sdbusplus::common::xyz::openbmc_project::sensor::threshold::Critical;
Alexander Hansenf365c7f2025-11-14 12:08:34 +010050
Tony Leec5324252019-10-31 17:24:16 +080051using namespace phosphor::logging;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050052
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050053/** @brief Make assertion set from input data
54 * @param[in] cmdData - Input sensor data
55 * @return pair of assertion and deassertion set
56 */
57AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData);
58
59/** @brief send the message to DBus
60 * @param[in] msg - message to send
61 * @return failure status in IPMI error code
62 */
George Liu23c868c2025-07-04 09:31:35 +080063ipmi::Cc updateToDbus(IpmiUpdateData& msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050064
Tom Joseph816e92b2017-09-06 19:23:00 +053065namespace get
66{
67
Tom Josephb0adbcd2018-01-24 11:51:29 +053068/** @brief Populate sensor name from the D-Bus property associated with the
69 * sensor. In the example entry from the yaml, the name of the D-bus
70 * property "AttemptsLeft" is the sensor name.
71 *
72 * 0x07:
73 * sensorType: 195
74 * path: /xyz/openbmc_project/state/host0
75 * sensorReadingType: 0x6F
76 * serviceInterface: org.freedesktop.DBus.Properties
77 * readingType: readingAssertion
78 * sensorNamePattern: nameProperty
79 * interfaces:
80 * xyz.openbmc_project.Control.Boot.RebootAttempts:
81 * AttemptsLeft:
82 * Offsets:
83 * 0xFF:
84 * type: uint32_t
85 *
86 *
87 * @param[in] sensorInfo - Dbus info related to sensor.
88 *
89 * @return On success return the sensor name for the sensor.
90 */
91inline SensorName nameProperty(const Info& sensorInfo)
92{
93 return sensorInfo.propertyInterfaces.begin()->second.begin()->first;
94}
95
96/** @brief Populate sensor name from the D-Bus object associated with the
97 * sensor. If the object path is /system/chassis/motherboard/dimm0 then
98 * the leaf dimm0 is considered as the sensor name.
99 *
100 * @param[in] sensorInfo - Dbus info related to sensor.
101 *
102 * @return On success return the sensor name for the sensor.
103 */
104inline SensorName nameLeaf(const Info& sensorInfo)
105{
106 return sensorInfo.sensorPath.substr(
Patrick Venture0b02be92018-08-31 11:55:55 -0700107 sensorInfo.sensorPath.find_last_of('/') + 1,
108 sensorInfo.sensorPath.length());
Tom Josephb0adbcd2018-01-24 11:51:29 +0530109}
110
111/** @brief Populate sensor name from the D-Bus object associated with the
Lotus Xu2101a442020-12-24 16:01:56 +0800112 * sensor and the property.
113 * If the object path is /xyz/openbmc_project/inventory/Fan0 and
114 * the property is Present, the leaf Fan0 and the Property is
115 * joined to Fan0_Present as the sensor name.
116 *
117 * @param[in] sensorInfo - Dbus info related to sensor.
118 *
119 * @return On success return the sensor name for the sensor.
120 */
121inline SensorName nameLeafProperty(const Info& sensorInfo)
122{
123 return nameLeaf(sensorInfo) + "_" + nameProperty(sensorInfo);
124}
125
126/** @brief Populate sensor name from the D-Bus object associated with the
Tom Josephb0adbcd2018-01-24 11:51:29 +0530127 * sensor. If the object path is /system/chassis/motherboard/cpu0/core0
128 * then the sensor name is cpu0_core0. The leaf and the parent is put
129 * together to get the sensor name.
130 *
131 * @param[in] sensorInfo - Dbus info related to sensor.
132 *
133 * @return On success return the sensor name for the sensor.
134 */
135SensorName nameParentLeaf(const Info& sensorInfo);
136
Tom Joseph816e92b2017-09-06 19:23:00 +0530137/**
138 * @brief Helper function to map the dbus info to sensor's assertion status
139 * for the get sensor reading command.
140 *
141 * @param[in] sensorInfo - Dbus info related to sensor.
142 * @param[in] path - Dbus object path.
143 * @param[in] interface - Dbus interface.
144 *
145 * @return Response for get sensor reading command.
146 */
147GetSensorResponse mapDbusToAssertion(const Info& sensorInfo,
148 const InstancePath& path,
149 const DbusInterface& interface);
150
Lei YU8c2c0482021-09-16 17:28:28 +0800151#ifndef FEATURE_SENSORS_CACHE
Tom Joseph816e92b2017-09-06 19:23:00 +0530152/**
153 * @brief Map the Dbus info to sensor's assertion status in the Get sensor
154 * reading command response.
155 *
156 * @param[in] sensorInfo - Dbus info related to sensor.
157 *
158 * @return Response for get sensor reading command.
159 */
160GetSensorResponse assertion(const Info& sensorInfo);
161
Tom Josephe4014fc2017-09-06 23:57:36 +0530162/**
163 * @brief Maps the Dbus info to the reading field in the Get sensor reading
164 * command response.
165 *
166 * @param[in] sensorInfo - Dbus info related to sensor.
167 *
168 * @return Response for get sensor reading command.
169 */
170GetSensorResponse eventdata2(const Info& sensorInfo);
171
Tom Joseph295f17e2017-09-07 00:09:46 +0530172/**
173 * @brief readingAssertion is a case where the entire assertion state field
174 * serves as the sensor value.
175 *
176 * @tparam T - type of the dbus property related to sensor.
177 * @param[in] sensorInfo - Dbus info related to sensor.
178 *
179 * @return Response for get sensor reading command.
180 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700181template <typename T>
Tom Joseph295f17e2017-09-07 00:09:46 +0530182GetSensorResponse readingAssertion(const Info& sensorInfo)
183{
Patrick Williams5d82f472022-07-22 19:26:53 -0500184 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700185 GetSensorResponse response{};
Tom Joseph295f17e2017-09-07 00:09:46 +0530186
George Liue6b2be52025-08-19 13:57:43 +0800187 enableScanning(response);
George Liu08d3add2024-11-18 15:22:43 +0800188 try
189 {
190 auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
191 sensorInfo.sensorPath);
192 auto propValue = ipmi::getDbusProperty(
193 bus, service, sensorInfo.sensorPath,
194 sensorInfo.propertyInterfaces.begin()->first,
195 sensorInfo.propertyInterfaces.begin()->second.begin()->first);
Jeremy Kerr3dc35582020-05-17 15:47:07 +0800196
George Liu08d3add2024-11-18 15:22:43 +0800197 setAssertionBytes(static_cast<uint16_t>(std::get<T>(propValue)),
George Liue6b2be52025-08-19 13:57:43 +0800198 response);
George Liu08d3add2024-11-18 15:22:43 +0800199 }
200 catch (const std::exception& e)
201 {
202 lg2::error(
203 "Failed to call readingAssertion, path: {PATH}, interface: {INTERFACE}: {ERROR}",
204 "PATH", sensorInfo.sensorPath, "INTERFACE",
205 sensorInfo.sensorInterface, "ERROR", e);
206 }
Tom Joseph295f17e2017-09-07 00:09:46 +0530207
208 return response;
209}
210
Tom Josephe05b2922017-09-07 00:43:16 +0530211/** @brief Map the Dbus info to the reading field in the Get sensor reading
212 * command response
213 *
214 * @tparam T - type of the dbus property related to sensor.
215 * @param[in] sensorInfo - Dbus info related to sensor.
216 *
217 * @return Response for get sensor reading command.
218 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700219template <typename T>
Tom Josephe05b2922017-09-07 00:43:16 +0530220GetSensorResponse readingData(const Info& sensorInfo)
221{
Patrick Williams5d82f472022-07-22 19:26:53 -0500222 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Tom Josephe05b2922017-09-07 00:43:16 +0530223
Sui Chen4cc42552019-09-11 10:28:35 -0700224 GetSensorResponse response{};
225
George Liue6b2be52025-08-19 13:57:43 +0800226 enableScanning(response);
Tom Josephe05b2922017-09-07 00:43:16 +0530227
Patrick Venture0b02be92018-08-31 11:55:55 -0700228 auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
Tom Josephe05b2922017-09-07 00:43:16 +0530229 sensorInfo.sensorPath);
230
Brandon Kim9cf85622019-06-19 12:05:08 -0700231#ifdef UPDATE_FUNCTIONAL_ON_FAIL
232 // Check the OperationalStatus interface for functional property
Alexander Hansenf365c7f2025-11-14 12:08:34 +0100233 if (sensorInfo.propertyInterfaces.begin()->first == SensorValue::interface)
Brandon Kim9cf85622019-06-19 12:05:08 -0700234 {
235 bool functional = true;
236 try
237 {
238 auto funcValue = ipmi::getDbusProperty(
239 bus, service, sensorInfo.sensorPath,
240 "xyz.openbmc_project.State.Decorator.OperationalStatus",
241 "Functional");
242 functional = std::get<bool>(funcValue);
243 }
244 catch (...)
245 {
246 // No-op if Functional property could not be found since this
247 // check is only valid for Sensor.Value read for hwmonio
248 }
249 if (!functional)
250 {
251 throw SensorFunctionalError();
252 }
253 }
254#endif
255
George Liu08d3add2024-11-18 15:22:43 +0800256 double value{};
257 try
258 {
259 auto propValue = ipmi::getDbusProperty(
260 bus, service, sensorInfo.sensorPath,
261 sensorInfo.propertyInterfaces.begin()->first,
262 sensorInfo.propertyInterfaces.begin()->second.begin()->first);
Tom Josephe05b2922017-09-07 00:43:16 +0530263
George Liu08d3add2024-11-18 15:22:43 +0800264 value = std::get<T>(propValue) *
265 std::pow(10, sensorInfo.scale - sensorInfo.exponentR);
266 }
267 catch (const std::exception& e)
268 {
269 lg2::error(
270 "Failed to call readingData, path: {PATH}, interface: {INTERFACE}: {ERROR}",
271 "PATH", sensorInfo.sensorPath, "INTERFACE",
272 sensorInfo.sensorInterface, "ERROR", e);
273 return response;
274 }
275
Patrick Williams1318a5e2024-08-16 15:19:54 -0400276 int32_t rawData =
277 (value - sensorInfo.scaledOffset) / sensorInfo.coefficientM;
Tom Josephe05b2922017-09-07 00:43:16 +0530278
Tony Leec5324252019-10-31 17:24:16 +0800279 constexpr uint8_t sensorUnitsSignedBits = 2 << 6;
280 constexpr uint8_t signedDataFormat = 0x80;
281 // if sensorUnits1 [7:6] = 10b, sensor is signed
Willy Tu9154caa2021-12-02 02:28:54 -0800282 int32_t minClamp;
283 int32_t maxClamp;
Tony Leec5324252019-10-31 17:24:16 +0800284 if ((sensorInfo.sensorUnits1 & sensorUnitsSignedBits) == signedDataFormat)
285 {
Willy Tu9154caa2021-12-02 02:28:54 -0800286 minClamp = std::numeric_limits<int8_t>::lowest();
287 maxClamp = std::numeric_limits<int8_t>::max();
Tony Leec5324252019-10-31 17:24:16 +0800288 }
289 else
290 {
Willy Tu9154caa2021-12-02 02:28:54 -0800291 minClamp = std::numeric_limits<uint8_t>::lowest();
292 maxClamp = std::numeric_limits<uint8_t>::max();
Tony Leec5324252019-10-31 17:24:16 +0800293 }
Willy Tu9154caa2021-12-02 02:28:54 -0800294 setReading(static_cast<uint8_t>(std::clamp(rawData, minClamp, maxClamp)),
George Liue6b2be52025-08-19 13:57:43 +0800295 response);
Tom Josephe05b2922017-09-07 00:43:16 +0530296
Konstantin Aladyshevf93b29c2021-05-05 14:49:14 +0300297 if (!std::isfinite(value))
298 {
299 response.readingOrStateUnavailable = 1;
300 }
301
Konstantin Aladyshev778f6592021-11-02 11:28:25 +0300302 bool critAlarmHigh;
303 try
304 {
305 critAlarmHigh = std::get<bool>(ipmi::getDbusProperty(
306 bus, service, sensorInfo.sensorPath,
Alexander Hansen653aec02025-11-14 13:38:08 +0100307 SensorThresholdCritical::interface,
308 SensorThresholdCritical::property_names::critical_alarm_high));
Konstantin Aladyshev778f6592021-11-02 11:28:25 +0300309 }
310 catch (const std::exception& e)
311 {
312 critAlarmHigh = false;
313 }
314 bool critAlarmLow;
315 try
316 {
317 critAlarmLow = std::get<bool>(ipmi::getDbusProperty(
318 bus, service, sensorInfo.sensorPath,
Alexander Hansen653aec02025-11-14 13:38:08 +0100319 SensorThresholdCritical::interface,
320 SensorThresholdCritical::property_names::critical_alarm_low));
Konstantin Aladyshev778f6592021-11-02 11:28:25 +0300321 }
322 catch (const std::exception& e)
323 {
324 critAlarmLow = false;
325 }
326 bool warningAlarmHigh;
327 try
328 {
329 warningAlarmHigh = std::get<bool>(ipmi::getDbusProperty(
330 bus, service, sensorInfo.sensorPath,
Alexander Hansen653aec02025-11-14 13:38:08 +0100331 SensorThresholdWarning::interface,
332 SensorThresholdWarning::property_names::warning_alarm_high));
Konstantin Aladyshev778f6592021-11-02 11:28:25 +0300333 }
334 catch (const std::exception& e)
335 {
336 warningAlarmHigh = false;
337 }
338 bool warningAlarmLow;
339 try
340 {
341 warningAlarmLow = std::get<bool>(ipmi::getDbusProperty(
342 bus, service, sensorInfo.sensorPath,
Alexander Hansen653aec02025-11-14 13:38:08 +0100343 SensorThresholdWarning::interface,
344 SensorThresholdWarning::property_names::warning_alarm_low));
Konstantin Aladyshev778f6592021-11-02 11:28:25 +0300345 }
346 catch (const std::exception& e)
347 {
348 warningAlarmLow = false;
349 }
350 response.thresholdLevelsStates =
YouPengWu19c962b2025-10-17 19:00:18 +0800351 0xC0 | (static_cast<uint8_t>(warningAlarmLow) << 0) |
352 (static_cast<uint8_t>(critAlarmLow) << 1) |
353 (static_cast<uint8_t>(warningAlarmHigh) << 3) |
354 (static_cast<uint8_t>(critAlarmHigh) << 4);
Tom Josephe05b2922017-09-07 00:43:16 +0530355 return response;
356}
357
Lei YU8c2c0482021-09-16 17:28:28 +0800358#else
359
Lei YU8c2c0482021-09-16 17:28:28 +0800360/**
361 * @brief Map the Dbus info to sensor's assertion status in the Get sensor
362 * reading command response.
363 *
364 * @param[in] id - The sensor id
365 * @param[in] sensorInfo - Dbus info related to sensor.
366 * @param[in] msg - Dbus message from match callback.
367 *
368 * @return Response for get sensor reading command.
369 */
370std::optional<GetSensorResponse> assertion(uint8_t id, const Info& sensorInfo,
Lei YU8e8152c2021-12-06 20:11:08 +0800371 const PropertyMap& properties);
Lei YU8c2c0482021-09-16 17:28:28 +0800372
373/**
374 * @brief Maps the Dbus info to the reading field in the Get sensor reading
375 * command response.
376 *
377 * @param[in] id - The sensor id
378 * @param[in] sensorInfo - Dbus info related to sensor.
379 * @param[in] msg - Dbus message from match callback.
380 *
381 * @return Response for get sensor reading command.
382 */
383std::optional<GetSensorResponse> eventdata2(uint8_t id, const Info& sensorInfo,
Lei YU8e8152c2021-12-06 20:11:08 +0800384 const PropertyMap& properties);
Lei YU8c2c0482021-09-16 17:28:28 +0800385
386/**
387 * @brief readingAssertion is a case where the entire assertion state field
388 * serves as the sensor value.
389 *
390 * @tparam T - type of the dbus property related to sensor.
391 * @param[in] id - The sensor id
392 * @param[in] sensorInfo - Dbus info related to sensor.
393 * @param[in] msg - Dbus message from match callback.
394 *
395 * @return Response for get sensor reading command.
396 */
397template <typename T>
Patrick Williams1318a5e2024-08-16 15:19:54 -0400398std::optional<GetSensorResponse> readingAssertion(
399 uint8_t id, const Info& sensorInfo, const PropertyMap& properties)
Lei YU8c2c0482021-09-16 17:28:28 +0800400{
Lei YU7d720342021-09-18 18:39:09 +0800401 GetSensorResponse response{};
George Liue6b2be52025-08-19 13:57:43 +0800402 enableScanning(response);
Lei YU7d720342021-09-18 18:39:09 +0800403
Lei YU7d720342021-09-18 18:39:09 +0800404 auto iter = properties.find(
405 sensorInfo.propertyInterfaces.begin()->second.begin()->first);
406 if (iter == properties.end())
407 {
408 return {};
409 }
410
411 setAssertionBytes(static_cast<uint16_t>(std::get<T>(iter->second)),
George Liue6b2be52025-08-19 13:57:43 +0800412 response);
Lei YU7d720342021-09-18 18:39:09 +0800413
414 if (!sensorCacheMap[id].has_value())
415 {
416 sensorCacheMap[id] = SensorData{};
417 }
418 sensorCacheMap[id]->response = response;
419 return response;
Lei YU8c2c0482021-09-16 17:28:28 +0800420}
421
422/** @brief Get sensor reading from the dbus message from match
423 *
424 * @tparam T - type of the dbus property related to sensor.
425 * @param[in] id - The sensor id
426 * @param[in] sensorInfo - Dbus info related to sensor.
427 * @param[in] msg - Dbus message from match callback.
428 *
429 * @return Response for get sensor reading command.
430 */
431template <typename T>
432std::optional<GetSensorResponse> readingData(uint8_t id, const Info& sensorInfo,
Lei YU8e8152c2021-12-06 20:11:08 +0800433 const PropertyMap& properties)
Lei YU8c2c0482021-09-16 17:28:28 +0800434{
Lei YU8e8152c2021-12-06 20:11:08 +0800435 auto iter = properties.find("Functional");
436 if (iter != properties.end())
Lei YUa55e9ea2021-09-18 15:15:17 +0800437 {
Lei YU8e8152c2021-12-06 20:11:08 +0800438 sensorCacheMap[id]->functional = std::get<bool>(iter->second);
Lei YUa55e9ea2021-09-18 15:15:17 +0800439 }
Lei YU8e8152c2021-12-06 20:11:08 +0800440 iter = properties.find("Available");
441 if (iter != properties.end())
442 {
443 sensorCacheMap[id]->available = std::get<bool>(iter->second);
444 }
445#ifdef UPDATE_FUNCTIONAL_ON_FAIL
446 if (sensorCacheMap[id])
447 {
448 if (!sensorCacheMap[id]->functional)
449 {
450 throw SensorFunctionalError();
451 }
452 }
453#endif
Lei YU97140502021-09-17 13:49:43 +0800454
455 GetSensorResponse response{};
456
George Liue6b2be52025-08-19 13:57:43 +0800457 enableScanning(response);
Lei YU97140502021-09-17 13:49:43 +0800458
Lei YU8e8152c2021-12-06 20:11:08 +0800459 iter = properties.find(
Lei YU97140502021-09-17 13:49:43 +0800460 sensorInfo.propertyInterfaces.begin()->second.begin()->first);
461 if (iter == properties.end())
462 {
463 return {};
464 }
465
466 double value = std::get<T>(iter->second) *
467 std::pow(10, sensorInfo.scale - sensorInfo.exponentR);
Patrick Williams1318a5e2024-08-16 15:19:54 -0400468 int32_t rawData =
469 (value - sensorInfo.scaledOffset) / sensorInfo.coefficientM;
Lei YU97140502021-09-17 13:49:43 +0800470
471 constexpr uint8_t sensorUnitsSignedBits = 2 << 6;
472 constexpr uint8_t signedDataFormat = 0x80;
473 // if sensorUnits1 [7:6] = 10b, sensor is signed
474 if ((sensorInfo.sensorUnits1 & sensorUnitsSignedBits) == signedDataFormat)
475 {
476 if (rawData > std::numeric_limits<int8_t>::max() ||
477 rawData < std::numeric_limits<int8_t>::lowest())
478 {
George Liu9b745a82024-07-19 09:09:36 +0800479 lg2::error("Value out of range");
Lei YU97140502021-09-17 13:49:43 +0800480 throw std::out_of_range("Value out of range");
481 }
George Liue6b2be52025-08-19 13:57:43 +0800482 setReading(static_cast<int8_t>(rawData), response);
Lei YU97140502021-09-17 13:49:43 +0800483 }
484 else
485 {
486 if (rawData > std::numeric_limits<uint8_t>::max() ||
487 rawData < std::numeric_limits<uint8_t>::lowest())
488 {
George Liu9b745a82024-07-19 09:09:36 +0800489 lg2::error("Value out of range");
Lei YU97140502021-09-17 13:49:43 +0800490 throw std::out_of_range("Value out of range");
491 }
George Liue6b2be52025-08-19 13:57:43 +0800492 setReading(static_cast<uint8_t>(rawData), response);
Lei YU97140502021-09-17 13:49:43 +0800493 }
494
495 if (!std::isfinite(value))
496 {
497 response.readingOrStateUnavailable = 1;
498 }
499
500 if (!sensorCacheMap[id].has_value())
501 {
502 sensorCacheMap[id] = SensorData{};
503 }
504 sensorCacheMap[id]->response = response;
505
506 return response;
Lei YU8c2c0482021-09-16 17:28:28 +0800507}
508
509#endif // FEATURE_SENSORS_CACHE
510
Patrick Venture0b02be92018-08-31 11:55:55 -0700511} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530512
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500513namespace set
514{
515
516/** @brief Make a DBus message for a Dbus call
517 * @param[in] updateInterface - Interface name
518 * @param[in] sensorPath - Path of the sensor
519 * @param[in] command - command to be executed
520 * @param[in] sensorInterface - DBus interface of sensor
521 * @return a dbus message
522 */
523IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
524 const std::string& sensorPath,
525 const std::string& command,
526 const std::string& sensorInterface);
527
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500528/** @brief Update d-bus based on assertion type sensor data
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500529 * @param[in] cmdData - input sensor data
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500530 * @param[in] sensorInfo - sensor d-bus info
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500531 * @return a IPMI error code
532 */
George Liu23c868c2025-07-04 09:31:35 +0800533ipmi::Cc assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500534
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500535/** @brief Update d-bus based on a reading assertion
536 * @tparam T - type of d-bus property mapping this sensor
537 * @param[in] cmdData - input sensor data
538 * @param[in] sensorInfo - sensor d-bus info
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500539 * @return a IPMI error code
540 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700541template <typename T>
George Liu23c868c2025-07-04 09:31:35 +0800542ipmi::Cc readingAssertion(const SetSensorReadingReq& cmdData,
543 const Info& sensorInfo)
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500544{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400545 auto msg =
546 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath,
547 "Set", sensorInfo.sensorInterface);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500548
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500549 const auto& interface = sensorInfo.propertyInterfaces.begin();
550 msg.append(interface->first);
551 for (const auto& property : interface->second)
552 {
553 msg.append(property.first);
Patrick Williams1318a5e2024-08-16 15:19:54 -0400554 std::variant<T> value = static_cast<T>(
555 (cmdData.assertOffset8_14 << 8) | cmdData.assertOffset0_7);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500556 msg.append(value);
557 }
558 return updateToDbus(msg);
559}
560
Emily Shaffercc941e12017-06-14 13:06:26 -0700561/** @brief Update d-bus based on a discrete reading
562 * @param[in] cmdData - input sensor data
563 * @param[in] sensorInfo - sensor d-bus info
564 * @return an IPMI error code
565 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700566template <typename T>
George Liu23c868c2025-07-04 09:31:35 +0800567ipmi::Cc readingData(const SetSensorReadingReq& cmdData, const Info& sensorInfo)
Emily Shaffercc941e12017-06-14 13:06:26 -0700568{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500569 T raw_value = (sensorInfo.coefficientM * cmdData.reading) +
570 sensorInfo.scaledOffset;
Tom Joseph22102152018-03-02 18:46:39 +0530571
Patrick Venture586d35b2018-09-07 19:56:18 -0700572 raw_value *= std::pow(10, sensorInfo.exponentR - sensorInfo.scale);
Tom Joseph22102152018-03-02 18:46:39 +0530573
Patrick Williams1318a5e2024-08-16 15:19:54 -0400574 auto msg =
575 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath,
576 "Set", sensorInfo.sensorInterface);
Emily Shaffercc941e12017-06-14 13:06:26 -0700577
578 const auto& interface = sensorInfo.propertyInterfaces.begin();
579 msg.append(interface->first);
580
Emily Shaffercc941e12017-06-14 13:06:26 -0700581 for (const auto& property : interface->second)
582 {
583 msg.append(property.first);
Vernon Mauery16b86932019-05-01 08:36:11 -0700584 std::variant<T> value = raw_value;
Emily Shaffercc941e12017-06-14 13:06:26 -0700585 msg.append(value);
586 }
587 return updateToDbus(msg);
588}
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500589
590/** @brief Update d-bus based on eventdata type sensor data
591 * @param[in] cmdData - input sensor data
592 * @param[in] sensorInfo - sensor d-bus info
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500593 * @return a IPMI error code
594 */
George Liu23c868c2025-07-04 09:31:35 +0800595ipmi::Cc eventdata(const SetSensorReadingReq& cmdData, const Info& sensorInfo,
596 uint8_t data);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500597
598/** @brief Update d-bus based on eventdata1 type sensor data
599 * @param[in] cmdData - input sensor data
600 * @param[in] sensorInfo - sensor d-bus info
601 * @return a IPMI error code
602 */
George Liu23c868c2025-07-04 09:31:35 +0800603inline ipmi::Cc eventdata1(const SetSensorReadingReq& cmdData,
604 const Info& sensorInfo)
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500605{
606 return eventdata(cmdData, sensorInfo, cmdData.eventData1);
607}
608
609/** @brief Update d-bus based on eventdata2 type sensor data
610 * @param[in] cmdData - input sensor data
611 * @param[in] sensorInfo - sensor d-bus info
612 * @return a IPMI error code
613 */
George Liu23c868c2025-07-04 09:31:35 +0800614inline ipmi::Cc eventdata2(const SetSensorReadingReq& cmdData,
615 const Info& sensorInfo)
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500616{
617 return eventdata(cmdData, sensorInfo, cmdData.eventData2);
618}
619
620/** @brief Update d-bus based on eventdata3 type sensor data
621 * @param[in] cmdData - input sensor data
622 * @param[in] sensorInfo - sensor d-bus info
623 * @return a IPMI error code
624 */
George Liu23c868c2025-07-04 09:31:35 +0800625inline ipmi::Cc eventdata3(const SetSensorReadingReq& cmdData,
626 const Info& sensorInfo)
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500627{
628 return eventdata(cmdData, sensorInfo, cmdData.eventData3);
629}
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500630
Patrick Venture0b02be92018-08-31 11:55:55 -0700631} // namespace set
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500632
633namespace notify
634{
635
636/** @brief Make a DBus message for a Dbus call
637 * @param[in] updateInterface - Interface name
638 * @param[in] sensorPath - Path of the sensor
639 * @param[in] command - command to be executed
640 * @param[in] sensorInterface - DBus interface of sensor
641 * @return a dbus message
642 */
643IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
644 const std::string& sensorPath,
645 const std::string& command,
646 const std::string& sensorInterface);
647
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500648/** @brief Update d-bus based on assertion type sensor data
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500649 * @param[in] interfaceMap - sensor interface
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500650 * @param[in] cmdData - input sensor data
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500651 * @param[in] sensorInfo - sensor d-bus info
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500652 * @return a IPMI error code
653 */
George Liu23c868c2025-07-04 09:31:35 +0800654ipmi::Cc assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500655
Patrick Venture0b02be92018-08-31 11:55:55 -0700656} // namespace notify
Tom Joseph816e92b2017-09-06 19:23:00 +0530657
658namespace inventory
659{
660
661namespace get
662{
663
Lei YUff8c9b42021-10-15 14:20:57 +0800664#ifndef FEATURE_SENSORS_CACHE
665
Tom Joseph816e92b2017-09-06 19:23:00 +0530666/**
667 * @brief Map the Dbus info to sensor's assertion status in the Get sensor
668 * reading command response.
669 *
670 * @param[in] sensorInfo - Dbus info related to sensor.
671 *
672 * @return Response for get sensor reading command.
673 */
674GetSensorResponse assertion(const Info& sensorInfo);
675
Lei YUff8c9b42021-10-15 14:20:57 +0800676#else
677
678/**
679 * @brief Map the Dbus info to sensor's assertion status in the Get sensor
680 * reading command response.
681 *
682 * @param[in] id - The sensor id
683 * @param[in] sensorInfo - Dbus info related to sensor.
684 * @param[in] msg - Dbus message from match callback.
685 *
686 * @return Response for get sensor reading command.
687 */
688std::optional<GetSensorResponse> assertion(uint8_t id, const Info& sensorInfo,
Lei YU8e8152c2021-12-06 20:11:08 +0800689 const PropertyMap& properties);
Lei YUff8c9b42021-10-15 14:20:57 +0800690
691#endif
692
Tom Joseph816e92b2017-09-06 19:23:00 +0530693} // namespace get
694
695} // namespace inventory
Patrick Venture0b02be92018-08-31 11:55:55 -0700696} // namespace sensor
697} // namespace ipmi