19d494bbeSDeepak Kodihalli #include <CLI/CLI.hpp>
29d494bbeSDeepak Kodihalli #include <array>
39d494bbeSDeepak Kodihalli #include <iostream>
49d494bbeSDeepak Kodihalli #include <sdeventplus/event.hpp>
59d494bbeSDeepak Kodihalli #include <sdeventplus/source/io.hpp>
69d494bbeSDeepak Kodihalli 
79d494bbeSDeepak Kodihalli #include "libpldm/base.h"
89d494bbeSDeepak Kodihalli #include "libpldm/platform.h"
99d494bbeSDeepak Kodihalli #include "libpldm/requester/pldm.h"
109d494bbeSDeepak Kodihalli 
119d494bbeSDeepak Kodihalli using namespace sdeventplus;
129d494bbeSDeepak Kodihalli using namespace sdeventplus::source;
139d494bbeSDeepak Kodihalli 
149d494bbeSDeepak Kodihalli int main(int argc, char** argv)
159d494bbeSDeepak Kodihalli {
169d494bbeSDeepak Kodihalli     CLI::App app{"Send PLDM command SetStateEffecterStates"};
179d494bbeSDeepak Kodihalli     uint8_t mctpEid{};
189d494bbeSDeepak Kodihalli     app.add_option("-m,--mctp_eid", mctpEid, "MCTP EID")->required();
199d494bbeSDeepak Kodihalli     uint16_t effecterId{};
209d494bbeSDeepak Kodihalli     app.add_option("-e,--effecter", effecterId, "Effecter Id")->required();
219d494bbeSDeepak Kodihalli     uint8_t state{};
229d494bbeSDeepak Kodihalli     app.add_option("-s,--state", state, "New state value")->required();
239d494bbeSDeepak Kodihalli     CLI11_PARSE(app, argc, argv);
249d494bbeSDeepak Kodihalli 
259d494bbeSDeepak Kodihalli     // Encode PLDM Request message
269d494bbeSDeepak Kodihalli     uint8_t effecterCount = 1;
279d494bbeSDeepak Kodihalli     std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(effecterId) +
289d494bbeSDeepak Kodihalli                             sizeof(effecterCount) +
299d494bbeSDeepak Kodihalli                             sizeof(set_effecter_state_field)>
309d494bbeSDeepak Kodihalli         requestMsg{};
319d494bbeSDeepak Kodihalli     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
329d494bbeSDeepak Kodihalli     set_effecter_state_field stateField{PLDM_REQUEST_SET, state};
339d494bbeSDeepak Kodihalli     auto rc = encode_set_state_effecter_states_req(0, effecterId, effecterCount,
349d494bbeSDeepak Kodihalli                                                    &stateField, request);
359d494bbeSDeepak Kodihalli     if (rc != PLDM_SUCCESS)
369d494bbeSDeepak Kodihalli     {
379d494bbeSDeepak Kodihalli         std::cerr << "Message encode failure. PLDM error code = " << std::hex
38*aa8ae72fSSampa Misra                   << std::showbase << rc << "\n";
399d494bbeSDeepak Kodihalli         return -1;
409d494bbeSDeepak Kodihalli     }
419d494bbeSDeepak Kodihalli 
429d494bbeSDeepak Kodihalli     // Get fd of MCTP socket
439d494bbeSDeepak Kodihalli     int fd = pldm_open();
449d494bbeSDeepak Kodihalli     if (-1 == fd)
459d494bbeSDeepak Kodihalli     {
46*aa8ae72fSSampa Misra         std::cerr << "Failed to init mctp"
47*aa8ae72fSSampa Misra                   << "\n";
489d494bbeSDeepak Kodihalli         return -1;
499d494bbeSDeepak Kodihalli     }
509d494bbeSDeepak Kodihalli 
519d494bbeSDeepak Kodihalli     // Create event loop and add a callback to handle EPOLLIN on fd
529d494bbeSDeepak Kodihalli     auto event = Event::get_default();
539d494bbeSDeepak Kodihalli     auto callback = [=](IO& io, int fd, uint32_t revents) {
549d494bbeSDeepak Kodihalli         if (!(revents & EPOLLIN))
559d494bbeSDeepak Kodihalli         {
569d494bbeSDeepak Kodihalli             return;
579d494bbeSDeepak Kodihalli         }
589d494bbeSDeepak Kodihalli 
599d494bbeSDeepak Kodihalli         uint8_t* responseMsg = nullptr;
609d494bbeSDeepak Kodihalli         size_t responseMsgSize{};
619d494bbeSDeepak Kodihalli         auto rc = pldm_recv(mctpEid, fd, request->hdr.instance_id, &responseMsg,
629d494bbeSDeepak Kodihalli                             &responseMsgSize);
639d494bbeSDeepak Kodihalli         if (!rc)
649d494bbeSDeepak Kodihalli         {
659d494bbeSDeepak Kodihalli             // We've got the response meant for the PLDM request msg that was
669d494bbeSDeepak Kodihalli             // sent out
679d494bbeSDeepak Kodihalli             io.set_enabled(Enabled::Off);
689d494bbeSDeepak Kodihalli             pldm_msg* response = reinterpret_cast<pldm_msg*>(responseMsg);
699d494bbeSDeepak Kodihalli             std::cout << "Done. PLDM RC = " << std::hex << std::showbase
709d494bbeSDeepak Kodihalli                       << static_cast<uint16_t>(response->payload[0])
719d494bbeSDeepak Kodihalli                       << std::endl;
729d494bbeSDeepak Kodihalli             free(responseMsg);
739d494bbeSDeepak Kodihalli             exit(EXIT_SUCCESS);
749d494bbeSDeepak Kodihalli         }
759d494bbeSDeepak Kodihalli     };
769d494bbeSDeepak Kodihalli     IO io(event, fd, EPOLLIN, std::move(callback));
779d494bbeSDeepak Kodihalli 
789d494bbeSDeepak Kodihalli     // Send PLDM Request message - pldm_send doesn't wait for response
799d494bbeSDeepak Kodihalli     rc = pldm_send(mctpEid, fd, requestMsg.data(), requestMsg.size());
809d494bbeSDeepak Kodihalli     if (0 > rc)
819d494bbeSDeepak Kodihalli     {
829d494bbeSDeepak Kodihalli         std::cerr << "Failed to send message/receive response. RC = " << rc
83*aa8ae72fSSampa Misra                   << ", errno = " << errno << "\n";
849d494bbeSDeepak Kodihalli         return -1;
859d494bbeSDeepak Kodihalli     }
869d494bbeSDeepak Kodihalli 
879d494bbeSDeepak Kodihalli     event.loop();
889d494bbeSDeepak Kodihalli 
899d494bbeSDeepak Kodihalli     return 0;
909d494bbeSDeepak Kodihalli }
91