blob: 271f9a79738a6ed6f973c4c13b68b1cbeebd3e85 [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 Mills72639152017-06-22 15:06:21 -05004#include "gpio_presence.hpp"
5
Patrick Venturedace6802018-11-01 16:52:10 -07006#include <systemd/sd-event.h>
7
George Liu7d7cc9e2023-08-02 08:52:01 +08008#include <CLI/CLI.hpp>
George Liu2a8848c2023-08-01 13:49:28 +08009#include <phosphor-logging/lg2.hpp>
Patrick Venturedace6802018-11-01 16:52:10 -070010
Patrick Williams39084b42023-05-10 07:50:58 -050011#include <iostream>
12
Gunnar Mills72639152017-06-22 15:06:21 -050013using namespace phosphor::gpio;
Gunnar Mills5f101102017-06-29 13:07:39 -050014using namespace phosphor::gpio::presence;
Gunnar Mills72639152017-06-22 15:06:21 -050015
Matt Spinlerd5636b02017-09-01 14:00:19 -050016/**
17 * Pulls out the path,device pairs from the string
18 * passed in
19 *
20 * @param[in] driverString - space separated path,device pairs
21 * @param[out] drivers - vector of device,path tuples filled in
22 * from driverString
23 *
24 * @return int - 0 if successful, < 0 else
25 */
Patrick Venture3c4a23e2018-10-14 14:26:35 -070026static int getDrivers(const std::string& driverString,
Matt Spinlerd5636b02017-09-01 14:00:19 -050027 std::vector<Driver>& drivers)
28{
29 std::istringstream stream{driverString};
30
31 while (true)
32 {
33 std::string entry;
34
Patrick Venturedace6802018-11-01 16:52:10 -070035 // Extract each path,device pair
Matt Spinlerd5636b02017-09-01 14:00:19 -050036 stream >> entry;
37
38 if (entry.empty())
39 {
40 break;
41 }
42
Patrick Venturedace6802018-11-01 16:52:10 -070043 // Extract the path and device and save them
Matt Spinlerd5636b02017-09-01 14:00:19 -050044 auto pos = entry.rfind(',');
45 if (pos != std::string::npos)
46 {
47 auto path = entry.substr(0, pos);
48 auto device = entry.substr(pos + 1);
49
Patrick Williams162bd712023-06-01 09:19:10 -050050 drivers.emplace_back(std::move(device), std::move(path));
Matt Spinlerd5636b02017-09-01 14:00:19 -050051 }
52 else
53 {
George Liu2a8848c2023-08-01 13:49:28 +080054 lg2::error("Invalid path,device combination: {ENTRY}", "ENTRY",
55 entry);
Matt Spinlerd5636b02017-09-01 14:00:19 -050056 return -1;
57 }
58 }
59
60 return 0;
61}
62
George Liu7d7cc9e2023-08-02 08:52:01 +080063int main(int argc, char** argv)
Gunnar Mills72639152017-06-22 15:06:21 -050064{
George Liu7d7cc9e2023-08-02 08:52:01 +080065 CLI::App app{"Monitor gpio presence status"};
Gunnar Mills72639152017-06-22 15:06:21 -050066
George Liu7d7cc9e2023-08-02 08:52:01 +080067 std::string path{};
68 std::string key{};
69 std::string name{};
70 std::string inventory{};
71 std::string drivers{};
72 std::string ifaces{};
73
74 /* Add an input option */
75 app.add_option(
76 "-p,--path", path,
77 " Path of device to read for GPIO pin state to determine presence of inventory item")
78 ->required();
79 app.add_option("-k,--key", key, "Input GPIO key number")->required();
80 app.add_option("-n,--name", name, "Pretty name of the inventory item")
81 ->required();
82 app.add_option("-i,--inventory", inventory,
83 "Object path under inventory that will be created")
84 ->required();
85 app.add_option(
George Liuc78e23d2023-08-10 15:49:07 +080086 "-d,--drivers", drivers,
87 "List of drivers to bind when card is added and unbind when card is removed\n"
88 "Format is a space separated list of path,device pairs.\n"
89 "For example: /sys/bus/i2c/drivers/some-driver,3-0068")
90 ->expected(0, 1);
George Liu7d7cc9e2023-08-02 08:52:01 +080091 app.add_option(
George Liuc78e23d2023-08-10 15:49:07 +080092 "-e,--extra-ifaces", ifaces,
93 "List of interfaces to associate to inventory item\n"
94 "Format is a comma separated list of interfaces.\n"
95 "For example: /xyz/openbmc_project/.../1,/xyz/openbmc_project/.../2")
96 ->expected(0, 1);
George Liu7d7cc9e2023-08-02 08:52:01 +080097
98 /* Parse input parameter */
99 try
Gunnar Mills72639152017-06-22 15:06:21 -0500100 {
George Liu7d7cc9e2023-08-02 08:52:01 +0800101 app.parse(argc, argv);
Gunnar Mills72639152017-06-22 15:06:21 -0500102 }
George Liu7d7cc9e2023-08-02 08:52:01 +0800103 catch (const CLI::Error& e)
Gunnar Mills72639152017-06-22 15:06:21 -0500104 {
George Liu7d7cc9e2023-08-02 08:52:01 +0800105 return app.exit(e);
Gunnar Mills72639152017-06-22 15:06:21 -0500106 }
Gunnar Mills80292bb2017-07-05 16:34:51 -0500107
Matt Spinler902d1c32017-09-01 11:03:02 -0500108 std::vector<Driver> driverList;
109
Patrick Venturedace6802018-11-01 16:52:10 -0700110 // Driver list is optional
George Liu7d7cc9e2023-08-02 08:52:01 +0800111 if (!drivers.empty())
Matt Spinlerd5636b02017-09-01 14:00:19 -0500112 {
113 if (getDrivers(drivers, driverList) < 0)
114 {
George Liu7d7cc9e2023-08-02 08:52:01 +0800115 lg2::error("Failed to parser drivers: {DRIVERS}", "DRIVERS",
116 drivers);
117 return -1;
Matt Spinlerd5636b02017-09-01 14:00:19 -0500118 }
119 }
Matt Spinler902d1c32017-09-01 11:03:02 -0500120
Anthony Wilson206f0042019-05-02 00:02:23 -0500121 std::vector<Interface> ifaceList;
122
123 // Extra interfaces list is optional
George Liu7d7cc9e2023-08-02 08:52:01 +0800124 if (!ifaces.empty())
Anthony Wilson206f0042019-05-02 00:02:23 -0500125 {
126 std::stringstream ss(ifaces);
127 Interface iface;
128 while (std::getline(ss, iface, ','))
129 {
130 ifaceList.push_back(iface);
131 }
132 }
133
Gunnar Mills80292bb2017-07-05 16:34:51 -0500134 auto bus = sdbusplus::bus::new_default();
Gunnar Mills765725e2017-07-06 14:17:44 -0500135 auto rc = 0;
136 sd_event* event = nullptr;
137 rc = sd_event_default(&event);
138 if (rc < 0)
139 {
George Liu2a8848c2023-08-01 13:49:28 +0800140 lg2::error("Error creating a default sd_event handler");
Gunnar Mills765725e2017-07-06 14:17:44 -0500141 return rc;
142 }
143 EventPtr eventP{event};
144 event = nullptr;
Gunnar Mills72639152017-06-22 15:06:21 -0500145
Patrick Venturedace6802018-11-01 16:52:10 -0700146 Presence presence(bus, inventory, path, std::stoul(key), name, eventP,
Anthony Wilson206f0042019-05-02 00:02:23 -0500147 driverList, ifaceList);
Gunnar Mills765725e2017-07-06 14:17:44 -0500148
149 while (true)
150 {
151 // -1 denotes wait forever
Patrick Venturedace6802018-11-01 16:52:10 -0700152 rc = sd_event_run(eventP.get(), (uint64_t)-1);
Gunnar Mills765725e2017-07-06 14:17:44 -0500153 if (rc < 0)
154 {
George Liu2a8848c2023-08-01 13:49:28 +0800155 lg2::error("Failure in processing request: {RC}", "RC", rc);
Gunnar Mills765725e2017-07-06 14:17:44 -0500156 break;
157 }
158 }
159 return rc;
Gunnar Mills72639152017-06-22 15:06:21 -0500160}