1 #pragma once 2 3 #include "common.hpp" 4 #include "gpio.hpp" 5 #include "xyz/openbmc_project/Chassis/Common/error.hpp" 6 7 #include <phosphor-logging/elog-errors.hpp> 8 // This is the base class for all the button interface types 9 // 10 class ButtonIface 11 { 12 public: 13 ButtonIface(sdbusplus::bus_t& bus, EventPtr& event, buttonConfig& buttonCfg, 14 sd_event_io_handler_t handler = ButtonIface::EventHandler) : 15 bus(bus), 16 event(event), config(buttonCfg), callbackHandler(handler) 17 { 18 int ret = -1; 19 20 // config group gpio based on the gpio defs read from the json file 21 ret = configGroupGpio(config); 22 23 if (ret < 0) 24 { 25 phosphor::logging::log<phosphor::logging::level::ERR>( 26 (getFormFactorType() + " : failed to config GPIO").c_str()); 27 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: 28 IOError(); 29 } 30 } 31 virtual ~ButtonIface() 32 {} 33 34 /** 35 * @brief This method is called from sd-event provided callback function 36 * callbackHandler if platform specific event handling is needed then a 37 * derived class instance with its specific evend handling logic along with 38 * init() function can be created to override the default event handling. 39 */ 40 41 virtual void handleEvent(sd_event_source* es, int fd, uint32_t revents) = 0; 42 static int EventHandler(sd_event_source* es, int fd, uint32_t revents, 43 void* userdata) 44 { 45 if (userdata) 46 { 47 ButtonIface* buttonIface = static_cast<ButtonIface*>(userdata); 48 buttonIface->handleEvent(es, fd, revents); 49 } 50 51 return 0; 52 } 53 54 std::string getFormFactorType() const 55 { 56 return config.formFactorName; 57 } 58 59 protected: 60 /** 61 * @brief oem specific initialization can be done under init function. 62 * if platform specific initialization is needed then 63 * a derived class instance with its own init function to override the 64 * default init() method can be added. 65 */ 66 67 virtual void init() 68 { 69 // initialize the button io fd from the buttonConfig 70 // which has fd stored when configGroupGpio is called 71 for (auto gpioCfg : config.gpios) 72 { 73 char buf; 74 int fd = gpioCfg.fd; 75 76 int ret = ::read(fd, &buf, sizeof(buf)); 77 if (ret < 0) 78 { 79 phosphor::logging::log<phosphor::logging::level::ERR>( 80 (getFormFactorType() + " : read error!").c_str()); 81 } 82 83 ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI, 84 callbackHandler, this); 85 if (ret < 0) 86 { 87 phosphor::logging::log<phosphor::logging::level::ERR>( 88 (getFormFactorType() + " : failed to add to event loop") 89 .c_str()); 90 ::closeGpio(fd); 91 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: 92 IOError(); 93 } 94 } 95 } 96 /** 97 * @brief similar to init() oem specific deinitialization can be done under 98 * deInit function. if platform specific deinitialization is needed then a 99 * derived class instance with its own init function to override the default 100 * deinit() method can be added. 101 */ 102 virtual void deInit() 103 { 104 for (auto gpioCfg : config.gpios) 105 { 106 ::closeGpio(gpioCfg.fd); 107 } 108 } 109 110 sdbusplus::bus_t& bus; 111 EventPtr& event; 112 buttonConfig config; 113 sd_event_io_handler_t callbackHandler; 114 }; 115