platform-mc: Support pollForPlatFormEventMessage

Supports polling all events synchronously when the terminus sends
`pldmMessagePollEvent` with the event id. BMC will use the received
event id as input for `pollForPlatformEventMessage` command to retrieve
the event data.

Change-Id: If01f63f30d3f57f8423c863ec776e83dda8e3042
Signed-off-by: Dung Cao <dung@os.amperecomputing.com>
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
diff --git a/platform-mc/event_manager.hpp b/platform-mc/event_manager.hpp
index c654eb7..14b6c8e 100644
--- a/platform-mc/event_manager.hpp
+++ b/platform-mc/event_manager.hpp
@@ -15,6 +15,12 @@
 namespace platform_mc
 {
 
+using EventType = uint8_t;
+using HandlerFunc =
+    std::function<int(pldm_tid_t tid, uint16_t eventId,
+                      const uint8_t* eventData, size_t eventDataSize)>;
+using EventMap = std::map<EventType, HandlerFunc>;
+
 /**
  * @brief EventManager
  *
@@ -35,7 +41,25 @@
 
     explicit EventManager(TerminusManager& terminusManager,
                           TerminiMapper& termini) :
-        terminusManager(terminusManager), termini(termini) {};
+        terminusManager(terminusManager), termini(termini)
+    {
+        // Default response handler for PollForPlatFormEventMessage
+        registerPolledEventHandler(
+            PLDM_MESSAGE_POLL_EVENT,
+            [this](pldm_tid_t tid, uint16_t eventId, const uint8_t* eventData,
+                   size_t eventDataSize) {
+                return this->handlePlatformEvent(tid, eventId,
+                                                 PLDM_MESSAGE_POLL_EVENT,
+                                                 eventData, eventDataSize);
+            });
+        registerPolledEventHandler(
+            PLDM_CPER_EVENT,
+            [this](pldm_tid_t tid, uint16_t eventId, const uint8_t* eventData,
+                   size_t eventDataSize) {
+                return this->handlePlatformEvent(tid, eventId, PLDM_CPER_EVENT,
+                                                 eventData, eventDataSize);
+            });
+    };
 
     /** @brief Handle platform event
      *
@@ -73,6 +97,24 @@
         return availableState[tid];
     };
 
+    /** @brief A Coroutine to poll all events from terminus
+     *
+     *  @param[in] tid - the destination TID
+     *  @param[in] pollDataTransferHandle - the dataTransferHandle from
+     *             pldmMessagePollEvent event
+     *  @return coroutine return_value - PLDM completion code
+     */
+    exec::task<int> pollForPlatformEventTask(pldm_tid_t tid,
+                                             uint32_t pollDataTransferHandle);
+
+    /** @brief Register response handler for the polled events from
+     *         PollForPlatFormEventMessage
+     */
+    void registerPolledEventHandler(uint8_t eventClass, HandlerFunc function)
+    {
+        eventHandlers.insert_or_assign(eventClass, std::move(function));
+    }
+
   protected:
     /** @brief Helper method to process the PLDM Numeric sensor event class
      *
@@ -96,8 +138,9 @@
      *
      *  @return PLDM completion code
      */
-    int processCperEvent(pldm_tid_t tid, uint16_t eventId,
-                         const uint8_t* eventData, const size_t eventDataSize);
+    virtual int processCperEvent(pldm_tid_t tid, uint16_t eventId,
+                                 const uint8_t* eventData,
+                                 const size_t eventDataSize);
 
     /** @brief Helper method to create CPER dump log
      *
@@ -111,6 +154,53 @@
                             const std::string& dataPath,
                             const std::string& typeName);
 
+    /** @brief Send pollForPlatformEventMessage and return response
+     *
+     *  @param[in] tid - Destination TID
+     *  @param[in] formatVersion - format Version
+     *  @param[in] transferOpFlag - Transfer Operation Flag
+     *  @param[in] dataTransferHandle - Data transfer handle
+     *  @param[in] eventIdToAcknowledge - Event ID
+     *  @param[out] completionCode - the complete code of response message
+     *  @param[out] eventTid - Event terminus ID
+     *  @param[out] eventId - Event ID
+     *  @param[out] nextDataTransferHandle - Next handle to get next data part
+     *  @param[out] transferFlag - transfer Flag of response data
+     *  @param[out] eventClass - event class
+     *  @param[out] eventDataSize - data size of event response message
+     *  @param[out] eventData - event data of response message
+     *  @param[out] eventDataIntegrityChecksum - check sum of final event
+     *
+     *  @return coroutine return_value - PLDM completion code
+     */
+    exec::task<int> pollForPlatformEventMessage(
+        pldm_tid_t tid, uint8_t formatVersion, uint8_t transferOperationFlag,
+        uint32_t dataTransferHandle, uint16_t eventIdToAcknowledge,
+        uint8_t& completionCode, uint8_t& eventTid, uint16_t& eventId,
+        uint32_t& nextDataTransferHandle, uint8_t& transferFlag,
+        uint8_t& eventClass, uint32_t& eventDataSize, uint8_t*& eventData,
+        uint32_t& eventDataIntegrityChecksum);
+
+    /** @brief Get the parameters for next pollForPlatformEventMessage to get
+     *         the remaining part of event if has
+     *
+     *  @param[in] eventId - Event ID
+     *  @param[in] eventMessage - event data of response message
+     *  @param[in] transferFlag - transfer Flag of response data
+     *  @param[in] eventDataIntegrityChecksum - check sum of final event
+     *  @param[in] nextDataTransferHandle - Next handle to get next data part
+     *  @param[out] transferOperationFlag - transfer Flag of next request data
+     *  @param[out] dataTransferHandle - Data transfer handle
+     *  @param[out] eventIdToAcknowledge - Event ID
+     *
+     *  @return return_value - PLDM completion code
+     */
+    int getNextPartParameters(
+        uint16_t eventId, std::vector<uint8_t> eventMessage,
+        uint8_t transferFlag, uint32_t eventDataIntegrityChecksum,
+        uint32_t nextDataTransferHandle, uint8_t* transferOperationFlag,
+        uint32_t* dataTransferHandle, uint32_t* eventIdToAcknowledge);
+
     /** @brief Reference of terminusManager */
     TerminusManager& terminusManager;
 
@@ -119,6 +209,9 @@
 
     /** @brief Available state for pldm request of terminus */
     std::unordered_map<pldm_tid_t, Availability> availableState;
+
+    /** @brief map of PLDM event type of polled event to EventHandlers */
+    pldm::platform_mc::EventMap eventHandlers;
 };
 } // namespace platform_mc
 } // namespace pldm