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