summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Zieba <robertzieba@google.com>2022-04-26 10:31:05 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-05-05 16:19:56 +0000
commiteeaeaf1bb9c3acf219a588793005c18481e040d0 (patch)
tree561d5c9d54a0947c16c78577b044b698a1881f6f
parentd767b1e4ac93b8e84110df19edc79a44bb789f76 (diff)
downloadchrome-ec-eeaeaf1bb9c3acf219a588793005c18481e040d0.tar.gz
i2c_controller: Add i2c_read_sized_block function
Currently there is `i2c_read_string` that reads data in the form `[Length] [byte 0] ... [byte Length-1]`. However this function only reads null terminated strings. This commit adds `i2c_read_sized_block` to support reading a general block of data with a length. This commit also re-implements `i2c_read_string` in terms of `i2c_read_sized_block` This changes the behavior of `i2c_read_string` to produce an empty string on failure. BUG=b:228589840 TEST=Verified that battery strings are read properly, used i2ctrace to verify that `i2c_read_sized_block` reads the correct number of bytes BRANCH=none Signed-off-by: Robert Zieba <robertzieba@google.com> Change-Id: Id4aaf727048329776311eec5d392aafbd1eef2b8 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3605884 Reviewed-by: Diana Z <dzigterman@chromium.org> Commit-Queue: Diana Z <dzigterman@chromium.org>
-rw-r--r--common/i2c_controller.c32
-rw-r--r--include/i2c.h12
2 files changed, 37 insertions, 7 deletions
diff --git a/common/i2c_controller.c b/common/i2c_controller.c
index 5064deb073..f29b40b251 100644
--- a/common/i2c_controller.c
+++ b/common/i2c_controller.c
@@ -765,13 +765,16 @@ int i2c_write_offset16_block(const int port,
return rv;
}
-int i2c_read_string(const int port,
- const uint16_t addr_flags,
- int offset, uint8_t *data, int len)
+int i2c_read_sized_block(const int port,
+ const uint16_t addr_flags,
+ int offset, uint8_t *data, int max_len, int *read_len)
{
int i, rv;
uint8_t reg, block_length;
+ if (max_len == 0)
+ return EC_ERROR_INVAL;
+
if (!IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags))
return EC_ERROR_UNIMPLEMENTED;
@@ -791,8 +794,8 @@ int i2c_read_string(const int port,
if (rv)
continue;
- if (len && block_length > (len - 1))
- data_length = len - 1;
+ if (max_len && block_length > max_len)
+ data_length = max_len;
else
data_length = block_length;
@@ -805,7 +808,6 @@ int i2c_read_string(const int port,
rv = i2c_xfer_unlocked(port, addr_flags,
0, 0, data, data_length, 0);
- data[data_length] = 0;
if (rv)
continue;
@@ -839,12 +841,12 @@ int i2c_read_string(const int port,
rv = i2c_xfer_unlocked(port, addr_flags,
0, 0, data, data_length,
I2C_XFER_STOP);
- data[data_length] = 0;
if (rv)
continue;
}
/* execution reaches here implies rv=0, so we can exit now */
+ *read_len = data_length;
break;
}
@@ -852,6 +854,22 @@ int i2c_read_string(const int port,
return rv;
}
+int i2c_read_string(const int port,
+ const uint16_t addr_flags,
+ int offset, uint8_t *data, int len)
+{
+ int read_len = 0;
+ int rv = 0;
+
+ if (len == 0)
+ return EC_ERROR_INVAL;
+
+ rv = i2c_read_sized_block(port, addr_flags, offset, data, len - 1,
+ &read_len);
+ data[read_len] = 0;
+ return rv;
+}
+
int i2c_read_block(const int port, const uint16_t addr_flags, int offset,
uint8_t *data, int len)
{
diff --git a/include/i2c.h b/include/i2c.h
index 86c6e24e85..3ae1f60d97 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -442,6 +442,18 @@ int i2c_is_busy(int port);
int i2c_unwedge(int port);
/**
+ * Read read using smbus read block protocol.
+ * Read bytestream from <addr_flags>:<offset> with format:
+ * [length_N] [byte_0] [byte_1] ... [byte_N]
+ *
+ * <len> : the max length of receiving buffer
+ * <len> == 0 : buffer size > 255
+ */
+int i2c_read_sized_block(const int port,
+ const uint16_t addr_flags,
+ int offset, uint8_t *data, int max_len, int *read_len);
+
+/**
* Read ascii string using smbus read block protocol.
* Read bytestream from <addr_flags>:<offset> with format:
* [length_N] [byte_0] [byte_1] ... [byte_N-1]