| /* |
| // Copyright (c) 2019 Intel Corporation |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <sys/ioctl.h> |
| #include <stdio.h> |
| #include <experimental/filesystem> |
| #include <phosphor-logging/log.hpp> |
| |
| extern "C" { |
| #include <i2c/smbus.h> |
| #include <linux/i2c-dev.h> |
| } |
| |
| namespace intel |
| { |
| namespace pfr |
| { |
| |
| /** @class I2CFile |
| * @brief Responsible for handling file pointer |
| */ |
| class I2CFile |
| { |
| private: |
| /** @brief handler for operating on file */ |
| int fd; |
| |
| public: |
| I2CFile() = delete; |
| I2CFile(const I2CFile&) = delete; |
| I2CFile& operator=(const I2CFile&) = delete; |
| I2CFile(I2CFile&&) = delete; |
| I2CFile& operator=(I2CFile&&) = delete; |
| |
| /** @brief Opens i2c device file and sets slave |
| * |
| * @param[in] i2cBus - I2C bus number |
| * @param[in] slaveAddr - I2C slave address |
| * @param[in] flags - Flags |
| */ |
| I2CFile(const int& i2cBus, const int& slaveAddr, const int& flags) |
| { |
| std::string i2cDev = "/dev/i2c-" + std::to_string(i2cBus); |
| |
| fd = open(i2cDev.c_str(), flags); |
| if (fd < 0) |
| { |
| throw std::runtime_error("Unable to open i2c device."); |
| } |
| |
| if (ioctl(fd, I2C_SLAVE_FORCE, slaveAddr) < 0) |
| { |
| close(fd); |
| fd = -1; |
| throw std::runtime_error("Unable to set i2c slave address."); |
| } |
| } |
| |
| /** @brief Reads the byte data from I2C dev |
| * |
| * @param[in] Offset - Offset value |
| * @param[out] byte data - Offset value |
| */ |
| uint8_t i2cReadByteData(const uint8_t& offset) |
| { |
| uint8_t value = i2c_smbus_read_byte_data(fd, offset); |
| |
| if (value < 0) |
| { |
| throw std::runtime_error("i2c_smbus_read_byte_data() failed"); |
| } |
| return value; |
| } |
| |
| /** @brief Writes the byte data to I2C dev |
| * |
| * @param[in] Offset - Offset value |
| * @param[in] Byte data - Data |
| */ |
| void i2cWriteByteData(const uint8_t offset, const uint8_t value) |
| { |
| int retries = 3; |
| while (i2c_smbus_write_byte_data(fd, offset, value) < 0) |
| { |
| phosphor::logging::log<phosphor::logging::level::WARNING>( |
| "PFR: I2c write failed, retrying....", |
| phosphor::logging::entry("COUNT=%d", retries)); |
| if (!retries--) |
| { |
| throw std::runtime_error("i2c_smbus_write_byte_data() failed"); |
| } |
| std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
| } |
| return; |
| } |
| |
| ~I2CFile() |
| { |
| if (!(fd < 0)) |
| { |
| close(fd); |
| } |
| } |
| |
| auto operator()() |
| { |
| return fd; |
| } |
| }; |
| |
| } // namespace pfr |
| } // namespace intel |