#pragma once #include #include #include #include #include #include #include #include #include constexpr const char* sensorType = "IpmbSensor"; constexpr const char* sdrInterface = "IpmbDevice"; enum class IpmbType { none, meSensor, PXE1410CVR, IR38363VR, ADM1278HSC, mpsVR, SMPro }; enum class IpmbSubType { none, temp, curr, power, volt, util }; enum class ReadingFormat { byte0, byte3, nineBit, tenBit, elevenBit, elevenBitShift, linearElevenBit, fifteenBit }; namespace ipmi { namespace sensor { constexpr uint8_t netFn = 0x04; constexpr uint8_t getSensorReading = 0x2d; static inline bool isValid(const std::vector& data) { constexpr auto readingUnavailableBit = 5; // Proper 'Get Sensor Reading' response has at least 4 bytes, including // Completion Code. Our IPMB stack strips Completion Code from payload so we // compare here against the rest of payload if (data.size() < 3) { return false; } // Per IPMI 'Get Sensor Reading' specification if ((data[1] & (1 << readingUnavailableBit)) != 0) { return false; } return true; } } // namespace sensor namespace me_bridge { constexpr uint8_t netFn = 0x2e; constexpr uint8_t sendRawPmbus = 0xd9; } // namespace me_bridge } // namespace ipmi using IpmbMethodType = std::tuple>; struct IpmbSensor : public Sensor, public std::enable_shared_from_this { IpmbSensor(std::shared_ptr& conn, boost::asio::io_context& io, const std::string& name, const std::string& sensorConfiguration, sdbusplus::asio::object_server& objectServer, std::vector&& thresholdData, uint8_t deviceAddress, uint8_t hostSMbusIndex, float pollRate, std::string& sensorTypeName); ~IpmbSensor() override; void checkThresholds() override; void read(); void init(); std::string getSubTypeUnits() const; void loadDefaults(); void runInitCmd(); static bool processReading(ReadingFormat readingFormat, uint8_t command, const std::vector& data, double& resp, size_t errCount); void parseConfigValues(const SensorBaseConfigMap& entry); bool sensorClassType(const std::string& sensorClass); void sensorSubType(const std::string& sensorTypeName); IpmbType type = IpmbType::none; IpmbSubType subType = IpmbSubType::none; double scaleVal = 1.0; double offsetVal = 0.0; uint8_t commandAddress = 0; uint8_t netfn = 0; uint8_t command = 0; uint8_t deviceAddress = 0; uint8_t errorCount = 0; uint8_t hostSMbusIndex = 0; std::vector commandData; std::optional initCommand; std::vector initData; int sensorPollMs; ReadingFormat readingFormat = ReadingFormat::byte0; private: void sendIpmbRequest(); sdbusplus::asio::object_server& objectServer; boost::asio::steady_timer waitTimer; void ipmbRequestCompletionCb(const boost::system::error_code& ec, const IpmbMethodType& response); }; void createSensors( boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer, boost::container::flat_map>& sensors, std::shared_ptr& dbusConnection); void interfaceRemoved( sdbusplus::message_t& message, boost::container::flat_map>& sensors);