GCC Code Coverage Report


Directory: ./
File: Drv/LinuxI2cDriver/LinuxI2cDriver.cpp
Date: 2026-09-03 22:12:29
Exec Total Coverage
Lines: 0 56 0.0%
Functions: 0 6 0.0%
Branches: 0 50 0.0%

Line Branch Exec Source
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 <Drv/LinuxI2cDriver/LinuxI2cDriver.hpp>
14 #include <Fw/FPrimeBasicTypes.hpp>
15 #include <Fw/Logger/Logger.hpp>
16 #include "Fw/Types/Assert.hpp"
17
18 #include <fcntl.h> // required for I2C device configuration
19 #include <linux/i2c-dev.h> // required for constant definitions
20 #include <linux/i2c.h> // required for struct / constant definitions
21 #include <sys/ioctl.h> // required for I2C device usage
22 #include <unistd.h> // required for I2C device access
23 #include <cerrno>
24
25 namespace Drv {
26
27 // ----------------------------------------------------------------------
28 // Construction, initialization, and destruction
29 // ----------------------------------------------------------------------
30
31 LinuxI2cDriver ::LinuxI2cDriver(const char* const compName) : LinuxI2cDriverComponentBase(compName), m_fd(-1) {}
32
33 LinuxI2cDriver::~LinuxI2cDriver() {
34 if (-1 != this->m_fd) { // check if file is open
35 (void)::close(this->m_fd);
36 }
37 }
38
39 bool LinuxI2cDriver::open(const char* device) {
40 FW_ASSERT(device != nullptr);
41 this->m_fd = ::open(device, O_RDWR);
42 return (-1 != this->m_fd);
43 }
44
45 // ----------------------------------------------------------------------
46 // Handler implementations for user-defined typed input ports
47 // ----------------------------------------------------------------------
48
49 // Note this port handler is guarded, so we can make the ioctl call
50
51 Drv::I2cStatus LinuxI2cDriver ::write_handler(const FwIndexType portNum, U32 addr, Fw::Buffer& serBuffer) {
52 // Make sure file has been opened
53 if (-1 == this->m_fd) {
54 return I2cStatus::I2C_OPEN_ERR;
55 }
56
57 // select slave address
58 int stat = ioctl(this->m_fd, I2C_SLAVE, addr);
59 if (stat == -1) {
60 return I2cStatus::I2C_ADDRESS_ERR;
61 }
62 // make sure it isn't a null pointer
63 FW_ASSERT(serBuffer.getData() != nullptr);
64 FW_ASSERT_NO_OVERFLOW(serBuffer.getSize(), size_t);
65 // write data
66 ssize_t status_write = write(this->m_fd, serBuffer.getData(), static_cast<size_t>(serBuffer.getSize()));
67 if ((status_write == -1) || (static_cast<FwSizeType>(status_write) != serBuffer.getSize())) {
68 return I2cStatus::I2C_WRITE_ERR;
69 }
70 return I2cStatus::I2C_OK;
71 }
72
73 Drv::I2cStatus LinuxI2cDriver ::read_handler(const FwIndexType portNum, U32 addr, Fw::Buffer& serBuffer) {
74 // Make sure file has been opened
75 if (-1 == this->m_fd) {
76 return I2cStatus::I2C_OPEN_ERR;
77 }
78
79 // select slave address
80 int stat = ioctl(this->m_fd, I2C_SLAVE, addr);
81 if (stat == -1) {
82 return I2cStatus::I2C_ADDRESS_ERR;
83 }
84 // make sure it isn't a null pointer
85 FW_ASSERT(serBuffer.getData() != nullptr);
86 // read data
87 FW_ASSERT_NO_OVERFLOW(serBuffer.getSize(), size_t);
88 ssize_t status_read = read(this->m_fd, serBuffer.getData(), static_cast<size_t>(serBuffer.getSize()));
89 if ((status_read == -1) || (static_cast<FwSizeType>(status_read) != serBuffer.getSize())) {
90 return I2cStatus::I2C_READ_ERR;
91 }
92 return I2cStatus::I2C_OK;
93 }
94
95 Drv::I2cStatus LinuxI2cDriver ::writeRead_handler(const FwIndexType portNum, /*!< The port number*/
96 U32 addr,
97 Fw::Buffer& writeBuffer,
98 Fw::Buffer& readBuffer) {
99 // Make sure file has been opened
100 if (-1 == this->m_fd) {
101 return I2cStatus::I2C_OPEN_ERR;
102 }
103 FW_ASSERT(-1 != this->m_fd);
104
105 // make sure they are not null pointers
106 FW_ASSERT(writeBuffer.getData() != nullptr);
107 FW_ASSERT(readBuffer.getData() != nullptr);
108 // make sure downcasts are safe
109 FW_ASSERT_NO_OVERFLOW(addr, U16);
110 FW_ASSERT_NO_OVERFLOW(writeBuffer.getSize(), U16);
111 FW_ASSERT_NO_OVERFLOW(readBuffer.getSize(), U16);
112
113 struct i2c_msg rdwr_msgs[2];
114
115 // Start address
116 rdwr_msgs[0].addr = static_cast<U16>(addr);
117 rdwr_msgs[0].flags = 0; // write
118 rdwr_msgs[0].len = static_cast<U16>(writeBuffer.getSize());
119 rdwr_msgs[0].buf = writeBuffer.getData();
120
121 // Read buffer
122 rdwr_msgs[1].addr = static_cast<U16>(addr);
123 rdwr_msgs[1].flags = I2C_M_RD; // read
124 rdwr_msgs[1].len = static_cast<U16>(readBuffer.getSize());
125 rdwr_msgs[1].buf = readBuffer.getData();
126
127 struct i2c_rdwr_ioctl_data rdwr_data;
128 rdwr_data.msgs = rdwr_msgs;
129 rdwr_data.nmsgs = 2;
130
131 // Use ioctl to perform the combined write/read transaction
132 int stat = ioctl(this->m_fd, I2C_RDWR, &rdwr_data);
133
134 if (stat == -1) {
135 // Because we're using ioctl to perform the transaction we dont know exactly the type of error that occurred
136 return I2cStatus::I2C_OTHER_ERR;
137 }
138
139 return I2cStatus::I2C_OK;
140 }
141
142 } // end namespace Drv
143