xref: /openbmc/dbus-sensors/src/ipmb/IpmbSensor.hpp (revision 18b6186e531ae37dd22b634c6530f793528473f4)
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