/** * Copyright © 2020 IBM Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "internal_interface.hpp" #include #include #include #include namespace phosphor { namespace led { namespace sysfs { namespace interface { InternalInterface::InternalInterface(sdbusplus::bus_t& bus, const char* path) : bus(bus), serverInterface(bus, path, internalInterface, vtable.data(), this) {} std::string InternalInterface::getDbusName(const LedDescr& ledDescr) { std::vector words; if (ledDescr.devicename.has_value()) { words.emplace_back(ledDescr.devicename.value()); } if (ledDescr.function.has_value()) { words.emplace_back(ledDescr.function.value()); } if (ledDescr.color.has_value()) { words.emplace_back(ledDescr.color.value()); } std::string s = std::accumulate(std::next(words.begin()), words.end(), words[0], [](std::string a, const std::string& b) { return std::move(a) + "_" + b; }); // we assume the string to be a correct dbus name besides // this detail std::replace(s.begin(), s.end(), '-', '_'); return s; } void InternalInterface::createLEDPath(const std::string& ledName) { std::string name; std::string path = devParent + ledName; if (!std::filesystem::exists(fs::path(path))) { lg2::error("No such directory {PATH}", "PATH", path); return; } auto sled = std::make_unique(fs::path(path)); // Convert LED name in sysfs into DBus name const LedDescr ledDescr = sled->getLedDescr(); name = getDbusName(ledDescr); lg2::debug("LED {NAME} receives dbus name {DBUSNAME}", "NAME", ledName, "DBUSNAME", name); // Unique path name representing a single LED. std::string objPath = std::string(physParent) + "/" + name; if (leds.contains(objPath)) { return; } leds.emplace(objPath, std::make_unique( bus, objPath, std::move(sled), ledDescr.color.value_or(""))); } void InternalInterface::addLED(const std::string& name) { createLEDPath(name); } // NOLINTNEXTLINE(readability-convert-member-functions-to-static) void InternalInterface::removeLED(const std::string& name) { lg2::debug("RemoveLED is not configured {NAME}", "NAME", name); } int InternalInterface::addLedConfigure(sd_bus_message* msg, void* context, sd_bus_error* error) { if (msg == nullptr && context == nullptr) { lg2::error("Unable to configure addLed"); return -EINVAL; } try { auto message = sdbusplus::message_t(msg); auto ledName = message.unpack(); auto* self = static_cast(context); self->addLED(ledName); auto reply = message.new_method_return(); reply.method_return(); } catch (const sdbusplus::exception_t& e) { return sd_bus_error_set(error, e.name(), e.description()); } return 1; } int InternalInterface::removeLedConfigure(sd_bus_message* msg, void* context, sd_bus_error* error) { if (msg == nullptr && context == nullptr) { lg2::error("Unable to configure removeLed"); return -EINVAL; } try { auto message = sdbusplus::message_t(msg); auto ledName = message.unpack(); auto* self = static_cast(context); self->removeLED(ledName); auto reply = message.new_method_return(); reply.method_return(); } catch (const sdbusplus::exception_t& e) { return sd_bus_error_set(error, e.name(), e.description()); } return 1; } const std::array InternalInterface::vtable = { sdbusplus::vtable::start(), // AddLed method takes a string parameter and returns void sdbusplus::vtable::method("AddLED", "s", "", addLedConfigure), // RemoveLed method takes a string parameter and returns void sdbusplus::vtable::method("RemoveLED", "s", "", removeLedConfigure), sdbusplus::vtable::end()}; } // namespace interface } // namespace sysfs } // namespace led } // namespace phosphor