serprog: Move synchronicity test into separate function

Extract the sequence to test for synchronicity into a new
function sp_test_sync().

Change-Id: I9e4aac5b8ac524804a3a8989c2794cdfaacb7b32
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/72994
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-by: Riku Viitanen <riku.viitanen@protonmail.com>
diff --git a/serprog.c b/serprog.c
index 90813fd..3c4e609 100644
--- a/serprog.c
+++ b/serprog.c
@@ -148,6 +148,45 @@
 }
 #endif
 
+static int sp_test_sync(void)
+{
+	int n;
+
+	unsigned char c = S_CMD_SYNCNOP;
+	if (serialport_write_nonblock(&c, 1, 1, NULL) != 0)
+		return -1;
+
+	for (n = 0; n < 10; n++) {
+		int ret = serialport_read_nonblock(&c, 1, 50, NULL);
+		if (ret < 0)
+			return -1;
+		if (ret > 0 || c != S_NAK)
+			continue;
+		ret = serialport_read_nonblock(&c, 1, 20, NULL);
+		if (ret < 0)
+			return -1;
+		if (ret > 0 || c != S_ACK)
+			continue;
+
+		c = S_CMD_SYNCNOP;
+		if (serialport_write_nonblock(&c, 1, 1, NULL) != 0)
+			return -1;
+		ret = serialport_read_nonblock(&c, 1, 500, NULL);
+		if (ret < 0)
+			return -1;
+		if (ret > 0 || c != S_NAK)
+			return 1;	/* soft fail */
+		ret = serialport_read_nonblock(&c, 1, 100, NULL);
+		if (ret > 0 || ret < 0)
+			return -1;
+		if (c != S_ACK)
+			return 1;	/* soft fail */
+		return 0;
+	}
+
+	return 1;	/* soft fail */
+}
+
 /* Synchronize: a bit tricky algorithm that tries to (and in my tests has *
  * always succeeded in) bring the serial protocol to known waiting-for-   *
  * command state - uses nonblocking I/O - rest of the driver uses         *
@@ -156,7 +195,7 @@
  * do is synchronize (eg. check that device is alive).			  */
 static int sp_synchronize(void)
 {
-	int i;
+	int i, ret;
 	unsigned char buf[8];
 	/* First sends 8 NOPs, then flushes the return data - should cause *
 	 * the device serial parser to get to a sane state, unless if it   *
@@ -174,41 +213,16 @@
 	 * up to 500ms per try, 8*0.5s = 4s; +1s (above) = up to 5s sync      *
 	 * attempt, ~1s if immediate success.                                 */
 	for (i = 0; i < 8; i++) {
-		int n;
-		unsigned char c = S_CMD_SYNCNOP;
-		if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
-			goto err_out;
-		}
 		msg_pdbg(".");
 		fflush(stdout);
-		for (n = 0; n < 10; n++) {
-			int ret = serialport_read_nonblock(&c, 1, 50, NULL);
-			if (ret < 0)
-				goto err_out;
-			if (ret > 0 || c != S_NAK)
-				continue;
-			ret = serialport_read_nonblock(&c, 1, 20, NULL);
-			if (ret < 0)
-				goto err_out;
-			if (ret > 0 || c != S_ACK)
-				continue;
-			c = S_CMD_SYNCNOP;
-			if (serialport_write_nonblock(&c, 1, 1, NULL) != 0) {
-				goto err_out;
-			}
-			ret = serialport_read_nonblock(&c, 1, 500, NULL);
-			if (ret < 0)
-				goto err_out;
-			if (ret > 0 || c != S_NAK)
-				break;	/* fail */
-			ret = serialport_read_nonblock(&c, 1, 100, NULL);
-			if (ret > 0 || ret < 0)
-				goto err_out;
-			if (c != S_ACK)
-				break;	/* fail */
-			msg_pdbg("\n");
-			return 0;
-		}
+
+		ret = sp_test_sync();
+		if (ret > 0)
+			continue;
+		if (ret < 0)
+			goto err_out;
+		msg_pdbg("\n");
+		return 0;
 	}
 err_out:
 	msg_perr("Error: cannot synchronize protocol - check communications and reset device?\n");