diff --git a/src/GpioDbusManager.cpp b/dbus/dbusmanager.cpp similarity index 35% rename from src/GpioDbusManager.cpp rename to dbus/dbusmanager.cpp index 89e8ddbcc24a0c8f9ecf8777a7389564f2227bb9..374d52ea4ef585576e0615c8fd3dbdc22e751fcf 100644 --- a/src/GpioDbusManager.cpp +++ b/dbus/dbusmanager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Phytium Technology Co., Ltd. + * Copyright (c) 2024, Phytium Technology Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,121 +14,120 @@ * limitations under the License. */ -#include "config.h" +#include "dbus/dbusmanager.hpp" -#include "GpioDbusManager.hpp" - -#include #include #include #include GpioDbusManager::GpioDbusManager( - const GpioInfo& gpioInfo, + const GpioInfo& info, std::shared_ptr interface, const std::string& property, boost::asio::io_context& io, - const std::pair& target) : - Gpio(gpioInfo), + const std::pair& target) : + Gpio(info), currentState(Gpio::getCurrentGpioValue()), interface(interface), - property(property), fd(io), target(target) + _property(property), _fd(io), _timer(io), _target(target) { - try + if (!Gpio::getGpioInfo().direction) { - if (!Gpio::getGpioInfo().direction) + try { int gpioFd = line.event_get_fd(); if (gpioFd < 0) { - std::cerr << "Get Fd Error" << std::endl; - + std::cerr << "Get Fd Error\n"; return; } - - fd.assign(gpioFd); - - interface->register_property(property, currentState); - gpioEventLoop(); + _fd.assign(gpioFd); } - else + catch (...) { - interface->register_property( - property, currentState, [this](const int& req, int& old) { - try - { - Gpio::setCurrentGpioValue(req); - old = Gpio::getCurrentGpioValue(); - } - catch (...) - { - return false; - } - return true; - }); + std::cerr << "Unknown initialization error\n"; + return; } + + interface->register_property(_property, currentState); + gpioEventLoop(); } - catch (...) + else { - std::cerr << "GpioDbusManager Init Error" << std::endl; - - return; + interface->register_property(_property, currentState, + [this](const int& req, int& old) { + try + { + Gpio::setCurrentGpioValue(req); + old = Gpio::getCurrentGpioValue(); + return true; + } + catch (...) + { + /** + * Do not perform any other + * operations. + * */ + } + return false; + }); } } GpioDbusManager::~GpioDbusManager() { - fd.close(); + _fd.close(); + _timer.cancel(); } void GpioDbusManager::gpioEventLoop() { - fd.async_wait(boost::asio::posix::stream_descriptor::wait_read, - [this](const boost::system::error_code& ec) { - if (ec == boost::system::errc::bad_file_descriptor) - { - std::cerr << "Fd error" << std::endl; - - return; - } - - try - { - line.event_read(); - - /* If there is an effective time for configuring the - * GPIO level, continue to check once after the time - * has ended. */ - boost::this_thread::sleep( - boost::posix_time::milliseconds( - Gpio::getGpioInfo().delayTime)); - if (currentState == Gpio::getCurrentGpioValue()) - { - gpioEventLoop(); - - return; - } - - currentState = Gpio::getCurrentGpioValue(); - interface->set_property(property, currentState); - - /* If there are services that rely on execution. */ - if (target != std::pair{}) - { - if (target.first == BOTH || - target.first == currentState) - { - startUnit(target.second, currentState); - } - } - } - catch (...) - { - std::cerr << "GPIO Event Loop error" << std::endl; - } - - gpioEventLoop(); - }); + _fd.async_wait( + boost::asio::posix::stream_descriptor::wait_read, + [this](const boost::system::error_code& ec) { + if (ec == boost::system::errc::bad_file_descriptor) + { + std::cerr << "Fd error\n"; + return; + } + + line.event_read(); + + /** + * The delay of the input signal depends on the corresponding JSON + * configuration file. The purpose of this is to filter out some + * erroneous input signals. + * */ + _timer.expires_after( + std::chrono::milliseconds(Gpio::getGpioInfo().delayTime)); + _timer.async_wait([this](const boost::system::error_code& ec) { + if (ec == boost::asio::error::operation_aborted || + currentState == Gpio::getCurrentGpioValue()) + { + return; + } + + currentState = Gpio::getCurrentGpioValue(); + interface->set_property(_property, currentState); + + /** + * Whether to execute corresponding services for changes in + * input signals depends on whether the corresponding JSON file + * is configured. + * */ + if (_target != std::pair{}) + { + static const std::array state{"low", "high", + "both"}; + if (_target.first == state.back() || + _target.first == state[currentState]) + { + startUnit(_target.second, currentState); + } + } + }); + gpioEventLoop(); + }); } void startUnit(std::string target, const int status) @@ -148,8 +147,9 @@ void startUnit(std::string target, const int status) try { auto bus = sdbusplus::bus::new_default(); - auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_PATH, - SYSTEMD_INTERFACE, "StartUnit"); + auto method = bus.new_method_call( + "org.freedesktop.systemd1", "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", "StartUnit"); method.append(target); method.append("replace"); @@ -159,6 +159,6 @@ void startUnit(std::string target, const int status) } catch (const sdbusplus::exception::exception& e) { - std::cerr << "Dbus execution failed" << e.what() << std::endl; + std::cerr << e.what() << "\n"; } } diff --git a/include/GpioDbusManager.hpp b/dbus/dbusmanager.hpp similarity index 74% rename from include/GpioDbusManager.hpp rename to dbus/dbusmanager.hpp index 58961731914537cf882ffd4c395cd92e7b18f859..22d3314efc028285eb23426709c97cf54b5404f1 100644 --- a/include/GpioDbusManager.hpp +++ b/dbus/dbusmanager.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Phytium Technology Co., Ltd. + * Copyright (c) 2024, Phytium Technology Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,11 @@ */ #pragma once -#include "Gpio.hpp" + +#include "gpio.hpp" #include +#include #include #include #include @@ -26,9 +28,8 @@ #include /** - * @class GpioDbusManager - * @brief The class managed by gpio. - */ + * @brief Manage GPIO classes in a Dbus manner. + * */ class GpioDbusManager : public Gpio { public: @@ -48,35 +49,25 @@ class GpioDbusManager : public Gpio * @param[in] target - The target content required for GPIO * monitoring. */ - GpioDbusManager(const GpioInfo& gpioInfo, + GpioDbusManager(const GpioInfo& info, std::shared_ptr interface, const std::string& property, boost::asio::io_context& io, - const std::pair& target = - std::pair{}); - - /** @brief The destructor of GpioDbusManager. */ + const std::pair& target = + std::pair{}); ~GpioDbusManager(); /** @brief GPIO event function. */ void gpioEventLoop(); protected: - /** @brief Current GPIO status. */ int currentState; - - /** @brief Dbus interface. */ std::shared_ptr interface; private: - - /** @brief The registered dbus attribute name. */ - const std::string property; - - /** @brief Stream descriptor. */ - boost::asio::posix::stream_descriptor fd; - - /** @brief Target state and target system unit. */ - const std::pair target; + const std::string _property; + boost::asio::posix::stream_descriptor _fd; + boost::asio::steady_timer _timer; + const std::pair _target; }; /** diff --git a/gpio.cpp b/gpio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecd1d7da2631c48beb061dd09de6f221f081ab71 --- /dev/null +++ b/gpio.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024, Phytium Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gpio.hpp" + +#include + +#include +#include +#include + +Gpio::Gpio(const GpioInfo& info) : + line(gpiod::chip(std::to_string(info.chip), gpiod::chip::OPEN_BY_NUMBER) + .get_line(info.line)), + _info(info) +{ + try + { + line.request( + {_info.name, + _info.direction ? gpiod::line_request::DIRECTION_OUTPUT + : gpiod::line_request::EVENT_BOTH_EDGES, + _info.polarity ? gpiod::line_request::FLAG_ACTIVE_LOW : 0}, + _info.defaultValue); + } + catch (...) + { + std::cerr << _info.name << " Init Error\n"; + return; + } +} + +Gpio::~Gpio() +{ + line.release(); +} + +int Gpio::getCurrentGpioValue() const +{ + return line.get_value(); +} + +void Gpio::setCurrentGpioValue(int value) const +{ + line.set_value(value); +} + +const GpioInfo& Gpio::getGpioInfo() const +{ + return _info; +} diff --git a/include/Gpio.hpp b/gpio.hpp similarity index 42% rename from include/Gpio.hpp rename to gpio.hpp index 10e5b33fa932d31b97e6d736e8d444caa8a64508..1b6922e7adf258f594d7bc6451b0a14fec206978 100644 --- a/include/Gpio.hpp +++ b/gpio.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Phytium Technology Co., Ltd. + * Copyright (c) 2024, Phytium Technology Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,9 @@ #include /** - * @struct GpioInfo - * @brief Structure of gpio information. - */ -struct GpioInfo + * @brief GPIO information structure. + * */ +typedef struct { int chip; int line; @@ -35,103 +34,54 @@ struct GpioInfo bool direction; bool defaultValue; std::string name; -}; +} GpioInfo; /** - * @struct GpioManger - * @brief Structure of GPIO management information. - */ -struct GpioManager + * @brief GPIO management structure. + * */ +typedef struct { GpioInfo manager; - uint8_t monitor; + std::string monitor; std::string target; -}; +} Manager; -/** - * @struct PowerControl - * @brief Structure of power control information. - */ -struct PowerControlInfo +typedef struct { - GpioInfo control; + GpioInfo info; bool isLevelTriggered; - uint8_t controlMethod; -}; - -/** - * @struct PowerManger - * @brief Structure of power information. - */ -struct PowerManger -{ - GpioManager pgood; - std::vector outs; - std::vector resetOuts; -}; + std::string controlMethod; +} Power; /** - * @struct Gpios - * @brief Structure of all gpio information. - */ -struct Gpios + * @brief Power management structure. + * */ +typedef struct { - PowerManger power; - std::vector managers; -}; + Manager pgood; + std::vector controls; + /** Not currently used. */ + std::vector resets; +} Powers; -/** - * @class Gpio - * @brief The base class for gpio information. - */ class Gpio { public: - Gpio() = delete; Gpio(const Gpio&) = delete; Gpio& operator=(const Gpio&) = delete; Gpio(const Gpio&&) = delete; Gpio&& operator=(const Gpio&&) = delete; - /** - * @brief The constructor for Gpio. - * - * @param[in] gpioInfo - Basic information of gpio. - */ - Gpio(const GpioInfo& gpioInfo); - - /** @brief The destructor of Gpio. */ + Gpio(const GpioInfo& info); ~Gpio(); - /** - * @brief Gets the value of the current gpio. - * @return int - Returns the current value. - */ int getCurrentGpioValue() const; - - /** - * @brief Set the current gpio. - * @param[in] value - Set the current gpio value. - */ void setCurrentGpioValue(int value) const; - - /** @brief Obtain current Gpio information. */ const GpioInfo& getGpioInfo() const; protected: - /** @brief The gpio line object. */ gpiod::line line; private: - /** @brief Basic information of gpio. */ - GpioInfo gpioInfo; + const GpioInfo& _info; }; - -/** - * @brief Load data managed by gpio. - * - * @param[in] gpios - Load the saved data. - * - * @return bool - Check whether the execution is successful. - */ -bool loadGpioInfoFromJson(Gpios& rawGpioData); diff --git a/json/json.cpp b/json/json.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99360443737526c6ca0de338e98317ed7a8ce877 --- /dev/null +++ b/json/json.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2024, Phytium Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "json/json.hpp" + +#include + +#include +#include +#include +#include +#include + +void from_json(const nlohmann::json& j, GpioInfo& m) +{ + j.at("Name").get_to(m.name); + j.at("Chip").get_to(m.chip); + j.at("Line").get_to(m.line); + + std::string direction = j.at("Direction"); + if (direction == "in") + { + m.direction = false; + } + else if (direction == "out") + { + m.direction = true; + } + else + { + throw std::runtime_error("Direction Error"); + } + + if (j.contains("Polarity")) + { + j.at("Polarity").get_to(m.polarity); + } + else + { + m.polarity = true; + } + + if (j.contains("DelayTime")) + { + j.at("DelayTime").get_to(m.delayTime); + } + + if (j.contains("DefaultValue")) + { + m.defaultValue = j.at("DefaultValue") == 1 ? true : false; + } +} + +namespace json +{ +void buildGpioJson(std::vector& dataManagers, Powers& powers) +{ + std::ifstream file("/etc/default/obmc/gpio/gpio_defs.json"); + if (!file.is_open()) + { + throw std::runtime_error("Failed to open file"); + return; + } + + auto json = nlohmann::json::parse(file, nullptr, false); + if (json.is_discarded()) + { + throw std::runtime_error("JSON parsing failed"); + return; + } + + std::vector gpios; + + for (const auto& definition : json["gpio_definitions"]) + { + gpios.emplace_back(definition.get()); + } + + auto findDefinition = [&gpios](const std::string& name) -> GpioInfo { + for (auto gpio : gpios) + { + if (gpio.name == name) + { + return gpio; + } + } + throw std::runtime_error("Not Found"); + return GpioInfo{}; + }; + + auto& power = json.at("power_config"); + auto& monitors = json.at("gpio_monitor"); + + std::string pgood = power.at("power_good_in").get(); + + if (monitors.contains(pgood)) + { + powers.pgood = Manager{findDefinition(pgood), + monitors[pgood].at("Monitor").get(), + monitors[pgood].at("Target").get()}; + } + else + { + powers.pgood = Manager{findDefinition(pgood), "", ""}; + } + + auto& outs = power.at("power_up_outs"); + for (const auto& out : outs) + { + const std::string& name = out.at("Name"); + + powers.controls.emplace_back(Power{findDefinition(name), + out.at("LevelTriggered").get(), + out.at("Power").get()}); + } + + auto& managers = json.at("gpio_manager"); + + for (const std::string& manager : managers) + { + if (monitors.contains(manager)) + { + dataManagers.emplace_back( + Manager{findDefinition(manager), + monitors[manager].at("Monitor").get(), + monitors[manager].at("Target").get()}); + } + else + { + dataManagers.emplace_back(Manager{findDefinition(manager), "", ""}); + } + } +} +}; // namespace json diff --git a/json/json.hpp b/json/json.hpp new file mode 100644 index 0000000000000000000000000000000000000000..72784b79945532107704bc316978a4fcfd911b00 --- /dev/null +++ b/json/json.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023, Phytium Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "gpio.hpp" + +namespace json +{ +void buildGpioJson(std::vector& dataManagers, Powers& powers); +}; diff --git a/src/GpioMain.cpp b/main.cpp similarity index 64% rename from src/GpioMain.cpp rename to main.cpp index 7c03828989bc1292e9065d030a0a9071d9b3644e..14b27daeb5f1e9ee0fca68b859a637bb5347fa0a 100644 --- a/src/GpioMain.cpp +++ b/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Phytium Technology Co., Ltd. + * Copyright (c) 2024, Phytium Technology Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,10 @@ * limitations under the License. */ -#include "config.h" - -#include "Gpio.hpp" -#include "GpioDbusManager.hpp" -#include "PowerControl.hpp" +#include "dbus/dbusmanager.hpp" +#include "gpio.hpp" +#include "json/json.hpp" +#include "power/powercontrol.hpp" #include #include @@ -29,44 +28,39 @@ int main() { - /* Load data from JSON */ - Gpios tempGpioInfoFormJson; + std::vector dataManagers; + Powers powers; - if (!loadGpioInfoFromJson(tempGpioInfoFormJson)) - { - std::cerr << "Empty data" << std::endl; - return 0; - } + json::buildGpioJson(dataManagers, powers); - /* GPIO management service */ auto io = std::make_shared(); auto conn = std::make_shared(*io); auto objServer = sdbusplus::asio::object_server(conn); std::vector> managers; - conn->request_name(GPIO_MANAGER_SERVICE); + conn->request_name("xyz.openbmc_project.Gpio.Manager"); - for (const GpioManager& manager : tempGpioInfoFormJson.managers) + for (const Manager& manager : dataManagers) { auto interface = objServer.add_interface( - GPIO_MANAGER_PATH + manager.manager.name, GPIO_MANAGER_INTERFACE); + "/xyz/openbmc_project/gpio/" + manager.manager.name, + "xyz.openbmc_project.Gpio.Manager"); if (manager.target.empty()) { managers.emplace_back(std::make_unique( - manager.manager, interface, GPIO_VALUE_PROPERTY, *io)); + manager.manager, interface, "Value", *io)); } else { managers.emplace_back(std::make_unique( - manager.manager, interface, GPIO_VALUE_PROPERTY, *io, + manager.manager, interface, "Value", *io, std::make_pair(manager.monitor, manager.target))); } interface->initialize(); } - /* Power control service */ std::shared_ptr sdbusp; sd_bus* bus = nullptr; @@ -75,12 +69,14 @@ int main() { sdbusp = std::make_shared(*io, bus); } - sdbusp->request_name(POWER_SERVICE); + sdbusp->request_name("org.openbmc.control.Power"); auto obj = sdbusplus::asio::object_server(sdbusp); - PowerControl control(std::move(tempGpioInfoFormJson.power), - obj.add_interface(POWER_PATH, POWER_INTERFACE), *io); + PowerControl control(powers, + obj.add_interface("/org/openbmc/control/power0", + "org.openbmc.control.Power"), + *io); io->run(); diff --git a/meson.build b/meson.build index 9a8c9c48d92b76c0947fe14d009a220e54da24c9..093d10a952072a12119ffa52f7d1b828c05b81fe 100644 --- a/meson.build +++ b/meson.build @@ -5,77 +5,26 @@ project('gpio-manager', 'warning_level=3', 'cpp_std=c++20' ]) -conf = configuration_data() -conf.set_quoted('JSON_NAME', 'Name') -conf.set_quoted('JSON_CHIP', 'Chip') -conf.set_quoted('JSON_LINE', 'Line') -conf.set_quoted('JSON_DELAYTIME', 'DelayTime') -conf.set_quoted('JSON_POLARITY', 'Polarity') -conf.set_quoted('JSON_LEVELTRIGGERED', 'LevelTriggered') -conf.set_quoted('JSON_DIRECTION', 'Direction') -conf.set_quoted('JSON_DEFAULTVALUE', 'DefaultValue') -conf.set_quoted('JSON_TARGET', 'Target') -conf.set_quoted('JSON_MONITOR', 'Monitor') -conf.set_quoted('JSON_POWER', 'Power') -conf.set_quoted('POWER_CONFIG', 'power_config') -conf.set_quoted('POWER_UP_OUTS', 'power_up_outs') -conf.set_quoted('POWER_GOOD_IN', 'power_good_in') -conf.set_quoted('GPIO_DEFINITIONS', 'gpio_definitions') -conf.set_quoted('POWER_RESET_OUTS', 'reset_outs') -conf.set_quoted('GPIO_MANAGER', 'gpio_manager') -conf.set_quoted('GPIO_MONITOR', 'gpio_monitor') - -conf.set_quoted('JSON_FILEPATH', '/etc/default/obmc/gpio/gpio_defs.json') - -conf.set_quoted('GPIO_VALUE_PROPERTY', 'Value') -conf.set_quoted('POWER_GOOD', 'pgood') -conf.set_quoted('POWER_STATE', 'state') -conf.set_quoted('GET_POWER_STATE', 'getPowerState') -conf.set_quoted('SET_POWER_STATE', 'setPowerState') -conf.set_quoted('OUT', 'out') - -conf.set_quoted('GPIO_MANAGER_SERVICE', 'xyz.openbmc_project.Gpio.Manager') -conf.set_quoted('GPIO_MANAGER_PATH', '/xyz/openbmc_project/gpio/') -conf.set_quoted('GPIO_MANAGER_INTERFACE', 'xyz.openbmc_project.Gpio.Manager') -conf.set_quoted('POWER_SERVICE', 'org.openbmc.control.Power') -conf.set_quoted('POWER_PATH', '/org/openbmc/control/power0') -conf.set_quoted('POWER_INTERFACE', 'org.openbmc.control.Power') -conf.set_quoted('SYSTEMD_SERVICE', 'org.freedesktop.systemd1') -conf.set_quoted('SYSTEMD_PATH', '/org/freedesktop/systemd1') -conf.set_quoted('SYSTEMD_INTERFACE', 'org.freedesktop.systemd1.Manager') - -conf.set('LOW', 0) -conf.set_quoted('LOW_STR', 'low') -conf.set('HIGH', 1) -conf.set_quoted('HIGH_STR', 'high') -conf.set_quoted('BOTH_STR', 'both') -conf.set('BOTH', 2) -conf.set('POWER_OFF', 0) -conf.set_quoted('POWER_OFF_STR', 'off') -conf.set_quoted('POWER_ON_STR', 'on') -conf.set('POWER_ON', 1) - -configure_file(output: 'config.h', configuration: conf) - systemd = dependency('systemd') nlohmann_json = dependency('nlohmann_json') sdbusplus = dependency('sdbusplus') boost = dependency('boost') libgpiod = dependency('libgpiod') -executable('gpio-management', - 'src/GpioMain.cpp', - 'src/Gpio.cpp', - 'src/GpioDbusManager.cpp', - 'src/PowerControl.cpp', - link_args: ['-lgpiodcxx', '-lboost_thread'], +executable('gpiomanagement', + 'main.cpp', + 'gpio.cpp', + 'json/json.cpp', + 'dbus/dbusmanager.cpp', + 'power/powercontrol.cpp', + link_args: ['-lgpiodcxx'], dependencies: [ nlohmann_json, systemd, sdbusplus, boost, libgpiod, ], - include_directories: 'include', + include_directories: '.', install : true, install_dir: get_option('bindir')) diff --git a/src/PowerControl.cpp b/power/powercontrol.cpp similarity index 40% rename from src/PowerControl.cpp rename to power/powercontrol.cpp index 89500948762fa19937e716947c7664f38be242d8..deb3ab707ae30aa2dd33331b466da61c16242b0f 100644 --- a/src/PowerControl.cpp +++ b/power/powercontrol.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Phytium Technology Co., Ltd. + * Copyright (c) 2024, Phytium Technology Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,59 +14,60 @@ * limitations under the License. */ -#include "config.h" - -#include "PowerControl.hpp" - -#include +#include "power/powercontrol.hpp" #include PowerControl::PowerControl( - const PowerManger& powers, + const Powers& powers, std::shared_ptr interface, boost::asio::io_context& io) : - GpioDbusManager(powers.pgood.manager, interface, POWER_GOOD, io, - std::make_pair(powers.pgood.monitor, powers.pgood.target)) + GpioDbusManager(powers.pgood.manager, interface, "pgood", io, + std::make_pair(powers.pgood.monitor, powers.pgood.target)), + _timer(io) { - /* Initialize and create GPIO control objects */ - for (const auto& out : powers.outs) + for (const auto& control : powers.controls) { - gpios.emplace_back(std::make_unique( - out.isLevelTriggered, out.controlMethod, - std::make_unique(out.control))); + _controls.emplace_back(std::make_unique( + control.isLevelTriggered, control.controlMethod, + std::make_unique(control.info))); } - /* Register the corresponding properties and methods */ - interface->register_property(POWER_STATE, GpioDbusManager::currentState); + interface->register_property("state", GpioDbusManager::currentState); interface->register_method( - GET_POWER_STATE, [this]() { return GpioDbusManager::currentState; }); - interface->register_method(SET_POWER_STATE, [&](int state) { + "getPowerState", [this]() { return GpioDbusManager::currentState; }); + interface->register_method("setPowerState", [&](int state) { if (state == Gpio::getCurrentGpioValue()) { std::cout - << "The status has not changed and does not need to be set" - << std::endl; + << "The status has not changed and does not need to be set\n"; } else { - /* There are two different control methods, namely level triggering - * and pulse form */ - for (const auto& gpio : gpios) + for (const auto& control : _controls) { - if (gpio->controlMethod == BOTH || gpio->controlMethod == state) + static const std::array powerState{"off", "on", + "both"}; + if (control->controlMethod == powerState.back() || + control->controlMethod == powerState[state]) { - if (!gpio->isLevelTriggered) + if (!control->isLevelTriggered) { - gpio->control->setCurrentGpioValue(0); - boost::this_thread::sleep( - boost::posix_time::milliseconds( - gpio->control->getGpioInfo().delayTime)); - gpio->control->setCurrentGpioValue(1); + control->control->setCurrentGpioValue(0); + _timer.expires_after(std::chrono::milliseconds( + control->control->getGpioInfo().delayTime)); + _timer.async_wait( + [&control](const boost::system::error_code& ec) { + if (ec == boost::asio::error::operation_aborted) + { + return; + } + control->control->setCurrentGpioValue(1); + }); } else { - gpio->control->setCurrentGpioValue(state); + control->control->setCurrentGpioValue(state); } } } @@ -74,13 +75,24 @@ PowerControl::PowerControl( << std::endl; } - interface->set_property(POWER_STATE, Gpio::getCurrentGpioValue()); + interface->set_property("state", state); }); interface->initialize(); - /* If it is turned on by default, update the status */ + /** + * When the initialization phase is in the power on state, execute the + * corresponding service. + * */ if (GpioDbusManager::currentState) { - startUnit(powers.pgood.target, 1); + if (!powers.pgood.target.empty()) + { + startUnit(powers.pgood.target, 1); + } } }; + +PowerControl::~PowerControl() +{ + _timer.cancel(); +} diff --git a/include/PowerControl.hpp b/power/powercontrol.hpp similarity index 65% rename from include/PowerControl.hpp rename to power/powercontrol.hpp index cd9c305ec89fa5d79802e7bdcedb2cfd0ca59676..9af0a02994a8d977fd451e9f5e81d155cd79246a 100644 --- a/include/PowerControl.hpp +++ b/power/powercontrol.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Phytium Technology Co., Ltd. + * Copyright (c) 2024, Phytium Technology Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,16 @@ #pragma once -#include "GpioDbusManager.hpp" +#include "dbus/dbusmanager.hpp" +#include "gpio.hpp" + +#include + +#include /** - * @class PowerControl - * @brief The object of power control. - */ + * @brief GPIO controls the class of power up and down. + * */ class PowerControl : public GpioDbusManager { public: @@ -31,26 +35,19 @@ class PowerControl : public GpioDbusManager PowerControl(const PowerControl&&) = delete; PowerControl&& operator=(const PowerControl&&) = delete; - /** - * @brief The constructor for PowerControl. - * - * @param[in] powers - Power management information. - * @param[in] io - Io context. - * @param[in] interface - Dbus interface. - * - */ - PowerControl(const PowerManger& powers, + PowerControl(const Powers& powers, std::shared_ptr interface, boost::asio::io_context& io); + ~PowerControl(); private: - struct ControlSet + typedef struct { bool isLevelTriggered; - uint8_t controlMethod; + std::string controlMethod; std::unique_ptr control; - }; + } ControlSet; - /** @brief On/off control. */ - std::vector> gpios; + std::vector> _controls; + boost::asio::steady_timer _timer; }; diff --git a/services/gpio-manager@.service b/services/gpio-manager@.service index 0139bd9cfc3677e6efe0753bd9fac06de5b4b51c..9bdf3d095c27b5c703d7c6e9de7a51d90a063636 100644 --- a/services/gpio-manager@.service +++ b/services/gpio-manager@.service @@ -3,7 +3,7 @@ Description=GPIO management [Service] Restart=always -ExecStart=/usr/bin/gpio-management +ExecStart=/usr/bin/gpiomanagement SyslogIdentifier=gpio-management Type=dbus BusName=org.openbmc.control.Power diff --git a/src/Gpio.cpp b/src/Gpio.cpp deleted file mode 100644 index c1d6111697f1bb9535a746580ac2237f0c30454f..0000000000000000000000000000000000000000 --- a/src/Gpio.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2023, Phytium Technology Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "config.h" - -#include "Gpio.hpp" - -#include - -#include -#include -#include - -Gpio::Gpio(const GpioInfo& gpioInfo) : - line(gpiod::chip(std::to_string(gpioInfo.chip), gpiod::chip::OPEN_BY_NUMBER) - .get_line(gpioInfo.line)), - gpioInfo(std::move(gpioInfo)) -{ - try - { - line.request( - {gpioInfo.name, - gpioInfo.direction ? gpiod::line_request::DIRECTION_OUTPUT - : gpiod::line_request::EVENT_BOTH_EDGES, - gpioInfo.polarity ? gpiod::line_request::FLAG_ACTIVE_LOW : 0}, - gpioInfo.defaultValue); - } - catch (...) - { - std::cerr << gpioInfo.name << " Init Error" << std::endl; - - return; - } -} - -Gpio::~Gpio() -{ - line.release(); -} - -int Gpio::getCurrentGpioValue() const -{ - return line.get_value(); -} - -void Gpio::setCurrentGpioValue(int value) const -{ - line.set_value(value); -} - -const GpioInfo& Gpio::getGpioInfo() const -{ - return gpioInfo; -} - -static bool loadGpioData(const nlohmann::json& defs, - const std::string& gpioName, GpioInfo& dataIn) -{ - try - { - auto it = std::find_if(defs.begin(), defs.end(), - [&gpioName](const auto& def) { - return def.at(JSON_NAME) == gpioName; - }); - - if (it != defs.end()) - { - dataIn = { - it->at(JSON_CHIP), - it->at(JSON_LINE), - it->contains(JSON_DELAYTIME) - ? it->at(JSON_DELAYTIME).get() - : static_cast(0), - it->at(JSON_POLARITY), - std::string(it->at(JSON_DIRECTION)) == OUT, - it->contains(JSON_DEFAULTVALUE) - ? static_cast(it->at(JSON_DEFAULTVALUE).get()) - : false, - it->at(JSON_NAME)}; - } - } - catch (const nlohmann::json::exception& e) - { - std::cerr << gpioName << " json error:" << e.what() << std::endl; - - return false; - } - return true; -} - -static bool loadGpioManagerData(const nlohmann::json& defs, - const nlohmann::json& monitor, - const std::string& key, GpioManager& manager) -{ - if (!loadGpioData(defs, key, manager.manager)) - { - std::cerr << key << " data format error" << std::endl; - - return false; - } - - if (monitor.contains(key)) - { - try - { - const std::string& monitorStr = monitor[key].at(JSON_MONITOR); - - if (monitorStr != BOTH_STR && monitorStr != HIGH_STR && - monitorStr != LOW_STR) - { - return false; - } - - manager.monitor = monitorStr == BOTH_STR - ? BOTH - : monitorStr == HIGH_STR ? HIGH : LOW; - - manager.target = monitor[key].at(JSON_TARGET); - } - catch (const nlohmann::json::exception& e) - { - std::cerr << "JSON data format error: " << e.what() << std::endl; - - return false; - } - } - return true; -} - -bool loadGpioInfoFromJson(Gpios& rawGpioData) -{ - if (!std::filesystem::exists(JSON_FILEPATH)) - { - std::cerr << JSON_FILEPATH << " not found" << std::endl; - - return false; - } - - std::ifstream inputStream(JSON_FILEPATH); - - if (!inputStream.good()) - { - std::cerr << JSON_FILEPATH << " can not open" << std::endl; - - return false; - } - - nlohmann::json loadJson; - - try - { - loadJson = nlohmann::json::parse(inputStream); - } - catch (const nlohmann::json::parse_error& e) - { - std::cerr << "Parse json error:" << e.what() << std::endl; - inputStream.close(); - - return false; - } - inputStream.close(); - - const auto& defs = loadJson[GPIO_DEFINITIONS]; - const auto& monitors = loadJson[GPIO_MONITOR]; - const std::string& pgood = loadJson[POWER_CONFIG][POWER_GOOD_IN]; - GpioManager tempGpioManager; - - /* pgoood */ - if (loadGpioManagerData(defs, monitors, pgood, tempGpioManager)) - { - rawGpioData.power.pgood = std::move(tempGpioManager); - } - - /* control outs */ - const auto& powerUpOuts = loadJson[POWER_CONFIG][POWER_UP_OUTS]; - - for (const nlohmann::json& out : powerUpOuts) - { - try - { - PowerControlInfo rawPowerData; - const std::string& powerMethod = out.at(JSON_POWER); - - if (powerMethod != BOTH_STR && powerMethod != POWER_OFF_STR && - powerMethod != POWER_ON_STR) - { - continue; - } - - rawPowerData.controlMethod = - powerMethod == BOTH_STR - ? BOTH - : powerMethod == POWER_OFF_STR ? POWER_OFF : POWER_ON; - - rawPowerData.isLevelTriggered = out.at(JSON_LEVELTRIGGERED); - - if (!loadGpioData(defs, out.at(JSON_NAME), rawPowerData.control)) - { - continue; - } - - rawGpioData.power.outs.emplace_back(rawPowerData); - } - catch (...) - { - std::cerr << "controls data format error" << std::endl; - } - } - - /* reset outs(Currently not in use.) */ - GpioInfo tempGpio; - const auto& powerResetOuts = loadJson[POWER_CONFIG][POWER_RESET_OUTS]; - - for (const auto& reset : powerResetOuts) - { - if (!loadGpioData(defs, reset, tempGpio)) - { - continue; - } - - rawGpioData.power.resetOuts.emplace_back(tempGpio); - } - - /* gpio manager */ - const auto& managers = loadJson[GPIO_MANAGER]; - - for (const std::string& manager : managers) - { - if (!loadGpioManagerData(defs, monitors, manager, tempGpioManager)) - { - continue; - } - - rawGpioData.managers.emplace_back(std::move(tempGpioManager)); - } - - return true; -}