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