serprog: Refine flushing before synchronization

We used to wait for 1s before flushing buffers of the tty layer.
However, if the programmer had more data to send than would fit
into these buffers, it would continue to send after flushing the
latter. So we try to read all the data instead. The added loop
reads up to 512KiB and stops when no data is received for 10ms.
Overall, it should time out after at most 10s.

Tests show that an stm32-vserprog can be re-synchronized after
interrupted reads, where the old implementation failed. In case
synchronization is necessary, it also succeeds without notice-
able delay.

Change-Id: Iaa5dfceac0629381ca0924bb59b988525bacba3f
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/72996
Reviewed-by: Riku Viitanen <riku.viitanen@protonmail.com>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/serprog.c b/serprog.c
index 60e87a4..6cf87f0 100644
--- a/serprog.c
+++ b/serprog.c
@@ -196,7 +196,7 @@
 static int sp_synchronize(void)
 {
 	int i, ret;
-	unsigned char buf[8];
+	unsigned char buf[512];
 
 	ret = sp_test_sync();
 	if (ret < 0)
@@ -215,9 +215,18 @@
 	if (serialport_write_nonblock(buf, 8, 1, NULL) != 0) {
 		goto err_out;
 	}
-	/* A second should be enough to get all the answers to the buffer */
-	internal_delay(1000 * 1000);
-	sp_flush_incoming();
+	/* To drain large reading orders that exceed FIFO sizes, we try
+	   to read repeatedly until no data is received for 10ms. */
+	const int timeout_ms = 10;
+	/* Limit the loop to guarantee termination within 10s. */
+	const int limit = 1 << 10;
+	for (i = 0, ret = 0; i < limit && ret == 0; ++i) {
+		ret = serialport_read_nonblock(buf, sizeof(buf), timeout_ms, NULL);
+		if (ret < 0)
+			goto err_out;
+	}
+	if (i == limit)
+		goto err_out;
 
 	/* Then try up to 8 times to send syncnop and get the correct special *
 	 * return of NAK+ACK. Timing note: up to 10 characters, 10*50ms =     *