diff options
author | Robert Zieba <robertzieba@google.com> | 2022-04-26 10:31:05 -0600 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-05-05 16:19:56 +0000 |
commit | eeaeaf1bb9c3acf219a588793005c18481e040d0 (patch) | |
tree | 561d5c9d54a0947c16c78577b044b698a1881f6f | |
parent | d767b1e4ac93b8e84110df19edc79a44bb789f76 (diff) | |
download | chrome-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.c | 32 | ||||
-rw-r--r-- | include/i2c.h | 12 |
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] |