blob: ca28e8bc3e4f6d7c0e94fa5e8c94922b1cec9d02 [file] [log] [blame]
#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_