xref: /openbmc/phosphor-gpio-monitor/presence/main.cpp (revision c78e23d6a61c863a57a516e6cbc197b59260c723)
17263915aSGunnar Mills #include "gpio_presence.hpp"
27263915aSGunnar Mills 
3dace680fSPatrick Venture #include <systemd/sd-event.h>
4dace680fSPatrick Venture 
57d7cc9e6SGeorge Liu #include <CLI/CLI.hpp>
62a8848c6SGeorge Liu #include <phosphor-logging/lg2.hpp>
7dace680fSPatrick Venture 
839084b4aSPatrick Williams #include <iostream>
939084b4aSPatrick Williams 
107263915aSGunnar Mills using namespace phosphor::gpio;
115f101103SGunnar Mills using namespace phosphor::gpio::presence;
127263915aSGunnar Mills 
13d5636b07SMatt Spinler /**
14d5636b07SMatt Spinler  * Pulls out the path,device pairs from the string
15d5636b07SMatt Spinler  * passed in
16d5636b07SMatt Spinler  *
17d5636b07SMatt Spinler  * @param[in] driverString - space separated path,device pairs
18d5636b07SMatt Spinler  * @param[out] drivers - vector of device,path tuples filled in
19d5636b07SMatt Spinler  *                       from driverString
20d5636b07SMatt Spinler  *
21d5636b07SMatt Spinler  * @return int - 0 if successful, < 0 else
22d5636b07SMatt Spinler  */
getDrivers(const std::string & driverString,std::vector<Driver> & drivers)233c4a23e7SPatrick Venture static int getDrivers(const std::string& driverString,
24d5636b07SMatt Spinler                       std::vector<Driver>& drivers)
25d5636b07SMatt Spinler {
26d5636b07SMatt Spinler     std::istringstream stream{driverString};
27d5636b07SMatt Spinler 
28d5636b07SMatt Spinler     while (true)
29d5636b07SMatt Spinler     {
30d5636b07SMatt Spinler         std::string entry;
31d5636b07SMatt Spinler 
32d5636b07SMatt Spinler         // Extract each path,device pair
33d5636b07SMatt Spinler         stream >> entry;
34d5636b07SMatt Spinler 
35d5636b07SMatt Spinler         if (entry.empty())
36d5636b07SMatt Spinler         {
37d5636b07SMatt Spinler             break;
38d5636b07SMatt Spinler         }
39d5636b07SMatt Spinler 
40d5636b07SMatt Spinler         // Extract the path and device and save them
41d5636b07SMatt Spinler         auto pos = entry.rfind(',');
42d5636b07SMatt Spinler         if (pos != std::string::npos)
43d5636b07SMatt Spinler         {
44d5636b07SMatt Spinler             auto path = entry.substr(0, pos);
45d5636b07SMatt Spinler             auto device = entry.substr(pos + 1);
46d5636b07SMatt Spinler 
47162bd710SPatrick Williams             drivers.emplace_back(std::move(device), std::move(path));
48d5636b07SMatt Spinler         }
49d5636b07SMatt Spinler         else
50d5636b07SMatt Spinler         {
512a8848c6SGeorge Liu             lg2::error("Invalid path,device combination: {ENTRY}", "ENTRY",
522a8848c6SGeorge Liu                        entry);
53d5636b07SMatt Spinler             return -1;
54d5636b07SMatt Spinler         }
55d5636b07SMatt Spinler     }
56d5636b07SMatt Spinler 
57d5636b07SMatt Spinler     return 0;
58d5636b07SMatt Spinler }
59d5636b07SMatt Spinler 
main(int argc,char ** argv)607d7cc9e6SGeorge Liu int main(int argc, char** argv)
617263915aSGunnar Mills {
627d7cc9e6SGeorge Liu     CLI::App app{"Monitor gpio presence status"};
637263915aSGunnar Mills 
647d7cc9e6SGeorge Liu     std::string path{};
657d7cc9e6SGeorge Liu     std::string key{};
667d7cc9e6SGeorge Liu     std::string name{};
677d7cc9e6SGeorge Liu     std::string inventory{};
687d7cc9e6SGeorge Liu     std::string drivers{};
697d7cc9e6SGeorge Liu     std::string ifaces{};
707d7cc9e6SGeorge Liu 
717d7cc9e6SGeorge Liu     /* Add an input option */
727d7cc9e6SGeorge Liu     app.add_option(
737d7cc9e6SGeorge Liu            "-p,--path", path,
747d7cc9e6SGeorge Liu            " Path of device to read for GPIO pin state to determine presence of inventory item")
757d7cc9e6SGeorge Liu         ->required();
767d7cc9e6SGeorge Liu     app.add_option("-k,--key", key, "Input GPIO key number")->required();
777d7cc9e6SGeorge Liu     app.add_option("-n,--name", name, "Pretty name of the inventory item")
787d7cc9e6SGeorge Liu         ->required();
797d7cc9e6SGeorge Liu     app.add_option("-i,--inventory", inventory,
807d7cc9e6SGeorge Liu                    "Object path under inventory that will be created")
817d7cc9e6SGeorge Liu         ->required();
827d7cc9e6SGeorge Liu     app.add_option(
837d7cc9e6SGeorge Liu            "-d,--drivers", drivers,
847d7cc9e6SGeorge Liu            "List of drivers to bind when card is added and unbind when card is removed\n"
857d7cc9e6SGeorge Liu            "Format is a space separated list of path,device pairs.\n"
86*c78e23d6SGeorge Liu            "For example: /sys/bus/i2c/drivers/some-driver,3-0068")
87*c78e23d6SGeorge Liu         ->expected(0, 1);
887d7cc9e6SGeorge Liu     app.add_option(
897d7cc9e6SGeorge Liu            "-e,--extra-ifaces", ifaces,
907d7cc9e6SGeorge Liu            "List of interfaces to associate to inventory item\n"
917d7cc9e6SGeorge Liu            "Format is a comma separated list of interfaces.\n"
92*c78e23d6SGeorge Liu            "For example: /xyz/openbmc_project/.../1,/xyz/openbmc_project/.../2")
93*c78e23d6SGeorge Liu         ->expected(0, 1);
947d7cc9e6SGeorge Liu 
957d7cc9e6SGeorge Liu     /* Parse input parameter */
967d7cc9e6SGeorge Liu     try
977263915aSGunnar Mills     {
987d7cc9e6SGeorge Liu         app.parse(argc, argv);
997263915aSGunnar Mills     }
1007d7cc9e6SGeorge Liu     catch (const CLI::Error& e)
1017263915aSGunnar Mills     {
1027d7cc9e6SGeorge Liu         return app.exit(e);
1037263915aSGunnar Mills     }
10480292bbeSGunnar Mills 
105902d1c37SMatt Spinler     std::vector<Driver> driverList;
106902d1c37SMatt Spinler 
107d5636b07SMatt Spinler     // Driver list is optional
1087d7cc9e6SGeorge Liu     if (!drivers.empty())
109d5636b07SMatt Spinler     {
110d5636b07SMatt Spinler         if (getDrivers(drivers, driverList) < 0)
111d5636b07SMatt Spinler         {
1127d7cc9e6SGeorge Liu             lg2::error("Failed to parser drivers: {DRIVERS}", "DRIVERS",
1137d7cc9e6SGeorge Liu                        drivers);
1147d7cc9e6SGeorge Liu             return -1;
115d5636b07SMatt Spinler         }
116d5636b07SMatt Spinler     }
117902d1c37SMatt Spinler 
118206f0040SAnthony Wilson     std::vector<Interface> ifaceList;
119206f0040SAnthony Wilson 
120206f0040SAnthony Wilson     // Extra interfaces list is optional
1217d7cc9e6SGeorge Liu     if (!ifaces.empty())
122206f0040SAnthony Wilson     {
123206f0040SAnthony Wilson         std::stringstream ss(ifaces);
124206f0040SAnthony Wilson         Interface iface;
125206f0040SAnthony Wilson         while (std::getline(ss, iface, ','))
126206f0040SAnthony Wilson         {
127206f0040SAnthony Wilson             ifaceList.push_back(iface);
128206f0040SAnthony Wilson         }
129206f0040SAnthony Wilson     }
130206f0040SAnthony Wilson 
13180292bbeSGunnar Mills     auto bus = sdbusplus::bus::new_default();
132765725e0SGunnar Mills     auto rc = 0;
133765725e0SGunnar Mills     sd_event* event = nullptr;
134765725e0SGunnar Mills     rc = sd_event_default(&event);
135765725e0SGunnar Mills     if (rc < 0)
136765725e0SGunnar Mills     {
1372a8848c6SGeorge Liu         lg2::error("Error creating a default sd_event handler");
138765725e0SGunnar Mills         return rc;
139765725e0SGunnar Mills     }
140765725e0SGunnar Mills     EventPtr eventP{event};
141765725e0SGunnar Mills     event = nullptr;
1427263915aSGunnar Mills 
143dace680fSPatrick Venture     Presence presence(bus, inventory, path, std::stoul(key), name, eventP,
144206f0040SAnthony Wilson                       driverList, ifaceList);
145765725e0SGunnar Mills 
146765725e0SGunnar Mills     while (true)
147765725e0SGunnar Mills     {
148765725e0SGunnar Mills         // -1 denotes wait forever
149765725e0SGunnar Mills         rc = sd_event_run(eventP.get(), (uint64_t)-1);
150765725e0SGunnar Mills         if (rc < 0)
151765725e0SGunnar Mills         {
1522a8848c6SGeorge Liu             lg2::error("Failure in processing request: {RC}", "RC", rc);
153765725e0SGunnar Mills             break;
154765725e0SGunnar Mills         }
155765725e0SGunnar Mills     }
156765725e0SGunnar Mills     return rc;
1577263915aSGunnar Mills }
158