1 #include "dbus_to_terminus_effecters.hpp" 2 3 #include <libpldm/pdr.h> 4 #include <libpldm/platform.h> 5 6 #include <phosphor-logging/lg2.hpp> 7 #include <xyz/openbmc_project/Common/error.hpp> 8 #include <xyz/openbmc_project/State/Boot/Progress/client.hpp> 9 #include <xyz/openbmc_project/State/OperatingSystem/Status/server.hpp> 10 11 #include <fstream> 12 13 PHOSPHOR_LOG2_USING; 14 15 using namespace pldm::utils; 16 17 namespace pldm 18 { 19 namespace host_effecters 20 { 21 using InternalFailure = 22 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 23 24 constexpr auto hostEffecterJson = "dbus_to_terminus_effecter.json"; 25 26 void HostEffecterParser::populatePropVals( 27 const Json& dBusValues, std::vector<PropertyValue>& propertyValues, 28 const std::string& propertyType) 29 30 { 31 for (const auto& elem : dBusValues) 32 { 33 auto value = jsonEntryToDbusVal(propertyType, elem); 34 propertyValues.emplace_back(value); 35 } 36 } 37 38 void HostEffecterParser::parseEffecterJson(const std::string& jsonPath) 39 { 40 fs::path jsonDir(jsonPath); 41 if (!fs::exists(jsonDir) || fs::is_empty(jsonDir)) 42 { 43 error("Effecter json file for remote terminus '{PATH}' does not exist.", 44 "PATH", jsonPath); 45 return; 46 } 47 48 fs::path jsonFilePath = jsonDir / hostEffecterJson; 49 if (!fs::exists(jsonFilePath)) 50 { 51 error("Json at path '{PATH}' does not exist.", "PATH", jsonFilePath); 52 throw InternalFailure(); 53 } 54 55 std::ifstream jsonFile(jsonFilePath); 56 auto data = Json::parse(jsonFile, nullptr, false); 57 if (data.is_discarded()) 58 { 59 error("Failed to parse json file {PATH}", "PATH", jsonFilePath); 60 throw InternalFailure(); 61 } 62 const Json empty{}; 63 const std::vector<Json> emptyList{}; 64 65 auto entries = data.value("entries", emptyList); 66 for (const auto& entry : entries) 67 { 68 EffecterInfo effecterInfo; 69 effecterInfo.mctpEid = entry.value("mctp_eid", 0xFF); 70 auto jsonEffecterInfo = entry.value("effecter_info", empty); 71 auto effecterId = 72 jsonEffecterInfo.value("effecterID", PLDM_INVALID_EFFECTER_ID); 73 /* default as PLDM_STATE_EFFECTER_PDR */ 74 auto effecterPdrType = 75 jsonEffecterInfo.value("effecterPdrType", PLDM_STATE_EFFECTER_PDR); 76 if (effecterPdrType != PLDM_STATE_EFFECTER_PDR && 77 effecterPdrType != PLDM_NUMERIC_EFFECTER_PDR) 78 { 79 error( 80 "Effecter PDRType not supported {TYPE} of effecterID '{EFFECTERID}'", 81 "TYPE", effecterPdrType, "EFFECTERID", effecterId); 82 continue; 83 } 84 effecterInfo.effecterPdrType = effecterPdrType; 85 effecterInfo.containerId = jsonEffecterInfo.value("containerID", 0); 86 effecterInfo.entityType = jsonEffecterInfo.value("entityType", 0); 87 effecterInfo.entityInstance = 88 jsonEffecterInfo.value("entityInstance", 0); 89 effecterInfo.compEffecterCnt = 90 jsonEffecterInfo.value("compositeEffecterCount", 0); 91 effecterInfo.checkHostState = 92 jsonEffecterInfo.value("checkHostState", true); 93 auto effecters = entry.value("effecters", emptyList); 94 95 if (effecterPdrType == PLDM_NUMERIC_EFFECTER_PDR) 96 { 97 for (const auto& effecter : effecters) 98 { 99 DBusNumericEffecterMapping dbusInfo{}; 100 auto jsonDbusInfo = effecter.value("dbus_info", empty); 101 dbusInfo.dataSize = effecter.value("effecterDataSize", 0); 102 dbusInfo.unitModifier = effecter.value("unitModifier", 0); 103 dbusInfo.resolution = effecter.value("resolution", 1); 104 dbusInfo.offset = effecter.value("offset", 0); 105 dbusInfo.dbusMap.objectPath = 106 jsonDbusInfo.value("object_path", ""); 107 dbusInfo.dbusMap.interface = 108 jsonDbusInfo.value("interface", ""); 109 dbusInfo.dbusMap.propertyName = 110 jsonDbusInfo.value("property_name", ""); 111 dbusInfo.dbusMap.propertyType = 112 jsonDbusInfo.value("property_type", ""); 113 /** 114 * Only support these property type for Numeric Effecter D-Bus 115 * property: 116 * "uint8_t", "int16_t", "uint16_t", "int32_t", "uint32_t", 117 * "int64_t", "uint64_t", "double" 118 */ 119 if (!dbusValueNumericTypeNames.contains( 120 dbusInfo.dbusMap.propertyType)) 121 { 122 lg2::error( 123 "Invalid PropertyType {TYPE} of object path {PATH} property name {NAME}", 124 "TYPE", dbusInfo.dbusMap.propertyType, "PATH", 125 dbusInfo.dbusMap.objectPath, "NAME", 126 dbusInfo.dbusMap.propertyName); 127 continue; 128 } 129 130 dbusInfo.propertyValue = 131 std::numeric_limits<double>::quiet_NaN(); 132 auto effecterInfoIndex = hostEffecterInfo.size(); 133 auto dbusInfoIndex = effecterInfo.dbusInfo.size(); 134 createHostEffecterMatch( 135 dbusInfo.dbusMap.objectPath, dbusInfo.dbusMap.interface, 136 effecterInfoIndex, dbusInfoIndex, effecterId); 137 effecterInfo.dbusNumericEffecterInfo.emplace_back( 138 std::move(dbusInfo)); 139 } 140 hostEffecterInfo.emplace_back(std::move(effecterInfo)); 141 continue; 142 } 143 144 for (const auto& effecter : effecters) 145 { 146 DBusEffecterMapping dbusInfo{}; 147 auto jsonDbusInfo = effecter.value("dbus_info", empty); 148 dbusInfo.dbusMap.objectPath = jsonDbusInfo.value("object_path", ""); 149 dbusInfo.dbusMap.interface = jsonDbusInfo.value("interface", ""); 150 dbusInfo.dbusMap.propertyName = 151 jsonDbusInfo.value("property_name", ""); 152 dbusInfo.dbusMap.propertyType = 153 jsonDbusInfo.value("property_type", ""); 154 Json propertyValues = jsonDbusInfo["property_values"]; 155 156 populatePropVals(propertyValues, dbusInfo.propertyValues, 157 dbusInfo.dbusMap.propertyType); 158 159 const std::vector<uint8_t> emptyStates{}; 160 auto state = effecter.value("state", empty); 161 dbusInfo.state.stateSetId = state.value("id", 0); 162 auto states = state.value("state_values", emptyStates); 163 if (dbusInfo.propertyValues.size() != states.size()) 164 { 165 error( 166 "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", 167 "PATH", dbusInfo.dbusMap.objectPath, "PROPERTY", 168 dbusInfo.dbusMap.propertyName); 169 continue; 170 } 171 for (const auto& s : states) 172 { 173 dbusInfo.state.states.emplace_back(s); 174 } 175 176 auto effecterInfoIndex = hostEffecterInfo.size(); 177 auto dbusInfoIndex = effecterInfo.dbusInfo.size(); 178 createHostEffecterMatch( 179 dbusInfo.dbusMap.objectPath, dbusInfo.dbusMap.interface, 180 effecterInfoIndex, dbusInfoIndex, effecterId); 181 effecterInfo.dbusInfo.emplace_back(std::move(dbusInfo)); 182 } 183 hostEffecterInfo.emplace_back(std::move(effecterInfo)); 184 } 185 } 186 187 bool HostEffecterParser::isHostOn(void) 188 { 189 using BootProgress = 190 sdbusplus::client::xyz::openbmc_project::state::boot::Progress<>; 191 constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0"; 192 try 193 { 194 auto propVal = dbusHandler->getDbusPropertyVariant( 195 hostStatePath, "BootProgress", BootProgress::interface); 196 197 using Stages = BootProgress::ProgressStages; 198 auto currHostState = sdbusplus::message::convert_from_string<Stages>( 199 std::get<std::string>(propVal)) 200 .value(); 201 202 if (currHostState != Stages::SystemInitComplete && 203 currHostState != Stages::OSRunning && 204 currHostState != Stages::SystemSetup && 205 currHostState != Stages::OEM) 206 { 207 info( 208 "Remote terminus is not up/active, current remote terminus state is: '{CURRENT_HOST_STATE}'", 209 "CURRENT_HOST_STATE", currHostState); 210 return false; 211 } 212 } 213 catch (const sdbusplus::exception_t& e) 214 { 215 error( 216 "Error in getting current remote terminus state. Will still continue to set the remote terminus effecter, error - {ERROR}", 217 "ERROR", e); 218 return false; 219 } 220 221 return true; 222 } 223 224 void HostEffecterParser::processHostEffecterChangeNotification( 225 const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex, 226 size_t dbusInfoIndex, uint16_t effecterId) 227 { 228 const auto& pdrType = hostEffecterInfo[effecterInfoIndex].effecterPdrType; 229 if (pdrType == PLDM_NUMERIC_EFFECTER_PDR) 230 { 231 processTerminusNumericEffecterChangeNotification( 232 chProperties, effecterInfoIndex, dbusInfoIndex, effecterId); 233 return; 234 } 235 const auto& propertyName = hostEffecterInfo[effecterInfoIndex] 236 .dbusInfo[dbusInfoIndex] 237 .dbusMap.propertyName; 238 239 const auto& it = chProperties.find(propertyName); 240 241 if (it == chProperties.end()) 242 { 243 return; 244 } 245 246 if (effecterId == PLDM_INVALID_EFFECTER_ID) 247 { 248 constexpr auto localOrRemote = false; 249 effecterId = findStateEffecterId( 250 pdrRepo, hostEffecterInfo[effecterInfoIndex].entityType, 251 hostEffecterInfo[effecterInfoIndex].entityInstance, 252 hostEffecterInfo[effecterInfoIndex].containerId, 253 hostEffecterInfo[effecterInfoIndex] 254 .dbusInfo[dbusInfoIndex] 255 .state.stateSetId, 256 localOrRemote); 257 if (effecterId == PLDM_INVALID_EFFECTER_ID) 258 { 259 error( 260 "Effecter ID '{EFFECTERID}' of entity type '{TYPE}', entityInstance '{INSTANCE}' and containerID '{CONTAINER_ID}' not found in pdr repo", 261 "EFFECTERID", effecterId, "TYPE", 262 hostEffecterInfo[effecterInfoIndex].entityType, "INSTANCE", 263 hostEffecterInfo[effecterInfoIndex].entityInstance, 264 "CONTAINER_ID", 265 hostEffecterInfo[effecterInfoIndex].containerId); 266 return; 267 } 268 } 269 270 if (!isHostOn()) 271 { 272 return; 273 } 274 275 uint8_t newState{}; 276 try 277 { 278 newState = 279 findNewStateValue(effecterInfoIndex, dbusInfoIndex, it->second); 280 } 281 catch (const std::out_of_range& e) 282 { 283 error("Failed to find new state '{NEW_STATE}' in json, error - {ERROR}", 284 "ERROR", e, "NEW_STATE", newState); 285 return; 286 } 287 288 std::vector<set_effecter_state_field> stateField; 289 for (uint8_t i = 0; i < hostEffecterInfo[effecterInfoIndex].compEffecterCnt; 290 i++) 291 { 292 if (i == dbusInfoIndex) 293 { 294 stateField.push_back({PLDM_REQUEST_SET, newState}); 295 } 296 else 297 { 298 stateField.push_back({PLDM_NO_CHANGE, 0}); 299 } 300 } 301 int rc{}; 302 try 303 { 304 rc = setHostStateEffecter(effecterInfoIndex, stateField, effecterId); 305 } 306 catch (const std::runtime_error& e) 307 { 308 error( 309 "Failed to set remote terminus state effecter for effecter ID '{EFFECTERID}', error - {ERROR}", 310 "ERROR", e, "EFFECTERID", effecterId); 311 return; 312 } 313 if (rc != PLDM_SUCCESS) 314 { 315 error( 316 "Failed to set the remote terminus state effecter for effecter ID '{EFFECTERID}', response code '{RC}'", 317 "EFFECTERID", effecterId, "RC", rc); 318 } 319 } 320 321 double HostEffecterParser::adjustValue(double value, double offset, 322 double resolution, int8_t modify) 323 { 324 double unitModifier = std::pow(10, signed(modify)); 325 return std::round((value - offset) * resolution / unitModifier); 326 } 327 328 void HostEffecterParser::processTerminusNumericEffecterChangeNotification( 329 const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex, 330 size_t dbusInfoIndex, uint16_t effecterId) 331 { 332 const auto& checkHost = hostEffecterInfo[effecterInfoIndex].checkHostState; 333 const auto& propValues = hostEffecterInfo[effecterInfoIndex] 334 .dbusNumericEffecterInfo[dbusInfoIndex]; 335 const auto& propertyName = propValues.dbusMap.propertyName; 336 const auto& propertyType = propValues.dbusMap.propertyType; 337 338 if (effecterId == PLDM_INVALID_EFFECTER_ID) 339 { 340 lg2::error( 341 "Dbus to PLDM Numeric Effecter setting requires valid effecter ID. Invalid effecter ID {EFFECTER_ID}", 342 "EFFECTER_ID", effecterId); 343 } 344 345 if (!dbusValueNumericTypeNames.contains(propertyType)) 346 { 347 lg2::error( 348 "DBus Value to PLDM Numeric Effecter setting only supports D-Bus Numeric data type. Invalid type {TYPE}", 349 "TYPE", propertyType); 350 return; 351 } 352 353 const auto& it = chProperties.find(propertyName); 354 355 if (it == chProperties.end()) 356 { 357 return; 358 } 359 360 double val = std::numeric_limits<double>::quiet_NaN(); 361 if (!pldm::utils::dbusPropValuesToDouble(propertyType, it->second, &val)) 362 { 363 lg2::error( 364 "DBus Value to PLDM Numeric Effecter setting only supports Numeric D-Bus data type. Invalid type {TYPE}", 365 "TYPE", propertyType); 366 return; 367 } 368 369 /* Update the current value of D-Bus interface*/ 370 if (!std::isnan(val) && std::isnan(propValues.propertyValue)) 371 { 372 hostEffecterInfo[effecterInfoIndex] 373 .dbusNumericEffecterInfo[dbusInfoIndex] 374 .propertyValue = val; 375 return; 376 } 377 378 /* Bypass the setting when the current value is NA or setting value is NA */ 379 if (std::isnan(propValues.propertyValue) || std::isnan(val)) 380 { 381 return; 382 } 383 384 /* Setting value equals the D-Bus value which is real value of effecter */ 385 if (val == propValues.propertyValue) 386 { 387 return; 388 } 389 390 double rawValue = adjustValue(val, propValues.offset, propValues.resolution, 391 propValues.unitModifier); 392 393 if (checkHost && !isHostOn()) 394 { 395 return; 396 } 397 398 try 399 { 400 auto rc = setTerminusNumericEffecter(effecterInfoIndex, effecterId, 401 propValues.dataSize, rawValue); 402 if (rc) 403 { 404 error( 405 "Could not set the numeric effecter ID '{EFFECTERID}' return code '{RC}'", 406 "EFFECTERID", effecterId, "RC", rc); 407 return; 408 } 409 } 410 catch (const std::runtime_error& e) 411 { 412 error("Could not set numeric effecter ID= '{EFFECTERID}'", "EFFECTERID", 413 effecterId); 414 return; 415 } 416 417 hostEffecterInfo[effecterInfoIndex] 418 .dbusNumericEffecterInfo[dbusInfoIndex] 419 .propertyValue = val; 420 421 return; 422 } 423 424 uint8_t HostEffecterParser::findNewStateValue( 425 size_t effecterInfoIndex, size_t dbusInfoIndex, 426 const PropertyValue& propertyValue) 427 { 428 const auto& propValues = hostEffecterInfo[effecterInfoIndex] 429 .dbusInfo[dbusInfoIndex] 430 .propertyValues; 431 auto it = std::find(propValues.begin(), propValues.end(), propertyValue); 432 uint8_t newState{}; 433 if (it != propValues.end()) 434 { 435 auto index = std::distance(propValues.begin(), it); 436 newState = hostEffecterInfo[effecterInfoIndex] 437 .dbusInfo[dbusInfoIndex] 438 .state.states[index]; 439 } 440 else 441 { 442 throw std::out_of_range("new state not found in json"); 443 } 444 return newState; 445 } 446 447 size_t getEffecterDataSize(uint8_t effecterDataSize) 448 { 449 switch (effecterDataSize) 450 { 451 case PLDM_EFFECTER_DATA_SIZE_UINT8: 452 return sizeof(uint8_t); 453 case PLDM_EFFECTER_DATA_SIZE_SINT8: 454 return sizeof(int8_t); 455 case PLDM_EFFECTER_DATA_SIZE_UINT16: 456 return sizeof(uint16_t); 457 case PLDM_EFFECTER_DATA_SIZE_SINT16: 458 return sizeof(int16_t); 459 case PLDM_EFFECTER_DATA_SIZE_UINT32: 460 return sizeof(uint32_t); 461 case PLDM_EFFECTER_DATA_SIZE_SINT32: 462 return sizeof(int32_t); 463 default: 464 return 0; 465 } 466 } 467 468 int HostEffecterParser::setTerminusNumericEffecter( 469 size_t effecterInfoIndex, uint16_t effecterId, uint8_t dataSize, 470 double rawValue) 471 { 472 uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid; 473 auto instanceId = instanceIdDb->next(mctpEid); 474 int rc = PLDM_ERROR; 475 std::vector<uint8_t> requestMsg; 476 477 /** 478 * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES = 4. It includes the 1 byte 479 * value for effecterValue as `Table 48 - SetNumericEffecterValue command 480 * format` DSP0248 V1.3.0 So the payload_length of `SetNumericEffecterValue` 481 * request message will be payload_length = 482 * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 + sizeof(dataType) 483 */ 484 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 + 485 getEffecterDataSize(dataSize); 486 requestMsg.resize(sizeof(pldm_msg_hdr) + payload_length); 487 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 488 switch (dataSize) 489 { 490 case PLDM_EFFECTER_DATA_SIZE_UINT8: 491 { 492 auto value_uint8 = (uint8_t)rawValue; 493 rc = encode_set_numeric_effecter_value_req( 494 instanceId, effecterId, dataSize, 495 reinterpret_cast<uint8_t*>(&value_uint8), request, 496 payload_length); 497 break; 498 } 499 case PLDM_EFFECTER_DATA_SIZE_SINT8: 500 { 501 auto value_int8 = (int8_t)rawValue; 502 rc = encode_set_numeric_effecter_value_req( 503 instanceId, effecterId, dataSize, 504 reinterpret_cast<uint8_t*>(&value_int8), request, 505 payload_length); 506 break; 507 } 508 case PLDM_EFFECTER_DATA_SIZE_UINT16: 509 { 510 auto value_uint16 = (uint16_t)rawValue; 511 rc = encode_set_numeric_effecter_value_req( 512 instanceId, effecterId, dataSize, 513 reinterpret_cast<uint8_t*>(&value_uint16), request, 514 payload_length); 515 break; 516 } 517 case PLDM_EFFECTER_DATA_SIZE_SINT16: 518 { 519 auto value_int16 = (int16_t)rawValue; 520 rc = encode_set_numeric_effecter_value_req( 521 instanceId, effecterId, dataSize, 522 reinterpret_cast<uint8_t*>(&value_int16), request, 523 payload_length); 524 break; 525 } 526 case PLDM_EFFECTER_DATA_SIZE_UINT32: 527 { 528 auto value_uint32 = (uint32_t)rawValue; 529 rc = encode_set_numeric_effecter_value_req( 530 instanceId, effecterId, dataSize, 531 reinterpret_cast<uint8_t*>(&value_uint32), request, 532 payload_length); 533 break; 534 } 535 case PLDM_EFFECTER_DATA_SIZE_SINT32: 536 { 537 auto value_int32 = (int32_t)rawValue; 538 rc = encode_set_numeric_effecter_value_req( 539 instanceId, effecterId, dataSize, 540 reinterpret_cast<uint8_t*>(&value_int32), request, 541 payload_length); 542 break; 543 } 544 default: 545 break; 546 } 547 548 if (rc) 549 { 550 error( 551 "Failed to encode set numeric effecter request message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with error code '{RC}'", 552 "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex, 553 rc); 554 555 instanceIdDb->free(mctpEid, instanceId); 556 return rc; 557 } 558 559 auto setNumericEffecterRespHandler = [effecterId](mctp_eid_t /*eid*/, 560 const pldm_msg* response, 561 size_t respMsgLen) { 562 if (response == nullptr || !respMsgLen) 563 { 564 error( 565 "Failed to receive response for setNumericEffecterValue command"); 566 return; 567 } 568 uint8_t completionCode{}; 569 auto rc = decode_set_numeric_effecter_value_resp(response, respMsgLen, 570 &completionCode); 571 572 if (rc) 573 { 574 error( 575 "Failed to decode set numeric effecter response message for effecter ID '{EFFECTERID}' with error code '{RC}'", 576 "EFFECTERID", effecterId, "RC", lg2::hex, rc); 577 } 578 if (completionCode) 579 { 580 error( 581 "Failed to set numeric effecter for effecter ID '{EFFECTERID}' with complete code '{CC}'", 582 "EFFECTERID", effecterId, "CC", lg2::hex, completionCode); 583 } 584 }; 585 586 rc = handler->registerRequest( 587 mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_NUMERIC_EFFECTER_VALUE, 588 std::move(requestMsg), std::move(setNumericEffecterRespHandler)); 589 if (rc) 590 { 591 error("Failed to send request to set an effecter on Host"); 592 } 593 return rc; 594 } 595 596 int HostEffecterParser::setHostStateEffecter( 597 size_t effecterInfoIndex, std::vector<set_effecter_state_field>& stateField, 598 uint16_t effecterId) 599 { 600 uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid; 601 uint8_t& compEffCnt = hostEffecterInfo[effecterInfoIndex].compEffecterCnt; 602 auto instanceId = instanceIdDb->next(mctpEid); 603 604 std::vector<uint8_t> requestMsg( 605 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(compEffCnt) + 606 sizeof(set_effecter_state_field) * compEffCnt, 607 0); 608 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 609 auto rc = encode_set_state_effecter_states_req( 610 instanceId, effecterId, compEffCnt, stateField.data(), request); 611 612 if (rc != PLDM_SUCCESS) 613 { 614 error( 615 "Failed to encode set state effecter states message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with response code '{RC}'", 616 "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex, 617 rc); 618 instanceIdDb->free(mctpEid, instanceId); 619 return rc; 620 } 621 622 auto setStateEffecterStatesRespHandler = [](mctp_eid_t /*eid*/, 623 const pldm_msg* response, 624 size_t respMsgLen) { 625 if (response == nullptr || !respMsgLen) 626 { 627 error( 628 "Failed to receive response for setting state effecter states."); 629 return; 630 } 631 uint8_t completionCode{}; 632 auto rc = decode_set_state_effecter_states_resp(response, respMsgLen, 633 &completionCode); 634 if (rc) 635 { 636 error( 637 "Failed to decode response of set state effecter states, response code '{RC}'", 638 "RC", rc); 639 pldm::utils::reportError( 640 "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed"); 641 } 642 if (completionCode) 643 { 644 error( 645 "Failed to set a remote terminus effecter, completion code '{CC}'", 646 "CC", completionCode); 647 pldm::utils::reportError( 648 "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed"); 649 } 650 }; 651 652 rc = handler->registerRequest( 653 mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES, 654 std::move(requestMsg), std::move(setStateEffecterStatesRespHandler)); 655 if (rc) 656 { 657 error( 658 "Failed to send request to set an effecter on remote terminus for effecter ID '{EFFECTERID}', response code '{RC}'", 659 "EFFECTERID", effecterId, "RC", rc); 660 } 661 return rc; 662 } 663 664 void HostEffecterParser::createHostEffecterMatch( 665 const std::string& objectPath, const std::string& interface, 666 size_t effecterInfoIndex, size_t dbusInfoIndex, uint16_t effecterId) 667 { 668 using namespace sdbusplus::bus::match::rules; 669 effecterInfoMatch.emplace_back(std::make_unique<sdbusplus::bus::match_t>( 670 pldm::utils::DBusHandler::getBus(), 671 propertiesChanged(objectPath, interface), 672 [this, effecterInfoIndex, dbusInfoIndex, 673 effecterId](sdbusplus::message_t& msg) { 674 DbusChgHostEffecterProps props; 675 std::string iface; 676 msg.read(iface, props); 677 processHostEffecterChangeNotification(props, effecterInfoIndex, 678 dbusInfoIndex, effecterId); 679 })); 680 } 681 682 } // namespace host_effecters 683 } // namespace pldm 684