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