1 /** 2 * Copyright © 2016 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "config.h" 18 19 #include "argument.hpp" 20 #include "physical.hpp" 21 #include "sysfs.hpp" 22 23 #include <algorithm> 24 #include <iostream> 25 #include <string> 26 27 static void ExitWithError(const char* err, char** argv) 28 { 29 phosphor::led::ArgumentParser::usage(argv); 30 std::cerr << std::endl; 31 std::cerr << "ERROR: " << err << std::endl; 32 exit(-1); 33 } 34 35 int main(int argc, char** argv) 36 { 37 namespace fs = std::experimental::filesystem; 38 39 // Read arguments. 40 auto options = phosphor::led::ArgumentParser(argc, argv); 41 42 // Parse out Path argument. 43 auto path = std::move((options)["path"]); 44 if (path == phosphor::led::ArgumentParser::empty_string) 45 { 46 ExitWithError("Path not specified.", argv); 47 } 48 49 // If the LED has a hyphen in the name like: "one-two", then it gets passed 50 // as /one/two/ as opposed to /one-two to the service file. There is a 51 // change needed in systemd to solve this issue and hence putting in this 52 // work-around. 53 54 // Since this application always gets invoked as part of a udev rule, 55 // it is always guaranteed to get /sys/class/leds/one/two 56 // and we can go beyond leds/ to get the actual led name. 57 // Refer: systemd/systemd#5072 58 59 // On an error, this throws an exception and terminates. 60 auto name = path.substr(strlen(DEVPATH)); 61 62 // LED names may have a hyphen and that would be an issue for 63 // dbus paths and hence need to convert them to underscores. 64 std::replace(name.begin(), name.end(), '/', '-'); 65 path = DEVPATH + name; 66 67 // Convert to lowercase just in case some are not and that 68 // we follow lowercase all over 69 std::transform(name.begin(), name.end(), name.begin(), ::tolower); 70 71 // LED names may have a hyphen and that would be an issue for 72 // dbus paths and hence need to convert them to underscores. 73 std::replace(name.begin(), name.end(), '-', '_'); 74 75 // Unique bus name representing a single LED. 76 auto busName = std::string(BUSNAME) + '.' + name; 77 auto objPath = std::string(OBJPATH) + '/' + name; 78 79 // Get a handle to system dbus. 80 auto bus = sdbusplus::bus::new_default(); 81 82 // Add systemd object manager. 83 sdbusplus::server::manager::manager(bus, objPath.c_str()); 84 85 // Create the Physical LED objects for directing actions. 86 // Need to save this else sdbusplus destructor will wipe this off. 87 phosphor::led::SysfsLed sled{fs::path(path)}; 88 phosphor::led::Physical led(bus, objPath, sled); 89 90 /** @brief Claim the bus */ 91 bus.request_name(busName.c_str()); 92 93 /** @brief Wait for client requests */ 94 while (true) 95 { 96 // Handle dbus message / signals discarding unhandled 97 bus.process_discard(); 98 bus.wait(); 99 } 100 return 0; 101 } 102