1*a9d39e30SKuiying Wang /* 2*a9d39e30SKuiying Wang // Copyright (c) 2018 Intel Corporation 3*a9d39e30SKuiying Wang // 4*a9d39e30SKuiying Wang // Licensed under the Apache License, Version 2.0 (the "License"); 5*a9d39e30SKuiying Wang // you may not use this file except in compliance with the License. 6*a9d39e30SKuiying Wang // You may obtain a copy of the License at 7*a9d39e30SKuiying Wang // 8*a9d39e30SKuiying Wang // http://www.apache.org/licenses/LICENSE-2.0 9*a9d39e30SKuiying Wang // 10*a9d39e30SKuiying Wang // Unless required by applicable law or agreed to in writing, software 11*a9d39e30SKuiying Wang // distributed under the License is distributed on an "AS IS" BASIS, 12*a9d39e30SKuiying Wang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*a9d39e30SKuiying Wang // See the License for the specific language governing permissions and 14*a9d39e30SKuiying Wang // limitations under the License. 15*a9d39e30SKuiying Wang */ 16*a9d39e30SKuiying Wang 17*a9d39e30SKuiying Wang #pragma once 18*a9d39e30SKuiying Wang #include <phosphor-logging/elog-errors.hpp> 19*a9d39e30SKuiying Wang #include <unistd.h> 20*a9d39e30SKuiying Wang #include "xyz/openbmc_project/Chassis/Common/error.hpp" 21*a9d39e30SKuiying Wang #include "xyz/openbmc_project/Chassis/Buttons/Power/server.hpp" 22*a9d39e30SKuiying Wang #include "common.hpp" 23*a9d39e30SKuiying Wang #include "gpio.hpp" 24*a9d39e30SKuiying Wang 25*a9d39e30SKuiying Wang const static constexpr char* POWER_BUTTON = "POWER_BUTTON"; 26*a9d39e30SKuiying Wang 27*a9d39e30SKuiying Wang struct PowerButton 28*a9d39e30SKuiying Wang : sdbusplus::server::object::object< 29*a9d39e30SKuiying Wang sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Power> 30*a9d39e30SKuiying Wang { 31*a9d39e30SKuiying Wang 32*a9d39e30SKuiying Wang PowerButton(sdbusplus::bus::bus& bus, const char* path, 33*a9d39e30SKuiying Wang EventPtr& event, 34*a9d39e30SKuiying Wang sd_event_io_handler_t handler = PowerButton::EventHandler) : 35*a9d39e30SKuiying Wang sdbusplus::server::object::object< 36*a9d39e30SKuiying Wang sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Power>( 37*a9d39e30SKuiying Wang bus, path), 38*a9d39e30SKuiying Wang fd(-1), bus(bus), event(event), callbackHandler(handler) 39*a9d39e30SKuiying Wang { 40*a9d39e30SKuiying Wang 41*a9d39e30SKuiying Wang int ret = -1; 42*a9d39e30SKuiying Wang 43*a9d39e30SKuiying Wang // config gpio 44*a9d39e30SKuiying Wang ret = ::configGpio(POWER_BUTTON, &fd, bus); 45*a9d39e30SKuiying Wang if (ret < 0) 46*a9d39e30SKuiying Wang { 47*a9d39e30SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>( 48*a9d39e30SKuiying Wang "POWER_BUTTON: failed to config GPIO"); 49*a9d39e30SKuiying Wang throw sdbusplus::xyz::openbmc_project::Chassis::Common:: 50*a9d39e30SKuiying Wang Error::IOError(); 51*a9d39e30SKuiying Wang } 52*a9d39e30SKuiying Wang 53*a9d39e30SKuiying Wang ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI, 54*a9d39e30SKuiying Wang callbackHandler, this); 55*a9d39e30SKuiying Wang if (ret < 0) 56*a9d39e30SKuiying Wang { 57*a9d39e30SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>( 58*a9d39e30SKuiying Wang "POWER_BUTTON: failed to add to event loop"); 59*a9d39e30SKuiying Wang ::closeGpio(fd); 60*a9d39e30SKuiying Wang throw sdbusplus::xyz::openbmc_project::Chassis::Common:: 61*a9d39e30SKuiying Wang Error::IOError(); 62*a9d39e30SKuiying Wang } 63*a9d39e30SKuiying Wang } 64*a9d39e30SKuiying Wang 65*a9d39e30SKuiying Wang ~PowerButton() 66*a9d39e30SKuiying Wang { 67*a9d39e30SKuiying Wang ::closeGpio(fd); 68*a9d39e30SKuiying Wang } 69*a9d39e30SKuiying Wang 70*a9d39e30SKuiying Wang void simPress() override; 71*a9d39e30SKuiying Wang void simLongPress() override; 72*a9d39e30SKuiying Wang 73*a9d39e30SKuiying Wang static int EventHandler(sd_event_source* es, int fd, 74*a9d39e30SKuiying Wang uint32_t revents, void* userdata) 75*a9d39e30SKuiying Wang { 76*a9d39e30SKuiying Wang 77*a9d39e30SKuiying Wang int n = -1; 78*a9d39e30SKuiying Wang char buf = '0'; 79*a9d39e30SKuiying Wang 80*a9d39e30SKuiying Wang if (!userdata) 81*a9d39e30SKuiying Wang { 82*a9d39e30SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>( 83*a9d39e30SKuiying Wang "POWER_BUTTON: userdata null!"); 84*a9d39e30SKuiying Wang throw sdbusplus::xyz::openbmc_project::Chassis::Common:: 85*a9d39e30SKuiying Wang Error::IOError(); 86*a9d39e30SKuiying Wang } 87*a9d39e30SKuiying Wang 88*a9d39e30SKuiying Wang PowerButton* powerButton = static_cast<PowerButton*>(userdata); 89*a9d39e30SKuiying Wang 90*a9d39e30SKuiying Wang if (!powerButton) 91*a9d39e30SKuiying Wang { 92*a9d39e30SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>( 93*a9d39e30SKuiying Wang "POWER_BUTTON: null pointer!"); 94*a9d39e30SKuiying Wang throw sdbusplus::xyz::openbmc_project::Chassis::Common:: 95*a9d39e30SKuiying Wang Error::IOError(); 96*a9d39e30SKuiying Wang } 97*a9d39e30SKuiying Wang 98*a9d39e30SKuiying Wang n = ::lseek(fd, 0, SEEK_SET); 99*a9d39e30SKuiying Wang 100*a9d39e30SKuiying Wang if (n < 0) 101*a9d39e30SKuiying Wang { 102*a9d39e30SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>( 103*a9d39e30SKuiying Wang "POWER_BUTTON: lseek error!"); 104*a9d39e30SKuiying Wang throw sdbusplus::xyz::openbmc_project::Chassis::Common:: 105*a9d39e30SKuiying Wang Error::IOError(); 106*a9d39e30SKuiying Wang } 107*a9d39e30SKuiying Wang 108*a9d39e30SKuiying Wang n = ::read(fd, &buf, sizeof(buf)); 109*a9d39e30SKuiying Wang if (n < 0) 110*a9d39e30SKuiying Wang { 111*a9d39e30SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>( 112*a9d39e30SKuiying Wang "POWER_BUTTON: read error!"); 113*a9d39e30SKuiying Wang throw sdbusplus::xyz::openbmc_project::Chassis::Common:: 114*a9d39e30SKuiying Wang Error::IOError(); 115*a9d39e30SKuiying Wang } 116*a9d39e30SKuiying Wang 117*a9d39e30SKuiying Wang if (buf == '0') 118*a9d39e30SKuiying Wang { 119*a9d39e30SKuiying Wang phosphor::logging::log<phosphor::logging::level::DEBUG>( 120*a9d39e30SKuiying Wang "POWER_BUTTON: pressed"); 121*a9d39e30SKuiying Wang // emit pressed signal 122*a9d39e30SKuiying Wang powerButton->pressed(); 123*a9d39e30SKuiying Wang } 124*a9d39e30SKuiying Wang else 125*a9d39e30SKuiying Wang { 126*a9d39e30SKuiying Wang phosphor::logging::log<phosphor::logging::level::DEBUG>( 127*a9d39e30SKuiying Wang "POWER_BUTTON: released"); 128*a9d39e30SKuiying Wang // released 129*a9d39e30SKuiying Wang powerButton->released(); 130*a9d39e30SKuiying Wang } 131*a9d39e30SKuiying Wang 132*a9d39e30SKuiying Wang return 0; 133*a9d39e30SKuiying Wang } 134*a9d39e30SKuiying Wang 135*a9d39e30SKuiying Wang private: 136*a9d39e30SKuiying Wang int fd; 137*a9d39e30SKuiying Wang sdbusplus::bus::bus& bus; 138*a9d39e30SKuiying Wang EventPtr& event; 139*a9d39e30SKuiying Wang sd_event_io_handler_t callbackHandler; 140*a9d39e30SKuiying Wang }; 141