Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
I2C.cxx
Go to the documentation of this file.
1
34#include <cstdint>
35#include <fcntl.h>
36#include "Devtab.hxx"
37#include "I2C.hxx"
38
45ssize_t I2C::read(File *file, void *buf, size_t count)
46{
47 int result;
48
49 if ((file->flags & O_ACCMODE) == O_WRONLY)
50 {
51 return -EBADF;
52 }
53
54 struct i2c_msg msg;
55 msg.addr = (uintptr_t)file->priv;
56 msg.flags = I2C_M_RD;
57 msg.len = count;
58 msg.buf = (uint8_t*)buf;
59
60 lock_.lock();
61 result = transfer(&msg, true);
62 lock_.unlock();
63
64 return result;
65}
66
73ssize_t I2C::write(File *file, const void *buf, size_t count)
74{
75 int result;
76
77 if ((file->flags & O_ACCMODE) == O_RDONLY)
78 {
79 return -EBADF;
80 }
81
82 struct i2c_msg msg;
83 msg.addr = (uintptr_t)file->priv;
84 msg.flags = 0;
85 msg.len = count;
86 msg.buf = (uint8_t*)buf;
87
88 lock_.lock();
89 result = transfer(&msg, true);
90 lock_.unlock();
91
92 return result;
93}
94
101int I2C::ioctl(File *file, unsigned long int key, unsigned long data)
102{
103 HASSERT(IOC_TYPE(key) == I2C_MAGIC);
104
105 switch (key)
106 {
107 default:
108 return -EINVAL;
109 case I2C_SLAVE:
110 file->priv = (void*)data;
111 break;
112 case I2C_RDWR:
113 {
114 struct i2c_rdwr_ioctl_data *rdwr_data = (struct i2c_rdwr_ioctl_data*)data;
115 return transfer_messages(rdwr_data->msgs, rdwr_data->nmsgs);
116 }
117 case I2C_SMBUS:
118 return smbus(file, data);
119 }
120 return 0;
121}
122
128int I2C::transfer_messages(struct i2c_msg *msgs, int num)
129{
130 HASSERT(num > 0);
131
132 int count = 0;
133 int result;
134
135 lock_.lock();
136 for (int i = 0; i < num; ++i)
137 {
138 count += msgs[i].len;
139 result = transfer(msgs + i, (num == (i + 1)));
140 if (result < 0)
141 {
142 lock_.unlock();
143 return result;
144 }
145 }
146 lock_.unlock();
147
148 return count;
149}
150
156int I2C::smbus(File *file, unsigned long data)
157{
158 struct i2c_smbus_ioctl_data *sm_data = (struct i2c_smbus_ioctl_data *)data;
159
160 /* check that we have a valid transaction type */
161 if ((sm_data->size != I2C_SMBUS_QUICK) &&
162 (sm_data->size != I2C_SMBUS_BYTE) &&
163 (sm_data->size != I2C_SMBUS_BYTE_DATA) &&
164 (sm_data->size != I2C_SMBUS_WORD_DATA) &&
165 (sm_data->size != I2C_SMBUS_PROC_CALL) &&
166 (sm_data->size != I2C_SMBUS_BLOCK_DATA) &&
167 (sm_data->size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
168 (sm_data->size != I2C_SMBUS_BLOCK_PROC_CALL) &&
169 (sm_data->size != I2C_SMBUS_I2C_BLOCK_DATA))
170 {
171 return -EINVAL;
172 }
173
174 /* check that we have a read or write */
175 if ((sm_data->read_write != I2C_SMBUS_READ) &&
176 (sm_data->read_write != I2C_SMBUS_WRITE))
177 {
178 return -EINVAL;
179 }
180
182 return 0;
183}
184
ssize_t write(File *file, const void *buf, size_t count) OVERRIDE
Write to a file or device.
Definition I2C.cxx:73
int smbus(File *file, unsigned long data)
Request an smbus (ioctl) transaction.
Definition I2C.cxx:156
ssize_t read(File *file, void *buf, size_t count) OVERRIDE
Read from a file or device.
Definition I2C.cxx:45
int ioctl(File *file, unsigned long int key, unsigned long data) OVERRIDE
Request an ioctl transaction.
Definition I2C.cxx:101
virtual int transfer(struct i2c_msg *msg, bool stop)=0
Method to transmit/receive the data.
int transfer_messages(struct i2c_msg *msgs, int num)
Conduct multiple message transfers with one stop at the end.
Definition I2C.cxx:128
OSMutex lock_
protects internal structures.
Definition Devtab.hxx:588
void lock()
Lock a mutex.
Definition OS.hxx:446
void unlock()
Unlock a mutex.
Definition OS.hxx:453
#define IOC_TYPE(_num)
Decode ioctl type.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
File information.
Definition Devtab.hxx:52
int flags
open flags
Definition Devtab.hxx:63
void * priv
file reference specific data "pointer"
Definition Devtab.hxx:57