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