| #ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_I2C_HWMON_BASED_SENSOR_H_ |
| #define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_I2C_HWMON_BASED_SENSOR_H_ |
| |
| #include <array> |
| #include <atomic> |
| #include <cstddef> |
| #include <fstream> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <string_view> |
| |
| #include "absl/functional/any_invocable.h" |
| #include "absl/status/statusor.h" |
| #include "boost/asio.hpp" //NOLINT: boost::asio is commonly used in BMC |
| #include "hwmon_temp_sensor_config.pb.h" |
| #include "i2c_common_config.pb.h" |
| #include "tlbmc/hal/sysfs/i2c.h" |
| #include "sensor.pb.h" |
| #include "tlbmc/sensors/sensor.h" |
| |
| namespace milotic_tlbmc { |
| |
| // This class is a base class for sensors that are based on I2C HWMon devices. |
| // All public interfaces are thread-safe. |
| // The `io_context` shall run only on a single thread. |
| class I2cHwmonBasedSensor |
| : public Sensor, |
| public std::enable_shared_from_this<I2cHwmonBasedSensor> { |
| public: |
| I2cHwmonBasedSensor( |
| const std::string& input_dev_path, |
| const std::shared_ptr<boost::asio::io_context>& io_context, |
| SensorAttributesStatic&& sensor_attributes_static, |
| std::optional<NotificationCb> on_batch_notify); |
| |
| void RefreshOnceAsync( |
| absl::AnyInvocable<void(const std::shared_ptr<const SensorValue>&)> |
| callback) override; |
| ~I2cHwmonBasedSensor() override; |
| |
| static absl::StatusOr<boost::filesystem::path> |
| CreateDeviceAndReturnsHwmonPath(const I2cCommonConfig& i2c_config, |
| std::string_view driver_name, |
| const I2cSysfs& i2c_sysfs); |
| |
| protected: |
| I2cHwmonBasedSensor() = default; |
| |
| bool IsInputDeviceUsable() const { return input_device_usable_; } |
| |
| void SetInputDeviceUsable(bool input_device_usable) { |
| input_device_usable_ = input_device_usable; |
| } |
| |
| const std::array<char, 128>& GetConstReadBuffer() const { |
| return read_buffer_; |
| } |
| |
| std::array<char, 128>& GetMutableReadBuffer() { return read_buffer_; } |
| |
| const std::shared_ptr<boost::asio::random_access_file>& GetInputDevice() |
| const { |
| return input_device_; |
| } |
| |
| std::ifstream& GetInputFile() { return input_file_; } |
| |
| std::string GetInputDevicePath() const { return input_dev_path_; } |
| |
| // Sets up the input device. This function shall be called on the |
| // `io_context_` thread or at construction time. |
| void SetUpInput(); |
| |
| // Sets up the file that input device will read from. This function attempts |
| // to create an io_uring based random_access_file. If it fails, it will fall |
| // back to use synchronous file read. |
| void SetUpInputDeviceFile(); |
| |
| // Descendants shall implement this function to handle the buffer that reads |
| // from the input device. This function will be called on the `io_context_` |
| // thread. |
| virtual void HandleRefreshResult(const boost::system::error_code& error, |
| size_t bytes_read) = 0; |
| |
| // Given an input file, returns the unit of the sensor. |
| static absl::StatusOr<SensorUnit> GetSensorUnit(std::string_view input_file); |
| |
| private: |
| std::string input_dev_path_; |
| std::shared_ptr<boost::asio::io_context> io_context_; |
| // The buffer to read the value from. |
| std::array<char, 128> read_buffer_ = {}; |
| // This variable is used to cancel any outstanding async read operations on |
| // `input_device_` when sensor is being destroyed. |
| std::atomic<bool> input_device_usable_ = false; |
| // The input device to read the temperature from. Please note `input_device_` |
| // is not thread-safe. |
| std::shared_ptr<boost::asio::random_access_file> input_device_; |
| std::ifstream input_file_; |
| }; |
| |
| } // namespace milotic_tlbmc |
| |
| #endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_I2C_HWMON_BASED_SENSOR_H_ |