summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apphandler.cpp46
-rw-r--r--include/ipmid/utils.hpp11
-rw-r--r--libipmid/utils.cpp65
3 files changed, 80 insertions, 42 deletions
diff --git a/apphandler.cpp b/apphandler.cpp
index 392d68a..a12e220 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -1191,9 +1191,6 @@ ipmi::RspType<std::vector<uint8_t>>
bool reserved, uint7_t slaveAddr, uint8_t readCount,
std::vector<uint8_t> writeData)
{
- i2c_rdwr_ioctl_data msgReadWrite = {0};
- i2c_msg i2cmsg[2] = {0};
-
if (readCount > maxIPMIWriteReadSize)
{
log<level::ERR>("Master write read command: Read count exceeds limit");
@@ -1219,46 +1216,11 @@ ipmi::RspType<std::vector<uint8_t>>
std::string i2cBus =
"/dev/i2c-" + std::to_string(static_cast<uint8_t>(busId));
- int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
- if (i2cDev < 0)
- {
- log<level::ERR>("Failed to open i2c bus",
- entry("BUS=%s", i2cBus.c_str()));
- return ipmi::responseInvalidFieldRequest();
- }
-
- int msgCount = 0;
- if (writeCount)
- {
- i2cmsg[msgCount].addr = static_cast<uint8_t>(slaveAddr);
- i2cmsg[msgCount].flags = 0x00;
- i2cmsg[msgCount].len = writeCount;
- i2cmsg[msgCount].buf = writeData.data();
- msgCount++;
- }
- if (readCount)
- {
- i2cmsg[msgCount].addr = static_cast<uint8_t>(slaveAddr);
- i2cmsg[msgCount].flags = I2C_M_RD;
- i2cmsg[msgCount].len = readCount;
- i2cmsg[msgCount].buf = readBuf.data();
- msgCount++;
- }
-
- msgReadWrite.msgs = i2cmsg;
- msgReadWrite.nmsgs = msgCount;
-
- int ret = ::ioctl(i2cDev, I2C_RDWR, &msgReadWrite);
- ::close(i2cDev);
-
- if (ret < 0)
- {
- log<level::ERR>("Master write read: Failed", entry("RET=%d", ret));
- return ipmi::responseUnspecifiedError();
- }
- if (readCount)
+ ipmi::Cc ret = ipmi::i2cWriteRead(i2cBus, static_cast<uint8_t>(slaveAddr),
+ writeData, readBuf);
+ if (ret != ipmi::ccSuccess)
{
- readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
+ return ipmi::response(ret);
}
return ipmi::responseSuccess(readBuf);
}
diff --git a/include/ipmid/utils.hpp b/include/ipmid/utils.hpp
index 9ef1488..45c9c1a 100644
--- a/include/ipmid/utils.hpp
+++ b/include/ipmid/utils.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <chrono>
+#include <ipmid/api-types.hpp>
#include <ipmid/types.hpp>
#include <optional>
#include <sdbusplus/server.hpp>
@@ -305,4 +306,14 @@ void createVLAN(sdbusplus::bus::bus& bus, const std::string& service,
uint32_t getVLAN(const std::string& path);
} // namespace network
+
+/** @brief Perform the low-level i2c bus write-read.
+ * @param[in] i2cBus - i2c bus device node name, such as /dev/i2c-2.
+ * @param[in] slaveAddr - i2c device slave address.
+ * @param[in] writeData - The data written to i2c device.
+ * @param[out] readBuf - Data read from the i2c device.
+ */
+ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
+ std::vector<uint8_t> writeData,
+ std::vector<uint8_t>& readBuf);
} // namespace ipmi
diff --git a/libipmid/utils.cpp b/libipmid/utils.cpp
index b8ba9a7..cc4b763 100644
--- a/libipmid/utils.cpp
+++ b/libipmid/utils.cpp
@@ -1,6 +1,12 @@
#include <arpa/inet.h>
#include <dirent.h>
+#include <fcntl.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <algorithm>
#include <chrono>
@@ -541,4 +547,63 @@ uint32_t getVLAN(const std::string& path)
}
} // namespace network
+
+ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
+ std::vector<uint8_t> writeData,
+ std::vector<uint8_t>& readBuf)
+{
+ // Open the i2c device, for low-level combined data write/read
+ int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
+ if (i2cDev < 0)
+ {
+ log<level::ERR>("Failed to open i2c bus",
+ phosphor::logging::entry("BUS=%s", i2cBus.c_str()));
+ return ipmi::ccInvalidFieldRequest;
+ }
+
+ const size_t writeCount = writeData.size();
+ const size_t readCount = readBuf.size();
+ int msgCount = 0;
+ i2c_msg i2cmsg[2] = {0};
+ if (writeCount)
+ {
+ // Data will be writtern to the slave address
+ i2cmsg[msgCount].addr = slaveAddr;
+ i2cmsg[msgCount].flags = 0x00;
+ i2cmsg[msgCount].len = writeCount;
+ i2cmsg[msgCount].buf = writeData.data();
+ msgCount++;
+ }
+ if (readCount)
+ {
+ // Data will be read into the buffer from the slave address
+ i2cmsg[msgCount].addr = slaveAddr;
+ i2cmsg[msgCount].flags = I2C_M_RD;
+ i2cmsg[msgCount].len = readCount;
+ i2cmsg[msgCount].buf = readBuf.data();
+ msgCount++;
+ }
+
+ i2c_rdwr_ioctl_data msgReadWrite = {0};
+ msgReadWrite.msgs = i2cmsg;
+ msgReadWrite.nmsgs = msgCount;
+
+ // Perform the combined write/read
+ int ret = ::ioctl(i2cDev, I2C_RDWR, &msgReadWrite);
+ ::close(i2cDev);
+
+ if (ret < 0)
+ {
+ log<level::ERR>("I2C WR Failed!",
+ phosphor::logging::entry("RET=%d", ret));
+ return ipmi::ccUnspecifiedError;
+ }
+ if (readCount)
+ {
+ readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
+ }
+
+ return ipmi::ccSuccess;
+}
+
} // namespace ipmi
OpenPOWER on IntegriCloud