1 #pragma once 2 3 #include "button_config.hpp" 4 #include "button_interface.hpp" 5 #include "config.hpp" 6 7 #include <phosphor-logging/elog-errors.hpp> 8 9 #include <unordered_map> 10 11 using buttonIfCreatorMethod = std::function<std::unique_ptr<ButtonIface>( 12 sdbusplus::bus_t& bus, EventPtr& event, ButtonConfig& buttonCfg)>; 13 14 /** 15 * @brief This is abstract factory for the creating phosphor buttons objects 16 * based on the button / formfactor type given. 17 */ 18 19 class ButtonFactory 20 { 21 public: instance()22 static ButtonFactory& instance() 23 { 24 static ButtonFactory buttonFactoryObj; 25 return buttonFactoryObj; 26 } 27 28 /** 29 * @brief this method creates a key and value pair element 30 * for the given button interface where key is the form factor 31 * name and the value is lambda method to return 32 * the instance of the button interface. 33 * This key value pair is stored in the Map buttonIfaceRegistry. 34 */ 35 36 template <typename T> addToRegistry()37 void addToRegistry() 38 { 39 buttonIfaceRegistry[T::getFormFactorName()] = 40 [](sdbusplus::bus_t& bus, EventPtr& event, 41 ButtonConfig& buttonCfg) { 42 return std::make_unique<T>(bus, T::getDbusObjectPath().c_str(), 43 event, buttonCfg); 44 }; 45 } 46 47 template <typename T> addToRegistry(size_t index)48 void addToRegistry(size_t index) 49 { 50 auto indexStr = std::to_string(index); 51 buttonIfaceRegistry[T::getFormFactorName() + indexStr] = 52 [=](sdbusplus::bus_t& bus, EventPtr& event, 53 ButtonConfig& buttonCfg) { 54 return std::make_unique<T>( 55 bus, (T::getDbusObjectPath() + indexStr).c_str(), event, 56 buttonCfg); 57 }; 58 } 59 60 /** 61 * @brief this method returns the button interface object 62 * corresponding to the button formfactor name provided 63 */ createInstance(const std::string & name,sdbusplus::bus_t & bus,EventPtr & event,ButtonConfig & buttonCfg)64 std::unique_ptr<ButtonIface> createInstance( 65 const std::string& name, sdbusplus::bus_t& bus, EventPtr& event, 66 ButtonConfig& buttonCfg) 67 { 68 // find matching name in the registry and call factory method. 69 auto objectIter = buttonIfaceRegistry.find(name); 70 if (objectIter != buttonIfaceRegistry.end()) 71 { 72 return objectIter->second(bus, event, buttonCfg); 73 } 74 else 75 { 76 return nullptr; 77 } 78 } 79 80 private: 81 // This map is the registry for keeping supported button interface types. 82 std::unordered_map<std::string, buttonIfCreatorMethod> buttonIfaceRegistry; 83 }; 84 85 template <class T> 86 class ButtonIFRegister 87 { 88 public: ButtonIFRegister()89 ButtonIFRegister() 90 { 91 // register the class factory function 92 ButtonFactory::instance().addToRegistry<T>(); 93 } 94 ButtonIFRegister(size_t count)95 explicit ButtonIFRegister(size_t count) 96 { 97 // The JSON power button definitions only have an instance in 98 // their name if there is more than 1 chassis. 99 if (instances.size() > 1) 100 { 101 // register the class factory function 102 // The index, 'countIter', starts at 1 and increments, 103 // representing slot_1 through slot_N. 104 for (size_t countIter = 1; countIter <= count; countIter++) 105 { 106 ButtonFactory::instance().addToRegistry<T>(countIter); 107 } 108 } 109 else 110 { 111 ButtonFactory::instance().addToRegistry<T>(); 112 } 113 } 114 }; 115