1 #include "argument.hpp"
2 #include "interfaces/internal_interface.hpp"
3 
4 #include <phosphor-logging/lg2.hpp>
5 #include <sdbusplus/bus.hpp>
6 
7 #include <filesystem>
8 
9 static constexpr auto devPath = "/sys/class/leds/";
10 
11 std::string rootPathVerify(std::string path)
12 {
13     if (!path.starts_with(devPath))
14     {
15         lg2::error("Invalid sys path - {PATH}", "PATH", path);
16         throw std::invalid_argument("Invalid argument");
17     }
18 
19     if (!std::filesystem::exists(path))
20     {
21         lg2::error("Path does not exist - {PATH}", "PATH", path);
22         throw std::invalid_argument("Invalid argument");
23     }
24 
25     std::string led = path.substr(strlen(devPath));
26 
27     // path can contain multiple path separators, e.g.
28     // /sys/class/leds//identify
29 
30     while (led.starts_with("/"))
31     {
32         led = led.substr(1);
33     }
34 
35     return led;
36 }
37 
38 void addLed(std::string ledName)
39 {
40     lg2::debug("Adding LED name - {LEDNAME}", "LEDNAME", ledName);
41     try
42     {
43         auto bus = sdbusplus::bus::new_default();
44         auto method = bus.new_method_call(busName, ledPath, internalInterface,
45                                           ledAddMethod);
46 
47         method.append(ledName);
48         bus.call(method);
49     }
50     catch (const std::exception& e)
51     {
52         lg2::error("Unable to add LED name - {LEDNAME}", "LEDNAME", ledName);
53         throw e;
54     }
55 }
56 
57 /* Each LED udev event will trigger systemd service (sysfs-led@.service)
58  * Systemd service will invoke the binary (add-led-action) by passing LED
59  * name as argument.
60  *
61  * Usage: /usr/libexec/phosphor-led-sysfs/add-led-action [options]
62  * Options:
63  *  --help           Print this menu
64  *  --path=<path>    absolute path of LED in sysfs; like /sys/class/leds/<name>
65  *
66  */
67 
68 int main(int argc, char* argv[])
69 {
70     // Read arguments.
71     auto options = phosphor::led::ArgumentParser(argc, argv);
72 
73     // Parse out Path argument.
74     const auto& path = options["path"];
75 
76     if (path.empty())
77     {
78         phosphor::led::ArgumentParser::usage(argv);
79 
80         lg2::error("Argument parser error : Path not specified");
81         throw std::invalid_argument("Invalid argument");
82     }
83 
84     std::string name = rootPathVerify(path);
85 
86     addLed(name);
87 
88     return 0;
89 }
90