blob: e7485d8882dd31f6486ff2fe47bf89e645cb8535 [file] [log] [blame]
#include "host_lamp_test.hpp"
#include "common/types.hpp"
#include "common/utils.hpp"
#include <libpldm/entity.h>
#include <libpldm/platform.h>
#include <libpldm/state_set.h>
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<int>(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<int>(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<uint16_t>(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<const pldm_state_effecter_pdr*>(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<uint8_t> requestMsg(
sizeof(pldm_msg_hdr) + sizeof(effecterID) + sizeof(effecterCount) +
sizeof(set_effecter_state_field));
auto request = reinterpret_cast<pldm_msg*>(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<int>(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<unsigned>(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