1 /** 2 * Copyright © 2020 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 "internal_interface.hpp" 18 19 #include <sdbusplus/message.hpp> 20 21 namespace phosphor 22 { 23 namespace led 24 { 25 namespace sysfs 26 { 27 namespace interface 28 { 29 30 InternalInterface::InternalInterface(sdbusplus::bus_t& bus, const char* path) : 31 bus(bus), serverInterface(bus, path, internalInterface, vtable.data(), this) 32 {} 33 34 void InternalInterface::getLedDescr(const std::string& name, LedDescr& ledDescr) 35 { 36 std::vector<std::string> words; 37 boost::split(words, name, boost::is_any_of(":")); 38 try 39 { 40 ledDescr.devicename = words.at(0); 41 ledDescr.color = words.at(1); 42 ledDescr.function = words.at(2); 43 } 44 catch (const std::out_of_range& e) 45 { 46 lg2::warning("LED description {DESC} not well formed, error {ERR}", 47 "DESC", name, "ERR", e.what()); 48 throw e; 49 } 50 } 51 52 std::string InternalInterface::getDbusName(const LedDescr& ledDescr) 53 { 54 std::vector<std::string> words; 55 words.emplace_back(ledDescr.devicename); 56 if (!ledDescr.function.empty()) 57 { 58 words.emplace_back(ledDescr.function); 59 } 60 61 if (!ledDescr.color.empty()) 62 { 63 words.emplace_back(ledDescr.color); 64 } 65 66 std::string s = boost::join(words, "_"); 67 68 sdbusplus::message::object_path path(s); 69 70 return path.str; 71 } 72 73 void InternalInterface::createLEDPath(const std::string& ledName) 74 { 75 std::string name; 76 std::string path = devParent + ledName; 77 78 if (!std::filesystem::exists(fs::path(path))) 79 { 80 lg2::error("No such directory {PATH}", "PATH", path); 81 return; 82 } 83 84 // Convert LED name in sysfs into DBus name 85 LedDescr ledDescr; 86 try 87 { 88 getLedDescr(ledName, ledDescr); 89 } 90 catch (...) 91 { 92 // Ignore the error, for simple LED which was not added in 3-part form. 93 // The simple LED can appear with it's plain name 94 } 95 name = getDbusName(ledDescr); 96 97 lg2::debug("LED {NAME} receives dbus name {DBUSNAME}", "NAME", ledName, 98 "DBUSNAME", name); 99 100 // Unique path name representing a single LED. 101 sdbusplus::message::object_path objPath = std::string(physParent); 102 objPath /= name; 103 104 if (leds.contains(objPath)) 105 { 106 return; 107 } 108 109 auto sled = std::make_unique<phosphor::led::SysfsLed>(fs::path(path)); 110 111 leds.emplace(objPath, std::make_unique<phosphor::led::Physical>( 112 bus, objPath, std::move(sled), ledDescr.color)); 113 } 114 115 void InternalInterface::addLED(const std::string& name) 116 { 117 createLEDPath(name); 118 } 119 120 // NOLINTNEXTLINE(readability-convert-member-functions-to-static) 121 void InternalInterface::removeLED(const std::string& name) 122 { 123 lg2::debug("RemoveLED is not configured {NAME}", "NAME", name); 124 } 125 126 int InternalInterface::addLedConfigure(sd_bus_message* msg, void* context, 127 sd_bus_error* error) 128 { 129 if (msg == nullptr && context == nullptr) 130 { 131 lg2::error("Unable to configure addLed"); 132 return -EINVAL; 133 } 134 135 try 136 { 137 auto message = sdbusplus::message_t(msg); 138 auto ledName = message.unpack<std::string>(); 139 140 auto* self = static_cast<InternalInterface*>(context); 141 self->addLED(ledName); 142 143 auto reply = message.new_method_return(); 144 reply.method_return(); 145 } 146 catch (const sdbusplus::exception_t& e) 147 { 148 return sd_bus_error_set(error, e.name(), e.description()); 149 } 150 151 return 1; 152 } 153 154 int InternalInterface::removeLedConfigure(sd_bus_message* msg, void* context, 155 sd_bus_error* error) 156 { 157 if (msg == nullptr && context == nullptr) 158 { 159 lg2::error("Unable to configure removeLed"); 160 return -EINVAL; 161 } 162 163 try 164 { 165 auto message = sdbusplus::message_t(msg); 166 auto ledName = message.unpack<std::string>(); 167 168 auto* self = static_cast<InternalInterface*>(context); 169 self->removeLED(ledName); 170 171 auto reply = message.new_method_return(); 172 reply.method_return(); 173 } 174 catch (const sdbusplus::exception_t& e) 175 { 176 return sd_bus_error_set(error, e.name(), e.description()); 177 } 178 179 return 1; 180 } 181 182 const std::array<sdbusplus::vtable::vtable_t, 4> InternalInterface::vtable = { 183 sdbusplus::vtable::start(), 184 // AddLed method takes a string parameter and returns void 185 sdbusplus::vtable::method("AddLED", "s", "", addLedConfigure), 186 // RemoveLed method takes a string parameter and returns void 187 sdbusplus::vtable::method("RemoveLED", "s", "", removeLedConfigure), 188 sdbusplus::vtable::end()}; 189 190 } // namespace interface 191 } // namespace sysfs 192 } // namespace led 193 } // namespace phosphor 194