blob: 57f9610f54d3f9d62c61d044d9a812d62fa939c0 [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
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