Add abstract factory to create button iface objects
A abstract factory class is implemented to return
the instance of button interface class based on the
button iface formfactor name provided as
parameter to the abstract factory createInstance
method.
Signed-off-by: Naveen Moses <naveen.mosess@hcl.com>
Change-Id: Ia791a2b6f52d09dd87da0e50a709fc72ac9d1bd7
diff --git a/inc/button_factory.hpp b/inc/button_factory.hpp
new file mode 100644
index 0000000..81c8e47
--- /dev/null
+++ b/inc/button_factory.hpp
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "button_interface.hpp"
+#include "gpio.hpp"
+
+#include <phosphor-logging/elog-errors.hpp>
+#include <unordered_map>
+
+using buttonIfCreatorMethod = std::function<std::unique_ptr<ButtonIface>(
+ sdbusplus::bus::bus& bus, EventPtr& event, buttonConfig& buttonCfg)>;
+
+/**
+ * @brief This is abstract factory for the creating phosphor buttons objects
+ * based on the button / formfactor type given.
+ */
+
+class ButtonFactory
+{
+
+ public:
+ static ButtonFactory& instance()
+ {
+ static ButtonFactory buttonFactoryObj;
+ return buttonFactoryObj;
+ }
+
+ /**
+ * @brief this method creates a key and value pair element
+ * for the given button interface where key is the form factor
+ * name and the value is lambda method to return
+ * the instance of the button interface.
+ * This key value pair is stored in the Map buttonIfaceRegistry.
+ */
+
+ template <typename T>
+ void addToRegistry()
+ {
+
+ buttonIfaceRegistry[std::string(T::getFormFactorName())] =
+ [](sdbusplus::bus::bus& bus, EventPtr& event,
+ buttonConfig& buttonCfg) {
+ return std::make_unique<T>(bus, T::getDbusObjectPath(), event,
+ buttonCfg);
+ };
+ }
+ /**
+ * @brief this method returns the button interface object
+ * corresponding to the button formfactor name provided
+ */
+ std::unique_ptr<ButtonIface> createInstance(std::string name,
+ sdbusplus::bus::bus& bus,
+ EventPtr& event,
+ buttonConfig& buttonCfg)
+ {
+
+ // find matching name in the registry and call factory method.
+
+ return buttonIfaceRegistry.at(name)(bus, event, buttonCfg);
+ }
+
+ private:
+ // This map is the registry for keeping supported button interface types.
+ std::unordered_map<std::string, buttonIfCreatorMethod> buttonIfaceRegistry;
+};
+
+template <class T>
+class ButtonIFRegister
+{
+ public:
+ ButtonIFRegister()
+ {
+ // register the class factory function
+ ButtonFactory::instance().addToRegistry<T>();
+ }
+};
\ No newline at end of file
diff --git a/inc/button_interface.hpp b/inc/button_interface.hpp
new file mode 100644
index 0000000..8648797
--- /dev/null
+++ b/inc/button_interface.hpp
@@ -0,0 +1,118 @@
+#pragma once
+
+#include "common.hpp"
+#include "gpio.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::bus& bus, EventPtr& event,
+ buttonConfig& buttonCfg,
+ sd_event_io_handler_t handler = ButtonIface::EventHandler) :
+ bus(bus),
+ event(event), config(buttonCfg), callbackHandler(handler)
+ {
+ int ret = -1;
+
+ // config group gpio based on the gpio defs read from the json file
+ ret = configGroupGpio(config);
+
+ if (ret < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ (getFormFactorType() + " : failed to config GPIO").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 is called
+ for (auto gpioCfg : config.gpios)
+ {
+ char buf;
+ int fd = gpioCfg.fd;
+
+ 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());
+ ::closeGpio(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 gpioCfg : config.gpios)
+ {
+ ::closeGpio(gpioCfg.fd);
+ }
+ }
+
+ buttonConfig config;
+ sdbusplus::bus::bus& bus;
+ EventPtr& event;
+ sd_event_io_handler_t callbackHandler;
+};
diff --git a/inc/gpio.hpp b/inc/gpio.hpp
index ba4b8ad..ebaf3cf 100644
--- a/inc/gpio.hpp
+++ b/inc/gpio.hpp
@@ -42,14 +42,14 @@
* @return int returns 0 on successful config of all gpios
*/
-int configGroupGpio(sdbusplus::bus::bus& bus, buttonConfig& buttonCfg);
+int configGroupGpio(buttonConfig& buttonCfg);
/**
* @brief configures and initializes the single gpio
* @return int returns 0 on successful config of all gpios
*/
-int configGpio(sdbusplus::bus::bus& bus, gpioInfo& gpioConfig);
+int configGpio(gpioInfo& gpioConfig);
uint32_t getGpioNum(const std::string& gpioPin);
void closeGpio(int fd);
diff --git a/inc/id_button.hpp b/inc/id_button.hpp
index cb32125..c58d264 100644
--- a/inc/id_button.hpp
+++ b/inc/id_button.hpp
@@ -15,6 +15,8 @@
*/
#pragma once
+#include "button_factory.hpp"
+#include "button_interface.hpp"
#include "common.hpp"
#include "gpio.hpp"
#include "xyz/openbmc_project/Chassis/Buttons/ID/server.hpp"
@@ -24,132 +26,40 @@
#include <phosphor-logging/elog-errors.hpp>
-const static constexpr char* ID_BUTTON = "ID_BTN";
+static constexpr std::string_view ID_BUTTON = "ID_BTN";
-struct IDButton
- : sdbusplus::server::object::object<
- sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::ID>
+class IDButton
+ : public sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::ID>,
+ public ButtonIface
{
+ public:
IDButton(sdbusplus::bus::bus& bus, const char* path, EventPtr& event,
- buttonConfig& buttonCfg,
- sd_event_io_handler_t handler = IDButton::EventHandler) :
+ buttonConfig& buttonCfg) :
sdbusplus::server::object::object<
sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::ID>(
bus, path),
- fd(-1), buttonIFConfig(buttonCfg), bus(bus), event(event),
- callbackHandler(handler)
+ ButtonIface(bus, event, buttonCfg)
{
-
- int ret = -1;
-
- // config group gpio based on the gpio defs read from the json file
- ret = configGroupGpio(bus, buttonIFConfig);
-
- if (ret < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ID_BUTTON: failed to config GPIO");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
- // initialize the button io fd from the buttonConfig
- // which has fd stored when configGroupGpio is called
- fd = buttonIFConfig.gpios[0].fd;
-
- char buf;
- ::read(fd, &buf, sizeof(buf));
-
- ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI,
- callbackHandler, this);
- if (ret < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ID_BUTTON: failed to add to event loop");
- ::closeGpio(fd);
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
+ init();
}
~IDButton()
{
- ::closeGpio(fd);
+ deInit();
}
void simPress() override;
- static const std::string getGpioName()
+ static constexpr std::string_view getFormFactorName()
{
return ID_BUTTON;
}
-
- static int EventHandler(sd_event_source* es, int fd, uint32_t revents,
- void* userdata)
+ static constexpr const char* getDbusObjectPath()
{
-
- int n = -1;
- char buf = '0';
-
- if (!userdata)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ID_BUTTON: userdata null!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- IDButton* idButton = static_cast<IDButton*>(userdata);
-
- if (!idButton)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ID_BUTTON: null pointer!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- n = ::lseek(fd, 0, SEEK_SET);
-
- if (n < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ID_BUTTON: lseek error!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- n = ::read(fd, &buf, sizeof(buf));
- if (n < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ID_BUTTON: read error!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- if (buf == '0')
- {
- phosphor::logging::log<phosphor::logging::level::DEBUG>(
- "ID_BUTTON: pressed");
- // emit pressed signal
- idButton->pressed();
- }
- else
- {
- phosphor::logging::log<phosphor::logging::level::DEBUG>(
- "ID_BUTTON: released");
- // released
- idButton->released();
- }
-
- return 0;
+ return ID_DBUS_OBJECT_NAME;
}
- private:
- int fd;
- buttonConfig buttonIFConfig;
- sdbusplus::bus::bus& bus;
- EventPtr& event;
- sd_event_io_handler_t callbackHandler;
+ void handleEvent(sd_event_source* es, int fd, uint32_t revents) override;
};
diff --git a/inc/power_button.hpp b/inc/power_button.hpp
index 283b149..bef2662 100644
--- a/inc/power_button.hpp
+++ b/inc/power_button.hpp
@@ -15,6 +15,8 @@
*/
#pragma once
+#include "button_factory.hpp"
+#include "button_interface.hpp"
#include "common.hpp"
#include "gpio.hpp"
#include "xyz/openbmc_project/Chassis/Buttons/Power/server.hpp"
@@ -25,159 +27,45 @@
#include <chrono>
#include <phosphor-logging/elog-errors.hpp>
-const static constexpr char* POWER_BUTTON = "POWER_BUTTON";
+static constexpr std::string_view POWER_BUTTON = "POWER_BUTTON";
-struct PowerButton
- : sdbusplus::server::object::object<
- sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Power>
+class PowerButton
+ : public sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Power>,
+ public ButtonIface
{
-
+ public:
PowerButton(sdbusplus::bus::bus& bus, const char* path, EventPtr& event,
- buttonConfig& buttonCfg,
- sd_event_io_handler_t handler = PowerButton::EventHandler) :
+ buttonConfig& buttonCfg) :
sdbusplus::server::object::object<
sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Power>(
bus, path),
- fd(-1), buttonIFConfig(buttonCfg), bus(bus), event(event),
- callbackHandler(handler)
+ ButtonIface(bus, event, buttonCfg)
{
-
- int ret = -1;
-
- // config group gpio based on the gpio defs read from the json file
- ret = configGroupGpio(bus, buttonIFConfig);
-
- if (ret < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "POWER_BUTTON: failed to config GPIO");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- // initialize the button io fd from the buttonConfig
- // which has fd stored when configGroupGpio is called
- fd = buttonIFConfig.gpios[0].fd;
-
- char buf;
- ::read(fd, &buf, sizeof(buf));
-
- ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI,
- callbackHandler, this);
- if (ret < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "POWER_BUTTON: failed to add to event loop");
- ::closeGpio(fd);
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
+ init();
}
~PowerButton()
{
- ::closeGpio(fd);
+
+ deInit();
}
void simPress() override;
void simLongPress() override;
- static const std::string getGpioName()
+ static constexpr std::string_view getFormFactorName()
{
return POWER_BUTTON;
}
-
- void updatePressedTime()
+ static constexpr const char* getDbusObjectPath()
{
- pressedTime = std::chrono::steady_clock::now();
+ return POWER_DBUS_OBJECT_NAME;
}
+ void updatePressedTime();
+ auto getPressTime() const;
+ void handleEvent(sd_event_source* es, int fd, uint32_t revents) override;
- auto getPressTime() const
- {
- return pressedTime;
- }
-
- static int EventHandler(sd_event_source* es, int fd, uint32_t revents,
- void* userdata)
- {
-
- int n = -1;
- char buf = '0';
-
- if (!userdata)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "POWER_BUTTON: userdata null!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- PowerButton* powerButton = static_cast<PowerButton*>(userdata);
-
- if (!powerButton)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "POWER_BUTTON: null pointer!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- n = ::lseek(fd, 0, SEEK_SET);
-
- if (n < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "POWER_BUTTON: lseek error!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- n = ::read(fd, &buf, sizeof(buf));
- if (n < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "POWER_BUTTON: read error!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- if (buf == '0')
- {
- phosphor::logging::log<phosphor::logging::level::DEBUG>(
- "POWER_BUTTON: pressed");
-
- powerButton->updatePressedTime();
- // emit pressed signal
- powerButton->pressed();
- }
- else
- {
- phosphor::logging::log<phosphor::logging::level::DEBUG>(
- "POWER_BUTTON: released");
-
- auto now = std::chrono::steady_clock::now();
- auto d = std::chrono::duration_cast<std::chrono::milliseconds>(
- now - powerButton->getPressTime());
-
- if (d > std::chrono::milliseconds(LONG_PRESS_TIME_MS))
- {
- powerButton->pressedLong();
- }
- else
- {
- // released
- powerButton->released();
- }
- }
-
- return 0;
- }
-
- private:
- int fd;
- buttonConfig buttonIFConfig; // button iface io details
- sdbusplus::bus::bus& bus;
- EventPtr& event;
- sd_event_io_handler_t callbackHandler;
+ protected:
decltype(std::chrono::steady_clock::now()) pressedTime;
};
diff --git a/inc/reset_button.hpp b/inc/reset_button.hpp
index 478628b..8e15740 100644
--- a/inc/reset_button.hpp
+++ b/inc/reset_button.hpp
@@ -15,6 +15,8 @@
*/
#pragma once
+#include "button_factory.hpp"
+#include "button_interface.hpp"
#include "common.hpp"
#include "gpio.hpp"
#include "xyz/openbmc_project/Chassis/Buttons/Reset/server.hpp"
@@ -24,133 +26,40 @@
#include <phosphor-logging/elog-errors.hpp>
-const static constexpr char* RESET_BUTTON = "RESET_BUTTON";
+static constexpr std::string_view RESET_BUTTON = "RESET_BUTTON";
-struct ResetButton
- : sdbusplus::server::object::object<
- sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Reset>
+class ResetButton
+ : public sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Reset>,
+ public ButtonIface
{
-
+ public:
ResetButton(sdbusplus::bus::bus& bus, const char* path, EventPtr& event,
- buttonConfig& buttonCfg,
- sd_event_io_handler_t handler = ResetButton::EventHandler) :
+ buttonConfig& buttonCfg) :
sdbusplus::server::object::object<
sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Reset>(
bus, path),
- fd(-1), buttonIFConfig(buttonCfg), bus(bus), event(event),
- callbackHandler(handler)
+ ButtonIface(bus, event, buttonCfg)
{
-
- int ret = -1;
-
- // config group gpio based on the gpio defs read from the json file
- ret = configGroupGpio(bus, buttonIFConfig);
-
- if (ret < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "RESET_BUTTON: failed to config GPIO");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- // initialize the button io fd from the buttonConfig
- // which has fd stored when configGroupGpio is called
- fd = buttonIFConfig.gpios[0].fd;
-
- char buf;
- ::read(fd, &buf, sizeof(buf));
-
- ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI,
- callbackHandler, this);
- if (ret < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "RESET_BUTTON: failed to add to event loop");
- ::closeGpio(fd);
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
+ init();
}
~ResetButton()
{
- ::closeGpio(fd);
+ deInit();
}
void simPress() override;
- static const std::string getGpioName()
+ static constexpr std::string_view getFormFactorName()
{
return RESET_BUTTON;
}
- static int EventHandler(sd_event_source* es, int fd, uint32_t revents,
- void* userdata)
+ static constexpr const char* getDbusObjectPath()
{
-
- int n = -1;
- char buf = '0';
-
- if (!userdata)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "RESET_BUTTON: userdata null!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- ResetButton* resetButton = static_cast<ResetButton*>(userdata);
-
- if (!resetButton)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "RESET_BUTTON: null pointer!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- n = ::lseek(fd, 0, SEEK_SET);
-
- if (n < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "RESET_BUTTON: lseek error!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- n = ::read(fd, &buf, sizeof(buf));
- if (n < 0)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "RESET_BUTTON: read error!");
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
-
- if (buf == '0')
- {
- phosphor::logging::log<phosphor::logging::level::DEBUG>(
- "RESET_BUTTON: pressed");
- // emit pressed signal
- resetButton->pressed();
- }
- else
- {
- phosphor::logging::log<phosphor::logging::level::DEBUG>(
- "RESET_BUTTON: released");
- // released
- resetButton->released();
- }
-
- return 0;
+ return RESET_DBUS_OBJECT_NAME;
}
- private:
- int fd;
- buttonConfig buttonIFConfig; // button iface io details
- sdbusplus::bus::bus& bus;
- EventPtr& event;
- sd_event_io_handler_t callbackHandler;
+ void handleEvent(sd_event_source* es, int fd, uint32_t revents) override;
};
diff --git a/src/gpio.cpp b/src/gpio.cpp
index 0538800..1caae54 100644
--- a/src/gpio.cpp
+++ b/src/gpio.cpp
@@ -83,14 +83,14 @@
return getGpioBase() + offset;
}
-int configGroupGpio(sdbusplus::bus::bus& bus, buttonConfig& buttonIFConfig)
+int configGroupGpio(buttonConfig& buttonIFConfig)
{
int result = 0;
// iterate the list of gpios from the button interface config
// and initialize them
for (auto& gpioCfg : buttonIFConfig.gpios)
{
- result = configGpio(bus, gpioCfg);
+ result = configGpio(gpioCfg);
if (result < 0)
{
@@ -107,7 +107,7 @@
return result;
}
-int configGpio(sdbusplus::bus::bus& bus, gpioInfo& gpioConfig)
+int configGpio(gpioInfo& gpioConfig)
{
auto gpioNum = gpioConfig.number;
diff --git a/src/id_button.cpp b/src/id_button.cpp
index c543556..71e8539 100644
--- a/src/id_button.cpp
+++ b/src/id_button.cpp
@@ -16,7 +16,47 @@
#include "id_button.hpp"
+// add the button iface class to registry
+static ButtonIFRegister<IDButton> buttonRegister;
+
void IDButton::simPress()
{
pressed();
-}
\ No newline at end of file
+}
+
+void IDButton::handleEvent(sd_event_source* es, int fd, uint32_t revents)
+{
+ int n = -1;
+ char buf = '0';
+ n = ::lseek(fd, 0, SEEK_SET);
+
+ if (n < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ (getFormFactorType() + " : lseek error!").c_str());
+ return;
+ }
+
+ n = ::read(fd, &buf, sizeof(buf));
+ if (n < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ (getFormFactorType() + " : read error!").c_str());
+ return;
+ }
+
+ if (buf == '0')
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ (getFormFactorType() + " : pressed").c_str());
+ // emit pressed signal
+ pressed();
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ (getFormFactorType() + " : released").c_str());
+ // released
+ released();
+ }
+}
diff --git a/src/main.cpp b/src/main.cpp
index ca7fbaa..a99c603 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -14,14 +14,12 @@
// limitations under the License.
*/
+#include "button_factory.hpp"
#include "gpio.hpp"
-#include "id_button.hpp"
-#include "power_button.hpp"
-#include "reset_button.hpp"
#include <fstream>
#include <nlohmann/json.hpp>
-
+#include <phosphor-logging/elog-errors.hpp>
static constexpr auto gpioDefFile = "/etc/default/obmc/gpio/gpio_defs.json";
int main(int argc, char* argv[])
@@ -29,7 +27,7 @@
int ret = 0;
phosphor::logging::log<phosphor::logging::level::INFO>(
- "Start power button service...");
+ "Start Phosphor buttons service...");
sd_event* event = nullptr;
ret = sd_event_default(&event);
@@ -47,6 +45,8 @@
bus, "/xyz/openbmc_project/Chassis/Buttons"};
bus.request_name("xyz.openbmc_project.Chassis.Buttons");
+ //
+ std::vector<std::unique_ptr<ButtonIface>> buttonInterfaces;
std::ifstream gpios{gpioDefFile};
auto json = nlohmann::json::parse(gpios, nullptr, true);
@@ -54,9 +54,6 @@
// load gpio config from gpio defs json file and create button interface
// objects based on the button form factor type
- std::unique_ptr<PowerButton> pb;
- std::unique_ptr<ResetButton> rb;
- std::unique_ptr<IDButton> ib;
for (auto groupGpioConfig : gpioDefs)
{
@@ -72,23 +69,9 @@
buttonCfg.formFactorName = formFactorName;
buttonCfg.gpios.push_back(gpioCfg);
}
- if (buttonCfg.formFactorName == PowerButton::getGpioName())
- {
- pb = std::make_unique<PowerButton>(bus, POWER_DBUS_OBJECT_NAME,
- eventP, buttonCfg);
- }
- if (buttonCfg.formFactorName == ResetButton::getGpioName())
- {
- rb = std::make_unique<ResetButton>(bus, RESET_DBUS_OBJECT_NAME,
- eventP, buttonCfg);
- }
-
- if (buttonCfg.formFactorName == IDButton::getGpioName())
- {
- ib = std::make_unique<IDButton>(bus, ID_DBUS_OBJECT_NAME, eventP,
- buttonCfg);
- }
+ buttonInterfaces.emplace_back(ButtonFactory::instance().createInstance(
+ formFactorName, bus, eventP, buttonCfg));
}
try
diff --git a/src/power_button.cpp b/src/power_button.cpp
index feadeee..2e69154 100644
--- a/src/power_button.cpp
+++ b/src/power_button.cpp
@@ -16,6 +16,9 @@
#include "power_button.hpp"
+// add the button iface class to registry
+static ButtonIFRegister<PowerButton> buttonRegister;
+
void PowerButton::simPress()
{
pressed();
@@ -25,3 +28,66 @@
{
pressedLong();
}
+
+void PowerButton::updatePressedTime()
+{
+ pressedTime = std::chrono::steady_clock::now();
+}
+
+auto PowerButton::getPressTime() const
+{
+ return pressedTime;
+}
+
+void PowerButton::handleEvent(sd_event_source* es, int fd, uint32_t revents)
+{
+
+ int n = -1;
+ char buf = '0';
+
+ n = ::lseek(fd, 0, SEEK_SET);
+
+ if (n < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "POWER_BUTTON: lseek error!");
+ return;
+ }
+
+ n = ::read(fd, &buf, sizeof(buf));
+ if (n < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "POWER_BUTTON: read error!");
+ return;
+ }
+
+ if (buf == '0')
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "POWER_BUTTON: pressed");
+
+ updatePressedTime();
+ // emit pressed signal
+ pressed();
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "POWER_BUTTON: released");
+
+ auto now = std::chrono::steady_clock::now();
+ auto d = std::chrono::duration_cast<std::chrono::milliseconds>(
+ now - getPressTime());
+
+ if (d > std::chrono::milliseconds(LONG_PRESS_TIME_MS))
+ {
+ pressedLong();
+ }
+ else
+ {
+ // released
+ released();
+ }
+ }
+}
diff --git a/src/reset_button.cpp b/src/reset_button.cpp
index 31e01e1..c3e467e 100644
--- a/src/reset_button.cpp
+++ b/src/reset_button.cpp
@@ -18,7 +18,51 @@
#include "xyz/openbmc_project/Chassis/Buttons/Reset/server.hpp"
+// add the button iface class to registry
+static ButtonIFRegister<ResetButton> buttonRegister;
+
void ResetButton::simPress()
{
pressed();
}
+
+void ResetButton::handleEvent(sd_event_source* es, int fd, uint32_t revents)
+{
+ int n = -1;
+ char buf = '0';
+
+ n = ::lseek(fd, 0, SEEK_SET);
+
+ if (n < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "RESET_BUTTON: lseek error!");
+
+ return;
+ }
+
+ n = ::read(fd, &buf, sizeof(buf));
+ if (n < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "RESET_BUTTON: read error!");
+ return;
+ }
+
+ if (buf == '0')
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "RESET_BUTTON: pressed");
+ // emit pressed signal
+ pressed();
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "RESET_BUTTON: released");
+ // released
+ released();
+ }
+
+ return;
+}