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