1 #pragma once
2 #include "Thresholds.hpp"
3 #include "Utils.hpp"
4
5 #include <boost/asio/io_context.hpp>
6 #include <boost/asio/steady_timer.hpp>
7 #include <boost/container/flat_map.hpp>
8 #include <sdbusplus/asio/connection.hpp>
9 #include <sdbusplus/asio/object_server.hpp>
10 #include <sdbusplus/message.hpp>
11 #include <sensor.hpp>
12
13 #include <cstddef>
14 #include <cstdint>
15 #include <memory>
16 #include <optional>
17 #include <string>
18 #include <tuple>
19 #include <vector>
20
21 constexpr const char* sensorType = "IpmbSensor";
22 constexpr const char* sdrInterface = "IpmbDevice";
23
24 enum class IpmbType
25 {
26 none,
27 meSensor,
28 PXE1410CVR,
29 IR38363VR,
30 ADM1278HSC,
31 mpsVR,
32 SMPro
33 };
34
35 enum class IpmbSubType
36 {
37 none,
38 temp,
39 curr,
40 power,
41 volt,
42 util
43 };
44
45 enum class ReadingFormat
46 {
47 byte0,
48 byte3,
49 nineBit,
50 tenBit,
51 elevenBit,
52 elevenBitShift,
53 linearElevenBit,
54 fifteenBit
55 };
56
57 namespace ipmi
58 {
59 namespace sensor
60 {
61 constexpr uint8_t netFn = 0x04;
62 constexpr uint8_t getSensorReading = 0x2d;
63
isValid(const std::vector<uint8_t> & data)64 static inline bool isValid(const std::vector<uint8_t>& data)
65 {
66 constexpr auto readingUnavailableBit = 5;
67
68 // Proper 'Get Sensor Reading' response has at least 4 bytes, including
69 // Completion Code. Our IPMB stack strips Completion Code from payload so we
70 // compare here against the rest of payload
71 if (data.size() < 3)
72 {
73 return false;
74 }
75
76 // Per IPMI 'Get Sensor Reading' specification
77 if ((data[1] & (1 << readingUnavailableBit)) != 0)
78 {
79 return false;
80 }
81
82 return true;
83 }
84
85 } // namespace sensor
86 namespace me_bridge
87 {
88 constexpr uint8_t netFn = 0x2e;
89 constexpr uint8_t sendRawPmbus = 0xd9;
90 } // namespace me_bridge
91 } // namespace ipmi
92
93 using IpmbMethodType =
94 std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>;
95
96 struct IpmbSensor :
97 public Sensor,
98 public std::enable_shared_from_this<IpmbSensor>
99 {
100 IpmbSensor(std::shared_ptr<sdbusplus::asio::connection>& conn,
101 boost::asio::io_context& io, const std::string& name,
102 const std::string& sensorConfiguration,
103 sdbusplus::asio::object_server& objectServer,
104 std::vector<thresholds::Threshold>&& thresholdData,
105 uint8_t deviceAddress, uint8_t hostSMbusIndex, float pollRate,
106 std::string& sensorTypeName);
107 ~IpmbSensor() override;
108
109 void checkThresholds() override;
110 void read();
111 void init();
112 std::string getSubTypeUnits() const;
113 void loadDefaults();
114 void runInitCmd();
115 static bool processReading(ReadingFormat readingFormat, uint8_t command,
116 const std::vector<uint8_t>& data, double& resp,
117 size_t errCount);
118 void parseConfigValues(const SensorBaseConfigMap& entry);
119 bool sensorClassType(const std::string& sensorClass);
120 void sensorSubType(const std::string& sensorTypeName);
121
122 IpmbType type = IpmbType::none;
123 IpmbSubType subType = IpmbSubType::none;
124 double scaleVal = 1.0;
125 double offsetVal = 0.0;
126 uint8_t commandAddress = 0;
127 uint8_t netfn = 0;
128 uint8_t command = 0;
129 uint8_t deviceAddress = 0;
130 uint8_t errorCount = 0;
131 uint8_t hostSMbusIndex = 0;
132 std::vector<uint8_t> commandData;
133 std::optional<uint8_t> initCommand;
134 std::vector<uint8_t> initData;
135 int sensorPollMs;
136
137 ReadingFormat readingFormat = ReadingFormat::byte0;
138
139 private:
140 void sendIpmbRequest();
141 sdbusplus::asio::object_server& objectServer;
142 boost::asio::steady_timer waitTimer;
143 void ipmbRequestCompletionCb(const boost::system::error_code& ec,
144 const IpmbMethodType& response);
145 };
146
147 void createSensors(
148 boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
149 boost::container::flat_map<std::string, std::shared_ptr<IpmbSensor>>&
150 sensors,
151 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection);
152
153 void interfaceRemoved(
154 sdbusplus::message_t& message,
155 boost::container::flat_map<std::string, std::shared_ptr<IpmbSensor>>&
156 sensors);
157