xref: /openbmc/phosphor-buttons/src/hostSelector_switch.cpp (revision 5f3c2e5b1115d0b532c8dc5330009fea42d4f15b)
1 
2 #include "hostSelector_switch.hpp"
3 
4 #include "gpio.hpp"
5 
6 #include <error.h>
7 
8 #include <phosphor-logging/lg2.hpp>
9 
10 // add the button iface class to registry
11 static ButtonIFRegister<HostSelector> buttonRegister;
12 
getMappedHSConfig(size_t hsPosition)13 size_t HostSelector::getMappedHSConfig(size_t hsPosition)
14 {
15     size_t adjustedPosition = INVALID_INDEX; // set bmc as default value
16     std::string hsPosStr;
17     hsPosStr = std::to_string(hsPosition);
18 
19     if (hsPosMap.find(hsPosStr) != hsPosMap.end())
20     {
21         adjustedPosition = hsPosMap[hsPosStr];
22     }
23     else
24     {
25         lg2::debug("getMappedHSConfig : {TYPE}: no valid value in map.", "TYPE",
26                    getFormFactorType());
27     }
28     return adjustedPosition;
29 }
30 
getGpioIndex(int fd)31 size_t HostSelector::getGpioIndex(int fd)
32 {
33     for (size_t index = 0; index < gpioLineCount; index++)
34     {
35         if (config.gpios[index].fd == fd)
36         {
37             return index;
38         }
39     }
40     return INVALID_INDEX;
41 }
42 
getValueFromFd(int fd)43 char HostSelector::getValueFromFd(int fd)
44 {
45     char buf;
46     auto result = ::lseek(fd, 0, SEEK_SET);
47 
48     if (result < 0)
49     {
50         throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
51             IOError();
52     }
53 
54     result = ::read(fd, &buf, sizeof(buf));
55     if (result < 0)
56     {
57         throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
58             IOError();
59     }
60     return buf;
61 }
62 
setInitialHostSelectorValue()63 void HostSelector::setInitialHostSelectorValue()
64 {
65     size_t hsPosMapped = 0;
66 
67     try
68     {
69         if (config.type == ConfigType::gpio)
70         {
71             for (size_t index = 0; index < gpioLineCount; index++)
72             {
73                 GpioState gpioState =
74                     (getValueFromFd(config.gpios[index].fd) == '0')
75                         ? (GpioState::deassert)
76                         : (GpioState::assert);
77                 setHostSelectorValue(config.gpios[index].fd, gpioState);
78             }
79             hsPosMapped = getMappedHSConfig(hostSelectorPosition);
80         }
81         else if (config.type == ConfigType::cpld)
82         {
83             hsPosMapped = getValueFromFd(config.cpld.cpldMappedFd) - '0';
84         }
85     }
86     catch (const std::exception& e)
87     {
88         lg2::error("{TYPE}: exception while reading fd : {ERROR}", "TYPE",
89                    getFormFactorType(), "ERROR", e.what());
90     }
91 
92     if (config.extraJsonInfo.value("polling_mode", false))
93     {
94         // If polling mode is enabled, set up a timer to poll the GPIO state
95         int intervalMs =
96             config.extraJsonInfo.value("polling_interval_ms", 1000);
97         auto event = Event::get_default();
98         pollTimer.emplace(
99             event, [this](Timer&) { pollGpioState(); },
100             std::chrono::milliseconds(intervalMs));
101         pollTimer->setEnabled(true);
102         lg2::info("Started polling mode: {MS}ms", "MS", intervalMs);
103     }
104 
105     if (hsPosMapped != INVALID_INDEX)
106     {
107         position(hsPosMapped, true);
108     }
109 }
110 
setHostSelectorValue(int fd,GpioState state)111 void HostSelector::setHostSelectorValue(int fd, GpioState state)
112 {
113     size_t pos = getGpioIndex(fd);
114 
115     if (pos == INVALID_INDEX)
116     {
117         return;
118     }
119     auto set_bit = [](size_t& val, size_t n) { val |= 0xff & (1 << n); };
120 
121     auto clr_bit = [](size_t& val, size_t n) { val &= ~(0xff & (1 << n)); };
122 
123     auto bit_op = (state == GpioState::deassert) ? set_bit : clr_bit;
124 
125     bit_op(hostSelectorPosition, pos);
126     return;
127 }
128 /**
129  * @brief This method is called from sd-event provided callback function
130  * callbackHandler if platform specific event handling is needed then a
131  * derived class instance with its specific event handling logic along with
132  * init() function can be created to override the default event handling
133  */
134 
handleEvent(sd_event_source *,int fd,uint32_t)135 void HostSelector::handleEvent(sd_event_source* /* es */, int fd,
136                                uint32_t /* revents */)
137 {
138     char buf = '0';
139     try
140     {
141         buf = getValueFromFd(fd);
142     }
143     catch (const std::exception& e)
144     {
145         lg2::error("{TYPE}: exception while reading fd : {ERROR}", "TYPE",
146                    getFormFactorType(), "ERROR", e.what());
147         return;
148     }
149 
150     size_t hsPosMapped = 0;
151     if (config.type == ConfigType::gpio)
152     {
153         // read the gpio state for the io event received
154         GpioState gpioState =
155             (buf == '0') ? (GpioState::deassert) : (GpioState::assert);
156 
157         setHostSelectorValue(fd, gpioState);
158         hsPosMapped = getMappedHSConfig(hostSelectorPosition);
159     }
160     else if (config.type == ConfigType::cpld)
161     {
162         hsPosMapped = buf - '0';
163     }
164 
165     if (hsPosMapped != INVALID_INDEX)
166     {
167         position(hsPosMapped);
168     }
169 }
170 
pollGpioState()171 void HostSelector::pollGpioState()
172 {
173     for (const auto& gpioInfo : config.gpios)
174     {
175         GpioState state = getGpioState(gpioInfo.fd, gpioInfo.polarity);
176         setHostSelectorValue(gpioInfo.fd, state);
177         lg2::debug("GPIO {NUM} state is {STATE}", "NUM", gpioInfo.number,
178                    "STATE", state);
179     }
180 
181     size_t currentPos = getMappedHSConfig(hostSelectorPosition);
182 
183     if (currentPos != INVALID_INDEX && currentPos != previousPos)
184     {
185         position(currentPos);
186         previousPos = currentPos;
187         lg2::info("Host selector position updated to {POS}", "POS", currentPos);
188     }
189 }
190