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