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