1 #pragma once
2 
3 #include "Thresholds.hpp"
4 #include "Utils.hpp"
5 
6 #include <boost/asio/streambuf.hpp>
7 #include <boost/container/flat_map.hpp>
8 #include <gpiod.hpp>
9 #include <sdbusplus/asio/object_server.hpp>
10 #include <sensor.hpp>
11 
12 #include <filesystem>
13 #include <fstream>
14 #include <memory>
15 #include <stdexcept>
16 #include <string>
17 #include <variant>
18 #include <vector>
19 
20 class IntelCPUSensor :
21     public Sensor,
22     public std::enable_shared_from_this<IntelCPUSensor>
23 {
24   public:
25     IntelCPUSensor(const std::string& path, const std::string& objectType,
26                    sdbusplus::asio::object_server& objectServer,
27                    std::shared_ptr<sdbusplus::asio::connection>& conn,
28                    boost::asio::io_context& io, const std::string& sensorName,
29                    std::vector<thresholds::Threshold>&& thresholds,
30                    const std::string& configuration, int cpuId, bool show,
31                    double dtsOffset);
32     ~IntelCPUSensor() override;
33     static constexpr unsigned int sensorScaleFactor = 1000;
34     static constexpr unsigned int sensorPollMs = 1000;
35     static constexpr size_t warnAfterErrorCount = 10;
36     static constexpr const char* labelTcontrol = "Tcontrol";
37     void setupRead();
38 
39   private:
40     sdbusplus::asio::object_server& objServer;
41     boost::asio::streambuf readBuf;
42     boost::asio::posix::stream_descriptor inputDev;
43     boost::asio::steady_timer waitTimer;
44     std::string nameTcontrol;
45     std::string path;
46     double privTcontrol;
47     double dtsOffset;
48     bool show;
49     size_t pollTime;
50     bool loggedInterfaceDown = false;
51     uint8_t minMaxReadCounter{0};
52     int fd{};
53     void handleResponse(const boost::system::error_code& err);
54     void checkThresholds() override;
55     void updateMinMaxValues();
56     void restartRead();
57 };
58 
59 extern boost::container::flat_map<std::string, std::shared_ptr<IntelCPUSensor>>
60     gCpuSensors;
61 
62 // this is added to intelcpusensor.hpp to avoid having every sensor have to link
63 // against libgpiod, if another sensor needs it we may move it to utils
cpuIsPresent(const SensorBaseConfigMap & gpioConfig)64 inline bool cpuIsPresent(const SensorBaseConfigMap& gpioConfig)
65 {
66     static boost::container::flat_map<std::string, bool> cpuPresence;
67 
68     auto findName = gpioConfig.find("Name");
69     if (findName == gpioConfig.end())
70     {
71         return false;
72     }
73     std::string gpioName =
74         std::visit(VariantToStringVisitor(), findName->second);
75 
76     auto findIndex = cpuPresence.find(gpioName);
77     if (findIndex != cpuPresence.end())
78     {
79         return findIndex->second;
80     }
81 
82     bool activeHigh = true;
83     auto findPolarity = gpioConfig.find("Polarity");
84     if (findPolarity != gpioConfig.end())
85     {
86         if (std::string("Low") ==
87             std::visit(VariantToStringVisitor(), findPolarity->second))
88         {
89             activeHigh = false;
90         }
91     }
92 
93     auto line = gpiod::find_line(gpioName);
94     if (!line)
95     {
96         std::cerr << "Error requesting gpio: " << gpioName << "\n";
97         return false;
98     }
99 
100     bool resp = false;
101     try
102     {
103         line.request({"cpusensor", gpiod::line_request::DIRECTION_INPUT,
104                       activeHigh ? 0 : gpiod::line_request::FLAG_ACTIVE_LOW});
105         resp = (line.get_value() != 0);
106     }
107     catch (const std::system_error&)
108     {
109         std::cerr << "Error reading gpio: " << gpioName << "\n";
110         return false;
111     }
112 
113     cpuPresence[gpioName] = resp;
114 
115     return resp;
116 }
117