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         }
54 
55         return 0;
56     }
57 
58     std::string getFormFactorType() const
59     {
60         return config.formFactorName;
61     }
62 
63   protected:
64     /**
65      * @brief oem specific initialization can be done under init function.
66      * if platform specific initialization is needed then
67      * a derived class instance with its own init function to override the
68      * default init() method can be added.
69      */
70 
71     virtual void init()
72     {
73 
74         // initialize the button io fd from the buttonConfig
75         // which has fd stored when configGroupGpio is called
76         for (auto gpioCfg : config.gpios)
77         {
78             char buf;
79             int fd = gpioCfg.fd;
80 
81             int ret = ::read(fd, &buf, sizeof(buf));
82             if (ret < 0)
83             {
84                 phosphor::logging::log<phosphor::logging::level::ERR>(
85                     (getFormFactorType() + " : read error!").c_str());
86             }
87 
88             ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI,
89                                   callbackHandler, this);
90             if (ret < 0)
91             {
92                 phosphor::logging::log<phosphor::logging::level::ERR>(
93                     (getFormFactorType() + " : failed to add to event loop")
94                         .c_str());
95                 ::closeGpio(fd);
96                 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
97                     IOError();
98             }
99         }
100     }
101     /**
102      * @brief similar to init() oem specific deinitialization can be done under
103      * deInit function. if platform specific deinitialization is needed then a
104      * derived class instance with its own init function to override the default
105      * deinit() method can be added.
106      */
107     virtual void deInit()
108     {
109         for (auto gpioCfg : config.gpios)
110         {
111             ::closeGpio(gpioCfg.fd);
112         }
113     }
114 
115     buttonConfig config;
116     sdbusplus::bus::bus& bus;
117     EventPtr& event;
118     sd_event_io_handler_t callbackHandler;
119 };
120