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