1*b49b7d80SGeorge Liu 2*b49b7d80SGeorge Liu #include "host_lamp_test.hpp" 3*b49b7d80SGeorge Liu 4*b49b7d80SGeorge Liu #include "common/types.hpp" 5*b49b7d80SGeorge Liu #include "common/utils.hpp" 6*b49b7d80SGeorge Liu 7*b49b7d80SGeorge Liu #include <libpldm/entity.h> 8*b49b7d80SGeorge Liu #include <libpldm/platform.h> 9*b49b7d80SGeorge Liu #include <libpldm/state_set.h> 10*b49b7d80SGeorge Liu 11*b49b7d80SGeorge Liu PHOSPHOR_LOG2_USING; 12*b49b7d80SGeorge Liu 13*b49b7d80SGeorge Liu namespace pldm 14*b49b7d80SGeorge Liu { 15*b49b7d80SGeorge Liu namespace led 16*b49b7d80SGeorge Liu { 17*b49b7d80SGeorge Liu 18*b49b7d80SGeorge Liu bool HostLampTest::asserted() const 19*b49b7d80SGeorge Liu { 20*b49b7d80SGeorge Liu return sdbusplus::xyz::openbmc_project::Led::server::Group::asserted(); 21*b49b7d80SGeorge Liu } 22*b49b7d80SGeorge Liu 23*b49b7d80SGeorge Liu bool HostLampTest::asserted(bool value) 24*b49b7d80SGeorge Liu { 25*b49b7d80SGeorge Liu // When setting the asserted property to true, need to notify the PHYP to 26*b49b7d80SGeorge Liu // start lamp test. 27*b49b7d80SGeorge Liu // When setting the asserted property to true again, need to notify the PHYP 28*b49b7d80SGeorge Liu // and PHYP will restart the lamp test. 29*b49b7d80SGeorge Liu // When setting the asserted property to false, just update the asserted 30*b49b7d80SGeorge Liu // property, do not need to notify the PHYP to stop lamp test, PHYP will 31*b49b7d80SGeorge Liu // wait for timeout to stop. 32*b49b7d80SGeorge Liu if (!value && 33*b49b7d80SGeorge Liu value == 34*b49b7d80SGeorge Liu sdbusplus::xyz::openbmc_project::Led::server::Group::asserted()) 35*b49b7d80SGeorge Liu { 36*b49b7d80SGeorge Liu return value; 37*b49b7d80SGeorge Liu } 38*b49b7d80SGeorge Liu 39*b49b7d80SGeorge Liu if (value) 40*b49b7d80SGeorge Liu { 41*b49b7d80SGeorge Liu if (effecterID == 0) 42*b49b7d80SGeorge Liu { 43*b49b7d80SGeorge Liu effecterID = getEffecterID(); 44*b49b7d80SGeorge Liu } 45*b49b7d80SGeorge Liu 46*b49b7d80SGeorge Liu if (effecterID != 0) 47*b49b7d80SGeorge Liu { 48*b49b7d80SGeorge Liu // Call setHostStateEffecter method to notify PHYP to start lamp 49*b49b7d80SGeorge Liu // test. If user set Asserted to true again, need to notify PHYP to 50*b49b7d80SGeorge Liu // start lamptest again. 51*b49b7d80SGeorge Liu uint8_t rc = setHostStateEffecter(effecterID); 52*b49b7d80SGeorge Liu if (rc) 53*b49b7d80SGeorge Liu { 54*b49b7d80SGeorge Liu throw sdbusplus::exception::SdBusError( 55*b49b7d80SGeorge Liu static_cast<int>(std::errc::invalid_argument), 56*b49b7d80SGeorge Liu "Set Host State Effector to start lamp test failed"); 57*b49b7d80SGeorge Liu } 58*b49b7d80SGeorge Liu else 59*b49b7d80SGeorge Liu { 60*b49b7d80SGeorge Liu return sdbusplus::xyz::openbmc_project::Led::server::Group:: 61*b49b7d80SGeorge Liu asserted(value); 62*b49b7d80SGeorge Liu } 63*b49b7d80SGeorge Liu } 64*b49b7d80SGeorge Liu else 65*b49b7d80SGeorge Liu { 66*b49b7d80SGeorge Liu throw sdbusplus::exception::SdBusError( 67*b49b7d80SGeorge Liu static_cast<int>(std::errc::invalid_argument), 68*b49b7d80SGeorge Liu "Get Effecter ID failed, effecter = 0"); 69*b49b7d80SGeorge Liu } 70*b49b7d80SGeorge Liu } 71*b49b7d80SGeorge Liu 72*b49b7d80SGeorge Liu return sdbusplus::xyz::openbmc_project::Led::server::Group::asserted(value); 73*b49b7d80SGeorge Liu } 74*b49b7d80SGeorge Liu 75*b49b7d80SGeorge Liu uint16_t HostLampTest::getEffecterID() 76*b49b7d80SGeorge Liu { 77*b49b7d80SGeorge Liu uint16_t effecterID = 0; 78*b49b7d80SGeorge Liu 79*b49b7d80SGeorge Liu if (!pdrRepo) 80*b49b7d80SGeorge Liu { 81*b49b7d80SGeorge Liu return effecterID; 82*b49b7d80SGeorge Liu } 83*b49b7d80SGeorge Liu 84*b49b7d80SGeorge Liu // INDICATOR is a logical entity, so the bit 15 in entity type is set. 85*b49b7d80SGeorge Liu pdr::EntityType entityType = PLDM_ENTITY_INDICATOR | 0x8000; 86*b49b7d80SGeorge Liu 87*b49b7d80SGeorge Liu auto stateEffecterPDRs = pldm::utils::findStateEffecterPDR( 88*b49b7d80SGeorge Liu mctp_eid, entityType, 89*b49b7d80SGeorge Liu static_cast<uint16_t>(PLDM_STATE_SET_IDENTIFY_STATE), pdrRepo); 90*b49b7d80SGeorge Liu 91*b49b7d80SGeorge Liu if (stateEffecterPDRs.empty()) 92*b49b7d80SGeorge Liu { 93*b49b7d80SGeorge Liu error( 94*b49b7d80SGeorge Liu "Lamp Test: The state set PDR can not be found, entityType = {ENTITY_TYP}", 95*b49b7d80SGeorge Liu "ENTITY_TYP", entityType); 96*b49b7d80SGeorge Liu return effecterID; 97*b49b7d80SGeorge Liu } 98*b49b7d80SGeorge Liu 99*b49b7d80SGeorge Liu for (const auto& rep : stateEffecterPDRs) 100*b49b7d80SGeorge Liu { 101*b49b7d80SGeorge Liu auto pdr = reinterpret_cast<const pldm_state_effecter_pdr*>(rep.data()); 102*b49b7d80SGeorge Liu effecterID = pdr->effecter_id; 103*b49b7d80SGeorge Liu break; 104*b49b7d80SGeorge Liu } 105*b49b7d80SGeorge Liu 106*b49b7d80SGeorge Liu return effecterID; 107*b49b7d80SGeorge Liu } 108*b49b7d80SGeorge Liu 109*b49b7d80SGeorge Liu uint8_t HostLampTest::setHostStateEffecter(uint16_t effecterID) 110*b49b7d80SGeorge Liu { 111*b49b7d80SGeorge Liu constexpr uint8_t effecterCount = 1; 112*b49b7d80SGeorge Liu auto instanceId = instanceIdDb.next(mctp_eid); 113*b49b7d80SGeorge Liu 114*b49b7d80SGeorge Liu std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + sizeof(effecterID) + 115*b49b7d80SGeorge Liu sizeof(effecterCount) + 116*b49b7d80SGeorge Liu sizeof(set_effecter_state_field)); 117*b49b7d80SGeorge Liu auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 118*b49b7d80SGeorge Liu set_effecter_state_field stateField{PLDM_REQUEST_SET, 119*b49b7d80SGeorge Liu PLDM_STATE_SET_IDENTIFY_STATE_ASSERTED}; 120*b49b7d80SGeorge Liu auto rc = encode_set_state_effecter_states_req( 121*b49b7d80SGeorge Liu instanceId, effecterID, effecterCount, &stateField, request); 122*b49b7d80SGeorge Liu if (rc != PLDM_SUCCESS) 123*b49b7d80SGeorge Liu { 124*b49b7d80SGeorge Liu instanceIdDb.free(mctp_eid, instanceId); 125*b49b7d80SGeorge Liu error("Failed to encode_set_state_effecter_states_req, rc = {RC}", "RC", 126*b49b7d80SGeorge Liu static_cast<int>(rc)); 127*b49b7d80SGeorge Liu return rc; 128*b49b7d80SGeorge Liu } 129*b49b7d80SGeorge Liu 130*b49b7d80SGeorge Liu auto setStateEffecterStatesResponseHandler = 131*b49b7d80SGeorge Liu [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) { 132*b49b7d80SGeorge Liu if (!response || !respMsgLen) 133*b49b7d80SGeorge Liu { 134*b49b7d80SGeorge Liu error( 135*b49b7d80SGeorge Liu "Failed to receive response for the Set State Effecter States"); 136*b49b7d80SGeorge Liu return; 137*b49b7d80SGeorge Liu } 138*b49b7d80SGeorge Liu 139*b49b7d80SGeorge Liu uint8_t completionCode{}; 140*b49b7d80SGeorge Liu auto rc = decode_set_state_effecter_states_resp(response, respMsgLen, 141*b49b7d80SGeorge Liu &completionCode); 142*b49b7d80SGeorge Liu 143*b49b7d80SGeorge Liu if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 144*b49b7d80SGeorge Liu { 145*b49b7d80SGeorge Liu error( 146*b49b7d80SGeorge Liu "Failed to decode_set_state_effecter_states_resp: rc={RC}, cc={CC}", 147*b49b7d80SGeorge Liu "RC", rc, "CC", static_cast<unsigned>(completionCode)); 148*b49b7d80SGeorge Liu } 149*b49b7d80SGeorge Liu }; 150*b49b7d80SGeorge Liu 151*b49b7d80SGeorge Liu rc = handler->registerRequest( 152*b49b7d80SGeorge Liu mctp_eid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES, 153*b49b7d80SGeorge Liu std::move(requestMsg), 154*b49b7d80SGeorge Liu std::move(setStateEffecterStatesResponseHandler)); 155*b49b7d80SGeorge Liu if (rc != PLDM_SUCCESS) 156*b49b7d80SGeorge Liu { 157*b49b7d80SGeorge Liu error("Failed to send the the Set State Effecter States request"); 158*b49b7d80SGeorge Liu } 159*b49b7d80SGeorge Liu 160*b49b7d80SGeorge Liu return rc; 161*b49b7d80SGeorge Liu } 162*b49b7d80SGeorge Liu 163*b49b7d80SGeorge Liu } // namespace led 164*b49b7d80SGeorge Liu } // namespace pldm 165