1 #pragma once 2 3 #include "i2c_interface.hpp" 4 5 namespace i2c 6 { 7 8 class I2CDevice : public I2CInterface 9 { 10 private: 11 I2CDevice() = delete; 12 13 /** @brief Constructor 14 * 15 * Construct I2CDevice object from the bus id and device address 16 * 17 * Automatically opens the I2CDevice if initialState is OPEN. 18 * 19 * @param[in] busId - The i2c bus ID 20 * @param[in] devAddr - The device address of the I2C device 21 * @param[in] initialState - Initial state of the I2CDevice object 22 */ 23 explicit I2CDevice(uint8_t busId, uint8_t devAddr, 24 InitialState initialState = InitialState::OPEN) : 25 busId(busId), 26 devAddr(devAddr) 27 { 28 busStr = "/dev/i2c-" + std::to_string(busId); 29 if (initialState == InitialState::OPEN) 30 { 31 open(); 32 } 33 } 34 35 /** @brief Invalid file descriptor */ 36 static constexpr int INVALID_FD = -1; 37 38 /** @brief Empty adapter functionality value with no bit flags set */ 39 static constexpr unsigned long NO_FUNCS = 0; 40 41 /** @brief The I2C bus ID */ 42 uint8_t busId; 43 44 /** @brief The i2c device address in the bus */ 45 uint8_t devAddr; 46 47 /** @brief The file descriptor of the opened i2c device */ 48 int fd = INVALID_FD; 49 50 /** @brief The i2c bus path in /dev */ 51 std::string busStr; 52 53 /** @brief Cached I2C adapter functionality value */ 54 unsigned long cachedFuncs = NO_FUNCS; 55 56 /** @brief Check that device interface is open 57 * 58 * @throw I2CException if device is not open 59 */ 60 void checkIsOpen() const 61 { 62 if (!isOpen()) 63 { 64 throw I2CException("Device not open", busStr, devAddr); 65 } 66 } 67 68 /** @brief Close device without throwing an exception if an error occurs */ 69 void closeWithoutException() noexcept 70 { 71 try 72 { 73 close(); 74 } 75 catch (...) 76 { 77 } 78 } 79 80 /** @brief Get I2C adapter functionality 81 * 82 * Caches the adapter functionality value since it shouldn't change after 83 * opening the device. 84 * 85 * @throw I2CException on error 86 * @return Adapter functionality value 87 */ 88 unsigned long getFuncs(); 89 90 /** @brief Check i2c adapter read functionality 91 * 92 * Check if the i2c adapter has the functionality specified by the SMBus 93 * transaction type 94 * 95 * @param[in] type - The SMBus transaction type defined in linux/i2c.h 96 * 97 * @throw I2CException if the function is not supported 98 */ 99 void checkReadFuncs(int type); 100 101 /** @brief Check i2c adapter write functionality 102 * 103 * Check if the i2c adapter has the functionality specified by the SMBus 104 * transaction type 105 * 106 * @param[in] type - The SMBus transaction type defined in linux/i2c.h 107 * 108 * @throw I2CException if the function is not supported 109 */ 110 void checkWriteFuncs(int type); 111 112 public: 113 /** @copydoc I2CInterface::~I2CInterface() */ 114 ~I2CDevice() 115 { 116 if (isOpen()) 117 { 118 // Note: destructors must not throw exceptions 119 closeWithoutException(); 120 } 121 } 122 123 /** @copydoc I2CInterface::open() */ 124 void open(); 125 126 /** @copydoc I2CInterface::isOpen() */ 127 bool isOpen() const 128 { 129 return (fd != INVALID_FD); 130 } 131 132 /** @copydoc I2CInterface::close() */ 133 void close(); 134 135 /** @copydoc I2CInterface::read(uint8_t&) */ 136 void read(uint8_t& data) override; 137 138 /** @copydoc I2CInterface::read(uint8_t,uint8_t&) */ 139 void read(uint8_t addr, uint8_t& data) override; 140 141 /** @copydoc I2CInterface::read(uint8_t,uint16_t&) */ 142 void read(uint8_t addr, uint16_t& data) override; 143 144 /** @copydoc I2CInterface::read(uint8_t,uint8_t&,uint8_t*,Mode) */ 145 void read(uint8_t addr, uint8_t& size, uint8_t* data, 146 Mode mode = Mode::SMBUS) override; 147 148 /** @copydoc I2CInterface::write(uint8_t) */ 149 void write(uint8_t data) override; 150 151 /** @copydoc I2CInterface::write(uint8_t,uint8_t) */ 152 void write(uint8_t addr, uint8_t data) override; 153 154 /** @copydoc I2CInterface::write(uint8_t,uint16_t) */ 155 void write(uint8_t addr, uint16_t data) override; 156 157 /** @copydoc I2CInterface::write(uint8_t,uint8_t,const uint8_t*,Mode) */ 158 void write(uint8_t addr, uint8_t size, const uint8_t* data, 159 Mode mode = Mode::SMBUS) override; 160 161 /** @brief Create an I2CInterface instance 162 * 163 * Automatically opens the I2CInterface if initialState is OPEN. 164 * 165 * @param[in] busId - The i2c bus ID 166 * @param[in] devAddr - The device address of the i2c 167 * @param[in] initialState - Initial state of the I2CInterface object 168 * 169 * @return The unique_ptr holding the I2CInterface 170 */ 171 static std::unique_ptr<I2CInterface> 172 create(uint8_t busId, uint8_t devAddr, 173 InitialState initialState = InitialState::OPEN); 174 }; 175 176 } // namespace i2c 177