dbus-sdr: Add hybrid sensors stack option
Because the dynamic sensor stack doesn't support non-threshold sensors,
this patch gives way for retrieving non-threshold sensors by walking
through the sensor.yaml. However, this patch filters out any threshold
sensors written in the sensor yaml file because the current dbus-sdr
already supports them.
The sensor stack has both dynamic and static in this patch, so this new
feature is named hybrid sensor stack.
Tested: Try the SDR get command
0xF9:
entityID: 0x21
entityInstance: 0
interfaces:
xyz.openbmc_project.State.Watchdog:
ExpireAction:
Offsets:
0x00:
assert: xyz.openbmc_project.State.Watchdog.Action.None
type: string
0x01:
assert: xyz.openbmc_project.State.Watchdog.Action.HardReset
type: string
0x02:
assert: xyz.openbmc_project.State.Watchdog.Action.PowerOff
type: string
0x03:
assert: xyz.openbmc_project.State.Watchdog.Action.PowerCycle
type: string
mutability: Mutability::Read
path: /xyz/openbmc_project/watchdog/host0
readingType: assertion
sensorNamePattern: nameLeaf
sensorReadingType: 0x6F
sensorType: 0x23
serviceInterface: org.freedesktop.DBus.Properties
$ ipmitool sdr get host0
Sensor ID : host0 (0xcd)
Entity ID : 33.0 (System Management Software)
Sensor Type (Discrete): Watchdog2 (0x23)
Sensor Reading : 0h
Event Message Control : Per-threshold
States Asserted : Watchdog2
[Hard reset]
Event Status : Event Messages Disabled
Assertion Events : Watchdog2
[Hard reset]
Event Enable : Event Messages Disabled
Assertions Enabled : Watchdog2
[Timer expired]
[Hard reset]
[Power down]
[Power cycle]
OEM : 0
Signed-off-by: Scron Chang <Scron.Chang@quantatw.com>
Change-Id: I1ac16f483f2f725077de9c15595195b848a224ab
diff --git a/dbus-sdr/sensorcommands.cpp b/dbus-sdr/sensorcommands.cpp
index 1f07299..bda56df 100644
--- a/dbus-sdr/sensorcommands.cpp
+++ b/dbus-sdr/sensorcommands.cpp
@@ -41,6 +41,18 @@
#include <utility>
#include <variant>
+#ifdef FEATURE_HYBRID_SENSORS
+
+#include "sensordatahandler.hpp"
+namespace ipmi
+{
+namespace sensor
+{
+extern const IdInfoMap sensors;
+} // namespace sensor
+} // namespace ipmi
+#endif
+
namespace ipmi
{
@@ -226,6 +238,19 @@
std::string sensorPath, DbusInterfaceMap& sensorMap,
int updatePeriod = sensorMapUpdatePeriod)
{
+#ifdef FEATURE_HYBRID_SENSORS
+ if (auto sensor = findStaticSensor(sensorPath);
+ sensor != ipmi::sensor::sensors.end() &&
+ getSensorEventTypeFromPath(sensorPath) !=
+ static_cast<uint8_t>(SensorEventTypeCodes::threshold))
+ {
+ // If the incoming sensor is a discrete sensor, it might fail in
+ // getManagedObjects(), return true, and use its own getFunc to get
+ // value.
+ return true;
+ }
+#endif
+
static boost::container::flat_map<
std::string, std::chrono::time_point<std::chrono::steady_clock>>
updateTimeMap;
@@ -615,6 +640,53 @@
return ipmi::response(status);
}
+#ifdef FEATURE_HYBRID_SENSORS
+ if (auto sensor = findStaticSensor(path);
+ sensor != ipmi::sensor::sensors.end() &&
+ getSensorEventTypeFromPath(path) !=
+ static_cast<uint8_t>(SensorEventTypeCodes::threshold))
+ {
+ if (ipmi::sensor::Mutability::Read !=
+ (sensor->second.mutability & ipmi::sensor::Mutability::Read))
+ {
+ return ipmi::responseIllegalCommand();
+ }
+
+ uint8_t operation;
+ try
+ {
+ ipmi::sensor::GetSensorResponse getResponse =
+ sensor->second.getFunc(sensor->second);
+
+ if (getResponse.readingOrStateUnavailable)
+ {
+ operation |= static_cast<uint8_t>(
+ IPMISensorReadingByte2::readingStateUnavailable);
+ }
+ if (getResponse.scanningEnabled)
+ {
+ operation |= static_cast<uint8_t>(
+ IPMISensorReadingByte2::sensorScanningEnable);
+ }
+ if (getResponse.allEventMessagesEnabled)
+ {
+ operation |= static_cast<uint8_t>(
+ IPMISensorReadingByte2::eventMessagesEnable);
+ }
+ return ipmi::responseSuccess(
+ getResponse.reading, operation,
+ getResponse.thresholdLevelsStates,
+ getResponse.discreteReadingSensorStates);
+ }
+ catch (const std::exception& e)
+ {
+ operation |= static_cast<uint8_t>(
+ IPMISensorReadingByte2::readingStateUnavailable);
+ return ipmi::responseSuccess(0, operation, 0, std::nullopt);
+ }
+ }
+#endif
+
DbusInterfaceMap sensorMap;
if (!getSensorMap(ctx, connection, path, sensorMap))
{
@@ -1103,6 +1175,31 @@
return ipmi::response(status);
}
+#ifdef FEATURE_HYBRID_SENSORS
+ if (auto sensor = findStaticSensor(path);
+ sensor != ipmi::sensor::sensors.end() &&
+ getSensorEventTypeFromPath(path) !=
+ static_cast<uint8_t>(SensorEventTypeCodes::threshold))
+ {
+ enabled = static_cast<uint8_t>(
+ IPMISensorEventEnableByte2::sensorScanningEnable);
+ uint16_t assertionEnabled = 0;
+ for (auto& offsetValMap : sensor->second.propertyInterfaces.begin()
+ ->second.begin()
+ ->second.second)
+ {
+ assertionEnabled |= (1 << offsetValMap.first);
+ }
+ assertionEnabledLsb = static_cast<uint8_t>((assertionEnabled & 0xFF));
+ assertionEnabledMsb =
+ static_cast<uint8_t>(((assertionEnabled >> 8) & 0xFF));
+
+ return ipmi::responseSuccess(enabled, assertionEnabledLsb,
+ assertionEnabledMsb, deassertionEnabledLsb,
+ deassertionEnabledMsb);
+ }
+#endif
+
DbusInterfaceMap sensorMap;
if (!getSensorMap(ctx, connection, path, sensorMap))
{
@@ -1198,6 +1295,40 @@
return ipmi::response(status);
}
+#ifdef FEATURE_HYBRID_SENSORS
+ if (auto sensor = findStaticSensor(path);
+ sensor != ipmi::sensor::sensors.end() &&
+ getSensorEventTypeFromPath(path) !=
+ static_cast<uint8_t>(SensorEventTypeCodes::threshold))
+ {
+ auto response = ipmi::sensor::get::mapDbusToAssertion(
+ sensor->second, path, sensor->second.sensorInterface);
+ std::bitset<16> assertions;
+ // deassertions are not used.
+ std::bitset<16> deassertions = 0;
+ uint8_t sensorEventStatus;
+ if (response.readingOrStateUnavailable)
+ {
+ sensorEventStatus |= static_cast<uint8_t>(
+ IPMISensorReadingByte2::readingStateUnavailable);
+ }
+ if (response.scanningEnabled)
+ {
+ sensorEventStatus |= static_cast<uint8_t>(
+ IPMISensorReadingByte2::sensorScanningEnable);
+ }
+ if (response.allEventMessagesEnabled)
+ {
+ sensorEventStatus |= static_cast<uint8_t>(
+ IPMISensorReadingByte2::eventMessagesEnable);
+ }
+ assertions |= response.discreteReadingSensorStates << 8;
+ assertions |= response.thresholdLevelsStates;
+ return ipmi::responseSuccess(sensorEventStatus, assertions,
+ deassertions);
+ }
+#endif
+
DbusInterfaceMap sensorMap;
if (!getSensorMap(ctx, connection, path, sensorMap))
{
@@ -1554,6 +1685,46 @@
return true;
}
+#ifdef FEATURE_HYBRID_SENSORS
+// Construct a type 1 SDR for discrete Sensor typed sensor.
+void constructStaticSensorSdr(ipmi::Context::ptr ctx, uint16_t sensorNum,
+ uint16_t recordID,
+ ipmi::sensor::IdInfoMap::const_iterator sensor,
+ get_sdr::SensorDataFullRecord& record)
+{
+ constructSensorSdrHeaderKey(sensorNum, recordID, record);
+
+ record.body.entity_id = sensor->second.entityType;
+ record.body.sensor_type = sensor->second.sensorType;
+ record.body.event_reading_type = sensor->second.sensorReadingType;
+ record.body.entity_instance = sensor->second.instance;
+ if (ipmi::sensor::Mutability::Write ==
+ (sensor->second.mutability & ipmi::sensor::Mutability::Write))
+ {
+ get_sdr::body::init_settable_state(true, &(record.body));
+ }
+
+ auto id_string = sensor->second.sensorName;
+
+ if (id_string.empty())
+ {
+ id_string = sensor->second.sensorNameFunc(sensor->second);
+ }
+
+ if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH)
+ {
+ get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH,
+ &(record.body));
+ }
+ else
+ {
+ get_sdr::body::set_id_strlen(id_string.length(), &(record.body));
+ }
+ std::strncpy(record.body.id_string, id_string.c_str(),
+ get_sdr::body::get_id_strlen(&(record.body)));
+}
+#endif
+
// Construct type 3 SDR header and key (for VR and other discrete sensors)
void constructEventSdrHeaderKey(uint16_t sensorNum, uint16_t recordID,
get_sdr::SensorDataEventRecord& record)
@@ -1729,6 +1900,32 @@
return 0;
}
+#ifdef FEATURE_HYBRID_SENSORS
+ if (auto sensor = findStaticSensor(path);
+ sensor != ipmi::sensor::sensors.end() &&
+ getSensorEventTypeFromPath(path) !=
+ static_cast<uint8_t>(SensorEventTypeCodes::threshold))
+ {
+ get_sdr::SensorDataFullRecord record = {0};
+
+ // If the request doesn't read SDR body, construct only header and key
+ // part to avoid additional DBus transaction.
+ if (readBytes <= sizeof(record.header) + sizeof(record.key))
+ {
+ constructSensorSdrHeaderKey(sensorNum, recordID, record);
+ }
+ else
+ {
+ constructStaticSensorSdr(ctx, sensorNum, recordID, sensor, record);
+ }
+
+ recordData.insert(recordData.end(), (uint8_t*)&record,
+ ((uint8_t*)&record) + sizeof(record));
+
+ return 0;
+ }
+#endif
+
// Contruct SDR type 3 record for VR sensor (daemon)
if (std::find(interfaces.begin(), interfaces.end(), sensor::vrInterface) !=
interfaces.end())