blob: b3a98cc552566f661b892f711bcd978719043b3a [file] [log] [blame]
Naveen Mosesa1af3292021-12-15 11:47:01 +05301#pragma once
2
Delphine CC Chiuccd7db02023-02-09 14:48:53 +08003#include "button_config.hpp"
Naveen Mosesa1af3292021-12-15 11:47:01 +05304#include "common.hpp"
Naveen Mosesa1af3292021-12-15 11:47:01 +05305#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//
10class ButtonIface
11{
Naveen Mosesa1af3292021-12-15 11:47:01 +053012 public:
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080013 ButtonIface(sdbusplus::bus_t& bus, EventPtr& event, ButtonConfig& buttonCfg,
Naveen Mosesa1af3292021-12-15 11:47:01 +053014 sd_event_io_handler_t handler = ButtonIface::EventHandler) :
15 bus(bus),
16 event(event), config(buttonCfg), callbackHandler(handler)
17 {
18 int ret = -1;
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080019 std::string configType;
Naveen Mosesa1af3292021-12-15 11:47:01 +053020
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080021 // 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 }
Naveen Mosesa1af3292021-12-15 11:47:01 +053032
33 if (ret < 0)
34 {
35 phosphor::logging::log<phosphor::logging::level::ERR>(
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080036 (getFormFactorType() + " : failed to config " + configType)
37 .c_str());
Naveen Mosesa1af3292021-12-15 11:47:01 +053038 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
39 IOError();
40 }
41 }
Patrick Williams0d038f52023-05-10 07:50:40 -050042 virtual ~ButtonIface() {}
Naveen Mosesa1af3292021-12-15 11:47:01 +053043
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 {
Naveen Mosesa1af3292021-12-15 11:47:01 +053057 ButtonIface* buttonIface = static_cast<ButtonIface*>(userdata);
58 buttonIface->handleEvent(es, fd, revents);
Naveen Mosesa1af3292021-12-15 11:47:01 +053059 }
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053060
61 return 0;
Naveen Mosesa1af3292021-12-15 11:47:01 +053062 }
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 {
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080079 // 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)
Naveen Mosesa1af3292021-12-15 11:47:01 +053082 {
83 char buf;
Naveen Mosesa1af3292021-12-15 11:47:01 +053084
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());
Delphine CC Chiuccd7db02023-02-09 14:48:53 +080099 if (fd > 0)
100 {
101 ::close(fd);
102 }
Naveen Mosesa1af3292021-12-15 11:47:01 +0530103 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 {
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800116 for (auto fd : config.fds)
Naveen Mosesa1af3292021-12-15 11:47:01 +0530117 {
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800118 if (fd > 0)
119 {
120 ::close(fd);
121 }
Naveen Mosesa1af3292021-12-15 11:47:01 +0530122 }
123 }
124
Patrick Williams9a529a62022-07-22 19:26:54 -0500125 sdbusplus::bus_t& bus;
Naveen Mosesa1af3292021-12-15 11:47:01 +0530126 EventPtr& event;
Delphine CC Chiuccd7db02023-02-09 14:48:53 +0800127 ButtonConfig config;
Naveen Mosesa1af3292021-12-15 11:47:01 +0530128 sd_event_io_handler_t callbackHandler;
129};