1ab1327c3SLei YU #pragma once 2ab1327c3SLei YU 3ab1327c3SLei YU #include "i2c_interface.hpp" 4ab1327c3SLei YU 5ab1327c3SLei YU namespace i2c 6ab1327c3SLei YU { 7ab1327c3SLei YU 8ab1327c3SLei YU class I2CDevice : public I2CInterface 9ab1327c3SLei YU { 10ab1327c3SLei YU private: 11ab1327c3SLei YU I2CDevice() = delete; 12ab1327c3SLei YU 139af82a5cSLei YU /** @brief Constructor 149af82a5cSLei YU * 159af82a5cSLei YU * Construct I2CDevice object from the bus id and device address 169af82a5cSLei YU * 17d45a9a6dSShawn McCarney * Automatically opens the I2CDevice if initialState is OPEN. 18d45a9a6dSShawn McCarney * 199af82a5cSLei YU * @param[in] busId - The i2c bus ID 209af82a5cSLei YU * @param[in] devAddr - The device address of the I2C device 21d45a9a6dSShawn McCarney * @param[in] initialState - Initial state of the I2CDevice object 22770de580SShawn McCarney * @param[in] maxRetries - Maximum number of times to retry an I2C operation 239af82a5cSLei YU */ I2CDevice(uint8_t busId,uint8_t devAddr,InitialState initialState=InitialState::OPEN,int maxRetries=0)24d45a9a6dSShawn McCarney explicit I2CDevice(uint8_t busId, uint8_t devAddr, 25770de580SShawn McCarney InitialState initialState = InitialState::OPEN, 26770de580SShawn McCarney int maxRetries = 0) : 2728a2ca4bSJayanth Othayoth devAddr(devAddr), maxRetries(maxRetries), 28b9cf0d2bSGeorge Liu busStr("/dev/i2c-" + std::to_string(busId)) 29ab1327c3SLei YU { 30d45a9a6dSShawn McCarney if (initialState == InitialState::OPEN) 31d45a9a6dSShawn McCarney { 329af82a5cSLei YU open(); 33ab1327c3SLei YU } 34d45a9a6dSShawn McCarney } 35ab1327c3SLei YU 36d45a9a6dSShawn McCarney /** @brief Invalid file descriptor */ 37d45a9a6dSShawn McCarney static constexpr int INVALID_FD = -1; 389af82a5cSLei YU 3938ed88d6SShawn McCarney /** @brief Empty adapter functionality value with no bit flags set */ 4038ed88d6SShawn McCarney static constexpr unsigned long NO_FUNCS = 0; 4138ed88d6SShawn McCarney 429af82a5cSLei YU /** @brief The i2c device address in the bus */ 439af82a5cSLei YU uint8_t devAddr; 449af82a5cSLei YU 45770de580SShawn McCarney /** @brief Maximum number of times to retry an I2C operation */ 46770de580SShawn McCarney int maxRetries = 0; 47770de580SShawn McCarney 489af82a5cSLei YU /** @brief The file descriptor of the opened i2c device */ 4938ed88d6SShawn McCarney int fd = INVALID_FD; 509af82a5cSLei YU 519af82a5cSLei YU /** @brief The i2c bus path in /dev */ 529af82a5cSLei YU std::string busStr; 539af82a5cSLei YU 5438ed88d6SShawn McCarney /** @brief Cached I2C adapter functionality value */ 5538ed88d6SShawn McCarney unsigned long cachedFuncs = NO_FUNCS; 5638ed88d6SShawn McCarney 57d45a9a6dSShawn McCarney /** @brief Check that device interface is open 58d45a9a6dSShawn McCarney * 59d45a9a6dSShawn McCarney * @throw I2CException if device is not open 60d45a9a6dSShawn McCarney */ checkIsOpen() const61d45a9a6dSShawn McCarney void checkIsOpen() const 62d45a9a6dSShawn McCarney { 63d45a9a6dSShawn McCarney if (!isOpen()) 64d45a9a6dSShawn McCarney { 65d45a9a6dSShawn McCarney throw I2CException("Device not open", busStr, devAddr); 66d45a9a6dSShawn McCarney } 67d45a9a6dSShawn McCarney } 68d45a9a6dSShawn McCarney 69d45a9a6dSShawn McCarney /** @brief Close device without throwing an exception if an error occurs */ closeWithoutException()70d45a9a6dSShawn McCarney void closeWithoutException() noexcept 71d45a9a6dSShawn McCarney { 72d45a9a6dSShawn McCarney try 73d45a9a6dSShawn McCarney { 74d45a9a6dSShawn McCarney close(); 75d45a9a6dSShawn McCarney } 76d45a9a6dSShawn McCarney catch (...) 770c9a33d6SAdriana Kobylak {} 78d45a9a6dSShawn McCarney } 79d45a9a6dSShawn McCarney 8038ed88d6SShawn McCarney /** @brief Get I2C adapter functionality 8138ed88d6SShawn McCarney * 8238ed88d6SShawn McCarney * Caches the adapter functionality value since it shouldn't change after 8338ed88d6SShawn McCarney * opening the device. 8438ed88d6SShawn McCarney * 8538ed88d6SShawn McCarney * @throw I2CException on error 8638ed88d6SShawn McCarney * @return Adapter functionality value 8738ed88d6SShawn McCarney */ 8838ed88d6SShawn McCarney unsigned long getFuncs(); 8938ed88d6SShawn McCarney 9092e89eb5SLei YU /** @brief Check i2c adapter read functionality 9192e89eb5SLei YU * 9292e89eb5SLei YU * Check if the i2c adapter has the functionality specified by the SMBus 9392e89eb5SLei YU * transaction type 9492e89eb5SLei YU * 9592e89eb5SLei YU * @param[in] type - The SMBus transaction type defined in linux/i2c.h 9692e89eb5SLei YU * 9792e89eb5SLei YU * @throw I2CException if the function is not supported 9892e89eb5SLei YU */ 9992e89eb5SLei YU void checkReadFuncs(int type); 10092e89eb5SLei YU 10134fb8bdaSLei YU /** @brief Check i2c adapter write functionality 10234fb8bdaSLei YU * 10334fb8bdaSLei YU * Check if the i2c adapter has the functionality specified by the SMBus 10434fb8bdaSLei YU * transaction type 10534fb8bdaSLei YU * 10634fb8bdaSLei YU * @param[in] type - The SMBus transaction type defined in linux/i2c.h 10734fb8bdaSLei YU * 10834fb8bdaSLei YU * @throw I2CException if the function is not supported 10934fb8bdaSLei YU */ 11034fb8bdaSLei YU void checkWriteFuncs(int type); 11134fb8bdaSLei YU 112a3ff7e71SShawn McCarney /** @brief SMBus Block Write-Block Read Process Call using SMBus function 113a3ff7e71SShawn McCarney * 114a3ff7e71SShawn McCarney * In SMBus 2.0 the maximum write size + read size is <= 32 bytes. 115a3ff7e71SShawn McCarney * In SMBus 3.0 the maximum write size + read size is <= 255 bytes. 116a3ff7e71SShawn McCarney * The Linux SMBus function currently only supports the SMBus 2.0 maximum. 117a3ff7e71SShawn McCarney * 118a3ff7e71SShawn McCarney * @param[in] addr - The register address of the i2c device 119a3ff7e71SShawn McCarney * @param[in] writeSize - The size of data to write. Write size + read size 120a3ff7e71SShawn McCarney * must be <= 32 bytes. 121a3ff7e71SShawn McCarney * @param[in] writeData - The data to write to the i2c device 122a3ff7e71SShawn McCarney * @param[out] readSize - The size of data read from i2c device. Write size 123a3ff7e71SShawn McCarney * + read size must be <= 32 bytes. 124a3ff7e71SShawn McCarney * @param[out] readData - Pointer to buffer to hold the data read from the 125a3ff7e71SShawn McCarney * i2c device. Must be large enough to hold the data 126a3ff7e71SShawn McCarney * returned by the device (max is 32 bytes). 127a3ff7e71SShawn McCarney * 128a3ff7e71SShawn McCarney * @throw I2CException on error 129a3ff7e71SShawn McCarney */ 130a3ff7e71SShawn McCarney void processCallSMBus(uint8_t addr, uint8_t writeSize, 131a3ff7e71SShawn McCarney const uint8_t* writeData, uint8_t& readSize, 132a3ff7e71SShawn McCarney uint8_t* readData); 133a3ff7e71SShawn McCarney 134a3ff7e71SShawn McCarney /** @brief SMBus Block Write-Block Read Process Call using I2C messages 135a3ff7e71SShawn McCarney * 136a3ff7e71SShawn McCarney * This method supports block writes of more than 32 bytes. It can also be 137a3ff7e71SShawn McCarney * used with I2C adapters that do not support the block process call 138a3ff7e71SShawn McCarney * protocol but do support I2C-level commands. 139a3ff7e71SShawn McCarney * 140a3ff7e71SShawn McCarney * This method implements the block process call using the lower level 141a3ff7e71SShawn McCarney * I2C_RDWR ioctl to send I2C messages. Using this ioctl allows for writes 142a3ff7e71SShawn McCarney * up to 255 bytes. The write size + read size must be <= 255 bytes. 143a3ff7e71SShawn McCarney * 144a3ff7e71SShawn McCarney * @param[in] addr - The register address of the i2c device 145a3ff7e71SShawn McCarney * @param[in] writeSize - The size of data to write. Write size + read size 146a3ff7e71SShawn McCarney * must be <= 255 bytes. 147a3ff7e71SShawn McCarney * @param[in] writeData - The data to write to the i2c device 148a3ff7e71SShawn McCarney * @param[out] readSize - The size of data read from i2c device. Max read 149a3ff7e71SShawn McCarney * size is 32 bytes, and write size + read size must 150a3ff7e71SShawn McCarney * be <= 255 bytes. 151a3ff7e71SShawn McCarney * @param[out] readData - Pointer to buffer to hold the data read from the 152a3ff7e71SShawn McCarney * i2c device. Must be large enough to hold the data 153a3ff7e71SShawn McCarney * returned by the device (max is 32 bytes). 154a3ff7e71SShawn McCarney * 155a3ff7e71SShawn McCarney * @throw I2CException on error 156a3ff7e71SShawn McCarney */ 157a3ff7e71SShawn McCarney void processCallI2C(uint8_t addr, uint8_t writeSize, 158a3ff7e71SShawn McCarney const uint8_t* writeData, uint8_t& readSize, 159a3ff7e71SShawn McCarney uint8_t* readData); 160a3ff7e71SShawn McCarney 161ab1327c3SLei YU public: 162d45a9a6dSShawn McCarney /** @copydoc I2CInterface::~I2CInterface() */ ~I2CDevice()1639af82a5cSLei YU ~I2CDevice() 1649af82a5cSLei YU { 165d45a9a6dSShawn McCarney if (isOpen()) 166d45a9a6dSShawn McCarney { 167d45a9a6dSShawn McCarney // Note: destructors must not throw exceptions 168d45a9a6dSShawn McCarney closeWithoutException(); 1699af82a5cSLei YU } 170d45a9a6dSShawn McCarney } 171d45a9a6dSShawn McCarney 172d45a9a6dSShawn McCarney /** @copydoc I2CInterface::open() */ 17312c4a420SJayanth Othayoth void open() override; 174d45a9a6dSShawn McCarney 175d45a9a6dSShawn McCarney /** @copydoc I2CInterface::isOpen() */ isOpen() const17612c4a420SJayanth Othayoth bool isOpen() const override 177d45a9a6dSShawn McCarney { 178d45a9a6dSShawn McCarney return (fd != INVALID_FD); 179d45a9a6dSShawn McCarney } 180d45a9a6dSShawn McCarney 181d45a9a6dSShawn McCarney /** @copydoc I2CInterface::close() */ 18212c4a420SJayanth Othayoth void close() override; 183ab1327c3SLei YU 184ab1327c3SLei YU /** @copydoc I2CInterface::read(uint8_t&) */ 185ab1327c3SLei YU void read(uint8_t& data) override; 186ab1327c3SLei YU 187ab1327c3SLei YU /** @copydoc I2CInterface::read(uint8_t,uint8_t&) */ 188ab1327c3SLei YU void read(uint8_t addr, uint8_t& data) override; 189ab1327c3SLei YU 190ab1327c3SLei YU /** @copydoc I2CInterface::read(uint8_t,uint16_t&) */ 191ab1327c3SLei YU void read(uint8_t addr, uint16_t& data) override; 192ab1327c3SLei YU 1931d103428SLei YU /** @copydoc I2CInterface::read(uint8_t,uint8_t&,uint8_t*,Mode) */ 1941d103428SLei YU void read(uint8_t addr, uint8_t& size, uint8_t* data, 1951d103428SLei YU Mode mode = Mode::SMBUS) override; 196ab1327c3SLei YU 197ab1327c3SLei YU /** @copydoc I2CInterface::write(uint8_t) */ 198ab1327c3SLei YU void write(uint8_t data) override; 199ab1327c3SLei YU 200ab1327c3SLei YU /** @copydoc I2CInterface::write(uint8_t,uint8_t) */ 201ab1327c3SLei YU void write(uint8_t addr, uint8_t data) override; 202ab1327c3SLei YU 203ab1327c3SLei YU /** @copydoc I2CInterface::write(uint8_t,uint16_t) */ 204ab1327c3SLei YU void write(uint8_t addr, uint16_t data) override; 205ab1327c3SLei YU 2061d103428SLei YU /** @copydoc I2CInterface::write(uint8_t,uint8_t,const uint8_t*,Mode) */ 2071d103428SLei YU void write(uint8_t addr, uint8_t size, const uint8_t* data, 2081d103428SLei YU Mode mode = Mode::SMBUS) override; 209ab1327c3SLei YU 210a3ff7e71SShawn McCarney /** @copydoc I2CInterface::processCall(uint8_t,uint16_t,uint16_t&) */ 211a3ff7e71SShawn McCarney void processCall(uint8_t addr, uint16_t writeData, 212a3ff7e71SShawn McCarney uint16_t& readData) override; 213a3ff7e71SShawn McCarney 214a3ff7e71SShawn McCarney /** @copydoc I2CInterface::processCall(uint8_t,uint8_t,const 215a3ff7e71SShawn McCarney * uint8_t*,uint8_t&,uint8_t*) */ 216a3ff7e71SShawn McCarney void processCall(uint8_t addr, uint8_t writeSize, const uint8_t* writeData, 217a3ff7e71SShawn McCarney uint8_t& readSize, uint8_t* readData) override; 218a3ff7e71SShawn McCarney 219ab1327c3SLei YU /** @brief Create an I2CInterface instance 220ab1327c3SLei YU * 221d45a9a6dSShawn McCarney * Automatically opens the I2CInterface if initialState is OPEN. 222d45a9a6dSShawn McCarney * 223ab1327c3SLei YU * @param[in] busId - The i2c bus ID 224ab1327c3SLei YU * @param[in] devAddr - The device address of the i2c 225d45a9a6dSShawn McCarney * @param[in] initialState - Initial state of the I2CInterface object 226770de580SShawn McCarney * @param[in] maxRetries - Maximum number of times to retry an I2C operation 227ab1327c3SLei YU * 228ab1327c3SLei YU * @return The unique_ptr holding the I2CInterface 229ab1327c3SLei YU */ 230*92261f88SPatrick Williams static std::unique_ptr<I2CInterface> create( 231*92261f88SPatrick Williams uint8_t busId, uint8_t devAddr, 232*92261f88SPatrick Williams InitialState initialState = InitialState::OPEN, int maxRetries = 0); 233ab1327c3SLei YU }; 234ab1327c3SLei YU 235ab1327c3SLei YU } // namespace i2c 236