xref: /openbmc/phosphor-gpio-monitor/presence/main.cpp (revision 206f0040985e27a0651a9164d7958bf347142a31)
1 #include "argument.hpp"
2 #include "gpio_presence.hpp"
3 
4 #include <systemd/sd-event.h>
5 
6 #include <iostream>
7 #include <phosphor-logging/log.hpp>
8 
9 using namespace phosphor::logging;
10 using namespace phosphor::gpio;
11 using namespace phosphor::gpio::presence;
12 
13 /**
14  * Pulls out the path,device pairs from the string
15  * passed in
16  *
17  * @param[in] driverString - space separated path,device pairs
18  * @param[out] drivers - vector of device,path tuples filled in
19  *                       from driverString
20  *
21  * @return int - 0 if successful, < 0 else
22  */
23 static int getDrivers(const std::string& driverString,
24                       std::vector<Driver>& drivers)
25 {
26     std::istringstream stream{driverString};
27 
28     while (true)
29     {
30         std::string entry;
31 
32         // Extract each path,device pair
33         stream >> entry;
34 
35         if (entry.empty())
36         {
37             break;
38         }
39 
40         // Extract the path and device and save them
41         auto pos = entry.rfind(',');
42         if (pos != std::string::npos)
43         {
44             auto path = entry.substr(0, pos);
45             auto device = entry.substr(pos + 1);
46 
47             drivers.emplace_back(device, path);
48         }
49         else
50         {
51             std::cerr << "Invalid path,device combination: " << entry << "\n";
52             return -1;
53         }
54     }
55 
56     return 0;
57 }
58 
59 int main(int argc, char* argv[])
60 {
61     auto options = ArgumentParser(argc, argv);
62 
63     auto inventory = options["inventory"];
64     auto key = options["key"];
65     auto path = options["path"];
66     auto drivers = options["drivers"];
67     auto ifaces = options["extra-ifaces"];
68     if (argc < 4)
69     {
70         std::cerr << "Too few arguments\n";
71         options.usage(argv);
72     }
73 
74     if (inventory == ArgumentParser::emptyString)
75     {
76         std::cerr << "Inventory argument required\n";
77         options.usage(argv);
78     }
79 
80     if (key == ArgumentParser::emptyString)
81     {
82         std::cerr << "GPIO key argument required\n";
83         options.usage(argv);
84     }
85 
86     if (path == ArgumentParser::emptyString)
87     {
88         std::cerr << "Device path argument required\n";
89         options.usage(argv);
90     }
91 
92     std::vector<Driver> driverList;
93 
94     // Driver list is optional
95     if (drivers != ArgumentParser::emptyString)
96     {
97         if (getDrivers(drivers, driverList) < 0)
98         {
99             options.usage(argv);
100         }
101     }
102 
103     std::vector<Interface> ifaceList;
104 
105     // Extra interfaces list is optional
106     if (ifaces != ArgumentParser::emptyString)
107     {
108         std::stringstream ss(ifaces);
109         Interface iface;
110         while (std::getline(ss, iface, ','))
111         {
112             ifaceList.push_back(iface);
113         }
114     }
115 
116     auto bus = sdbusplus::bus::new_default();
117     auto rc = 0;
118     sd_event* event = nullptr;
119     rc = sd_event_default(&event);
120     if (rc < 0)
121     {
122         log<level::ERR>("Error creating a default sd_event handler");
123         return rc;
124     }
125     EventPtr eventP{event};
126     event = nullptr;
127 
128     auto name = options["name"];
129     Presence presence(bus, inventory, path, std::stoul(key), name, eventP,
130                       driverList, ifaceList);
131 
132     while (true)
133     {
134         // -1 denotes wait forever
135         rc = sd_event_run(eventP.get(), (uint64_t)-1);
136         if (rc < 0)
137         {
138             log<level::ERR>("Failure in processing request",
139                             entry("ERROR=%s", strerror(-rc)));
140             break;
141         }
142     }
143     return rc;
144 }
145