From eeaeaf1bb9c3acf219a588793005c18481e040d0 Mon Sep 17 00:00:00 2001 From: Robert Zieba Date: Tue, 26 Apr 2022 10:31:05 -0600 Subject: 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 Change-Id: Id4aaf727048329776311eec5d392aafbd1eef2b8 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3605884 Reviewed-by: Diana Z Commit-Queue: Diana Z --- common/i2c_controller.c | 32 +++++++++++++++++++++++++------- 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 @@ -441,6 +441,18 @@ int i2c_is_busy(int port); */ int i2c_unwedge(int port); +/** + * Read read using smbus read block protocol. + * Read bytestream from : with format: + * [length_N] [byte_0] [byte_1] ... [byte_N] + * + * : the max length of receiving buffer + * == 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 : with format: -- cgit v1.2.1