1 #include "cooling_type.hpp"
2 
3 #include "sdbusplus.hpp"
4 #include "utility.hpp"
5 
6 #include <fcntl.h>
7 #include <libevdev/libevdev.h>
8 #include <unistd.h>
9 
10 #include <phosphor-logging/elog-errors.hpp>
11 #include <phosphor-logging/elog.hpp>
12 #include <phosphor-logging/log.hpp>
13 #include <sdbusplus/bus.hpp>
14 #include <xyz/openbmc_project/Common/error.hpp>
15 
16 #include <format>
17 
18 namespace phosphor
19 {
20 namespace cooling
21 {
22 namespace type
23 {
24 
25 // For throwing exception
26 using namespace phosphor::logging;
27 using InternalFailure =
28     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
29 
30 std::unique_ptr<libevdev, FreeEvDev> evdevOpen(int fd)
31 {
32     libevdev* gpioDev = nullptr;
33 
34     auto rc = libevdev_new_from_fd(fd, &gpioDev);
35     if (!rc)
36     {
37         return decltype(evdevOpen(0))(gpioDev);
38     }
39 
40     log<level::ERR>(
41         std::format(
42             "Failed to get libevdev from file descriptor {}, return code {}",
43             fd, rc)
44             .c_str());
45     elog<InternalFailure>();
46     return decltype(evdevOpen(0))(nullptr);
47 }
48 
49 void CoolingType::setAirCooled()
50 {
51     airCooled = true;
52 }
53 
54 void CoolingType::setWaterCooled()
55 {
56     waterCooled = true;
57 }
58 
59 void CoolingType::readGpio(const std::string& gpioPath, unsigned int keycode)
60 {
61     using namespace phosphor::logging;
62 
63     gpioFd.open(gpioPath.c_str(), O_RDONLY);
64 
65     auto gpioDev = evdevOpen(gpioFd());
66 
67     int value = 0;
68     auto fetch_rc = libevdev_fetch_event_value(gpioDev.get(), EV_KEY, keycode,
69                                                &value);
70     if (0 == fetch_rc)
71     {
72         log<level::ERR>(
73             std::format("Device does not support event type keycode {}",
74                         keycode)
75                 .c_str());
76         elog<InternalFailure>();
77     }
78 
79     // TODO openbmc/phosphor-fan-presence#6
80     if (value > 0)
81     {
82         setAirCooled();
83     }
84     else
85     {
86         setWaterCooled();
87     }
88 }
89 
90 CoolingType::ObjectMap CoolingType::getObjectMap(const std::string& objpath)
91 {
92     ObjectMap invObj;
93     InterfaceMap invIntf;
94     PropertyMap invProp;
95 
96     invProp.emplace("AirCooled", airCooled);
97     invProp.emplace("WaterCooled", waterCooled);
98     invIntf.emplace("xyz.openbmc_project.Inventory.Decorator.CoolingType",
99                     std::move(invProp));
100     invObj.emplace(objpath, std::move(invIntf));
101 
102     return invObj;
103 }
104 
105 void CoolingType::updateInventory(const std::string& objpath)
106 {
107     using namespace phosphor::fan;
108 
109     ObjectMap invObj = getObjectMap(objpath);
110 
111     // Update inventory
112     static_cast<void>(util::SDBusPlus::lookupAndCallMethod(
113         bus, util::INVENTORY_PATH, util::INVENTORY_INTF, "Notify",
114         std::move(invObj)));
115 }
116 
117 } // namespace type
118 } // namespace cooling
119 } // namespace phosphor
120 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
121