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