diff --git a/pldm.cpp b/pldm.cpp
index a65369a..d22a73d 100644
--- a/pldm.cpp
+++ b/pldm.cpp
@@ -1,355 +1,355 @@
-#include "pldm.hpp"
-
-#include "file.hpp"
-
-#include <fmt/core.h>
-#include <libpldm/entity.h>
-#include <libpldm/platform.h>
-#include <libpldm/state_set.h>
-
-#include <phosphor-logging/log.hpp>
-
-namespace pldm
-{
-
-using sdbusplus::exception::SdBusError;
-using namespace phosphor::logging;
-
-void Interface::fetchOCCSensorInfo(const PdrList& pdrs,
-                                   SensorToOCCInstance& sensorInstanceMap,
-                                   SensorOffset& sensorOffset)
-{
-    bool offsetFound = false;
-    auto pdr =
-        reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
-    auto possibleStatesPtr = pdr->possible_states;
-    for (auto offset = 0; offset < pdr->composite_sensor_count; offset++)
-    {
-        auto possibleStates =
-            reinterpret_cast<const state_sensor_possible_states*>(
-                possibleStatesPtr);
-
-        if (possibleStates->state_set_id ==
-            PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS)
-        {
-            sensorOffset = offset;
-            offsetFound = true;
-            break;
-        }
-        possibleStatesPtr += sizeof(possibleStates->state_set_id) +
-                             sizeof(possibleStates->possible_states_size) +
-                             possibleStates->possible_states_size;
-    }
-
-    if (!offsetFound)
-    {
-        log<level::ERR>("pldm: OCC state sensor PDR with StateSetId "
-                        "PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS not found");
-        return;
-    }
-
-    // To order SensorID based on the EntityInstance.
-    // Note that when a proc is on a DCM, the PDRs for these sensors
-    // could have the same instance IDs but different container IDs.
-    std::map<uint32_t, SensorID> entityInstMap{};
-    for (auto& pdr : pdrs)
-    {
-        auto pdrPtr =
-            reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
-        uint32_t key = (static_cast<uint32_t>(pdrPtr->container_id) << 16) |
-                       static_cast<uint32_t>(pdrPtr->entity_instance);
-        entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
-    }
-
-    open_power::occ::instanceID count = start;
-    for (auto const& pair : entityInstMap)
-    {
-        sensorInstanceMap.emplace(pair.second, count);
-        count++;
-    }
-}
-
-void Interface::sensorEvent(sdbusplus::message::message& msg)
-{
-    if (!isOCCSensorCacheValid())
-    {
-        PdrList pdrs{};
-
-        auto& bus = open_power::occ::utils::getBus();
-        try
-        {
-            auto method = bus.new_method_call(
-                "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
-                "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
-            method.append(tid, (uint16_t)PLDM_ENTITY_PROC,
-                          (uint16_t)PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS);
-
-            auto responseMsg = bus.call(method);
-            responseMsg.read(pdrs);
-        }
-        catch (const SdBusError& e)
-        {
-            log<level::ERR>("pldm: Failed to fetch the OCC state sensor PDRs",
-                            entry("ERROR=%s", e.what()));
-        }
-
-        if (!pdrs.size())
-        {
-            log<level::ERR>("pldm: OCC state sensor PDRs not present");
-            return;
-        }
-
-        fetchOCCSensorInfo(pdrs, sensorToOCCInstance, sensorOffset);
-    }
-
-    TerminusID tid{};
-    SensorID sensorId{};
-    SensorOffset msgSensorOffset{};
-    EventState eventState{};
-    EventState previousEventState{};
-
-    msg.read(tid, sensorId, msgSensorOffset, eventState, previousEventState);
-
-    auto sensorEntry = sensorToOCCInstance.find(sensorId);
-    if (sensorEntry == sensorToOCCInstance.end() ||
-        (msgSensorOffset != sensorOffset))
-    {
-        // No action for non matching sensorEvents
-        return;
-    }
-
-    if (eventState == static_cast<EventState>(
-                          PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
-    {
-        log<level::INFO>(
-            fmt::format("PLDM: OCC{} is RUNNING", sensorEntry->second).c_str());
-        callBack(sensorEntry->second, true);
-    }
-    else if (eventState ==
-             static_cast<EventState>(
-                 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
-    {
-        log<level::INFO>(
-            fmt::format("PLDM: OCC{} has now STOPPED", sensorEntry->second)
-                .c_str());
-        callBack(sensorEntry->second, false);
-    }
-
-    return;
-}
-
-void Interface::hostStateEvent(sdbusplus::message::message& msg)
-{
-    std::map<std::string, std::variant<std::string>> properties{};
-    std::string interface;
-    msg.read(interface, properties);
-    const auto stateEntry = properties.find("CurrentHostState");
-    if (stateEntry != properties.end())
-    {
-        auto stateEntryValue = stateEntry->second;
-        auto propVal = std::get<std::string>(stateEntryValue);
-        if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
-        {
-            sensorToOCCInstance.clear();
-            occInstanceToEffecter.clear();
-        }
-    }
-}
-
-void Interface::fetchOCCEffecterInfo(
-    const PdrList& pdrs, OccInstanceToEffecter& instanceToEffecterMap,
-    CompositeEffecterCount& count, uint8_t& bootRestartPos)
-{
-    bool offsetFound = false;
-    auto pdr =
-        reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
-    auto possibleStatesPtr = pdr->possible_states;
-    for (auto offset = 0; offset < pdr->composite_effecter_count; offset++)
-    {
-        auto possibleStates =
-            reinterpret_cast<const state_effecter_possible_states*>(
-                possibleStatesPtr);
-
-        if (possibleStates->state_set_id == PLDM_STATE_SET_BOOT_RESTART_CAUSE)
-        {
-            bootRestartPos = offset;
-            effecterCount = pdr->composite_effecter_count;
-            offsetFound = true;
-            break;
-        }
-        possibleStatesPtr += sizeof(possibleStates->state_set_id) +
-                             sizeof(possibleStates->possible_states_size) +
-                             possibleStates->possible_states_size;
-    }
-
-    if (!offsetFound)
-    {
-        return;
-    }
-
-    std::map<EntityInstance, EffecterID> entityInstMap{};
-    for (auto& pdr : pdrs)
-    {
-        auto pdrPtr =
-            reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
-        uint32_t key = (static_cast<uint32_t>(pdrPtr->container_id) << 16) |
-                       static_cast<uint32_t>(pdrPtr->entity_instance);
-        entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id));
-    }
-
-    open_power::occ::instanceID position = start;
-    for (auto const& pair : entityInstMap)
-    {
-        occInstanceToEffecter.emplace(position, pair.second);
-        position++;
-    }
-}
-
-std::vector<uint8_t>
-    Interface::prepareSetEffecterReq(uint8_t instanceId, EffecterID effecterId,
-                                     CompositeEffecterCount effecterCount,
-                                     uint8_t bootRestartPos)
-{
-    std::vector<uint8_t> request(
-        sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
-        (effecterCount * sizeof(set_effecter_state_field)));
-    auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
-    std::vector<set_effecter_state_field> stateField;
-
-    for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
-    {
-        if (effecterPos == bootRestartPos)
-        {
-            stateField.emplace_back(set_effecter_state_field{
-                PLDM_REQUEST_SET,
-                PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET});
-        }
-        else
-        {
-            stateField.emplace_back(
-                set_effecter_state_field{PLDM_NO_CHANGE, 0});
-        }
-    }
-    auto rc = encode_set_state_effecter_states_req(
-        instanceId, effecterId, effecterCount, stateField.data(), requestMsg);
-    if (rc != PLDM_SUCCESS)
-    {
-        log<level::ERR>("encode set effecter states request returned error ",
-                        entry("RC=%d", rc));
-        request.clear();
-    }
-    return request;
-}
-
-void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
-{
-    if (!isPDREffecterCacheValid())
-    {
-        PdrList pdrs{};
-
-        auto& bus = open_power::occ::utils::getBus();
-        try
-        {
-            auto method = bus.new_method_call(
-                "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
-                "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
-            method.append(tid, (uint16_t)PLDM_ENTITY_PROC_MODULE,
-                          (uint16_t)PLDM_STATE_SET_BOOT_RESTART_CAUSE);
-
-            auto responseMsg = bus.call(method);
-            responseMsg.read(pdrs);
-        }
-        catch (const SdBusError& e)
-        {
-            log<level::ERR>("pldm: Failed to fetch the OCC state effecter PDRs",
-                            entry("ERROR=%s", e.what()));
-        }
-
-        if (!pdrs.size())
-        {
-            log<level::ERR>("pldm: OCC state effecter PDRs not present");
-            return;
-        }
-
-        fetchOCCEffecterInfo(pdrs, occInstanceToEffecter, effecterCount,
-                             bootRestartPosition);
-    }
-
-    // Find the matching effecter for the OCC instance
-    auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
-    if (effecterEntry == occInstanceToEffecter.end())
-    {
-        log<level::ERR>(
-            "pldm: Failed to find a matching effecter for OCC instance",
-            entry("OCC_INSTANCE_ID=%d", occInstanceId));
-
-        return;
-    }
-
-    uint8_t instanceId{};
-
-    auto& bus = open_power::occ::utils::getBus();
-    try
-    {
-        auto method = bus.new_method_call(
-            "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
-            "xyz.openbmc_project.PLDM.Requester", "GetInstanceId");
-        method.append(mctpEid);
-        auto reply = bus.call(method);
-        reply.read(instanceId);
-    }
-    catch (const SdBusError& e)
-    {
-        log<level::ERR>("pldm: GetInstanceId returned error",
-                        entry("ERROR=%s", e.what()));
-        return;
-    }
-
-    // Prepare the SetStateEffecterStates request to reset the OCC
-    auto request = prepareSetEffecterReq(instanceId, effecterEntry->second,
-                                         effecterCount, bootRestartPosition);
-
-    if (request.empty())
-    {
-        log<level::ERR>("pldm: SetStateEffecterStates request message empty");
-        return;
-    }
-
-    // Connect to MCTP scoket
-    int fd = pldm_open();
-    if (fd == -1)
-    {
-        log<level::ERR>("pldm: Failed to connect to MCTP socket");
-        return;
-    }
-    open_power::occ::FileDescriptor fileFd(fd);
-
-    // Send the PLDM request message to HBRT
-    uint8_t* response = nullptr;
-    size_t responseSize{};
-    auto rc = pldm_send_recv(mctpEid, fileFd(), request.data(), request.size(),
-                             &response, &responseSize);
-    std::unique_ptr<uint8_t, decltype(std::free)*> responsePtr{response,
-                                                               std::free};
-    if (rc)
-    {
-        log<level::ERR>("pldm: pldm_send_recv failed for OCC reset",
-                        entry("RC=%d", rc));
-    }
-
-    uint8_t completionCode{};
-    auto responseMsg = reinterpret_cast<const pldm_msg*>(responsePtr.get());
-    auto rcDecode = decode_set_state_effecter_states_resp(
-        responseMsg, responseSize - sizeof(pldm_msg_hdr), &completionCode);
-    if (rcDecode || completionCode)
-    {
-        log<level::ERR>(
-            "pldm: decode_set_state_effecter_states_resp returned error",
-            entry("RC=%d", rcDecode),
-            entry("COMPLETION_CODE=%d", completionCode));
-    }
-
-    return;
-}
-
-} // namespace pldm
+#include "pldm.hpp"
+
+#include "file.hpp"
+
+#include <fmt/core.h>
+#include <libpldm/entity.h>
+#include <libpldm/platform.h>
+#include <libpldm/state_set.h>
+
+#include <phosphor-logging/log.hpp>
+
+namespace pldm
+{
+
+using sdbusplus::exception::SdBusError;
+using namespace phosphor::logging;
+
+void Interface::fetchOCCSensorInfo(const PdrList& pdrs,
+                                   SensorToOCCInstance& sensorInstanceMap,
+                                   SensorOffset& sensorOffset)
+{
+    bool offsetFound = false;
+    auto pdr =
+        reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
+    auto possibleStatesPtr = pdr->possible_states;
+    for (auto offset = 0; offset < pdr->composite_sensor_count; offset++)
+    {
+        auto possibleStates =
+            reinterpret_cast<const state_sensor_possible_states*>(
+                possibleStatesPtr);
+
+        if (possibleStates->state_set_id ==
+            PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS)
+        {
+            sensorOffset = offset;
+            offsetFound = true;
+            break;
+        }
+        possibleStatesPtr += sizeof(possibleStates->state_set_id) +
+                             sizeof(possibleStates->possible_states_size) +
+                             possibleStates->possible_states_size;
+    }
+
+    if (!offsetFound)
+    {
+        log<level::ERR>("pldm: OCC state sensor PDR with StateSetId "
+                        "PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS not found");
+        return;
+    }
+
+    // To order SensorID based on the EntityInstance.
+    // Note that when a proc is on a DCM, the PDRs for these sensors
+    // could have the same instance IDs but different container IDs.
+    std::map<uint32_t, SensorID> entityInstMap{};
+    for (auto& pdr : pdrs)
+    {
+        auto pdrPtr =
+            reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
+        uint32_t key = (static_cast<uint32_t>(pdrPtr->container_id) << 16) |
+                       static_cast<uint32_t>(pdrPtr->entity_instance);
+        entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
+    }
+
+    open_power::occ::instanceID count = start;
+    for (auto const& pair : entityInstMap)
+    {
+        sensorInstanceMap.emplace(pair.second, count);
+        count++;
+    }
+}
+
+void Interface::sensorEvent(sdbusplus::message::message& msg)
+{
+    if (!isOCCSensorCacheValid())
+    {
+        PdrList pdrs{};
+
+        auto& bus = open_power::occ::utils::getBus();
+        try
+        {
+            auto method = bus.new_method_call(
+                "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
+                "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
+            method.append(tid, (uint16_t)PLDM_ENTITY_PROC,
+                          (uint16_t)PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS);
+
+            auto responseMsg = bus.call(method);
+            responseMsg.read(pdrs);
+        }
+        catch (const SdBusError& e)
+        {
+            log<level::ERR>("pldm: Failed to fetch the OCC state sensor PDRs",
+                            entry("ERROR=%s", e.what()));
+        }
+
+        if (!pdrs.size())
+        {
+            log<level::ERR>("pldm: OCC state sensor PDRs not present");
+            return;
+        }
+
+        fetchOCCSensorInfo(pdrs, sensorToOCCInstance, sensorOffset);
+    }
+
+    TerminusID tid{};
+    SensorID sensorId{};
+    SensorOffset msgSensorOffset{};
+    EventState eventState{};
+    EventState previousEventState{};
+
+    msg.read(tid, sensorId, msgSensorOffset, eventState, previousEventState);
+
+    auto sensorEntry = sensorToOCCInstance.find(sensorId);
+    if (sensorEntry == sensorToOCCInstance.end() ||
+        (msgSensorOffset != sensorOffset))
+    {
+        // No action for non matching sensorEvents
+        return;
+    }
+
+    if (eventState == static_cast<EventState>(
+                          PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
+    {
+        log<level::INFO>(
+            fmt::format("PLDM: OCC{} is RUNNING", sensorEntry->second).c_str());
+        callBack(sensorEntry->second, true);
+    }
+    else if (eventState ==
+             static_cast<EventState>(
+                 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
+    {
+        log<level::INFO>(
+            fmt::format("PLDM: OCC{} has now STOPPED", sensorEntry->second)
+                .c_str());
+        callBack(sensorEntry->second, false);
+    }
+
+    return;
+}
+
+void Interface::hostStateEvent(sdbusplus::message::message& msg)
+{
+    std::map<std::string, std::variant<std::string>> properties{};
+    std::string interface;
+    msg.read(interface, properties);
+    const auto stateEntry = properties.find("CurrentHostState");
+    if (stateEntry != properties.end())
+    {
+        auto stateEntryValue = stateEntry->second;
+        auto propVal = std::get<std::string>(stateEntryValue);
+        if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
+        {
+            sensorToOCCInstance.clear();
+            occInstanceToEffecter.clear();
+        }
+    }
+}
+
+void Interface::fetchOCCEffecterInfo(
+    const PdrList& pdrs, OccInstanceToEffecter& instanceToEffecterMap,
+    CompositeEffecterCount& count, uint8_t& bootRestartPos)
+{
+    bool offsetFound = false;
+    auto pdr =
+        reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
+    auto possibleStatesPtr = pdr->possible_states;
+    for (auto offset = 0; offset < pdr->composite_effecter_count; offset++)
+    {
+        auto possibleStates =
+            reinterpret_cast<const state_effecter_possible_states*>(
+                possibleStatesPtr);
+
+        if (possibleStates->state_set_id == PLDM_STATE_SET_BOOT_RESTART_CAUSE)
+        {
+            bootRestartPos = offset;
+            effecterCount = pdr->composite_effecter_count;
+            offsetFound = true;
+            break;
+        }
+        possibleStatesPtr += sizeof(possibleStates->state_set_id) +
+                             sizeof(possibleStates->possible_states_size) +
+                             possibleStates->possible_states_size;
+    }
+
+    if (!offsetFound)
+    {
+        return;
+    }
+
+    std::map<EntityInstance, EffecterID> entityInstMap{};
+    for (auto& pdr : pdrs)
+    {
+        auto pdrPtr =
+            reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
+        uint32_t key = (static_cast<uint32_t>(pdrPtr->container_id) << 16) |
+                       static_cast<uint32_t>(pdrPtr->entity_instance);
+        entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id));
+    }
+
+    open_power::occ::instanceID position = start;
+    for (auto const& pair : entityInstMap)
+    {
+        occInstanceToEffecter.emplace(position, pair.second);
+        position++;
+    }
+}
+
+std::vector<uint8_t>
+    Interface::prepareSetEffecterReq(uint8_t instanceId, EffecterID effecterId,
+                                     CompositeEffecterCount effecterCount,
+                                     uint8_t bootRestartPos)
+{
+    std::vector<uint8_t> request(
+        sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
+        (effecterCount * sizeof(set_effecter_state_field)));
+    auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
+    std::vector<set_effecter_state_field> stateField;
+
+    for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
+    {
+        if (effecterPos == bootRestartPos)
+        {
+            stateField.emplace_back(set_effecter_state_field{
+                PLDM_REQUEST_SET,
+                PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET});
+        }
+        else
+        {
+            stateField.emplace_back(
+                set_effecter_state_field{PLDM_NO_CHANGE, 0});
+        }
+    }
+    auto rc = encode_set_state_effecter_states_req(
+        instanceId, effecterId, effecterCount, stateField.data(), requestMsg);
+    if (rc != PLDM_SUCCESS)
+    {
+        log<level::ERR>("encode set effecter states request returned error ",
+                        entry("RC=%d", rc));
+        request.clear();
+    }
+    return request;
+}
+
+void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
+{
+    if (!isPDREffecterCacheValid())
+    {
+        PdrList pdrs{};
+
+        auto& bus = open_power::occ::utils::getBus();
+        try
+        {
+            auto method = bus.new_method_call(
+                "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
+                "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
+            method.append(tid, (uint16_t)PLDM_ENTITY_PROC_MODULE,
+                          (uint16_t)PLDM_STATE_SET_BOOT_RESTART_CAUSE);
+
+            auto responseMsg = bus.call(method);
+            responseMsg.read(pdrs);
+        }
+        catch (const SdBusError& e)
+        {
+            log<level::ERR>("pldm: Failed to fetch the OCC state effecter PDRs",
+                            entry("ERROR=%s", e.what()));
+        }
+
+        if (!pdrs.size())
+        {
+            log<level::ERR>("pldm: OCC state effecter PDRs not present");
+            return;
+        }
+
+        fetchOCCEffecterInfo(pdrs, occInstanceToEffecter, effecterCount,
+                             bootRestartPosition);
+    }
+
+    // Find the matching effecter for the OCC instance
+    auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
+    if (effecterEntry == occInstanceToEffecter.end())
+    {
+        log<level::ERR>(
+            "pldm: Failed to find a matching effecter for OCC instance",
+            entry("OCC_INSTANCE_ID=%d", occInstanceId));
+
+        return;
+    }
+
+    uint8_t instanceId{};
+
+    auto& bus = open_power::occ::utils::getBus();
+    try
+    {
+        auto method = bus.new_method_call(
+            "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
+            "xyz.openbmc_project.PLDM.Requester", "GetInstanceId");
+        method.append(mctpEid);
+        auto reply = bus.call(method);
+        reply.read(instanceId);
+    }
+    catch (const SdBusError& e)
+    {
+        log<level::ERR>("pldm: GetInstanceId returned error",
+                        entry("ERROR=%s", e.what()));
+        return;
+    }
+
+    // Prepare the SetStateEffecterStates request to reset the OCC
+    auto request = prepareSetEffecterReq(instanceId, effecterEntry->second,
+                                         effecterCount, bootRestartPosition);
+
+    if (request.empty())
+    {
+        log<level::ERR>("pldm: SetStateEffecterStates request message empty");
+        return;
+    }
+
+    // Connect to MCTP scoket
+    int fd = pldm_open();
+    if (fd == -1)
+    {
+        log<level::ERR>("pldm: Failed to connect to MCTP socket");
+        return;
+    }
+    open_power::occ::FileDescriptor fileFd(fd);
+
+    // Send the PLDM request message to HBRT
+    uint8_t* response = nullptr;
+    size_t responseSize{};
+    auto rc = pldm_send_recv(mctpEid, fileFd(), request.data(), request.size(),
+                             &response, &responseSize);
+    std::unique_ptr<uint8_t, decltype(std::free)*> responsePtr{response,
+                                                               std::free};
+    if (rc)
+    {
+        log<level::ERR>("pldm: pldm_send_recv failed for OCC reset",
+                        entry("RC=%d", rc));
+    }
+
+    uint8_t completionCode{};
+    auto responseMsg = reinterpret_cast<const pldm_msg*>(responsePtr.get());
+    auto rcDecode = decode_set_state_effecter_states_resp(
+        responseMsg, responseSize - sizeof(pldm_msg_hdr), &completionCode);
+    if (rcDecode || completionCode)
+    {
+        log<level::ERR>(
+            "pldm: decode_set_state_effecter_states_resp returned error",
+            entry("RC=%d", rcDecode),
+            entry("COMPLETION_CODE=%d", completionCode));
+    }
+
+    return;
+}
+
+} // namespace pldm
