libpldm: Implement encode/decode for GetStateSensorReadings
The spec of GetStateSensorReadings command refers to DSP0248_1.2.0: 20.2
Change-Id: I8b2222196d1b960697b73d83911937c4164b09af
Signed-off-by: Jolie Ku <jolie_ku@wistron.com>
diff --git a/libpldm/platform.c b/libpldm/platform.c
index aef6c5e..cd332e6 100644
--- a/libpldm/platform.c
+++ b/libpldm/platform.c
@@ -428,3 +428,130 @@
return PLDM_SUCCESS;
}
+
+int encode_get_state_sensor_readings_resp(uint8_t instance_id,
+ uint8_t completion_code,
+ uint8_t comp_sensor_count,
+ get_sensor_state_field *field,
+ struct pldm_msg *msg)
+{
+ struct pldm_header_info header = {0};
+ int rc = PLDM_SUCCESS;
+
+ header.msg_type = PLDM_RESPONSE;
+ header.instance = instance_id;
+ header.pldm_type = PLDM_PLATFORM;
+ header.command = PLDM_GET_STATE_SENSOR_READINGS;
+
+ if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+ return rc;
+ }
+
+ if (comp_sensor_count < 0x1 || comp_sensor_count > 0x8) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ struct pldm_get_state_sensor_readings_resp *response =
+ (struct pldm_get_state_sensor_readings_resp *)msg->payload;
+
+ response->completion_code = completion_code;
+ response->comp_sensor_count = comp_sensor_count;
+ memcpy(response->field, field,
+ (sizeof(get_sensor_state_field) * comp_sensor_count));
+
+ return rc;
+}
+
+int encode_get_state_sensor_readings_req(uint8_t instance_id,
+ uint16_t sensor_id,
+ bitfield8_t sensor_rearm,
+ uint8_t reserved, struct pldm_msg *msg)
+{
+ struct pldm_header_info header = {0};
+ int rc = PLDM_SUCCESS;
+
+ header.msg_type = PLDM_REQUEST;
+ header.instance = instance_id;
+ header.pldm_type = PLDM_PLATFORM;
+ header.command = PLDM_GET_STATE_SENSOR_READINGS;
+
+ if (msg == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+ return rc;
+ }
+
+ struct pldm_get_state_sensor_readings_req *request =
+ (struct pldm_get_state_sensor_readings_req *)msg->payload;
+
+ request->sensor_id = htole16(sensor_id);
+ request->reserved = reserved;
+ request->sensor_rearm = sensor_rearm;
+
+ return PLDM_SUCCESS;
+}
+
+int decode_get_state_sensor_readings_resp(const struct pldm_msg *msg,
+ size_t payload_length,
+ uint8_t *completion_code,
+ uint8_t *comp_sensor_count,
+ get_sensor_state_field *field)
+{
+ if (msg == NULL || completion_code == NULL ||
+ comp_sensor_count == NULL || field == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ *completion_code = msg->payload[0];
+ if (PLDM_SUCCESS != *completion_code) {
+ return PLDM_SUCCESS;
+ }
+
+ if (payload_length > PLDM_GET_STATE_SENSOR_READINGS_RESP_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_get_state_sensor_readings_resp *response =
+ (struct pldm_get_state_sensor_readings_resp *)msg->payload;
+
+ if (response->comp_sensor_count < 0x1 ||
+ response->comp_sensor_count > 0x8) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+ if (response->comp_sensor_count > *comp_sensor_count) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+ *comp_sensor_count = response->comp_sensor_count;
+
+ memcpy(field, response->field,
+ (sizeof(get_sensor_state_field) * (*comp_sensor_count)));
+
+ return PLDM_SUCCESS;
+}
+
+int decode_get_state_sensor_readings_req(const struct pldm_msg *msg,
+ size_t payload_length,
+ uint16_t *sensor_id,
+ bitfield8_t *sensor_rearm,
+ uint8_t *reserved)
+{
+ if (msg == NULL || sensor_id == NULL || sensor_rearm == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (payload_length != PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_get_state_sensor_readings_req *request =
+ (struct pldm_get_state_sensor_readings_req *)msg->payload;
+
+ *sensor_id = le16toh(request->sensor_id);
+ *reserved = request->reserved;
+ memcpy(&(sensor_rearm->byte), &(request->sensor_rearm.byte),
+ sizeof(request->sensor_rearm.byte));
+
+ return PLDM_SUCCESS;
+}
diff --git a/libpldm/platform.h b/libpldm/platform.h
index 0cce1b4..0371d1c 100644
--- a/libpldm/platform.h
+++ b/libpldm/platform.h
@@ -12,8 +12,10 @@
/* Maximum size for request */
#define PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES 19
+#define PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES 4
/* Response lengths are inclusive of completion code */
#define PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES 1
+#define PLDM_GET_STATE_SENSOR_READINGS_RESP_BYTES 34
#define PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES 1
#define PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES 4
@@ -35,7 +37,33 @@
enum effecter_state { PLDM_INVALID_VALUE = 0xFF };
+enum sensor_operational_state {
+ ENABLED = 0x00,
+ DISABLED = 0x01,
+ UNAVAILABLE = 0x02,
+ STATUSUNKNOWN = 0x03,
+ FAILED = 0x04,
+ INITIALIZING = 0x05,
+ SHUTTINGDOWN = 0x06,
+ INTEST = 0x07
+};
+
+enum present_state {
+ UNKNOWN = 0x0,
+ NORMAL = 0x01,
+ WARNING = 0x02,
+ CRITICAL = 0x03,
+ FATAL = 0x04,
+ LOWERWARNING = 0x05,
+ LOWERCRITICAL = 0x06,
+ LOWERFATAL = 0x07,
+ UPPERWARNING = 0x08,
+ UPPERCRITICAL = 0x09,
+ UPPERFATAL = 0x0a
+};
+
enum pldm_platform_commands {
+ PLDM_GET_STATE_SENSOR_READINGS = 0x21,
PLDM_SET_NUMERIC_EFFECTER_VALUE = 0x31,
PLDM_SET_STATE_EFFECTER_STATES = 0x39,
PLDM_GET_PDR = 0x51,
@@ -127,6 +155,20 @@
uint8_t effecter_state; //!< Expected state of the effecter
} __attribute__((packed)) set_effecter_state_field;
+/** @struct get_sensor_readings_field
+ *
+ * Structure representing a stateField in GetStateSensorReadings command */
+
+typedef struct state_field_for_get_state_sensor_readings {
+ uint8_t sensor_op_state; //!< The state of the sensor itself
+ uint8_t present_state; //!< Return a state value
+ uint8_t previous_state; //!< The state that the presentState was entered
+ //! from. This must be different from the
+ //! present state
+ uint8_t event_state; //!< Return a state value from a PLDM State Set
+ //! that is associated with the sensor
+} __attribute__((packed)) get_sensor_state_field;
+
/** @struct PLDM_SetStateEffecterStates_Request
*
* Structure representing PLDM set state effecter states request.
@@ -174,6 +216,26 @@
uint8_t effecter_value[1];
} __attribute__((packed));
+/** @struct pldm_get_state_sensor_readings_req
+ *
+ * Structure representing PLDM get state sensor readings request.
+ */
+struct pldm_get_state_sensor_readings_req {
+ uint16_t sensor_id;
+ bitfield8_t sensor_rearm;
+ uint8_t reserved;
+} __attribute__((packed));
+
+/** @struct pldm_get_state_sensor_readings_resp
+ *
+ * Structure representing PLDM get state sensor readings response.
+ */
+struct pldm_get_state_sensor_readings_resp {
+ uint8_t completion_code;
+ uint8_t comp_sensor_count;
+ get_sensor_state_field field[1];
+} __attribute__((packed));
+
/* Responder */
/* SetNumericEffecterValue */
@@ -299,6 +361,48 @@
uint8_t *transfer_op_flag, uint16_t *request_cnt,
uint16_t *record_chg_num);
+/* GetStateSensorReadings */
+
+/** @brief Decode GetStateSensorReadings request data
+ *
+ * @param[in] msg - Request message
+ * @param[in] payload_length - Length of request message payload
+ * @param[out] sensor_id - used to identify and access the simple or composite
+ * sensor
+ * @param[out] sensor_rearm - Each bit location in this field corresponds to a
+ * particular sensor within the state sensor, where bit [0] corresponds
+ * to the first state sensor (sensor offset 0) and bit [7] corresponds
+ * to the eighth sensor (sensor offset 7), sequentially.
+ * @param[out] reserved - value: 0x00
+ * @return pldm_completion_codes
+ */
+
+int decode_get_state_sensor_readings_req(const struct pldm_msg *msg,
+ size_t payload_length,
+ uint16_t *sensor_id,
+ bitfield8_t *sensor_rearm,
+ uint8_t *reserved);
+
+/** @brief Encode GetStateSensorReadings response data
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] completion_code - PLDM completion code
+ * @param[out] comp_sensor_count - The number of individual sets of sensor
+ * information that this command accesses
+ * @param[out] field - Each stateField is an instance of a stateField structure
+ * that is used to return the present operational state setting and the
+ * present state and event state for a particular set of sensor
+ * information contained within the state sensor
+ * @param[out] msg - Message will be written to this
+ * @return pldm_completion_codes
+ */
+
+int encode_get_state_sensor_readings_resp(uint8_t instance_id,
+ uint8_t completion_code,
+ uint8_t comp_sensor_count,
+ get_sensor_state_field *field,
+ struct pldm_msg *msg);
+
/* Requester */
/* GetPDR */
@@ -433,6 +537,48 @@
size_t payload_length,
uint8_t *completion_code);
+/** @brief Create a PLDM request message for GetStateSensorReadings
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] sensor_id - used to identify and access the simple or composite
+ * sensor
+ * @param[in] sensorRearm - Each bit location in this field corresponds to a
+ * particular sensor within the state sensor, where bit [0] corresponds
+ * to the first state sensor (sensor offset 0) and bit [7] corresponds
+ * to the eighth sensor (sensor offset 7), sequentially
+ * @param[in] reserved - value: 0x00
+ * @param[out] msg - Message will be written to this
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+
+int encode_get_state_sensor_readings_req(uint8_t instance_id,
+ uint16_t sensor_id,
+ bitfield8_t sensor_rearm,
+ uint8_t reserved,
+ struct pldm_msg *msg);
+
+/** @brief Decode GetStateSensorReadings response data
+ *
+ * @param[in] msg - Request message
+ * @param[in] payload_length - Length of response message payload
+ * @param[out] completion_code - PLDM completion code
+ * @param[in,out] comp_sensor_count - The number of individual sets of sensor
+ * information that this command accesses
+ * @param[out] field - Each stateField is an instance of a stateField structure
+ * that is used to return the present operational state setting and the
+ * present state and event state for a particular set of sensor
+ * information contained within the state sensor
+ * @return pldm_completion_codes
+ */
+
+int decode_get_state_sensor_readings_resp(const struct pldm_msg *msg,
+ size_t payload_length,
+ uint8_t *completion_code,
+ uint8_t *comp_sensor_count,
+ get_sensor_state_field *field);
+
#ifdef __cplusplus
}
#endif
diff --git a/libpldm/tests/libpldm_platform_test.cpp b/libpldm/tests/libpldm_platform_test.cpp
index f810ae4..b6f47c8 100644
--- a/libpldm/tests/libpldm_platform_test.cpp
+++ b/libpldm/tests/libpldm_platform_test.cpp
@@ -546,3 +546,223 @@
0, PLDM_SUCCESS, NULL, PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
+
+TEST(GetStateSensorReadings, testGoodEncodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_STATE_SENSOR_READINGS_RESP_BYTES>
+ responseMsg{};
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ uint8_t completionCode = 0;
+ uint8_t comp_sensorCnt = 0x2;
+
+ std::array<get_sensor_state_field, 2> stateField{};
+ stateField[0] = {ENABLED, NORMAL, WARNING, UNKNOWN};
+ stateField[1] = {FAILED, UPPERFATAL, UPPERCRITICAL, FATAL};
+
+ auto rc = encode_get_state_sensor_readings_resp(
+ 0, PLDM_SUCCESS, comp_sensorCnt, stateField.data(), response);
+
+ struct pldm_get_state_sensor_readings_resp* resp =
+ reinterpret_cast<struct pldm_get_state_sensor_readings_resp*>(
+ response->payload);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completionCode, resp->completion_code);
+ EXPECT_EQ(comp_sensorCnt, resp->comp_sensor_count);
+ EXPECT_EQ(stateField[0].sensor_op_state, resp->field->sensor_op_state);
+ EXPECT_EQ(stateField[0].present_state, resp->field->present_state);
+ EXPECT_EQ(stateField[0].previous_state, resp->field->previous_state);
+ EXPECT_EQ(stateField[0].event_state, resp->field->event_state);
+ EXPECT_EQ(stateField[1].sensor_op_state, resp->field[1].sensor_op_state);
+ EXPECT_EQ(stateField[1].present_state, resp->field[1].present_state);
+ EXPECT_EQ(stateField[1].previous_state, resp->field[1].previous_state);
+ EXPECT_EQ(stateField[1].event_state, resp->field[1].event_state);
+}
+
+TEST(GetStateSensorReadings, testBadEncodeResponse)
+{
+ auto rc = encode_get_state_sensor_readings_resp(0, PLDM_SUCCESS, 0, nullptr,
+ nullptr);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetStateSensorReadings, testGoodDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_STATE_SENSOR_READINGS_RESP_BYTES>
+ responseMsg{};
+
+ uint8_t completionCode = 0;
+ uint8_t comp_sensorCnt = 2;
+
+ std::array<get_sensor_state_field, 2> stateField{};
+ stateField[0] = {DISABLED, UNKNOWN, UNKNOWN, UNKNOWN};
+ stateField[1] = {ENABLED, LOWERFATAL, LOWERCRITICAL, WARNING};
+
+ uint8_t retcompletion_code = 0;
+ uint8_t retcomp_sensorCnt = 2;
+ std::array<get_sensor_state_field, 2> retstateField{};
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ struct pldm_get_state_sensor_readings_resp* resp =
+ reinterpret_cast<struct pldm_get_state_sensor_readings_resp*>(
+ response->payload);
+
+ resp->completion_code = completionCode;
+ resp->comp_sensor_count = comp_sensorCnt;
+ memcpy(resp->field, &stateField,
+ (sizeof(get_sensor_state_field) * comp_sensorCnt));
+
+ auto rc = decode_get_state_sensor_readings_resp(
+ response, responseMsg.size() - hdrSize, &retcompletion_code,
+ &retcomp_sensorCnt, retstateField.data());
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completionCode, retcompletion_code);
+ EXPECT_EQ(comp_sensorCnt, retcomp_sensorCnt);
+ EXPECT_EQ(stateField[0].sensor_op_state, retstateField[0].sensor_op_state);
+ EXPECT_EQ(stateField[0].present_state, retstateField[0].present_state);
+ EXPECT_EQ(stateField[0].previous_state, retstateField[0].previous_state);
+ EXPECT_EQ(stateField[0].event_state, retstateField[0].event_state);
+ EXPECT_EQ(stateField[1].sensor_op_state, retstateField[1].sensor_op_state);
+ EXPECT_EQ(stateField[1].present_state, retstateField[1].present_state);
+ EXPECT_EQ(stateField[1].previous_state, retstateField[1].previous_state);
+ EXPECT_EQ(stateField[1].event_state, retstateField[1].event_state);
+}
+
+TEST(GetStateSensorReadings, testBadDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_STATE_SENSOR_READINGS_RESP_BYTES>
+ responseMsg{};
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_get_state_sensor_readings_resp(
+ response, responseMsg.size() - hdrSize, nullptr, nullptr, nullptr);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ uint8_t completionCode = 0;
+ uint8_t comp_sensorCnt = 1;
+
+ std::array<get_sensor_state_field, 1> stateField{};
+ stateField[0] = {ENABLED, UPPERFATAL, UPPERCRITICAL, WARNING};
+
+ uint8_t retcompletion_code = 0;
+ uint8_t retcomp_sensorCnt = 0;
+ std::array<get_sensor_state_field, 1> retstateField{};
+
+ struct pldm_get_state_sensor_readings_resp* resp =
+ reinterpret_cast<struct pldm_get_state_sensor_readings_resp*>(
+ response->payload);
+
+ resp->completion_code = completionCode;
+ resp->comp_sensor_count = comp_sensorCnt;
+ memcpy(resp->field, &stateField,
+ (sizeof(get_sensor_state_field) * comp_sensorCnt));
+
+ rc = decode_get_state_sensor_readings_resp(
+ response, responseMsg.size() - hdrSize, &retcompletion_code,
+ &retcomp_sensorCnt, retstateField.data());
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetStateSensorReadings, testGoodEncodeRequest)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES>
+ requestMsg{};
+
+ uint16_t sensorId = 0xAB;
+ bitfield8_t sensorRearm;
+ sensorRearm.byte = 0x03;
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto rc = encode_get_state_sensor_readings_req(0, sensorId, sensorRearm, 0,
+ request);
+
+ struct pldm_get_state_sensor_readings_req* req =
+ reinterpret_cast<struct pldm_get_state_sensor_readings_req*>(
+ request->payload);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(sensorId, le16toh(req->sensor_id));
+ EXPECT_EQ(sensorRearm.byte, req->sensor_rearm.byte);
+}
+
+TEST(GetStateSensorReadings, testBadEncodeRequest)
+{
+ bitfield8_t sensorRearm;
+ sensorRearm.byte = 0x0;
+
+ auto rc =
+ encode_get_state_sensor_readings_req(0, 0, sensorRearm, 0, nullptr);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetStateSensorReadings, testGoodDecodeRequest)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES>
+ requestMsg{};
+
+ uint16_t sensorId = 0xCD;
+ bitfield8_t sensorRearm;
+ sensorRearm.byte = 0x10;
+
+ uint16_t retsensorId;
+ bitfield8_t retsensorRearm;
+ uint8_t retreserved;
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ struct pldm_get_state_sensor_readings_req* req =
+ reinterpret_cast<struct pldm_get_state_sensor_readings_req*>(
+ request->payload);
+
+ req->sensor_id = htole16(sensorId);
+ req->sensor_rearm.byte = sensorRearm.byte;
+
+ auto rc = decode_get_state_sensor_readings_req(
+ request, requestMsg.size() - hdrSize, &retsensorId, &retsensorRearm,
+ &retreserved);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(sensorId, retsensorId);
+ EXPECT_EQ(sensorRearm.byte, retsensorRearm.byte);
+ EXPECT_EQ(0, retreserved);
+}
+
+TEST(GetStateSensorReadings, testBadDecodeRequest)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES>
+ requestMsg{};
+
+ auto rc = decode_get_state_sensor_readings_req(
+ nullptr, requestMsg.size() - hdrSize, nullptr, nullptr, nullptr);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ uint16_t sensorId = 0x11;
+ bitfield8_t sensorRearm;
+ sensorRearm.byte = 0x04;
+
+ uint16_t retsensorId;
+ bitfield8_t retsensorRearm;
+ uint8_t retreserved;
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ struct pldm_get_state_sensor_readings_req* req =
+ reinterpret_cast<struct pldm_get_state_sensor_readings_req*>(
+ request->payload);
+
+ req->sensor_id = htole16(sensorId);
+ req->sensor_rearm.byte = sensorRearm.byte;
+
+ rc = decode_get_state_sensor_readings_req(
+ request, requestMsg.size() - hdrSize - 1, &retsensorId, &retsensorRearm,
+ &retreserved);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}