blob: 4b631d94fca89046f17b4fa73af88927c5c19474 [file] [log] [blame]
/**
* Copyright © 2019 Facebook
* Copyright © 2023 9elements GmbH
*
* 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_presence.hpp"
#include <CLI/CLI.hpp>
#include <boost/asio/io_context.hpp>
#include <nlohmann/json.hpp>
#include <phosphor-logging/lg2.hpp>
#include <fstream>
namespace phosphor
{
namespace gpio
{
const std::map<std::string, int> biasMap = {
/**< Set bias as is. */
{"AS_IS", 0},
/**< Disable bias. */
{"DISABLE", GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE},
/**< Enable pull-up. */
{"PULL_UP", GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP},
/**< Enable pull-down. */
{"PULL_DOWN", GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN}};
}
} // namespace phosphor
int main(int argc, char** argv)
{
boost::asio::io_context io;
CLI::App app{"Monitor gpio presence status"};
std::string gpioFileName;
/* Add an input option */
app.add_option("-c,--config", gpioFileName, "Name of config json file")
->required()
->check(CLI::ExistingFile);
/* Parse input parameter */
try
{
app.parse(argc, argv);
}
catch (const CLI::Error& e)
{
return app.exit(e);
}
/* Get list of gpio config details from json file */
std::ifstream file(gpioFileName);
if (!file)
{
lg2::error("Failed to open config file: {FILE}", "FILE", gpioFileName);
return -1;
}
nlohmann::json gpioMonObj;
file >> gpioMonObj;
file.close();
std::vector<phosphor::gpio::GpioPresence> gpios;
for (auto& obj : gpioMonObj)
{
/* GPIO Line message */
std::string lineMsg = "GPIO Line ";
/* GPIO line */
gpiod_line* line = NULL;
/* GPIO line configuration, default to monitor both edge */
struct gpiod_line_request_config config
{
"gpio_monitor", GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES, 0
};
/* Pretty name of the inventory object */
std::string name;
/* Object path under inventory that will be created */
std::string inventory;
/* List of interfaces to associate to inventory item */
std::vector<std::string> extraInterfaces;
if (obj.find("LineName") == obj.end())
{
/* If there is no line Name defined then gpio num nd chip
* id must be defined. GpioNum is integer mapping to the
* GPIO key configured by the kernel
*/
if (obj.find("GpioNum") == obj.end() ||
obj.find("ChipId") == obj.end())
{
lg2::error("Failed to find line name or gpio number: {FILE}",
"FILE", gpioFileName);
return -1;
}
std::string chipIdStr = obj["ChipId"].get<std::string>();
int gpioNum = obj["GpioNum"].get<int>();
lineMsg += chipIdStr + " " + std::to_string(gpioNum);
/* Get the GPIO line */
line = gpiod_line_get(chipIdStr.c_str(), gpioNum);
}
else
{
/* Find the GPIO line */
std::string lineName = obj["LineName"].get<std::string>();
lineMsg += lineName;
line = gpiod_line_find(lineName.c_str());
}
if (line == NULL)
{
lg2::error("Failed to find the {GPIO}", "GPIO", lineMsg);
return -1;
}
/* Parse out inventory argument. */
if (obj.find("Inventory") == obj.end())
{
lg2::error("{GPIO}: Inventory path not specified", "GPIO", lineMsg);
return -1;
}
else
{
inventory = obj["Inventory"].get<std::string>();
}
if (obj.find("Name") == obj.end())
{
lg2::error("{GPIO}: Name path not specified", "GPIO", lineMsg);
return -1;
}
else
{
name = obj["Name"].get<std::string>();
}
/* Parse optional bias */
if (obj.find("Bias") != obj.end())
{
std::string biasName = obj["Bias"].get<std::string>();
auto findBias = phosphor::gpio::biasMap.find(biasName);
if (findBias == phosphor::gpio::biasMap.end())
{
lg2::error("{GPIO}: Bias unknown: {BIAS}", "GPIO", lineMsg,
"BIAS", biasName);
return -1;
}
config.flags = findBias->second;
}
/* Parse optional active level */
if (obj.find("ActiveLow") != obj.end() && obj["ActiveLow"].get<bool>())
{
config.flags |= GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW;
}
/* Parse optional extra interfaces */
if (obj.find("ExtraInterfaces") != obj.end())
{
obj.at("ExtraInterfaces").get_to(extraInterfaces);
}
/* Create a monitor object and let it do all the rest */
gpios.push_back(phosphor::gpio::GpioPresence(
line, config, io, inventory, extraInterfaces, name, lineMsg));
}
io.run();
return 0;
}