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