Fix issues and support signed sensor values
Sensor will get "disable" when the command "ipmitool sdr elist" is
executed that if sensorReadingType is 0x6F.
sensor_units_1 is always set to 0 currently. To support the display of
signed sensor values, we add the attribute "sensorUnits1" to the sensor
mapping yaml. This attribute can be used to determine whether the
sensor is signed.
It were making negative values 0 in get::readingData(). Fix the issue
by using a int32_t and add an overflow check.
Change-Id: I705defcf18805db9ada7d0de0738a59aedab61df
Signed-off-by: Tony Lee <tony.lee@quantatw.com>
diff --git a/include/ipmid/types.hpp b/include/ipmid/types.hpp
index 6eec66b..1705335 100644
--- a/include/ipmid/types.hpp
+++ b/include/ipmid/types.hpp
@@ -134,6 +134,7 @@
using EntityType = uint8_t;
using EntityInst = uint8_t;
using SensorName = std::string;
+using SensorUnits1 = uint8_t;
enum class Mutability
{
@@ -168,6 +169,7 @@
Exponent exponentR;
bool hasScale;
Scale scale;
+ SensorUnits1 sensorUnits1;
Unit unit;
std::function<uint8_t(SetSensorReadingReq&, const Info&)> updateFunc;
std::function<GetSensorResponse(const Info&)> getFunc;
diff --git a/scripts/sensor-example.yaml b/scripts/sensor-example.yaml
index 9760cd0..bddd2e6 100644
--- a/scripts/sensor-example.yaml
+++ b/scripts/sensor-example.yaml
@@ -112,6 +112,8 @@
# Applies for analog sensors, the actual reading value for the sensor is
# Value * 10^N
scale: -3
+ # Indicate Analog Data Format, Rate unit, Modifier unit and Percentage
+ sensorUnits1 : 0x80
mutability: Mutability::Write|Mutability::Read
serviceInterface: org.freedesktop.DBus.Properties
readingType: readingData
diff --git a/scripts/writesensor.mako.cpp b/scripts/writesensor.mako.cpp
index 8b26805..813f940 100644
--- a/scripts/writesensor.mako.cpp
+++ b/scripts/writesensor.mako.cpp
@@ -49,6 +49,7 @@
offsetB = sensor.get("offsetB", 0)
bExp = sensor.get("bExp", 0)
rExp = sensor.get("rExp", 0)
+ sensorUnits1 = sensor.get("sensorUnits1", 0)
unit = sensor.get("unit", "")
scale = sensor.get("scale", 0)
hasScale = "true" if "scale" in sensor.keys() else "false"
@@ -91,6 +92,7 @@
.exponentR = ${rExp},
.hasScale = ${hasScale},
.scale = ${scale},
+ .sensorUnits1 = ${sensorUnits1},
.unit = "${unit}",
.updateFunc = ${updateFunc},
.getFunc = ${getFunc},
diff --git a/sensordatahandler.cpp b/sensordatahandler.cpp
index 06f5f42..fc74b8f 100644
--- a/sensordatahandler.cpp
+++ b/sensordatahandler.cpp
@@ -7,8 +7,6 @@
#include <ipmid/types.hpp>
#include <ipmid/utils.hpp>
#include <optional>
-#include <phosphor-logging/elog-errors.hpp>
-#include <phosphor-logging/log.hpp>
#include <sdbusplus/message/types.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
diff --git a/sensordatahandler.hpp b/sensordatahandler.hpp
index f263636..3ec1a4d 100644
--- a/sensordatahandler.hpp
+++ b/sensordatahandler.hpp
@@ -8,6 +8,8 @@
#include <ipmid/api.hpp>
#include <ipmid/types.hpp>
#include <ipmid/utils.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
#include <sdbusplus/message/types.hpp>
namespace ipmi
@@ -28,6 +30,7 @@
using Interfaces = std::vector<Interface>;
using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>;
+using namespace phosphor::logging;
/** @brief get the D-Bus service and service path
* @param[in] bus - The Dbus bus object
@@ -225,10 +228,32 @@
double value = std::get<T>(propValue) *
std::pow(10, sensorInfo.scale - sensorInfo.exponentR);
+ int32_t rawData =
+ (value - sensorInfo.scaledOffset) / sensorInfo.coefficientM;
- auto rawData = static_cast<uint8_t>((value - sensorInfo.scaledOffset) /
- sensorInfo.coefficientM);
- setReading(rawData, &response);
+ constexpr uint8_t sensorUnitsSignedBits = 2 << 6;
+ constexpr uint8_t signedDataFormat = 0x80;
+ // if sensorUnits1 [7:6] = 10b, sensor is signed
+ if ((sensorInfo.sensorUnits1 & sensorUnitsSignedBits) == signedDataFormat)
+ {
+ if (rawData > std::numeric_limits<int8_t>::max() ||
+ rawData < std::numeric_limits<int8_t>::lowest())
+ {
+ log<level::ERR>("Value out of range");
+ throw std::out_of_range("Value out of range");
+ }
+ setReading(static_cast<int8_t>(rawData), &response);
+ }
+ else
+ {
+ if (rawData > std::numeric_limits<uint8_t>::max() ||
+ rawData < std::numeric_limits<uint8_t>::lowest())
+ {
+ log<level::ERR>("Value out of range");
+ throw std::out_of_range("Value out of range");
+ }
+ setReading(static_cast<uint8_t>(rawData), &response);
+ }
if (!std::isfinite(value))
{
diff --git a/sensorhandler.cpp b/sensorhandler.cpp
index edd4806..4b6eb6e 100644
--- a/sensorhandler.cpp
+++ b/sensorhandler.cpp
@@ -706,9 +706,8 @@
/* Functional sensor case */
if (isAnalogSensor(info->propertyInterfaces.begin()->first))
{
-
- body->sensor_units_1 = 0; // unsigned, no rate, no modifier, not a %
-
+ body->sensor_units_1 = info->sensorUnits1; // default is 0. unsigned, no
+ // rate, no modifier, not a %
/* Unit info */
setUnitFieldsForObject(info, body);