xref: /openbmc/phosphor-fan-presence/presence/gpio.cpp (revision 5c5894878b09fdef8fcbee000f83283b73b8da64)
1*5c589487SBrad Bishop /**
2*5c589487SBrad Bishop  * Copyright © 2017 IBM Corporation
3*5c589487SBrad Bishop  *
4*5c589487SBrad Bishop  * Licensed under the Apache License, Version 2.0 (the "License");
5*5c589487SBrad Bishop  * you may not use this file except in compliance with the License.
6*5c589487SBrad Bishop  * You may obtain a copy of the License at
7*5c589487SBrad Bishop  *
8*5c589487SBrad Bishop  *     http://www.apache.org/licenses/LICENSE-2.0
9*5c589487SBrad Bishop  *
10*5c589487SBrad Bishop  * Unless required by applicable law or agreed to in writing, software
11*5c589487SBrad Bishop  * distributed under the License is distributed on an "AS IS" BASIS,
12*5c589487SBrad Bishop  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5c589487SBrad Bishop  * See the License for the specific language governing permissions and
14*5c589487SBrad Bishop  * limitations under the License.
15*5c589487SBrad Bishop  */
16*5c589487SBrad Bishop #include <memory>
17*5c589487SBrad Bishop #include <phosphor-logging/elog-errors.hpp>
18*5c589487SBrad Bishop #include <phosphor-logging/elog.hpp>
19*5c589487SBrad Bishop #include <tuple>
20*5c589487SBrad Bishop #include <xyz/openbmc_project/Common/Callout/error.hpp>
21*5c589487SBrad Bishop #include "gpio.hpp"
22*5c589487SBrad Bishop #include "rpolicy.hpp"
23*5c589487SBrad Bishop #include "sdevent.hpp"
24*5c589487SBrad Bishop 
25*5c589487SBrad Bishop namespace phosphor
26*5c589487SBrad Bishop {
27*5c589487SBrad Bishop namespace fan
28*5c589487SBrad Bishop {
29*5c589487SBrad Bishop namespace presence
30*5c589487SBrad Bishop {
31*5c589487SBrad Bishop 
32*5c589487SBrad Bishop Gpio::Gpio(
33*5c589487SBrad Bishop         const std::string& physDevice,
34*5c589487SBrad Bishop         unsigned int physPin) :
35*5c589487SBrad Bishop     currentState(false),
36*5c589487SBrad Bishop     evdevfd(open("/dev/input/by-path/platform-gpio-keys-event",
37*5c589487SBrad Bishop                  O_RDONLY | O_NONBLOCK)),
38*5c589487SBrad Bishop     evdev(evdevpp::evdev::newFromFD(evdevfd())),
39*5c589487SBrad Bishop     phys(physDevice),
40*5c589487SBrad Bishop     pin(physPin),
41*5c589487SBrad Bishop     callback(nullptr)
42*5c589487SBrad Bishop {
43*5c589487SBrad Bishop 
44*5c589487SBrad Bishop }
45*5c589487SBrad Bishop 
46*5c589487SBrad Bishop bool Gpio::start()
47*5c589487SBrad Bishop {
48*5c589487SBrad Bishop     callback = std::make_unique<sdevent::event::io::IO>(
49*5c589487SBrad Bishop             util::SDEvent::getEvent(),
50*5c589487SBrad Bishop             evdevfd(),
51*5c589487SBrad Bishop             [this](auto& s){this->ioCallback(s);});
52*5c589487SBrad Bishop     currentState = present();
53*5c589487SBrad Bishop     return currentState;
54*5c589487SBrad Bishop }
55*5c589487SBrad Bishop 
56*5c589487SBrad Bishop void Gpio::stop()
57*5c589487SBrad Bishop {
58*5c589487SBrad Bishop     callback = nullptr;
59*5c589487SBrad Bishop }
60*5c589487SBrad Bishop 
61*5c589487SBrad Bishop bool Gpio::present()
62*5c589487SBrad Bishop {
63*5c589487SBrad Bishop     return evdev.fetch(EV_KEY, pin) != 0;
64*5c589487SBrad Bishop }
65*5c589487SBrad Bishop 
66*5c589487SBrad Bishop void Gpio::fail()
67*5c589487SBrad Bishop {
68*5c589487SBrad Bishop     using namespace sdbusplus::xyz::openbmc_project::Common::Callout::Error;
69*5c589487SBrad Bishop     using namespace phosphor::logging;
70*5c589487SBrad Bishop     using namespace xyz::openbmc_project::Common::Callout;
71*5c589487SBrad Bishop 
72*5c589487SBrad Bishop     report<sdbusplus::xyz::openbmc_project::Common::Callout::Error::GPIO>(
73*5c589487SBrad Bishop             GPIO::CALLOUT_GPIO_NUM(pin),
74*5c589487SBrad Bishop             GPIO::CALLOUT_ERRNO(0),
75*5c589487SBrad Bishop             GPIO::CALLOUT_DEVICE_PATH(phys.c_str()));
76*5c589487SBrad Bishop }
77*5c589487SBrad Bishop 
78*5c589487SBrad Bishop void Gpio::ioCallback(sdevent::source::Source& source)
79*5c589487SBrad Bishop {
80*5c589487SBrad Bishop     unsigned int type, code, value;
81*5c589487SBrad Bishop 
82*5c589487SBrad Bishop     std::tie(type, code, value) = evdev.next();
83*5c589487SBrad Bishop     if (type != EV_KEY || code != pin)
84*5c589487SBrad Bishop     {
85*5c589487SBrad Bishop         return;
86*5c589487SBrad Bishop     }
87*5c589487SBrad Bishop 
88*5c589487SBrad Bishop     bool newState = value != 0;
89*5c589487SBrad Bishop 
90*5c589487SBrad Bishop     if (currentState != newState)
91*5c589487SBrad Bishop     {
92*5c589487SBrad Bishop         getPolicy().stateChanged(newState);
93*5c589487SBrad Bishop         currentState = newState;
94*5c589487SBrad Bishop     }
95*5c589487SBrad Bishop }
96*5c589487SBrad Bishop } // namespace presence
97*5c589487SBrad Bishop } // namespace fan
98*5c589487SBrad Bishop } // namespace phosphor
99