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