#include "i2c.hpp" #include #include #include #include #include #include extern "C" { #include #include #include } namespace i2c { void I2CDevice::open() { fd = ::open(busStr.c_str(), O_RDWR); if (fd == -1) { throw I2CException("Failed to open", busStr, devAddr, errno); } if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { throw I2CException("Failed to set I2C_SLAVE", busStr, devAddr, errno); } } void I2CDevice::close() { ::close(fd); } void I2CDevice::checkReadFuncs(int type) { unsigned long funcs; /* Check adapter functionality */ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) { throw I2CException("Failed to get funcs", busStr, devAddr, errno); } switch (type) { case I2C_SMBUS_BYTE: if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) { throw I2CException("Missing SMBUS_READ_BYTE", busStr, devAddr); } break; case I2C_SMBUS_BYTE_DATA: if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA)) { throw I2CException("Missing SMBUS_READ_BYTE_DATA", busStr, devAddr); } break; case I2C_SMBUS_WORD_DATA: if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA)) { throw I2CException("Missing SMBUS_READ_WORD_DATA", busStr, devAddr); } break; case I2C_SMBUS_BLOCK_DATA: if (!(funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA)) { throw I2CException("Missing SMBUS_READ_BLOCK_DATA", busStr, devAddr); } break; default: fprintf(stderr, "Unexpected read size type: %d\n", type); assert(false); break; } } void I2CDevice::checkWriteFuncs(int type) { unsigned long funcs; /* Check adapter functionality */ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) { throw I2CException("Failed to get funcs", busStr, devAddr, errno); } switch (type) { case I2C_SMBUS_BYTE: if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) { throw I2CException("Missing SMBUS_WRITE_BYTE", busStr, devAddr); } break; case I2C_SMBUS_BYTE_DATA: if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { throw I2CException("Missing SMBUS_WRITE_BYTE_DATA", busStr, devAddr); } break; case I2C_SMBUS_WORD_DATA: if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA)) { throw I2CException("Missing SMBUS_WRITE_WORD_DATA", busStr, devAddr); } break; case I2C_SMBUS_BLOCK_DATA: if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) { throw I2CException("Missing SMBUS_WRITE_BLOCK_DATA", busStr, devAddr); } break; default: fprintf(stderr, "Unexpected read size type: %d\n", type); assert(false); } } void I2CDevice::read(uint8_t& data) { checkReadFuncs(I2C_SMBUS_BYTE); int ret = i2c_smbus_read_byte(fd); if (ret < 0) { throw I2CException("Failed to read byte", busStr, devAddr, errno); } data = static_cast(ret); } void I2CDevice::read(uint8_t addr, uint8_t& data) { checkReadFuncs(I2C_SMBUS_BYTE_DATA); int ret = i2c_smbus_read_byte_data(fd, addr); if (ret < 0) { throw I2CException("Failed to read byte data", busStr, devAddr, errno); } data = static_cast(ret); } void I2CDevice::read(uint8_t addr, uint16_t& data) { checkReadFuncs(I2C_SMBUS_WORD_DATA); int ret = i2c_smbus_read_word_data(fd, addr); if (ret < 0) { throw I2CException("Failed to read word data", busStr, devAddr, errno); } data = static_cast(ret); } void I2CDevice::read(uint8_t addr, uint8_t& size, uint8_t* data) { checkReadFuncs(I2C_SMBUS_BLOCK_DATA); int ret = i2c_smbus_read_block_data(fd, addr, data); if (ret < 0) { throw I2CException("Failed to read block data", busStr, devAddr, errno); } size = static_cast(ret); } void I2CDevice::write(uint8_t data) { checkWriteFuncs(I2C_SMBUS_BYTE); if (i2c_smbus_write_byte(fd, data) < 0) { throw I2CException("Failed to write byte", busStr, devAddr, errno); } } void I2CDevice::write(uint8_t addr, uint8_t data) { checkWriteFuncs(I2C_SMBUS_BYTE_DATA); if (i2c_smbus_write_byte_data(fd, addr, data) < 0) { throw I2CException("Failed to write byte data", busStr, devAddr, errno); } } void I2CDevice::write(uint8_t addr, uint16_t data) { checkWriteFuncs(I2C_SMBUS_WORD_DATA); if (i2c_smbus_write_word_data(fd, addr, data) < 0) { throw I2CException("Failed to write word data", busStr, devAddr, errno); } } void I2CDevice::write(uint8_t addr, uint8_t size, const uint8_t* data) { checkWriteFuncs(I2C_SMBUS_BLOCK_DATA); if (i2c_smbus_write_block_data(fd, addr, size, data) < 0) { throw I2CException("Failed to write block data", busStr, devAddr, errno); } } std::unique_ptr I2CDevice::create(uint8_t busId, uint8_t devAddr) { std::unique_ptr dev(new I2CDevice(busId, devAddr)); return dev; } std::unique_ptr create(uint8_t busId, uint8_t devAddr) { return I2CDevice::create(busId, devAddr); } } // namespace i2c