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