diff -urN orig/avrdude-4.0.0/Makefile.am avrdude-4.0.0/Makefile.am
--- orig/avrdude-4.0.0/Makefile.am	2003-03-11 20:09:57.000000000 -0600
+++ avrdude-4.0.0/Makefile.am	2003-11-24 21:44:21.000000000 -0600
@@ -71,7 +71,11 @@
 	stk500.h \
 	stk500_private.h \ term.c \
-	term.h
+	term.h \
+	usb.c \
+	avr_usb.h \
+	hostlib.c \
+	hostlib.h
 
 man_MANS = avrdude.1
 
diff -urN orig/avrdude-4.0.0/avr.c avrdude-4.0.0/avr.c
--- orig/avrdude-4.0.0/avr.c	2003-03-04 22:30:20.000000000 -0600
+++ avrdude-4.0.0/avr.c	2003-11-26 16:24:59.000000000 -0600
@@ -17,7 +17,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-/* $Id: avr.c,v 1.52 2003/03/05 04:30:20 bdean Exp $ */
+/* $Id: avr.c,v 1.1 2003/11/26 22:24:50 jepler Exp jepler $ */
 
 #include "ac_cfg.h"
 
@@ -477,7 +477,7 @@
   int rc;
   int readok=0;
 
-  if (!mem->paged) {
+  if (!mem->paged && strcmp(pgm->type, "USB")) {
     /* 
      * check to see if the write is necessary by reading the existing
      * value and only write if we are changing the value; we can't
@@ -557,7 +557,8 @@
      * read operation not supported for this memory type, just wait
      * the max programming time and then return 
      */
-    usleep(mem->max_write_delay); /* maximum write delay */
+    if(mem->max_write_delay > 0) 
+      usleep(mem->max_write_delay); /* maximum write delay */
     pgm->pgm_led(pgm, OFF);
     return 0;
   }
diff -urN orig/avrdude-4.0.0/avr_usb.h avrdude-4.0.0/avr_usb.h
--- orig/avrdude-4.0.0/avr_usb.h	1969-12-31 18:00:00.000000000 -0600
+++ avrdude-4.0.0/avr_usb.h	2003-11-24 21:53:56.000000000 -0600
@@ -0,0 +1,30 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2000, 2001, 2002, 2003  Brian S. Dean <bsd@bsdhome.com>
+ *
+ * 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: par.h,v 1.1 2003/02/13 19:27:50 bdean Exp $ */
+
+#ifndef __avr_usb_h__
+#define __avr_usb_h__
+
+#include "config.h"
+
+void ausb_initpgm        (PROGRAMMER * pgm);
+#endif
+
+
diff -urN orig/avrdude-4.0.0/config_gram.y avrdude-4.0.0/config_gram.y
--- orig/avrdude-4.0.0/config_gram.y	2003-03-04 19:19:17.000000000 -0600
+++ avrdude-4.0.0/config_gram.y	2003-11-24 21:53:47.000000000 -0600
@@ -29,6 +29,7 @@
 #include "config.h"
 #include "lists.h"
 #include "par.h"
+#include "avr_usb.h"
 #include "pindefs.h"
 #include "ppi.h"
 #include "pgm.h"
@@ -102,6 +103,7 @@
 %token K_SIZE
 %token K_STK500
 %token K_TYPE
+%token K_USB
 %token K_VCC
 %token K_VFYLED
 %token K_WRITEPAGE
@@ -284,6 +286,12 @@
     }
   } |
 
+  K_TYPE TKN_EQUAL K_USB {
+    {
+      ausb_initpgm(current_prog);
+    }
+  } |
+
   K_DESC TKN_EQUAL TKN_STRING {
     strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN);
     current_prog->desc[PGM_DESCLEN-1] = 0;
diff -urN orig/avrdude-4.0.0/hostlib.c avrdude-4.0.0/hostlib.c
--- orig/avrdude-4.0.0/hostlib.c	1969-12-31 18:00:00.000000000 -0600
+++ avrdude-4.0.0/hostlib.c	2003-11-28 09:45:41.000000000 -0600
@@ -0,0 +1,101 @@
+#include "hostlib.h"
+
+#include <usb.h>
+#include <stdio.h>
+#include <time.h>
+
+#define DO_DEBUG 0 
+
+
+#if DO_DEBUG
+static struct timeval t0, t1; 
+#define DEBUG(x) (printf x)
+#define TB() gettimeofday(&t0)
+#define TE(s) gettimeofday(&t1); DEBUG(( s ": %f\n", t1.tv_sec - t0.tv_sec + (t1.tv_usec - t0.tv_usec) * 1e-6 ))
+#else
+#define TB() (void)0
+#define TE(s) (void)0
+#define DEBUG(x) (void)0
+#endif
+struct usb_device *find_on_bus(struct usb_bus *bus, u_int16_t v, u_int16_t p) {
+    struct usb_device *dev = bus->devices;
+
+    for(; dev; dev = dev->next) {
+        if(dev->descriptor.idVendor == v && dev->descriptor.idProduct == p) {
+            return dev;
+        }
+    }
+    return NULL;
+}
+
+struct usb_device *find_dev(u_int16_t v, u_int16_t p) {
+    struct usb_bus *bus = usb_get_busses();
+    struct usb_device *dev = NULL;
+
+    for(; bus; bus = bus->next) {
+        dev = find_on_bus(bus, v, p);
+        if(dev) return dev;
+    }
+    return NULL;
+}
+
+void send_command(avr_device *dev, int cmd, int val) {
+    DEBUG(("send_command %d %02x\n", cmd, val));
+    TB();
+    usb_control_msg((usb_dev_handle *)dev, USB_TYPE_VENDOR, cmd, val,
+                    0, NULL, 0, 1000);
+    TE("send_command");
+}
+
+void send_command_idx(avr_device *dev, int cmd, int val, int idx) {
+    DEBUG(("send_command %d %02x\n", cmd, val));
+    TB();
+    usb_control_msg((usb_dev_handle *)dev, USB_TYPE_VENDOR, cmd, val,
+                    idx, NULL, 0, 1000);
+    TE("send_command");
+}
+
+
+int get_response(avr_device *dev, int cmd, int val, char *buf, int len) {
+    DEBUG(("get_response %d %02x", cmd, val));
+    TB();
+    int ret = usb_control_msg((usb_dev_handle *)dev,
+                    USB_TYPE_VENDOR | USB_ENDPOINT_IN, cmd, val,
+                    0, buf, len, 1000);
+    TE("get_response");
+    DEBUG((" -> %d  (buf[0] = %02x)\n", ret, (unsigned char)buf[0]));
+    return ret;
+}
+
+
+int get_response_idx(avr_device *dev, int cmd, int val, int idx,
+                     char *buf, int len) {
+    DEBUG(("get_response %d %02x", cmd, val));
+    TB();
+    int ret = usb_control_msg((usb_dev_handle *)dev,
+                    USB_TYPE_VENDOR | USB_ENDPOINT_IN, cmd, val,
+                    idx, buf, len, 1000);
+    TE("get_response");
+    DEBUG((" -> %d  (buf[0] = %02x)\n", ret, (unsigned char)buf[0]));
+    return ret;
+}
+
+avr_device get_avr(void) {
+    struct usb_device *dev;
+    usb_dev_handle *devh;
+
+    usb_init();
+    usb_set_debug(0xff);
+    usb_find_busses();
+    usb_find_devices();
+
+    dev = find_dev(0x3eb, 0x2);
+    if(!dev) return NULL;
+
+    devh = usb_open(dev);
+
+    usb_claim_interface(devh, 0);
+    return (avr_device)devh;
+}
+
+// vim:sts=4:sw=4:et
diff -urN orig/avrdude-4.0.0/hostlib.h avrdude-4.0.0/hostlib.h
--- orig/avrdude-4.0.0/hostlib.h	1969-12-31 18:00:00.000000000 -0600
+++ avrdude-4.0.0/hostlib.h	2003-11-28 09:45:54.000000000 -0600
@@ -0,0 +1,27 @@
+#ifndef AVR_HOSTLIB_H
+#define AVR_HOSTLIB_H
+
+#define AVR_INFRA_BUFFER_EMPTY 1
+#define AVR_INFRA_GET_CODE     2
+#define AVR_DDR_SET            3
+#define AVR_DDR_GET            4
+#define AVR_PORT_SET           5
+#define AVR_PORT_GET           6
+#define AVR_PIN_GET            7
+#define AVR_EEPROM_READ        8
+#define AVR_EEPROM_WRITE       9
+#define AVR_RS232_WRITE        10
+#define AVR_RS232_READ         11
+#define AVR_RS232_BAUD_SET     12
+#define AVR_RS232_BAUD_GET     13
+#define AVR_SPI4               15
+
+typedef void* avr_device;
+
+avr_device get_avr();
+void send_command(avr_device *dev, int cmd, int val);
+void send_command_idx(avr_device *dev, int cmd, int val, int idx);
+int get_response(avr_device *dev, int cmd, int val, char *buf, int len);
+int get_response_idx(avr_device *dev, int cmd, int idx, int val,
+                     char *buf, int len);
+#endif
diff -urN orig/avrdude-4.0.0/lexer.l avrdude-4.0.0/lexer.l
--- orig/avrdude-4.0.0/lexer.l	2003-02-27 10:42:56.000000000 -0600
+++ avrdude-4.0.0/lexer.l	2003-11-24 21:43:14.000000000 -0600
@@ -153,6 +153,7 @@
 size             { yylval=NULL; return K_SIZE; }
 stk500           { yylval=NULL; return K_STK500; }
 type             { yylval=NULL; return K_TYPE; }
+usb              { yylval=NULL; return K_USB; }
 vcc              { yylval=NULL; return K_VCC; }
 vfyled           { yylval=NULL; return K_VFYLED; }
 
diff -urN orig/avrdude-4.0.0/pgm.h avrdude-4.0.0/pgm.h
--- orig/avrdude-4.0.0/pgm.h	2003-02-22 10:45:13.000000000 -0600
+++ avrdude-4.0.0/pgm.h	2003-11-24 21:48:36.000000000 -0600
@@ -27,7 +27,7 @@
 #include "avrpart.h"
 #include "lists.h"
 #include "pindefs.h"
-
+#include "hostlib.h"
 
 #define ON  1
 #define OFF 0
@@ -43,6 +43,7 @@
   unsigned int pinno[N_PINS];
   int ppidata;
   int fd;
+  avr_device dev;
   int  page_size;  /* page size if the programmer supports paged write/load */
   int  (*rdy_led)        (struct programmer_t * pgm, int value);
   int  (*err_led)        (struct programmer_t * pgm, int value);
diff -urN orig/avrdude-4.0.0/usb.c avrdude-4.0.0/usb.c
--- orig/avrdude-4.0.0/usb.c	1969-12-31 18:00:00.000000000 -0600
+++ avrdude-4.0.0/usb.c	2003-11-28 09:46:47.000000000 -0600
@@ -0,0 +1,431 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2000, 2001, 2002, 2003  Brian S. Dean <bsd@bsdhome.com>
+ *
+ * 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: usb.c,v 1.2 2003/11/26 22:24:50 jepler Exp jepler $ */
+
+#include "ac_cfg.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <usb.h>
+
+#include "avr.h"
+#include "pindefs.h"
+#include "pgm.h"
+#include "avr_usb.h"
+#include "hostlib.h"
+
+#define SLOW_TOGGLE 0
+
+extern char * progname;
+extern int do_cycles;
+extern int verbose;
+
+
+static int ausb_setpin          (PROGRAMMER *pgm, int pin, int value);
+
+static int ausb_getpin          (PROGRAMMER *pgm, int pin);
+
+static int ausb_pulsepin        (PROGRAMMER *pgm, int pin);
+
+
+static int  ausb_rdy_led        (PROGRAMMER * pgm, int value);
+
+static int  ausb_err_led        (PROGRAMMER * pgm, int value);
+
+static int  ausb_pgm_led        (PROGRAMMER * pgm, int value);
+
+static int  ausb_vfy_led        (PROGRAMMER * pgm, int value);
+
+static int  ausb_cmd            (PROGRAMMER * pgm, unsigned char cmd[4], 
+                                unsigned char res[4]);
+
+static int  ausb_chip_erase     (PROGRAMMER * pgm, AVRPART * p);
+
+static int  ausb_program_enable (PROGRAMMER * pgm, AVRPART * p);
+
+static void ausb_powerup        (PROGRAMMER * pgm);
+
+static void ausb_powerdown      (PROGRAMMER * pgm);
+
+static int  ausb_initialize     (PROGRAMMER * pgm, AVRPART * p);
+
+static int  ausb_save           (PROGRAMMER * pgm);
+
+static void ausb_restore        (PROGRAMMER * pgm);
+
+static void ausb_disable        (PROGRAMMER * pgm);
+
+static void ausb_enable         (PROGRAMMER * pgm);
+
+static void ausb_open           (PROGRAMMER * pgm, char * port);
+
+static void ausb_close          (PROGRAMMER * pgm);
+
+
+#define USB_RESET 4
+#define USB_MOSI 5
+#define USB_MISO 6
+#define USB_SCK 7
+
+static unsigned pins = 0;
+
+static int ausb_setpin(PROGRAMMER *pgm, int pin, int value)
+{
+  unsigned char c = pins;
+
+  if (pin < 0 || pin > 7)
+    return -1;
+
+  if(value)
+	c |= (1<<pin);
+  else
+	c &= ~(1<<pin);
+
+  if(c == pins) return;
+
+  send_command(pgm->dev, AVR_PORT_SET, c);
+  pins = c;
+
+  return 0;
+}
+
+
+static int ausb_getpin(PROGRAMMER *pgm, int pin)
+{
+  int value;
+  unsigned char c;
+
+  if (pin < 0 || pin > 7)
+    return -1;
+
+  if (pin == USB_MISO)
+    get_response(pgm->dev, AVR_PIN_GET, 0, &c, 1);
+  else
+    c = pins;
+
+  value = !!(c & (1<<pin));
+
+  return value;
+}
+
+
+static int ausb_pulsepin(PROGRAMMER *pgm, int pin)
+{
+  int value;
+
+  if (pin < 0 || pin > 7)
+    return -1;
+
+  value = ausb_getpin(pgm->dev, pin);
+
+  ausb_setpin(pgm, pin, !value);
+  ausb_setpin(pgm, pin, value);
+
+  return 0;
+}
+
+static int ausb_rdy_led(PROGRAMMER * pgm, int value)
+{
+  //ausb_setpin(pgm, USB_RDY, value);
+}
+
+static int ausb_err_led(PROGRAMMER * pgm, int value)
+{
+  //ausb_setpin(pgm, USB_ERR, value);
+}
+
+static int ausb_pgm_led(PROGRAMMER * pgm, int value)
+{
+  //ausb_setpin(pgm, USB_PGM, value);
+}
+
+static int ausb_vfy_led(PROGRAMMER * pgm, int value)
+{
+  //ausb_setpin(pgm, USB_VFY, value);
+}
+
+
+/*
+ * transmit an AVR device command and return the results; 'cmd' and
+ * 'res' must point to at least a 4 byte data buffer
+ */
+static int ausb_cmd(PROGRAMMER * pgm, unsigned char cmd[4], 
+                   unsigned char res[4])
+{
+  int i;
+
+  get_response_idx(pgm->dev, AVR_SPI4, cmd[0] + 256*cmd[1],
+		   cmd[2] + 256*cmd[3], res, 4);
+
+    if(verbose >= 2)
+	{
+        fprintf(stderr, "ausb_cmd(): [ ");
+        for(i = 0; i < 4; i++)
+            fprintf(stderr, "%02X ", cmd[i]);
+        fprintf(stderr, "] [ ");
+        for(i = 0; i < 4; i++)
+		{
+            fprintf(stderr, "%02X ", res[i]);
+		}
+        fprintf(stderr, "]\n");
+	}
+
+  return 0;
+}
+
+
+/*
+ * issue the 'chip erase' command to the AVR device
+ */
+static int ausb_chip_erase(PROGRAMMER * pgm, AVRPART * p)
+{
+  unsigned char cmd[4];
+  unsigned char res[4];
+  int cycles;
+  int rc;
+
+  if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
+    fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
+            p->desc);
+    return -1;
+  }
+
+  rc = avr_get_cycle_count(pgm, p, &cycles);
+
+  /*
+   * only print out the current cycle count if we aren't going to
+   * display it below 
+   */
+  if (!do_cycles && ((rc >= 0) && (cycles != 0xffffffff))) {
+    fprintf(stderr,
+            "%s: current erase-rewrite cycle count is %d%s\n",
+            progname, cycles, 
+            do_cycles ? "" : " (if being tracked)");
+  }
+
+  pgm->pgm_led(pgm, ON);
+
+  memset(cmd, 0, sizeof(cmd));
+
+  avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
+  pgm->cmd(pgm, cmd, res);
+  usleep(p->chip_erase_delay);
+  pgm->initialize(pgm, p);
+
+  pgm->pgm_led(pgm, OFF);
+
+  if (do_cycles && (cycles != -1)) {
+    if (cycles == 0x00ffff) {
+      cycles = 0;
+    }
+    cycles++;
+    fprintf(stderr, "%s: erase-rewrite cycle count is now %d\n", 
+            progname, cycles);
+    avr_put_cycle_count(pgm, p, cycles);
+  }
+
+  return 0;
+}
+
+/*
+ * issue the 'program enable' command to the AVR device
+ */
+static int ausb_program_enable(PROGRAMMER * pgm, AVRPART * p)
+{
+  unsigned char cmd[4];
+  unsigned char res[4];
+
+  if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
+    fprintf(stderr, "program enable instruction not defined for part \"%s\"\n",
+            p->desc);
+    return -1;
+  }
+
+  memset(cmd, 0, sizeof(cmd));
+  avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd);
+  pgm->cmd(pgm, cmd, res);
+
+  if (res[2] != cmd[1])
+    return -2;
+
+  return 0;
+}
+
+
+/*
+ * apply power to the AVR processor
+ */
+static void ausb_powerup(PROGRAMMER * pgm)
+{
+}
+
+
+/*
+ * remove power from the AVR processor
+ */
+static void ausb_powerdown(PROGRAMMER * pgm)
+{
+}
+
+
+/*
+ * initialize the AVR device and prepare it to accept commands
+ */
+static int ausb_initialize(PROGRAMMER * pgm, AVRPART * p)
+{
+  int rc;
+  int tries;
+
+  pgm->powerup(pgm);
+  usleep(20000);
+
+  ausb_setpin(pgm, USB_SCK, 0);
+  ausb_setpin(pgm, USB_RESET, 0);
+  usleep(20000);
+
+  ausb_pulsepin(pgm, USB_RESET);
+
+  usleep(20000); /* 20 ms XXX should be a per-chip parameter */
+
+  /*
+   * Enable programming mode.  If we are programming an AT90S1200, we
+   * can only issue the command and hope it worked.  If we are using
+   * one of the other chips, the chip will echo 0x53 when issuing the
+   * third byte of the command.  In this case, try up to 32 times in
+   * order to possibly get back into sync with the chip if we are out
+   * of sync.
+   */
+  if (strcmp(p->desc, "AT90S1200")==0) {
+    pgm->program_enable(pgm, p);
+  }
+  else {
+    tries = 0;
+    do {
+      rc = pgm->program_enable(pgm, p);
+      if ((rc == 0)||(rc == -1))
+        break;
+      ausb_pulsepin(pgm, USB_SCK);
+      tries++;
+    } while (tries < 65);
+
+    /*
+     * can't sync with the device, maybe it's not attached?
+     */
+    if (rc) {
+      fprintf(stderr, "%s: AVR device not responding\n", progname);
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+
+static int ausb_save(PROGRAMMER * pgm)
+{
+  int rc;
+
+  return 0;
+}
+
+static void ausb_restore(PROGRAMMER * pgm)
+{
+}
+
+static void ausb_disable(PROGRAMMER * pgm)
+{
+}
+
+static void ausb_enable(PROGRAMMER * pgm)
+{
+  /*
+   * Prepare to start talking to the connected device - pull reset low
+   * first, delay a few milliseconds, then enable the buffer.  This
+   * sequence allows the AVR to be reset before the buffer is enabled
+   * to avoid a short period of time where the AVR may be driving the
+   * programming lines at the same time the programmer tries to.  Of
+   * course, if a buffer is being used, then the /RESET line from the
+   * programmer needs to be directly connected to the AVR /RESET line
+   * and not via the buffer chip.
+   */
+
+  ausb_setpin(pgm, USB_RESET, 0);
+  usleep(1);
+}
+
+
+static void ausb_open(PROGRAMMER * pgm, char * port)
+{
+  pgm->dev = get_avr();
+  if (pgm->dev == 0) {
+    fprintf(stderr, "%s: failed to open usb port \"%s\"\n\n",
+            progname, port);
+    exit(1);
+  }
+
+  send_command(pgm->dev, AVR_DDR_SET, ~(1<<USB_MISO));
+  send_command(pgm->dev, AVR_PORT_SET, 1<<USB_MISO);
+}
+
+
+static void ausb_close(PROGRAMMER * pgm)
+{
+  send_command(pgm->dev, AVR_DDR_SET, 0x00);
+  send_command(pgm->dev, AVR_PORT_SET, 0x00);
+
+  pgm->dev = (avr_device)-1;
+}
+
+
+static void ausb_display(PROGRAMMER * pgm, char * p)
+{
+  fprintf(stderr, "BUH?   FUH!\n");
+}
+
+
+void ausb_initpgm(PROGRAMMER * pgm)
+{
+  strcpy(pgm->type, "USB");
+
+  pgm->rdy_led        = ausb_rdy_led;
+  pgm->err_led        = ausb_err_led;
+  pgm->pgm_led        = ausb_pgm_led;
+  pgm->vfy_led        = ausb_vfy_led;
+  pgm->initialize     = ausb_initialize;
+  pgm->display        = ausb_display;
+  pgm->save           = ausb_save;
+  pgm->restore        = ausb_restore;
+  pgm->enable         = ausb_enable;
+  pgm->disable        = ausb_disable;
+  pgm->powerup        = ausb_powerup;
+  pgm->powerdown      = ausb_powerdown;
+  pgm->program_enable = ausb_program_enable;
+  pgm->chip_erase     = ausb_chip_erase;
+  pgm->cmd            = ausb_cmd;
+  pgm->open           = ausb_open;
+  pgm->close          = ausb_close;
+}
+
+
