diff options
author | Yong Li <yong.b.li@linux.intel.com> | 2019-08-23 17:44:32 +0800 |
---|---|---|
committer | Vernon Mauery <vernon.mauery@linux.intel.com> | 2019-08-30 15:55:14 +0000 |
commit | 7dc4ac0246bfae3da04c11e7a2053d28acfde35c (patch) | |
tree | 90bb088e2fbf675a26f45ffff000ebfee38b09c4 | |
parent | bd0503a75067ea80072f6716b379694da134026d (diff) | |
download | phosphor-host-ipmid-7dc4ac0246bfae3da04c11e7a2053d28acfde35c.tar.gz phosphor-host-ipmid-7dc4ac0246bfae3da04c11e7a2053d28acfde35c.zip |
Move i2c WR api into libipmid
Move the low-level i2c write-read api into libipmid,
to allow provider libraries access to i2c without duplicating this code.
Tested:
I2c master write read command still works:
ipmitool i2c bus=2 0x9c 8 0
Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
Change-Id: I0d5f82cf46ecf871eebb47aae25537b5da1f2e6a
-rw-r--r-- | apphandler.cpp | 46 | ||||
-rw-r--r-- | include/ipmid/utils.hpp | 11 | ||||
-rw-r--r-- | libipmid/utils.cpp | 65 |
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 |