xref: /openbmc/entity-manager/src/gpio-presence/device_presence.cpp (revision b0f157189b02902917fa76feca5ce549808b0d56)
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2022-2024. All rights
3  * reserved. SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include "device_presence.hpp"
7 
8 #include <phosphor-logging/lg2.hpp>
9 #include <sdbusplus/message/native_types.hpp>
10 #include <xyz/openbmc_project/Configuration/GPIODeviceDetect/client.hpp>
11 #include <xyz/openbmc_project/Configuration/GPIODeviceDetect/common.hpp>
12 #include <xyz/openbmc_project/Inventory/Source/DevicePresence/aserver.hpp>
13 
14 #include <string>
15 #include <vector>
16 
17 PHOSPHOR_LOG2_USING;
18 
19 using DevicePresenceProperties = sdbusplus::common::xyz::openbmc_project::
20     inventory::source::DevicePresence::properties_t;
21 
22 namespace gpio_presence
23 {
24 
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)25 DevicePresence::DevicePresence(
26     sdbusplus::async::context& ctx, const std::vector<std::string>& gpioNames,
27     const std::vector<uint64_t>& gpioValues, const std::string& deviceName,
28     const std::unordered_map<std::string, bool>& gpioState) :
29     deviceName(deviceName), gpioState(gpioState), ctx(ctx)
30 {
31     for (size_t i = 0; i < gpioNames.size(); i++)
32     {
33         GPIO_POLARITY polarity =
34             (gpioValues[i] == 0) ? ACTIVE_LOW : ACTIVE_HIGH;
35         gpioPolarity[gpioNames[i]] = polarity;
36     }
37 }
38 
updateGPIOPresence(const std::string & gpioLine)39 auto DevicePresence::updateGPIOPresence(const std::string& gpioLine) -> void
40 {
41     if (!gpioPolarity.contains(gpioLine))
42     {
43         return;
44     }
45 
46     updateDbusInterfaces();
47 }
48 
getObjPath() const49 auto DevicePresence::getObjPath() const -> sdbusplus::message::object_path
50 {
51     sdbusplus::message::object_path objPathBase(
52         "/xyz/openbmc_project/GPIODeviceDetected/");
53     sdbusplus::message::object_path objPath = objPathBase / deviceName;
54     return objPath;
55 }
56 
isPresent()57 auto DevicePresence::isPresent() -> bool
58 {
59     for (auto& [name, polarity] : gpioPolarity)
60     {
61         if (!gpioState.contains(name))
62         {
63             error("GPIO {NAME} not in cached state", "NAME", name);
64             return false;
65         }
66 
67         const bool state = gpioState.at(name);
68 
69         if (state && polarity == ACTIVE_LOW)
70         {
71             return false;
72         }
73         if (!state && polarity == ACTIVE_HIGH)
74         {
75             return false;
76         }
77     }
78 
79     return true;
80 }
81 
updateDbusInterfaces()82 auto DevicePresence::updateDbusInterfaces() -> void
83 {
84     debug("Updating dbus interface for config {OBJPATH}", "OBJPATH",
85           deviceName);
86 
87     const bool present = isPresent();
88     sdbusplus::message::object_path objPath = getObjPath();
89 
90     if (present && !detectedIface)
91     {
92         info("Detected {NAME} as present, adding dbus interface", "NAME",
93              deviceName);
94 
95         detectedIface = std::make_unique<DevicePresenceInterface>(
96             ctx, objPath.str.c_str(), DevicePresenceProperties{deviceName});
97 
98         detectedIface->emit_added();
99     }
100 
101     if (!present && detectedIface)
102     {
103         info("Detected {NAME} as absent, removing dbus interface", "NAME",
104              deviceName);
105         detectedIface->emit_removed();
106 
107         detectedIface.reset();
108     }
109 }
110 
111 } // namespace gpio_presence
112