blob: e6ef782a0d8384891a6c4be4f74da101f8e085f9 [file] [log] [blame]
Christopher Meis75ff1672025-09-23 11:40:06 +02001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Vijay Khemka939a6432019-10-09 17:45:45 -07003
4#include "gpioMon.hpp"
5
6#include <CLI/CLI.hpp>
Ed Tanous854404e2023-02-28 13:37:51 -08007#include <boost/asio/io_context.hpp>
Vijay Khemka939a6432019-10-09 17:45:45 -07008#include <nlohmann/json.hpp>
George Liu2a8848c2023-08-01 13:49:28 +08009#include <phosphor-logging/lg2.hpp>
Vijay Khemka939a6432019-10-09 17:45:45 -070010
Patrick Williams39084b42023-05-10 07:50:58 -050011#include <fstream>
12
Vijay Khemka939a6432019-10-09 17:45:45 -070013namespace phosphor
14{
15namespace gpio
16{
17
18std::map<std::string, int> polarityMap = {
19 /**< Only watch falling edge events. */
20 {"FALLING", GPIOD_LINE_REQUEST_EVENT_FALLING_EDGE},
21 /**< Only watch rising edge events. */
22 {"RISING", GPIOD_LINE_REQUEST_EVENT_RISING_EDGE},
23 /**< Monitor both types of events. */
24 {"BOTH", GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES}};
25
26}
27} // namespace phosphor
28
29int main(int argc, char** argv)
30{
Ed Tanous854404e2023-02-28 13:37:51 -080031 boost::asio::io_context io;
Vijay Khemka939a6432019-10-09 17:45:45 -070032
33 CLI::App app{"Monitor GPIO line for requested state change"};
34
35 std::string gpioFileName;
36
37 /* Add an input option */
38 app.add_option("-c,--config", gpioFileName, "Name of config json file")
39 ->required()
40 ->check(CLI::ExistingFile);
41
42 /* Parse input parameter */
43 try
44 {
45 app.parse(argc, argv);
46 }
Patrick Williams67554142021-10-06 13:00:15 -050047 catch (const CLI::Error& e)
Vijay Khemka939a6432019-10-09 17:45:45 -070048 {
49 return app.exit(e);
50 }
51
52 /* Get list of gpio config details from json file */
53 std::ifstream file(gpioFileName);
54 if (!file)
55 {
George Liu2a8848c2023-08-01 13:49:28 +080056 lg2::error("GPIO monitor config file not found: {FILE}", "FILE",
57 gpioFileName);
Vijay Khemka939a6432019-10-09 17:45:45 -070058 return -1;
59 }
60
61 nlohmann::json gpioMonObj;
62 file >> gpioMonObj;
63 file.close();
64
65 std::vector<std::unique_ptr<phosphor::gpio::GpioMonitor>> gpios;
66
67 for (auto& obj : gpioMonObj)
68 {
Vijay Khemka939a6432019-10-09 17:45:45 -070069 /* GPIO Line message */
70 std::string lineMsg = "GPIO Line ";
71
72 /* GPIO line */
Jayanth Othayothcf33c592024-12-18 07:27:03 -060073 gpiod_line* line = nullptr;
Vijay Khemka939a6432019-10-09 17:45:45 -070074
Vijay Khemka939a6432019-10-09 17:45:45 -070075 /* GPIO line configuration, default to monitor both edge */
Patrick Williams1c888032024-12-18 11:21:41 -050076 struct gpiod_line_request_config config{
77 "gpio_monitor", GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES, 0};
Vijay Khemka939a6432019-10-09 17:45:45 -070078
79 /* flag to monitor */
80 bool flag = false;
81
82 /* target to start */
83 std::string target;
84
Delphine CC Chiua66ac0f2023-01-09 17:12:23 +080085 /* multi targets to start */
86 std::map<std::string, std::vector<std::string>> targets;
87
Vijay Khemka939a6432019-10-09 17:45:45 -070088 if (obj.find("LineName") == obj.end())
89 {
90 /* If there is no line Name defined then gpio num nd chip
91 * id must be defined. GpioNum is integer mapping to the
92 * GPIO key configured by the kernel
93 */
94 if (obj.find("GpioNum") == obj.end() ||
95 obj.find("ChipId") == obj.end())
96 {
George Liu2a8848c2023-08-01 13:49:28 +080097 lg2::error("Failed to find line name or gpio number: {FILE}",
98 "FILE", gpioFileName);
Vijay Khemka939a6432019-10-09 17:45:45 -070099 return -1;
100 }
101
102 std::string chipIdStr = obj["ChipId"];
103 int gpioNum = obj["GpioNum"];
104
105 lineMsg += std::to_string(gpioNum);
106
107 /* Get the GPIO line */
108 line = gpiod_line_get(chipIdStr.c_str(), gpioNum);
109 }
110 else
111 {
112 /* Find the GPIO line */
113 std::string lineName = obj["LineName"];
114 lineMsg += lineName;
115 line = gpiod_line_find(lineName.c_str());
116 }
117
Jayanth Othayothcf33c592024-12-18 07:27:03 -0600118 if (line == nullptr)
Vijay Khemka939a6432019-10-09 17:45:45 -0700119 {
Yang Chen38cd74c2024-11-07 14:42:24 +0800120 lg2::error("Failed to find the {GPIO}", "GPIO", lineMsg);
121 continue;
Vijay Khemka939a6432019-10-09 17:45:45 -0700122 }
123
124 /* Get event to be monitored, if it is not defined then
125 * Both rising falling edge will be monitored.
126 */
127 if (obj.find("EventMon") != obj.end())
128 {
129 std::string eventStr = obj["EventMon"];
130 auto findEvent = phosphor::gpio::polarityMap.find(eventStr);
131 if (findEvent == phosphor::gpio::polarityMap.end())
132 {
George Liu2a8848c2023-08-01 13:49:28 +0800133 lg2::error("{GPIO}: event missing: {EVENT}", "GPIO", lineMsg,
134 "EVENT", eventStr);
Vijay Khemka939a6432019-10-09 17:45:45 -0700135 return -1;
136 }
137
138 config.request_type = findEvent->second;
139 }
140
141 /* Get flag if monitoring needs to continue after first event */
142 if (obj.find("Continue") != obj.end())
143 {
144 flag = obj["Continue"];
145 }
146
147 /* Parse out target argument. It is fine if the user does not
148 * pass this if they are not interested in calling into any target
149 * on meeting a condition.
150 */
151 if (obj.find("Target") != obj.end())
152 {
153 target = obj["Target"];
154 }
155
Delphine CC Chiua66ac0f2023-01-09 17:12:23 +0800156 /* Parse out the targets argument if multi-targets are needed.*/
157 if (obj.find("Targets") != obj.end())
158 {
159 obj.at("Targets").get_to(targets);
160 }
161
Vijay Khemka939a6432019-10-09 17:45:45 -0700162 /* Create a monitor object and let it do all the rest */
163 gpios.push_back(std::make_unique<phosphor::gpio::GpioMonitor>(
Delphine CC Chiua66ac0f2023-01-09 17:12:23 +0800164 line, config, io, target, targets, lineMsg, flag));
Vijay Khemka939a6432019-10-09 17:45:45 -0700165 }
166 io.run();
167
168 return 0;
169}