Add encode/decode pldmMessagePollEvent data

The API decodes/encodes eventData fields for pldmMessagePollEvent type
(section 16.15) of PlatformEventMessage command(0xA) which is defined
in DSP0248 Version 1.2.2.

Signed-off-by: Dung Cao <dung@os.amperecomputing.com>
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Change-Id: I1934792f0ce8f339ee04c4bae0c65e3973ed38b4
diff --git a/CHANGELOG.md b/CHANGELOG.md
index aceb34d..91e3e43 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,10 @@
 
 ## [Unreleased]
 
+### Added
+
+1. Add encode/decode pldmMessagePollEvent data
+
 ### Changed
 
 1. include: Move installed transport.h under libpldm/
diff --git a/include/libpldm/platform.h b/include/libpldm/platform.h
index ead3421..26d47c5 100644
--- a/include/libpldm/platform.h
+++ b/include/libpldm/platform.h
@@ -52,6 +52,11 @@
 #define PLDM_PLATFORM_EVENT_MESSAGE_STATE_SENSOR_STATE_REQ_BYTES 6
 #define PLDM_PLATFORM_EVENT_MESSAGE_RESP_BYTES			 2
 #define PLDM_PLATFORM_EVENT_MESSAGE_FORMAT_VERSION		 1
+#define PLDM_PLATFORM_EVENT_MESSAGE_EVENT_ID			 2
+#define PLDM_PLATFORM_EVENT_MESSAGE_TRANFER_HANDLE		 4
+
+/* Minumum length of senson event data */
+#define PLDM_MSG_POLL_EVENT_LENGTH 7
 
 /* Minumum length of senson event data */
 #define PLDM_SENSOR_EVENT_DATA_MIN_LENGTH			 5
@@ -1938,6 +1943,41 @@
 	uint8_t *event_data_format, uint8_t *number_of_change_records,
 	size_t *change_record_data_offset);
 
+/** @brief Decode pldmMessagePollEvent event data type
+ *
+ *  @param[in] event_data - event data from the response message
+ *  @param[in] event_data_length - length of the event data
+ *  @param[out] format_version - Version of the event format
+ *  @param[out] event_id - The event id
+ *  @param[out] data_transfer_handle - The data transfer handle
+ *  should be read from event data
+ *  @return pldm_completion_codes
+ *  @note  Caller is responsible for memory alloc and dealloc of param
+ *         'event_data'
+ */
+int decode_pldm_message_poll_event_data(const uint8_t *event_data,
+					size_t event_data_length,
+					uint8_t *format_version,
+					uint16_t *event_id,
+					uint32_t *data_transfer_handle);
+
+/** @brief Encode pldmMessagePollEvent event data type
+ *
+ *  @param[in] format_version - Version of the event format
+ *  @param[in] event_id - The event id
+ *  @param[in] data_transfer_handle - The data transfer handle
+ *  @param[out] event_data - event data to the response message
+ *  @param[in] event_data_length - length of the event data
+ *  @return pldm_completion_codes
+ *  @note The caller is responsible for allocating and deallocating the
+ *        event_data
+ */
+int encode_pldm_message_poll_event_data(uint8_t format_version,
+					uint16_t event_id,
+					uint32_t data_transfer_handle,
+					uint8_t *event_data,
+					size_t event_data_length);
+
 /** @brief Encode PLDM PDR Repository Change eventData
  *  @param[in] event_data_format - Format of this event data (e.g.
  * FORMAT_IS_PDR_HANDLES)
diff --git a/src/platform.c b/src/platform.c
index 5da538c..c6f3cf6 100644
--- a/src/platform.c
+++ b/src/platform.c
@@ -1855,6 +1855,71 @@
 	return pldm_msgbuf_destroy(buf);
 }
 
+int decode_pldm_message_poll_event_data(const uint8_t *event_data,
+					size_t event_data_length,
+					uint8_t *format_version,
+					uint16_t *event_id,
+					uint32_t *data_transfer_handle)
+{
+	struct pldm_msgbuf _buf;
+	struct pldm_msgbuf *buf = &_buf;
+	int rc;
+
+	if (event_data == NULL || format_version == NULL || event_id == NULL ||
+	    data_transfer_handle == NULL) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	rc = pldm_msgbuf_init(buf, PLDM_MSG_POLL_EVENT_LENGTH, event_data,
+			      event_data_length);
+	if (rc) {
+		return rc;
+	}
+
+	pldm_msgbuf_extract(buf, format_version);
+	rc = pldm_msgbuf_extract(buf, event_id);
+	if (rc) {
+		return rc;
+	}
+
+	if (*event_id == 0x0000 || *event_id == 0xffff) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	pldm_msgbuf_extract(buf, data_transfer_handle);
+
+	return pldm_msgbuf_destroy_consumed(buf);
+}
+
+int encode_pldm_message_poll_event_data(uint8_t format_version,
+					uint16_t event_id,
+					uint32_t data_transfer_handle,
+					uint8_t *event_data,
+					size_t event_data_length)
+{
+	struct pldm_msgbuf _buf;
+	struct pldm_msgbuf *buf = &_buf;
+	int rc;
+
+	if (event_data == NULL) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	if (event_id == 0x0000 || event_id == 0xffff) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	rc = pldm_msgbuf_init(buf, PLDM_MSG_POLL_EVENT_LENGTH, event_data,
+			      event_data_length);
+	if (rc) {
+		return rc;
+	}
+	pldm_msgbuf_insert(buf, format_version);
+	pldm_msgbuf_insert(buf, event_id);
+	pldm_msgbuf_insert(buf, data_transfer_handle);
+
+	return pldm_msgbuf_destroy(buf);
+}
 int decode_pldm_pdr_repository_change_record_data(
 	const uint8_t *change_record_data, size_t change_record_data_size,
 	uint8_t *event_data_operation, uint8_t *number_of_change_entries,
diff --git a/tests/libpldm_platform_test.cpp b/tests/libpldm_platform_test.cpp
index 0b3370d..6f5cc0e 100644
--- a/tests/libpldm_platform_test.cpp
+++ b/tests/libpldm_platform_test.cpp
@@ -2124,6 +2124,147 @@
     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
 }
 
+TEST(PlatformEventMessage, testGoodPldmMsgPollEventDataDecodeRequest)
+{
+    std::array<uint8_t, PLDM_PLATFORM_EVENT_MESSAGE_FORMAT_VERSION +
+                            PLDM_PLATFORM_EVENT_MESSAGE_EVENT_ID +
+                            PLDM_PLATFORM_EVENT_MESSAGE_TRANFER_HANDLE>
+        eventData{
+            0x1,                   // version
+            0x88, 0x77,            // Event Id
+            0x44, 0x33, 0x22, 0x11 // Tranfer Handle
+        };
+
+    uint8_t formatVersion = 0x01;
+    uint16_t eventID = 0x7788;
+    uint32_t dataTransferHandle = 0x11223344;
+
+    uint8_t retFormatVersion;
+    uint16_t reteventID;
+    uint32_t retDataTransferHandle;
+
+    auto rc = decode_pldm_message_poll_event_data(
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size(),
+        &retFormatVersion, &reteventID, &retDataTransferHandle);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(retFormatVersion, formatVersion);
+    EXPECT_EQ(reteventID, eventID);
+    EXPECT_EQ(retDataTransferHandle, dataTransferHandle);
+}
+
+TEST(PlatformEventMessage, testBadPldmMsgPollEventDataDecodeRequest)
+{
+
+    std::array<uint8_t, PLDM_PLATFORM_EVENT_MESSAGE_FORMAT_VERSION +
+                            PLDM_PLATFORM_EVENT_MESSAGE_EVENT_ID +
+                            PLDM_PLATFORM_EVENT_MESSAGE_TRANFER_HANDLE>
+        eventData{
+            0x1,                   // version
+            0x88, 0x77,            // Event Id
+            0x44, 0x33, 0x22, 0x11 // Tranfer Handle
+        };
+
+    uint8_t retFormatVersion;
+    uint16_t reteventID;
+    uint32_t retDataTransferHandle;
+
+    auto rc = decode_pldm_message_poll_event_data(
+        NULL, eventData.size(), &retFormatVersion, &reteventID,
+        &retDataTransferHandle);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_pldm_message_poll_event_data(
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size() - 1,
+        &retFormatVersion, &reteventID, &retDataTransferHandle);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+
+    // Event id is 0x0000
+    eventData[1] = 0x00;
+    eventData[2] = 0x00;
+    rc = decode_pldm_message_poll_event_data(
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size(),
+        &retFormatVersion, &reteventID, &retDataTransferHandle);
+
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    // Event id is 0xffff
+    eventData[1] = 0xff;
+    eventData[2] = 0xff;
+    rc = decode_pldm_message_poll_event_data(
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size(),
+        &retFormatVersion, &reteventID, &retDataTransferHandle);
+
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(PlatformEventMessage, testGoodPldmMsgPollEventDataEncode)
+{
+    std::array<uint8_t, PLDM_PLATFORM_EVENT_MESSAGE_FORMAT_VERSION +
+                            PLDM_PLATFORM_EVENT_MESSAGE_EVENT_ID +
+                            PLDM_PLATFORM_EVENT_MESSAGE_TRANFER_HANDLE>
+        eventData{};
+
+    uint8_t formatVersion = 0x01;
+    uint16_t eventID = 0x7788;
+    uint32_t dataTransferHandle = 0x11223344;
+
+    int rc = encode_pldm_message_poll_event_data(
+        formatVersion, eventID, dataTransferHandle,
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size());
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+
+    struct pldm_msgbuf _buf;
+    struct pldm_msgbuf* buf = &_buf;
+
+    rc = pldm_msgbuf_init(buf, PLDM_MSG_POLL_EVENT_LENGTH,
+                          reinterpret_cast<uint8_t*>(eventData.data()),
+                          eventData.size());
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+
+    uint8_t retFormatVersion;
+    uint16_t reteventID;
+    uint32_t retDataTransferHandle;
+
+    EXPECT_EQ(pldm_msgbuf_extract_uint8(buf, &retFormatVersion), PLDM_SUCCESS);
+    EXPECT_EQ(pldm_msgbuf_extract_uint16(buf, &reteventID), PLDM_SUCCESS);
+    EXPECT_EQ(pldm_msgbuf_extract_uint32(buf, &retDataTransferHandle),
+              PLDM_SUCCESS);
+    EXPECT_EQ(retFormatVersion, formatVersion);
+    EXPECT_EQ(reteventID, eventID);
+    EXPECT_EQ(retDataTransferHandle, dataTransferHandle);
+    EXPECT_EQ(pldm_msgbuf_destroy_consumed(buf), PLDM_SUCCESS);
+}
+
+TEST(PlatformEventMessage, testBadPldmMsgPollEventDataEncode)
+{
+    std::array<uint8_t, PLDM_PLATFORM_EVENT_MESSAGE_FORMAT_VERSION +
+                            PLDM_PLATFORM_EVENT_MESSAGE_EVENT_ID +
+                            PLDM_PLATFORM_EVENT_MESSAGE_TRANFER_HANDLE>
+        eventData{};
+
+    uint8_t formatVersion = 0x01;
+    uint16_t eventID = 0x7788;
+    uint32_t dataTransferHandle = 0x11223344;
+
+    int rc = encode_pldm_message_poll_event_data(
+        formatVersion, eventID, dataTransferHandle, NULL, eventData.size());
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    eventID = 0x0000;
+    rc = encode_pldm_message_poll_event_data(
+        formatVersion, eventID, dataTransferHandle,
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size());
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    eventID = 0xffff;
+    rc = encode_pldm_message_poll_event_data(
+        formatVersion, eventID, dataTransferHandle,
+        reinterpret_cast<uint8_t*>(eventData.data()), eventData.size());
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
 TEST(PlatformEventMessage, testGoodSensorOpEventDataDecodeRequest)
 {
     std::array<uint8_t, PLDM_SENSOR_EVENT_SENSOR_OP_STATE_DATA_LENGTH>