xref: /openbmc/phosphor-buttons/src/main.cpp (revision 31ce375e7e71ff6b3da460dc63c1ab4f16cf4df6)
1a9d39e30SKuiying Wang /*
2a9d39e30SKuiying Wang // Copyright (c) 2018 Intel Corporation
3a9d39e30SKuiying Wang //
4a9d39e30SKuiying Wang // Licensed under the Apache License, Version 2.0 (the "License");
5a9d39e30SKuiying Wang // you may not use this file except in compliance with the License.
6a9d39e30SKuiying Wang // You may obtain a copy of the License at
7a9d39e30SKuiying Wang //
8a9d39e30SKuiying Wang //      http://www.apache.org/licenses/LICENSE-2.0
9a9d39e30SKuiying Wang //
10a9d39e30SKuiying Wang // Unless required by applicable law or agreed to in writing, software
11a9d39e30SKuiying Wang // distributed under the License is distributed on an "AS IS" BASIS,
12a9d39e30SKuiying Wang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a9d39e30SKuiying Wang // See the License for the specific language governing permissions and
14a9d39e30SKuiying Wang // limitations under the License.
15a9d39e30SKuiying Wang */
16a9d39e30SKuiying Wang 
17ccd7db05SDelphine CC Chiu #include "button_config.hpp"
18a1af329fSNaveen Moses #include "button_factory.hpp"
19a9d39e30SKuiying Wang 
20dd5495cfSNaveen Moses #include <nlohmann/json.hpp>
21a1af329fSNaveen Moses #include <phosphor-logging/elog-errors.hpp>
22a6d4e65dSNaveen Moses #include <phosphor-logging/lg2.hpp>
235b98f4dbSGeorge Liu 
245b98f4dbSGeorge Liu #include <fstream>
25dd5495cfSNaveen Moses 
main(void)2694afa4baSGeorge Liu int main(void)
27a9d39e30SKuiying Wang {
28ccd7db05SDelphine CC Chiu     nlohmann::json gpioDefs;
29ccd7db05SDelphine CC Chiu     nlohmann::json cpldDefs;
30ccd7db05SDelphine CC Chiu 
31a9d39e30SKuiying Wang     int ret = 0;
32a9d39e30SKuiying Wang 
33a6d4e65dSNaveen Moses     lg2::info("Start Phosphor buttons service...");
34a9d39e30SKuiying Wang 
35a9d39e30SKuiying Wang     sd_event* event = nullptr;
36a9d39e30SKuiying Wang     ret = sd_event_default(&event);
37a9d39e30SKuiying Wang     if (ret < 0)
38a9d39e30SKuiying Wang     {
39a6d4e65dSNaveen Moses         lg2::error("Error creating a default sd_event handler");
40a9d39e30SKuiying Wang         return ret;
41a9d39e30SKuiying Wang     }
42a9d39e30SKuiying Wang     EventPtr eventP{event};
43a9d39e30SKuiying Wang     event = nullptr;
44a9d39e30SKuiying Wang 
459a529a69SPatrick Williams     sdbusplus::bus_t bus = sdbusplus::bus::new_default();
469a529a69SPatrick Williams     sdbusplus::server::manager_t objManager{
47a9d39e30SKuiying Wang         bus, "/xyz/openbmc_project/Chassis/Buttons"};
48a9d39e30SKuiying Wang 
49a9d39e30SKuiying Wang     bus.request_name("xyz.openbmc_project.Chassis.Buttons");
50a1af329fSNaveen Moses     std::vector<std::unique_ptr<ButtonIface>> buttonInterfaces;
51a9d39e30SKuiying Wang 
52dd5495cfSNaveen Moses     std::ifstream gpios{gpioDefFile};
53ccd7db05SDelphine CC Chiu     auto configDefJson = nlohmann::json::parse(gpios, nullptr, true);
54ccd7db05SDelphine CC Chiu     gpioDefs = configDefJson["gpio_definitions"];
55ccd7db05SDelphine CC Chiu     cpldDefs = configDefJson["cpld_definitions"];
56ccd7db05SDelphine CC Chiu 
57ccd7db05SDelphine CC Chiu     // load cpld config from gpio defs json file and create button interface
58ccd7db05SDelphine CC Chiu     for (const auto& cpldConfig : cpldDefs)
59ccd7db05SDelphine CC Chiu     {
60ccd7db05SDelphine CC Chiu         std::string formFactorName = cpldConfig["name"];
61ccd7db05SDelphine CC Chiu 
62ccd7db05SDelphine CC Chiu         ButtonConfig buttonCfg;
63ccd7db05SDelphine CC Chiu         buttonCfg.type = ConfigType::cpld;
64ccd7db05SDelphine CC Chiu         buttonCfg.formFactorName = formFactorName;
65ccd7db05SDelphine CC Chiu         buttonCfg.extraJsonInfo = cpldConfig;
66ccd7db05SDelphine CC Chiu 
67ccd7db05SDelphine CC Chiu         CpldInfo cpldCfg;
68ccd7db05SDelphine CC Chiu         cpldCfg.registerName = cpldConfig["register_name"];
69ccd7db05SDelphine CC Chiu 
70ccd7db05SDelphine CC Chiu         cpldCfg.i2cAddress = cpldConfig["i2c_address"].get<int>();
71ccd7db05SDelphine CC Chiu         cpldCfg.i2cBus = cpldConfig["i2c_bus"].get<int>();
72ccd7db05SDelphine CC Chiu         buttonCfg.cpld = cpldCfg;
73ccd7db05SDelphine CC Chiu 
74ccd7db05SDelphine CC Chiu         auto tempButtonIf = ButtonFactory::instance().createInstance(
75ccd7db05SDelphine CC Chiu             formFactorName, bus, eventP, buttonCfg);
76ccd7db05SDelphine CC Chiu         if (tempButtonIf)
77ccd7db05SDelphine CC Chiu         {
78ccd7db05SDelphine CC Chiu             buttonInterfaces.emplace_back(std::move(tempButtonIf));
79ccd7db05SDelphine CC Chiu         }
80ccd7db05SDelphine CC Chiu     }
81dd5495cfSNaveen Moses 
82dd5495cfSNaveen Moses     // load gpio config from gpio defs json file and create button interface
83dd5495cfSNaveen Moses     // objects based on the button form factor type
84dd5495cfSNaveen Moses 
85eea8a4a5SNaveen Moses     for (const auto& gpioConfig : gpioDefs)
868605bdffSMatt Spinler     {
87eea8a4a5SNaveen Moses         std::string formFactorName = gpioConfig["name"];
88ccd7db05SDelphine CC Chiu         ButtonConfig buttonCfg;
89eea8a4a5SNaveen Moses         buttonCfg.formFactorName = formFactorName;
903bd1cfcbSNaveen Moses         buttonCfg.extraJsonInfo = gpioConfig;
91ccd7db05SDelphine CC Chiu         buttonCfg.type = ConfigType::gpio;
92dd5495cfSNaveen Moses 
93*010035eeSManojkiran Eda         /* The following code checks if the gpio config read
94eea8a4a5SNaveen Moses         from json file is single gpio config or group gpio config,
95eea8a4a5SNaveen Moses         based on that further data is processed. */
96a6d4e65dSNaveen Moses         lg2::debug("Found button config : {FORM_FACTOR_NAME}",
97a6d4e65dSNaveen Moses                    "FORM_FACTOR_NAME", buttonCfg.formFactorName);
98eea8a4a5SNaveen Moses         if (gpioConfig.contains("group_gpio_config"))
99eea8a4a5SNaveen Moses         {
100eea8a4a5SNaveen Moses             const auto& groupGpio = gpioConfig["group_gpio_config"];
101eea8a4a5SNaveen Moses 
102eea8a4a5SNaveen Moses             for (const auto& config : groupGpio)
103eea8a4a5SNaveen Moses             {
104ccd7db05SDelphine CC Chiu                 GpioInfo gpioCfg;
105cb418b0dSJonico Eustaquio                 if (gpioConfig.contains("pin"))
106cb418b0dSJonico Eustaquio                 {
107cb418b0dSJonico Eustaquio                     // When "pin" key is used, parse as alphanumeric
108cb418b0dSJonico Eustaquio                     gpioCfg.number = getGpioNum(gpioConfig.at("pin"));
109cb418b0dSJonico Eustaquio                 }
110cb418b0dSJonico Eustaquio                 else
111cb418b0dSJonico Eustaquio                 {
112cb418b0dSJonico Eustaquio                     // Without "pin", "num" is assumed and parsed as an integer
113cb418b0dSJonico Eustaquio                     gpioCfg.number = gpioConfig.at("num").get<uint32_t>();
114cb418b0dSJonico Eustaquio                 }
115eea8a4a5SNaveen Moses                 gpioCfg.direction = config["direction"];
116d219fa3cSNaveen Moses                 gpioCfg.name = config["name"];
117d219fa3cSNaveen Moses                 gpioCfg.polarity = (config["polarity"] == "active_high")
118d219fa3cSNaveen Moses                                        ? GpioPolarity::activeHigh
119d219fa3cSNaveen Moses                                        : GpioPolarity::activeLow;
120eea8a4a5SNaveen Moses                 buttonCfg.gpios.push_back(gpioCfg);
121eea8a4a5SNaveen Moses             }
122eea8a4a5SNaveen Moses         }
123eea8a4a5SNaveen Moses         else
124dd5495cfSNaveen Moses         {
125ccd7db05SDelphine CC Chiu             GpioInfo gpioCfg;
126cb418b0dSJonico Eustaquio             if (gpioConfig.contains("pin"))
127cb418b0dSJonico Eustaquio             {
128cb418b0dSJonico Eustaquio                 // When "pin" key is used, parse as alphanumeric
129cb418b0dSJonico Eustaquio                 gpioCfg.number = getGpioNum(gpioConfig.at("pin"));
130cb418b0dSJonico Eustaquio             }
131cb418b0dSJonico Eustaquio             else
132cb418b0dSJonico Eustaquio             {
133cb418b0dSJonico Eustaquio                 // Without "pin", "num" is assumed and parsed as an integer
134cb418b0dSJonico Eustaquio                 gpioCfg.number = gpioConfig.at("num").get<uint32_t>();
135cb418b0dSJonico Eustaquio             }
136dd5495cfSNaveen Moses             gpioCfg.direction = gpioConfig["direction"];
137dd5495cfSNaveen Moses             buttonCfg.gpios.push_back(gpioCfg);
138dd5495cfSNaveen Moses         }
139eea8a4a5SNaveen Moses         auto tempButtonIf = ButtonFactory::instance().createInstance(
140eea8a4a5SNaveen Moses             formFactorName, bus, eventP, buttonCfg);
141eea8a4a5SNaveen Moses         /* There are additional gpio configs present in some platforms
142eea8a4a5SNaveen Moses          that are not supported in phosphor-buttons.
143eea8a4a5SNaveen Moses         But they may be used by other applications. so skipping such configs
144eea8a4a5SNaveen Moses         if present in gpio_defs.json file*/
145eea8a4a5SNaveen Moses         if (tempButtonIf)
146eea8a4a5SNaveen Moses         {
147eea8a4a5SNaveen Moses             buttonInterfaces.emplace_back(std::move(tempButtonIf));
148eea8a4a5SNaveen Moses         }
1498605bdffSMatt Spinler     }
150a9d39e30SKuiying Wang 
151a9d39e30SKuiying Wang     try
152a9d39e30SKuiying Wang     {
153a9d39e30SKuiying Wang         bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL);
154a9d39e30SKuiying Wang         ret = sd_event_loop(eventP.get());
155a9d39e30SKuiying Wang         if (ret < 0)
156a9d39e30SKuiying Wang         {
157a6d4e65dSNaveen Moses             lg2::error("Error occurred during the sd_event_loop : {RESULT}",
158a6d4e65dSNaveen Moses                        "RESULT", ret);
159a9d39e30SKuiying Wang         }
160a9d39e30SKuiying Wang     }
1616d724ce8SPatrick Williams     catch (const std::exception& e)
162a9d39e30SKuiying Wang     {
163a9d39e30SKuiying Wang         phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
164a9d39e30SKuiying Wang         ret = -1;
165a9d39e30SKuiying Wang     }
166a9d39e30SKuiying Wang     return ret;
167a9d39e30SKuiying Wang }
168