blob: efc53783e6f87704e00a567bf62f072cb00615ca [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>
6#include <filesystem>
7#include <gpiod.hpp>
8#include <iostream>
9#include <sdbusplus/asio/connection.hpp>
10#include <sdbusplus/asio/object_server.hpp>
11#include <sdbusplus/asio/property.hpp>
12#include <sdbusplus/bus.hpp>
13#include <sdbusplus/server.hpp>
14#include <xyz/openbmc_project/Chassis/Buttons/HostSelector/server.hpp>
15#include <xyz/openbmc_project/State/Boot/Raw/server.hpp>
16
17const std::string ipmiSnoopObject = "/xyz/openbmc_project/state/boot/raw";
18
19const int hostParseIdx = 3;
20const int maxPostcode = 255;
21const int maxPosition = 4;
22
23std::vector<gpiod::line> led_lines;
24
25using Selector =
26 sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::HostSelector;
27
28std::unique_ptr<sdbusplus::bus::match_t> matchSignal;
29
30const std::string selectorService = "xyz.openbmc_project.Chassis.Buttons";
31const std::string selectorObject =
32 "/xyz/openbmc_project/Chassis/Buttons/HostSelector";
33const std::string selectorIface =
34 "xyz.openbmc_project.Chassis.Buttons.HostSelector";
35
36const std::string rawObject = "/xyz/openbmc_project/state/boot";
37const std::string rawIface = "xyz.openbmc_project.State.Boot.Raw";
38const std::string rawService = "xyz.openbmc_project.State.Boot.Raw";
39
40uint32_t getSelectorPosition(sdbusplus::bus::bus& bus)
41{
42 const std::string propertyName = "Position";
43
44 auto method =
45 bus.new_method_call(selectorService.c_str(), selectorObject.c_str(),
46 "org.freedesktop.DBus.Properties", "Get");
47 method.append(selectorIface.c_str(), propertyName);
48
49 try
50 {
51 std::variant<uint32_t> value{};
52 auto reply = bus.call(method);
53 reply.read(value);
54 return std::get<uint32_t>(value);
55 }
56 catch (const sdbusplus::exception::exception& ex)
57 {
58 std::cerr << "GetProperty call failed ";
59 throw std::runtime_error("GetProperty call failed");
60 }
61}
62
63struct IpmiPostReporter : PostObject
64{
65 IpmiPostReporter(sdbusplus::bus::bus& bus, const char* objPath) :
66 PostObject(bus, objPath), bus(bus),
67 propertiesChangedSignalRaw(
68 bus,
69 sdbusplus::bus::match::rules::propertiesChanged(objPath, rawIface),
70
71 [this, &bus](sdbusplus::message::message& msg) {
72 using primarycode_t = uint64_t;
73 using secondarycode_t = std::vector<uint8_t>;
74 using postcode_t = std::tuple<primarycode_t, secondarycode_t>;
75
76 std::string objectName;
77 std::string InterfaceName;
78 std::map<std::string, std::variant<postcode_t>> msgData;
79 msg.read(InterfaceName, msgData);
80
81 std::filesystem::path name(msg.get_path());
82 objectName = name.filename();
83
84 std::string hostNumStr = objectName.substr(hostParseIdx);
85 size_t hostNum = std::stoi(hostNumStr);
86
87 size_t position = getSelectorPosition(bus);
88
89 if (position > maxPosition)
90 {
91 std::cerr << "Invalid position. Position should be 1 to 4 "
92 "for all hosts "
93 << std::endl;
94 }
95
96 // Check if it was the Value property that changed.
97 auto valPropMap = msgData.find("Value");
98 if (valPropMap == msgData.end())
99 {
100 std::cerr << "Value property is not found " << std::endl;
101 return;
102 }
103 uint64_t postcode =
104 std::get<0>(std::get<postcode_t>(valPropMap->second));
105
106 if (postcode <= maxPostcode)
107 {
108 if (position == hostNum)
109 {
110 uint8_t postcode_8bit =
111 static_cast<uint8_t>(postcode & 0x0000FF);
112
113 // write postcode into seven segment display
114 if (postCodeDisplay(postcode_8bit) < 0)
115 {
116 fprintf(stderr, "Error in display the postcode\n");
117 }
118 }
119 else
120 {
121 fprintf(stderr, "Host Selector Position and host "
122 "number is not matched..\n");
123 }
124 }
125 else
126 {
127 fprintf(stderr, "invalid postcode value \n");
128 }
129 })
130 {
131 }
132
133 sdbusplus::bus::bus& bus;
134 sdbusplus::bus::match_t propertiesChangedSignalRaw;
135 int postCodeDisplay(uint8_t);
136 void getSelectorPositionSignal(sdbusplus::bus::bus& bus);
137};
138
139// Configure the seven segment display connected GPIOs direction
140int configGPIODirOutput()
141{
142 std::string gpioStr;
143 // Need to define gpio names LED_POST_CODE_0 to 8 in dts file
144 std::string gpioName = "LED_POST_CODE_";
145 const int value = 0;
146
147 for (int iteration = 0; iteration < 8; iteration++)
148 {
149 gpioStr = gpioName + std::to_string(iteration);
150 gpiod::line gpioLine = gpiod::find_line(gpioStr);
151
152 if (!gpioLine)
153 {
154 std::string errMsg = "Failed to find the " + gpioStr + " line";
155 std::cerr << errMsg.c_str() << std::endl;
156 return -1;
157 }
158
159 led_lines.push_back(gpioLine);
160 // Request GPIO output to specified value
161 try
162 {
163 gpioLine.request({__FUNCTION__,
164 gpiod::line_request::DIRECTION_OUTPUT,
165 gpiod::line_request::FLAG_ACTIVE_LOW},
166 value);
167 }
168 catch (std::exception&)
169 {
170 std::string errMsg = "Failed to request " + gpioStr + " output";
171 std::cerr << errMsg.c_str() << std::endl;
172 return -1;
173 }
174 }
175
176 return 0;
177}
178
179// Display the received postcode into seven segment display
180int IpmiPostReporter::postCodeDisplay(uint8_t status)
181{
182 for (int iteration = 0; iteration < 8; iteration++)
183 {
184 // split byte to write into GPIOs
185 int value = !((status >> iteration) & 0x01);
186
187 led_lines[iteration].set_value(value);
188 }
189 return 0;
190}