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