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