1 #include "common/transport.hpp"
2 
3 #include <libpldm/base.h>
4 #include <libpldm/platform.h>
5 
6 #include <CLI/CLI.hpp>
7 #include <phosphor-logging/lg2.hpp>
8 #include <sdeventplus/event.hpp>
9 #include <sdeventplus/source/io.hpp>
10 
11 #include <array>
12 
13 using namespace sdeventplus;
14 using namespace sdeventplus::source;
15 PHOSPHOR_LOG2_USING;
16 
17 int main(int argc, char** argv)
18 {
19     CLI::App app{"Send PLDM command SetStateEffecterStates"};
20     uint8_t mctpEid{};
21     app.add_option("-m,--mctp_eid", mctpEid, "MCTP EID")->required();
22     uint16_t effecterId{};
23     app.add_option("-e,--effecter", effecterId, "Effecter Id")->required();
24     uint8_t state{};
25     app.add_option("-s,--state", state, "New state value")->required();
26     CLI11_PARSE(app, argc, argv);
27 
28     pldm_tid_t dstTid = static_cast<pldm_tid_t>(mctpEid);
29 
30     // Encode PLDM Request message
31     uint8_t effecterCount = 1;
32     std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(effecterId) +
33                             sizeof(effecterCount) +
34                             sizeof(set_effecter_state_field)>
35         requestMsg{};
36     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
37     set_effecter_state_field stateField{PLDM_REQUEST_SET, state};
38     auto rc = encode_set_state_effecter_states_req(0, effecterId, effecterCount,
39                                                    &stateField, request);
40     if (rc != PLDM_SUCCESS)
41     {
42         error("Message encode failure. PLDM error code = {RC}", "RC", lg2::hex,
43               rc);
44         return -1;
45     }
46 
47     PldmTransport pldmTransport{};
48 
49     // Create event loop and add a callback to handle EPOLLIN on fd
50     auto event = Event::get_default();
51     auto callback = [=, &pldmTransport](IO& io, int fd,
52                                         uint32_t revents) mutable {
53         if (!(revents & EPOLLIN))
54         {
55             return;
56         }
57 
58         if (pldmTransport.getEventSource() != fd)
59         {
60             return;
61         }
62 
63         void* responseMsg = nullptr;
64         size_t responseMsgSize{};
65         pldm_tid_t srcTid;
66         auto rc = pldmTransport.recvMsg(srcTid, responseMsg, responseMsgSize);
67         pldm_msg* response = reinterpret_cast<pldm_msg*>(responseMsg);
68         if (rc || dstTid != srcTid ||
69             !pldm_msg_hdr_correlate_response(&request->hdr, &response->hdr))
70         {
71             return;
72         }
73 
74         // We've got the response meant for the PLDM request msg that was sent
75         // out
76         io.set_enabled(Enabled::Off);
77         info("Done. PLDM RC = {RC}", "RC", lg2::hex,
78              static_cast<uint16_t>(response->payload[0]));
79         free(responseMsg);
80         exit(EXIT_SUCCESS);
81     };
82     IO io(event, pldmTransport.getEventSource(), EPOLLIN, std::move(callback));
83 
84     rc = pldmTransport.sendMsg(dstTid, requestMsg.data(), requestMsg.size());
85     if (0 > rc)
86     {
87         error(
88             "Failed to send message/receive response. RC = {RC} errno = {ERR}",
89             "RC", rc, "ERR", errno);
90         return -1;
91     }
92 
93     event.loop();
94 
95     return 0;
96 }
97