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