|  | /* | 
|  | * SPDX-FileCopyrightText: Copyright (c) 2022-2024. All rights | 
|  | * reserved. SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include "device_presence.hpp" | 
|  |  | 
|  | #include <phosphor-logging/lg2.hpp> | 
|  | #include <sdbusplus/message/native_types.hpp> | 
|  | #include <xyz/openbmc_project/Configuration/GPIODeviceDetect/client.hpp> | 
|  | #include <xyz/openbmc_project/Configuration/GPIODeviceDetect/common.hpp> | 
|  | #include <xyz/openbmc_project/Inventory/Source/DevicePresence/aserver.hpp> | 
|  |  | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | PHOSPHOR_LOG2_USING; | 
|  |  | 
|  | using DevicePresenceProperties = sdbusplus::common::xyz::openbmc_project:: | 
|  | inventory::source::DevicePresence::properties_t; | 
|  |  | 
|  | namespace gpio_presence | 
|  | { | 
|  |  | 
|  | DevicePresence::DevicePresence( | 
|  | sdbusplus::async::context& ctx, const std::vector<std::string>& gpioNames, | 
|  | const std::vector<uint64_t>& gpioValues, const std::string& deviceName, | 
|  | const std::unordered_map<std::string, bool>& gpioState) : | 
|  | deviceName(deviceName), gpioState(gpioState), ctx(ctx) | 
|  | { | 
|  | for (size_t i = 0; i < gpioNames.size(); i++) | 
|  | { | 
|  | GPIO_POLARITY polarity = | 
|  | (gpioValues[i] == 0) ? ACTIVE_LOW : ACTIVE_HIGH; | 
|  | gpioPolarity[gpioNames[i]] = polarity; | 
|  | } | 
|  | } | 
|  |  | 
|  | auto DevicePresence::updateGPIOPresence(const std::string& gpioLine) -> void | 
|  | { | 
|  | if (!gpioPolarity.contains(gpioLine)) | 
|  | { | 
|  | return; | 
|  | } | 
|  |  | 
|  | updateDbusInterfaces(); | 
|  | } | 
|  |  | 
|  | auto DevicePresence::getObjPath() const -> sdbusplus::message::object_path | 
|  | { | 
|  | sdbusplus::message::object_path objPathBase( | 
|  | "/xyz/openbmc_project/GPIODeviceDetected/"); | 
|  | sdbusplus::message::object_path objPath = objPathBase / deviceName; | 
|  | return objPath; | 
|  | } | 
|  |  | 
|  | auto DevicePresence::isPresent() -> bool | 
|  | { | 
|  | for (auto& [name, polarity] : gpioPolarity) | 
|  | { | 
|  | if (!gpioState.contains(name)) | 
|  | { | 
|  | error("GPIO {NAME} not in cached state", "NAME", name); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | const bool state = gpioState.at(name); | 
|  |  | 
|  | if (state && polarity == ACTIVE_LOW) | 
|  | { | 
|  | return false; | 
|  | } | 
|  | if (!state && polarity == ACTIVE_HIGH) | 
|  | { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | auto DevicePresence::updateDbusInterfaces() -> void | 
|  | { | 
|  | debug("Updating dbus interface for config {OBJPATH}", "OBJPATH", | 
|  | deviceName); | 
|  |  | 
|  | const bool present = isPresent(); | 
|  | sdbusplus::message::object_path objPath = getObjPath(); | 
|  |  | 
|  | if (present && !detectedIface) | 
|  | { | 
|  | info("Detected {NAME} as present, adding dbus interface", "NAME", | 
|  | deviceName); | 
|  |  | 
|  | detectedIface = std::make_unique<DevicePresenceInterface>( | 
|  | ctx, objPath.str.c_str(), DevicePresenceProperties{deviceName}); | 
|  |  | 
|  | detectedIface->emit_added(); | 
|  | } | 
|  |  | 
|  | if (!present && detectedIface) | 
|  | { | 
|  | info("Detected {NAME} as absent, removing dbus interface", "NAME", | 
|  | deviceName); | 
|  | detectedIface->emit_removed(); | 
|  |  | 
|  | detectedIface.reset(); | 
|  | } | 
|  | } | 
|  |  | 
|  | } // namespace gpio_presence |