i2c: Implement write function
Implement I2CDevice::write() by invoking i2c_smbus_write_xxx() APIs.
The code is referenced from i2c-tools' i2cset.c:
https://github.com/ev3dev/i2c-tools/blob/ev3dev-stretch/tools/i2cset.c
Tested: Verify on Witherspoon that it writes the PSU unlock upgrade
command and boot flag successfully.
Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: I9fb014c787ef3ebb2f7793a0d012b1d652ef069f
diff --git a/tools/i2c/i2c.cpp b/tools/i2c/i2c.cpp
index da121d8..76756be 100644
--- a/tools/i2c/i2c.cpp
+++ b/tools/i2c/i2c.cpp
@@ -83,6 +83,52 @@
}
}
+void I2CDevice::checkWriteFuncs(int type)
+{
+ unsigned long funcs;
+
+ /* Check adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0)
+ {
+ throw I2CException("Failed to get funcs", busStr, devAddr, errno);
+ }
+
+ switch (type)
+ {
+ case I2C_SMBUS_BYTE:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE))
+ {
+ throw I2CException("Missing SMBUS_WRITE_BYTE", busStr, devAddr);
+ }
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ {
+ throw I2CException("Missing SMBUS_WRITE_BYTE_DATA", busStr,
+ devAddr);
+ }
+ break;
+
+ case I2C_SMBUS_WORD_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA))
+ {
+ throw I2CException("Missing SMBUS_WRITE_WORD_DATA", busStr,
+ devAddr);
+ }
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
+ {
+ throw I2CException("Missing SMBUS_WRITE_BLOCK_DATA", busStr,
+ devAddr);
+ }
+ break;
+ default:
+ fprintf(stderr, "Unexpected read size type: %d\n", type);
+ assert(false);
+ }
+}
+
void I2CDevice::read(uint8_t& data)
{
checkReadFuncs(I2C_SMBUS_BYTE);
@@ -132,30 +178,43 @@
void I2CDevice::write(uint8_t data)
{
- // TODO
- (void)data;
+ checkWriteFuncs(I2C_SMBUS_BYTE);
+
+ if (i2c_smbus_write_byte(fd, data) < 0)
+ {
+ throw I2CException("Failed to write byte", busStr, devAddr, errno);
+ }
}
void I2CDevice::write(uint8_t addr, uint8_t data)
{
- // TODO
- (void)addr;
- (void)data;
+ checkWriteFuncs(I2C_SMBUS_BYTE_DATA);
+
+ if (i2c_smbus_write_byte_data(fd, addr, data) < 0)
+ {
+ throw I2CException("Failed to write byte data", busStr, devAddr, errno);
+ }
}
void I2CDevice::write(uint8_t addr, uint16_t data)
{
- // TODO
- (void)addr;
- (void)data;
+ checkWriteFuncs(I2C_SMBUS_WORD_DATA);
+
+ if (i2c_smbus_write_word_data(fd, addr, data) < 0)
+ {
+ throw I2CException("Failed to write word data", busStr, devAddr, errno);
+ }
}
void I2CDevice::write(uint8_t addr, uint8_t size, const uint8_t* data)
{
- // TODO
- (void)addr;
- (void)size;
- (void)data;
+ checkWriteFuncs(I2C_SMBUS_BLOCK_DATA);
+
+ if (i2c_smbus_write_block_data(fd, addr, size, data) < 0)
+ {
+ throw I2CException("Failed to write block data", busStr, devAddr,
+ errno);
+ }
}
std::unique_ptr<I2CInterface> I2CDevice::create(uint8_t busId, uint8_t devAddr)
diff --git a/tools/i2c/i2c.hpp b/tools/i2c/i2c.hpp
index 7fe064f..befeaba 100644
--- a/tools/i2c/i2c.hpp
+++ b/tools/i2c/i2c.hpp
@@ -53,6 +53,17 @@
*/
void checkReadFuncs(int type);
+ /** @brief Check i2c adapter write functionality
+ *
+ * Check if the i2c adapter has the functionality specified by the SMBus
+ * transaction type
+ *
+ * @param[in] type - The SMBus transaction type defined in linux/i2c.h
+ *
+ * @throw I2CException if the function is not supported
+ */
+ void checkWriteFuncs(int type);
+
public:
~I2CDevice()
{