libpldmresponder: Implement GetStateSensorReadings
Register the getStateSensorReadings method and get the state sensor PDR
structure according to the SensorId property.
Tested with JSON file:
https://gist.github.com/lxwinspur/6a40abea7330c25e4d49826e890c4be9
pldmtool raw -d 0x80 0x02 0x21 0x01 0x00 0x01 0x00
Request Message:
08 01 80 02 21 01 00 01 00
Response Message:
08 01 00 02 21 00 01 03 00 00 00
Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I4faeb1e85f9fd4a2745f592d37be38c28112f5b9
diff --git a/libpldm/platform.h b/libpldm/platform.h
index 7834f59..bd4d557 100644
--- a/libpldm/platform.h
+++ b/libpldm/platform.h
@@ -157,6 +157,9 @@
/** @brief PLDM Platform M&C completion codes
*/
enum pldm_platform_completion_codes {
+ PLDM_PLATFORM_INVALID_SENSOR_ID = 0x80,
+ PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE = 0x81,
+
PLDM_PLATFORM_INVALID_EFFECTER_ID = 0x80,
PLDM_PLATFORM_INVALID_STATE_VALUE = 0x81,
diff --git a/libpldmresponder/pdr_utils.hpp b/libpldmresponder/pdr_utils.hpp
index c463f1f..9406d46 100644
--- a/libpldmresponder/pdr_utils.hpp
+++ b/libpldmresponder/pdr_utils.hpp
@@ -89,6 +89,26 @@
return Json::parse(jsonFile);
}
+/** @brief Function to get the Bitfield count to 1
+ *
+ * @param[in] bit - Bitfield
+ *
+ * @return - uint8_t return the number of 1
+ */
+inline uint8_t getBitfieldCount(const bitfield8_t bit)
+{
+ uint8_t count = 0;
+ for (uint8_t i = 0; i < 8; ++i)
+ {
+ if (bit.byte & (1 << i))
+ {
+ ++count;
+ }
+ }
+
+ return count;
+}
+
/** @brief Populate the mapping between D-Bus property stateId and attribute
* value for the effecter PDR enumeration attribute.
*
diff --git a/libpldmresponder/platform.cpp b/libpldmresponder/platform.cpp
index 61d09ad..c017486 100644
--- a/libpldmresponder/platform.cpp
+++ b/libpldmresponder/platform.cpp
@@ -7,8 +7,10 @@
#include "pdr_numeric_effecter.hpp"
#include "pdr_state_effecter.hpp"
#include "pdr_state_sensor.hpp"
+#include "pdr_utils.hpp"
#include "platform_numeric_effecter.hpp"
#include "platform_state_effecter.hpp"
+#include "platform_state_sensor.hpp"
namespace pldm
{
@@ -614,6 +616,56 @@
pdrEntry.size = pdrBuffer.size();
repo.addRecord(pdrEntry);
}
+
+Response Handler::getStateSensorReadings(const pldm_msg* request,
+ size_t payloadLength)
+{
+ uint16_t sensorId{};
+ bitfield8_t sensorRearm{};
+ uint8_t reserved{};
+
+ if (payloadLength != PLDM_GET_SENSOR_READING_REQ_BYTES)
+ {
+ return ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
+ }
+
+ int rc = decode_get_state_sensor_readings_req(
+ request, payloadLength, &sensorId, &sensorRearm, &reserved);
+
+ if (rc != PLDM_SUCCESS)
+ {
+ return ccOnlyResponse(request, rc);
+ }
+
+ // 0x01 to 0x08
+ uint8_t sensorRearmCout = getBitfieldCount(sensorRearm);
+ std::vector<get_sensor_state_field> stateField(sensorRearmCout);
+ uint8_t comSensorCnt{};
+ const pldm::utils::DBusHandler dBusIntf;
+ rc = platform_state_sensor::getStateSensorReadingsHandler<
+ pldm::utils::DBusHandler, Handler>(
+ dBusIntf, *this, sensorId, sensorRearmCout, comSensorCnt, stateField);
+
+ if (rc != PLDM_SUCCESS)
+ {
+ return ccOnlyResponse(request, rc);
+ }
+
+ Response response(sizeof(pldm_msg_hdr) +
+ PLDM_GET_STATE_SENSOR_READINGS_MIN_RESP_BYTES +
+ sizeof(get_sensor_state_field) * comSensorCnt);
+ auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+ rc = encode_get_state_sensor_readings_resp(request->hdr.instance_id, rc,
+ comSensorCnt, stateField.data(),
+ responsePtr);
+ if (rc != PLDM_SUCCESS)
+ {
+ return ccOnlyResponse(request, rc);
+ }
+
+ return response;
+}
+
} // namespace platform
} // namespace responder
} // namespace pldm
diff --git a/libpldmresponder/platform.hpp b/libpldmresponder/platform.hpp
index 06496dc..6d6fd95 100644
--- a/libpldmresponder/platform.hpp
+++ b/libpldmresponder/platform.hpp
@@ -92,6 +92,11 @@
return this->platformEventMessage(request,
payloadLength);
});
+ handlers.emplace(PLDM_GET_STATE_SENSOR_READINGS,
+ [this](const pldm_msg* request, size_t payloadLength) {
+ return this->getStateSensorReadings(request,
+ payloadLength);
+ });
// Default handler for PLDM Events
eventHandlers[PLDM_SENSOR_EVENT].emplace_back(
@@ -211,6 +216,15 @@
Response setNumericEffecterValue(const pldm_msg* request,
size_t payloadLength);
+ /** @brief Handler for getStateSensorReadings
+ *
+ * @param[in] request - Request message
+ * @param[in] payloadLength - Request payload length
+ * @return Response - PLDM Response message
+ */
+ Response getStateSensorReadings(const pldm_msg* request,
+ size_t payloadLength);
+
/** @brief Handler for setStateEffecterStates
*
* @param[in] request - Request message
diff --git a/libpldmresponder/platform_state_sensor.hpp b/libpldmresponder/platform_state_sensor.hpp
new file mode 100644
index 0000000..3fd55cd
--- /dev/null
+++ b/libpldmresponder/platform_state_sensor.hpp
@@ -0,0 +1,157 @@
+#pragma once
+
+#include "config.h"
+
+#include "libpldm/platform.h"
+#include "libpldm/states.h"
+
+#include "common/utils.hpp"
+#include "libpldmresponder/pdr.hpp"
+#include "pdr_utils.hpp"
+#include "pldmd/handler.hpp"
+
+#include <cstdint>
+#include <map>
+
+using namespace pldm::responder::pdr;
+
+namespace pldm
+{
+namespace responder
+{
+namespace platform_state_sensor
+{
+
+/** @brief Function to get the sensor state
+ *
+ * @tparam[in] DBusInterface - DBus interface type
+ * @param[in] dBusIntf - The interface object of DBusInterface
+ * @param[in] stateToDbusValue - Map of DBus property State to attribute value
+ * @param[in] dbusMapping - The d-bus object
+ *
+ * @return - Enumeration of SensorState
+ */
+template <class DBusInterface>
+uint8_t getStateSensorEventState(
+ const DBusInterface& dBusIntf,
+ const std::map<State, pldm::utils::PropertyValue>& stateToDbusValue,
+ const DBusMapping& dbusMapping)
+{
+ try
+ {
+ auto propertyValue = dBusIntf.getDbusPropertyVariant(
+ dbusMapping.objectPath.c_str(), dbusMapping.propertyName.c_str(),
+ dbusMapping.interface.c_str());
+
+ for (const auto& stateValue : stateToDbusValue)
+ {
+ if (stateValue.second == propertyValue)
+ {
+ return stateValue.first;
+ }
+ }
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << e.what() << '\n';
+ }
+
+ return PLDM_SENSOR_DISABLED;
+}
+
+/** @brief Function to get the state sensor readings requested by pldm requester
+ *
+ * @tparam[in] DBusInterface - DBus interface type
+ * @tparam[in] Handler - pldm::responder::platform::Handler
+ * @param[in] dBusIntf - The interface object of DBusInterface
+ * @param[in] handler - The interface object of
+ * pldm::responder::platform::Handler
+ * @param[in] sensorId - Sensor ID sent by the requester to act on
+ * @param[in] sensorRearmCnt - Each bit location in this field corresponds to a
+ * particular sensor within the state sensor
+ * @param[out] compSensorCnt - composite sensor count
+ * @param[out] stateField - The state field data for each of the states,
+ * equal to composite sensor count in number
+ * @return - Success or failure in setting the states. Returns failure in
+ * terms of PLDM completion codes if atleast one state fails to be set
+ */
+template <class DBusInterface, class Handler>
+int getStateSensorReadingsHandler(
+ const DBusInterface& dBusIntf, Handler& handler, uint16_t sensorId,
+ uint8_t sensorRearmCnt, uint8_t& compSensorCnt,
+ std::vector<get_sensor_state_field>& stateField)
+{
+ using namespace pldm::responder::pdr;
+ using namespace pldm::utils;
+
+ pldm_state_sensor_pdr* pdr = nullptr;
+
+ std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateSensorPdrRepo(
+ pldm_pdr_init(), pldm_pdr_destroy);
+ Repo stateSensorPDRs(stateSensorPdrRepo.get());
+ getRepoByType(handler.getRepo(), stateSensorPDRs, PLDM_STATE_SENSOR_PDR);
+ if (stateSensorPDRs.empty())
+ {
+ std::cerr << "Failed to get record by PDR type\n";
+ return PLDM_PLATFORM_INVALID_SENSOR_ID;
+ }
+
+ PdrEntry pdrEntry{};
+ auto pdrRecord = stateSensorPDRs.getFirstRecord(pdrEntry);
+ while (pdrRecord)
+ {
+ pdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdrEntry.data);
+ assert(pdr != NULL);
+ if (pdr->sensor_id != sensorId)
+ {
+ pdr = nullptr;
+ pdrRecord = stateSensorPDRs.getNextRecord(pdrRecord, pdrEntry);
+ continue;
+ }
+
+ compSensorCnt = pdr->composite_sensor_count;
+ if (sensorRearmCnt > compSensorCnt)
+ {
+ std::cerr << "The requester sent wrong sensorRearm"
+ << " count for the sensor, SENSOR_ID=" << sensorId
+ << "SENSOR_REARM_COUNT=" << sensorRearmCnt << "\n";
+ return PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE;
+ }
+ break;
+ }
+
+ if (!pdr)
+ {
+ return PLDM_PLATFORM_INVALID_SENSOR_ID;
+ }
+
+ int rc = PLDM_SUCCESS;
+ try
+ {
+ const auto& [dbusMappings, dbusValMaps] =
+ handler.getDbusObjMaps(sensorId, TypeId::PLDM_SENSOR_ID);
+
+ stateField.clear();
+ for (size_t i = 0; i < compSensorCnt; i++)
+ {
+ auto& dbusMapping = dbusMappings[i];
+
+ uint8_t sensorOpState = getStateSensorEventState<DBusInterface>(
+ dBusIntf, dbusValMaps[i], dbusMapping);
+ stateField.push_back({PLDM_SENSOR_ENABLED, PLDM_SENSOR_UNKNOWN,
+ PLDM_SENSOR_UNKNOWN, sensorOpState});
+ }
+ }
+ catch (const std::out_of_range& e)
+ {
+ std::cerr << "the sensorId does not exist. sensor id: " << sensorId
+ << e.what() << '\n';
+ rc = PLDM_ERROR;
+ }
+
+ return rc;
+}
+
+} // namespace platform_state_sensor
+} // namespace responder
+} // namespace pldm