1 #include "ipmisnoop.hpp"
2
3 std::vector<std::unique_ptr<IpmiPostReporter>> reporters;
4 bool sevenSegmentLedEnabled = true;
5 std::vector<gpiod::line> led_lines;
6
getSelectorPosition(sdbusplus::bus_t & bus)7 uint32_t getSelectorPosition(sdbusplus::bus_t& bus)
8 {
9 const std::string propertyName = "Position";
10
11 auto method =
12 bus.new_method_call(selectorService.c_str(), selectorObject.c_str(),
13 "org.freedesktop.DBus.Properties", "Get");
14 method.append(selectorIface.c_str(), propertyName);
15
16 try
17 {
18 std::variant<uint32_t> value{};
19 auto reply = bus.call(method);
20 reply.read(value);
21 return std::get<uint32_t>(value);
22 }
23 catch (const sdbusplus::exception_t& ex)
24 {
25 std::cerr << "GetProperty call failed. " << ex.what() << std::endl;
26 return 0;
27 }
28 }
29
30 // Configure the seven segment display connected GPIOs direction
configGPIODirOutput()31 static int configGPIODirOutput()
32 {
33 std::string gpioStr;
34 // Need to define gpio names LED_POST_CODE_0 to 8 in dts file
35 std::string gpioName = "LED_POST_CODE_";
36 const int value = 0;
37
38 for (int iteration = 0; iteration < 8; iteration++)
39 {
40 gpioStr = gpioName + std::to_string(iteration);
41 gpiod::line gpioLine = gpiod::find_line(gpioStr);
42
43 if (!gpioLine)
44 {
45 std::string errMsg = "Failed to find the " + gpioStr + " line";
46 std::cerr << errMsg.c_str() << std::endl;
47
48 /* sevenSegmentLedEnabled flag is unset when GPIO pins are not there
49 * 7 seg display for fewer platforms.
50 */
51 sevenSegmentLedEnabled = false;
52 return -1;
53 }
54
55 led_lines.push_back(gpioLine);
56 // Request GPIO output to specified value
57 try
58 {
59 gpioLine.request({__FUNCTION__,
60 gpiod::line_request::DIRECTION_OUTPUT,
61 gpiod::line_request::FLAG_ACTIVE_LOW},
62 value);
63 }
64 catch (std::exception&)
65 {
66 std::string errMsg = "Failed to request " + gpioStr + " output";
67 std::cerr << errMsg.c_str() << std::endl;
68 return -1;
69 }
70 }
71
72 return 0;
73 }
74
75 // Display the received postcode into seven segment display
postCodeDisplay(uint8_t status)76 int IpmiPostReporter::postCodeDisplay(uint8_t status)
77 {
78 for (int iteration = 0; iteration < 8; iteration++)
79 {
80 // split byte to write into GPIOs
81 int value = !((status >> iteration) & 0x01);
82
83 led_lines[iteration].set_value(value);
84 }
85 return 0;
86 }
87
getSelectorPositionSignal(sdbusplus::bus_t & bus)88 void IpmiPostReporter::getSelectorPositionSignal(sdbusplus::bus_t& bus)
89 {
90 constexpr uint8_t minPositionVal = 0;
91 constexpr uint8_t maxPositionVal = 5;
92
93 size_t posVal = 0;
94
95 static auto matchSignal = std::make_unique<sdbusplus::bus::match_t>(
96 bus,
97 sdbusplus::bus::match::rules::propertiesChanged(selectorObject,
98 selectorIface),
99 [&](sdbusplus::message_t& msg) {
100 std::string objectName;
101 std::map<std::string, Selector::PropertiesVariant> msgData;
102 msg.read(objectName, msgData);
103
104 auto valPropMap = msgData.find("Position");
105 {
106 if (valPropMap == msgData.end())
107 {
108 std::cerr << "Position property not found " << std::endl;
109 return;
110 }
111
112 posVal = std::get<size_t>(valPropMap->second);
113
114 if (posVal > minPositionVal && posVal < maxPositionVal)
115 {
116 std::tuple<primary_post_code_t, secondary_post_code_t>
117 postcodes = reporters[posVal - 1]->value();
118 auto postcode = std::get<0>(postcodes);
119
120 // write postcode into seven segment display
121 if (postCodeDisplay(postcode[0]) < 0)
122 {
123 fprintf(stderr, "Error in display the postcode\n");
124 }
125 }
126 }
127 });
128 }
129
130 // handle muti-host D-bus
postCodeIpmiHandler(const std::string & snoopObject,const std::string & snoopDbus,sdbusplus::bus_t & bus,std::span<std::string> host)131 int postCodeIpmiHandler(const std::string& snoopObject,
132 const std::string& snoopDbus, sdbusplus::bus_t& bus,
133 std::span<std::string> host)
134 {
135 int ret = 0;
136
137 try
138 {
139 for (size_t iteration = 0; iteration < host.size(); iteration++)
140 {
141 std::string objPathInst = snoopObject + host[iteration];
142
143 sdbusplus::server::manager_t m{bus, objPathInst.c_str()};
144
145 /* Create a monitor object and let it do all the rest */
146 reporters.emplace_back(
147 std::make_unique<IpmiPostReporter>(bus, objPathInst.c_str()));
148
149 reporters[iteration]->emit_object_added();
150 }
151
152 bus.request_name(snoopDbus.c_str());
153
154 /* sevenSegmentLedEnabled flag is unset when GPIO pins are not there 7
155 seg display for fewer platforms. So, the code for postcode display and
156 Get Selector position can be skipped in those platforms.
157 */
158 if (sevenSegmentLedEnabled)
159 {
160 reporters[0]->getSelectorPositionSignal(bus);
161 }
162 else
163 {
164 reporters.clear();
165 }
166 }
167 catch (const std::exception& e)
168 {
169 fprintf(stderr, "%s\n", e.what());
170 }
171
172 // Configure seven segment dsiplay connected to GPIOs as output
173 ret = configGPIODirOutput();
174 if (ret < 0)
175 {
176 fprintf(stderr, "Failed find the gpio line. Cannot display postcodes "
177 "in seven segment display..\n");
178 }
179
180 while (true)
181 {
182 bus.process_discard();
183 bus.wait();
184 }
185 exit(EXIT_SUCCESS);
186 }
187