diff --git a/ChangeLog b/ChangeLog
index 48cb86a3..f5bc20cb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2003-03-12  Theodore A. Roth  <troth@openavr.org>
+
+	* Makefile.am (avrdude_SOURCES): Add avr910.[ch], serial.h and
+	ser_posix.c files.
+	* avr910.c: New file (stubs for avr910 serial programmer).
+	* avr910.h: New file.
+	* ser_posix.c: New file.
+	* ser_win32.c: New file (just stubs for now).
+	* serial.h: New file.
+	* stk500.c: Move all the code for accessing the posix serial ports
+	into ser_posix. This will make a native win32 port easier and allows
+	the avr910 programmer to share the serial code.
+
 2003-03-12  Theodore A. Roth  <troth@openavr.org>
 
 	* configure.ac (AC_INIT): Set version to 4.0.0cvs since we're done
diff --git a/Makefile.am b/Makefile.am
index 0f3813e8..589d5359 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -48,6 +48,8 @@ avrdude_SOURCES = \
 	lexer.l \
 	avr.c \
 	avr.h \
+	avr910.c \
+	avr910.h \
 	avrpart.h \
 	config.c \
 	config.h \
@@ -67,6 +69,9 @@ avrdude_SOURCES = \
 	ppi.c \
 	ppi.h \
 	ppiwin.c \
+	serial.h \
+	ser_posix.c \
+	ser_win32.c \
 	stk500.c \
 	stk500.h \
 	stk500_private.h \
diff --git a/avr910.c b/avr910.c
new file mode 100644
index 00000000..72de6b22
--- /dev/null
+++ b/avr910.c
@@ -0,0 +1,216 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2003  Theodore A. Roth  <troth@openavr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* $Id$ */
+
+/*
+ * avrdude interface for Atmel Low Cost Serial programmers which adher to the
+ * protocol described in application note avr910.
+ */
+
+#include "ac_cfg.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "avr.h"
+#include "pgm.h"
+#include "avr910.h"
+#include "serial.h"
+
+extern char * progname;
+extern int do_cycles;
+
+
+static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len)
+{
+  return serial_send(pgm->fd, buf, len);
+}
+
+
+static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len)
+{
+  return serial_recv(pgm->fd, buf, len);
+}
+
+
+static int avr910_drain(PROGRAMMER * pgm, int display)
+{
+  return serial_drain(pgm->fd, display);
+}
+
+
+static int avr910_rdy_led(PROGRAMMER * pgm, int value)
+{
+  return 0;
+}
+
+
+static int avr910_err_led(PROGRAMMER * pgm, int value)
+{
+  return 0;
+}
+
+
+static int avr910_pgm_led(PROGRAMMER * pgm, int value)
+{
+  return 0;
+}
+
+
+static int avr910_vfy_led(PROGRAMMER * pgm, int value)
+{
+  return 0;
+}
+
+
+/*
+ * issue the 'chip erase' command to the AVR device
+ */
+static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p)
+{
+  return 0;
+}
+
+/*
+ * issue the 'program enable' command to the AVR device
+ */
+static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p)
+{
+  return -1;
+}
+
+
+/*
+ * apply power to the AVR processor
+ */
+static void avr910_powerup(PROGRAMMER * pgm)
+{
+  return;
+}
+
+
+/*
+ * remove power from the AVR processor
+ */
+static void avr910_powerdown(PROGRAMMER * pgm)
+{
+  return;
+}
+
+
+/*
+ * initialize the AVR device and prepare it to accept commands
+ */
+static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
+{
+  return 0;
+}
+
+
+static int avr910_save(PROGRAMMER * pgm)
+{
+  return 0;
+}
+
+
+static void avr910_restore(PROGRAMMER * pgm)
+{
+  return;
+}
+
+
+static void avr910_disable(PROGRAMMER * pgm)
+{
+  return;
+}
+
+
+static void avr910_enable(PROGRAMMER * pgm)
+{
+  return;
+}
+
+
+/*
+ * transmit an AVR device command and return the results; 'cmd' and
+ * 'res' must point to at least a 4 byte data buffer
+ */
+static int avr910_cmd(PROGRAMMER * pgm, unsigned char cmd[4], 
+                      unsigned char res[4])
+{
+    return 0;
+}
+
+
+static void avr910_open(PROGRAMMER * pgm, char * port)
+{
+  strcpy(pgm->port, port);
+  pgm->fd = serial_open(port, 19200);
+
+  /*
+   * drain any extraneous input
+   */
+  avr910_drain (pgm, 0);
+}
+
+static void avr910_close(PROGRAMMER * pgm)
+{
+  serial_close(pgm->fd);
+  pgm->fd = -1;
+}
+
+
+static void avr910_display(PROGRAMMER * pgm, char * p)
+{
+  return;
+}
+
+
+void avr910_initpgm(PROGRAMMER * pgm)
+{
+  strcpy(pgm->type, "avr910");
+
+  /*
+   * mandatory functions
+   */
+  pgm->rdy_led        = avr910_rdy_led;
+  pgm->err_led        = avr910_err_led;
+  pgm->pgm_led        = avr910_pgm_led;
+  pgm->vfy_led        = avr910_vfy_led;
+  pgm->initialize     = avr910_initialize;
+  pgm->display        = avr910_display;
+  pgm->save           = avr910_save;
+  pgm->restore        = avr910_restore;
+  pgm->enable         = avr910_enable;
+  pgm->disable        = avr910_disable;
+  pgm->powerup        = avr910_powerup;
+  pgm->powerdown      = avr910_powerdown;
+  pgm->program_enable = avr910_program_enable;
+  pgm->chip_erase     = avr910_chip_erase;
+  pgm->cmd            = avr910_cmd;
+  pgm->open           = avr910_open;
+  pgm->close          = avr910_close;
+
+  /*
+   * optional functions
+   */
+}
diff --git a/avr910.h b/avr910.h
new file mode 100644
index 00000000..9ae392e1
--- /dev/null
+++ b/avr910.h
@@ -0,0 +1,29 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2003  Theodore A. Roth  <troth@openavr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* $Id$ */
+
+#ifndef __avr910_h__
+#define __avr910_h__
+
+#include "config.h"
+
+void avr910_initpgm (PROGRAMMER * pgm);
+
+#endif /* __avr910_h__ */
diff --git a/ser_posix.c b/ser_posix.c
new file mode 100644
index 00000000..51719e2f
--- /dev/null
+++ b/ser_posix.c
@@ -0,0 +1,298 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2003  Theodore A. Roth  <troth@openavr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* $Id$ */
+
+/*
+ * Posix serial interface for avrdude.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+
+extern char *progname;
+
+struct baud_mapping {
+  int baud;
+  speed_t speed;
+};
+
+/* There are a lot more baud rates we could handle, but what's the point? */
+
+static struct baud_mapping baud_lookup_table [] = {
+  { 1200,   B1200 },
+  { 2400,   B2400 },
+  { 4800,   B4800 },
+  { 9600,   B9600 },
+  { 19200,  B19200 },
+  { 38400,  B38400 },
+  { 57600,  B57600 },
+  { 115200, B115200 },
+  { 230400, B230400 },
+  { 0,      0 }                 /* Terminator. */
+};
+
+static speed_t serial_baud_lookup(int baud)
+{
+  struct baud_mapping *map = baud_lookup_table;
+
+  while (map->baud) {
+    if (map->baud == baud)
+      return map->speed;
+    map++;
+  }
+
+  fprintf(stderr, "%s: serial_baud_lookup(): unknown baud rate: %d", 
+          progname, baud);
+  exit(1);
+}
+
+static int serial_setattr(int fd, int baud)
+{
+  int rc;
+  struct termios termios;
+  speed_t speed = serial_baud_lookup (baud);
+  
+  if (!isatty(fd))
+    return -1;
+  
+  /*
+   * initialize terminal modes
+   */
+  rc = tcgetattr(fd, &termios);
+  if (rc < 0) {
+    fprintf(stderr, "%s: serial_setattr(): tcgetattr() failed, %s", 
+            progname, strerror(errno));
+    return -errno;
+  }
+
+  termios.c_iflag = 0;
+  termios.c_oflag = 0;
+  termios.c_cflag = 0;
+  termios.c_cflag |=   (CS8 | CREAD | CLOCAL);
+  termios.c_lflag = 0;
+  termios.c_cc[VMIN]  = 1;
+  termios.c_cc[VTIME] = 0;
+
+  cfsetospeed(&termios, speed);
+  cfsetispeed(&termios, speed);
+  
+  rc = tcsetattr(fd, TCSANOW, &termios);
+  if (rc < 0) {
+    fprintf(stderr, "%s: serial_setattr(): tcsetattr() failed, %s", 
+            progname, strerror(errno));
+    return -errno;
+  }
+
+  return 0;
+}
+
+
+int serial_open(char * port, int baud)
+{
+  int rc;
+  int fd;
+
+  /*
+   * open the serial port
+   */
+  fd = open(port, O_RDWR | O_NOCTTY /*| O_NONBLOCK*/);
+  if (fd < 0) {
+    fprintf(stderr, "%s: serial_open(): can't open device \"%s\": %s\n",
+            progname, port, strerror(errno));
+    exit(1);
+  }
+
+  /*
+   * set serial line attributes
+   */
+  rc = serial_setattr(fd, baud);
+  if (rc) {
+    fprintf(stderr, 
+            "%s: serial_open(): can't set attributes for device \"%s\"\n",
+            progname, port);
+    exit(1);
+  }
+
+  return fd;
+}
+
+
+void serial_close(int fd)
+{
+  /* FIXME: Should really restore the terminal to original state here. */
+
+  close(fd);
+}
+
+
+int serial_send(int fd, char * buf, size_t buflen)
+{
+  struct timeval timeout;
+  fd_set wfds;
+  int nfds;
+  int rc;
+
+  if (!buflen)
+    return 0;
+
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 500000;
+
+  while (buflen) {
+    FD_ZERO(&wfds);
+    FD_SET(fd, &wfds);
+
+  reselect:
+    nfds = select(fd+1, NULL, &wfds, NULL, &timeout);
+    if (nfds == 0) {
+      fprintf(stderr,
+              "%s: serial_send(): programmer is not responding\n",
+              progname);
+      exit(1);
+    }
+    else if (nfds == -1) {
+      if (errno == EINTR) {
+        goto reselect;
+      }
+      else {
+        fprintf(stderr, "%s: serial_send(): select(): %s\n",
+                progname, strerror(errno));
+        exit(1);
+      }
+    }
+
+    rc = write(fd, buf, 1);
+    if (rc < 0) {
+      fprintf(stderr, "%s: serial_send(): write error: %s\n",
+              progname, strerror(errno));
+      exit(1);
+    }
+    buf++;
+    buflen--;
+  }
+
+  return 0;
+}
+
+
+int serial_recv(int fd, char * buf, size_t buflen)
+{
+  struct timeval timeout;
+  fd_set rfds;
+  int nfds;
+  int rc;
+
+  timeout.tv_sec  = 5;
+  timeout.tv_usec = 0;
+
+  while (buflen) {
+    FD_ZERO(&rfds);
+    FD_SET(fd, &rfds);
+
+  reselect:
+    nfds = select(fd+1, &rfds, NULL, NULL, &timeout);
+    if (nfds == 0) {
+      fprintf(stderr, 
+              "%s: serial_recv(): programmer is not responding\n",
+              progname);
+      exit(1);
+    }
+    else if (nfds == -1) {
+      if (errno == EINTR) {
+        goto reselect;
+      }
+      else {
+        fprintf(stderr, "%s: serial_recv(): select(): %s\n",
+                progname, strerror(errno));
+        exit(1);
+      }
+    }
+
+    rc = read(fd, buf, 1);
+    if (rc < 0) {
+      fprintf(stderr, "%s: serial_recv(): read error: %s\n",
+              progname, strerror(errno));
+      exit(1);
+    }
+    buf++;
+    buflen--;
+  }
+
+  return 0;
+}
+
+
+int serial_drain(int fd, int display)
+{
+  struct timeval timeout;
+  fd_set rfds;
+  int nfds;
+  int rc;
+  unsigned char buf;
+
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 250000;
+
+  if (display) {
+    fprintf(stderr, "drain>");
+  }
+
+  while (1) {
+    FD_ZERO(&rfds);
+    FD_SET(fd, &rfds);
+
+  reselect:
+    nfds = select(fd+1, &rfds, NULL, NULL, &timeout);
+    if (nfds == 0) {
+      if (display) {
+        fprintf(stderr, "<drain\n");
+      }
+      
+      break;
+    }
+    else if (nfds == -1) {
+      if (errno == EINTR) {
+        goto reselect;
+      }
+      else {
+        fprintf(stderr, "%s: serial_drain(): select(): %s\n",
+                progname, strerror(errno));
+        exit(1);
+      }
+    }
+
+    rc = read(fd, &buf, 1);
+    if (rc < 0) {
+      fprintf(stderr, "%s: serial_drain(): read error: %s\n",
+              progname, strerror(errno));
+      exit(1);
+    }
+    if (display) {
+      fprintf(stderr, "%02x ", buf);
+    }
+  }
+
+  return 0;
+}
diff --git a/ser_win32.c b/ser_win32.c
new file mode 100644
index 00000000..8ddf17fe
--- /dev/null
+++ b/ser_win32.c
@@ -0,0 +1,58 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2003  Theodore A. Roth  <troth@openavr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* $Id$ */
+
+/*
+ * Posix serial interface for avrdude.
+ */
+
+extern char *progname;
+
+#if 0
+
+int serial_open(char * port, int baud)
+{
+  return fd;
+}
+
+
+void serial_close(int fd)
+{
+}
+
+
+int serial_send(int fd, char * buf, size_t buflen)
+{
+  return 0;
+}
+
+
+int serial_recv(int fd, char * buf, size_t buflen)
+{
+  return 0;
+}
+
+
+int serial_drain(int fd, int display)
+{
+  return 0;
+}
+
+#endif
diff --git a/serial.h b/serial.h
new file mode 100644
index 00000000..b8aaf3ff
--- /dev/null
+++ b/serial.h
@@ -0,0 +1,42 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2003  Theodore A. Roth  <troth@openavr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* $Id$ */
+
+/* This is the API for the generic serial interface. The implementations are
+   actually provided by the target dependant files:
+
+   ser_posix.c : posix serial interface.
+   ser_win32.c : native win32 serial interface.
+
+   The target file will be selected at configure time. */
+
+#ifndef __serial_h__
+#define __serial_h__
+
+#include "config.h"
+
+extern int serial_open(char * port, int baud);
+extern void serial_close(int fd);
+
+extern int serial_send(int fd, char * buf, size_t buflen);
+extern int serial_recv(int fd, char * buf, size_t buflen);
+extern int serial_drain(int fd, int display);
+
+#endif /* __serial_h__ */
diff --git a/stk500.c b/stk500.c
index 2442f37f..c570c8a5 100644
--- a/stk500.c
+++ b/stk500.c
@@ -33,15 +33,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
 #include <errno.h>
-#include <termios.h>
-#include <sys/time.h>
 
 #include "avr.h"
 #include "pgm.h"
 #include "stk500_private.h"
+#include "serial.h"
 
 
 extern char * progname;
@@ -51,153 +48,21 @@ extern int do_cycles;
 static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value);
 
 
-static int stk500_send(PROGRAMMER * pgm, char * buf, int buflen)
+static int stk500_send(PROGRAMMER * pgm, char * buf, size_t len)
 {
-  struct timeval timeout;
-  fd_set wfds;
-  int nfds;
-  int rc;
-
-  if (!buflen)
-    return 0;
-
-  timeout.tv_sec = 0;
-  timeout.tv_usec = 500000;
-
-  while (buflen) {
-    FD_ZERO(&wfds);
-    FD_SET(pgm->fd, &wfds);
-
-  reselect:
-    nfds = select(pgm->fd+1, NULL, &wfds, NULL, &timeout);
-    if (nfds == 0) {
-      fprintf(stderr, 
-              "%s: stk500_send(): programmer is not responding on %s\n",
-              progname, pgm->port);
-      exit(1);
-    }
-    else if (nfds == -1) {
-      if (errno == EINTR) {
-        goto reselect;
-      }
-      else {
-        fprintf(stderr, "%s: stk500_send(): select(): %s\n",
-                progname, strerror(errno));
-        exit(1);
-      }
-    }
-
-    rc = write(pgm->fd, buf, 1);
-    if (rc < 0) {
-      fprintf(stderr, "%s: stk500_send(): write error: %s\n",
-              progname, strerror(errno));
-      exit(1);
-    }
-    buf++;
-    buflen--;
-  }
-
-  return 0;
+  return serial_send(pgm->fd, buf, len);
 }
 
-      
-  
-static int stk500_recv(PROGRAMMER * pgm, char * buf, int n)
+
+static int stk500_recv(PROGRAMMER * pgm, char * buf, size_t len)
 {
-  struct timeval timeout;
-  fd_set rfds;
-  int nfds;
-  int rc;
-
-  timeout.tv_sec  = 5;
-  timeout.tv_usec = 0;
-
-  while (n) {
-    FD_ZERO(&rfds);
-    FD_SET(pgm->fd, &rfds);
-
-  reselect:
-    nfds = select(pgm->fd+1, &rfds, NULL, NULL, &timeout);
-    if (nfds == 0) {
-      fprintf(stderr, 
-              "%s: stk500_recv(): programmer is not responding on %s\n",
-              progname, pgm->port);
-      exit(1);
-    }
-    else if (nfds == -1) {
-      if (errno == EINTR) {
-        goto reselect;
-      }
-      else {
-        fprintf(stderr, "%s: stk500_recv(): select(): %s\n",
-                progname, strerror(errno));
-        exit(1);
-      }
-    }
-
-    rc = read(pgm->fd, buf, 1);
-    if (rc < 0) {
-      fprintf(stderr, "%s: stk500_recv(): read error: %s\n",
-              progname, strerror(errno));
-      exit(1);
-    }
-    buf++;
-    n--;
-  }
-
-  return 0;
+  return serial_recv(pgm->fd, buf, len);
 }
 
-      
+
 static int stk500_drain(PROGRAMMER * pgm, int display)
 {
-  struct timeval timeout;
-  fd_set rfds;
-  int nfds;
-  int rc;
-  unsigned char buf;
-
-  timeout.tv_sec = 0;
-  timeout.tv_usec = 250000;
-
-  if (display) {
-    fprintf(stderr, "drain>");
-  }
-
-  while (1) {
-    FD_ZERO(&rfds);
-    FD_SET(pgm->fd, &rfds);
-
-  reselect:
-    nfds = select(pgm->fd+1, &rfds, NULL, NULL, &timeout);
-    if (nfds == 0) {
-      if (display) {
-        fprintf(stderr, "<drain\n");
-      }
-      
-      return 0;
-    }
-    else if (nfds == -1) {
-      if (errno == EINTR) {
-        goto reselect;
-      }
-      else {
-        fprintf(stderr, "%s: stk500_drain(): select(): %s\n",
-                progname, strerror(errno));
-        exit(1);
-      }
-    }
-
-    rc = read(pgm->fd, &buf, 1);
-    if (rc < 0) {
-      fprintf(stderr, "%s: stk500_drain(): read error: %s\n",
-              progname, strerror(errno));
-      exit(1);
-    }
-    if (display) {
-      fprintf(stderr, "%02x ", buf);
-    }
-  }
+  return serial_drain(pgm->fd, display);
 }
 
 
@@ -739,72 +604,10 @@ static void stk500_enable(PROGRAMMER * pgm)
 }
 
 
-static int stk500_setattr(int fd)
-{
-  int rc;
-  struct termios termios;
-  
-  if (!isatty(fd))
-    return -1;
-  
-  /*
-   * initialize terminal modes
-   */
-  rc = tcgetattr(fd, &termios);
-  if (rc < 0) {
-    fprintf(stderr, "%s: stk500_setattr(): tcgetattr() failed, %s", 
-            progname, strerror(errno));
-    return -errno;
-  }
-
-  termios.c_iflag = 0;
-  termios.c_oflag = 0;
-  termios.c_cflag = 0;
-  termios.c_cflag |=   (CS8 | CREAD | CLOCAL);
-  termios.c_lflag = 0;
-  termios.c_cc[VMIN]  = 1;
-  termios.c_cc[VTIME] = 0;
-
-  cfsetospeed(&termios, B115200);
-  cfsetispeed(&termios, B115200);
-  
-  rc = tcsetattr(fd, TCSANOW, &termios);
-  if (rc < 0) {
-    fprintf(stderr, "%s: stk500_setattr(): tcsetattr() failed, %s", 
-            progname, strerror(errno));
-    return -errno;
-  }
-
-  return 0;
-}
-
-
 static void stk500_open(PROGRAMMER * pgm, char * port)
 {
-  int rc;
-
   strcpy(pgm->port, port);
-
-  /*
-   * open the serial port
-   */
-  pgm->fd = open(port, O_RDWR | O_NOCTTY /*| O_NONBLOCK*/);
-  if (pgm->fd < 0) {
-    fprintf(stderr, "%s: stk500_open(): can't open device \"%s\": %s\n",
-            progname, port, strerror(errno));
-    exit(1);
-  }
-
-  /*
-   * set serial line attributes
-   */
-  rc = stk500_setattr(pgm->fd);
-  if (rc) {
-    fprintf(stderr, 
-            "%s: stk500_open(): can't set attributes for device \"%s\"\n",
-            progname, port);
-    exit(1);
-  }
+  pgm->fd = serial_open(port, 115200);
 
   /*
    * drain any extraneous input
@@ -819,7 +622,7 @@ static void stk500_open(PROGRAMMER * pgm, char * port)
 
 static void stk500_close(PROGRAMMER * pgm)
 {
-  close(pgm->fd);
+  serial_close(pgm->fd);
   pgm->fd = -1;
 }