From a14d519212747a8a58dc48ddc4ffffb1cd88896f Mon Sep 17 00:00:00 2001
From: Daniel Friesel <daniel.friesel@uos.de>
Date: Fri, 18 Oct 2019 10:39:11 +0200
Subject: [PATCH] softi2c: handle SCL BUSY timeouts

---
 src/driver/soft_i2c.cc | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/driver/soft_i2c.cc b/src/driver/soft_i2c.cc
index 89f038b..285caef 100644
--- a/src/driver/soft_i2c.cc
+++ b/src/driver/soft_i2c.cc
@@ -127,7 +127,15 @@ bool SoftI2C::tx(unsigned char byte)
 		i2c_wait();
 		SCL_HIGH;
 		i2c_wait();
-		while (!gpio.read(scl)) ;
+
+		// Avoid hanging indefinitely if the bus / device is stuck
+		for (unsigned char i = 0; i < 200 && !gpio.read(scl); i++) {
+			i2c_wait();
+		}
+		if (!gpio.read(scl)) {
+			return false;
+		}
+
 		if (i == 8) {
 			if (!gpio.read(sda)) {
 				got_ack = 1;
@@ -146,7 +154,15 @@ unsigned char SoftI2C::rx(bool send_ack)
 		i2c_wait();
 		SCL_HIGH;
 		i2c_wait();
-		while (!gpio.read(scl)) ;
+
+		// Avoid hanging indefinitely if the bus / device is stuck
+		for (unsigned char i = 0; i < 200 && !gpio.read(scl); i++) {
+			i2c_wait();
+		}
+		if (!gpio.read(scl)) {
+			return false;
+		}
+
 		if ((i < 8) && gpio.read(sda)) {
 			byte |= 1 << (7 - i);
 		}
-- 
GitLab