blob: cc3e358ac440cf42daba64a6ae778dac7722a12a [file] [log] [blame]
Christopher Meis75ff1672025-09-23 11:40:06 +02001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3
Gunnar Mills835dfb82017-07-26 16:15:21 -05004#pragma once
Gunnar Mills835dfb82017-07-26 16:15:21 -05005#include "file.hpp"
6
Patrick Venturedace6802018-11-01 16:52:10 -07007#include <libevdev/libevdev.h>
8#include <systemd/sd-event.h>
9
Patrick Williams39084b42023-05-10 07:50:58 -050010#include <sdbusplus/message.hpp>
11
Patrick Venturedace6802018-11-01 16:52:10 -070012#include <map>
13#include <memory>
Patrick Venturedace6802018-11-01 16:52:10 -070014#include <string>
15
Gunnar Mills835dfb82017-07-26 16:15:21 -050016namespace phosphor
17{
18namespace gpio
19{
20
21/* Need a custom deleter for freeing up sd_event */
22struct EventDeleter
23{
24 void operator()(sd_event* event) const
25 {
George Liu9b4c6cf2023-08-03 11:01:27 +080026 sd_event_unref(event);
Gunnar Mills835dfb82017-07-26 16:15:21 -050027 }
28};
29using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
30
31/* Need a custom deleter for freeing up sd_event_source */
32struct EventSourceDeleter
33{
34 void operator()(sd_event_source* eventSource) const
35 {
George Liu9b4c6cf2023-08-03 11:01:27 +080036 sd_event_source_unref(eventSource);
Gunnar Mills835dfb82017-07-26 16:15:21 -050037 }
38};
39using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;
40
41/* Need a custom deleter for freeing up evdev struct */
42struct FreeEvDev
43{
44 void operator()(struct libevdev* device) const
45 {
46 libevdev_free(device);
47 }
48};
49using EvdevPtr = std::unique_ptr<struct libevdev, FreeEvDev>;
50
51/** @class Evdev
52 * @brief Responsible for catching GPIO state changes conditions and taking
53 * actions
54 */
55class Evdev
56{
Patrick Venturedace6802018-11-01 16:52:10 -070057 using Property = std::string;
Patrick Williams3ce88a72020-06-03 06:02:48 -050058 using Value = std::variant<bool, std::string>;
Patrick Venturedace6802018-11-01 16:52:10 -070059 // Association between property and its value
60 using PropertyMap = std::map<Property, Value>;
61 using Interface = std::string;
62 // Association between interface and the D-Bus property
63 using InterfaceMap = std::map<Interface, PropertyMap>;
64 using Object = sdbusplus::message::object_path;
65 // Association between object and the interface
66 using ObjectMap = std::map<Object, InterfaceMap>;
Gunnar Mills835dfb82017-07-26 16:15:21 -050067
Patrick Venturedace6802018-11-01 16:52:10 -070068 public:
69 Evdev() = delete;
70 ~Evdev() = default;
71 Evdev(const Evdev&) = delete;
72 Evdev& operator=(const Evdev&) = delete;
73 Evdev(Evdev&&) = delete;
74 Evdev& operator=(Evdev&&) = delete;
Gunnar Mills835dfb82017-07-26 16:15:21 -050075
Patrick Venturedace6802018-11-01 16:52:10 -070076 /** @brief Constructs Evdev object.
77 *
78 * @param[in] path - Device path to read for GPIO pin state
79 * @param[in] key - GPIO key to monitor
80 * @param[in] event - sd_event handler
81 * @param[in] handler - IO callback handler.
82 * @param[in] useEvDev - Whether to use EvDev to retrieve events
83 */
84 Evdev(const std::string& path, const unsigned int key, EventPtr& event,
85 sd_event_io_handler_t handler, bool useEvDev = true) :
Patrick Williams8377d592024-08-16 15:21:08 -040086 path(path), key(key), event(event), callbackHandler(handler),
87 fd(openDevice())
Gunnar Mills835dfb82017-07-26 16:15:21 -050088
Patrick Venturedace6802018-11-01 16:52:10 -070089 {
90 if (useEvDev)
Gunnar Mills835dfb82017-07-26 16:15:21 -050091 {
Patrick Venturedace6802018-11-01 16:52:10 -070092 // If we are asked to use EvDev, do that initialization.
93 initEvDev();
Gunnar Mills835dfb82017-07-26 16:15:21 -050094 }
95
Patrick Venturedace6802018-11-01 16:52:10 -070096 // Register callback handler when FD has some data
97 registerCallback();
98 }
Gunnar Mills835dfb82017-07-26 16:15:21 -050099
Patrick Venturedace6802018-11-01 16:52:10 -0700100 protected:
101 /** @brief Device path to read for GPIO pin state */
102 const std::string path;
Gunnar Mills835dfb82017-07-26 16:15:21 -0500103
Patrick Venturedace6802018-11-01 16:52:10 -0700104 /** @brief GPIO key to monitor */
105 const unsigned int key;
Gunnar Mills835dfb82017-07-26 16:15:21 -0500106
Patrick Venturedace6802018-11-01 16:52:10 -0700107 /** @brief Event structure */
108 EvdevPtr devicePtr;
Gunnar Mills835dfb82017-07-26 16:15:21 -0500109
Patrick Venturedace6802018-11-01 16:52:10 -0700110 /** @brief Monitor to sd_event */
111 EventPtr& event;
Gunnar Mills835dfb82017-07-26 16:15:21 -0500112
Patrick Venturedace6802018-11-01 16:52:10 -0700113 /** @brief Callback handler when the FD has some data */
114 sd_event_io_handler_t callbackHandler;
Gunnar Mills835dfb82017-07-26 16:15:21 -0500115
Patrick Venturedace6802018-11-01 16:52:10 -0700116 /** @brief event source */
117 EventSourcePtr eventSource;
Gunnar Mills835dfb82017-07-26 16:15:21 -0500118
Patrick Venturedace6802018-11-01 16:52:10 -0700119 /** @brief Opens the device and populates the descriptor */
120 int openDevice();
Gunnar Mills835dfb82017-07-26 16:15:21 -0500121
Patrick Venturedace6802018-11-01 16:52:10 -0700122 /** @brief attaches FD to events and sets up callback handler */
123 void registerCallback();
Gunnar Mills835dfb82017-07-26 16:15:21 -0500124
Patrick Venturedace6802018-11-01 16:52:10 -0700125 /** @brief File descriptor manager */
126 FileDescriptor fd;
127
128 /** @brief Initializes evdev handle with the fd */
129 void initEvDev();
Gunnar Mills835dfb82017-07-26 16:15:21 -0500130};
131
132} // namespace gpio
133} // namespace phosphor