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 /libipmid/utils.cpp | |
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
Diffstat (limited to 'libipmid/utils.cpp')
-rw-r--r-- | libipmid/utils.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
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 |