1 #pragma once
2 
3 #include "lpcsnoop/snoop.hpp"
4 
5 #include <boost/asio.hpp>
6 #include <gpiod.hpp>
7 #include <sdbusplus/asio/connection.hpp>
8 #include <sdbusplus/asio/object_server.hpp>
9 #include <sdbusplus/asio/property.hpp>
10 #include <sdbusplus/bus.hpp>
11 #include <sdbusplus/server.hpp>
12 #include <xyz/openbmc_project/Chassis/Buttons/HostSelector/server.hpp>
13 #include <xyz/openbmc_project/State/Boot/Raw/server.hpp>
14 
15 #include <filesystem>
16 #include <iostream>
17 #include <span>
18 
19 const std::string ipmiSnoopObject = "/xyz/openbmc_project/state/boot/raw";
20 
21 const int hostParseIdx = 3;
22 const int maxPosition = 4;
23 
24 extern bool sevenSegmentLedEnabled;
25 
26 extern std::vector<gpiod::line> led_lines;
27 
28 using Selector =
29     sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::HostSelector;
30 
31 const std::string selectorService = "xyz.openbmc_project.Chassis.Buttons";
32 const std::string selectorObject =
33     "/xyz/openbmc_project/Chassis/Buttons/HostSelector";
34 const std::string selectorIface =
35     "xyz.openbmc_project.Chassis.Buttons.HostSelector";
36 
37 const std::string rawObject = "/xyz/openbmc_project/state/boot";
38 const std::string rawIface = "xyz.openbmc_project.State.Boot.Raw";
39 const std::string rawService = "xyz.openbmc_project.State.Boot.Raw";
40 
41 int postCodeIpmiHandler(const std::string& snoopObject,
42                         const std::string& snoopDbus, sdbusplus::bus_t& bus,
43                         std::span<std::string> host);
44 
45 uint32_t getSelectorPosition(sdbusplus::bus_t& bus);
46 
47 struct IpmiPostReporter : PostObject
48 {
IpmiPostReporterIpmiPostReporter49     IpmiPostReporter(sdbusplus::bus_t& bus, const char* objPath) :
50         PostObject(bus, objPath), bus(bus),
51         propertiesChangedSignalRaw(
52             bus,
53             sdbusplus::bus::match::rules::propertiesChanged(objPath, rawIface),
54 
55             [this, &bus](sdbusplus::message_t& msg) {
56                 using primarycode_t = std::vector<uint8_t>;
57                 using secondarycode_t = std::vector<uint8_t>;
58                 using postcode_t = std::tuple<primarycode_t, secondarycode_t>;
59 
60                 /* sevenSegmentLedEnabled flag is set when GPIO pins are not
61                 there 7 seg display for fewer platforms. So, the code for
62                 postcode display and Get Selector position can be skipped in
63                 those platforms.
64                 */
65                 if (!sevenSegmentLedEnabled)
66                 {
67                     return;
68                 }
69 
70                 std::string objectName;
71                 std::string InterfaceName;
72                 std::map<std::string, std::variant<postcode_t>> msgData;
73                 msg.read(InterfaceName, msgData);
74 
75                 std::filesystem::path name(msg.get_path());
76                 objectName = name.filename();
77 
78                 std::string hostNumStr = objectName.substr(hostParseIdx);
79                 size_t hostNum = std::stoi(hostNumStr);
80 
81                 size_t position = getSelectorPosition(bus);
82 
83                 if (position > maxPosition)
84                 {
85                     std::cerr << "Invalid position. Position should be 1 to 4 "
86                                  "for all hosts "
87                               << std::endl;
88                 }
89 
90                 // Check if it was the Value property that changed.
91                 auto valPropMap = msgData.find("Value");
92                 if (valPropMap == msgData.end())
93                 {
94                     std::cerr << "Value property is not found " << std::endl;
95                     return;
96                 }
97                 auto postcode =
98                     std::get<0>(std::get<postcode_t>(valPropMap->second));
99 
100                 if (postcode.size() == 1)
101                 {
102                     if (position == hostNum)
103                     {
104                         // write postcode into seven segment display
105                         if (postCodeDisplay(postcode[0]) < 0)
106                         {
107                             fprintf(stderr, "Error in display the postcode\n");
108                         }
109                     }
110                     else
111                     {
112                         fprintf(stderr, "Host Selector Position and host "
113                                         "number is not matched..\n");
114                     }
115                 }
116                 else
117                 {
118                     fprintf(stderr, "invalid postcode value \n");
119                 }
120             })
121     {}
122 
123     sdbusplus::bus_t& bus;
124     sdbusplus::bus::match_t propertiesChangedSignalRaw;
125     int postCodeDisplay(uint8_t);
126     void getSelectorPositionSignal(sdbusplus::bus_t& bus);
127 };
128