From d960673681db074f99078a946c663d6d3e58c751 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Mon, 24 Oct 2016 09:34:19 +0200 Subject: [PATCH] drivers: pn532_i2c: Add retry on error mechanism Currently, we very occasionally can EXNIO errors from pn532_i2c_write() -> i2c_write() -> write(). This may happen about once every 30 seconds. Based from the kernel sources, EXNIO happens if the chip no longer responds to its own address. To make sure we do not loose any sent packets, we retry to send PN532_SEND_RETRIES number of times. Since we miss 1 every 30 or so seconds, doing 1 retry should be fine. This might be considered a hack as the failure may be some other timing related issue. Signed-off-by: Olliver Schinagl --- libnfc/drivers/pn532_i2c.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libnfc/drivers/pn532_i2c.c b/libnfc/drivers/pn532_i2c.c index 6315954..6d9e3fd 100644 --- a/libnfc/drivers/pn532_i2c.c +++ b/libnfc/drivers/pn532_i2c.c @@ -59,6 +59,13 @@ // I2C address of the PN532 chip. #define PN532_I2C_ADDR 0x24 +/* + * When sending lots of data, the pn532 occasionally fails to respond in time. + * Since it happens so rarely, lets try to fix it by re-sending the data. This + * define allows for fine tuning the number of retries. + */ +#define PN532_SEND_RETRIES 3 + // Internal data structs const struct pn53x_io pn532_i2c_io; @@ -368,6 +375,7 @@ static int pn532_i2c_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout) { int res = 0; + uint8_t retries; // Discard any existing data ? @@ -403,7 +411,13 @@ pn532_i2c_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int return pnd->last_error; } - res = pn532_i2c_write(DRIVER_DATA(pnd)->dev, abtFrame, szFrame); + for (retries = PN532_SEND_RETRIES; retries > 0; retries--) { + res = pn532_i2c_write(DRIVER_DATA(pnd)->dev, abtFrame, szFrame); + if (res >= 0) + break; + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Failed to transmit data. Retries left: %d.", retries - 1); + } if (res < 0) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");