1 #include "i2c.hpp" 2 3 #include <fcntl.h> 4 #include <sys/ioctl.h> 5 #include <sys/stat.h> 6 #include <unistd.h> 7 8 #include <cassert> 9 #include <cerrno> 10 11 extern "C" { 12 #include <i2c/smbus.h> 13 #include <linux/i2c-dev.h> 14 #include <linux/i2c.h> 15 } 16 17 namespace i2c 18 { 19 20 void I2CDevice::open() 21 { 22 fd = ::open(busStr.c_str(), O_RDWR); 23 if (fd == -1) 24 { 25 throw I2CException("Failed to open", busStr, devAddr, errno); 26 } 27 28 if (ioctl(fd, I2C_SLAVE, devAddr) < 0) 29 { 30 throw I2CException("Failed to set I2C_SLAVE", busStr, devAddr, errno); 31 } 32 } 33 34 void I2CDevice::close() 35 { 36 ::close(fd); 37 } 38 39 void I2CDevice::checkReadFuncs(int type) 40 { 41 unsigned long funcs; 42 43 /* Check adapter functionality */ 44 if (ioctl(fd, I2C_FUNCS, &funcs) < 0) 45 { 46 throw I2CException("Failed to get funcs", busStr, devAddr, errno); 47 } 48 49 switch (type) 50 { 51 case I2C_SMBUS_BYTE: 52 if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) 53 { 54 throw I2CException("Missing SMBUS_READ_BYTE", busStr, devAddr); 55 } 56 break; 57 case I2C_SMBUS_BYTE_DATA: 58 if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA)) 59 { 60 throw I2CException("Missing SMBUS_READ_BYTE_DATA", busStr, 61 devAddr); 62 } 63 break; 64 65 case I2C_SMBUS_WORD_DATA: 66 if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA)) 67 { 68 throw I2CException("Missing SMBUS_READ_WORD_DATA", busStr, 69 devAddr); 70 } 71 break; 72 case I2C_SMBUS_BLOCK_DATA: 73 if (!(funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA)) 74 { 75 throw I2CException("Missing SMBUS_READ_BLOCK_DATA", busStr, 76 devAddr); 77 } 78 break; 79 default: 80 fprintf(stderr, "Unexpected read size type: %d\n", type); 81 assert(false); 82 break; 83 } 84 } 85 86 void I2CDevice::checkWriteFuncs(int type) 87 { 88 unsigned long funcs; 89 90 /* Check adapter functionality */ 91 if (ioctl(fd, I2C_FUNCS, &funcs) < 0) 92 { 93 throw I2CException("Failed to get funcs", busStr, devAddr, errno); 94 } 95 96 switch (type) 97 { 98 case I2C_SMBUS_BYTE: 99 if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) 100 { 101 throw I2CException("Missing SMBUS_WRITE_BYTE", busStr, devAddr); 102 } 103 break; 104 case I2C_SMBUS_BYTE_DATA: 105 if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) 106 { 107 throw I2CException("Missing SMBUS_WRITE_BYTE_DATA", busStr, 108 devAddr); 109 } 110 break; 111 112 case I2C_SMBUS_WORD_DATA: 113 if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA)) 114 { 115 throw I2CException("Missing SMBUS_WRITE_WORD_DATA", busStr, 116 devAddr); 117 } 118 break; 119 case I2C_SMBUS_BLOCK_DATA: 120 if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) 121 { 122 throw I2CException("Missing SMBUS_WRITE_BLOCK_DATA", busStr, 123 devAddr); 124 } 125 break; 126 default: 127 fprintf(stderr, "Unexpected read size type: %d\n", type); 128 assert(false); 129 } 130 } 131 132 void I2CDevice::read(uint8_t& data) 133 { 134 checkReadFuncs(I2C_SMBUS_BYTE); 135 136 int ret = i2c_smbus_read_byte(fd); 137 if (ret < 0) 138 { 139 throw I2CException("Failed to read byte", busStr, devAddr, errno); 140 } 141 data = static_cast<uint8_t>(ret); 142 } 143 144 void I2CDevice::read(uint8_t addr, uint8_t& data) 145 { 146 checkReadFuncs(I2C_SMBUS_BYTE_DATA); 147 148 int ret = i2c_smbus_read_byte_data(fd, addr); 149 if (ret < 0) 150 { 151 throw I2CException("Failed to read byte data", busStr, devAddr, errno); 152 } 153 data = static_cast<uint8_t>(ret); 154 } 155 156 void I2CDevice::read(uint8_t addr, uint16_t& data) 157 { 158 checkReadFuncs(I2C_SMBUS_WORD_DATA); 159 int ret = i2c_smbus_read_word_data(fd, addr); 160 if (ret < 0) 161 { 162 throw I2CException("Failed to read word data", busStr, devAddr, errno); 163 } 164 data = static_cast<uint16_t>(ret); 165 } 166 167 void I2CDevice::read(uint8_t addr, uint8_t& size, uint8_t* data) 168 { 169 checkReadFuncs(I2C_SMBUS_BLOCK_DATA); 170 171 int ret = i2c_smbus_read_block_data(fd, addr, data); 172 if (ret < 0) 173 { 174 throw I2CException("Failed to read block data", busStr, devAddr, errno); 175 } 176 size = static_cast<uint8_t>(ret); 177 } 178 179 void I2CDevice::write(uint8_t data) 180 { 181 checkWriteFuncs(I2C_SMBUS_BYTE); 182 183 if (i2c_smbus_write_byte(fd, data) < 0) 184 { 185 throw I2CException("Failed to write byte", busStr, devAddr, errno); 186 } 187 } 188 189 void I2CDevice::write(uint8_t addr, uint8_t data) 190 { 191 checkWriteFuncs(I2C_SMBUS_BYTE_DATA); 192 193 if (i2c_smbus_write_byte_data(fd, addr, data) < 0) 194 { 195 throw I2CException("Failed to write byte data", busStr, devAddr, errno); 196 } 197 } 198 199 void I2CDevice::write(uint8_t addr, uint16_t data) 200 { 201 checkWriteFuncs(I2C_SMBUS_WORD_DATA); 202 203 if (i2c_smbus_write_word_data(fd, addr, data) < 0) 204 { 205 throw I2CException("Failed to write word data", busStr, devAddr, errno); 206 } 207 } 208 209 void I2CDevice::write(uint8_t addr, uint8_t size, const uint8_t* data) 210 { 211 checkWriteFuncs(I2C_SMBUS_BLOCK_DATA); 212 213 if (i2c_smbus_write_block_data(fd, addr, size, data) < 0) 214 { 215 throw I2CException("Failed to write block data", busStr, devAddr, 216 errno); 217 } 218 } 219 220 std::unique_ptr<I2CInterface> I2CDevice::create(uint8_t busId, uint8_t devAddr) 221 { 222 std::unique_ptr<I2CDevice> dev(new I2CDevice(busId, devAddr)); 223 return dev; 224 } 225 226 std::unique_ptr<I2CInterface> create(uint8_t busId, uint8_t devAddr) 227 { 228 return I2CDevice::create(busId, devAddr); 229 } 230 231 } // namespace i2c 232