ApraLinuxUtils 1.0.0
C++ utility library for embedded Linux systems
 
Loading...
Searching...
No Matches
I2CBus.cpp
Go to the documentation of this file.
1/*
2 * I2CBus.cpp
3 *
4 * Copyright (c) 2024 Apra Labs
5 *
6 * This file is part of ApraUtils.
7 *
8 * Licensed under the MIT License.
9 * See LICENSE file in the project root for full license information.
10 */
11
12#include <linux/i2c-dev.h>
13#include <linux/i2c.h>
14#include <sys/ioctl.h>
15#include <fcntl.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <inttypes.h>
19#include "models/I2CError.h"
20#include "utils/Utils.h"
21#include "utils/Macro.h"
22
23#include "utils/I2CBus.h"
24using namespace apra;
25
26I2C_Bus::I2C_Bus(string i2cPath, bool shouldPrint) :
27 m_i2cPath(i2cPath), m_shouldPrint(shouldPrint), m_i2cFileDescriptor(-1), m_registerSize(
28 1), m_dataSize(1), m_lastI2COperationTs(0)
29{
30
31}
32
36
38{
39 MONOCURRTIME(timeNow);
40 return !((timeNow - m_lastI2COperationTs) > CONSEQUENT_I2C_TIME_LIMIT_US);
41}
42
43void I2C_Bus::setSize(uint8_t registerSize, uint8_t dataSize)
44{
45 m_registerSize = registerSize;
46 m_dataSize = dataSize;
47}
48
50{
51 I2CError error;
52#if defined(__arm__) || defined(__aarch64__)
53 m_i2cFileDescriptor = open(m_i2cPath.c_str(), O_RDWR);
54 if (m_i2cFileDescriptor < 0)
55 {
56 m_i2cFileDescriptor = -1;
57 if (m_shouldPrint)
58 {
59 char err[200];
60 sprintf(err, "open('%s') in i2c_init", m_i2cPath.c_str());
61 error = I2CError(err, OPEN_BUS_ERROR);
62 perror(err);
63 }
64 }
65#endif
66 return error;
67}
68
70{
71#if defined(__arm__) || defined(__aarch64__)
72 if (m_i2cFileDescriptor > -1)
73 {
74 close(m_i2cFileDescriptor);
75 m_i2cFileDescriptor = -1;
76 }
77#endif
78}
79
80I2CError I2C_Bus::genericWrite(uint8_t chipAddress,
81 vector<uint8_t> registerAddress, vector<uint8_t> data)
82{
83 I2CError error;
84#if defined(__arm__) || defined(__aarch64__)
85 if (m_i2cFileDescriptor > -1)
86 {
87 vector<uint8_t> i2cBytes = registerAddress;
88 i2cBytes.insert(i2cBytes.end(), data.begin(), data.end());
89 struct i2c_msg msgs[1];
90 struct i2c_rdwr_ioctl_data msgset[1];
91 msgs[0].addr = chipAddress;
92 msgs[0].flags = 0;
93 msgs[0].len = i2cBytes.size();
94 msgs[0].buf = i2cBytes.data();
95 msgset[0].msgs = msgs;
96 msgset[0].nmsgs = 1;
97 string debugString(__func__);
98 debugString += " , 0x";
99 for (uint32_t count = 0; count < registerAddress.size(); count++)
100 {
101 char regCh[5] =
102 { 0};
103 sprintf(regCh, "%02x", registerAddress[count]);
104 debugString += string(regCh);
105 }
106 debugString += " <--> 0x";
107 for (uint32_t count = 0; count < data.size(); count++)
108 {
109 char dataCh[5] =
110 { 0};
111 sprintf(dataCh, "%02x", data[count]);
112 debugString += string(dataCh);
113 }
114 debugString += "\n";
115 if (m_shouldPrint)
116 {
117 printf("%s", debugString.c_str());
118 }
119 if (ioctl(m_i2cFileDescriptor, I2C_RDWR, &msgset) < 0)
120 {
121 error = I2CError("ioctl(I2C_RDWR) in i2c_write", debugString,
123 if(m_shouldPrint)
124 {
125 perror(error.getMessage().c_str());}
126 }
127 else
128 {
129 MONOTIMEUS(m_lastI2COperationTs);
130 }
131 }
132 else
133 {
134 error = I2CError("I2C bus is not opened yet");
135 }
136#endif
137 return error;
138
139}
140I2CError I2C_Bus::genericRead(uint8_t chipAddress,
141 vector<uint8_t> registerAddress, vector<uint8_t> &readData)
142{
143 I2CError error;
144 string debugString(__func__);
145#if defined(__arm__) || defined(__aarch64__)
146 uint8_t *readBytes = (uint8_t*) calloc((m_dataSize + 1), 1);
147 if (readBytes == NULL)
148 {
149 error = I2CError("Unable to allocate memory for i2c read");
150 if (m_shouldPrint)
151 {
152 printf("%s\n", error.getMessage().c_str());
153 }
154 }
155 else
156 {
157 vector<uint8_t> i2cBytes = registerAddress;
158 struct i2c_msg msgs[2];
159 struct i2c_rdwr_ioctl_data msgset[1];
160 msgs[0].addr = chipAddress;
161 msgs[0].flags = 0;
162 msgs[0].len = i2cBytes.size();
163 msgs[0].buf = i2cBytes.data();
164 msgs[1].addr = chipAddress;
165 msgs[1].flags = I2C_M_RD;
166 msgs[1].len = m_dataSize;
167 msgs[1].buf = readBytes;
168 msgset[0].msgs = msgs;
169 msgset[0].nmsgs = 2;
170 debugString += " , 0x";
171 for (uint32_t count = 0; count < registerAddress.size(); count++)
172 {
173 char regCh[5] =
174 { 0};
175 sprintf(regCh, "%02x", registerAddress[count]);
176 debugString += string(regCh);
177 }
178 if (ioctl(m_i2cFileDescriptor, I2C_RDWR, &msgset) < 0 )
179 {
180 debugString += "\n";
181 error = I2CError("ioctl(I2C_RDWR) in i2c_read", debugString,
182 READ_ERROR);
183 if(m_shouldPrint)
184 {
185 perror(error.getMessage().c_str());}
186 }
187 else
188 {
189 MONOTIMEUS(m_lastI2COperationTs);
190 readData.clear();
191 for (uint16_t count = 0; count < m_dataSize; ++count)
192 {
193 readData.push_back(readBytes[count]);
194 }
195 }
196 }
197 if (readBytes != NULL)
198 {
199 free(readBytes);
200 readBytes = NULL;
201 }
202
203 if (m_shouldPrint)
204 {
205 printf("%s <--> 0x", debugString.c_str());
206 for (uint32_t count = 0; count < readData.size(); count++)
207 {
208 printf("%02x", readData[count]);
209 }
210 printf("\n");
211 }
212#endif
213 return error;
214}
215
216I2CError I2C_Bus::writeOnce(uint8_t chipAddress, uint64_t registerAddress,
217 uint64_t data)
218{
219 I2CError error = openBus();
220 if (!error.isError())
221 {
222 error = apra::I2C_Bus::writeOnI2C(chipAddress, registerAddress, data);
223 closeBus();
224 }
225 return error;
226}
227
228I2CError I2C_Bus::readOnce(uint8_t chipAddress, uint64_t registerAddress,
229 uint64_t &data)
230{
231 I2CError error = openBus();
232 if (!error.isError())
233 {
234 error = apra::I2C_Bus::readOnI2C(chipAddress, registerAddress, data);
235 closeBus();
236 }
237 return error;
238}
239
240I2CError I2C_Bus::writeOnI2C(uint8_t chipAddress, uint64_t registerAddress,
241 uint64_t data)
242{
243 I2CError error;
244 vector<uint8_t> registerArray = Utils::extractBytes(registerAddress,
245 m_registerSize);
246 vector<uint8_t> dataArray = Utils::extractBytes(data, m_dataSize);
247#if defined(__arm__) || defined(__aarch64__)
248 if (m_i2cFileDescriptor > -1)
249 {
250 error = genericWrite(chipAddress, registerArray, dataArray);
251 }
252 else
253 {
254 error = I2CError("I2C bus is not opened yet", BUS_UNOPENED);
255 }
256#endif
257 return error;
258}
259
260I2CError I2C_Bus::readOnI2C(uint8_t chipAddress, uint64_t registerAddress,
261 uint64_t &data)
262{
263 I2CError error;
264 vector<uint8_t> registerArray = Utils::extractBytes(registerAddress,
265 m_registerSize);
266 vector<uint8_t> dataArray;
267#if defined(__arm__) || defined(__aarch64__)
268 if (m_i2cFileDescriptor > -1)
269 {
270 error = genericRead(chipAddress, registerArray, dataArray);
271 if (!error.isError())
272 {
273 data = Utils::combineBytes(dataArray);
274 }
275 }
276 else
277 {
278 error = I2CError("I2C bus is not opened yet", BUS_UNOPENED);
279 }
280#endif
281 return error;
282}
#define CONSEQUENT_I2C_TIME_LIMIT_US
Definition I2CBus.h:19
#define MONOTIMEUS(ret)
Definition Macro.h:75
#define MONOCURRTIME(ret)
Definition Macro.h:81
std::string getMessage()
bool isI2CExecRecommended()
Definition I2CBus.cpp:37
void closeBus()
Definition I2CBus.cpp:69
I2CError genericWrite(uint8_t chipAddress, vector< uint8_t > registerAddress, vector< uint8_t > data)
Definition I2CBus.cpp:80
I2CError writeOnce(uint8_t chipAddress, uint64_t registerAddress, uint64_t data)
Definition I2CBus.cpp:216
I2CError readOnce(uint8_t chipAddress, uint64_t registerAddress, uint64_t &data)
Definition I2CBus.cpp:228
I2CError genericRead(uint8_t chipAddress, vector< uint8_t > registerAddress, vector< uint8_t > &readData)
Definition I2CBus.cpp:140
I2CError openBus()
Definition I2CBus.cpp:49
I2C_Bus(string i2cPath, bool shouldPrint)
Definition I2CBus.cpp:26
void setSize(uint8_t registerSize, uint8_t dataSize)
Definition I2CBus.cpp:43
virtual ~I2C_Bus()
Definition I2CBus.cpp:33
I2CError writeOnI2C(uint8_t chipAddress, uint64_t registerAddress, uint64_t data)
Definition I2CBus.cpp:240
I2CError readOnI2C(uint8_t chipAddress, uint64_t registerAddress, uint64_t &data)
Definition I2CBus.cpp:260
static vector< uint8_t > extractBytes(uint64_t hexData, uint8_t numberOfBytes)
Definition Utils.cpp:84
static uint64_t combineBytes(vector< uint8_t > byteArray)
Definition Utils.cpp:97
@ READ_ERROR
Definition I2CError.h:22
@ WRITE_ERROR
Definition I2CError.h:22
@ OPEN_BUS_ERROR
Definition I2CError.h:22
@ BUS_UNOPENED
Definition I2CError.h:22