1 
2 #include "hostSelector_switch.hpp"
3 
4 #include <error.h>
5 
6 #include <phosphor-logging/lg2.hpp>
7 
8 // add the button iface class to registry
9 static ButtonIFRegister<HostSelector> buttonRegister;
10 
getMappedHSConfig(size_t hsPosition)11 size_t HostSelector::getMappedHSConfig(size_t hsPosition)
12 {
13     size_t adjustedPosition = INVALID_INDEX; // set bmc as default value
14     std::string hsPosStr;
15     hsPosStr = std::to_string(hsPosition);
16 
17     if (hsPosMap.find(hsPosStr) != hsPosMap.end())
18     {
19         adjustedPosition = hsPosMap[hsPosStr];
20     }
21     else
22     {
23         lg2::debug("getMappedHSConfig : {TYPE}: no valid value in map.", "TYPE",
24                    getFormFactorType());
25     }
26     return adjustedPosition;
27 }
28 
getGpioIndex(int fd)29 size_t HostSelector::getGpioIndex(int fd)
30 {
31     for (size_t index = 0; index < gpioLineCount; index++)
32     {
33         if (config.gpios[index].fd == fd)
34         {
35             return index;
36         }
37     }
38     return INVALID_INDEX;
39 }
40 
getValueFromFd(int fd)41 char HostSelector::getValueFromFd(int fd)
42 {
43     char buf;
44     auto result = ::lseek(fd, 0, SEEK_SET);
45 
46     if (result < 0)
47     {
48         throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
49             IOError();
50     }
51 
52     result = ::read(fd, &buf, sizeof(buf));
53     if (result < 0)
54     {
55         throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
56             IOError();
57     }
58     return buf;
59 }
60 
setInitialHostSelectorValue()61 void HostSelector::setInitialHostSelectorValue()
62 {
63     size_t hsPosMapped = 0;
64 
65     try
66     {
67         if (config.type == ConfigType::gpio)
68         {
69             for (size_t index = 0; index < gpioLineCount; index++)
70             {
71                 GpioState gpioState =
72                     (getValueFromFd(config.gpios[index].fd) == '0')
73                         ? (GpioState::deassert)
74                         : (GpioState::assert);
75                 setHostSelectorValue(config.gpios[index].fd, gpioState);
76             }
77             hsPosMapped = getMappedHSConfig(hostSelectorPosition);
78         }
79         else if (config.type == ConfigType::cpld)
80         {
81             hsPosMapped = getValueFromFd(config.cpld.cpldMappedFd) - '0';
82         }
83     }
84     catch (const std::exception& e)
85     {
86         lg2::error("{TYPE}: exception while reading fd : {ERROR}", "TYPE",
87                    getFormFactorType(), "ERROR", e.what());
88     }
89 
90     if (hsPosMapped != INVALID_INDEX)
91     {
92         position(hsPosMapped, true);
93     }
94 }
95 
setHostSelectorValue(int fd,GpioState state)96 void HostSelector::setHostSelectorValue(int fd, GpioState state)
97 {
98     size_t pos = getGpioIndex(fd);
99 
100     if (pos == INVALID_INDEX)
101     {
102         return;
103     }
104     auto set_bit = [](size_t& val, size_t n) { val |= 0xff & (1 << n); };
105 
106     auto clr_bit = [](size_t& val, size_t n) { val &= ~(0xff & (1 << n)); };
107 
108     auto bit_op = (state == GpioState::deassert) ? set_bit : clr_bit;
109 
110     bit_op(hostSelectorPosition, pos);
111     return;
112 }
113 /**
114  * @brief This method is called from sd-event provided callback function
115  * callbackHandler if platform specific event handling is needed then a
116  * derived class instance with its specific event handling logic along with
117  * init() function can be created to override the default event handling
118  */
119 
handleEvent(sd_event_source *,int fd,uint32_t)120 void HostSelector::handleEvent(sd_event_source* /* es */, int fd,
121                                uint32_t /* revents */)
122 {
123     char buf = '0';
124     try
125     {
126         buf = getValueFromFd(fd);
127     }
128     catch (const std::exception& e)
129     {
130         lg2::error("{TYPE}: exception while reading fd : {ERROR}", "TYPE",
131                    getFormFactorType(), "ERROR", e.what());
132         return;
133     }
134 
135     size_t hsPosMapped = 0;
136     if (config.type == ConfigType::gpio)
137     {
138         // read the gpio state for the io event received
139         GpioState gpioState =
140             (buf == '0') ? (GpioState::deassert) : (GpioState::assert);
141 
142         setHostSelectorValue(fd, gpioState);
143         hsPosMapped = getMappedHSConfig(hostSelectorPosition);
144     }
145     else if (config.type == ConfigType::cpld)
146     {
147         hsPosMapped = buf - '0';
148     }
149 
150     if (hsPosMapped != INVALID_INDEX)
151     {
152         position(hsPosMapped);
153     }
154 }
155