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,
33                sizeof(pldm_msg_hdr) + sizeof(effecterId) +
34                    sizeof(effecterCount) + 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(
43             "Failed to encode set state effecter states request, response code '{RC}'",
44             "RC", lg2::hex, rc);
45         return -1;
46     }
47 
48     PldmTransport pldmTransport{};
49 
50     // Create event loop and add a callback to handle EPOLLIN on fd
51     auto event = Event::get_default();
52     auto callback = [=,
53                      &pldmTransport](IO& io, int fd, uint32_t revents) mutable {
54         if (!(revents & EPOLLIN))
55         {
56             return;
57         }
58 
59         if (pldmTransport.getEventSource() != fd)
60         {
61             return;
62         }
63 
64         void* responseMsg = nullptr;
65         size_t responseMsgSize{};
66         pldm_tid_t srcTid;
67         auto rc = pldmTransport.recvMsg(srcTid, responseMsg, responseMsgSize);
68         pldm_msg* response = reinterpret_cast<pldm_msg*>(responseMsg);
69         if (rc || dstTid != srcTid ||
70             !pldm_msg_hdr_correlate_response(&request->hdr, &response->hdr))
71         {
72             return;
73         }
74 
75         // We've got the response meant for the PLDM request msg that was sent
76         // out
77         io.set_enabled(Enabled::Off);
78         info(
79             "Done! Got the response for PLDM request message, response code '{RC}'",
80             "RC", lg2::hex, response->payload[0]);
81         free(responseMsg);
82         exit(EXIT_SUCCESS);
83     };
84     IO io(event, pldmTransport.getEventSource(), EPOLLIN, std::move(callback));
85 
86     rc = pldmTransport.sendMsg(dstTid, requestMsg.data(), requestMsg.size());
87     if (0 > rc)
88     {
89         error(
90             "Failed to send message/receive response, response code '{RC}' and error - {ERROR}",
91             "RC", rc, "ERROR", errno);
92         return -1;
93     }
94 
95     event.loop();
96 
97     return 0;
98 }
99