1 /* 2 // Copyright (c) 2018 Intel 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 17 #pragma once 18 #include "common.hpp" 19 #include "gpio.hpp" 20 #include "xyz/openbmc_project/Chassis/Buttons/Reset/server.hpp" 21 #include "xyz/openbmc_project/Chassis/Common/error.hpp" 22 23 #include <unistd.h> 24 25 #include <phosphor-logging/elog-errors.hpp> 26 27 const static constexpr char* RESET_BUTTON = "RESET_BUTTON"; 28 29 struct ResetButton 30 : sdbusplus::server::object::object< 31 sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Reset> 32 { 33 34 ResetButton(sdbusplus::bus::bus& bus, const char* path, EventPtr& event, 35 buttonConfig& buttonCfg, 36 sd_event_io_handler_t handler = ResetButton::EventHandler) : 37 sdbusplus::server::object::object< 38 sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Reset>( 39 bus, path), 40 fd(-1), buttonIFConfig(buttonCfg), bus(bus), event(event), 41 callbackHandler(handler) 42 { 43 44 int ret = -1; 45 46 // config group gpio based on the gpio defs read from the json file 47 ret = configGroupGpio(bus, buttonIFConfig); 48 49 if (ret < 0) 50 { 51 phosphor::logging::log<phosphor::logging::level::ERR>( 52 "RESET_BUTTON: failed to config GPIO"); 53 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: 54 IOError(); 55 } 56 57 // initialize the button io fd from the buttonConfig 58 // which has fd stored when configGroupGpio is called 59 fd = buttonIFConfig.gpios[0].fd; 60 61 char buf; 62 ::read(fd, &buf, sizeof(buf)); 63 64 ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI, 65 callbackHandler, this); 66 if (ret < 0) 67 { 68 phosphor::logging::log<phosphor::logging::level::ERR>( 69 "RESET_BUTTON: failed to add to event loop"); 70 ::closeGpio(fd); 71 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: 72 IOError(); 73 } 74 } 75 76 ~ResetButton() 77 { 78 ::closeGpio(fd); 79 } 80 81 void simPress() override; 82 83 static const std::string getGpioName() 84 { 85 return RESET_BUTTON; 86 } 87 88 static int EventHandler(sd_event_source* es, int fd, uint32_t revents, 89 void* userdata) 90 { 91 92 int n = -1; 93 char buf = '0'; 94 95 if (!userdata) 96 { 97 phosphor::logging::log<phosphor::logging::level::ERR>( 98 "RESET_BUTTON: userdata null!"); 99 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: 100 IOError(); 101 } 102 103 ResetButton* resetButton = static_cast<ResetButton*>(userdata); 104 105 if (!resetButton) 106 { 107 phosphor::logging::log<phosphor::logging::level::ERR>( 108 "RESET_BUTTON: null pointer!"); 109 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: 110 IOError(); 111 } 112 113 n = ::lseek(fd, 0, SEEK_SET); 114 115 if (n < 0) 116 { 117 phosphor::logging::log<phosphor::logging::level::ERR>( 118 "RESET_BUTTON: lseek error!"); 119 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: 120 IOError(); 121 } 122 123 n = ::read(fd, &buf, sizeof(buf)); 124 if (n < 0) 125 { 126 phosphor::logging::log<phosphor::logging::level::ERR>( 127 "RESET_BUTTON: read error!"); 128 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: 129 IOError(); 130 } 131 132 if (buf == '0') 133 { 134 phosphor::logging::log<phosphor::logging::level::DEBUG>( 135 "RESET_BUTTON: pressed"); 136 // emit pressed signal 137 resetButton->pressed(); 138 } 139 else 140 { 141 phosphor::logging::log<phosphor::logging::level::DEBUG>( 142 "RESET_BUTTON: released"); 143 // released 144 resetButton->released(); 145 } 146 147 return 0; 148 } 149 150 private: 151 int fd; 152 buttonConfig buttonIFConfig; // button iface io details 153 sdbusplus::bus::bus& bus; 154 EventPtr& event; 155 sd_event_io_handler_t callbackHandler; 156 }; 157