From 645d61251bb4f8894b0a2f58c3e71d7cf0bd086f Mon Sep 17 00:00:00 2001
From: Robert Spitzenpfeil <robert@linuxbox.site>
Date: Sat, 16 Jul 2011 17:16:16 +0200
Subject: [PATCH 3/3] Added serial_toggle_dtr_rts().

---
 arduino.c   |   22 ++++++++++++++++++----
 ser_posix.c |   24 +++++++++++++++++++++++-
 serial.h    |    2 ++
 3 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/arduino.c b/arduino.c
index b62bf2f..2588424 100644
--- a/arduino.c
+++ b/arduino.c
@@ -130,12 +130,26 @@ static int arduino_open(PROGRAMMER * pgm, char * port)
    * 
    */
   
-  /* Set DTR and RTS to HIGH */
-  serial_set_dtr_rts(&pgm->fd, 1);
+
+  /* 
+   * If DTR is initially high:
+   *
+   * HIGH-->LOW-->HIGH: reset pulse generated on 1st edge (falling)
+   *
+   *
+   * if DTR is initially low:
+   *
+   * LOW-->HIGH-->LOW: reset pulse generated on 2nd edge (falling)
+   *
+   *
+   * The time difference between the two edges shouldn't matter.
+   *
+   */
+
+  serial_toggle_dtr_rts(&pgm->fd);
   usleep(50*1000);
 
-  /* Set DTR and RTS back to LOW */
-  serial_set_dtr_rts(&pgm->fd, 0);
+  serial_toggle_dtr_rts(&pgm->fd);
   usleep(50*1000);
 
   /*
diff --git a/ser_posix.c b/ser_posix.c
index 4121b1b..879b9cc 100644
--- a/ser_posix.c
+++ b/ser_posix.c
@@ -217,7 +217,6 @@ net_open(const char *port, union filedescriptor *fdp)
   fdp->ifd = fd;
 }
 
-
 static int ser_set_dtr_rts(union filedescriptor *fdp, int is_on)
 {
   unsigned int	ctl;
@@ -247,6 +246,28 @@ static int ser_set_dtr_rts(union filedescriptor *fdp, int is_on)
   return 0;
 }
 
+static int ser_toggle_dtr_rts(union filedescriptor *fdp)
+{
+  unsigned int	ctl;
+  int           r;
+
+  r = ioctl(fdp->ifd, TIOCMGET, &ctl);
+  if (r < 0) {
+    perror("ioctl(\"TIOCMGET\")");
+    return -1;
+  }
+
+  ctl ^= (TIOCM_DTR | TIOCM_RTS);
+
+  r = ioctl(fdp->ifd, TIOCMSET, &ctl);
+  if (r < 0) {
+    perror("ioctl(\"TIOCMSET\")");
+    return -1;
+  }
+
+  return 0;
+}
+
 static void ser_open(char * port, long baud, union filedescriptor *fdp)
 {
   int rc;
@@ -493,6 +514,7 @@ struct serial_device serial_serdev =
   .recv = ser_recv,
   .drain = ser_drain,
   .set_dtr_rts = ser_set_dtr_rts,
+  .toggle_dtr_rts = ser_toggle_dtr_rts,
   .flags = SERDEV_FL_CANSETSPEED,
 };
 
diff --git a/serial.h b/serial.h
index 9e9476e..9b85fdc 100644
--- a/serial.h
+++ b/serial.h
@@ -53,6 +53,7 @@ struct serial_device
   int (*drain)(union filedescriptor *fd, int display);
 
   int (*set_dtr_rts)(union filedescriptor *fd, int is_on);
+  int (*toggle_dtr_rts)(union filedescriptor *fd);
 
   int flags;
 #define SERDEV_FL_NONE         0x0000 /* no flags */
@@ -72,5 +73,6 @@ extern struct serial_device avrdoper_serdev;
 #define serial_recv (serdev->recv)
 #define serial_drain (serdev->drain)
 #define serial_set_dtr_rts (serdev->set_dtr_rts)
+#define serial_toggle_dtr_rts (serdev->toggle_dtr_rts)
 
 #endif /* serial_h */
-- 
1.7.6

