12 #include <boost/exception/errinfo_errno.hpp> 13 #include <boost/exception/errinfo_file_name.hpp> 18 #include <sys/ioctl.h> 19 #include <linux/i2c.h> 20 #include <linux/i2c-dev.h> 22 namespace duds {
namespace hardware {
namespace interface {
namespace linux {
25 dev(devname), addr(devaddr) {
26 fd = open(
dev.c_str(), O_RDWR);
32 if ((
addr > 127) && (ioctl(
fd, I2C_TENBIT, 1) < 0)) {
38 if (ioctl(
fd, I2C_SLAVE,
addr) < 0) {
45 if (ioctl(
fd, I2C_PEC, pec ? 1 : 0) < 0) {
60 if (ioctl(
fd, I2C_SMBUS, &sdat) < 0) {
65 std::this_thread::yield();
69 boost::errinfo_file_name(
dev) <<
74 boost::errinfo_file_name(
dev) <<
82 boost::errinfo_file_name(
dev) <<
83 boost::errinfo_errno(res) <<
88 boost::errinfo_file_name(
dev) <<
93 boost::errinfo_file_name(
dev) <<
98 boost::errinfo_file_name(
dev) <<
103 boost::errinfo_file_name(
dev) <<
104 boost::errinfo_errno(res) <<
109 }
while (res == EAGAIN);
113 i2c_smbus_ioctl_data sdat = {
114 .read_write = (std::uint8_t)(out ? I2C_SMBUS_READ : I2C_SMBUS_WRITE),
116 .size = I2C_SMBUS_QUICK,
124 i2c_smbus_ioctl_data sdat = {
125 .read_write = I2C_SMBUS_READ,
127 .size = I2C_SMBUS_BYTE,
136 i2c_smbus_ioctl_data sdat = {
137 .read_write = I2C_SMBUS_WRITE,
139 .size = I2C_SMBUS_BYTE,
148 i2c_smbus_ioctl_data sdat = {
149 .read_write = I2C_SMBUS_READ,
151 .size = I2C_SMBUS_BYTE_DATA,
160 i2c_smbus_ioctl_data sdat = {
161 .read_write = I2C_SMBUS_WRITE,
163 .size = I2C_SMBUS_BYTE_DATA,
172 i2c_smbus_ioctl_data sdat = {
173 .read_write = I2C_SMBUS_READ,
175 .size = I2C_SMBUS_WORD_DATA,
184 i2c_smbus_ioctl_data sdat = {
185 .read_write = I2C_SMBUS_WRITE,
187 .size = I2C_SMBUS_WORD_DATA,
196 i2c_smbus_ioctl_data sdat = {
197 .read_write = I2C_SMBUS_READ,
199 .size = I2C_SMBUS_BLOCK_DATA,
203 std::memcpy(in, msg.block + 1, std::max(maxlen, (
int)msg.block[0]));
204 if (maxlen < (
int)msg.block[0]) {
206 boost::errinfo_file_name(
dev) <<
215 i2c_smbus_ioctl_data sdat = {
216 .read_write = I2C_SMBUS_READ,
218 .size = I2C_SMBUS_BLOCK_DATA,
222 in.resize(msg.block[0]);
223 std::memcpy(&(in[0]), msg.block + 1, msg.block[0]);
228 const std::uint8_t *out,
231 if ((len <= 0) || (len > 32)) {
237 i2c_smbus_ioctl_data sdat = {
238 .read_write = I2C_SMBUS_WRITE,
240 .size = I2C_SMBUS_BLOCK_DATA,
244 std::memcpy(msg.block + 1, out, len);
250 i2c_smbus_ioctl_data sdat = {
251 .read_write = I2C_SMBUS_WRITE,
253 .size = I2C_SMBUS_BLOCK_DATA,
263 const std::vector<std::uint8_t> &out,
264 std::vector<std::uint8_t> &in
266 if (out.size() > 32) {
272 i2c_smbus_ioctl_data sdat = {
273 .read_write = I2C_SMBUS_WRITE,
275 .size = I2C_SMBUS_BLOCK_DATA,
278 msg.block[0] = out.size();
279 std::memcpy(msg.block + 1, &(out[0]), out.size());
281 in.resize(msg.block[0]);
282 std::memcpy(&(in[0]), msg.block + 1, msg.block[0]);
DevSmbus(const std::string &devname, int devaddr, bool pec=true)
Opens the device file for the bus.
virtual void transmitByte(std::uint8_t byte)
Sends a single byte to the device.
A timeout occured while waiting to use the bus.
The attempted operation is not supported by the bus master.
virtual int receive(std::uint8_t cmd, std::uint8_t *in, const int maxlen)
Sends a command byte, then reads a block of data from the device.
The device did not respond to its address.
An attempt was made to use a non-existent SMBus bus.
~DevSmbus()
Closes the device file.
The device has failed to conform to the protocol.
The received message included a bad checksum and Packet Error Checking is in use. ...
virtual int address() const
Returns the address of the device that this object will attempt to communicate with.
boost::error_info< struct Info_smbusdevaddr, int > SmbusDeviceAddr
Provides the device (slave) address along with an error.
virtual void transmit(std::uint8_t cmd, const std::uint8_t *out, const int len)
Sends a command byte and a block of data to the device.
Base class for all errors specific to SMBus communications and used for very general errors...
virtual std::uint8_t receiveByte()
Read a single byte from the device without sending a command/register byte first. ...
int addr
The device (slave) address; used for error reporting.
The operation took too long.
int fd
The file descriptor for the open device.
A message of an invalid length was specified, or a message too big for a buffer was received...
void io(i2c_smbus_ioctl_data &sdat)
Sends I/O requests to the kernel, then checks for an error and if found throws the appropriate except...
std::string dev
Stores the device file name for later error reporting.
virtual std::uint16_t receiveWord(std::uint8_t cmd)
Sends a command byte, then reads a word, two bytes, from the device.
virtual void transmitWord(std::uint8_t cmd, std::uint16_t word)
Sends a command byte and a data word to the device.
virtual std::uint16_t call(std::uint8_t cmd, std::uint16_t word)
Does a process call operation.
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
virtual void transmitBool(bool out)
Sends a single bit to the device.