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 /** @brief Get I2C adapter functionality 80 * 81 * Caches the adapter functionality value since it shouldn't change after 82 * opening the device. 83 * 84 * @throw I2CException on error 85 * @return Adapter functionality value 86 */ 87 unsigned long getFuncs(); 88 89 /** @brief Check i2c adapter read functionality 90 * 91 * Check if the i2c adapter has the functionality specified by the SMBus 92 * transaction type 93 * 94 * @param[in] type - The SMBus transaction type defined in linux/i2c.h 95 * 96 * @throw I2CException if the function is not supported 97 */ 98 void checkReadFuncs(int type); 99 100 /** @brief Check i2c adapter write functionality 101 * 102 * Check if the i2c adapter has the functionality specified by the SMBus 103 * transaction type 104 * 105 * @param[in] type - The SMBus transaction type defined in linux/i2c.h 106 * 107 * @throw I2CException if the function is not supported 108 */ 109 void checkWriteFuncs(int type); 110 111 public: 112 /** @copydoc I2CInterface::~I2CInterface() */ 113 ~I2CDevice() 114 { 115 if (isOpen()) 116 { 117 // Note: destructors must not throw exceptions 118 closeWithoutException(); 119 } 120 } 121 122 /** @copydoc I2CInterface::open() */ 123 void open(); 124 125 /** @copydoc I2CInterface::isOpen() */ 126 bool isOpen() const 127 { 128 return (fd != INVALID_FD); 129 } 130 131 /** @copydoc I2CInterface::close() */ 132 void close(); 133 134 /** @copydoc I2CInterface::read(uint8_t&) */ 135 void read(uint8_t& data) override; 136 137 /** @copydoc I2CInterface::read(uint8_t,uint8_t&) */ 138 void read(uint8_t addr, uint8_t& data) override; 139 140 /** @copydoc I2CInterface::read(uint8_t,uint16_t&) */ 141 void read(uint8_t addr, uint16_t& data) override; 142 143 /** @copydoc I2CInterface::read(uint8_t,uint8_t&,uint8_t*,Mode) */ 144 void read(uint8_t addr, uint8_t& size, uint8_t* data, 145 Mode mode = Mode::SMBUS) override; 146 147 /** @copydoc I2CInterface::write(uint8_t) */ 148 void write(uint8_t data) override; 149 150 /** @copydoc I2CInterface::write(uint8_t,uint8_t) */ 151 void write(uint8_t addr, uint8_t data) override; 152 153 /** @copydoc I2CInterface::write(uint8_t,uint16_t) */ 154 void write(uint8_t addr, uint16_t data) override; 155 156 /** @copydoc I2CInterface::write(uint8_t,uint8_t,const uint8_t*,Mode) */ 157 void write(uint8_t addr, uint8_t size, const uint8_t* data, 158 Mode mode = Mode::SMBUS) override; 159 160 /** @brief Create an I2CInterface instance 161 * 162 * Automatically opens the I2CInterface if initialState is OPEN. 163 * 164 * @param[in] busId - The i2c bus ID 165 * @param[in] devAddr - The device address of the i2c 166 * @param[in] initialState - Initial state of the I2CInterface object 167 * 168 * @return The unique_ptr holding the I2CInterface 169 */ 170 static std::unique_ptr<I2CInterface> 171 create(uint8_t busId, uint8_t devAddr, 172 InitialState initialState = InitialState::OPEN); 173 }; 174 175 } // namespace i2c 176