blob: fd08c741d41a500f4ec00105a7396c608c18c8a4 [file] [log] [blame]
Vishwanatha Subbanna835571e2016-11-30 11:29:30 +05301/**
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
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +053017#include "physical.hpp"
Andrew Jeffery42e02d32018-05-24 13:34:05 +093018#include "sysfs.hpp"
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +093019
George Liueaa1c892023-08-03 16:19:51 +080020#include <CLI/CLI.hpp>
Alexander Soldatov97ddb722019-04-16 09:10:00 +030021#include <boost/algorithm/string.hpp>
George Liu61b90632020-06-22 10:55:13 +080022
23#include <algorithm>
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +093024#include <iostream>
25#include <string>
Vishwanatha Subbanna835571e2016-11-30 11:29:30 +053026
Alexander Soldatov97ddb722019-04-16 09:10:00 +030027struct LedDescr
28{
29 std::string devicename;
30 std::string color;
31 std::string function;
32};
33
34/** @brief parse LED name in sysfs
35 * Parse sysfs LED name in format "devicename:colour:function"
36 * or "devicename:colour" or "devicename" and sets corresponding
37 * fields in LedDescr struct.
38 *
39 * @param[in] name - LED name in sysfs
40 * @param[out] ledDescr - LED description
41 */
42void getLedDescr(const std::string& name, LedDescr& ledDescr)
43{
44 std::vector<std::string> words;
George Liueaa1c892023-08-03 16:19:51 +080045 // FIXME: https://bugs.llvm.org/show_bug.cgi?id=41141
46 // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks)
Alexander Soldatov97ddb722019-04-16 09:10:00 +030047 boost::split(words, name, boost::is_any_of(":"));
George Liueaa1c892023-08-03 16:19:51 +080048 // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
Alexander Soldatov97ddb722019-04-16 09:10:00 +030049 try
50 {
51 ledDescr.devicename = words.at(0);
52 ledDescr.color = words.at(1);
53 ledDescr.function = words.at(2);
54 }
55 catch (const std::out_of_range&)
56 {
57 return;
58 }
59}
60
61/** @brief generates LED DBus name from LED description
62 *
63 * @param[in] name - LED description
64 * @return - DBus LED name
65 */
66std::string getDbusName(const LedDescr& ledDescr)
67{
68 std::vector<std::string> words;
69 words.emplace_back(ledDescr.devicename);
70 if (!ledDescr.function.empty())
Andrew Jeffery20aef9a2023-02-06 10:41:07 +103071 {
Alexander Soldatov97ddb722019-04-16 09:10:00 +030072 words.emplace_back(ledDescr.function);
Andrew Jeffery20aef9a2023-02-06 10:41:07 +103073 }
Alexander Soldatov97ddb722019-04-16 09:10:00 +030074 if (!ledDescr.color.empty())
Andrew Jeffery20aef9a2023-02-06 10:41:07 +103075 {
Alexander Soldatov97ddb722019-04-16 09:10:00 +030076 words.emplace_back(ledDescr.color);
Andrew Jeffery20aef9a2023-02-06 10:41:07 +103077 }
Alexander Soldatov97ddb722019-04-16 09:10:00 +030078 return boost::join(words, "_");
79}
80
Vishwanatha Subbanna835571e2016-11-30 11:29:30 +053081int main(int argc, char** argv)
82{
George Liu45eba6f2021-05-18 14:32:20 +080083 namespace fs = std::filesystem;
Andrew Jefferye2dc00a2023-02-06 10:44:03 +103084 static constexpr auto busParent = "xyz.openbmc_project.LED.Controller";
85 static constexpr auto objParent = "/xyz/openbmc_project/led/physical";
86 static constexpr auto devParent = "/sys/class/leds/";
Andrew Jeffery42e02d32018-05-24 13:34:05 +093087
George Liueaa1c892023-08-03 16:19:51 +080088 CLI::App app{"Control and Drive the physical LEDs"};
Vishwanatha Subbanna835571e2016-11-30 11:29:30 +053089
George Liueaa1c892023-08-03 16:19:51 +080090 // Read arguments.
91 std::string path{};
92 app.add_option("-p,--path", path,
93 "absolute path of LED in sysfs; like /sys/class/leds/<name>")
94 ->required();
Andrew Jefferycb14f2d2023-02-06 14:19:37 +103095
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +053096 // Parse out Path argument.
George Liueaa1c892023-08-03 16:19:51 +080097 try
Vishwanatha Subbanna835571e2016-11-30 11:29:30 +053098 {
George Liueaa1c892023-08-03 16:19:51 +080099 app.parse(argc, argv);
Vishwanatha Subbanna835571e2016-11-30 11:29:30 +0530100 }
George Liueaa1c892023-08-03 16:19:51 +0800101 catch (const CLI::Error& e)
102 {
103 return app.exit(e);
104 }
Andrew Jeffery444ee362023-02-06 10:47:54 +1030105
Vishwanatha Subbannaf9de54b2017-05-25 21:06:33 +0530106 // If the LED has a hyphen in the name like: "one-two", then it gets passed
107 // as /one/two/ as opposed to /one-two to the service file. There is a
108 // change needed in systemd to solve this issue and hence putting in this
109 // work-around.
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530110
Vishwanatha Subbannaf9de54b2017-05-25 21:06:33 +0530111 // Since this application always gets invoked as part of a udev rule,
112 // it is always guaranteed to get /sys/class/leds/one/two
Alexander Soldatov97ddb722019-04-16 09:10:00 +0300113 // and we can go beyond leds/ to get the actual LED name.
Vishwanatha Subbannaf9de54b2017-05-25 21:06:33 +0530114 // Refer: systemd/systemd#5072
115
116 // On an error, this throws an exception and terminates.
Andrew Jefferye2dc00a2023-02-06 10:44:03 +1030117 auto name = path.substr(strlen(devParent));
Vishwanatha Subbannaf9de54b2017-05-25 21:06:33 +0530118
119 // LED names may have a hyphen and that would be an issue for
120 // dbus paths and hence need to convert them to underscores.
121 std::replace(name.begin(), name.end(), '/', '-');
Andrew Jefferye2dc00a2023-02-06 10:44:03 +1030122 path = devParent + name;
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530123
Vishwanatha Subbanna413fd342017-03-30 17:25:18 +0530124 // Convert to lowercase just in case some are not and that
125 // we follow lowercase all over
126 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
127
128 // LED names may have a hyphen and that would be an issue for
129 // dbus paths and hence need to convert them to underscores.
130 std::replace(name.begin(), name.end(), '-', '_');
131
Alexander Soldatov97ddb722019-04-16 09:10:00 +0300132 // Convert LED name in sysfs into DBus name
133 LedDescr ledDescr;
134 getLedDescr(name, ledDescr);
George Liueaa1c892023-08-03 16:19:51 +0800135
Alexander Soldatov97ddb722019-04-16 09:10:00 +0300136 name = getDbusName(ledDescr);
137
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530138 // Unique bus name representing a single LED.
Andrew Jefferye2dc00a2023-02-06 10:44:03 +1030139 auto busName = std::string(busParent) + '.' + name;
140 auto objPath = std::string(objParent) + '/' + name;
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530141
142 // Get a handle to system dbus.
Andrew Jefferycd3b05e2018-05-24 13:05:30 +0930143 auto bus = sdbusplus::bus::new_default();
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530144
Andrew Jefferyb754cf02023-02-06 11:54:12 +1030145 sdbusplus::server::manager_t manager{bus, objPath.c_str()};
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530146
147 // Create the Physical LED objects for directing actions.
148 // Need to save this else sdbusplus destructor will wipe this off.
Andrew Jeffery42e02d32018-05-24 13:34:05 +0930149 phosphor::led::SysfsLed sled{fs::path(path)};
Alexander Soldatov97ddb722019-04-16 09:10:00 +0300150 phosphor::led::Physical led(bus, objPath, sled, ledDescr.color);
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530151
152 /** @brief Claim the bus */
153 bus.request_name(busName.c_str());
154
155 /** @brief Wait for client requests */
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +0930156 while (true)
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530157 {
158 // Handle dbus message / signals discarding unhandled
159 bus.process_discard();
160 bus.wait();
161 }
Vishwanatha Subbanna835571e2016-11-30 11:29:30 +0530162 return 0;
163}