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