| #pragma once |
| |
| #include "lpcsnoop/snoop.hpp" |
| |
| #include <boost/asio.hpp> |
| #include <filesystem> |
| #include <gpiod.hpp> |
| #include <iostream> |
| #include <sdbusplus/asio/connection.hpp> |
| #include <sdbusplus/asio/object_server.hpp> |
| #include <sdbusplus/asio/property.hpp> |
| #include <sdbusplus/bus.hpp> |
| #include <sdbusplus/server.hpp> |
| #include <xyz/openbmc_project/Chassis/Buttons/HostSelector/server.hpp> |
| #include <xyz/openbmc_project/State/Boot/Raw/server.hpp> |
| |
| const std::string ipmiSnoopObject = "/xyz/openbmc_project/state/boot/raw"; |
| |
| const int hostParseIdx = 3; |
| const int maxPostcode = 255; |
| const int maxPosition = 4; |
| |
| std::vector<gpiod::line> led_lines; |
| |
| using Selector = |
| sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::HostSelector; |
| |
| std::unique_ptr<sdbusplus::bus::match_t> matchSignal; |
| |
| const std::string selectorService = "xyz.openbmc_project.Chassis.Buttons"; |
| const std::string selectorObject = |
| "/xyz/openbmc_project/Chassis/Buttons/HostSelector"; |
| const std::string selectorIface = |
| "xyz.openbmc_project.Chassis.Buttons.HostSelector"; |
| |
| const std::string rawObject = "/xyz/openbmc_project/state/boot"; |
| const std::string rawIface = "xyz.openbmc_project.State.Boot.Raw"; |
| const std::string rawService = "xyz.openbmc_project.State.Boot.Raw"; |
| |
| uint32_t getSelectorPosition(sdbusplus::bus_t& bus) |
| { |
| const std::string propertyName = "Position"; |
| |
| auto method = |
| bus.new_method_call(selectorService.c_str(), selectorObject.c_str(), |
| "org.freedesktop.DBus.Properties", "Get"); |
| method.append(selectorIface.c_str(), propertyName); |
| |
| try |
| { |
| std::variant<uint32_t> value{}; |
| auto reply = bus.call(method); |
| reply.read(value); |
| return std::get<uint32_t>(value); |
| } |
| catch (const sdbusplus::exception_t& ex) |
| { |
| std::cerr << "GetProperty call failed "; |
| throw std::runtime_error("GetProperty call failed"); |
| } |
| } |
| |
| struct IpmiPostReporter : PostObject |
| { |
| IpmiPostReporter(sdbusplus::bus_t& bus, const char* objPath) : |
| PostObject(bus, objPath), bus(bus), |
| propertiesChangedSignalRaw( |
| bus, |
| sdbusplus::bus::match::rules::propertiesChanged(objPath, rawIface), |
| |
| [this, &bus](sdbusplus::message_t& msg) { |
| using primarycode_t = uint64_t; |
| using secondarycode_t = std::vector<uint8_t>; |
| using postcode_t = std::tuple<primarycode_t, secondarycode_t>; |
| |
| std::string objectName; |
| std::string InterfaceName; |
| std::map<std::string, std::variant<postcode_t>> msgData; |
| msg.read(InterfaceName, msgData); |
| |
| std::filesystem::path name(msg.get_path()); |
| objectName = name.filename(); |
| |
| std::string hostNumStr = objectName.substr(hostParseIdx); |
| size_t hostNum = std::stoi(hostNumStr); |
| |
| size_t position = getSelectorPosition(bus); |
| |
| if (position > maxPosition) |
| { |
| std::cerr << "Invalid position. Position should be 1 to 4 " |
| "for all hosts " |
| << std::endl; |
| } |
| |
| // Check if it was the Value property that changed. |
| auto valPropMap = msgData.find("Value"); |
| if (valPropMap == msgData.end()) |
| { |
| std::cerr << "Value property is not found " << std::endl; |
| return; |
| } |
| uint64_t postcode = |
| std::get<0>(std::get<postcode_t>(valPropMap->second)); |
| |
| if (postcode <= maxPostcode) |
| { |
| if (position == hostNum) |
| { |
| uint8_t postcode_8bit = |
| static_cast<uint8_t>(postcode & 0x0000FF); |
| |
| // write postcode into seven segment display |
| if (postCodeDisplay(postcode_8bit) < 0) |
| { |
| fprintf(stderr, "Error in display the postcode\n"); |
| } |
| } |
| else |
| { |
| fprintf(stderr, "Host Selector Position and host " |
| "number is not matched..\n"); |
| } |
| } |
| else |
| { |
| fprintf(stderr, "invalid postcode value \n"); |
| } |
| }) |
| { |
| } |
| |
| sdbusplus::bus_t& bus; |
| sdbusplus::bus::match_t propertiesChangedSignalRaw; |
| int postCodeDisplay(uint8_t); |
| void getSelectorPositionSignal(sdbusplus::bus_t& bus); |
| }; |
| |
| // Configure the seven segment display connected GPIOs direction |
| int configGPIODirOutput() |
| { |
| std::string gpioStr; |
| // Need to define gpio names LED_POST_CODE_0 to 8 in dts file |
| std::string gpioName = "LED_POST_CODE_"; |
| const int value = 0; |
| |
| for (int iteration = 0; iteration < 8; iteration++) |
| { |
| gpioStr = gpioName + std::to_string(iteration); |
| gpiod::line gpioLine = gpiod::find_line(gpioStr); |
| |
| if (!gpioLine) |
| { |
| std::string errMsg = "Failed to find the " + gpioStr + " line"; |
| std::cerr << errMsg.c_str() << std::endl; |
| return -1; |
| } |
| |
| led_lines.push_back(gpioLine); |
| // Request GPIO output to specified value |
| try |
| { |
| gpioLine.request({__FUNCTION__, |
| gpiod::line_request::DIRECTION_OUTPUT, |
| gpiod::line_request::FLAG_ACTIVE_LOW}, |
| value); |
| } |
| catch (std::exception&) |
| { |
| std::string errMsg = "Failed to request " + gpioStr + " output"; |
| std::cerr << errMsg.c_str() << std::endl; |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| // Display the received postcode into seven segment display |
| int IpmiPostReporter::postCodeDisplay(uint8_t status) |
| { |
| for (int iteration = 0; iteration < 8; iteration++) |
| { |
| // split byte to write into GPIOs |
| int value = !((status >> iteration) & 0x01); |
| |
| led_lines[iteration].set_value(value); |
| } |
| return 0; |
| } |