From c3d9b86662ceec2f8e9e3c6fe0092fb7f11e0aa5 Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Tue, 21 Mar 2017 07:12:07 -0600 Subject: [PATCH] input/mxt: prevent overriding i2c transfer return value put_reg/get_reg function was overriding i2c transfer error code with i2creset return value, that lead to OK status although actual transfer failed. Signed-off-by: Juha Niskanen Reported-by: Harri Luhtala --- drivers/input/mxt.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/input/mxt.c b/drivers/input/mxt.c index f19c2bb0be..dcd26a2b19 100644 --- a/drivers/input/mxt.c +++ b/drivers/input/mxt.c @@ -88,6 +88,10 @@ #define INVALID_POSITION 0x1000 +/* Maximum number of retries */ + +#define MAX_RETRIES 3 + /* Get a 16-bit value in little endian order (not necessarily aligned). The * source data is in little endian order. The host byte order does not * matter in this case. @@ -311,7 +315,7 @@ static int mxt_getreg(FAR struct mxt_dev_s *priv, uint16_t regaddr, /* Try up to three times to read the register */ - for (retries = 1; retries <= 3; retries++) + for (retries = 1; retries <= MAX_RETRIES; retries++) { iinfo("retries=%d regaddr=%04x buflen=%d\n", retries, regaddr, buflen); @@ -342,15 +346,20 @@ static int mxt_getreg(FAR struct mxt_dev_s *priv, uint16_t regaddr, if (ret < 0) { #ifdef CONFIG_I2C_RESET - /* Perhaps the I2C bus is locked up? Try to shake the bus free */ + /* Perhaps the I2C bus is locked up? Try to shake the bus free. + * Don't bother with the reset if this was the last attempt. + */ - iwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret); - - ret = I2C_RESET(priv->i2c); - if (ret < 0) + if (retries < MAX_RETRIES) { - ierr("ERROR: I2C_RESET failed: %d\n", ret); - break; + iwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret); + + ret = I2C_RESET(priv->i2c); + if (ret < 0) + { + ierr("ERROR: I2C_RESET failed: %d\n", ret); + break; + } } #else ierr("ERROR: I2C_TRANSFER failed: %d\n", ret); @@ -385,7 +394,7 @@ static int mxt_putreg(FAR struct mxt_dev_s *priv, uint16_t regaddr, /* Try up to three times to read the register */ - for (retries = 1; retries <= 3; retries++) + for (retries = 1; retries <= MAX_RETRIES; retries++) { iinfo("retries=%d regaddr=%04x buflen=%d\n", retries, regaddr, buflen); @@ -416,14 +425,19 @@ static int mxt_putreg(FAR struct mxt_dev_s *priv, uint16_t regaddr, if (ret < 0) { #ifdef CONFIG_I2C_RESET - /* Perhaps the I2C bus is locked up? Try to shake the bus free */ + /* Perhaps the I2C bus is locked up? Try to shake the bus free. + * Don't bother with the reset if this was the last attempt. + */ - iwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret); - - ret = I2C_RESET(priv->i2c); - if (ret < 0) + if (retries < MAX_RETRIES) { - ierr("ERROR: I2C_RESET failed: %d\n", ret); + iwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret); + + ret = I2C_RESET(priv->i2c); + if (ret < 0) + { + ierr("ERROR: I2C_RESET failed: %d\n", ret); + } } #else ierr("ERROR: I2C_TRANSFER failed: %d\n", ret);