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