blob: 567f338c82e611f621e4918eb70d47b90dc32ec1 [file] [log] [blame]
Naveen Moses3bd1cfc2022-02-14 18:04:20 +05301
2#include "hostSelector_switch.hpp"
3
LioraGuo-wiwynn5f3c2e52025-07-20 18:04:39 +08004#include "gpio.hpp"
5
George Liu9fb15972022-06-20 14:54:38 +08006#include <error.h>
7
8#include <phosphor-logging/lg2.hpp>
9
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053010// add the button iface class to registry
11static ButtonIFRegister<HostSelector> buttonRegister;
George Liu9fb15972022-06-20 14:54:38 +080012
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053013size_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 {
George Liu9fb15972022-06-20 14:54:38 +080025 lg2::debug("getMappedHSConfig : {TYPE}: no valid value in map.", "TYPE",
26 getFormFactorType());
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053027 }
28 return adjustedPosition;
29}
30
31size_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}
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080042
43char HostSelector::getValueFromFd(int fd)
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053044{
45 char buf;
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080046 auto result = ::lseek(fd, 0, SEEK_SET);
47
48 if (result < 0)
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053049 {
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080050 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
51 IOError();
52 }
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053053
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080054 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}
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053062
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080063void HostSelector::setInitialHostSelectorValue()
64{
65 size_t hsPosMapped = 0;
66
67 try
68 {
69 if (config.type == ConfigType::gpio)
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053070 {
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080071 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);
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053080 }
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080081 else if (config.type == ConfigType::cpld)
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053082 {
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080083 hsPosMapped = getValueFromFd(config.cpld.cpldMappedFd) - '0';
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053084 }
85 }
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080086 catch (const std::exception& e)
87 {
88 lg2::error("{TYPE}: exception while reading fd : {ERROR}", "TYPE",
89 getFormFactorType(), "ERROR", e.what());
90 }
91
LioraGuo-wiwynn5f3c2e52025-07-20 18:04:39 +080092 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
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800105 if (hsPosMapped != INVALID_INDEX)
106 {
107 position(hsPosMapped, true);
108 }
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530109}
110
111void 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
Naveen Mosesd219fa32022-07-20 00:01:46 +0530123 auto bit_op = (state == GpioState::deassert) ? set_bit : clr_bit;
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530124
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
George Liu94afa4b2022-06-20 13:36:43 +0800135void HostSelector::handleEvent(sd_event_source* /* es */, int fd,
136 uint32_t /* revents */)
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530137{
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530138 char buf = '0';
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800139 try
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530140 {
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800141 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());
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530147 return;
148 }
149
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800150 size_t hsPosMapped = 0;
151 if (config.type == ConfigType::gpio)
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530152 {
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800153 // read the gpio state for the io event received
Patrick Williamsd36b6b12024-08-16 15:20:34 -0400154 GpioState gpioState =
155 (buf == '0') ? (GpioState::deassert) : (GpioState::assert);
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800156
157 setHostSelectorValue(fd, gpioState);
158 hsPosMapped = getMappedHSConfig(hostSelectorPosition);
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530159 }
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800160 else if (config.type == ConfigType::cpld)
161 {
162 hsPosMapped = buf - '0';
163 }
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530164
165 if (hsPosMapped != INVALID_INDEX)
166 {
167 position(hsPosMapped);
168 }
Patrick Williams0d038f52023-05-10 07:50:40 -0500169}
LioraGuo-wiwynn5f3c2e52025-07-20 18:04:39 +0800170
171void 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}