Add handler for Deactivate payload command.

Change-Id: I6d01757b7b526ad15b1c059506603b5921e30473
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/command/payload_cmds.cpp b/command/payload_cmds.cpp
index 02c854a..31ab3a7 100644
--- a/command/payload_cmds.cpp
+++ b/command/payload_cmds.cpp
@@ -81,6 +81,67 @@
     return outPayload;
 }
 
+std::vector<uint8_t> deactivatePayload(std::vector<uint8_t>& inPayload,
+                                       const message::Handler& handler)
+{
+    std::vector<uint8_t> outPayload(sizeof(DeactivatePayloadResponse));
+    auto request = reinterpret_cast<DeactivatePayloadRequest*>
+            (inPayload.data());
+    auto response = reinterpret_cast<DeactivatePayloadResponse*>
+            (outPayload.data());
+
+    response->completionCode = IPMI_CC_OK;
+
+    // SOL is the payload currently supported for deactivation
+    if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType)
+    {
+        response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+        return outPayload;
+    }
+
+    // Only one instance of SOL is supported
+    if (request->payloadInstance != 1)
+    {
+        response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+        return outPayload;
+    }
+
+    auto status = std::get<sol::Manager&>(singletonPool).isPayloadActive(
+            request->payloadInstance);
+    if (!status)
+    {
+        response->completionCode = IPMI_CC_PAYLOAD_DEACTIVATED;
+        return outPayload;
+    }
+
+    try
+    {
+        auto& context = std::get<sol::Manager&>(singletonPool).getContext
+                (request->payloadInstance);
+        auto sessionID = context.sessionID;
+
+        activating(request->payloadInstance, sessionID);
+        std::get<sol::Manager&>(singletonPool).stopPayloadInstance(
+                request->payloadInstance);
+
+        auto check = std::get<session::Manager&>(singletonPool).stopSession
+                (sessionID);
+        if(!check)
+        {
+            response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
+        }
+    }
+    catch (std::exception& e)
+    {
+        log<level::ERR>(e.what());
+        response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
+        return outPayload;
+    }
+
+    return outPayload;
+}
+
 } // namespace command
 
 } // namespace sol
+
diff --git a/command/payload_cmds.hpp b/command/payload_cmds.hpp
index ed6ca92..47b0ad1 100644
--- a/command/payload_cmds.hpp
+++ b/command/payload_cmds.hpp
@@ -111,6 +111,68 @@
 std::vector<uint8_t> activatePayload(std::vector<uint8_t>& inPayload,
                                      const message::Handler& handler);
 
+constexpr uint8_t IPMI_CC_PAYLOAD_DEACTIVATED = 0x80;
+
+/** @struct DeactivatePayloadRequest
+ *
+ *  IPMI payload for Deactivate Payload command request.
+ */
+struct DeactivatePayloadRequest
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t payloadType : 6;        //!< Payload type.
+    uint8_t reserved1 : 2;          //!< Reserved.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+    uint8_t reserved1 : 2;          //!< Payload type.
+    uint8_t payloadType : 6;        //!< Reserved.
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t payloadInstance : 4;    //!< Payload instance.
+    uint8_t reserved2 : 4;          //!< Reserved.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+    uint8_t reserved2 : 4;          //!< Reserved.
+    uint8_t payloadInstance : 4;    //!< Payload instance.
+#endif
+
+    /** @brief No auxiliary data for payload type SOL */
+    uint8_t auxData1;               //!< Auxiliary data 1
+    uint8_t auxData2;               //!< Auxiliary data 2
+    uint8_t auxData3;               //!< Auxiliary data 3
+} __attribute__((packed));
+
+/** @struct DeactivatePayloadResponse
+ *
+ * IPMI payload for Deactivate Payload Command response.
+ */
+struct DeactivatePayloadResponse
+{
+    uint8_t completionCode;         //!< Completion code
+} __attribute__((packed));
+
+/** @brief Deactivate Payload Command.
+ *
+ *  This command is used to terminate use of a given payload on an IPMI session.
+ *  This type of traffic then becomes freed for activation by another session,
+ *  or for possible re-activation under the present session.The Deactivate
+ *  Payload command does not cause the session to be terminated. The Close
+ *  Session command should be used for that purpose. A remote console
+ *  terminating a application does not need to explicitly deactivate payload(s)
+ *  prior to session. When a session terminates all payloads that were active
+ *  under that session are automatically deactivated by the BMC.
+ *
+ * @param[in] inPayload - Request data for the command.
+ * @param[in] handler - Reference to the message handler.
+ *
+ * @return Response data for the command.
+ */
+std::vector<uint8_t> deactivatePayload(std::vector<uint8_t>& inPayload,
+                                       const message::Handler& handler);
+
 } // namespace command
 
 } // namespace sol