blob: 76756be5a6b5256ce6dd4f885b791a103ed70fda [file] [log] [blame]
Lei YUab1327c2019-11-04 16:53:39 +08001#include "i2c.hpp"
2
Lei YU9af82a52019-11-06 14:51:22 +08003#include <fcntl.h>
Lei YU92e89eb2019-11-06 18:08:25 +08004#include <sys/ioctl.h>
Lei YU9af82a52019-11-06 14:51:22 +08005#include <sys/stat.h>
6#include <unistd.h>
7
Lei YU92e89eb2019-11-06 18:08:25 +08008#include <cassert>
Lei YU9af82a52019-11-06 14:51:22 +08009#include <cerrno>
10
Lei YU92e89eb2019-11-06 18:08:25 +080011extern "C" {
12#include <i2c/smbus.h>
13#include <linux/i2c-dev.h>
14#include <linux/i2c.h>
15}
16
Lei YUab1327c2019-11-04 16:53:39 +080017namespace i2c
18{
19
Lei YU9af82a52019-11-06 14:51:22 +080020void 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 }
Lei YU92e89eb2019-11-06 18:08:25 +080027
28 if (ioctl(fd, I2C_SLAVE, devAddr) < 0)
29 {
30 throw I2CException("Failed to set I2C_SLAVE", busStr, devAddr, errno);
31 }
Lei YU9af82a52019-11-06 14:51:22 +080032}
33
34void I2CDevice::close()
35{
36 ::close(fd);
37}
38
Lei YU92e89eb2019-11-06 18:08:25 +080039void 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
Lei YU34fb8bd2019-11-07 14:24:20 +080086void 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
Lei YUab1327c2019-11-04 16:53:39 +0800132void I2CDevice::read(uint8_t& data)
133{
Lei YU92e89eb2019-11-06 18:08:25 +0800134 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);
Lei YUab1327c2019-11-04 16:53:39 +0800142}
143
144void I2CDevice::read(uint8_t addr, uint8_t& data)
145{
Lei YU92e89eb2019-11-06 18:08:25 +0800146 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);
Lei YUab1327c2019-11-04 16:53:39 +0800154}
155
156void I2CDevice::read(uint8_t addr, uint16_t& data)
157{
Lei YU92e89eb2019-11-06 18:08:25 +0800158 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);
Lei YUab1327c2019-11-04 16:53:39 +0800165}
166
167void I2CDevice::read(uint8_t addr, uint8_t& size, uint8_t* data)
168{
Lei YU92e89eb2019-11-06 18:08:25 +0800169 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);
Lei YUab1327c2019-11-04 16:53:39 +0800177}
178
179void I2CDevice::write(uint8_t data)
180{
Lei YU34fb8bd2019-11-07 14:24:20 +0800181 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 }
Lei YUab1327c2019-11-04 16:53:39 +0800187}
188
189void I2CDevice::write(uint8_t addr, uint8_t data)
190{
Lei YU34fb8bd2019-11-07 14:24:20 +0800191 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 }
Lei YUab1327c2019-11-04 16:53:39 +0800197}
198
199void I2CDevice::write(uint8_t addr, uint16_t data)
200{
Lei YU34fb8bd2019-11-07 14:24:20 +0800201 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 }
Lei YUab1327c2019-11-04 16:53:39 +0800207}
208
209void I2CDevice::write(uint8_t addr, uint8_t size, const uint8_t* data)
210{
Lei YU34fb8bd2019-11-07 14:24:20 +0800211 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 }
Lei YUab1327c2019-11-04 16:53:39 +0800218}
219
220std::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
226std::unique_ptr<I2CInterface> create(uint8_t busId, uint8_t devAddr)
227{
228 return I2CDevice::create(busId, devAddr);
229}
230
231} // namespace i2c