xref: /openbmc/phosphor-bmc-code-mgmt/common/i2c/i2c.cpp (revision 37a301437cd5dfcd36dc8ecb1769163b262493b4)
1 #include "i2c.hpp"
2 
3 #include <unistd.h>
4 
5 extern "C"
6 {
7 #include <i2c/smbus.h>
8 #include <linux/i2c-dev.h>
9 #include <linux/i2c.h>
10 }
11 
12 namespace phosphor::i2c
13 {
14 
open()15 int I2C::open()
16 {
17     int ret = 0;
18     fd = ::open(busStr.c_str(), O_RDWR);
19     if (fd < 0)
20     {
21         return fd;
22     }
23 
24     ret = ioctl(fd, I2C_SLAVE_FORCE, deviceNode);
25     if (ret < 0)
26     {
27         close();
28         return ret;
29     }
30 
31     return 0;
32 }
33 
sendReceive(uint8_t * writeData,uint8_t writeSize,uint8_t * readData,uint8_t readSize) const34 sdbusplus::async::task<bool> I2C::sendReceive(
35     uint8_t* writeData, uint8_t writeSize, uint8_t* readData,
36     uint8_t readSize) const
37 {
38     bool result = true;
39 
40     if (fd <= 0)
41     {
42         result = false;
43     }
44     else
45     {
46         struct i2c_msg msg[2];
47         struct i2c_rdwr_ioctl_data readWriteData;
48         int msgIndex = 0;
49 
50         if (writeSize)
51         {
52             msg[msgIndex].addr = deviceNode;
53             msg[msgIndex].flags = 0;
54             msg[msgIndex].len = writeSize;
55             msg[msgIndex].buf = writeData;
56             msgIndex++;
57         }
58 
59         if (readSize)
60         {
61             msg[msgIndex].addr = deviceNode;
62             msg[msgIndex].flags = I2C_M_RD;
63             msg[msgIndex].len = readSize;
64             msg[msgIndex].buf = readData;
65             msgIndex++;
66         }
67 
68         readWriteData.msgs = msg;
69         readWriteData.nmsgs = msgIndex;
70 
71         if (ioctl(fd, I2C_RDWR, &readWriteData) < 0)
72         {
73             result = false;
74         }
75     }
76     co_return result;
77 }
78 
sendReceive(const std::vector<uint8_t> & writeData,std::vector<uint8_t> & readData) const79 bool I2C::sendReceive(const std::vector<uint8_t>& writeData,
80                       std::vector<uint8_t>& readData) const
81 {
82     bool result = true;
83 
84     if (fd <= 0)
85     {
86         return false;
87     }
88     else
89     {
90         struct i2c_msg msg[2];
91         struct i2c_rdwr_ioctl_data readWriteData;
92         int msgIndex = 0;
93 
94         if (!writeData.empty())
95         {
96             msg[msgIndex].addr = deviceNode;
97             msg[msgIndex].flags = 0;
98             msg[msgIndex].len = writeData.size();
99             msg[msgIndex].buf = const_cast<uint8_t*>(writeData.data());
100             msgIndex++;
101         }
102 
103         if (!readData.empty())
104         {
105             msg[msgIndex].addr = deviceNode;
106             msg[msgIndex].flags = I2C_M_RD;
107             msg[msgIndex].len = readData.size();
108             msg[msgIndex].buf = readData.data();
109             msgIndex++;
110         }
111 
112         readWriteData.msgs = msg;
113         readWriteData.nmsgs = msgIndex;
114 
115         if (ioctl(fd, I2C_RDWR, &readWriteData) < 0)
116         {
117             result = false;
118         }
119     }
120 
121     return result;
122 }
123 
close() const124 int I2C::close() const
125 {
126     return ::close(fd);
127 }
128 
129 } // namespace phosphor::i2c
130