blob: da121d89096f1a98048935b244c1246b0a24d5d2 [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 YUab1327c2019-11-04 16:53:39 +080086void I2CDevice::read(uint8_t& data)
87{
Lei YU92e89eb2019-11-06 18:08:25 +080088 checkReadFuncs(I2C_SMBUS_BYTE);
89
90 int ret = i2c_smbus_read_byte(fd);
91 if (ret < 0)
92 {
93 throw I2CException("Failed to read byte", busStr, devAddr, errno);
94 }
95 data = static_cast<uint8_t>(ret);
Lei YUab1327c2019-11-04 16:53:39 +080096}
97
98void I2CDevice::read(uint8_t addr, uint8_t& data)
99{
Lei YU92e89eb2019-11-06 18:08:25 +0800100 checkReadFuncs(I2C_SMBUS_BYTE_DATA);
101
102 int ret = i2c_smbus_read_byte_data(fd, addr);
103 if (ret < 0)
104 {
105 throw I2CException("Failed to read byte data", busStr, devAddr, errno);
106 }
107 data = static_cast<uint8_t>(ret);
Lei YUab1327c2019-11-04 16:53:39 +0800108}
109
110void I2CDevice::read(uint8_t addr, uint16_t& data)
111{
Lei YU92e89eb2019-11-06 18:08:25 +0800112 checkReadFuncs(I2C_SMBUS_WORD_DATA);
113 int ret = i2c_smbus_read_word_data(fd, addr);
114 if (ret < 0)
115 {
116 throw I2CException("Failed to read word data", busStr, devAddr, errno);
117 }
118 data = static_cast<uint16_t>(ret);
Lei YUab1327c2019-11-04 16:53:39 +0800119}
120
121void I2CDevice::read(uint8_t addr, uint8_t& size, uint8_t* data)
122{
Lei YU92e89eb2019-11-06 18:08:25 +0800123 checkReadFuncs(I2C_SMBUS_BLOCK_DATA);
124
125 int ret = i2c_smbus_read_block_data(fd, addr, data);
126 if (ret < 0)
127 {
128 throw I2CException("Failed to read block data", busStr, devAddr, errno);
129 }
130 size = static_cast<uint8_t>(ret);
Lei YUab1327c2019-11-04 16:53:39 +0800131}
132
133void I2CDevice::write(uint8_t data)
134{
135 // TODO
136 (void)data;
137}
138
139void I2CDevice::write(uint8_t addr, uint8_t data)
140{
141 // TODO
142 (void)addr;
143 (void)data;
144}
145
146void I2CDevice::write(uint8_t addr, uint16_t data)
147{
148 // TODO
149 (void)addr;
150 (void)data;
151}
152
153void I2CDevice::write(uint8_t addr, uint8_t size, const uint8_t* data)
154{
155 // TODO
156 (void)addr;
157 (void)size;
158 (void)data;
159}
160
161std::unique_ptr<I2CInterface> I2CDevice::create(uint8_t busId, uint8_t devAddr)
162{
163 std::unique_ptr<I2CDevice> dev(new I2CDevice(busId, devAddr));
164 return dev;
165}
166
167std::unique_ptr<I2CInterface> create(uint8_t busId, uint8_t devAddr)
168{
169 return I2CDevice::create(busId, devAddr);
170}
171
172} // namespace i2c