#include "host_lamp_test.hpp" #include "common/types.hpp" #include "common/utils.hpp" #include #include #include PHOSPHOR_LOG2_USING; namespace pldm { namespace led { bool HostLampTest::asserted() const { return sdbusplus::xyz::openbmc_project::Led::server::Group::asserted(); } bool HostLampTest::asserted(bool value) { // When setting the asserted property to true, need to notify the PHYP to // start lamp test. // When setting the asserted property to true again, need to notify the PHYP // and PHYP will restart the lamp test. // When setting the asserted property to false, just update the asserted // property, do not need to notify the PHYP to stop lamp test, PHYP will // wait for timeout to stop. if (!value && value == sdbusplus::xyz::openbmc_project::Led::server::Group::asserted()) { return value; } if (value) { if (effecterID == 0) { effecterID = getEffecterID(); } if (effecterID != 0) { // Call setHostStateEffecter method to notify PHYP to start lamp // test. If user set Asserted to true again, need to notify PHYP to // start lamptest again. uint8_t rc = setHostStateEffecter(effecterID); if (rc) { throw sdbusplus::exception::SdBusError( static_cast(std::errc::invalid_argument), "Set Host State Effector to start lamp test failed"); } else { return sdbusplus::xyz::openbmc_project::Led::server::Group:: asserted(value); } } else { throw sdbusplus::exception::SdBusError( static_cast(std::errc::invalid_argument), "Get Effecter ID failed, effecter = 0"); } } return sdbusplus::xyz::openbmc_project::Led::server::Group::asserted(value); } uint16_t HostLampTest::getEffecterID() { uint16_t effecterID = 0; if (!pdrRepo) { return effecterID; } // INDICATOR is a logical entity, so the bit 15 in entity type is set. pdr::EntityType entityType = PLDM_ENTITY_INDICATOR | 0x8000; auto stateEffecterPDRs = pldm::utils::findStateEffecterPDR( mctp_eid, entityType, static_cast(PLDM_STATE_SET_IDENTIFY_STATE), pdrRepo); if (stateEffecterPDRs.empty()) { error( "Lamp Test: The state set PDR can not be found, entityType = {ENTITY_TYP}", "ENTITY_TYP", entityType); return effecterID; } for (const auto& rep : stateEffecterPDRs) { auto pdr = reinterpret_cast(rep.data()); effecterID = pdr->effecter_id; break; } return effecterID; } uint8_t HostLampTest::setHostStateEffecter(uint16_t effecterID) { constexpr uint8_t effecterCount = 1; auto instanceId = instanceIdDb.next(mctp_eid); std::vector requestMsg( sizeof(pldm_msg_hdr) + sizeof(effecterID) + sizeof(effecterCount) + sizeof(set_effecter_state_field)); auto request = reinterpret_cast(requestMsg.data()); set_effecter_state_field stateField{PLDM_REQUEST_SET, PLDM_STATE_SET_IDENTIFY_STATE_ASSERTED}; auto rc = encode_set_state_effecter_states_req( instanceId, effecterID, effecterCount, &stateField, request); if (rc != PLDM_SUCCESS) { instanceIdDb.free(mctp_eid, instanceId); error("Failed to encode_set_state_effecter_states_req, rc = {RC}", "RC", static_cast(rc)); return rc; } auto setStateEffecterStatesResponseHandler = [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) { if (!response || !respMsgLen) { error( "Failed to receive response for the Set State Effecter States"); return; } uint8_t completionCode{}; auto rc = decode_set_state_effecter_states_resp(response, respMsgLen, &completionCode); if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) { error( "Failed to decode_set_state_effecter_states_resp: rc={RC}, cc={CC}", "RC", rc, "CC", static_cast(completionCode)); } }; rc = handler->registerRequest( mctp_eid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES, std::move(requestMsg), std::move(setStateEffecterStatesResponseHandler)); if (rc != PLDM_SUCCESS) { error("Failed to send the the Set State Effecter States request"); } return rc; } } // namespace led } // namespace pldm