#pragma once #include "button_config.hpp" #include "common.hpp" #include "xyz/openbmc_project/Chassis/Common/error.hpp" #include <phosphor-logging/elog-errors.hpp> // This is the base class for all the button interface types // class ButtonIface { public: ButtonIface(sdbusplus::bus_t& bus, EventPtr& event, ButtonConfig& buttonCfg, sd_event_io_handler_t handler = ButtonIface::EventHandler) : bus(bus), event(event), config(buttonCfg), callbackHandler(handler) { int ret = -1; std::string configType; // config group gpio or cpld based on the defs read from the json file if (buttonCfg.type == ConfigType::gpio) { configType = "GPIO"; ret = configGroupGpio(config); } else if (buttonCfg.type == ConfigType::cpld) { configType = "CPLD"; ret = configCpld(config); } if (ret < 0) { phosphor::logging::log<phosphor::logging::level::ERR>( (getFormFactorType() + " : failed to config " + configType) .c_str()); throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: IOError(); } } virtual ~ButtonIface() {} /** * @brief This method is called from sd-event provided callback function * callbackHandler if platform specific event handling is needed then a * derived class instance with its specific evend handling logic along with * init() function can be created to override the default event handling. */ virtual void handleEvent(sd_event_source* es, int fd, uint32_t revents) = 0; static int EventHandler(sd_event_source* es, int fd, uint32_t revents, void* userdata) { if (userdata) { ButtonIface* buttonIface = static_cast<ButtonIface*>(userdata); buttonIface->handleEvent(es, fd, revents); } return 0; } std::string getFormFactorType() const { return config.formFactorName; } protected: /** * @brief oem specific initialization can be done under init function. * if platform specific initialization is needed then * a derived class instance with its own init function to override the * default init() method can be added. */ virtual void init() { // initialize the button io fd from the ButtonConfig // which has fd stored when configGroupGpio or configCpld is called for (auto fd : config.fds) { char buf; int ret = ::read(fd, &buf, sizeof(buf)); if (ret < 0) { phosphor::logging::log<phosphor::logging::level::ERR>( (getFormFactorType() + " : read error!").c_str()); } ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI, callbackHandler, this); if (ret < 0) { phosphor::logging::log<phosphor::logging::level::ERR>( (getFormFactorType() + " : failed to add to event loop") .c_str()); if (fd > 0) { ::close(fd); } throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error:: IOError(); } } } /** * @brief similar to init() oem specific deinitialization can be done under * deInit function. if platform specific deinitialization is needed then a * derived class instance with its own init function to override the default * deinit() method can be added. */ virtual void deInit() { for (auto fd : config.fds) { if (fd > 0) { ::close(fd); } } } sdbusplus::bus_t& bus; EventPtr& event; ButtonConfig config; sd_event_io_handler_t callbackHandler; };