1d219fa3cSNaveen Moses #include "serial_uart_mux.hpp"
2d219fa3cSNaveen Moses 
3d219fa3cSNaveen Moses #include "xyz/openbmc_project/Chassis/Buttons/HostSelector/server.hpp"
4d219fa3cSNaveen Moses 
5d219fa3cSNaveen Moses #include <error.h>
6d219fa3cSNaveen Moses 
7d219fa3cSNaveen Moses #include <phosphor-logging/lg2.hpp>
8d219fa3cSNaveen Moses namespace sdbusRule = sdbusplus::bus::match::rules;
9d219fa3cSNaveen Moses // add the button iface class to registry
10d219fa3cSNaveen Moses static ButtonIFRegister<SerialUartMux> buttonRegister;
11*0d6d74c8SPatrick Williams using HostSelectorServerObj =
12*0d6d74c8SPatrick Williams     sdbusplus::server::xyz::openbmc_project::chassis::buttons::HostSelector;
13*0d6d74c8SPatrick Williams using HostSelectorClientObj =
14*0d6d74c8SPatrick Williams     sdbusplus::common::xyz::openbmc_project::chassis::buttons::HostSelector;
15d219fa3cSNaveen Moses 
16d219fa3cSNaveen Moses constexpr std::string_view SERIAL_UART_RX_GPIO = "serial_uart_rx";
init()17d219fa3cSNaveen Moses void SerialUartMux::init()
18d219fa3cSNaveen Moses {
19d219fa3cSNaveen Moses     try
20d219fa3cSNaveen Moses     {
21d219fa3cSNaveen Moses         // when Host Selector Position is changed call the handler
22d219fa3cSNaveen Moses 
23d219fa3cSNaveen Moses         std::string matchPattern = sdbusRule::propertiesChanged(
24d219fa3cSNaveen Moses             HS_DBUS_OBJECT_NAME, HostSelectorClientObj::interface);
25d219fa3cSNaveen Moses 
26d219fa3cSNaveen Moses         hostPositionChanged = std::make_unique<sdbusplus::bus::match_t>(
27d219fa3cSNaveen Moses             bus, matchPattern,
28d219fa3cSNaveen Moses             std::bind(std::mem_fn(&SerialUartMux::hostSelectorPositionChanged),
29d219fa3cSNaveen Moses                       this, std::placeholders::_1));
30d219fa3cSNaveen Moses     }
31d219fa3cSNaveen Moses     catch (const std::exception& e)
32d219fa3cSNaveen Moses     {
33d219fa3cSNaveen Moses         lg2::error(
34d219fa3cSNaveen Moses             "Failed binding to matching function : {BUTTON_TYPE},Exception : {ERROR}",
35d219fa3cSNaveen Moses             "BUTTON_TYPE", getFormFactorName(), "ERROR", e);
36d219fa3cSNaveen Moses         throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
37d219fa3cSNaveen Moses             IOError();
38d219fa3cSNaveen Moses     }
39d219fa3cSNaveen Moses }
40d219fa3cSNaveen Moses // check the debug card present pin
isOCPDebugCardPresent()41d219fa3cSNaveen Moses bool SerialUartMux::isOCPDebugCardPresent()
42d219fa3cSNaveen Moses {
430d038f58SPatrick Williams     auto gpioState = getGpioState(debugCardPresentGpio.fd,
440d038f58SPatrick Williams                                   debugCardPresentGpio.polarity);
45d219fa3cSNaveen Moses     return (gpioState == GpioState::assert);
46d219fa3cSNaveen Moses }
47d219fa3cSNaveen Moses // set the serial uart MUX to select the console w.r.t host selector position
configSerialConsoleMux(size_t position)48d219fa3cSNaveen Moses void SerialUartMux::configSerialConsoleMux(size_t position)
49d219fa3cSNaveen Moses {
50d219fa3cSNaveen Moses     auto debugCardPresent = isOCPDebugCardPresent();
51d219fa3cSNaveen Moses 
52d219fa3cSNaveen Moses     if (debugCardPresent)
53d219fa3cSNaveen Moses     {
54d219fa3cSNaveen Moses         lg2::info("Debug card is present ");
55d219fa3cSNaveen Moses     }
56d219fa3cSNaveen Moses     else
57d219fa3cSNaveen Moses     {
58d219fa3cSNaveen Moses         lg2::info("Debug card not present ");
59d219fa3cSNaveen Moses     }
60d219fa3cSNaveen Moses 
61d219fa3cSNaveen Moses     for (size_t uartMuxSel = 0; uartMuxSel < gpioLineCount; uartMuxSel++)
62d219fa3cSNaveen Moses     {
63d219fa3cSNaveen Moses         auto gpioState = GpioState::invalid;
64ccd7db05SDelphine CC Chiu         GpioInfo gpioConfig = config.gpios[uartMuxSel];
65d219fa3cSNaveen Moses 
66d219fa3cSNaveen Moses         if (gpioConfig.name == SERIAL_UART_RX_GPIO)
67d219fa3cSNaveen Moses         {
680d038f58SPatrick Williams             gpioState = debugCardPresent ? GpioState::assert
690d038f58SPatrick Williams                                          : GpioState::deassert;
70d219fa3cSNaveen Moses         }
71d219fa3cSNaveen Moses         else
72d219fa3cSNaveen Moses         {
73d219fa3cSNaveen Moses             gpioState = (serialUartMuxMap[position] & (0x1 << uartMuxSel))
74d219fa3cSNaveen Moses                             ? GpioState::assert
75d219fa3cSNaveen Moses                             : GpioState::deassert;
76d219fa3cSNaveen Moses         }
77d219fa3cSNaveen Moses         setGpioState(gpioConfig.fd, gpioConfig.polarity, gpioState);
78d219fa3cSNaveen Moses     }
79d219fa3cSNaveen Moses }
80d219fa3cSNaveen Moses 
hostSelectorPositionChanged(sdbusplus::message_t & msg)81d219fa3cSNaveen Moses void SerialUartMux::hostSelectorPositionChanged(sdbusplus::message_t& msg)
82d219fa3cSNaveen Moses {
83d219fa3cSNaveen Moses     std::string interface;
84*0d6d74c8SPatrick Williams     std::map<std::string, HostSelectorServerObj::PropertiesVariant>
85d219fa3cSNaveen Moses         propertiesChanged;
86d219fa3cSNaveen Moses     lg2::info("hostSelectorPositionChanged callback : {BUTTON_TYPE}",
87d219fa3cSNaveen Moses               "BUTTON_TYPE", getFormFactorName());
88d219fa3cSNaveen Moses 
89d219fa3cSNaveen Moses     try
90d219fa3cSNaveen Moses     {
91d219fa3cSNaveen Moses         msg.read(interface, propertiesChanged);
92d219fa3cSNaveen Moses         for (auto& property : propertiesChanged)
93d219fa3cSNaveen Moses         {
94d219fa3cSNaveen Moses             auto propertyName = property.first;
95d219fa3cSNaveen Moses             if (propertyName == "Position")
96d219fa3cSNaveen Moses             {
97d219fa3cSNaveen Moses                 size_t hostPosition = std::get<size_t>(property.second);
98d219fa3cSNaveen Moses                 lg2::debug("property changed : {VALUE}", "VALUE", hostPosition);
99d219fa3cSNaveen Moses                 configSerialConsoleMux(hostPosition);
100d219fa3cSNaveen Moses                 return;
101d219fa3cSNaveen Moses             }
102d219fa3cSNaveen Moses         }
103d219fa3cSNaveen Moses     }
104d219fa3cSNaveen Moses     catch (const std::exception& e)
105d219fa3cSNaveen Moses     {
106d219fa3cSNaveen Moses         lg2::error("exception while reading dbus property : {ERROR}", "ERROR",
107d219fa3cSNaveen Moses                    e.what());
108d219fa3cSNaveen Moses         return;
109d219fa3cSNaveen Moses     }
110d219fa3cSNaveen Moses }
111