blob: e7485d8882dd31f6486ff2fe47bf89e645cb8535 [file] [log] [blame]
George Liub49b7d82021-02-08 14:10:17 +08001
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
11PHOSPHOR_LOG2_USING;
12
13namespace pldm
14{
15namespace led
16{
17
18bool HostLampTest::asserted() const
19{
20 return sdbusplus::xyz::openbmc_project::Led::server::Group::asserted();
21}
22
23bool 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
75uint16_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
109uint8_t HostLampTest::setHostStateEffecter(uint16_t effecterID)
110{
111 constexpr uint8_t effecterCount = 1;
112 auto instanceId = instanceIdDb.next(mctp_eid);
113
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400114 std::vector<uint8_t> requestMsg(
115 sizeof(pldm_msg_hdr) + sizeof(effecterID) + sizeof(effecterCount) +
116 sizeof(set_effecter_state_field));
George Liub49b7d82021-02-08 14:10:17 +0800117 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
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400130 auto setStateEffecterStatesResponseHandler = [](mctp_eid_t /*eid*/,
131 const pldm_msg* response,
132 size_t respMsgLen) {
George Liub49b7d82021-02-08 14:10:17 +0800133 if (!response || !respMsgLen)
134 {
135 error(
136 "Failed to receive response for the Set State Effecter States");
137 return;
138 }
139
140 uint8_t completionCode{};
141 auto rc = decode_set_state_effecter_states_resp(response, respMsgLen,
142 &completionCode);
143
144 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
145 {
146 error(
147 "Failed to decode_set_state_effecter_states_resp: rc={RC}, cc={CC}",
148 "RC", rc, "CC", static_cast<unsigned>(completionCode));
149 }
150 };
151
152 rc = handler->registerRequest(
153 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES,
154 std::move(requestMsg),
155 std::move(setStateEffecterStatesResponseHandler));
156 if (rc != PLDM_SUCCESS)
157 {
158 error("Failed to send the the Set State Effecter States request");
159 }
160
161 return rc;
162}
163
164} // namespace led
165} // namespace pldm