-
Notifications
You must be signed in to change notification settings - Fork 0
/
smbus_linux.cpp
165 lines (135 loc) · 5.33 KB
/
smbus_linux.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "smbus.h"
#if !(WIN32)
#include <stdexcept>
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
// Define the I2C commands if not already defined
#ifndef I2C_SLAVE
#define I2C_SLAVE 0x0703
#endif
namespace X
{
namespace ElectonLink
{
bool SMBus::setSlaveAddress(int deviceAddress) {
if (ioctl(fileDescriptor, I2C_SLAVE, deviceAddress) < 0) {
perror("Failed to set slave address");
return false;
}
return true;
}
SMBus::~SMBus() {
if (m_isOpen) {
closeBus();
}
}
bool SMBus::openBus() {
std::string busPath;
if (m_busName.IsLong()) {
busPath = "/dev/i2c-" + std::to_string((int)m_busName);
}
else {
busPath = m_busName.ToString();
}
fileDescriptor = open(busPath.c_str(), O_RDWR);
if (fileDescriptor < 0) {
perror("Failed to open the bus");
return false;
}
m_isOpen = true;
return true;
}
void SMBus::closeBus() {
if (fileDescriptor >= 0) {
close(fileDescriptor);
fileDescriptor = -1;
}
m_isOpen = false;
}
uint8_t SMBus::readByte(int i2c_addr, bool force) {
setSlaveAddress(i2c_addr); // Assumes setSlaveAddress always succeeds, handle exceptions or errors as necessary
uint8_t data = 0;
if (read(fileDescriptor, &data, 1) != 1) {
throw std::runtime_error("Failed to read byte");
}
return data;
}
void SMBus::writeByte(int i2c_addr, uint8_t value, bool force) {
setSlaveAddress(i2c_addr);
if (write(fileDescriptor, &value, 1) != 1) {
throw std::runtime_error("Failed to write byte");
}
}
uint8_t SMBus::readByteData(int i2c_addr, uint8_t reg, bool force) {
setSlaveAddress(i2c_addr);
// Write the register address we want to read from
if (write(fileDescriptor, ®, 1) != 1) {
throw std::runtime_error("Failed to write register address");
}
// Read the data from the register
uint8_t data;
if (read(fileDescriptor, &data, 1) != 1) {
throw std::runtime_error("Failed to read byte data");
}
return data;
}
void SMBus::writeByteData(int i2c_addr, uint8_t reg, uint8_t value, bool force) {
setSlaveAddress(i2c_addr);
// Write the register address followed by the data
uint8_t buffer[2] = { reg, value };
if (write(fileDescriptor, buffer, 2) != 2) {
throw std::runtime_error("Failed to write byte data");
}
}
uint16_t SMBus::readWordData(int i2c_addr, uint8_t reg, bool force) {
setSlaveAddress(i2c_addr);
// Write the register address we want to read from
if (write(fileDescriptor, ®, 1) != 1) {
throw std::runtime_error("Failed to write register address");
}
// Read the data from the register
uint16_t data;
if (read(fileDescriptor, &data, 2) != 2) {
throw std::runtime_error("Failed to read word data");
}
return data;
}
void SMBus::writeWordData(int i2c_addr, uint8_t reg, uint16_t value, bool force) {
setSlaveAddress(i2c_addr);
// Write the register address followed by the data
uint8_t buffer[3] = { reg, static_cast<uint8_t>(value & 0xFF), static_cast<uint8_t>((value >> 8) & 0xFF) };
if (write(fileDescriptor, buffer, 3) != 3) {
throw std::runtime_error("Failed to write word data");
}
}
std::vector<uint8_t> SMBus::readBlockData(int i2c_addr, uint8_t reg, bool force) {
setSlaveAddress(i2c_addr);
// Write the register address we want to read from
if (write(fileDescriptor, ®, 1) != 1) {
throw std::runtime_error("Failed to write register address");
}
// Read the block of data
std::vector<uint8_t> data(32); // Assuming max block size of 32 bytes
int length = read(fileDescriptor, data.data(), data.size());
if (length < 0) {
throw std::runtime_error("Failed to read block data");
}
data.resize(length); // Adjust the vector size to actual data length
return data;
}
void SMBus::writeBlockData(int i2c_addr, uint8_t reg, const std::vector<uint8_t>& data, bool force) {
setSlaveAddress(i2c_addr);
// Prepare the buffer to send
std::vector<uint8_t> buffer(1 + data.size());
buffer[0] = reg;
std::copy(data.begin(), data.end(), buffer.begin() + 1);
// Write the buffer
if (write(fileDescriptor, buffer.data(), buffer.size()) != static_cast<ssize_t>(buffer.size())) {
throw std::runtime_error("Failed to write block data");
}
}
} // namespace ElectonLink
} // namespace X
#endif