diff -Nru dfu-programmer-0.3.0/dfu-programmer.spec dfu-programmer-0.3.0-hmw2/dfu-programmer.spec
--- dfu-programmer-0.3.0/dfu-programmer.spec	2006-07-01 03:38:39.000000000 +0200
+++ dfu-programmer-0.3.0-hmw2/dfu-programmer.spec	1970-01-01 01:00:00.000000000 +0100
@@ -1,51 +0,0 @@
-Name:       dfu-programmer
-Summary:    A Device Firmware Update based USB programmer for Atmel chips.
-Version:    0.3.0
-Release:    fc5
-Group:      Development/Tools
-License:    GPL
-URL:        http://dfu-programmer.sourceforge.net/
-Packager:   Weston Schmidt <weston_schmidt@alumni.purdue.edu>
-Source:     %{name}-%{version}.tar.gz
-BuildRoot:  %{_tmppath}/%{name}-%{version}-%{release}-root
-Requires:   libusb >= 0.1.10a
-
-%description 
-A linux based command-line programmer for Atmel chips with a USB
-bootloader supporting ISP. This is a mostly Device Firmware Update
-(DFU) 1.0 compliant user-space application.
-Currently supported chips:
-        8051                        AVR
-    ------------                -----------
-    at89c51snd1c                at90usb1287
-    at89c5130                   at90usb1286
-    at89c5131                   at90usb647 
-    at89c5132                   at90usb646
-
-%prep
-%setup -q
-
-%build
-%configure
-make
-
-%install
-rm -rf ${buildroot}
-
-%makeinstall
-
-%clean
-rm -rf ${buildroot}
-
-%files
-%defattr(-,root,root,-)
-%doc %attr(0644, root, root) AUTHORS ChangeLog NEWS README COPYING
-%{_bindir}/dfu-programmer
-%{_mandir}/man1/%{name}.1*
-
-%changelog
-
-* Wed May 07 2006 Weston Schmidt <weston_schmidt@alumni.purdue.edu>
-- updated the release to Fedora Core 5 & the email address
-* Wed Aug 31 2005 Weston Schmidt <weston_schmidt@yahoo.com>
-- initial creation
diff -Nru dfu-programmer-0.3.0/docs/Makefile.in dfu-programmer-0.3.0-hmw2/docs/Makefile.in
--- dfu-programmer-0.3.0/docs/Makefile.in	2006-07-01 03:37:18.000000000 +0200
+++ dfu-programmer-0.3.0-hmw2/docs/Makefile.in	2006-09-20 14:05:40.000000000 +0200
@@ -70,6 +70,7 @@
 ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
+GREP = @GREP@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -95,7 +96,6 @@
 STRIP = @STRIP@
 VERSION = @VERSION@
 ac_ct_CC = @ac_ct_CC@
-ac_ct_STRIP = @ac_ct_STRIP@
 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
 am__include = @am__include@
@@ -106,19 +106,26 @@
 bindir = @bindir@
 build_alias = @build_alias@
 datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
 exec_prefix = @exec_prefix@
 host_alias = @host_alias@
+htmldir = @htmldir@
 includedir = @includedir@
 infodir = @infodir@
 install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
+localedir = @localedir@
 localstatedir = @localstatedir@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
+psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 sysconfdir = @sysconfdir@
@@ -137,9 +144,9 @@
 	      exit 1;; \
 	  esac; \
 	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  docs/Makefile'; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  docs/Makefile'; \
 	cd $(top_srcdir) && \
-	  $(AUTOMAKE) --foreign  docs/Makefile
+	  $(AUTOMAKE) --gnu  docs/Makefile
 .PRECIOUS: Makefile
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
 	@case '$?' in \
diff -Nru dfu-programmer-0.3.0/src/Makefile.am dfu-programmer-0.3.0-hmw2/src/Makefile.am
--- dfu-programmer-0.3.0/src/Makefile.am	2006-06-19 01:54:15.000000000 +0200
+++ dfu-programmer-0.3.0-hmw2/src/Makefile.am	2006-09-18 08:27:26.000000000 +0200
@@ -2,5 +2,5 @@
 bin_PROGRAMS = dfu-programmer
 dfu_programmer_SOURCES = main.c arguments.c arguments.h atmel.c atmel.h \
                          commands.c commands.h dfu.c dfu.h \
-                         intel_hex.c intel_hex.h
+                         intel_hex.c intel_hex.h sam7dfu.c
 
diff -Nru dfu-programmer-0.3.0/src/Makefile.in dfu-programmer-0.3.0-hmw2/src/Makefile.in
--- dfu-programmer-0.3.0/src/Makefile.in	2006-07-01 03:37:18.000000000 +0200
+++ dfu-programmer-0.3.0-hmw2/src/Makefile.in	2006-09-20 14:05:40.000000000 +0200
@@ -49,7 +49,7 @@
 PROGRAMS = $(bin_PROGRAMS)
 am_dfu_programmer_OBJECTS = main.$(OBJEXT) arguments.$(OBJEXT) \
 	atmel.$(OBJEXT) commands.$(OBJEXT) dfu.$(OBJEXT) \
-	intel_hex.$(OBJEXT)
+	intel_hex.$(OBJEXT) sam7dfu.$(OBJEXT)
 dfu_programmer_OBJECTS = $(am_dfu_programmer_OBJECTS)
 dfu_programmer_LDADD = $(LDADD)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@@ -85,6 +85,7 @@
 ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
+GREP = @GREP@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -110,7 +111,6 @@
 STRIP = @STRIP@
 VERSION = @VERSION@
 ac_ct_CC = @ac_ct_CC@
-ac_ct_STRIP = @ac_ct_STRIP@
 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
 am__include = @am__include@
@@ -121,19 +121,26 @@
 bindir = @bindir@
 build_alias = @build_alias@
 datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
 exec_prefix = @exec_prefix@
 host_alias = @host_alias@
+htmldir = @htmldir@
 includedir = @includedir@
 infodir = @infodir@
 install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
+localedir = @localedir@
 localstatedir = @localstatedir@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
+psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 sysconfdir = @sysconfdir@
@@ -141,7 +148,7 @@
 AM_CFLAGS = -Wall
 dfu_programmer_SOURCES = main.c arguments.c arguments.h atmel.c atmel.h \
                          commands.c commands.h dfu.c dfu.h \
-                         intel_hex.c intel_hex.h
+                         intel_hex.c intel_hex.h sam7dfu.c
 
 all: all-am
 
@@ -156,9 +163,9 @@
 	      exit 1;; \
 	  esac; \
 	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/Makefile'; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  src/Makefile'; \
 	cd $(top_srcdir) && \
-	  $(AUTOMAKE) --foreign  src/Makefile
+	  $(AUTOMAKE) --gnu  src/Makefile
 .PRECIOUS: Makefile
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
 	@case '$?' in \
@@ -215,6 +222,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dfu.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_hex.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sam7dfu.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
diff -Nru dfu-programmer-0.3.0/src/arguments.c dfu-programmer-0.3.0-hmw2/src/arguments.c
--- dfu-programmer-0.3.0/src/arguments.c	2006-06-25 02:01:37.000000000 +0200
+++ dfu-programmer-0.3.0-hmw2/src/arguments.c	2006-09-23 00:58:18.000000000 +0200
@@ -64,6 +64,8 @@
                 64 * 1024 - 8 * 1024 },
     { "at90usb646",   tar_at90usb646,   device_AVR, 0x2FFB, 0x03eb,
                 64 * 1024 - 8 * 1024 },
+    { "sam7dfu",      tar_sam7dfu, device_SAM7, 0x0001, 0x2342,
+    	        128 *1024 - 4096 },
     { NULL }
 };
 
@@ -76,6 +78,8 @@
     { "get",       com_get       },
     { "start",     com_start_app },
     { "version",   com_version   },
+    { "dfu_upload",com_upload	 },
+    { "dfu_dnload",com_dnload	 },
     { NULL }
 };
 
@@ -137,6 +141,8 @@
                      "[global-options]\n" );
     fprintf( stderr, "        start [global-options]\n" );
     fprintf( stderr, "        version [global-options]\n" );
+    fprintf( stderr, "        dfu_dnload file\n" );
+    fprintf( stderr, "        dfu_upload file\n" );
 }
 
 static int assign_option( int *arg,
@@ -176,6 +182,10 @@
                 case device_AVR:
                     strncpy( args->device_type_string, "AVR",
                              DEVICE_TYPE_STRING_MAX_LENGTH );
+		    break;
+		case device_SAM7:
+		    strncpy( args->device_type_string, "SAM7",
+		    	     DEVICE_TYPE_STRING_MAX_LENGTH );
                     break;
             }
             return 0;
@@ -329,6 +339,8 @@
                     return -1;
                 break;
 
+	    case com_upload:
+	    case com_dnload:
             case com_flash:
                 required_params = 1;
                 if( 0 != assign_com_flash_option(args, param, argv[i]) )
@@ -407,6 +419,10 @@
         case com_get:
             printf( "       name: %d\n", args->com_get_data.name );
             break;
+        case com_upload:
+	case com_dnload:
+            printf( "   dfu file: %s\n", args->com_flash_data.file );
+	    break;
         default:
             break;
     }
@@ -471,7 +487,9 @@
     }
 
     /* if this is a flash command, restore the filename */
-    if( com_flash == args->command ) {
+    if( com_flash == args->command ||
+        com_dnload == args->command ||
+	com_upload == args->command ) {
         if( 0 == args->com_flash_data.file ) {
             fprintf( stderr, "flash filename is missing\n" );
             status = -8;
diff -Nru dfu-programmer-0.3.0/src/arguments.h dfu-programmer-0.3.0-hmw2/src/arguments.h
--- dfu-programmer-0.3.0/src/arguments.h	2006-06-25 02:01:37.000000000 +0200
+++ dfu-programmer-0.3.0-hmw2/src/arguments.h	2006-09-18 08:17:39.000000000 +0200
@@ -44,11 +44,12 @@
                     tar_at90usb1286  = 5,
                     tar_at90usb647   = 6,
                     tar_at90usb646   = 7,
-                    tar_none         = 8 };
+                    tar_sam7dfu      = 8,
+                    tar_none };
 
 enum commands_enum { com_none, com_erase, com_flash,
                      com_configure, com_get, com_dump, com_start_app,
-                     com_version };
+                     com_version, com_upload, com_dnload };
 
 enum configure_enum { conf_BSB = ATMEL_SET_CONFIG_BSB,
                       conf_SBV = ATMEL_SET_CONFIG_SBV,
@@ -60,7 +61,7 @@
                 get_EB, get_manufacturer, get_family, get_product_name,
                 get_product_rev, get_HSB };
 
-enum device_type_enum { device_8051, device_AVR };
+enum device_type_enum { device_8051, device_AVR, device_SAM7 };
 
 struct programmer_arguments {
     /* target-specific inputs */
diff -Nru dfu-programmer-0.3.0/src/commands.c dfu-programmer-0.3.0-hmw2/src/commands.c
--- dfu-programmer-0.3.0/src/commands.c	2006-06-25 02:01:37.000000000 +0200
+++ dfu-programmer-0.3.0-hmw2/src/commands.c	2006-09-20 14:05:11.000000000 +0200
@@ -310,6 +310,42 @@
 }
 
 
+static int execute_dnload( struct usb_dev_handle *device,
+			   int interface,
+			   struct programmer_arguments args )
+{
+    if( device_SAM7 != args.device_type ) {
+    	fprintf( stderr, "target doesn't support dfu download operation.\n" );
+	return -1;
+    }
+
+    if ( 0 > sam7dfu_do_dnload(device, interface, 256, /* FIXME */
+    			       args.com_flash_data.file) )
+    {
+	fprintf( stderr, "Download failed.\n" );
+	return -1;
+    }
+}
+
+
+static int execute_upload( struct usb_dev_handle *device,
+			   int interface,
+			   struct programmer_arguments args )
+{
+    if( device_SAM7 != args.device_type ) {
+    	fprintf( stderr, "target doesn't support dfu upload operation.\n" );
+	return -1;
+    }
+
+    if ( 0 > sam7dfu_do_upload(device, interface, 256, /* FIXME */
+    			       args.com_flash_data.file) )
+    {
+	fprintf( stderr, "Download failed.\n" );
+	return -1;
+    }
+}
+
+
 int execute_command( struct usb_dev_handle *device,
                      int interface,
                      struct programmer_arguments args )
@@ -327,6 +363,10 @@
             return execute_dump( device, interface, args );
         case com_configure:
             return execute_configure( device, interface, args );
+	case com_dnload:
+	    return execute_dnload( device, interface, args );
+	case com_upload:
+	    return execute_upload( device, interface, args );
         default:
             fprintf( stderr, "Not supported at this time.\n" );
     }
diff -Nru dfu-programmer-0.3.0/src/dfu.h dfu-programmer-0.3.0-hmw2/src/dfu.h
--- dfu-programmer-0.3.0/src/dfu.h	2005-09-25 03:27:42.000000000 +0200
+++ dfu-programmer-0.3.0-hmw2/src/dfu.h	2006-09-14 22:44:34.000000000 +0200
@@ -22,6 +22,7 @@
 #define __DFU_H__
 
 #include <usb.h>
+#include "usb_dfu.h"
 
 /* DFU states */
 #define STATE_APP_IDLE                  0x00
diff -Nru dfu-programmer-0.3.0/src/main.c dfu-programmer-0.3.0-hmw2/src/main.c
--- dfu-programmer-0.3.0/src/main.c	2006-06-20 08:28:04.000000000 +0200
+++ dfu-programmer-0.3.0-hmw2/src/main.c	2006-09-21 20:28:02.000000000 +0200
@@ -28,6 +28,7 @@
 #include "arguments.h"
 #include "commands.h"
 
+//#include "usb_dfu.h"
 
 /*
  *  device_init is designed to find one of the usb devices which match
@@ -43,6 +44,8 @@
     struct usb_bus *usb_bus;
     struct usb_device *dev;
 
+    printf("looking for %04x:%04x\n", vendor, product);
+
     usb_init();
     usb_find_busses();
     usb_find_devices();
@@ -71,6 +74,7 @@
     struct usb_dev_handle *usb_handle = NULL;
     struct dfu_status status;
     struct programmer_arguments args;
+	struct usb_dfu_func_descriptor func_dfu;
     int interface = 0;
 
     memset( &args, 0, sizeof(args) );
@@ -111,10 +115,63 @@
         goto exit_1;
     }
 
-    atmel_init();
-
-    dfu_get_status( usb_handle, interface, &status );
+    //atmel_init();
+    sam7dfu_init();
 
+retry:
+	printf("determining device status: ");
+	if (dfu_get_status( usb_handle, interface, &status ) < 0) {
+		fprintf(stderr, "error get_status: %s\n", usb_strerror());
+		exit(1);
+	}
+	printf("state = %d, status = %d\n", status.bState, status.bStatus);
+
+	switch (status.bState) {
+	case STATE_APP_IDLE:
+		printf("Device in Runtime Mode, send DFU detach request...\n");
+		if (dfu_detach(usb_handle, interface, 1000) < 0) {
+			fprintf(stderr, "error detaching: %s\n", usb_strerror());
+			exit(1);
+			break;
+		}
+		sleep(1);
+		printf("Resetting USB...\n");
+		if (usb_reset(usb_handle) < 0) {
+			fprintf(stderr, "error resetting after detach: %s\n", usb_strerror());
+			exit(1);
+			break;
+		}
+		goto retry;
+		break;
+	case STATE_DFU_ERROR:
+		printf("dfuERROR, clearing status\n");
+		if (dfu_clear_status(usb_handle, interface) < 0) {
+			fprintf(stderr, "error clear_status: %s\n", usb_strerror());
+			exit(1);
+			break;
+		}
+		goto retry;
+		break;
+	case STATE_DFU_IDLE:
+		printf("dfuIDLE, continuing\n");
+		break;
+	}
+
+	{
+		int ret;
+		
+		ret = usb_get_descriptor(usb_handle, 0x21, 0x00, &func_dfu,
+					 sizeof(func_dfu));
+		if (ret < 0) {
+			fprintf(stderr, "error clear_status: %s\n",
+				usb_strerror());
+			exit(1);
+		}
+
+		printf("wTransferSize = 0x%04x\n", func_dfu.wTransferSize);
+			
+	}
+	
     if( DFU_STATUS_OK != status.bStatus ) {
         /* Clear our status & try again. */
         dfu_clear_status( usb_handle, interface );
@@ -128,12 +185,21 @@
         }
     }
 
+#if 0
+	sam7dfu_do_upload(usb_handle, interface, func_dfu.wTransferSize, 
+			  "/tmp/dfu_upload.img");
+	//sam7dfu_do_dnload(usb_handle, interface, 252,
+	sam7dfu_do_dnload(usb_handle, interface, func_dfu.wTransferSize, 
+			  "/tmp/dfu_upload.img");
+#endif
 
+#if 1
     if( 0 != execute_command(usb_handle, interface, args) ) {
         /* command issued a specific diagnostic already */
         retval = 1;
         goto exit_2;
     }
+#endif
 
     retval = 0;
 
diff -Nru dfu-programmer-0.3.0/src/sam7dfu.c dfu-programmer-0.3.0-hmw2/src/sam7dfu.c
--- dfu-programmer-0.3.0/src/sam7dfu.c	1970-01-01 01:00:00.000000000 +0100
+++ dfu-programmer-0.3.0-hmw2/src/sam7dfu.c	2006-09-21 16:48:16.000000000 +0200
@@ -0,0 +1,138 @@
+/* This is supposed to be a "real" DFU implementation, just as specified in the
+ * USB DFU 1.0 Spec.  Not overloaded like the Atmel one...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <usb.h>
+
+#include "config.h"
+#include "arguments.h"
+#include "dfu.h"
+#include "atmel.h"
+
+
+#include "usb_dfu.h"
+
+int sam7dfu_do_upload(struct usb_dev_handle *usb_handle, int interface, 
+		      int xfer_size, const char *fname)
+{
+	int ret, fd, total_bytes;
+	char *buf = malloc(xfer_size);
+
+	if (!buf)
+		return -ENOMEM;
+
+	fd = creat(fname, 0644);
+	if (fd < 0) {
+		ret = fd;
+		goto out_free;
+	}
+	
+	while (1) {
+		int rc, write_rc;
+		rc = dfu_upload(usb_handle, interface, xfer_size, buf);
+		if (rc < 0) {
+			ret = rc;
+			goto out_close;
+		}
+		write_rc = write(fd, buf, rc);
+		if (write_rc < rc) {
+			fprintf(stderr, "Short write: %s\n",
+				strerror(errno));
+			goto out_close;
+		}
+		total_bytes += rc;
+		if (rc < xfer_size) {
+			/* last block, return */
+			ret = total_bytes;
+			goto out_close;
+		}
+	}
+	ret = 0;
+
+out_close:
+	close(fd);
+out_free:
+	free(buf);
+	
+	return ret;
+}
+
+int sam7dfu_do_dnload(struct usb_dev_handle *usb_handle, int interface,
+		      int xfer_size, const char *fname)
+{
+	int ret, fd, bytes_sent = 0;
+	char *buf = malloc(xfer_size);
+	struct stat st;
+
+	if (!buf)
+		return -ENOMEM;
+
+	fd = open(fname, O_RDONLY);
+	if (fd < 0) {
+		ret = fd;
+		goto out_free;
+	}
+	
+	ret = fstat(fd, &st);
+	if (ret < 0)
+		goto out_close;
+
+	if (st.st_size <= 0 /* + DFU_HDR */) {
+		fprintf(stderr, "File seems a bit too small...\n");
+		ret = -EINVAL;
+		goto out_close;	
+	}
+
+#if 0
+	read(fd, DFU_HDR);
+#endif
+	printf("Starting download: [");
+	while (bytes_sent < st.st_size /* - DFU_HDR */) {
+		struct dfu_status dst;
+
+		ret = read(fd, buf, xfer_size);
+		if (ret < 0)
+			goto out_close;
+		ret = dfu_download(usb_handle, interface, ret, buf);
+		if (ret < 0)
+			goto out_close;
+		bytes_sent += ret;
+		do {
+			ret = dfu_get_status(usb_handle, interface, &dst);
+			if (ret < 0)
+				goto out_close;
+		} while (dst.bState != DFU_STATE_dfuDNLOAD_IDLE ||
+			 dst.bStatus != DFU_STATUS_OK);
+		putchar('#');
+		usleep(5000);
+		fflush(stdout);
+	}
+
+	/* send one zero sized download request to signalize end */
+	ret = dfu_download(usb_handle, interface, 0, NULL);
+	if (ret >= 0)
+		ret = bytes_sent;
+	
+	printf("] finished!\n");
+out_close:
+	close(fd);
+out_free:
+	free(buf);
+
+	return ret;
+}
+
+void sam7dfu_init()
+{
+    dfu_debug( debug );
+    dfu_init( 5000 );
+}
+
+
diff -Nru dfu-programmer-0.3.0/src/usb_dfu.h dfu-programmer-0.3.0-hmw2/src/usb_dfu.h
--- dfu-programmer-0.3.0/src/usb_dfu.h	1970-01-01 01:00:00.000000000 +0100
+++ dfu-programmer-0.3.0-hmw2/src/usb_dfu.h	2006-09-14 22:44:57.000000000 +0200
@@ -0,0 +1,83 @@
+#ifndef _USB_DFU_H
+#define _USB_DFU_H
+/* USB Device Firmware Update Implementation for OpenPCD
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * Protocol definitions for USB DFU
+ *
+ * This ought to be compliant to the USB DFU Spec 1.0 as available from
+ * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
+ *
+ */
+
+#include <sys/types.h>
+
+#define USB_DT_DFU			0x21
+
+struct usb_dfu_func_descriptor {
+	u_int8_t		bLength;
+	u_int8_t		bDescriptorType;
+	u_int8_t		bmAttributes;
+#define USB_DFU_CAN_DOWNLOAD	(1 << 0)
+#define USB_DFU_CAN_UPLOAD	(1 << 1)
+#define USB_DFU_MANIFEST_TOL	(1 << 2)
+#define USB_DFU_WILL_DETACH	(1 << 3)
+	u_int16_t		wDetachTimeOut;
+	u_int16_t		wTransferSize;
+	u_int16_t		bcdDFUVersion;
+} __attribute__ ((packed));
+
+#define USB_DT_DFU_SIZE			9
+
+#define USB_TYPE_DFU		(USB_TYPE_CLASS|USB_RECIP_INTERFACE)
+
+/* DFU class-specific requests (Section 3, DFU Rev 1.1) */
+#define USB_REQ_DFU_DETACH	0x00
+#define USB_REQ_DFU_DNLOAD	0x01
+#define USB_REQ_DFU_UPLOAD	0x02
+#define USB_REQ_DFU_GETSTATUS	0x03
+#define USB_REQ_DFU_CLRSTATUS	0x04
+#define USB_REQ_DFU_GETSTATE	0x05
+#define USB_REQ_DFU_ABORT	0x06
+
+#if 0
+struct dfu_status {
+	u_int8_t bStatus;
+	u_int8_t bwPollTimeout[3];
+	u_int8_t bState;
+	u_int8_t iString;
+} __attribute__((packed));
+#endif
+
+#define DFU_STATUS_OK			0x00
+#define DFU_STATUS_errTARGET		0x01
+#define DFU_STATUS_errFILE		0x02
+#define DFU_STATUS_errWRITE		0x03
+#define DFU_STATUS_errERASE		0x04
+#define DFU_STATUS_errCHECK_ERASED	0x05
+#define DFU_STATUS_errPROG		0x06
+#define DFU_STATUS_errVERIFY		0x07
+#define DFU_STATUS_errADDRESS		0x08
+#define DFU_STATUS_errNOTDONE		0x09
+#define DFU_STATUS_errFIRMWARE		0x0a
+#define DFU_STATUS_errVENDOR		0x0b
+#define DFU_STATUS_errUSBR		0x0c
+#define DFU_STATUS_errPOR		0x0d
+#define DFU_STATUS_errUNKNOWN		0x0e
+#define DFU_STATUS_errSTALLEDPKT	0x0f
+
+enum dfu_state {
+	DFU_STATE_appIDLE		= 0,
+	DFU_STATE_appDETACH		= 1,
+	DFU_STATE_dfuIDLE		= 2,
+	DFU_STATE_dfuDNLOAD_SYNC	= 3,
+	DFU_STATE_dfuDNBUSY		= 4,
+	DFU_STATE_dfuDNLOAD_IDLE	= 5,
+	DFU_STATE_dfuMANIFEST_SYNC	= 6,
+	DFU_STATE_dfuMANIFEST		= 7,
+	DFU_STATE_dfuMANIFEST_WAIT_RST	= 8,
+	DFU_STATE_dfuUPLOAD_IDLE	= 9,
+	DFU_STATE_dfuERROR		= 10,
+};
+
+#endif /* _USB_DFU_H */

