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