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