18c4b1d99SAlexander Hansen /*
28c4b1d99SAlexander Hansen * SPDX-FileCopyrightText: Copyright (c) 2022-2024. All rights
38c4b1d99SAlexander Hansen * reserved. SPDX-License-Identifier: Apache-2.0
48c4b1d99SAlexander Hansen */
58c4b1d99SAlexander Hansen
68c4b1d99SAlexander Hansen #include "device_presence.hpp"
78c4b1d99SAlexander Hansen
88c4b1d99SAlexander Hansen #include <phosphor-logging/lg2.hpp>
98c4b1d99SAlexander Hansen #include <sdbusplus/message/native_types.hpp>
108c4b1d99SAlexander Hansen #include <xyz/openbmc_project/Configuration/GPIODeviceDetect/client.hpp>
118c4b1d99SAlexander Hansen #include <xyz/openbmc_project/Configuration/GPIODeviceDetect/common.hpp>
128c4b1d99SAlexander Hansen #include <xyz/openbmc_project/Inventory/Source/DevicePresence/aserver.hpp>
138c4b1d99SAlexander Hansen
148c4b1d99SAlexander Hansen #include <string>
158c4b1d99SAlexander Hansen #include <vector>
168c4b1d99SAlexander Hansen
178c4b1d99SAlexander Hansen PHOSPHOR_LOG2_USING;
188c4b1d99SAlexander Hansen
19*b0f15718SAlexander Hansen using DevicePresenceProperties = sdbusplus::common::xyz::openbmc_project::
20*b0f15718SAlexander Hansen inventory::source::DevicePresence::properties_t;
21*b0f15718SAlexander Hansen
228c4b1d99SAlexander Hansen namespace gpio_presence
238c4b1d99SAlexander Hansen {
248c4b1d99SAlexander Hansen
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)258c4b1d99SAlexander Hansen DevicePresence::DevicePresence(
268c4b1d99SAlexander Hansen sdbusplus::async::context& ctx, const std::vector<std::string>& gpioNames,
278c4b1d99SAlexander Hansen const std::vector<uint64_t>& gpioValues, const std::string& deviceName,
288c4b1d99SAlexander Hansen const std::unordered_map<std::string, bool>& gpioState) :
298c4b1d99SAlexander Hansen deviceName(deviceName), gpioState(gpioState), ctx(ctx)
308c4b1d99SAlexander Hansen {
318c4b1d99SAlexander Hansen for (size_t i = 0; i < gpioNames.size(); i++)
328c4b1d99SAlexander Hansen {
338c4b1d99SAlexander Hansen GPIO_POLARITY polarity =
348c4b1d99SAlexander Hansen (gpioValues[i] == 0) ? ACTIVE_LOW : ACTIVE_HIGH;
358c4b1d99SAlexander Hansen gpioPolarity[gpioNames[i]] = polarity;
368c4b1d99SAlexander Hansen }
378c4b1d99SAlexander Hansen }
388c4b1d99SAlexander Hansen
updateGPIOPresence(const std::string & gpioLine)398c4b1d99SAlexander Hansen auto DevicePresence::updateGPIOPresence(const std::string& gpioLine) -> void
408c4b1d99SAlexander Hansen {
418c4b1d99SAlexander Hansen if (!gpioPolarity.contains(gpioLine))
428c4b1d99SAlexander Hansen {
438c4b1d99SAlexander Hansen return;
448c4b1d99SAlexander Hansen }
458c4b1d99SAlexander Hansen
468c4b1d99SAlexander Hansen updateDbusInterfaces();
478c4b1d99SAlexander Hansen }
488c4b1d99SAlexander Hansen
getObjPath() const498c4b1d99SAlexander Hansen auto DevicePresence::getObjPath() const -> sdbusplus::message::object_path
508c4b1d99SAlexander Hansen {
518c4b1d99SAlexander Hansen sdbusplus::message::object_path objPathBase(
528c4b1d99SAlexander Hansen "/xyz/openbmc_project/GPIODeviceDetected/");
538c4b1d99SAlexander Hansen sdbusplus::message::object_path objPath = objPathBase / deviceName;
548c4b1d99SAlexander Hansen return objPath;
558c4b1d99SAlexander Hansen }
568c4b1d99SAlexander Hansen
isPresent()578c4b1d99SAlexander Hansen auto DevicePresence::isPresent() -> bool
588c4b1d99SAlexander Hansen {
598c4b1d99SAlexander Hansen for (auto& [name, polarity] : gpioPolarity)
608c4b1d99SAlexander Hansen {
618c4b1d99SAlexander Hansen if (!gpioState.contains(name))
628c4b1d99SAlexander Hansen {
638c4b1d99SAlexander Hansen error("GPIO {NAME} not in cached state", "NAME", name);
648c4b1d99SAlexander Hansen return false;
658c4b1d99SAlexander Hansen }
668c4b1d99SAlexander Hansen
678c4b1d99SAlexander Hansen const bool state = gpioState.at(name);
688c4b1d99SAlexander Hansen
698c4b1d99SAlexander Hansen if (state && polarity == ACTIVE_LOW)
708c4b1d99SAlexander Hansen {
718c4b1d99SAlexander Hansen return false;
728c4b1d99SAlexander Hansen }
738c4b1d99SAlexander Hansen if (!state && polarity == ACTIVE_HIGH)
748c4b1d99SAlexander Hansen {
758c4b1d99SAlexander Hansen return false;
768c4b1d99SAlexander Hansen }
778c4b1d99SAlexander Hansen }
788c4b1d99SAlexander Hansen
798c4b1d99SAlexander Hansen return true;
808c4b1d99SAlexander Hansen }
818c4b1d99SAlexander Hansen
updateDbusInterfaces()828c4b1d99SAlexander Hansen auto DevicePresence::updateDbusInterfaces() -> void
838c4b1d99SAlexander Hansen {
848c4b1d99SAlexander Hansen debug("Updating dbus interface for config {OBJPATH}", "OBJPATH",
858c4b1d99SAlexander Hansen deviceName);
868c4b1d99SAlexander Hansen
878c4b1d99SAlexander Hansen const bool present = isPresent();
888c4b1d99SAlexander Hansen sdbusplus::message::object_path objPath = getObjPath();
898c4b1d99SAlexander Hansen
908c4b1d99SAlexander Hansen if (present && !detectedIface)
918c4b1d99SAlexander Hansen {
928c4b1d99SAlexander Hansen info("Detected {NAME} as present, adding dbus interface", "NAME",
938c4b1d99SAlexander Hansen deviceName);
948c4b1d99SAlexander Hansen
95*b0f15718SAlexander Hansen detectedIface = std::make_unique<DevicePresenceInterface>(
96*b0f15718SAlexander Hansen ctx, objPath.str.c_str(), DevicePresenceProperties{deviceName});
978c4b1d99SAlexander Hansen
988c4b1d99SAlexander Hansen detectedIface->emit_added();
998c4b1d99SAlexander Hansen }
1008c4b1d99SAlexander Hansen
1018c4b1d99SAlexander Hansen if (!present && detectedIface)
1028c4b1d99SAlexander Hansen {
1038c4b1d99SAlexander Hansen info("Detected {NAME} as absent, removing dbus interface", "NAME",
1048c4b1d99SAlexander Hansen deviceName);
1058c4b1d99SAlexander Hansen detectedIface->emit_removed();
1068c4b1d99SAlexander Hansen
1078c4b1d99SAlexander Hansen detectedIface.reset();
1088c4b1d99SAlexander Hansen }
1098c4b1d99SAlexander Hansen }
1108c4b1d99SAlexander Hansen
1118c4b1d99SAlexander Hansen } // namespace gpio_presence
112