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