blob: 77311b254a6a16c4d8ce0dd83beff344671eaaa2 [file] [log] [blame]
Kumar Thangavel0269eaf2021-08-11 15:45:18 +05301#pragma once
2
3#include "lpcsnoop/snoop.hpp"
4
5#include <boost/asio.hpp>
Kumar Thangavel0269eaf2021-08-11 15:45:18 +05306#include <gpiod.hpp>
Kumar Thangavel0269eaf2021-08-11 15:45:18 +05307#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
Patrick Williams0ea73572023-05-10 07:50:44 -050015#include <filesystem>
16#include <iostream>
17
Kumar Thangavel0269eaf2021-08-11 15:45:18 +053018const std::string ipmiSnoopObject = "/xyz/openbmc_project/state/boot/raw";
19
20const int hostParseIdx = 3;
21const int maxPostcode = 255;
22const int maxPosition = 4;
23
Kumar Thangavelaee65402022-08-09 17:21:48 +053024bool sevenSegmentLedEnabled = true;
25
Kumar Thangavel0269eaf2021-08-11 15:45:18 +053026std::vector<gpiod::line> led_lines;
27
28using Selector =
29 sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::HostSelector;
30
31std::unique_ptr<sdbusplus::bus::match_t> matchSignal;
32
33const std::string selectorService = "xyz.openbmc_project.Chassis.Buttons";
34const std::string selectorObject =
35 "/xyz/openbmc_project/Chassis/Buttons/HostSelector";
36const std::string selectorIface =
37 "xyz.openbmc_project.Chassis.Buttons.HostSelector";
38
39const std::string rawObject = "/xyz/openbmc_project/state/boot";
40const std::string rawIface = "xyz.openbmc_project.State.Boot.Raw";
41const std::string rawService = "xyz.openbmc_project.State.Boot.Raw";
42
Patrick Williamsaebf87c2022-07-22 19:26:54 -050043uint32_t getSelectorPosition(sdbusplus::bus_t& bus)
Kumar Thangavel0269eaf2021-08-11 15:45:18 +053044{
45 const std::string propertyName = "Position";
46
Patrick Williams0ea73572023-05-10 07:50:44 -050047 auto method = bus.new_method_call(selectorService.c_str(),
48 selectorObject.c_str(),
49 "org.freedesktop.DBus.Properties", "Get");
Kumar Thangavel0269eaf2021-08-11 15:45:18 +053050 method.append(selectorIface.c_str(), propertyName);
51
52 try
53 {
54 std::variant<uint32_t> value{};
55 auto reply = bus.call(method);
56 reply.read(value);
57 return std::get<uint32_t>(value);
58 }
Patrick Williamsaebf87c2022-07-22 19:26:54 -050059 catch (const sdbusplus::exception_t& ex)
Kumar Thangavel0269eaf2021-08-11 15:45:18 +053060 {
Kumar Thangavelaee65402022-08-09 17:21:48 +053061 std::cerr << "GetProperty call failed. " << ex.what() << std::endl;
62 return 0;
Kumar Thangavel0269eaf2021-08-11 15:45:18 +053063 }
64}
65
66struct IpmiPostReporter : PostObject
67{
Patrick Williamsaebf87c2022-07-22 19:26:54 -050068 IpmiPostReporter(sdbusplus::bus_t& bus, const char* objPath) :
Kumar Thangavel0269eaf2021-08-11 15:45:18 +053069 PostObject(bus, objPath), bus(bus),
70 propertiesChangedSignalRaw(
71 bus,
72 sdbusplus::bus::match::rules::propertiesChanged(objPath, rawIface),
73
Patrick Williamsaebf87c2022-07-22 19:26:54 -050074 [this, &bus](sdbusplus::message_t& msg) {
Patrick Williams0ea73572023-05-10 07:50:44 -050075 using primarycode_t = uint64_t;
76 using secondarycode_t = std::vector<uint8_t>;
77 using postcode_t = std::tuple<primarycode_t, secondarycode_t>;
Kumar Thangavel0269eaf2021-08-11 15:45:18 +053078
Patrick Williams0ea73572023-05-10 07:50:44 -050079 /* sevenSegmentLedEnabled flag is set when GPIO pins are not
80 there 7 seg display for fewer platforms. So, the code for
81 postcode dispay and Get Selector position can be skipped in
82 those platforms.
83 */
84 if (!sevenSegmentLedEnabled)
85 {
86 return;
87 }
88
89 std::string objectName;
90 std::string InterfaceName;
91 std::map<std::string, std::variant<postcode_t>> msgData;
92 msg.read(InterfaceName, msgData);
93
94 std::filesystem::path name(msg.get_path());
95 objectName = name.filename();
96
97 std::string hostNumStr = objectName.substr(hostParseIdx);
98 size_t hostNum = std::stoi(hostNumStr);
99
100 size_t position = getSelectorPosition(bus);
101
102 if (position > maxPosition)
103 {
104 std::cerr << "Invalid position. Position should be 1 to 4 "
105 "for all hosts "
106 << std::endl;
107 }
108
109 // Check if it was the Value property that changed.
110 auto valPropMap = msgData.find("Value");
111 if (valPropMap == msgData.end())
112 {
113 std::cerr << "Value property is not found " << std::endl;
114 return;
115 }
116 uint64_t postcode =
117 std::get<0>(std::get<postcode_t>(valPropMap->second));
118
119 if (postcode <= maxPostcode)
120 {
121 if (position == hostNum)
122 {
123 uint8_t postcode_8bit =
124 static_cast<uint8_t>(postcode & 0x0000FF);
125
126 // write postcode into seven segment display
127 if (postCodeDisplay(postcode_8bit) < 0)
Kumar Thangavelaee65402022-08-09 17:21:48 +0530128 {
Patrick Williams0ea73572023-05-10 07:50:44 -0500129 fprintf(stderr, "Error in display the postcode\n");
Kumar Thangavelaee65402022-08-09 17:21:48 +0530130 }
Patrick Williams0ea73572023-05-10 07:50:44 -0500131 }
132 else
133 {
134 fprintf(stderr, "Host Selector Position and host "
135 "number is not matched..\n");
136 }
137 }
138 else
139 {
140 fprintf(stderr, "invalid postcode value \n");
141 }
Kumar Thangavel0269eaf2021-08-11 15:45:18 +0530142 })
Patrick Williams0ea73572023-05-10 07:50:44 -0500143 {}
Kumar Thangavel0269eaf2021-08-11 15:45:18 +0530144
Patrick Williamsaebf87c2022-07-22 19:26:54 -0500145 sdbusplus::bus_t& bus;
Kumar Thangavel0269eaf2021-08-11 15:45:18 +0530146 sdbusplus::bus::match_t propertiesChangedSignalRaw;
147 int postCodeDisplay(uint8_t);
Patrick Williamsaebf87c2022-07-22 19:26:54 -0500148 void getSelectorPositionSignal(sdbusplus::bus_t& bus);
Kumar Thangavel0269eaf2021-08-11 15:45:18 +0530149};
150
151// Configure the seven segment display connected GPIOs direction
152int configGPIODirOutput()
153{
154 std::string gpioStr;
155 // Need to define gpio names LED_POST_CODE_0 to 8 in dts file
156 std::string gpioName = "LED_POST_CODE_";
157 const int value = 0;
158
159 for (int iteration = 0; iteration < 8; iteration++)
160 {
161 gpioStr = gpioName + std::to_string(iteration);
162 gpiod::line gpioLine = gpiod::find_line(gpioStr);
163
164 if (!gpioLine)
165 {
166 std::string errMsg = "Failed to find the " + gpioStr + " line";
167 std::cerr << errMsg.c_str() << std::endl;
Kumar Thangavelaee65402022-08-09 17:21:48 +0530168
169 /* sevenSegmentLedEnabled flag is unset when GPIO pins are not there
170 * 7 seg display for fewer platforms.
171 */
172 sevenSegmentLedEnabled = false;
Kumar Thangavel0269eaf2021-08-11 15:45:18 +0530173 return -1;
174 }
175
176 led_lines.push_back(gpioLine);
177 // Request GPIO output to specified value
178 try
179 {
180 gpioLine.request({__FUNCTION__,
181 gpiod::line_request::DIRECTION_OUTPUT,
182 gpiod::line_request::FLAG_ACTIVE_LOW},
183 value);
184 }
185 catch (std::exception&)
186 {
187 std::string errMsg = "Failed to request " + gpioStr + " output";
188 std::cerr << errMsg.c_str() << std::endl;
189 return -1;
190 }
191 }
192
193 return 0;
194}
195
196// Display the received postcode into seven segment display
197int IpmiPostReporter::postCodeDisplay(uint8_t status)
198{
199 for (int iteration = 0; iteration < 8; iteration++)
200 {
201 // split byte to write into GPIOs
202 int value = !((status >> iteration) & 0x01);
203
204 led_lines[iteration].set_value(value);
205 }
206 return 0;
207}