F´ Flight Software - C/C++ Documentation NASA-v1.6.0
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LinuxI2cDriver.cpp
Go to the documentation of this file.
1// ======================================================================
2// \title LinuxI2cDriverComponentImpl.cpp
3// \author tcanham
4// \brief cpp file for LinuxI2cDriver component implementation class
5//
6// \copyright
7// Copyright 2009-2015, by the California Institute of Technology.
8// ALL RIGHTS RESERVED. United States Government Sponsorship
9// acknowledged.
10//
11// ======================================================================
12
13#include "Fw/Types/Assert.hpp"
14#include <FpConfig.hpp>
16#include <Fw/Logger/Logger.hpp>
17
18#include <unistd.h> // required for I2C device access
19#include <fcntl.h> // required for I2C device configuration
20#include <sys/ioctl.h> // required for I2C device usage
21#include <linux/i2c.h> // required for struct / constant definitions
22#include <linux/i2c-dev.h> // required for constant definitions
23#include <cerrno>
24
25#define DEBUG_PRINT 0
26
27namespace Drv {
28
29 // ----------------------------------------------------------------------
30 // Construction, initialization, and destruction
31 // ----------------------------------------------------------------------
32
33 LinuxI2cDriver ::
34 LinuxI2cDriver(
35 const char *const compName
36 ) : LinuxI2cDriverComponentBase(compName),
37 m_fd(-1)
38 {
39
40 }
41
42 void LinuxI2cDriver ::
43 init(
44 const NATIVE_INT_TYPE instance
45 )
46 {
47 LinuxI2cDriverComponentBase::init(instance);
48 }
49
52 {
53 if (-1 != this->m_fd) { // check if file is open
54 ::close(this->m_fd);
55 }
56 }
57
58 bool LinuxI2cDriver::open(const char* device) {
59 FW_ASSERT(device);
60 this->m_fd = ::open(device, O_RDWR);
61 return (-1 != this->m_fd);
62 }
63
64
65 // ----------------------------------------------------------------------
66 // Handler implementations for user-defined typed input ports
67 // ----------------------------------------------------------------------
68
69 // Note this port handler is guarded, so we can make the ioctl call
70
71 Drv::I2cStatus LinuxI2cDriver ::
72 write_handler(
73 const NATIVE_INT_TYPE portNum,
74 U32 addr,
75 Fw::Buffer &serBuffer
76 )
77 {
78 // Make sure file has been opened
79 if (-1 == this->m_fd) {
80 return I2cStatus::I2C_OPEN_ERR;
81 }
82
83#if DEBUG_PRINT
84 Fw::Logger::logMsg("I2c addr: 0x%02X\n",addr);
85 for (U32 byte = 0; byte < serBuffer.getSize(); byte++) {
86 Fw::Logger::logMsg("0x%02X ",serBuffer.getData()[byte]);
87
88 }
90#endif
91 // select slave address
92 int stat = ioctl(this->m_fd, I2C_SLAVE, addr);
93 if (stat == -1) {
94#if DEBUG_PRINT
95 Fw::Logger::logMsg("Status: %d Errno: %d\n", stat, errno);
96#endif
97 return I2cStatus::I2C_ADDRESS_ERR;
98 }
99 // make sure it isn't a null pointer
100 FW_ASSERT(serBuffer.getData());
101 // write data
102 stat = write(this->m_fd, serBuffer.getData(), serBuffer.getSize());
103 if (stat == -1) {
104#if DEBUG_PRINT
105 Fw::Logger::logMsg("Status: %d Errno: %d\n", stat, errno);
106#endif
107 return I2cStatus::I2C_WRITE_ERR;
108 }
109 return I2cStatus::I2C_OK;
110 }
111
112 Drv::I2cStatus LinuxI2cDriver ::
113 read_handler(
114 const NATIVE_INT_TYPE portNum,
115 U32 addr,
116 Fw::Buffer &serBuffer
117 )
118 {
119 // Make sure file has been opened
120 if (-1 == this->m_fd) {
121 return I2cStatus::I2C_OPEN_ERR;
122 }
123
124#if DEBUG_PRINT
125 Fw::Logger::logMsg("I2c addr: 0x%02X\n",addr);
126#endif
127 // select slave address
128 int stat = ioctl(this->m_fd, I2C_SLAVE, addr);
129 if (stat == -1) {
130#if DEBUG_PRINT
131 Fw::Logger::logMsg("Status: %d Errno: %d\n", stat, errno);
132#endif
133 return I2cStatus::I2C_ADDRESS_ERR;
134 }
135 // make sure it isn't a null pointer
136 FW_ASSERT(serBuffer.getData());
137 // read data
138 stat = read(this->m_fd, serBuffer.getData(), serBuffer.getSize());
139 if (stat == -1) {
140#if DEBUG_PRINT
141 Fw::Logger::logMsg("Status: %d Errno: %d\n", stat, errno);
142#endif
143 return I2cStatus::I2C_READ_ERR;
144 }
145#if DEBUG_PRINT
146 for (U32 byte = 0; byte < serBuffer.getSize(); byte++) {
147 Fw::Logger::logMsg("0x%02X ",serBuffer.getData()[byte]);
148
149 }
150 Fw::Logger::logMsg("\n");
151#endif
152 return I2cStatus::I2C_OK;
153 }
154
155 Drv::I2cStatus LinuxI2cDriver ::
156 writeRead_handler(
157 const NATIVE_INT_TYPE portNum,
158 U32 addr,
159 Fw::Buffer &writeBuffer,
160 Fw::Buffer &readBuffer
161 ){
162
163 // Make sure file has been opened
164 if (-1 == this->m_fd) {
165 return I2cStatus::I2C_OPEN_ERR;
166 }
167 FW_ASSERT(-1 != this->m_fd);
168
169 // make sure they are not null pointers
170 FW_ASSERT(writeBuffer.getData());
171 FW_ASSERT(readBuffer.getData());
172
173 #if DEBUG_PRINT
174 Fw::Logger::logMsg("I2c addr: 0x%02X\n",addr);
175 #endif
176
177 struct i2c_msg rdwr_msgs[2] = {
178 { // Start address
179 .addr = static_cast<U16>(addr),
180 .flags = 0, // write
181 .len = static_cast<U16>(writeBuffer.getSize()),
182 .buf = writeBuffer.getData()
183 },
184 { // Read buffer
185 .addr = static_cast<U16>(addr),
186 .flags = I2C_M_RD, // read
187 .len = static_cast<U16>(readBuffer.getSize()),
188 .buf = readBuffer.getData()
189 }
190 };
191
192 struct i2c_rdwr_ioctl_data rdwr_data = {
193 .msgs = rdwr_msgs,
194 .nmsgs = 2
195 };
196
197 //Use ioctl to perform the combined write/read transaction
198 NATIVE_INT_TYPE stat = ioctl(this->m_fd, I2C_RDWR, &rdwr_data);
199
200 if(stat == -1){
201 #if DEBUG_PRINT
202 Fw::Logger::logMsg("Status: %d Errno: %d\n", stat, errno);
203 #endif
204 //Because we're using ioctl to perform the transaction we dont know exactly the type of error that occurred
205 return I2cStatus::I2C_OTHER_ERR;
206 }
207
208#if DEBUG_PRINT
209 Fw::Logger::logMsg("Wrote:\n");
210 for (U32 byte = 0; byte < writeBuffer.getSize(); byte++) {
211 Fw::Logger::logMsg("0x%02X ",writeBuffer.getData()[byte]);
212
213 }
214 Fw::Logger::logMsg("\n");
215 Fw::Logger::logMsg("Read:\n");
216 for (U32 byte = 0; byte < readBuffer.getSize(); byte++) {
217 Fw::Logger::logMsg("0x%02X ",readBuffer.getData()[byte]);
218
219 }
220 Fw::Logger::logMsg("\n");
221#endif
222
223 return I2cStatus::I2C_OK;
224 }
225
226} // end namespace Drv
#define FW_ASSERT(...)
Definition Assert.hpp:7
PlatformIntType NATIVE_INT_TYPE
Definition BasicTypes.h:51
C++-compatible configuration header for fprime configuration.
bool open(const char *device)
U8 * getData() const
Definition Buffer.cpp:60
U32 getSize() const
Definition Buffer.cpp:64
static void logMsg(const char *fmt, POINTER_CAST a0=0, POINTER_CAST a1=0, POINTER_CAST a2=0, POINTER_CAST a3=0, POINTER_CAST a4=0, POINTER_CAST a5=0, POINTER_CAST a6=0, POINTER_CAST a7=0, POINTER_CAST a8=0, POINTER_CAST a9=0)
Definition Logger.cpp:18