| #include "dbus_to_terminus_effecters.hpp" |
| |
| #include <libpldm/pdr.h> |
| #include <libpldm/platform.h> |
| |
| #include <phosphor-logging/lg2.hpp> |
| #include <xyz/openbmc_project/Common/error.hpp> |
| #include <xyz/openbmc_project/State/Boot/Progress/client.hpp> |
| #include <xyz/openbmc_project/State/OperatingSystem/Status/server.hpp> |
| |
| #include <fstream> |
| |
| PHOSPHOR_LOG2_USING; |
| |
| using namespace pldm::utils; |
| |
| namespace pldm |
| { |
| namespace host_effecters |
| { |
| using InternalFailure = |
| sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; |
| |
| constexpr auto hostEffecterJson = "dbus_to_terminus_effecter.json"; |
| |
| void HostEffecterParser::populatePropVals( |
| const Json& dBusValues, std::vector<PropertyValue>& propertyValues, |
| const std::string& propertyType) |
| |
| { |
| for (const auto& elem : dBusValues) |
| { |
| auto value = jsonEntryToDbusVal(propertyType, elem); |
| propertyValues.emplace_back(value); |
| } |
| } |
| |
| void HostEffecterParser::parseEffecterJson(const std::string& jsonPath) |
| { |
| fs::path jsonDir(jsonPath); |
| if (!fs::exists(jsonDir) || fs::is_empty(jsonDir)) |
| { |
| error("Effecter json file for remote terminus '{PATH}' does not exist.", |
| "PATH", jsonPath); |
| return; |
| } |
| |
| fs::path jsonFilePath = jsonDir / hostEffecterJson; |
| if (!fs::exists(jsonFilePath)) |
| { |
| error("Json at path '{PATH}' does not exist.", "PATH", jsonFilePath); |
| throw InternalFailure(); |
| } |
| |
| std::ifstream jsonFile(jsonFilePath); |
| auto data = Json::parse(jsonFile, nullptr, false); |
| if (data.is_discarded()) |
| { |
| error("Failed to parse json file {PATH}", "PATH", jsonFilePath); |
| throw InternalFailure(); |
| } |
| const Json empty{}; |
| const std::vector<Json> emptyList{}; |
| |
| auto entries = data.value("entries", emptyList); |
| for (const auto& entry : entries) |
| { |
| EffecterInfo effecterInfo; |
| effecterInfo.mctpEid = entry.value("mctp_eid", 0xFF); |
| auto jsonEffecterInfo = entry.value("effecter_info", empty); |
| auto effecterId = |
| jsonEffecterInfo.value("effecterID", PLDM_INVALID_EFFECTER_ID); |
| /* default as PLDM_STATE_EFFECTER_PDR */ |
| auto effecterPdrType = |
| jsonEffecterInfo.value("effecterPdrType", PLDM_STATE_EFFECTER_PDR); |
| if (effecterPdrType != PLDM_STATE_EFFECTER_PDR && |
| effecterPdrType != PLDM_NUMERIC_EFFECTER_PDR) |
| { |
| error( |
| "Effecter PDRType not supported {TYPE} of effecterID '{EFFECTERID}'", |
| "TYPE", effecterPdrType, "EFFECTERID", effecterId); |
| continue; |
| } |
| effecterInfo.effecterPdrType = effecterPdrType; |
| effecterInfo.containerId = jsonEffecterInfo.value("containerID", 0); |
| effecterInfo.entityType = jsonEffecterInfo.value("entityType", 0); |
| effecterInfo.entityInstance = |
| jsonEffecterInfo.value("entityInstance", 0); |
| effecterInfo.compEffecterCnt = |
| jsonEffecterInfo.value("compositeEffecterCount", 0); |
| effecterInfo.checkHostState = |
| jsonEffecterInfo.value("checkHostState", true); |
| auto effecters = entry.value("effecters", emptyList); |
| |
| if (effecterPdrType == PLDM_NUMERIC_EFFECTER_PDR) |
| { |
| for (const auto& effecter : effecters) |
| { |
| DBusNumericEffecterMapping dbusInfo{}; |
| auto jsonDbusInfo = effecter.value("dbus_info", empty); |
| dbusInfo.dataSize = effecter.value("effecterDataSize", 0); |
| dbusInfo.unitModifier = effecter.value("unitModifier", 0); |
| dbusInfo.resolution = effecter.value("resolution", 1); |
| dbusInfo.offset = effecter.value("offset", 0); |
| dbusInfo.dbusMap.objectPath = |
| jsonDbusInfo.value("object_path", ""); |
| dbusInfo.dbusMap.interface = |
| jsonDbusInfo.value("interface", ""); |
| dbusInfo.dbusMap.propertyName = |
| jsonDbusInfo.value("property_name", ""); |
| dbusInfo.dbusMap.propertyType = |
| jsonDbusInfo.value("property_type", ""); |
| /** |
| * Only support these property type for Numeric Effecter D-Bus |
| * property: |
| * "uint8_t", "int16_t", "uint16_t", "int32_t", "uint32_t", |
| * "int64_t", "uint64_t", "double" |
| */ |
| if (!dbusValueNumericTypeNames.contains( |
| dbusInfo.dbusMap.propertyType)) |
| { |
| lg2::error( |
| "Invalid PropertyType {TYPE} of object path {PATH} property name {NAME}", |
| "TYPE", dbusInfo.dbusMap.propertyType, "PATH", |
| dbusInfo.dbusMap.objectPath, "NAME", |
| dbusInfo.dbusMap.propertyName); |
| continue; |
| } |
| |
| dbusInfo.propertyValue = |
| std::numeric_limits<double>::quiet_NaN(); |
| auto effecterInfoIndex = hostEffecterInfo.size(); |
| auto dbusInfoIndex = effecterInfo.dbusInfo.size(); |
| createHostEffecterMatch( |
| dbusInfo.dbusMap.objectPath, dbusInfo.dbusMap.interface, |
| effecterInfoIndex, dbusInfoIndex, effecterId); |
| effecterInfo.dbusNumericEffecterInfo.emplace_back( |
| std::move(dbusInfo)); |
| } |
| hostEffecterInfo.emplace_back(std::move(effecterInfo)); |
| continue; |
| } |
| |
| for (const auto& effecter : effecters) |
| { |
| DBusEffecterMapping dbusInfo{}; |
| auto jsonDbusInfo = effecter.value("dbus_info", empty); |
| dbusInfo.dbusMap.objectPath = jsonDbusInfo.value("object_path", ""); |
| dbusInfo.dbusMap.interface = jsonDbusInfo.value("interface", ""); |
| dbusInfo.dbusMap.propertyName = |
| jsonDbusInfo.value("property_name", ""); |
| dbusInfo.dbusMap.propertyType = |
| jsonDbusInfo.value("property_type", ""); |
| Json propertyValues = jsonDbusInfo["property_values"]; |
| |
| populatePropVals(propertyValues, dbusInfo.propertyValues, |
| dbusInfo.dbusMap.propertyType); |
| |
| const std::vector<uint8_t> emptyStates{}; |
| auto state = effecter.value("state", empty); |
| dbusInfo.state.stateSetId = state.value("id", 0); |
| auto states = state.value("state_values", emptyStates); |
| if (dbusInfo.propertyValues.size() != states.size()) |
| { |
| error( |
| "Number of states do not match with number of D-Bus property values in the json. Object path at '{PATH}' and property '{PROPERTY}' will not be monitored", |
| "PATH", dbusInfo.dbusMap.objectPath, "PROPERTY", |
| dbusInfo.dbusMap.propertyName); |
| continue; |
| } |
| for (const auto& s : states) |
| { |
| dbusInfo.state.states.emplace_back(s); |
| } |
| |
| auto effecterInfoIndex = hostEffecterInfo.size(); |
| auto dbusInfoIndex = effecterInfo.dbusInfo.size(); |
| createHostEffecterMatch( |
| dbusInfo.dbusMap.objectPath, dbusInfo.dbusMap.interface, |
| effecterInfoIndex, dbusInfoIndex, effecterId); |
| effecterInfo.dbusInfo.emplace_back(std::move(dbusInfo)); |
| } |
| hostEffecterInfo.emplace_back(std::move(effecterInfo)); |
| } |
| } |
| |
| bool HostEffecterParser::isHostOn(void) |
| { |
| using BootProgress = |
| sdbusplus::client::xyz::openbmc_project::state::boot::Progress<>; |
| constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0"; |
| try |
| { |
| auto propVal = dbusHandler->getDbusPropertyVariant( |
| hostStatePath, "BootProgress", BootProgress::interface); |
| |
| using Stages = BootProgress::ProgressStages; |
| auto currHostState = sdbusplus::message::convert_from_string<Stages>( |
| std::get<std::string>(propVal)) |
| .value(); |
| |
| if (currHostState != Stages::SystemInitComplete && |
| currHostState != Stages::OSRunning && |
| currHostState != Stages::SystemSetup && |
| currHostState != Stages::OEM) |
| { |
| info( |
| "Remote terminus is not up/active, current remote terminus state is: '{CURRENT_HOST_STATE}'", |
| "CURRENT_HOST_STATE", currHostState); |
| return false; |
| } |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| error( |
| "Error in getting current remote terminus state. Will still continue to set the remote terminus effecter, error - {ERROR}", |
| "ERROR", e); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| void HostEffecterParser::processHostEffecterChangeNotification( |
| const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex, |
| size_t dbusInfoIndex, uint16_t effecterId) |
| { |
| const auto& pdrType = hostEffecterInfo[effecterInfoIndex].effecterPdrType; |
| if (pdrType == PLDM_NUMERIC_EFFECTER_PDR) |
| { |
| processTerminusNumericEffecterChangeNotification( |
| chProperties, effecterInfoIndex, dbusInfoIndex, effecterId); |
| return; |
| } |
| const auto& propertyName = hostEffecterInfo[effecterInfoIndex] |
| .dbusInfo[dbusInfoIndex] |
| .dbusMap.propertyName; |
| |
| const auto& it = chProperties.find(propertyName); |
| |
| if (it == chProperties.end()) |
| { |
| return; |
| } |
| |
| if (effecterId == PLDM_INVALID_EFFECTER_ID) |
| { |
| constexpr auto localOrRemote = false; |
| effecterId = findStateEffecterId( |
| pdrRepo, hostEffecterInfo[effecterInfoIndex].entityType, |
| hostEffecterInfo[effecterInfoIndex].entityInstance, |
| hostEffecterInfo[effecterInfoIndex].containerId, |
| hostEffecterInfo[effecterInfoIndex] |
| .dbusInfo[dbusInfoIndex] |
| .state.stateSetId, |
| localOrRemote); |
| if (effecterId == PLDM_INVALID_EFFECTER_ID) |
| { |
| error( |
| "Effecter ID '{EFFECTERID}' of entity type '{TYPE}', entityInstance '{INSTANCE}' and containerID '{CONTAINER_ID}' not found in pdr repo", |
| "EFFECTERID", effecterId, "TYPE", |
| hostEffecterInfo[effecterInfoIndex].entityType, "INSTANCE", |
| hostEffecterInfo[effecterInfoIndex].entityInstance, |
| "CONTAINER_ID", |
| hostEffecterInfo[effecterInfoIndex].containerId); |
| return; |
| } |
| } |
| |
| if (!isHostOn()) |
| { |
| return; |
| } |
| |
| uint8_t newState{}; |
| try |
| { |
| newState = |
| findNewStateValue(effecterInfoIndex, dbusInfoIndex, it->second); |
| } |
| catch (const std::out_of_range& e) |
| { |
| error("Failed to find new state '{NEW_STATE}' in json, error - {ERROR}", |
| "ERROR", e, "NEW_STATE", newState); |
| return; |
| } |
| |
| std::vector<set_effecter_state_field> stateField; |
| for (uint8_t i = 0; i < hostEffecterInfo[effecterInfoIndex].compEffecterCnt; |
| i++) |
| { |
| if (i == dbusInfoIndex) |
| { |
| stateField.push_back({PLDM_REQUEST_SET, newState}); |
| } |
| else |
| { |
| stateField.push_back({PLDM_NO_CHANGE, 0}); |
| } |
| } |
| int rc{}; |
| try |
| { |
| rc = setHostStateEffecter(effecterInfoIndex, stateField, effecterId); |
| } |
| catch (const std::runtime_error& e) |
| { |
| error( |
| "Failed to set remote terminus state effecter for effecter ID '{EFFECTERID}', error - {ERROR}", |
| "ERROR", e, "EFFECTERID", effecterId); |
| return; |
| } |
| if (rc != PLDM_SUCCESS) |
| { |
| error( |
| "Failed to set the remote terminus state effecter for effecter ID '{EFFECTERID}', response code '{RC}'", |
| "EFFECTERID", effecterId, "RC", rc); |
| } |
| } |
| |
| double HostEffecterParser::adjustValue(double value, double offset, |
| double resolution, int8_t modify) |
| { |
| double unitModifier = std::pow(10, signed(modify)); |
| return std::round((value - offset) * resolution / unitModifier); |
| } |
| |
| void HostEffecterParser::processTerminusNumericEffecterChangeNotification( |
| const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex, |
| size_t dbusInfoIndex, uint16_t effecterId) |
| { |
| const auto& checkHost = hostEffecterInfo[effecterInfoIndex].checkHostState; |
| const auto& propValues = hostEffecterInfo[effecterInfoIndex] |
| .dbusNumericEffecterInfo[dbusInfoIndex]; |
| const auto& propertyName = propValues.dbusMap.propertyName; |
| const auto& propertyType = propValues.dbusMap.propertyType; |
| |
| if (effecterId == PLDM_INVALID_EFFECTER_ID) |
| { |
| lg2::error( |
| "Dbus to PLDM Numeric Effecter setting requires valid effecter ID. Invalid effecter ID {EFFECTER_ID}", |
| "EFFECTER_ID", effecterId); |
| } |
| |
| if (!dbusValueNumericTypeNames.contains(propertyType)) |
| { |
| lg2::error( |
| "DBus Value to PLDM Numeric Effecter setting only supports D-Bus Numeric data type. Invalid type {TYPE}", |
| "TYPE", propertyType); |
| return; |
| } |
| |
| const auto& it = chProperties.find(propertyName); |
| |
| if (it == chProperties.end()) |
| { |
| return; |
| } |
| |
| double val = std::numeric_limits<double>::quiet_NaN(); |
| if (!pldm::utils::dbusPropValuesToDouble(propertyType, it->second, &val)) |
| { |
| lg2::error( |
| "DBus Value to PLDM Numeric Effecter setting only supports Numeric D-Bus data type. Invalid type {TYPE}", |
| "TYPE", propertyType); |
| return; |
| } |
| |
| /* Update the current value of D-Bus interface*/ |
| if (!std::isnan(val) && std::isnan(propValues.propertyValue)) |
| { |
| hostEffecterInfo[effecterInfoIndex] |
| .dbusNumericEffecterInfo[dbusInfoIndex] |
| .propertyValue = val; |
| return; |
| } |
| |
| /* Bypass the setting when the current value is NA or setting value is NA */ |
| if (std::isnan(propValues.propertyValue) || std::isnan(val)) |
| { |
| return; |
| } |
| |
| /* Setting value equals the D-Bus value which is real value of effecter */ |
| if (val == propValues.propertyValue) |
| { |
| return; |
| } |
| |
| double rawValue = adjustValue(val, propValues.offset, propValues.resolution, |
| propValues.unitModifier); |
| |
| if (checkHost && !isHostOn()) |
| { |
| return; |
| } |
| |
| try |
| { |
| auto rc = setTerminusNumericEffecter(effecterInfoIndex, effecterId, |
| propValues.dataSize, rawValue); |
| if (rc) |
| { |
| error( |
| "Could not set the numeric effecter ID '{EFFECTERID}' return code '{RC}'", |
| "EFFECTERID", effecterId, "RC", rc); |
| return; |
| } |
| } |
| catch (const std::runtime_error& e) |
| { |
| error("Could not set numeric effecter ID= '{EFFECTERID}'", "EFFECTERID", |
| effecterId); |
| return; |
| } |
| |
| hostEffecterInfo[effecterInfoIndex] |
| .dbusNumericEffecterInfo[dbusInfoIndex] |
| .propertyValue = val; |
| |
| return; |
| } |
| |
| uint8_t HostEffecterParser::findNewStateValue( |
| size_t effecterInfoIndex, size_t dbusInfoIndex, |
| const PropertyValue& propertyValue) |
| { |
| const auto& propValues = hostEffecterInfo[effecterInfoIndex] |
| .dbusInfo[dbusInfoIndex] |
| .propertyValues; |
| auto it = std::find(propValues.begin(), propValues.end(), propertyValue); |
| uint8_t newState{}; |
| if (it != propValues.end()) |
| { |
| auto index = std::distance(propValues.begin(), it); |
| newState = hostEffecterInfo[effecterInfoIndex] |
| .dbusInfo[dbusInfoIndex] |
| .state.states[index]; |
| } |
| else |
| { |
| throw std::out_of_range("new state not found in json"); |
| } |
| return newState; |
| } |
| |
| size_t getEffecterDataSize(uint8_t effecterDataSize) |
| { |
| switch (effecterDataSize) |
| { |
| case PLDM_EFFECTER_DATA_SIZE_UINT8: |
| return sizeof(uint8_t); |
| case PLDM_EFFECTER_DATA_SIZE_SINT8: |
| return sizeof(int8_t); |
| case PLDM_EFFECTER_DATA_SIZE_UINT16: |
| return sizeof(uint16_t); |
| case PLDM_EFFECTER_DATA_SIZE_SINT16: |
| return sizeof(int16_t); |
| case PLDM_EFFECTER_DATA_SIZE_UINT32: |
| return sizeof(uint32_t); |
| case PLDM_EFFECTER_DATA_SIZE_SINT32: |
| return sizeof(int32_t); |
| default: |
| return 0; |
| } |
| } |
| |
| int HostEffecterParser::setTerminusNumericEffecter( |
| size_t effecterInfoIndex, uint16_t effecterId, uint8_t dataSize, |
| double rawValue) |
| { |
| uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid; |
| auto instanceId = instanceIdDb->next(mctpEid); |
| int rc = PLDM_ERROR; |
| std::vector<uint8_t> requestMsg; |
| |
| /** |
| * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES = 4. It includes the 1 byte |
| * value for effecterValue as `Table 48 - SetNumericEffecterValue command |
| * format` DSP0248 V1.3.0 So the payload_length of `SetNumericEffecterValue` |
| * request message will be payload_length = |
| * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 + sizeof(dataType) |
| */ |
| size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 + |
| getEffecterDataSize(dataSize); |
| requestMsg.resize(sizeof(pldm_msg_hdr) + payload_length); |
| auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| switch (dataSize) |
| { |
| case PLDM_EFFECTER_DATA_SIZE_UINT8: |
| { |
| auto value_uint8 = (uint8_t)rawValue; |
| rc = encode_set_numeric_effecter_value_req( |
| instanceId, effecterId, dataSize, |
| reinterpret_cast<uint8_t*>(&value_uint8), request, |
| payload_length); |
| break; |
| } |
| case PLDM_EFFECTER_DATA_SIZE_SINT8: |
| { |
| auto value_int8 = (int8_t)rawValue; |
| rc = encode_set_numeric_effecter_value_req( |
| instanceId, effecterId, dataSize, |
| reinterpret_cast<uint8_t*>(&value_int8), request, |
| payload_length); |
| break; |
| } |
| case PLDM_EFFECTER_DATA_SIZE_UINT16: |
| { |
| auto value_uint16 = (uint16_t)rawValue; |
| rc = encode_set_numeric_effecter_value_req( |
| instanceId, effecterId, dataSize, |
| reinterpret_cast<uint8_t*>(&value_uint16), request, |
| payload_length); |
| break; |
| } |
| case PLDM_EFFECTER_DATA_SIZE_SINT16: |
| { |
| auto value_int16 = (int16_t)rawValue; |
| rc = encode_set_numeric_effecter_value_req( |
| instanceId, effecterId, dataSize, |
| reinterpret_cast<uint8_t*>(&value_int16), request, |
| payload_length); |
| break; |
| } |
| case PLDM_EFFECTER_DATA_SIZE_UINT32: |
| { |
| auto value_uint32 = (uint32_t)rawValue; |
| rc = encode_set_numeric_effecter_value_req( |
| instanceId, effecterId, dataSize, |
| reinterpret_cast<uint8_t*>(&value_uint32), request, |
| payload_length); |
| break; |
| } |
| case PLDM_EFFECTER_DATA_SIZE_SINT32: |
| { |
| auto value_int32 = (int32_t)rawValue; |
| rc = encode_set_numeric_effecter_value_req( |
| instanceId, effecterId, dataSize, |
| reinterpret_cast<uint8_t*>(&value_int32), request, |
| payload_length); |
| break; |
| } |
| default: |
| break; |
| } |
| |
| if (rc) |
| { |
| error( |
| "Failed to encode set numeric effecter request message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with error code '{RC}'", |
| "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex, |
| rc); |
| |
| instanceIdDb->free(mctpEid, instanceId); |
| return rc; |
| } |
| |
| auto setNumericEffecterRespHandler = [effecterId](mctp_eid_t /*eid*/, |
| const pldm_msg* response, |
| size_t respMsgLen) { |
| if (response == nullptr || !respMsgLen) |
| { |
| error( |
| "Failed to receive response for setNumericEffecterValue command"); |
| return; |
| } |
| uint8_t completionCode{}; |
| auto rc = decode_set_numeric_effecter_value_resp(response, respMsgLen, |
| &completionCode); |
| |
| if (rc) |
| { |
| error( |
| "Failed to decode set numeric effecter response message for effecter ID '{EFFECTERID}' with error code '{RC}'", |
| "EFFECTERID", effecterId, "RC", lg2::hex, rc); |
| } |
| if (completionCode) |
| { |
| error( |
| "Failed to set numeric effecter for effecter ID '{EFFECTERID}' with complete code '{CC}'", |
| "EFFECTERID", effecterId, "CC", lg2::hex, completionCode); |
| } |
| }; |
| |
| rc = handler->registerRequest( |
| mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_NUMERIC_EFFECTER_VALUE, |
| std::move(requestMsg), std::move(setNumericEffecterRespHandler)); |
| if (rc) |
| { |
| error("Failed to send request to set an effecter on Host"); |
| } |
| return rc; |
| } |
| |
| int HostEffecterParser::setHostStateEffecter( |
| size_t effecterInfoIndex, std::vector<set_effecter_state_field>& stateField, |
| uint16_t effecterId) |
| { |
| uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid; |
| uint8_t& compEffCnt = hostEffecterInfo[effecterInfoIndex].compEffecterCnt; |
| auto instanceId = instanceIdDb->next(mctpEid); |
| |
| std::vector<uint8_t> requestMsg( |
| sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(compEffCnt) + |
| sizeof(set_effecter_state_field) * compEffCnt, |
| 0); |
| auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| auto rc = encode_set_state_effecter_states_req( |
| instanceId, effecterId, compEffCnt, stateField.data(), request); |
| |
| if (rc != PLDM_SUCCESS) |
| { |
| error( |
| "Failed to encode set state effecter states message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with response code '{RC}'", |
| "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex, |
| rc); |
| instanceIdDb->free(mctpEid, instanceId); |
| return rc; |
| } |
| |
| auto setStateEffecterStatesRespHandler = [](mctp_eid_t /*eid*/, |
| const pldm_msg* response, |
| size_t respMsgLen) { |
| if (response == nullptr || !respMsgLen) |
| { |
| error( |
| "Failed to receive response for setting state effecter states."); |
| return; |
| } |
| uint8_t completionCode{}; |
| auto rc = decode_set_state_effecter_states_resp(response, respMsgLen, |
| &completionCode); |
| if (rc) |
| { |
| error( |
| "Failed to decode response of set state effecter states, response code '{RC}'", |
| "RC", rc); |
| pldm::utils::reportError( |
| "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed"); |
| } |
| if (completionCode) |
| { |
| error( |
| "Failed to set a remote terminus effecter, completion code '{CC}'", |
| "CC", completionCode); |
| pldm::utils::reportError( |
| "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed"); |
| } |
| }; |
| |
| rc = handler->registerRequest( |
| mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES, |
| std::move(requestMsg), std::move(setStateEffecterStatesRespHandler)); |
| if (rc) |
| { |
| error( |
| "Failed to send request to set an effecter on remote terminus for effecter ID '{EFFECTERID}', response code '{RC}'", |
| "EFFECTERID", effecterId, "RC", rc); |
| } |
| return rc; |
| } |
| |
| void HostEffecterParser::createHostEffecterMatch( |
| const std::string& objectPath, const std::string& interface, |
| size_t effecterInfoIndex, size_t dbusInfoIndex, uint16_t effecterId) |
| { |
| using namespace sdbusplus::bus::match::rules; |
| effecterInfoMatch.emplace_back(std::make_unique<sdbusplus::bus::match_t>( |
| pldm::utils::DBusHandler::getBus(), |
| propertiesChanged(objectPath, interface), |
| [this, effecterInfoIndex, dbusInfoIndex, |
| effecterId](sdbusplus::message_t& msg) { |
| DbusChgHostEffecterProps props; |
| std::string iface; |
| msg.read(iface, props); |
| processHostEffecterChangeNotification(props, effecterInfoIndex, |
| dbusInfoIndex, effecterId); |
| })); |
| } |
| |
| } // namespace host_effecters |
| } // namespace pldm |