blob: 4b631d94fca89046f17b4fa73af88927c5c19474 [file] [log] [blame]
Patrick Rudolph46a9a5b2023-08-10 18:32:05 +02001/**
2 * Copyright © 2019 Facebook
3 * Copyright © 2023 9elements GmbH
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "gpio_presence.hpp"
19
20#include <CLI/CLI.hpp>
21#include <boost/asio/io_context.hpp>
22#include <nlohmann/json.hpp>
23#include <phosphor-logging/lg2.hpp>
24
25#include <fstream>
26
27namespace phosphor
28{
29namespace gpio
30{
31
32const std::map<std::string, int> biasMap = {
33 /**< Set bias as is. */
34 {"AS_IS", 0},
35 /**< Disable bias. */
36 {"DISABLE", GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE},
37 /**< Enable pull-up. */
38 {"PULL_UP", GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP},
39 /**< Enable pull-down. */
40 {"PULL_DOWN", GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN}};
41}
42} // namespace phosphor
43
44int main(int argc, char** argv)
45{
46 boost::asio::io_context io;
47
48 CLI::App app{"Monitor gpio presence status"};
49
50 std::string gpioFileName;
51
52 /* Add an input option */
53 app.add_option("-c,--config", gpioFileName, "Name of config json file")
54 ->required()
55 ->check(CLI::ExistingFile);
56
57 /* Parse input parameter */
58 try
59 {
60 app.parse(argc, argv);
61 }
62 catch (const CLI::Error& e)
63 {
64 return app.exit(e);
65 }
66
67 /* Get list of gpio config details from json file */
68 std::ifstream file(gpioFileName);
69 if (!file)
70 {
71 lg2::error("Failed to open config file: {FILE}", "FILE", gpioFileName);
72 return -1;
73 }
74
75 nlohmann::json gpioMonObj;
76 file >> gpioMonObj;
77 file.close();
78
79 std::vector<phosphor::gpio::GpioPresence> gpios;
80
81 for (auto& obj : gpioMonObj)
82 {
83 /* GPIO Line message */
84 std::string lineMsg = "GPIO Line ";
85
86 /* GPIO line */
87 gpiod_line* line = NULL;
88
89 /* GPIO line configuration, default to monitor both edge */
90 struct gpiod_line_request_config config
91 {
92 "gpio_monitor", GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES, 0
93 };
94
95 /* Pretty name of the inventory object */
96 std::string name;
97
98 /* Object path under inventory that will be created */
99 std::string inventory;
100
101 /* List of interfaces to associate to inventory item */
102 std::vector<std::string> extraInterfaces;
103
104 if (obj.find("LineName") == obj.end())
105 {
106 /* If there is no line Name defined then gpio num nd chip
107 * id must be defined. GpioNum is integer mapping to the
108 * GPIO key configured by the kernel
109 */
110 if (obj.find("GpioNum") == obj.end() ||
111 obj.find("ChipId") == obj.end())
112 {
113 lg2::error("Failed to find line name or gpio number: {FILE}",
114 "FILE", gpioFileName);
115 return -1;
116 }
117
118 std::string chipIdStr = obj["ChipId"].get<std::string>();
119 int gpioNum = obj["GpioNum"].get<int>();
120
121 lineMsg += chipIdStr + " " + std::to_string(gpioNum);
122
123 /* Get the GPIO line */
124 line = gpiod_line_get(chipIdStr.c_str(), gpioNum);
125 }
126 else
127 {
128 /* Find the GPIO line */
129 std::string lineName = obj["LineName"].get<std::string>();
130 lineMsg += lineName;
131 line = gpiod_line_find(lineName.c_str());
132 }
133
134 if (line == NULL)
135 {
136 lg2::error("Failed to find the {GPIO}", "GPIO", lineMsg);
137 return -1;
138 }
139
140 /* Parse out inventory argument. */
141 if (obj.find("Inventory") == obj.end())
142 {
143 lg2::error("{GPIO}: Inventory path not specified", "GPIO", lineMsg);
144 return -1;
145 }
146 else
147 {
148 inventory = obj["Inventory"].get<std::string>();
149 }
150
151 if (obj.find("Name") == obj.end())
152 {
153 lg2::error("{GPIO}: Name path not specified", "GPIO", lineMsg);
154 return -1;
155 }
156 else
157 {
158 name = obj["Name"].get<std::string>();
159 }
160
161 /* Parse optional bias */
162 if (obj.find("Bias") != obj.end())
163 {
164 std::string biasName = obj["Bias"].get<std::string>();
165 auto findBias = phosphor::gpio::biasMap.find(biasName);
166 if (findBias == phosphor::gpio::biasMap.end())
167 {
168 lg2::error("{GPIO}: Bias unknown: {BIAS}", "GPIO", lineMsg,
169 "BIAS", biasName);
170 return -1;
171 }
172
173 config.flags = findBias->second;
174 }
175
176 /* Parse optional active level */
177 if (obj.find("ActiveLow") != obj.end() && obj["ActiveLow"].get<bool>())
178 {
179 config.flags |= GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW;
180 }
181
182 /* Parse optional extra interfaces */
183 if (obj.find("ExtraInterfaces") != obj.end())
184 {
185 obj.at("ExtraInterfaces").get_to(extraInterfaces);
186 }
187
188 /* Create a monitor object and let it do all the rest */
189 gpios.push_back(phosphor::gpio::GpioPresence(
190 line, config, io, inventory, extraInterfaces, name, lineMsg));
191 }
192 io.run();
193
194 return 0;
195}