From e44b866716b360b9126b7fba63499ac278340f78 Mon Sep 17 00:00:00 2001
From: joerg_wunsch <joerg_wunsch@81a1dc3b-b13d-400b-aceb-764788c761c2>
Date: Wed, 11 May 2005 17:00:11 +0000
Subject: [PATCH] Try reading/writing more than one byte at a time, to improve
 overall performance.

Note that many consumers still read one byte at a time though.

This patch has once been submitted to me by Bernd Walter
<ticso@cicely.de>, minor tweak by me (mainly to get it running under
Linux, too).


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@459 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 ser_posix.c | 41 +++++++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 14 deletions(-)

diff --git a/ser_posix.c b/ser_posix.c
index 39947b8c..b8b6986e 100644
--- a/ser_posix.c
+++ b/ser_posix.c
@@ -115,6 +115,14 @@ int serial_setspeed(int fd, long baud)
     return -errno;
   }
 
+#if 0
+  /*
+   * set non blocking mode
+   */
+  rc = fcntl(fd, F_GETFL, 0);
+  fcntl(fd, F_SETFL, rc | O_NONBLOCK);
+#endif
+
   return 0;
 }
 
@@ -159,7 +167,7 @@ void serial_close(int fd)
 
 int serial_send(int fd, char * buf, size_t buflen)
 {
-  struct timeval timeout;
+  struct timeval timeout, to2;
   fd_set wfds;
   int nfds;
   int rc;
@@ -193,13 +201,14 @@ int serial_send(int fd, char * buf, size_t buflen)
 
   timeout.tv_sec = 0;
   timeout.tv_usec = 500000;
+  to2 = timeout;
 
   while (len) {
+  reselect:
     FD_ZERO(&wfds);
     FD_SET(fd, &wfds);
 
-  reselect:
-    nfds = select(fd+1, NULL, &wfds, NULL, &timeout);
+    nfds = select(fd+1, NULL, &wfds, NULL, &to2);
     if (nfds == 0) {
       if (verbose >= 1)
 	fprintf(stderr,
@@ -208,7 +217,7 @@ int serial_send(int fd, char * buf, size_t buflen)
       exit(1);
     }
     else if (nfds == -1) {
-      if (errno == EINTR) {
+      if (errno == EINTR || errno == EAGAIN) {
         goto reselect;
       }
       else {
@@ -218,14 +227,14 @@ int serial_send(int fd, char * buf, size_t buflen)
       }
     }
 
-    rc = write(fd, p, 1);
+    rc = write(fd, p, (len > 1024) ? 1024 : len);
     if (rc < 0) {
       fprintf(stderr, "%s: serial_send(): write error: %s\n",
               progname, strerror(errno));
       exit(1);
     }
-    p++;
-    len--;
+    p += rc;
+    len -= rc;
   }
 
   return 0;
@@ -234,7 +243,7 @@ int serial_send(int fd, char * buf, size_t buflen)
 
 int serial_recv(int fd, char * buf, size_t buflen)
 {
-  struct timeval timeout;
+  struct timeval timeout, to2;
   fd_set rfds;
   int nfds;
   int rc;
@@ -244,13 +253,14 @@ int serial_recv(int fd, char * buf, size_t buflen)
 
   timeout.tv_sec  = serial_recv_timeout / 1000L;
   timeout.tv_usec = (serial_recv_timeout % 1000L) * 1000;
+  to2 = timeout;
 
   while (len < buflen) {
+  reselect:
     FD_ZERO(&rfds);
     FD_SET(fd, &rfds);
 
-  reselect:
-    nfds = select(fd+1, &rfds, NULL, NULL, &timeout);
+    nfds = select(fd+1, &rfds, NULL, NULL, &to2);
     if (nfds == 0) {
       if (verbose > 1)
 	fprintf(stderr,
@@ -259,7 +269,10 @@ int serial_recv(int fd, char * buf, size_t buflen)
       return -1;
     }
     else if (nfds == -1) {
-      if (errno == EINTR) {
+      if (errno == EINTR || errno == EAGAIN) {
+	fprintf(stderr,
+		"%s: serial_recv(): programmer is not responding,reselecting\n",
+		progname);
         goto reselect;
       }
       else {
@@ -269,14 +282,14 @@ int serial_recv(int fd, char * buf, size_t buflen)
       }
     }
 
-    rc = read(fd, p, 1);
+    rc = read(fd, p, (buflen - len > 1024) ? 1024 : buflen - len);
     if (rc < 0) {
       fprintf(stderr, "%s: serial_recv(): read error: %s\n",
               progname, strerror(errno));
       exit(1);
     }
-    p++;
-    len++;
+    p += rc;
+    len += rc;
   }
 
   p = buf;