diff options
author | Yong Li <yong.b.li@intel.com> | 2017-11-24 15:41:23 +0300 |
---|---|---|
committer | Yong Li <yong.b.li@linux.intel.com> | 2018-04-11 06:23:32 +0300 |
commit | 49ac43d9cae497fa0755af42bfb33952acbdf445 (patch) | |
tree | 864acbaa8d8acda580296cb91eeeb99af2de4a63 /services | |
parent | c8e06e4f91a3673f50b14919dc2c1c9d5acefc40 (diff) | |
download | provingground-49ac43d9cae497fa0755af42bfb33952acbdf445.tar.xz |
Implement the power/reset button monitor using sdbusplus
Implement the below service using sdbusplus, as a replacement:
https://github.com/openbmc/skeleton/blob/master/pwrbutton/button_power_obj.c
https://github.com/openbmc/skeleton/blob/master/rstbutton/button_reset_obj.c
Change-Id: Ib8e4dbc6bb062b729cd012f0688b028e695795ec
Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
Diffstat (limited to 'services')
17 files changed, 951 insertions, 0 deletions
diff --git a/services/chassis/Buttons/.clang-format b/services/chassis/Buttons/.clang-format new file mode 100644 index 0000000..bbc1bb1 --- /dev/null +++ b/services/chassis/Buttons/.clang-format @@ -0,0 +1,85 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +PointerAlignment: Left +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IndentCaseLabels: true +IndentWidth: 4 +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: true +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... + diff --git a/services/chassis/Buttons/CMakeLists.txt b/services/chassis/Buttons/CMakeLists.txt new file mode 100644 index 0000000..8ce6728 --- /dev/null +++ b/services/chassis/Buttons/CMakeLists.txt @@ -0,0 +1,119 @@ +cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR) +project(Buttons CXX) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH} ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +include(GNUInstallDirs) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +set(POWER_DBUS_OBJECT_NAME "xyz/openbmc_project/Chassis/Buttons/Power") +set(POWER_DBUS_INTF_NAME "xyz.openbmc_project.Chassis.Buttons.Power") + +set(RESET_DBUS_OBJECT_NAME "xyz/openbmc_project/Chassis/Buttons/Reset") +set(RESET_DBUS_INTF_NAME "xyz.openbmc_project.Chassis.Buttons.Reset") + +add_definitions(-DPOWER_DBUS_OBJECT_NAME="/${POWER_DBUS_OBJECT_NAME}") + +add_definitions(-DRESET_DBUS_OBJECT_NAME="/${RESET_DBUS_OBJECT_NAME}") + +set(SRC_FILES + src/PowerButton.cpp + src/ResetButton.cpp + src/main.cpp +) +set(GENERATED_SRC_FILES + ${POWER_DBUS_OBJECT_NAME}/error.cpp + ${POWER_DBUS_OBJECT_NAME}/server.cpp + ${RESET_DBUS_OBJECT_NAME}/error.cpp + ${RESET_DBUS_OBJECT_NAME}/server.cpp +) + +# import libsystemd +find_package(PkgConfig REQUIRED) +pkg_check_modules(SYSTEMD libsystemd REQUIRED) +include_directories(${SYSTEMD_INCLUDE_DIRS}) +link_directories(${SYSTEMD_LIBRARY_DIRS}) + +# import sdbusplus +find_package(PkgConfig REQUIRED) +pkg_check_modules(SDBUSPLUSPLUS sdbusplus REQUIRED) +include_directories(${SDBUSPLUSPLUS_INCLUDE_DIRS}) +link_directories(${SDBUSPLUSPLUS_LIBRARY_DIRS}) +find_program(SDBUSPLUSPLUS sdbus++) + +# import phosphor-logging +find_package(PkgConfig REQUIRED) +pkg_check_modules(LOGGING phosphor-logging REQUIRED) +include_directories(${LOGGING_INCLUDE_DIRS}) +link_directories(${LOGGING_LIBRARY_DIRS}) + +# phosphor-dbus-interfaces +find_package(PkgConfig REQUIRED) +pkg_check_modules(DBUSINTERFACE phosphor-dbus-interfaces REQUIRED) +include_directories(${DBUSINTERFACE_INCLUDE_DIRS}) +link_directories(${DBUSINTERFACE_LIBRARY_DIRS}) + +#include_directories(${CMAKE_CURRENT_BINARY_DIR}/${DBUS_OBJECT_NAME}) + +add_custom_command( + OUTPUT ${POWER_DBUS_OBJECT_NAME}/error.hpp + OUTPUT ${POWER_DBUS_OBJECT_NAME}/error.cpp + COMMAND mkdir -p ${POWER_DBUS_OBJECT_NAME} + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} error exception-header ${POWER_DBUS_INTF_NAME} > ${POWER_DBUS_OBJECT_NAME}/error.hpp + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} error exception-cpp ${POWER_DBUS_INTF_NAME} > ${POWER_DBUS_OBJECT_NAME}/error.cpp + DEPENDS ${POWER_DBUS_OBJECT_NAME}.errors.yaml +) +set_source_files_properties( + ${POWER_DBUS_OBJECT_NAME}/error.hpp + ${POWER_DBUS_OBJECT_NAME}/error.cpp + PROPERTIES GENERATED TRUE) + +add_custom_command( + OUTPUT ${RESET_DBUS_OBJECT_NAME}/error.hpp + OUTPUT ${RESET_DBUS_OBJECT_NAME}/error.cpp + COMMAND mkdir -p ${RESET_DBUS_OBJECT_NAME} + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} error exception-header ${RESET_DBUS_INTF_NAME} > ${RESET_DBUS_OBJECT_NAME}/error.hpp + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} error exception-cpp ${RESET_DBUS_INTF_NAME} > ${RESET_DBUS_OBJECT_NAME}/error.cpp + DEPENDS ${RESET_DBUS_OBJECT_NAME}.errors.yaml +) +set_source_files_properties( + ${RESET_DBUS_OBJECT_NAME}/error.hpp + ${RESET_DBUS_OBJECT_NAME}/error.cpp + PROPERTIES GENERATED TRUE) + +add_custom_command( + OUTPUT ${POWER_DBUS_OBJECT_NAME}/server.hpp + OUTPUT ${POWER_DBUS_OBJECT_NAME}/server.cpp + COMMAND mkdir -p ${POWER_DBUS_OBJECT_NAME} + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} interface server-header ${POWER_DBUS_INTF_NAME} > ${POWER_DBUS_OBJECT_NAME}/server.hpp + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} interface server-cpp ${POWER_DBUS_INTF_NAME} > ${POWER_DBUS_OBJECT_NAME}/server.cpp + DEPENDS ${POWER_DBUS_OBJECT_NAME}.interface.yaml +) +set_source_files_properties( + ${POWER_DBUS_OBJECT_NAME}/server.hpp + ${POWER_DBUS_OBJECT_NAME}/server.cpp + PROPERTIES GENERATED TRUE) + +add_custom_command( + OUTPUT ${RESET_DBUS_OBJECT_NAME}/server.hpp + OUTPUT ${RESET_DBUS_OBJECT_NAME}/server.cpp + COMMAND mkdir -p ${RESET_DBUS_OBJECT_NAME} + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} interface server-header ${RESET_DBUS_INTF_NAME} > ${RESET_DBUS_OBJECT_NAME}/server.hpp + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} interface server-cpp ${RESET_DBUS_INTF_NAME} > ${RESET_DBUS_OBJECT_NAME}/server.cpp + DEPENDS ${RESET_DBUS_OBJECT_NAME}.interface.yaml +) +set_source_files_properties( + ${RESET_DBUS_OBJECT_NAME}/server.hpp + ${RESET_DBUS_OBJECT_NAME}/server.cpp + PROPERTIES GENERATED TRUE) + +add_executable(${PROJECT_NAME} ${SRC_FILES} ${GENERATED_SRC_FILES}) +target_link_libraries(${PROJECT_NAME} ${SYSTEMD_LIBRARIES} gpio) +target_link_libraries(${PROJECT_NAME} "${SDBUSPLUSPLUS_LIBRARIES} -lstdc++fs") + +install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/services/chassis/Buttons/inc/Common.hpp b/services/chassis/Buttons/inc/Common.hpp new file mode 100644 index 0000000..b7651ec --- /dev/null +++ b/services/chassis/Buttons/inc/Common.hpp @@ -0,0 +1,9 @@ +#pragma once +struct EventDeleter +{ + void operator()(sd_event *event) const + { + event = sd_event_unref(event); + } +}; +using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
\ No newline at end of file diff --git a/services/chassis/Buttons/inc/PowerButton.hpp b/services/chassis/Buttons/inc/PowerButton.hpp new file mode 100644 index 0000000..6ec947e --- /dev/null +++ b/services/chassis/Buttons/inc/PowerButton.hpp @@ -0,0 +1,97 @@ +#pragma once +#include "xyz/openbmc_project/Chassis/Buttons/Power/error.hpp" +#include "xyz/openbmc_project/Chassis/Buttons/Power/server.hpp" +#include "Common.hpp" +#include "Gpio.hpp" + +const static constexpr char *POWER_BUTTON = "POWER_BUTTON"; + +struct PowerButton + : sdbusplus::server::object::object< + sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Power> +{ + + PowerButton(sdbusplus::bus::bus &bus, const char *path, EventPtr &event, + sd_event_io_handler_t handler = PowerButton::EventHandler) : + sdbusplus::server::object::object< + sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Power>( + bus, path), + fd(-1), bus(bus), event(event), callbackHandler(handler) + { + + int ret; + + // config gpio + ret = ::configGpio(POWER_BUTTON, &fd, bus); + if (ret < 0) + { + throw std::runtime_error("failed to config GPIO"); + } + + ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI, + callbackHandler, this); + if (ret < 0) + { + throw std::runtime_error("failed to add to event loop"); + } + } + + ~PowerButton() + { + ::closeGpio(fd); + } + bool simPress() override; + bool simLongPress() override; + static int EventHandler(sd_event_source *es, int fd, uint32_t revents, + void *userdata) + { + + int n; + char buf; + + PowerButton *powerButton = static_cast<PowerButton *>(userdata); + + if (!powerButton) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "null pointer!"); + return -1; + } + + n = ::lseek(fd, 0, SEEK_SET); + + if (n < 0) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "lseek error!"); + return n; + } + + n = ::read(fd, &buf, 1); + if (n < 0) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "read error!"); + return n; + } + + if (buf == '0') + { + // emit pressed signal + powerButton->pressed(); + } + else + { + // released + powerButton->released(); + } + + return 0; + } + + private: + int fd; + sdbusplus::bus::bus &bus; + EventPtr &event; + sd_event_io_handler_t callbackHandler; +}; diff --git a/services/chassis/Buttons/inc/ResetButton.hpp b/services/chassis/Buttons/inc/ResetButton.hpp new file mode 100644 index 0000000..f5f1aa7 --- /dev/null +++ b/services/chassis/Buttons/inc/ResetButton.hpp @@ -0,0 +1,96 @@ +#pragma once +#include "xyz/openbmc_project/Chassis/Buttons/Reset/error.hpp" +#include "xyz/openbmc_project/Chassis/Buttons/Reset/server.hpp" +#include "Common.hpp" +#include "Gpio.hpp" + +const static constexpr char *RESET_BUTTON = "RESET_BUTTON"; + +struct ResetButton + : sdbusplus::server::object::object< + sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Reset> +{ + + ResetButton(sdbusplus::bus::bus &bus, const char *path, EventPtr &event, + sd_event_io_handler_t handler = ResetButton::EventHandler) : + sdbusplus::server::object::object< + sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::Reset>( + bus, path), + fd(-1), bus(bus), event(event), callbackHandler(handler) + { + + int ret; + + // config gpio + ret = ::configGpio(RESET_BUTTON, &fd, bus); + if (ret < 0) + { + throw std::runtime_error("failed to config GPIO"); + } + + ret = sd_event_add_io(event.get(), nullptr, fd, EPOLLPRI, + callbackHandler, this); + if (ret < 0) + { + throw std::runtime_error("failed to add to event loop"); + } + } + + ~ResetButton() + { + ::closeGpio(fd); + } + bool simPress() override; + static int EventHandler(sd_event_source *es, int fd, uint32_t revents, + void *userdata) + { + + int n; + char buf; + + ResetButton *resetButton = static_cast<ResetButton *>(userdata); + + if (!resetButton) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "null pointer!"); + return -1; + } + + n = ::lseek(fd, 0, SEEK_SET); + + if (n < 0) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "lseek error!"); + return n; + } + + n = ::read(fd, &buf, 1); + if (n < 0) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "read error!"); + return n; + } + + if (buf == '0') + { + // emit pressed signal + resetButton->pressed(); + } + else + { + // released + resetButton->released(); + } + + return 0; + } + + private: + int fd; + sdbusplus::bus::bus &bus; + EventPtr &event; + sd_event_io_handler_t callbackHandler; +}; diff --git a/services/chassis/Buttons/src/PowerButton.cpp b/services/chassis/Buttons/src/PowerButton.cpp new file mode 100644 index 0000000..79f9f83 --- /dev/null +++ b/services/chassis/Buttons/src/PowerButton.cpp @@ -0,0 +1,54 @@ +/* +// Copyright (c) 2018 Intel Corporation +// +// 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 <chrono> +#include <experimental/filesystem> +#include <fcntl.h> +#include <fstream> +#include <iostream> +#include <phosphor-logging/elog-errors.hpp> +#include <phosphor-logging/elog.hpp> +#include <phosphor-logging/log.hpp> +#include <sys/stat.h> +#include <sys/types.h> +#include <systemd/sd-event.h> +#include <unistd.h> +#include <xyz/openbmc_project/Common/error.hpp> +#include "PowerButton.hpp" + +const static constexpr char *SYSMGR_SERVICE = "org.openbmc.managers.System"; +const static constexpr char *SYSMGR_OBJ_PATH = "/org/openbmc/managers/System"; +const static constexpr char *SYSMGR_INTERFACE = "org.openbmc.managers.System"; + +static constexpr size_t LONG_PRESS_MS = 6000; + +bool PowerButton::simPress() +{ + uint64_t currentTimeMs = + std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); + pressedTime(currentTimeMs); + buttonState(false); + pressed(); + return true; +} + +bool PowerButton::simLongPress() +{ + buttonState(true); + pressedLong(); + return true; +}
\ No newline at end of file diff --git a/services/chassis/Buttons/src/ResetButton.cpp b/services/chassis/Buttons/src/ResetButton.cpp new file mode 100644 index 0000000..d299fee --- /dev/null +++ b/services/chassis/Buttons/src/ResetButton.cpp @@ -0,0 +1,39 @@ +/* +// Copyright (c) 2018 Intel Corporation +// +// 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 <chrono> +#include <experimental/filesystem> +#include <fcntl.h> +#include <fstream> +#include <iostream> +#include <phosphor-logging/elog-errors.hpp> +#include <phosphor-logging/elog.hpp> +#include <phosphor-logging/log.hpp> +#include <sys/stat.h> +#include <sys/types.h> +#include <systemd/sd-event.h> +#include <unistd.h> +#include <xyz/openbmc_project/Common/error.hpp> +#include "ResetButton.hpp" + +const static constexpr char *SYSMGR_SERVICE = "org.openbmc.managers.System"; +const static constexpr char *SYSMGR_OBJ_PATH = "/org/openbmc/managers/System"; +const static constexpr char *SYSMGR_INTERFACE = "org.openbmc.managers.System"; + +bool ResetButton::simPress() +{ + pressed(); + return true; +}
\ No newline at end of file diff --git a/services/chassis/Buttons/src/main.cpp b/services/chassis/Buttons/src/main.cpp new file mode 100644 index 0000000..a329dab --- /dev/null +++ b/services/chassis/Buttons/src/main.cpp @@ -0,0 +1,67 @@ +#include <chrono> +#include <experimental/filesystem> +#include <fcntl.h> +#include <fstream> +#include <iostream> +#include <phosphor-logging/elog-errors.hpp> +#include <phosphor-logging/elog.hpp> +#include <phosphor-logging/log.hpp> +#include <sys/stat.h> +#include <sys/types.h> +#include <systemd/sd-event.h> +#include <unistd.h> +#include <xyz/openbmc_project/Common/error.hpp> +#include "ResetButton.hpp" +#include "PowerButton.hpp" + +int main(int argc, char *argv[]) +{ + int ret = 0; + + phosphor::logging::log<phosphor::logging::level::INFO>( + "Start power button service..."); + + sd_event *event = nullptr; + ret = sd_event_default(&event); + if (ret < 0) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error creating a default sd_event handler"); + return ret; + } + EventPtr eventP{event}; + event = nullptr; + + auto bus = sdbusplus::bus::new_default(); + sdbusplus::server::manager::manager objManager{ + bus, "/xyz/openbmc_project/Chassis/Buttons"}; + + bus.request_name("xyz.openbmc_project.Chassis.Buttons"); + + PowerButton powerButton{bus, POWER_DBUS_OBJECT_NAME, eventP}; + + ResetButton resetButton{bus, RESET_DBUS_OBJECT_NAME, eventP}; + + try + { + bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL); + + while (true) + { + ret = sd_event_run(eventP.get(), (uint64_t)-1); + if (ret < 0) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error waiting for events"); + break; + } + } + } + + catch (std::exception &e) + { + phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); + ret = -1; + } + return ret; +} diff --git a/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Power.errors.yaml b/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Power.errors.yaml new file mode 100644 index 0000000..9de4b9d --- /dev/null +++ b/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Power.errors.yaml @@ -0,0 +1,9 @@ +- name: UnsupportedCommand + description: > + An unsupported command was attempted. +- name: InvalidParameter + description: > + An invalid parameter was attempted. +- name: IOError + description: > + An IO error occurred. diff --git a/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Power.interface.yaml b/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Power.interface.yaml new file mode 100644 index 0000000..e361ce7 --- /dev/null +++ b/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Power.interface.yaml @@ -0,0 +1,51 @@ +description: > + power button control service +methods: + - name: simPress + description: > + emulate power button press. + returns: + - name: state + type: boolean + description: > + The result of command. + errors: + - self.Error.UnsupportedCommand + - self.Error.InvalidParameter + - self.Error.IOError + + - name: simLongPress + description: > + emulate power button long press. + returns: + - name: state + type: boolean + description: > + The result of command. + errors: + - self.Error.UnsupportedCommand + - self.Error.InvalidParameter + - self.Error.IOError + +properties: + - name: ButtonState + type: boolean + default: 0 + description: > + power button value + + - name: PressedTime + type: uint64 + default: 0 + description: > + when power button is pressed +signals: + - name: Released + description: > + power button release signal + - name: Pressed + description: > + power button pressed signal + - name: PressedLong + description: > + power button long pressed signal diff --git a/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Reset.errors.yaml b/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Reset.errors.yaml new file mode 100644 index 0000000..9de4b9d --- /dev/null +++ b/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Reset.errors.yaml @@ -0,0 +1,9 @@ +- name: UnsupportedCommand + description: > + An unsupported command was attempted. +- name: InvalidParameter + description: > + An invalid parameter was attempted. +- name: IOError + description: > + An IO error occurred. diff --git a/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Reset.interface.yaml b/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Reset.interface.yaml new file mode 100644 index 0000000..700583f --- /dev/null +++ b/services/chassis/Buttons/xyz/openbmc_project/Chassis/Buttons/Reset.interface.yaml @@ -0,0 +1,24 @@ +description: > + reset button control service +methods: + - name: simPress + description: > + emulate reset button press. + returns: + - name: state + type: boolean + description: > + The result of command. + errors: + - self.Error.UnsupportedCommand + - self.Error.InvalidParameter + - self.Error.IOError + + +signals: + - name: Released + description: > + reset button release signal + - name: Pressed + description: > + reset button pressed signal diff --git a/services/chassis/CMakeLists.txt b/services/chassis/CMakeLists.txt new file mode 100644 index 0000000..6404467 --- /dev/null +++ b/services/chassis/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Gpio/inc) + +add_subdirectory(Gpio) +add_subdirectory(Buttons)
\ No newline at end of file diff --git a/services/chassis/Gpio/.clang-format b/services/chassis/Gpio/.clang-format new file mode 100644 index 0000000..bbc1bb1 --- /dev/null +++ b/services/chassis/Gpio/.clang-format @@ -0,0 +1,85 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +PointerAlignment: Left +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IndentCaseLabels: true +IndentWidth: 4 +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: true +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... + diff --git a/services/chassis/Gpio/CMakeLists.txt b/services/chassis/Gpio/CMakeLists.txt new file mode 100644 index 0000000..5f4b0e1 --- /dev/null +++ b/services/chassis/Gpio/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR) +project(gpio CXX) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include(GNUInstallDirs) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc) + +add_library(${PROJECT_NAME} SHARED src/Gpio.cpp) + +set_target_properties(${PROJECT_NAME} PROPERTIES VERSION "0.1.0") +set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION "0") + +install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/services/chassis/Gpio/inc/Gpio.hpp b/services/chassis/Gpio/inc/Gpio.hpp new file mode 100644 index 0000000..c906976 --- /dev/null +++ b/services/chassis/Gpio/inc/Gpio.hpp @@ -0,0 +1,3 @@ +#pragma once +int configGpio(const char *gpioName, int *fd, sdbusplus::bus::bus &bus); +int closeGpio(int fd);
\ No newline at end of file diff --git a/services/chassis/Gpio/src/Gpio.cpp b/services/chassis/Gpio/src/Gpio.cpp new file mode 100644 index 0000000..ef1490c --- /dev/null +++ b/services/chassis/Gpio/src/Gpio.cpp @@ -0,0 +1,182 @@ +#include <experimental/filesystem> +#include <fcntl.h> +#include <fstream> +#include <iostream> +#include <phosphor-logging/elog-errors.hpp> +#include <phosphor-logging/elog.hpp> +#include <phosphor-logging/log.hpp> +#include <sys/stat.h> +#include <sys/types.h> +#include <systemd/sd-event.h> +#include <unistd.h> +#include <xyz/openbmc_project/Common/error.hpp> +#include "Gpio.hpp" + +const static constexpr char *SYSMGR_SERVICE = "org.openbmc.managers.System"; +const static constexpr char *SYSMGR_OBJ_PATH = "/org/openbmc/managers/System"; +const static constexpr char *SYSMGR_INTERFACE = "org.openbmc.managers.System"; + +int closeGpio(int fd) +{ + if (fd > 0) + { + ::close(fd); + } + return 0; +} + +int configGpio(const char *gpioName, int *fd, sdbusplus::bus::bus &bus) +{ + auto method = bus.new_method_call(SYSMGR_SERVICE, SYSMGR_OBJ_PATH, + SYSMGR_INTERFACE, "gpioInit"); + + method.append(gpioName); + + auto result = bus.call(method); + + if (result.is_method_error()) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "bus call error!"); + return -1; + } + + int32_t gpioNum; + std::string gpioDev; + std::string gpioDirection; + + result.read(gpioDev, gpioNum, gpioDirection); + + std::string devPath; + + std::fstream stream; + + stream.exceptions(std::ifstream::failbit | std::ifstream::badbit); + + devPath.clear(); + devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/value"; + + std::experimental::filesystem::path fullPath(devPath); + + if (std::experimental::filesystem::exists(fullPath)) + { + phosphor::logging::log<phosphor::logging::level::INFO>("GPIO exported"); + } + else + { + devPath.clear(); + devPath = gpioDev + "/export"; + + stream.open(devPath, std::fstream::out); + try + { + stream << gpioNum; + stream.close(); + } + + catch (const std::exception &e) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error in writing!", + phosphor::logging::entry("PATH=%s", devPath.c_str()), + phosphor::logging::entry("NUM=%d", gpioNum)); + return -1; + } + } + + if (gpioDirection == "out") + { + devPath.clear(); + devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/value"; + + uint32_t currentValue; + + stream.open(devPath, std::fstream::in); + try + { + stream >> currentValue; + stream.close(); + } + + catch (const std::exception &e) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error in reading!", + phosphor::logging::entry("PATH=%s", devPath.c_str())); + return -1; + } + + const char *direction = currentValue ? "high" : "low"; + + devPath.clear(); + devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/direction"; + + stream.open(devPath, std::fstream::out); + try + { + stream << direction; + stream.close(); + } + + catch (const std::exception &e) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error in writing!"); + return -1; + } + } + else if (gpioDirection == "in") + { + devPath.clear(); + devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/direction"; + + stream.open(devPath, std::fstream::out); + try + { + stream << gpioDirection; + stream.close(); + } + + catch (const std::exception &e) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error in writing!"); + return -1; + } + } + else if ((gpioDirection == "both")) + { + + // For gpio configured as ‘both’, it is an interrupt pin and trigged on + // both rising and falling signals + devPath.clear(); + devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/edge"; + + stream.open(devPath, std::fstream::out); + try + { + stream << gpioDirection; + stream.close(); + } + + catch (const std::exception &e) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error in writing!"); + return -1; + } + } + + devPath.clear(); + devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/value"; + + *fd = ::open(devPath.c_str(), O_RDWR | O_NONBLOCK); + + if (*fd < 0) + { + phosphor::logging::log<phosphor::logging::level::ERR>("open error!"); + return -1; + } + + return 0; +} |