summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUwe Hermann <uwe@debian.org>2014-10-04 15:12:31 +0200
committerAndrej Shadura <andrewsh@debian.org>2014-10-04 15:12:31 +0200
commit16b2269e15aed2debe6346fd7cb6353f5b2911da (patch)
tree8ab3e3aa98a8e2ed5a8950856220c16c2d27202b
parent3ed0a169046f81531836cbc16e87aeae9c8cc086 (diff)
Import Upstream version 0.8
-rw-r--r--AUTHORS30
-rw-r--r--ChangeLog47
-rw-r--r--DEVICES.txt5
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in141
-rw-r--r--README11
-rw-r--r--TODO13
-rw-r--r--aclocal.m4158
-rwxr-xr-xautogen.sh4
-rw-r--r--config.h.in32
-rwxr-xr-xconfigure459
-rw-r--r--configure.ac21
-rwxr-xr-xdfuse-pack.py121
-rw-r--r--doc/Makefile.in83
-rw-r--r--doc/dfu-util.1225
-rwxr-xr-xm4/depcomp190
-rwxr-xr-xm4/install-sh29
-rwxr-xr-xm4/missing53
-rw-r--r--src/Makefile.am15
-rw-r--r--src/Makefile.in122
-rw-r--r--src/dfu.c200
-rw-r--r--src/dfu.h52
-rw-r--r--src/dfu_file.c430
-rw-r--r--src/dfu_file.h64
-rw-r--r--src/dfu_load.c172
-rw-r--r--src/dfu_load.h10
-rw-r--r--src/dfu_util.c346
-rw-r--r--src/dfu_util.h36
-rw-r--r--src/dfuse.c583
-rw-r--r--src/dfuse.h20
-rw-r--r--src/dfuse_mem.c61
-rw-r--r--src/dfuse_mem.h6
-rw-r--r--src/main.c1193
-rw-r--r--src/portable.h72
-rw-r--r--src/prefix.c176
-rwxr-xr-x[-rw-r--r--]src/quirks.c42
-rwxr-xr-x[-rw-r--r--]src/quirks.h16
-rw-r--r--src/suffix.c176
-rw-r--r--src/usb_dfu.h54
39 files changed, 3308 insertions, 2162 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..1b36c73
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,30 @@
+Authors ordered by first contribution.
+
+Harald Welte
+Werner Almesberger
+Michael Lauer
+Jim Huang
+Stefan Schmidt
+Daniel Willmann
+Mike Frysinger
+Uwe Hermann
+C. Scott Ananian
+Bernard Blackham
+Holger Freyther
+Marc Singer
+James Perkins
+Tommi Keisala
+Pascal Schweizer
+Bradley Scott
+Uwe Bonnes
+Andrey Smirnov
+Jussi Timperi
+Hans Petter Selasky
+Bo Shen
+Henrique de Almeida Mendonca
+Bernd Krumboeck
+Dennis Meier
+Veli-Pekka Peltola
+Dave Hylands
+Michael Grzeschik
+Paul Fertser
diff --git a/ChangeLog b/ChangeLog
index dec58a8..37f1add 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,50 @@
+0.8:
+ o New, separate dfu-prefix tool (Uwe Bonnes)
+ o Allow filtering on serial number (Uwe Bonnes)
+ o Improved VID/PID/serial filtering (Bradley Scott)
+ o Support reading firmware from stdin (Tormod Volden)
+ o Warn if missing DFU suffix (Tormod Volden)
+ o Improved progress bar (Hans Petter Selasky)
+ o Fix dfuse leave option (Uwe Bonnes)
+ o Major code rework (Hans Petter Selasky)
+ o MS Visual Studio build support (Henrique Mendonca)
+ o dfuse-pack.py tool for .dfu files (Antonio Galeo)
+ o Many other fixes from many people
+
+2014-09-13: Tormod Volden <debian.tormod@gmail.com>
+
+0.7:
+ o Support for TI Stellaris devices (Tommi Keisala)
+ o Fix libusb detection on MacOSX (Marc Singer)
+ o Fix libusb detection on FreeBSD (Tormod Volden)
+ o Improved DfuSe support (Tormod Volden)
+ o Support all special commands (leave, unprotect, mass-erase)
+ o Arbitrary upload lengths
+ o "force" option for various possible (dangerous) overrides
+
+2012-10-07: Tormod Volden <debian.tormod@gmail.com>
+
+0.6:
+ o Add detach mode (Stefan Schmidt)
+ o Check return value on all libusb calls (Tormod Volden)
+ o Fix segmentation fault with -s option (Tormod Volden)
+ o Add DFU suffix manipulation tool (Stefan Schmidt)
+ o Port to Windows: (Tormod Volden, some parts based on work from Satz
+ Klauer)
+ o Port file handling to stdio streams
+ o Sleep() macros
+ o C99 types
+ o Pack structs
+ o Detect DfuSe device correctly on big-endian architectures (Tormod
+ Volden)
+ o Add dfuse progress indication on download (Tormod Volden)
+ o Cleanup: gcc pedantic, gcc extension, ... (Tormod Volden)
+ o Rely on page size from functional descriptor. Please report if you get
+ an error about it. (Tormod Volden)
+ o Add quirk for Maple since it reports wrong DFU version (Tormod Volden)
+
+2012-04-22: Stefan Schmidt <stefan@datenfreihafen.org>
+
0.5:
o DfuSe extension support for ST devices (Tormod Volden)
o Add initial support for bitWillDetach flag from DFU 1.1 (Tormod
diff --git a/DEVICES.txt b/DEVICES.txt
index 12a3e94..bdd9f1f 100644
--- a/DEVICES.txt
+++ b/DEVICES.txt
@@ -6,6 +6,7 @@ Software user (bootloader, etc)
- U-boot: DFU patches
- Barebox: http://www.barebox.org/
- Leaflabs: http://code.google.com/p/leaflabs/
+- Blackmagic DFU
Products using DFU
------------------
@@ -13,3 +14,7 @@ Products using DFU
- Openmoko Neo 1973 and Freerunner (u-boot with DFU patches)
- Leaflabs Maple
- ATUSB from Qi Hardware
+- STM32F105/7, STM32F2/F3/F4 in System Bootloader
+- Blackmagic debug probe
+- NXP LPC31xx/LPC43XX, e.g. LPC-Link and LPC-Link2, need binaries
+ with LPC prefix and encoding (LPC-Link)
diff --git a/Makefile.am b/Makefile.am
index d7a21a6..641dda5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,3 @@
SUBDIRS = src doc
-EXTRA_DIST = autogen.sh TODO DEVICES.txt
+EXTRA_DIST = autogen.sh TODO DEVICES.txt dfuse-pack.py
diff --git a/Makefile.in b/Makefile.in
index 8430546..5c37a8d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,9 +1,9 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -15,6 +15,23 @@
@SET_MAKE@
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -34,8 +51,8 @@ POST_UNINSTALL = :
subdir = .
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
- $(top_srcdir)/configure COPYING ChangeLog TODO m4/depcomp \
- m4/install-sh m4/missing
+ $(top_srcdir)/configure AUTHORS COPYING ChangeLog TODO \
+ m4/depcomp m4/install-sh m4/missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@@ -46,11 +63,11 @@ mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
-AM_V_GEN = $(am__v_GEN_$(V))
-am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
-AM_V_at = $(am__v_at_$(V))
-am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
SOURCES =
DIST_SOURCES =
@@ -61,6 +78,11 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
install-pdf-recursive install-ps-recursive install-recursive \
installcheck-recursive installdirs-recursive pdf-recursive \
ps-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@@ -73,9 +95,11 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
- { test ! -d "$(distdir)" \
- || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
- && rm -fr "$(distdir)"; }; }
+ if test -d "$(distdir)"; then \
+ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -rf "$(distdir)" \
+ || { sleep 5 && rm -rf "$(distdir)"; }; \
+ else :; fi
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
@@ -104,6 +128,8 @@ am__relativize = \
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@@ -135,7 +161,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
@@ -199,14 +224,14 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = src doc
-EXTRA_DIST = autogen.sh TODO DEVICES.txt
+EXTRA_DIST = autogen.sh TODO DEVICES.txt dfuse-pack.py
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
-am--refresh:
+am--refresh: Makefile
@:
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@@ -233,22 +258,20 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+$(top_srcdir)/configure: $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
config.h: stamp-h1
- @if test ! -f $@; then \
- rm -f stamp-h1; \
- $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
- else :; fi
+ @if test ! -f $@; then rm -f stamp-h1; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status config.h
-$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+$(srcdir)/config.h.in: $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f stamp-h1
touch $@
@@ -425,13 +448,10 @@ distdir: $(DISTFILES)
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
- test -d "$(distdir)/$$subdir" \
- || $(MKDIR_P) "$(distdir)/$$subdir" \
- || exit 1; \
- fi; \
- done
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
@@ -463,7 +483,11 @@ dist-gzip: distdir
$(am__remove_distdir)
dist-bzip2: distdir
- tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzip: distdir
+ tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
$(am__remove_distdir)
dist-lzma: distdir
@@ -471,7 +495,7 @@ dist-lzma: distdir
$(am__remove_distdir)
dist-xz: distdir
- tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
+ tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__remove_distdir)
dist-tarZ: distdir
@@ -502,6 +526,8 @@ distcheck: dist
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lzma*) \
lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.lz*) \
+ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
@@ -511,7 +537,7 @@ distcheck: dist
*.zip*) \
unzip $(distdir).zip ;;\
esac
- chmod -R a-w $(distdir); chmod a+w $(distdir)
+ chmod -R a-w $(distdir); chmod u+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
@@ -521,6 +547,7 @@ distcheck: dist
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
@@ -549,8 +576,16 @@ distcheck: dist
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
- @$(am__cd) '$(distuninstallcheck_dir)' \
- && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ @test -n '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: trying to run $@ with an empty' \
+ '$$(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ $(am__cd) '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
@@ -581,10 +616,15 @@ install-am: all-am
installcheck: installcheck-recursive
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
mostlyclean-generic:
clean-generic:
@@ -671,17 +711,18 @@ uninstall-am:
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
all all-am am--refresh check check-am clean clean-generic \
ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
- dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \
- distclean distclean-generic distclean-hdr distclean-tags \
- distcleancheck distdir distuninstallcheck dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-man install-pdf install-pdf-am \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs installdirs-am maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
- pdf-am ps ps-am tags tags-recursive uninstall uninstall-am
+ dist-lzip dist-lzma dist-shar dist-tarZ dist-xz dist-zip \
+ distcheck distclean distclean-generic distclean-hdr \
+ distclean-tags distcleancheck distdir distuninstallcheck dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/README b/README
index 2196a48..0f8f262 100644
--- a/README
+++ b/README
@@ -1,17 +1,18 @@
Dfu-util - Device Firmware Upgrade Utilities
-Dfu-util is the host side implementation of the DFU 1.0 [1] specification of
-the USB forum.
+Dfu-util is the host side implementation of the DFU 1.0 [1] and DFU 1.1 [2]
+specification of the USB forum.
DFU is intended to download and upload firmware to devices connected over
USB. It ranges from small devices like micro-controller boards up to mobile
phones. With dfu-util you are able to download firmware to your device or
upload firmware from it.
-Most tests have been done with the Openmoko Neo1973 and Freerunner so far but
-other devices have been reported working and is being worked on.
+dfu-util has been tested with Openmoko Neo1973 and Freerunner and many
+other devices.
-[1] DFU spec: http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
+[1] DFU 1.0 spec: http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
+[2] DFU 1.1 spec: http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf
The official website is:
diff --git a/TODO b/TODO
index ebd0c7d..900c30c 100644
--- a/TODO
+++ b/TODO
@@ -1,15 +1,14 @@
-Core:
-- DFU 1.1 support
-
-CLI:
-- Status bar end marker or percentage values
+DfuSe:
+- Do erase and write in two separate passes when downloading
+- Skip "Set Address" command when downloading contiguous blocks
+- Implement "Get Commands" command
Devices:
- Research iPhone/iPod/iPad support
+ Heavily modified dfu-util fork here:
+ https://github.com/planetbeing/xpwn/tree/master/dfu-util
- Test against Niftylights
Non-Code:
-- Make sure distros pick up the releases
-- List with supported devices / bootloaders
- Logo
- Re-License as LGPL for usage as library?
diff --git a/aclocal.m4 b/aclocal.m4
index aa3003b..3515374 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,7 +1,8 @@
-# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.11.6 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+# Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -13,8 +14,8 @@
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
-[m4_warning([this file was generated for autoconf 2.68.
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.])])
@@ -179,12 +180,15 @@ else
fi[]dnl
])# PKG_CHECK_MODULES
-# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software
+# Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
@@ -194,7 +198,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.11'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.11.1], [],
+m4_if([$1], [1.11.6], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -210,19 +214,21 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.11.1])dnl
+[AM_AUTOMAKE_VERSION([1.11.6])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
@@ -304,14 +310,14 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
-# Free Software Foundation, Inc.
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009,
+# 2010, 2011 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 10
+# serial 12
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
# written in clear, in which case automake, when reading aclocal.m4,
@@ -351,6 +357,7 @@ AC_CACHE_CHECK([dependency style of $depcc],
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
+ rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -415,7 +422,7 @@ AC_CACHE_CHECK([dependency style of $depcc],
break
fi
;;
- msvisualcpp | msvcmsys)
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -480,10 +487,13 @@ AC_DEFUN([AM_DEP_TRACK],
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
+ am__nodep='_no'
fi
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
AC_SUBST([AMDEPBACKSLASH])dnl
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
])
# Generate code to set up dependency tracking. -*- Autoconf -*-
@@ -566,18 +576,6 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
])
-# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 8
-
-# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
-AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
-
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
@@ -717,12 +715,15 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation,
+# Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
@@ -759,46 +760,6 @@ fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
-# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
-# From Jim Meyering
-
-# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 5
-
-# AM_MAINTAINER_MODE([DEFAULT-MODE])
-# ----------------------------------
-# Control maintainer-specific portions of Makefiles.
-# Default is to disable them, unless `enable' is passed literally.
-# For symmetry, `disable' may be passed as well. Anyway, the user
-# can override the default with the --enable/--disable switch.
-AC_DEFUN([AM_MAINTAINER_MODE],
-[m4_case(m4_default([$1], [disable]),
- [enable], [m4_define([am_maintainer_other], [disable])],
- [disable], [m4_define([am_maintainer_other], [enable])],
- [m4_define([am_maintainer_other], [enable])
- m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
-AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
- dnl maintainer-mode's default is 'disable' unless 'enable' is passed
- AC_ARG_ENABLE([maintainer-mode],
-[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful
- (and sometimes confusing) to the casual installer],
- [USE_MAINTAINER_MODE=$enableval],
- [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
- AC_MSG_RESULT([$USE_MAINTAINER_MODE])
- AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
- MAINT=$MAINTAINER_MODE_TRUE
- AC_SUBST([MAINT])dnl
-]
-)
-
-AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
-
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
@@ -894,12 +855,15 @@ else
fi
])
-# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation,
+# Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# AM_PROG_MKDIR_P
# ---------------
# Check for `mkdir -p'.
@@ -922,13 +886,14 @@ esac
# Helper functions for option handling. -*- Autoconf -*-
-# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software
+# Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 4
+# serial 5
# _AM_MANGLE_OPTION(NAME)
# -----------------------
@@ -936,13 +901,13 @@ AC_DEFUN([_AM_MANGLE_OPTION],
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
# _AM_SET_OPTION(NAME)
-# ------------------------------
+# --------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
# _AM_SET_OPTIONS(OPTIONS)
-# ----------------------------------
+# ------------------------
# OPTIONS is a space-separated list of Automake options.
AC_DEFUN([_AM_SET_OPTIONS],
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
@@ -1018,13 +983,13 @@ Check your system clock])
fi
AC_MSG_RESULT(yes)])
-# Copyright (C) 2009 Free Software Foundation, Inc.
+# Copyright (C) 2009, 2011 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 1
+# serial 2
# AM_SILENT_RULES([DEFAULT])
# --------------------------
@@ -1039,18 +1004,50 @@ yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
esac
+dnl
+dnl A few `make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+ [am_cv_make_support_nested_variables],
+ [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+ dnl Using `$V' instead of `$(V)' breaks IRIX make.
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
AM_BACKSLASH='\'
AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
-# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# AM_PROG_INSTALL_STRIP
# ---------------------
# One issue with vendor `install' (even GNU) is that you can't
@@ -1073,13 +1070,13 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
-# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 2
+# serial 3
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
@@ -1088,13 +1085,13 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])])
AC_DEFUN([_AM_SUBST_NOTMAKE])
# AM_SUBST_NOTMAKE(VARIABLE)
-# ---------------------------
+# --------------------------
# Public sister of _AM_SUBST_NOTMAKE.
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
-# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -1116,10 +1113,11 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# a tarball read from stdin.
# $(am__untar) < result.tar
AC_DEFUN([_AM_PROG_TAR],
-[# Always define AMTAR for backward compatibility.
-AM_MISSING_PROG([AMTAR], [tar])
+[# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
m4_if([$1], [v7],
- [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
[m4_case([$1], [ustar],, [pax],,
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
diff --git a/autogen.sh b/autogen.sh
index 6bd21eb..e67aed3 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,4 +1,2 @@
#! /bin/sh
-AUTOMAKE="automake --foreign --add-missing --copy"
-export AUTOMAKE
-autoreconf
+autoreconf -v -i
diff --git a/config.h.in b/config.h.in
index 68b8d96..891f69e 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,27 +1,32 @@
/* config.h.in. Generated from configure.ac by autoheader. */
+/* Define to 1 if you have the `err' function. */
+#undef HAVE_ERR
+
+/* Define to 1 if you have the `ftruncate' function. */
+#undef HAVE_FTRUNCATE
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
+/* Define to 1 if you have the `usb' library (-lusb). */
+#undef HAVE_LIBUSB
+
/* Define to 1 if you have the `usbpath' library (-lusbpath). */
#undef HAVE_LIBUSBPATH
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
- to 0 otherwise. */
-#undef HAVE_MALLOC
-
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
-/* Define to 1 if you have the `memset' function. */
-#undef HAVE_MEMSET
+/* Define to 1 if you have the `nanosleep' function. */
+#undef HAVE_NANOSLEEP
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
-/* Define to 1 if you have the <stdio.h> header file. */
-#undef HAVE_STDIO_H
-
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
@@ -31,6 +36,9 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
+/* Define to 1 if you have the <sysexits.h> header file. */
+#undef HAVE_SYSEXITS_H
+
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
@@ -43,6 +51,9 @@
/* Define to 1 if you have the <usbpath.h> header file. */
#undef HAVE_USBPATH_H
+/* Define to 1 if you have the <windows.h> header file. */
+#undef HAVE_WINDOWS_H
+
/* Name of package */
#undef PACKAGE
@@ -73,8 +84,5 @@
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
-/* Define to rpl_malloc if the replacement function should be used. */
-#undef malloc
-
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
diff --git a/configure b/configure
index 3b9d000..95fd159 100755
--- a/configure
+++ b/configure
@@ -1,11 +1,11 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for dfu-util 0.5.
+# Generated by GNU Autoconf 2.69 for dfu-util 0.8.
#
+# Report bugs to <dfu-util@lists.gnumonks.org>.
#
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
-# Foundation, Inc.
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -134,6 +134,31 @@ export LANGUAGE
# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
@@ -167,7 +192,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
else
exitcode=1; echo positional parameters were not saved.
fi
-test x\$exitcode = x0 || exit 1"
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -212,21 +238,25 @@ IFS=$as_save_IFS
if test "x$CONFIG_SHELL" != x; then :
- # We cannot yet assume a decent shell, so we have to provide a
- # neutralization value for shells without unset; and this also
- # works around shells that cannot unset nonexistent variables.
- # Preserve -v and -x to the replacement shell.
- BASH_ENV=/dev/null
- ENV=/dev/null
- (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
- export CONFIG_SHELL
- case $- in # ((((
- *v*x* | *x*v* ) as_opts=-vx ;;
- *v* ) as_opts=-v ;;
- *x* ) as_opts=-x ;;
- * ) as_opts= ;;
- esac
- exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
if test x$as_have_required = xno; then :
@@ -236,7 +266,8 @@ fi
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: dfu-util@lists.gnumonks.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -328,6 +359,14 @@ $as_echo X"$as_dir" |
} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -449,6 +488,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
chmod +x "$as_me.lineno" ||
{ $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
# original and so on. Autoconf is especially sensitive to this).
@@ -483,16 +526,16 @@ if (echo >conf$$.file) 2>/dev/null; then
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -p'.
+ # In both cases, we have to default to `cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -p'
+ as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
- as_ln_s='cp -p'
+ as_ln_s='cp -pR'
fi
else
- as_ln_s='cp -p'
+ as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
@@ -504,28 +547,8 @@ else
as_mkdir_p=false
fi
-if test -x / >/dev/null 2>&1; then
- as_test_x='test -x'
-else
- if ls -dL / >/dev/null 2>&1; then
- as_ls_L_option=L
- else
- as_ls_L_option=
- fi
- as_test_x='
- eval sh -c '\''
- if test -d "$1"; then
- test -d "$1/.";
- else
- case $1 in #(
- -*)set "./$1";;
- esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
- ???[sx]*):;;*)false;;esac;fi
- '\'' sh
- '
-fi
-as_executable_p=$as_test_x
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -557,10 +580,10 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='dfu-util'
PACKAGE_TARNAME='dfu-util'
-PACKAGE_VERSION='0.5'
-PACKAGE_STRING='dfu-util 0.5'
-PACKAGE_BUGREPORT=''
-PACKAGE_URL=''
+PACKAGE_VERSION='0.8'
+PACKAGE_STRING='dfu-util 0.8'
+PACKAGE_BUGREPORT='dfu-util@lists.gnumonks.org'
+PACKAGE_URL='http://dfu-util.gnumonks.org'
# Factoring default headers for most tests.
ac_includes_default="\
@@ -613,6 +636,7 @@ PKG_CONFIG
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
+am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
@@ -626,11 +650,10 @@ CPPFLAGS
LDFLAGS
CFLAGS
CC
-MAINT
-MAINTAINER_MODE_FALSE
-MAINTAINER_MODE_TRUE
AM_BACKSLASH
AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
am__untar
am__tar
AMTAR
@@ -696,7 +719,6 @@ ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_silent_rules
-enable_maintainer_mode
enable_dependency_tracking
'
ac_precious_vars='build_alias
@@ -1168,8 +1190,6 @@ target=$target_alias
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
- $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
- If a cross compiler is detected then cross compile mode will be used" >&2
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
@@ -1255,7 +1275,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures dfu-util 0.5 to adapt to many kinds of systems.
+\`configure' configures dfu-util 0.8 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1321,7 +1341,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of dfu-util 0.5:";;
+ short | recursive ) echo "Configuration of dfu-util 0.8:";;
esac
cat <<\_ACEOF
@@ -1331,8 +1351,6 @@ Optional Features:
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-silent-rules less verbose build output (undo: `make V=1')
--disable-silent-rules verbose build output (undo: `make V=0')
- --enable-maintainer-mode enable make rules and dependencies not useful
- (and sometimes confusing) to the casual installer
--disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors
@@ -1356,7 +1374,8 @@ Some influential environment variables:
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
-Report bugs to the package provider.
+Report bugs to <dfu-util@lists.gnumonks.org>.
+dfu-util home page: <http://dfu-util.gnumonks.org>.
_ACEOF
ac_status=$?
fi
@@ -1419,10 +1438,10 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-dfu-util configure 0.5
-generated by GNU Autoconf 2.68
+dfu-util configure 0.8
+generated by GNU Autoconf 2.69
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1498,7 +1517,7 @@ $as_echo "$ac_try_echo"; } >&5
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
+ test -x conftest$ac_exeext
}; then :
ac_retval=0
else
@@ -1666,6 +1685,10 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ------------------------------------------ ##
+## Report this to dfu-util@lists.gnumonks.org ##
+## ------------------------------------------ ##"
+ ) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
@@ -1838,8 +1861,8 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by dfu-util $as_me 0.5, which was
-generated by GNU Autoconf 2.68. Invocation command line was
+It was created by dfu-util $as_me 0.8, which was
+generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2254,7 +2277,7 @@ case $as_dir/ in #((
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
if test $ac_prog = install &&
grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
@@ -2423,7 +2446,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_STRIP="${ac_tool_prefix}strip"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2463,7 +2486,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_STRIP="strip"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2514,7 +2537,7 @@ do
test -z "$as_dir" && as_dir=.
for ac_prog in mkdir gmkdir; do
for ac_exec_ext in '' $ac_executable_extensions; do
- { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+ as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
'mkdir (GNU coreutils) '* | \
'mkdir (coreutils) '* | \
@@ -2567,7 +2590,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_AWK="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2652,8 +2675,8 @@ fi
# Define the identity of the package.
- PACKAGE=dfu-util
- VERSION=0.5
+ PACKAGE='dfu-util'
+ VERSION='0.8'
cat >>confdefs.h <<_ACEOF
@@ -2683,11 +2706,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
-# Always define AMTAR for backward compatibility.
+# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
-AMTAR=${AMTAR-"${am_missing_run}tar"}
-
-am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
@@ -2707,31 +2730,34 @@ yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=0;;
esac
-AM_BACKSLASH='\'
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
-$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
- # Check whether --enable-maintainer-mode was given.
-if test "${enable_maintainer_mode+set}" = set; then :
- enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
else
- USE_MAINTAINER_MODE=no
+ am_cv_make_support_nested_variables=no
fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
-$as_echo "$USE_MAINTAINER_MODE" >&6; }
- if test $USE_MAINTAINER_MODE = yes; then
- MAINTAINER_MODE_TRUE=
- MAINTAINER_MODE_FALSE='#'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
- MAINTAINER_MODE_TRUE='#'
- MAINTAINER_MODE_FALSE=
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
-
- MAINT=$MAINTAINER_MODE_TRUE
-
+AM_BACKSLASH='\'
# Checks for programs.
@@ -2757,7 +2783,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2797,7 +2823,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2850,7 +2876,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2891,7 +2917,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
@@ -2949,7 +2975,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2993,7 +3019,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -3439,8 +3465,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdarg.h>
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -3576,6 +3601,7 @@ fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
+ am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
@@ -3600,6 +3626,7 @@ else
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
+ rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -3659,7 +3686,7 @@ else
break
fi
;;
- msvisualcpp | msvcmsys)
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -3716,6 +3743,55 @@ fi
# Checks for libraries.
+# On FreeBSD the libusb-1.0 is called libusb and resides in system location
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libusb_init in -lusb" >&5
+$as_echo_n "checking for libusb_init in -lusb... " >&6; }
+if ${ac_cv_lib_usb_libusb_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lusb $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char libusb_init ();
+int
+main ()
+{
+return libusb_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_usb_libusb_init=yes
+else
+ ac_cv_lib_usb_libusb_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_libusb_init" >&5
+$as_echo "$ac_cv_lib_usb_libusb_init" >&6; }
+if test "x$ac_cv_lib_usb_libusb_init" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBUSB 1
+_ACEOF
+
+ LIBS="-lusb $LIBS"
+
+else
+ native_libusb=no
+fi
+
@@ -3743,7 +3819,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -3786,7 +3862,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -3836,6 +3912,8 @@ $as_echo "no" >&6; }
PKG_CONFIG=""
fi
fi
+if test x$native_libusb = xno; then :
+
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB" >&5
@@ -3908,6 +3986,7 @@ $as_echo "yes" >&6; }
fi
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_path2devnum in -lusbpath" >&5
$as_echo_n "checking for usb_path2devnum in -lusbpath... " >&6; }
if ${ac_cv_lib_usbpath_usb_path2devnum+:} false; then :
@@ -4112,7 +4191,7 @@ do
for ac_prog in grep ggrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ as_fn_executable_p "$ac_path_GREP" || continue
# Check for GNU ac_path_GREP and select it if it is found.
# Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in
@@ -4178,7 +4257,7 @@ do
for ac_prog in egrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
# Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
@@ -4355,7 +4434,7 @@ fi
done
-for ac_header in stdlib.h string.h stdio.h usbpath.h
+for ac_header in usbpath.h windows.h sysexits.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -4381,11 +4460,11 @@ else
int
main ()
{
-/* FIXME: Include the comments suggested by Paul. */
+
#ifndef __cplusplus
- /* Ultrix mips cc rejects this. */
+ /* Ultrix mips cc rejects this sort of thing. */
typedef int charset[2];
- const charset cs;
+ const charset cs = { 0, 0 };
/* SunOS 4.1.1 cc rejects this. */
char const *const *pcpcc;
char **ppc;
@@ -4402,8 +4481,9 @@ main ()
++pcpcc;
ppc = (char**) pcpcc;
pcpcc = (char const *const *) ppc;
- { /* SCO 3.2v4 cc rejects this. */
- char *t;
+ { /* SCO 3.2v4 cc rejects this sort of thing. */
+ char tx;
+ char *t = &tx;
char const *s = 0 ? (char *) 0 : (char const *) 0;
*t++ = 0;
@@ -4419,10 +4499,10 @@ main ()
iptr p = 0;
++p;
}
- { /* AIX XL C 1.02.0.0 rejects this saying
+ { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying
"k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
- struct s { int j; const int *ap[3]; };
- struct s *b; b->j = 5;
+ struct s { int j; const int *ap[3]; } bx;
+ struct s *b = &bx; b->j = 5;
}
{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
const int foo = 10;
@@ -4463,73 +4543,6 @@ fi
# Checks for library functions.
-for ac_header in stdlib.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_stdlib_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_STDLIB_H 1
-_ACEOF
-
-fi
-
-done
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5
-$as_echo_n "checking for GNU libc compatible malloc... " >&6; }
-if ${ac_cv_func_malloc_0_nonnull+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
- ac_cv_func_malloc_0_nonnull=no
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#if defined STDC_HEADERS || defined HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-char *malloc ();
-#endif
-
-int
-main ()
-{
-return ! malloc (0);
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
- ac_cv_func_malloc_0_nonnull=yes
-else
- ac_cv_func_malloc_0_nonnull=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5
-$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; }
-if test $ac_cv_func_malloc_0_nonnull = yes; then :
-
-$as_echo "#define HAVE_MALLOC 1" >>confdefs.h
-
-else
- $as_echo "#define HAVE_MALLOC 0" >>confdefs.h
-
- case " $LIBOBJS " in
- *" malloc.$ac_objext "* ) ;;
- *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
- ;;
-esac
-
-
-$as_echo "#define malloc rpl_malloc" >>confdefs.h
-
-fi
-
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5
$as_echo_n "checking for working memcmp... " >&6; }
if ${ac_cv_func_memcmp_working+:} false; then :
@@ -4592,12 +4605,13 @@ test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in
esac
-for ac_func in memset
+for ac_func in ftruncate getpagesize nanosleep err
do :
- ac_fn_c_check_func "$LINENO" "memset" "ac_cv_func_memset"
-if test "x$ac_cv_func_memset" = xyes; then :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_MEMSET 1
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
@@ -4723,10 +4737,6 @@ else
am__EXEEXT_FALSE=
fi
-if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
- as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
as_fn_error $? "conditional \"AMDEP\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -5033,16 +5043,16 @@ if (echo >conf$$.file) 2>/dev/null; then
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -p'.
+ # In both cases, we have to default to `cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -p'
+ as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
- as_ln_s='cp -p'
+ as_ln_s='cp -pR'
fi
else
- as_ln_s='cp -p'
+ as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
@@ -5102,28 +5112,16 @@ else
as_mkdir_p=false
fi
-if test -x / >/dev/null 2>&1; then
- as_test_x='test -x'
-else
- if ls -dL / >/dev/null 2>&1; then
- as_ls_L_option=L
- else
- as_ls_L_option=
- fi
- as_test_x='
- eval sh -c '\''
- if test -d "$1"; then
- test -d "$1/.";
- else
- case $1 in #(
- -*)set "./$1";;
- esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
- ???[sx]*):;;*)false;;esac;fi
- '\'' sh
- '
-fi
-as_executable_p=$as_test_x
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -5144,8 +5142,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by dfu-util $as_me 0.5, which was
-generated by GNU Autoconf 2.68. Invocation command line was
+This file was extended by dfu-util $as_me 0.8, which was
+generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -5204,17 +5202,18 @@ $config_headers
Configuration commands:
$config_commands
-Report bugs to the package provider."
+Report bugs to <dfu-util@lists.gnumonks.org>.
+dfu-util home page: <http://dfu-util.gnumonks.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-dfu-util config.status 0.5
-configured by $0, generated by GNU Autoconf 2.68,
+dfu-util config.status 0.8
+configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -5305,7 +5304,7 @@ fi
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
- set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
\$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
diff --git a/configure.ac b/configure.ac
index fe7c37a..8622114 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,22 +2,24 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
-AC_INIT([dfu-util],[0.5])
+AC_INIT([dfu-util],[0.8],[dfu-util@lists.gnumonks.org],,[http://dfu-util.gnumonks.org])
AC_CONFIG_AUX_DIR(m4)
-AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
-AM_CONFIG_HEADER([config.h])
+AM_INIT_AUTOMAKE([foreign])
+AC_CONFIG_HEADERS([config.h])
# Test for new silent rules and enable only if they are available
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-AM_MAINTAINER_MODE
-
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
-PKG_CHECK_MODULES(USB, libusb-1.0 >= 1.0.0,,
- AC_MSG_ERROR([*** Required libusb-1.0 >= 1.0.0 not installed ***]))
+# On FreeBSD the libusb-1.0 is called libusb and resides in system location
+AC_CHECK_LIB([usb], [libusb_init],, [native_libusb=no],)
+AS_IF([test x$native_libusb = xno], [
+ PKG_CHECK_MODULES([USB], [libusb-1.0 >= 1.0.0],,
+ AC_MSG_ERROR([*** Required libusb-1.0 >= 1.0.0 not installed ***]))
+])
AC_CHECK_LIB([usbpath],[usb_path2devnum],,,-lusb)
LIBS="$LIBS $USB_LIBS"
@@ -25,16 +27,15 @@ CFLAGS="$CFLAGS $USB_CFLAGS"
# Checks for header files.
AC_HEADER_STDC
-AC_CHECK_HEADERS([stdlib.h string.h stdio.h usbpath.h])
+AC_CHECK_HEADERS([usbpath.h windows.h sysexits.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
# Checks for library functions.
-AC_FUNC_MALLOC
AC_FUNC_MEMCMP
-AC_CHECK_FUNCS([memset])
+AC_CHECK_FUNCS([ftruncate getpagesize nanosleep err])
AC_CONFIG_FILES(Makefile src/Makefile doc/Makefile)
AC_OUTPUT
diff --git a/dfuse-pack.py b/dfuse-pack.py
new file mode 100755
index 0000000..875cc5c
--- /dev/null
+++ b/dfuse-pack.py
@@ -0,0 +1,121 @@
+#!/usr/bin/python
+
+# Written by Antonio Galea - 2010/11/18
+# Distributed under Gnu LGPL 3.0
+# see http://www.gnu.org/licenses/lgpl-3.0.txt
+
+import sys,struct,zlib,os
+from optparse import OptionParser
+
+DEFAULT_DEVICE="0x0483:0xdf11"
+
+def named(tuple,names):
+ return dict(zip(names.split(),tuple))
+def consume(fmt,data,names):
+ n = struct.calcsize(fmt)
+ return named(struct.unpack(fmt,data[:n]),names),data[n:]
+def cstring(string):
+ return string.split('\0',1)[0]
+def compute_crc(data):
+ return 0xFFFFFFFF & -zlib.crc32(data) -1
+
+def parse(file,dump_images=False):
+ print 'File: "%s"' % file
+ data = open(file,'rb').read()
+ crc = compute_crc(data[:-4])
+ prefix, data = consume('<5sBIB',data,'signature version size targets')
+ print '%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix
+ for t in range(prefix['targets']):
+ tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements')
+ tprefix['num'] = t
+ if tprefix['named']:
+ tprefix['name'] = cstring(tprefix['name'])
+ else:
+ tprefix['name'] = ''
+ print '%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix
+ tsize = tprefix['size']
+ target, data = data[:tsize], data[tsize:]
+ for e in range(tprefix['elements']):
+ eprefix, target = consume('<2I',target,'address size')
+ eprefix['num'] = e
+ print ' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix
+ esize = eprefix['size']
+ image, target = target[:esize], target[esize:]
+ if dump_images:
+ out = '%s.target%d.image%d.bin' % (file,t,e)
+ open(out,'wb').write(image)
+ print ' DUMPED IMAGE TO "%s"' % out
+ if len(target):
+ print "target %d: PARSE ERROR" % t
+ suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc')
+ print 'usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix
+ if crc != suffix['crc']:
+ print "CRC ERROR: computed crc32 is 0x%08x" % crc
+ data = data[16:]
+ if data:
+ print "PARSE ERROR"
+
+def build(file,targets,device=DEFAULT_DEVICE):
+ data = ''
+ for t,target in enumerate(targets):
+ tdata = ''
+ for image in target:
+ tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data']
+ tdata = struct.pack('<6sBI255s2I','Target',0,1,'ST...',len(tdata),len(target)) + tdata
+ data += tdata
+ data = struct.pack('<5sBIB','DfuSe',1,len(data)+11,len(targets)) + data
+ v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1))
+ data += struct.pack('<4H3sB',0,d,v,0x011a,'UFD',16)
+ crc = compute_crc(data)
+ data += struct.pack('<I',crc)
+ open(file,'wb').write(data)
+
+if __name__=="__main__":
+ usage = """
+%prog [-d|--dump] infile.dfu
+%prog {-b|--build} address:file.bin [-b address:file.bin ...] [{-D|--device}=vendor:device] outfile.dfu"""
+ parser = OptionParser(usage=usage)
+ parser.add_option("-b", "--build", action="append", dest="binfiles",
+ help="build a DFU file from given BINFILES", metavar="BINFILES")
+ parser.add_option("-D", "--device", action="store", dest="device",
+ help="build for DEVICE, defaults to %s" % DEFAULT_DEVICE, metavar="DEVICE")
+ parser.add_option("-d", "--dump", action="store_true", dest="dump_images",
+ default=False, help="dump contained images to current directory")
+ (options, args) = parser.parse_args()
+
+ if options.binfiles and len(args)==1:
+ target = []
+ for arg in options.binfiles:
+ try:
+ address,binfile = arg.split(':',1)
+ except ValueError:
+ print "Address:file couple '%s' invalid." % arg
+ sys.exit(1)
+ try:
+ address = int(address,0) & 0xFFFFFFFF
+ except ValueError:
+ print "Address %s invalid." % address
+ sys.exit(1)
+ if not os.path.isfile(binfile):
+ print "Unreadable file '%s'." % binfile
+ sys.exit(1)
+ target.append({ 'address': address, 'data': open(binfile,'rb').read() })
+ outfile = args[0]
+ device = DEFAULT_DEVICE
+ if options.device:
+ device=options.device
+ try:
+ v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1))
+ except:
+ print "Invalid device '%s'." % device
+ sys.exit(1)
+ build(outfile,[target],device)
+ elif len(args)==1:
+ infile = args[0]
+ if not os.path.isfile(infile):
+ print "Unreadable file '%s'." % infile
+ sys.exit(1)
+ parse(infile, dump_images=options.dump_images)
+ else:
+ parser.print_help()
+ sys.exit(1)
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 094affd..6985d61 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -1,9 +1,9 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -15,6 +15,23 @@
@SET_MAKE@
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -41,14 +58,19 @@ mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
-AM_V_GEN = $(am__v_GEN_$(V))
-am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
-AM_V_at = $(am__v_at_$(V))
-am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
SOURCES =
DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -70,6 +92,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
man1dir = $(mandir)/man1
am__installdirs = "$(DESTDIR)$(man1dir)"
NROFF = nroff
@@ -105,7 +133,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
@@ -173,7 +200,7 @@ EXTRA_DIST = dfu-util.1
all: all-am
.SUFFIXES:
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@@ -198,18 +225,25 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-man1: $(man_MANS)
@$(NORMAL_INSTALL)
- test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
- @list=''; test -n "$(man1dir)" || exit 0; \
- { for i in $$list; do echo "$$i"; done; \
- l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.1[a-z]*$$/p'; \
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man1dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.1[a-z]*$$/p'; \
+ fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
@@ -238,9 +272,7 @@ uninstall-man1:
sed -n '/\.1[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
- test -z "$$files" || { \
- echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(man1dir)" && rm -f $$files; }
+ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
tags: TAGS
TAGS:
@@ -308,10 +340,15 @@ install-am: all-am
installcheck: installcheck-am
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
mostlyclean-generic:
clean-generic:
diff --git a/doc/dfu-util.1 b/doc/dfu-util.1
index 9c40317..96d7c2d 100644
--- a/doc/dfu-util.1
+++ b/doc/dfu-util.1
@@ -1,41 +1,133 @@
-.TH DFU-UTIL 1 "February 29, 2008"
+.TH DFU-UTIL 1 "September 23, 2012"
.SH NAME
dfu-util \- Device firmware update (DFU) USB programmer
.SH SYNOPSIS
-.B dfu-util \fR[\fB\-ldpciatUDRhvV\fR]
+.\" Listing devices
+.HP
+.B dfu-util
+.B \-l
+.RB [\| \-v \|]
+.RB [\| \-d
+.IR vid:pid [\|, vid:pid \|]\|]
+.RB [\| \-p
+.IR path \|]
+.RB [\| \-c
+.IR configuration \|]
+.RB [\| \-i
+.IR interface \|]
+.RB [\| \-a
+.IR alt-intf \|]
+.RB [\| \-S
+.IR serial [\|, serial \|]\|]
+.\" Download to or upload from device
+.HP
+.B dfu-util
+.RB [\| \-v \|]
+.RB [\| \-d
+.IR vid:pid [\|, vid:pid \|]\|]
+.RB [\| \-p
+.IR path \|]
+.RB [\| \-c
+.IR configuration \|]
+.RB [\| \-i
+.IR interface \|]
+.RB [\| \-a
+.IR alt-intf \|]
+.RB [\| \-S
+.IR serial [\|, serial \|]\|]
+.RB [\| \-t
+.IR size \|]
+.RB [\| \-Z
+.IR size \|]
+.RB [\| \-s
+.IR address \|]
+.RB [\| \-R \|]
+.RB [\| \-D \||\| \-U
+.IR file \|]
+.\" --help and --version
+.HP
+.B dfu-util
+.RB [\| \-hV \|]
.SH DESCRIPTION
.B dfu-util
is a program that implements the host (computer) side of the USB DFU
(Universal Serial Bus Device Firmware Upgrade) protocol.
.sp
-In the OpenMoko project (for example), this program is used to communicate
-with the specially enhanced u-boot boot loader, which implements the DFU
-device side.
+dfu-util communicates with devices that implement the device side of the
+USB DFU protocol, and is often used to upgrade the firmware of such
+devices.
.SH OPTIONS
.TP
.B "\-l, \-\-list"
List the currently attached DFU capable USB devices.
.TP
-.BR "\-d, \-\-device" " VENDOR:PRODUCT"
-Specify vendor/product ID of the DFU device. Both
-.B VENDOR
-and
-.B PRODUCT
-are hexadecimal numbers (no prefix needed).
-Example:
+.BR "\-d, \-\-device" " [\fIRun-Time VENDOR\fP]:[\fIRun-Time PRODUCT\fP][,[\fIDFU Mode VENDOR\fP]:[\fIDFU Mode PRODUCT\fP]]"
+.RS
+Specify run-time and/or DFU mode vendor and/or product IDs of the DFU device
+to work with. \fBVENDOR\fP and \fBPRODUCT\fP are hexadecimal numbers (no prefix
+needed), "*" (match any), or "-" (match nothing). By default, any DFU capable
+device in either run-time or DFU mode will be considered.
+.sp
+If you only have one standards-compliant DFU device attached to your computer,
+this parameter is optional. However, as soon as you have multiple DFU devices
+connected, dfu-util will detect this and abort, asking you to specify which
+device to use.
+.sp
+If only run-time IDs are specified (e.g. "\fB--device 1457:51ab\fP"), then in
+addition to the specified run-time IDs, any DFU mode devices will also be
+considered. This is beneficial to allow a DFU capable device to be found
+again after a switch to DFU mode, since the vendor and/or product ID of a
+device usually changes in DFU mode.
+.sp
+If only DFU mode IDs are specified (e.g. "\fB--device ,951:26\fP"), then all
+run-time devices will be ignored, making it easy to target a specific device in
+DFU mode.
+.sp
+If both run-time and DFU mode IDs are specified (e.g. "\fB--device
+1457:51ab,:2bc\fP"), then unspecified DFU mode components will use the run-time
+value specified.
+.sp
+Examples:
+.TP
+.B "--device 1457:51ab,951:26"
+.br
+Work with a device in run-time mode with
+vendor ID 0x1457 and product ID 0x51ab, or in DFU mode with vendor ID 0x0951
+and product ID 0x0026
.sp
-.B " $ dfu-util --device 1457:51ab"
+.TP
+.B "--device 1457:51ab,:2bc"
+.br
+Work with a device in run-time mode with vendor ID 0x1457 and product ID
+0x51ab, or in DFU mode with vendor ID 0x1457 and product ID 0x02bc
.sp
-If you only have one standards-compliant DFU device attached to your PC,
-this is optional. However, as soon as you have multiple DFU devices,
-dfu-util will detect this and abort, asking you to specify which device
-it shall use.
+.TP
+.B "--device 1457:51ab"
+.br
+Work with a device in run-time mode with vendor ID 0x1457 and product ID
+0x51ab, or in DFU mode with any vendor and product ID
+.sp
+.TP
+.B "--device ,951:26"
+.br
+Work with a device in DFU mode with vendor ID 0x0951 and product ID 0x0026
+.sp
+.TP
+.B "--device *,-"
+.br
+Work with any device in run-time mode, and ignore any device in DFU mode
+.sp
+.TP
+.B "--device ,"
+.br
+Ignore any device in run-time mode, and Work with any device in DFU mode
+.RE
.TP
.BR "\-p, \-\-path" " BUS-PORT. ... .PORT"
Specify the path to the DFU device.
.TP
.BR "\-c, \-\-cfg" " CONFIG-NR"
-Specify the configuration of the DFU device.
+Specify the configuration of the DFU device. Note that this is only used for matching, the configuration is not set by dfu-util.
.TP
.BR "\-i, \-\-intf" " INTF-NR"
Specify the DFU interface number.
@@ -43,17 +135,28 @@ Specify the DFU interface number.
.BR "\-a, \-\-alt" " ALT"
Specify the altsetting of the DFU interface by name or by number.
.TP
-.B "\-t, \-\-transfer-size"
-Specify the number of bytes per USB transfer. If you don't supply this
-option, the maximum possible size for your combination of host OS and
-USB device is chosen (for optimal performance).
+.BR "\-S, \-\-serial" " [\fIRun-Time SERIAL\fP][,[\fIDFU Mode SERIAL\fP]]"
+Specify the run-time and DFU mode serial numbers used to further restrict
+device matches. If multiple, identical DFU devices are simultaneously
+connected to a system then vendor and product ID will be insufficient for
+targeting a single device. In this situation, it may be possible to use this
+parameter to specify a serial number which also must match.
+.sp
+If only a single serial number is specified, then the same serial number is
+used in both run-time and DFU mode. An empty serial number will match any
+serial number in the corresponding mode.
+.TP
+.B "\-t, \-\-transfer-size" " SIZE"
+Specify the number of bytes per USB transfer. The optimal value is
+usually determined automatically so this option is rarely useful. If
+you need to use this option for a device, please report it as a bug.
+.TP
+.B "\-Z, \-\-upload-size" " SIZE"
+Specify the expected upload size, in bytes.
.TP
.BR "\-U, \-\-upload" " FILE"
Read firmware from device into
.BR FILE .
-.sp
-.B Note:
-Upload support is currently broken.
.TP
.BR "\-D, \-\-download" " FILE"
Write firmware from
@@ -61,25 +164,29 @@ Write firmware from
into device.
.TP
.B "\-R, \-\-reset"
-Issue USB reset signalling once we are finished.
+Issue USB reset signalling after upload or download has finished.
.TP
-.B "\-s, \-\-dfuse-address"
-Specify target address for raw binary download/upload on DfuSe devices.
-Do not use this for downloading DfuSe files.
-.TP
-.B "\-h, \-\-help"
-Show a help text and exit.
+.BR "\-s, \-\-dfuse-address" " address"
+Specify target address for raw binary download/upload on DfuSe devices. Do
+.B not
+use this for downloading DfuSe (.dfu) files. Modifiers can be added
+to the address, separated by a colon, to perform special DfuSE commands such
+as "leave" DFU mode, "unprotect" and "mass-erase" flash memory.
.TP
.B "\-v, \-\-verbose"
Print more information about dfu-util's operation. A second
.B -v
-will turn on verbose logging of USB requests.
+will turn on verbose logging of USB requests. Repeat this option to further
+increase verbosity.
+.TP
+.B "\-h, \-\-help"
+Show a help text and exit.
.TP
.B "\-V, \-\-version"
Show version information and exit.
.SH EXAMPLES
-Here are some examples for the usage of dfu-util in the OpenMoko project
-(working with the Neo1973 hardware):
+.SS Using dfu-util in the OpenMoko project
+(with the Neo1973 hardware)
.PP
Flashing the rootfs:
.br
@@ -99,23 +206,43 @@ Copying a kernel into RAM:
.sp
Once this has finished, the kernel will be available at the default load
address of 0x32000000 in Neo1973 RAM.
-.sp
.B Note:
You cannot transfer more than 2MB of data into RAM using this method.
-.SH BUGS
-Please see
-.B http://wiki.openmoko.org/wiki/Dfu-util
-for some limitations and bugs in the current dfu-util code.
+.sp
+.SS Using dfu-util with a DfuSe device
.PP
-Please report any further bugs at on the openmoko mailing list at
-.BR openmoko@lists.openmoko.org .
+Flashing a
+.B .dfu
+(special DfuSe format) file to the device:
+.br
+.B " $ dfu-util -a 0 -D /path/to/dfuse-image.dfu"
+.PP
+Reading out 1 KB of flash starting at address 0x8000000:
+.br
+.B " $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin"
+.PP
+Flashing a binary file to address 0x8004000 of device memory and
+ask the device to leave DFU mode:
+.br
+.B " $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin"
+.\" There are no bugs of course
+.SH BUGS
+Please report any bugs to the dfu-util mailing list at
+.BR dfu-util@lists.gnumonks.org .
+Please use the
+.IR --verbose " option (repeated as necessary) to provide more"
+information in your bug report.
+.SH SEE ALSO
+The dfu-util home page is
+.B http://dfu-util.gnumonks.org
+.SH HISTORY
+dfu-util was originally written for the OpenMoko project by
+Weston Schmidt <weston_schmidt@yahoo.com> and
+Harald Welte <hwelte@hmw-consulting.de>. Over time, nearly complete
+support of DFU 1.0, DFU 1.1 and DfuSe ("1.1a") has been added.
.SH LICENCE
.B dfu-util
is covered by the GNU General Public License (GPL), version 2 or later.
-.SH AUTHORS
-Weston Schmidt <weston_schmidt@yahoo.com>
-.br
-Harald Welte <hwelte@hmw-consulting.de>
-.PP
-This manual page was written by Uwe Hermann <uwe@hermann-uwe.de>.
-It is licensed under the terms of the GNU GPL (version 2 or later).
+.SH COPYRIGHT
+This manual page was originally written by Uwe Hermann <uwe@hermann-uwe.de>,
+and is now part of the dfu-util project.
diff --git a/m4/depcomp b/m4/depcomp
index df8eea7..25a39e6 100755
--- a/m4/depcomp
+++ b/m4/depcomp
@@ -1,10 +1,10 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2012-03-27.16; # UTC
-# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
-# Software Foundation, Inc.
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
+# 2011, 2012 Free Software Foundation, Inc.
# 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
@@ -28,7 +28,7 @@ scriptversion=2009-04-28.21; # UTC
case $1 in
'')
- echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
@@ -40,11 +40,11 @@ as side-effects.
Environment variables:
depmode Dependency tracking mode.
- source Source file read by `PROGRAMS ARGS'.
- object Object file output by `PROGRAMS ARGS'.
+ source Source file read by 'PROGRAMS ARGS'.
+ object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
- tmpdepfile Temporary file to use when outputing dependencies.
+ tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
@@ -57,6 +57,12 @@ EOF
;;
esac
+# A tabulation character.
+tab=' '
+# A newline character.
+nl='
+'
+
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
@@ -90,10 +96,24 @@ if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
- cygpath_u="sed s,\\\\\\\\,/,g"
+ cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
+if test "$depmode" = msvc7msys; then
+ # This is just like msvc7 but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u='sed s,\\\\,/,g'
+ depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+ # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
+ gccflag=-qmakedep=gcc,-MF
+ depmode=gcc
+fi
+
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
@@ -148,20 +168,21 @@ gcc)
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
-## This next piece of magic avoids the `deleted header file' problem.
+## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
- tr ' ' '
-' < "$tmpdepfile" |
-## Some versions of gcc put a space before the `:'. On the theory
+ tr ' ' "$nl" < "$tmpdepfile" |
+## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
-## well.
+## well. hp depmode also adds that space, but also prefixes the VPATH
+## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
@@ -193,18 +214,15 @@ sgi)
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
- # the IRIX cc adds comments like `#:fec' to the end of the
+ # the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
- tr ' ' '
-' < "$tmpdepfile" \
+ tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
- tr '
-' ' ' >> "$depfile"
+ tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
- tr ' ' '
-' < "$tmpdepfile" \
+ tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
@@ -216,10 +234,17 @@ sgi)
rm -f "$tmpdepfile"
;;
+xlc)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
- # current directory. Also, the AIX compiler puts `$object:' at the
+ # current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
@@ -249,12 +274,11 @@ aix)
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
- # Each line is of the form `foo.o: dependent.h'.
+ # Each line is of the form 'foo.o: dependent.h'.
# Do two passes, one to just change these to
- # `$object: dependent.h' and one to simply `dependent.h:'.
+ # '$object: dependent.h' and one to simply 'dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
- # That's a tab and a space in the [].
- sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
@@ -265,23 +289,26 @@ aix)
;;
icc)
- # Intel's C compiler understands `-MD -MF file'. However on
- # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
+ # However on
+ # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
- # which is wrong. We want:
+ # which is wrong. We want
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
- # and will wrap long lines using \ :
+ # and will wrap long lines using '\':
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
-
+ # tcc 0.9.26 (FIXME still under development at the moment of writing)
+ # will emit a similar output, but also prepend the continuation lines
+ # with horizontal tabulation characters.
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
@@ -290,15 +317,21 @@ icc)
exit $stat
fi
rm -f "$depfile"
- # Each line is of the form `foo.o: dependent.h',
- # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Each line is of the form 'foo.o: dependent.h',
+ # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
# Do two passes, one to just change these to
- # `$object: dependent.h' and one to simply `dependent.h:'.
- sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
- # Some versions of the HPUX 10.20 sed can't process this invocation
- # correctly. Breaking it into two sed invocations is a workaround.
- sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
- sed -e 's/$/ :/' >> "$depfile"
+ # '$object: dependent.h' and one to simply 'dependent.h:'.
+ sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
+ < "$tmpdepfile" > "$depfile"
+ sed '
+ s/[ '"$tab"'][ '"$tab"']*/ /g
+ s/^ *//
+ s/ *\\*$//
+ s/^[^:]*: *//
+ /^$/d
+ /:$/d
+ s/$/ :/
+ ' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
@@ -334,7 +367,7 @@ hp2)
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
- # Add `dependent.h:' lines.
+ # Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
@@ -349,9 +382,9 @@ hp2)
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
- # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
- # dependencies in `foo.d' instead, so we check for that too.
+ # dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
@@ -397,14 +430,59 @@ tru64)
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
- # That's a tab and a space in the [].
- sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
+msvc7)
+ if test "$libtool" = yes; then
+ showIncludes=-Wc,-showIncludes
+ else
+ showIncludes=-showIncludes
+ fi
+ "$@" $showIncludes > "$tmpdepfile"
+ stat=$?
+ grep -v '^Note: including file: ' "$tmpdepfile"
+ if test "$stat" = 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ # The first sed program below extracts the file names and escapes
+ # backslashes for cygpath. The second sed program outputs the file
+ # name when reading, but also accumulates all include files in the
+ # hold buffer in order to output them again at the end. This only
+ # works with sed implementations that can handle large buffers.
+ sed < "$tmpdepfile" -n '
+/^Note: including file: *\(.*\)/ {
+ s//\1/
+ s/\\/\\\\/g
+ p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+ s/.*/'"$tab"'/
+ G
+ p
+}' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvc7msys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
@@ -422,7 +500,7 @@ dashmstdout)
shift
fi
- # Remove `-o $object'.
+ # Remove '-o $object'.
IFS=" "
for arg
do
@@ -442,15 +520,14 @@ dashmstdout)
done
test -z "$dashmflag" && dashmflag=-M
- # Require at least two characters before searching for `:'
+ # Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
- # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
- sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
- tr ' ' '
-' < "$tmpdepfile" | \
+ tr ' ' "$nl" < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
@@ -503,9 +580,10 @@ makedepend)
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
- cat < "$tmpdepfile" > "$depfile"
- sed '1,2d' "$tmpdepfile" | tr ' ' '
-' | \
+ # makedepend may prepend the VPATH from the source file name to the object.
+ # No need to regex-escape $object, excess matching of '.' is harmless.
+ sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
@@ -525,7 +603,7 @@ cpp)
shift
fi
- # Remove `-o $object'.
+ # Remove '-o $object'.
IFS=" "
for arg
do
@@ -594,8 +672,8 @@ msvisualcpp)
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
- sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
- echo " " >> "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+ echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
diff --git a/m4/install-sh b/m4/install-sh
index 6781b98..a9244eb 100755
--- a/m4/install-sh
+++ b/m4/install-sh
@@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2011-01-19.21; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@@ -156,6 +156,10 @@ while test $# -ne 0; do
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
+ # Protect names problematic for `test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
shift;;
-T) no_target_directory=true;;
@@ -186,6 +190,10 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
fi
shift # arg
dst_arg=$arg
+ # Protect names problematic for `test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
done
fi
@@ -200,7 +208,11 @@ if test $# -eq 0; then
fi
if test -z "$dir_arg"; then
- trap '(exit $?); exit' 1 2 13 15
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
@@ -228,9 +240,9 @@ fi
for src
do
- # Protect names starting with `-'.
+ # Protect names problematic for `test' and other utilities.
case $src in
- -*) src=./$src;;
+ -* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
@@ -252,12 +264,7 @@ do
echo "$0: no destination specified." >&2
exit 1
fi
-
dst=$dst_arg
- # Protect names starting with `-'.
- case $dst in
- -*) dst=./$dst;;
- esac
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
@@ -385,7 +392,7 @@ do
case $dstdir in
/*) prefix='/';;
- -*) prefix='./';;
+ [-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
@@ -403,7 +410,7 @@ do
for d
do
- test -z "$d" && continue
+ test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
diff --git a/m4/missing b/m4/missing
index 28055d2..86a8fc3 100755
--- a/m4/missing
+++ b/m4/missing
@@ -1,10 +1,10 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2012-01-06.13; # UTC
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
-# 2008, 2009 Free Software Foundation, Inc.
+# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
@@ -84,7 +84,6 @@ Supported PROGRAM values:
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
- tar try tar, gnutar, gtar, then tar without non-portable flags
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
@@ -122,15 +121,6 @@ case $1 in
# Not GNU programs, they don't have --version.
;;
- tar*)
- if test -n "$run"; then
- echo 1>&2 "ERROR: \`tar' requires --run"
- exit 1
- elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
- exit 1
- fi
- ;;
-
*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
@@ -226,7 +216,7 @@ WARNING: \`$1' $msg. You should only need it if
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if test $# -ne 1; then
- eval LASTARG="\${$#}"
+ eval LASTARG=\${$#}
case $LASTARG in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
@@ -256,7 +246,7 @@ WARNING: \`$1' is $msg. You should only need it if
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if test $# -ne 1; then
- eval LASTARG="\${$#}"
+ eval LASTARG=\${$#}
case $LASTARG in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
@@ -318,41 +308,6 @@ WARNING: \`$1' is $msg. You should only need it if
touch $file
;;
- tar*)
- shift
-
- # We have already tried tar in the generic part.
- # Look for gnutar/gtar before invocation to avoid ugly error
- # messages.
- if (gnutar --version > /dev/null 2>&1); then
- gnutar "$@" && exit 0
- fi
- if (gtar --version > /dev/null 2>&1); then
- gtar "$@" && exit 0
- fi
- firstarg="$1"
- if shift; then
- case $firstarg in
- *o*)
- firstarg=`echo "$firstarg" | sed s/o//`
- tar "$firstarg" "$@" && exit 0
- ;;
- esac
- case $firstarg in
- *h*)
- firstarg=`echo "$firstarg" | sed s/h//`
- tar "$firstarg" "$@" && exit 0
- ;;
- esac
- fi
-
- echo 1>&2 "\
-WARNING: I can't seem to be able to run \`tar' with the given arguments.
- You may want to install GNU tar or Free paxutils, or check the
- command line arguments."
- exit 1
- ;;
-
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and is $msg.
diff --git a/src/Makefile.am b/src/Makefile.am
index 203aff6..70179c4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,9 +1,12 @@
-AM_CFLAGS = -Wall
+AM_CFLAGS = -Wall -Wextra
-bin_PROGRAMS = dfu-util
+bin_PROGRAMS = dfu-util dfu-suffix dfu-prefix
dfu_util_SOURCES = main.c \
+ portable.h \
dfu_load.c \
dfu_load.h \
+ dfu_util.c \
+ dfu_util.h \
dfuse.c \
dfuse.h \
dfuse_mem.c \
@@ -15,3 +18,11 @@ dfu_util_SOURCES = main.c \
dfu_file.h \
quirks.c \
quirks.h
+
+dfu_suffix_SOURCES = suffix.c \
+ dfu_file.h \
+ dfu_file.c
+
+dfu_prefix_SOURCES = prefix.c \
+ dfu_file.h \
+ dfu_file.c
diff --git a/src/Makefile.in b/src/Makefile.in
index 61a44d9..1542812 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,9 +1,9 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -16,6 +16,23 @@
@SET_MAKE@
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -32,7 +49,8 @@ POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
-bin_PROGRAMS = dfu-util$(EXEEXT)
+bin_PROGRAMS = dfu-util$(EXEEXT) dfu-suffix$(EXEEXT) \
+ dfu-prefix$(EXEEXT)
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -45,9 +63,15 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS)
+am_dfu_prefix_OBJECTS = prefix.$(OBJEXT) dfu_file.$(OBJEXT)
+dfu_prefix_OBJECTS = $(am_dfu_prefix_OBJECTS)
+dfu_prefix_LDADD = $(LDADD)
+am_dfu_suffix_OBJECTS = suffix.$(OBJEXT) dfu_file.$(OBJEXT)
+dfu_suffix_OBJECTS = $(am_dfu_suffix_OBJECTS)
+dfu_suffix_LDADD = $(LDADD)
am_dfu_util_OBJECTS = main.$(OBJEXT) dfu_load.$(OBJEXT) \
- dfuse.$(OBJEXT) dfuse_mem.$(OBJEXT) dfu.$(OBJEXT) \
- dfu_file.$(OBJEXT) quirks.$(OBJEXT)
+ dfu_util.$(OBJEXT) dfuse.$(OBJEXT) dfuse_mem.$(OBJEXT) \
+ dfu.$(OBJEXT) dfu_file.$(OBJEXT) quirks.$(OBJEXT)
dfu_util_OBJECTS = $(am_dfu_util_OBJECTS)
dfu_util_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
@@ -56,22 +80,29 @@ am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_$(V))
-am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
-AM_V_at = $(am__v_at_$(V))
-am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_$(V))
-am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
-AM_V_GEN = $(am__v_GEN_$(V))
-am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
-SOURCES = $(dfu_util_SOURCES)
-DIST_SOURCES = $(dfu_util_SOURCES)
+SOURCES = $(dfu_prefix_SOURCES) $(dfu_suffix_SOURCES) \
+ $(dfu_util_SOURCES)
+DIST_SOURCES = $(dfu_prefix_SOURCES) $(dfu_suffix_SOURCES) \
+ $(dfu_util_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -105,7 +136,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
@@ -168,10 +198,13 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-AM_CFLAGS = -Wall
+AM_CFLAGS = -Wall -Wextra
dfu_util_SOURCES = main.c \
+ portable.h \
dfu_load.c \
dfu_load.h \
+ dfu_util.c \
+ dfu_util.h \
dfuse.c \
dfuse.h \
dfuse_mem.c \
@@ -184,11 +217,19 @@ dfu_util_SOURCES = main.c \
quirks.c \
quirks.h
+dfu_suffix_SOURCES = suffix.c \
+ dfu_file.h \
+ dfu_file.c
+
+dfu_prefix_SOURCES = prefix.c \
+ dfu_file.h \
+ dfu_file.c
+
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@@ -213,15 +254,18 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
- test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p; \
@@ -255,7 +299,13 @@ uninstall-binPROGRAMS:
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-dfu-util$(EXEEXT): $(dfu_util_OBJECTS) $(dfu_util_DEPENDENCIES)
+dfu-prefix$(EXEEXT): $(dfu_prefix_OBJECTS) $(dfu_prefix_DEPENDENCIES) $(EXTRA_dfu_prefix_DEPENDENCIES)
+ @rm -f dfu-prefix$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dfu_prefix_OBJECTS) $(dfu_prefix_LDADD) $(LIBS)
+dfu-suffix$(EXEEXT): $(dfu_suffix_OBJECTS) $(dfu_suffix_DEPENDENCIES) $(EXTRA_dfu_suffix_DEPENDENCIES)
+ @rm -f dfu-suffix$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dfu_suffix_OBJECTS) $(dfu_suffix_LDADD) $(LIBS)
+dfu-util$(EXEEXT): $(dfu_util_OBJECTS) $(dfu_util_DEPENDENCIES) $(EXTRA_dfu_util_DEPENDENCIES)
@rm -f dfu-util$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(dfu_util_OBJECTS) $(dfu_util_LDADD) $(LIBS)
@@ -268,26 +318,27 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dfu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dfu_file.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dfu_load.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dfu_util.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dfuse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dfuse_mem.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prefix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quirks.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/suffix.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -388,10 +439,15 @@ install-am: all-am
installcheck: installcheck-am
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
mostlyclean-generic:
clean-generic:
diff --git a/src/dfu.c b/src/dfu.c
index e473784..14d7673 100644
--- a/src/dfu.c
+++ b/src/dfu.c
@@ -1,9 +1,10 @@
/*
- * low-level DFU message sending routines, originally taken from
+ * Low-level DFU communication routines, originally taken from
* $Id: dfu.c,v 1.3 2006/06/20 06:28:04 schmidtw Exp $
* (part of dfu-programmer).
*
- * (C) 2005-2006 Weston Schmidt <weston_schmidt@alumni.purdue.edu>
+ * Copyright 2005-2006 Weston Schmidt <weston_schmidt@alumni.purdue.edu>
+ * Copyright 2011-2014 Tormod Volden <debian.tormod@gmail.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
@@ -21,44 +22,15 @@
*/
#include <stdio.h>
-#include <libusb.h>
-#include "dfu.h"
-
-#define INVALID_DFU_TIMEOUT -1
+#include <stdlib.h>
-static int dfu_timeout = INVALID_DFU_TIMEOUT;
-static unsigned short transaction = 0;
-
-static int dfu_debug_level = 0;
-
-void dfu_init( const int timeout )
-{
- if( timeout > 0 ) {
- dfu_timeout = timeout;
- } else {
- if( 0 != dfu_debug_level )
- fprintf( stderr, "dfu_init: Invalid timeout value %d.\n", timeout );
- }
-}
-
-static int dfu_verify_init( const char *function )
-{
- if( INVALID_DFU_TIMEOUT == dfu_timeout ) {
- if( 0 != dfu_debug_level )
- fprintf( stderr,
- "%s: dfu system not property initialized.\n",
- function );
- return -1;
- }
-
- return 0;
-}
+#include <libusb.h>
-void dfu_debug( const int level )
-{
- dfu_debug_level = level;
-}
+#include "portable.h"
+#include "dfu.h"
+#include "quirks.h"
+static int dfu_timeout = 5000; /* 5 seconds - default */
/*
* DFU_DETACH Request (DFU Spec 1.0, Section 5.1)
@@ -74,9 +46,6 @@ int dfu_detach( libusb_device_handle *device,
const unsigned short interface,
const unsigned short timeout )
{
- if( 0 != dfu_verify_init(__FUNCTION__) )
- return -1;
-
return libusb_control_transfer( device,
/* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
/* bRequest */ DFU_DETACH,
@@ -102,44 +71,19 @@ int dfu_detach( libusb_device_handle *device,
int dfu_download( libusb_device_handle *device,
const unsigned short interface,
const unsigned short length,
+ const unsigned short transaction,
unsigned char* data )
{
int status;
- if( 0 != dfu_verify_init(__FUNCTION__) )
- return -1;
-
- /* Sanity checks */
- if( (0 != length) && (NULL == data) ) {
- if( 0 != dfu_debug_level )
- fprintf( stderr,
- "%s: data was NULL, but length != 0\n",
- __FUNCTION__ );
- return -1;
- }
-
- if( (0 == length) && (NULL != data) ) {
- if( 0 != dfu_debug_level )
- fprintf( stderr,
- "%s: data was not NULL, but length == 0\n",
- __FUNCTION__ );
- return -2;
- }
-
status = libusb_control_transfer( device,
/* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
/* bRequest */ DFU_DNLOAD,
- /* wValue */ transaction++,
+ /* wValue */ transaction,
/* wIndex */ interface,
/* Data */ data,
/* wLength */ length,
dfu_timeout );
- if( status < 0 ) {
- fprintf( stderr, "%s: libusb_control_transfer returned %d\n",
- __FUNCTION__,
- status);
- }
-
return status;
}
@@ -158,36 +102,19 @@ int dfu_download( libusb_device_handle *device,
int dfu_upload( libusb_device_handle *device,
const unsigned short interface,
const unsigned short length,
+ const unsigned short transaction,
unsigned char* data )
{
int status;
- if( 0 != dfu_verify_init(__FUNCTION__) )
- return -1;
-
- /* Sanity checks */
- if( (0 == length) || (NULL == data) ) {
- if( 0 != dfu_debug_level )
- fprintf( stderr,
- "%s: data was NULL, or length is 0\n",
- __FUNCTION__ );
- return -1;
- }
-
status = libusb_control_transfer( device,
/* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
/* bRequest */ DFU_UPLOAD,
- /* wValue */ transaction++,
+ /* wValue */ transaction,
/* wIndex */ interface,
/* Data */ data,
/* wLength */ length,
dfu_timeout );
- if( status < 0 ) {
- fprintf( stderr, "%s: libusb_control_msg returned %d\n",
- __FUNCTION__,
- status);
- }
-
return status;
}
@@ -201,37 +128,34 @@ int dfu_upload( libusb_device_handle *device,
*
* return the number of bytes read in or < 0 on an error
*/
-int dfu_get_status( libusb_device_handle *device,
- const unsigned short interface,
- struct dfu_status *status )
+int dfu_get_status( struct dfu_if *dif, struct dfu_status *status )
{
unsigned char buffer[6];
int result;
- if( 0 != dfu_verify_init(__FUNCTION__) )
- return -1;
-
/* Initialize the status data structure */
status->bStatus = DFU_STATUS_ERROR_UNKNOWN;
status->bwPollTimeout = 0;
status->bState = STATE_DFU_ERROR;
status->iString = 0;
- result = libusb_control_transfer( device,
+ result = libusb_control_transfer( dif->dev_handle,
/* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
/* bRequest */ DFU_GETSTATUS,
/* wValue */ 0,
- /* wIndex */ interface,
+ /* wIndex */ dif->interface,
/* Data */ buffer,
/* wLength */ 6,
dfu_timeout );
if( 6 == result ) {
status->bStatus = buffer[0];
- status->bwPollTimeout = ((0xff & buffer[3]) << 16) |
- ((0xff & buffer[2]) << 8) |
- (0xff & buffer[1]);
-
+ if (dif->quirks & QUIRK_POLLTIMEOUT)
+ status->bwPollTimeout = DEFAULT_POLLTIMEOUT;
+ else
+ status->bwPollTimeout = ((0xff & buffer[3]) << 16) |
+ ((0xff & buffer[2]) << 8) |
+ (0xff & buffer[1]);
status->bState = buffer[4];
status->iString = buffer[5];
}
@@ -251,9 +175,6 @@ int dfu_get_status( libusb_device_handle *device,
int dfu_clear_status( libusb_device_handle *device,
const unsigned short interface )
{
- if( 0 != dfu_verify_init(__FUNCTION__) )
- return -1;
-
return libusb_control_transfer( device,
/* bmRequestType */ LIBUSB_ENDPOINT_OUT| LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
/* bRequest */ DFU_CLRSTATUS,
@@ -282,9 +203,6 @@ int dfu_get_state( libusb_device_handle *device,
int result;
unsigned char buffer[1];
- if( 0 != dfu_verify_init(__FUNCTION__) )
- return -1;
-
result = libusb_control_transfer( device,
/* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
/* bRequest */ DFU_GETSTATE,
@@ -295,9 +213,8 @@ int dfu_get_state( libusb_device_handle *device,
dfu_timeout );
/* Return the error if there is one. */
- if( result < 1 ) {
- return result;
- }
+ if (result < 1)
+ return -1;
/* Return the state. */
return buffer[0];
@@ -315,9 +232,6 @@ int dfu_get_state( libusb_device_handle *device,
int dfu_abort( libusb_device_handle *device,
const unsigned short interface )
{
- if( 0 != dfu_verify_init(__FUNCTION__) )
- return -1;
-
return libusb_control_transfer( device,
/* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
/* bRequest */ DFU_ABORT,
@@ -329,11 +243,11 @@ int dfu_abort( libusb_device_handle *device,
}
-char* dfu_state_to_string( int state )
+const char* dfu_state_to_string( int state )
{
- char *message = NULL;
+ const char *message;
- switch( state ) {
+ switch (state) {
case STATE_APP_IDLE:
message = "appIDLE";
break;
@@ -367,6 +281,9 @@ char* dfu_state_to_string( int state )
case STATE_DFU_ERROR:
message = "dfuERROR";
break;
+ default:
+ message = NULL;
+ break;
}
return message;
@@ -374,37 +291,38 @@ char* dfu_state_to_string( int state )
/* Chapter 6.1.2 */
static const char *dfu_status_names[] = {
- [DFU_STATUS_OK] = "No error condition is present",
- [DFU_STATUS_errTARGET] =
+ /* DFU_STATUS_OK */
+ "No error condition is present",
+ /* DFU_STATUS_errTARGET */
"File is not targeted for use by this device",
- [DFU_STATUS_errFILE] =
+ /* DFU_STATUS_errFILE */
"File is for this device but fails some vendor-specific test",
- [DFU_STATUS_errWRITE] =
+ /* DFU_STATUS_errWRITE */
"Device is unable to write memory",
- [DFU_STATUS_errERASE] =
+ /* DFU_STATUS_errERASE */
"Memory erase function failed",
- [DFU_STATUS_errCHECK_ERASED] =
+ /* DFU_STATUS_errCHECK_ERASED */
"Memory erase check failed",
- [DFU_STATUS_errPROG] =
+ /* DFU_STATUS_errPROG */
"Program memory function failed",
- [DFU_STATUS_errVERIFY] =
+ /* DFU_STATUS_errVERIFY */
"Programmed memory failed verification",
- [DFU_STATUS_errADDRESS] =
+ /* DFU_STATUS_errADDRESS */
"Cannot program memory due to received address that is out of range",
- [DFU_STATUS_errNOTDONE] =
+ /* DFU_STATUS_errNOTDONE */
"Received DFU_DNLOAD with wLength = 0, but device does not think that it has all data yet",
- [DFU_STATUS_errFIRMWARE] =
+ /* DFU_STATUS_errFIRMWARE */
"Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations",
- [DFU_STATUS_errVENDOR] =
+ /* DFU_STATUS_errVENDOR */
"iString indicates a vendor specific error",
- [DFU_STATUS_errUSBR] =
+ /* DFU_STATUS_errUSBR */
"Device detected unexpected USB reset signalling",
- [DFU_STATUS_errPOR] =
+ /* DFU_STATUS_errPOR */
"Device detected unexpected power on reset",
- [DFU_STATUS_errUNKNOWN] =
+ /* DFU_STATUS_errUNKNOWN */
"Something went wrong, but the device does not know what it was",
- [DFU_STATUS_errSTALLEDPKT] =
- "Device stalled an unexpected request",
+ /* DFU_STATUS_errSTALLEDPKT */
+ "Device stalled an unexpected request"
};
@@ -415,3 +333,25 @@ const char *dfu_status_to_string(int status)
return dfu_status_names[status];
}
+int dfu_abort_to_idle(struct dfu_if *dif)
+{
+ int ret;
+ struct dfu_status dst;
+
+ ret = dfu_abort(dif->dev_handle, dif->interface);
+ if (ret < 0) {
+ errx(EX_IOERR, "Error sending dfu abort request");
+ exit(1);
+ }
+ ret = dfu_get_status(dif, &dst);
+ if (ret < 0) {
+ errx(EX_IOERR, "Error during abort get_status");
+ exit(1);
+ }
+ if (dst.bState != DFU_STATE_dfuIDLE) {
+ errx(EX_IOERR, "Failed to enter idle state on abort");
+ exit(1);
+ }
+ milli_sleep(dst.bwPollTimeout);
+ return ret;
+}
diff --git a/src/dfu.h b/src/dfu.h
index 9e6fda7..8e3caeb 100644
--- a/src/dfu.h
+++ b/src/dfu.h
@@ -18,8 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __DFU_H__
-#define __DFU_H__
+#ifndef DFU_H
+#define DFU_H
#include <libusb.h>
#include "usb_dfu.h"
@@ -67,13 +67,6 @@
/* DFU interface */
#define DFU_IFF_DFU 0x0001 /* DFU Mode, (not Runtime) */
-#define DFU_IFF_VENDOR 0x0100
-#define DFU_IFF_PRODUCT 0x0200
-#define DFU_IFF_CONFIG 0x0400
-#define DFU_IFF_IFACE 0x0800
-#define DFU_IFF_ALT 0x1000
-#define DFU_IFF_DEVNUM 0x2000
-#define DFU_IFF_PATH 0x4000
/* This is based off of DFU_GETSTATUS
*
@@ -91,36 +84,39 @@ struct dfu_status {
};
struct dfu_if {
- u_int16_t vendor;
- u_int16_t product;
- u_int8_t configuration;
- u_int8_t interface;
- u_int8_t altsetting;
- unsigned char *alt_name;
- int bus;
- u_int8_t devnum;
- const char *path;
- unsigned int flags;
- unsigned int count;
+ struct usb_dfu_func_descriptor func_dfu;
+ uint16_t quirks;
+ uint16_t busnum;
+ uint16_t devnum;
+ uint16_t vendor;
+ uint16_t product;
+ uint16_t bcdDevice;
+ uint8_t configuration;
+ uint8_t interface;
+ uint8_t altsetting;
+ uint8_t flags;
+ uint8_t bMaxPacketSize0;
+ char *alt_name;
+ char *serial_name;
libusb_device *dev;
libusb_device_handle *dev_handle;
+ struct dfu_if *next;
};
-void dfu_init( const int timeout );
-void dfu_debug( const int level );
int dfu_detach( libusb_device_handle *device,
const unsigned short interface,
const unsigned short timeout );
int dfu_download( libusb_device_handle *device,
const unsigned short interface,
const unsigned short length,
+ const unsigned short transaction,
unsigned char* data );
int dfu_upload( libusb_device_handle *device,
const unsigned short interface,
const unsigned short length,
+ const unsigned short transaction,
unsigned char* data );
-int dfu_get_status( libusb_device_handle *device,
- const unsigned short interface,
+int dfu_get_status( struct dfu_if *dif,
struct dfu_status *status );
int dfu_clear_status( libusb_device_handle *device,
const unsigned short interface );
@@ -128,10 +124,10 @@ int dfu_get_state( libusb_device_handle *device,
const unsigned short interface );
int dfu_abort( libusb_device_handle *device,
const unsigned short interface );
+int dfu_abort_to_idle( struct dfu_if *dif);
-char* dfu_state_to_string( int state );
+const char *dfu_state_to_string( int state );
-const char *dfu_status_to_string(int status);
+const char *dfu_status_to_string( int status );
-int debug;
-#endif
+#endif /* DFU_H */
diff --git a/src/dfu_file.c b/src/dfu_file.c
index b6a190f..7c897d4 100644
--- a/src/dfu_file.c
+++ b/src/dfu_file.c
@@ -1,7 +1,8 @@
/*
- * Checks for and parses a DFU suffix
+ * Load or store DFU files including suffix and prefix
*
- * (C) 2011 Tormod Volden <debian.tormod@gmail.com>
+ * Copyright 2014 Tormod Volden <debian.tormod@gmail.com>
+ * Copyright 2012 Stefan Schmidt <stefan@datenfreihafen.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
@@ -19,17 +20,23 @@
*/
#include <stdio.h>
-#include <unistd.h>
#include <string.h>
-#include <fcntl.h>
-#include <sys/stat.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+#include "portable.h"
#include "dfu_file.h"
-unsigned long crc32_table[] = {
+#define DFU_SUFFIX_LENGTH 16
+#define LMDFU_PREFIX_LENGTH 8
+#define LPCDFU_PREFIX_LENGTH 16
+#define PROGRESS_BAR_WIDTH 25
+#define STDIN_CHUNK_SIZE 65536
+
+static const unsigned long crc32_table[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
@@ -74,117 +81,364 @@ unsigned long crc32_table[] = {
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
-uint32_t crc32_byte(uint32_t accum, uint8_t delta)
+static uint32_t crc32_byte(uint32_t accum, uint8_t delta)
{
return crc32_table[(accum ^ delta) & 0xff] ^ (accum >> 8);
}
-/* reads the fd and name member, fills in all others
- returns 0 if no DFU suffix
- returns positive if valid DFU suffix
- returns negative on file read error */
-int parse_dfu_suffix(struct dfu_file *file)
+static int probe_prefix(struct dfu_file *file)
+{
+ uint8_t *prefix = file->firmware;
+
+ if (file->size.total < LMDFU_PREFIX_LENGTH)
+ return 1;
+ if ((prefix[0] == 0x01) && (prefix[1] == 0x00)) {
+ file->prefix_type = LMDFU_PREFIX;
+ file->size.prefix = LMDFU_PREFIX_LENGTH;
+ file->lmdfu_address = 1024 * ((prefix[3] << 8) | prefix[2]);
+ }
+ else if (((prefix[0] & 0x3f) == 0x1a) && ((prefix[1] & 0x3f)== 0x3f)) {
+ file->prefix_type = LPCDFU_UNENCRYPTED_PREFIX;
+ file->size.prefix = LPCDFU_PREFIX_LENGTH;
+ }
+
+ if (file->size.prefix + file->size.suffix > file->size.total)
+ return 1;
+ return 0;
+}
+
+void dfu_progress_bar(const char *desc, unsigned long long curr,
+ unsigned long long max)
+{
+ static char buf[PROGRESS_BAR_WIDTH + 1];
+ static unsigned long long last_progress = -1;
+ static time_t last_time;
+ time_t curr_time = time(NULL);
+ unsigned long long progress;
+ unsigned long long x;
+
+ /* check for not known maximum */
+ if (max < curr)
+ max = curr + 1;
+ /* make none out of none give zero */
+ if (max == 0 && curr == 0)
+ max = 1;
+
+ /* compute completion */
+ progress = (PROGRESS_BAR_WIDTH * curr) / max;
+ if (progress > PROGRESS_BAR_WIDTH)
+ progress = PROGRESS_BAR_WIDTH;
+ if (progress == last_progress &&
+ curr_time == last_time)
+ return;
+ last_progress = progress;
+ last_time = curr_time;
+
+ for (x = 0; x != PROGRESS_BAR_WIDTH; x++) {
+ if (x < progress)
+ buf[x] = '=';
+ else
+ buf[x] = ' ';
+ }
+ buf[x] = 0;
+
+ printf("\r%s\t[%s] %3lld%% %12lld bytes", desc, buf,
+ (100ULL * curr) / max, curr);
+
+ if (progress == PROGRESS_BAR_WIDTH)
+ printf("\n%s done.\n", desc);
+}
+
+void *dfu_malloc(size_t size)
+{
+ void *ptr = malloc(size);
+ if (ptr == NULL)
+ errx(EX_SOFTWARE, "Cannot allocate memory of size %d bytes", (int)size);
+ return (ptr);
+}
+
+uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size)
{
- int ret;
+ int x;
+
+ /* compute CRC */
+ for (x = 0; x != size; x++)
+ crc = crc32_byte(crc, ((uint8_t *)buf)[x]);
+
+ /* write data */
+ if (write(f, buf, size) != size)
+ err(EX_IOERR, "Could not write %d bytes to file %d", size, f);
+
+ return (crc);
+}
+
+void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix)
+{
+ off_t offset;
+ int f;
int i;
- struct stat st;
- uint32_t crc = 0xffffffff;
- /* supported suffices are at least 16 bytes */
- unsigned char dfusuffix[16];
- unsigned char *firmware = NULL;
+ int res;
+
+ file->size.prefix = 0;
+ file->size.suffix = 0;
- file->size = 0;
/* default values, if no valid suffix is found */
- file->dwCRC = 0;
- file->suffixlen = 0;
file->bcdDFU = 0;
file->idVendor = 0xffff; /* wildcard value */
file->idProduct = 0xffff; /* wildcard value */
file->bcdDevice = 0xffff; /* wildcard value */
- ret = fstat(file->fd, &st);
- if (ret < 0) {
- perror(file->name);
- return ret;
- }
+ /* default values, if no valid prefix is found */
+ file->lmdfu_address = 0;
- file->size = st.st_size;
- if (file->size < sizeof(dfusuffix)) {
- fprintf(stderr, "File too short for DFU suffix\n");
- return 0;
- }
+ free(file->firmware);
- firmware = malloc(file->size);
- if (!firmware) {
- fprintf(stderr, "Unable to allocate file buffer for firmware.\n");
- exit(1);
- }
+ if (!strcmp(file->name, "-")) {
+ int read_bytes;
- ret = read(file->fd, firmware, file->size);
- if (ret < 0) {
- fprintf(stderr, "Could not read file\n");
- perror(file->name);
- return ret;
- }
+#ifdef WIN32
+ _setmode( _fileno( stdin ), _O_BINARY );
+#endif
+ file->firmware = (uint8_t*) dfu_malloc(STDIN_CHUNK_SIZE);
+ read_bytes = fread(file->firmware, 1, STDIN_CHUNK_SIZE, stdin);
+ file->size.total = read_bytes;
+ while (read_bytes == STDIN_CHUNK_SIZE) {
+ file->firmware = (uint8_t*) realloc(file->firmware, file->size.total + STDIN_CHUNK_SIZE);
+ if (!file->firmware)
+ err(EX_IOERR, "Could not allocate firmware buffer");
+ read_bytes = fread(file->firmware + file->size.total, 1, STDIN_CHUNK_SIZE, stdin);
+ file->size.total += read_bytes;
+ }
+ if (verbose)
+ printf("Read %i bytes from stdin\n", file->size.total);
+ /* Never require suffix when reading from stdin */
+ check_suffix = MAYBE_SUFFIX;
+ } else {
+ f = open(file->name, O_RDONLY | O_BINARY);
+ if (f < 0)
+ err(EX_IOERR, "Could not open file %s for reading", file->name);
- for (i = 0; i < file->size - 4; i++)
- crc = crc32_byte(crc, firmware[i]);
+ offset = lseek(f, 0, SEEK_END);
- free(firmware);
+ if ((int)offset < 0 || (int)offset != offset)
+ err(EX_IOERR, "File size is too big");
- ret = lseek(file->fd, -sizeof(dfusuffix), SEEK_END);
- if (ret < 0) {
- fprintf(stderr, "Could not seek to DFU suffix\n");
- perror(file->name);
- goto rewind;
- }
+ if (lseek(f, 0, SEEK_SET) != 0)
+ err(EX_IOERR, "Could not seek to beginning");
- ret = read(file->fd, dfusuffix, sizeof(dfusuffix));
- if (ret < 0) {
- fprintf(stderr, "Could not read DFU suffix\n");
- perror(file->name);
- goto rewind;
- } else if (ret < sizeof(dfusuffix)) {
- fprintf(stderr, "Could not read whole DFU suffix\n");
- ret = -EIO;
- goto rewind;
- }
+ file->size.total = offset;
+ file->firmware = dfu_malloc(file->size.total);
- if (dfusuffix[10] != 'D' ||
- dfusuffix[9] != 'F' ||
- dfusuffix[8] != 'U') {
- fprintf(stderr, "No valid DFU suffix signature\n");
- ret = 0;
- goto rewind;
+ if (read(f, file->firmware, file->size.total) != file->size.total) {
+ err(EX_IOERR, "Could not read %d bytes from %s",
+ file->size.total, file->name);
+ }
+ close(f);
}
- file->dwCRC = (dfusuffix[15] << 24) +
- (dfusuffix[14] << 16) +
- (dfusuffix[13] << 8) +
- dfusuffix[12];
+ /* Check for possible DFU file suffix by trying to parse one */
+ {
+ uint32_t crc = 0xffffffff;
+ const uint8_t *dfusuffix;
+ int missing_suffix = 0;
+ const char *reason;
+
+ if (file->size.total < DFU_SUFFIX_LENGTH) {
+ reason = "File too short for DFU suffix";
+ missing_suffix = 1;
+ goto checked;
+ }
+
+ dfusuffix = file->firmware + file->size.total -
+ DFU_SUFFIX_LENGTH;
+
+ for (i = 0; i < file->size.total - 4; i++)
+ crc = crc32_byte(crc, file->firmware[i]);
+
+ if (dfusuffix[10] != 'D' ||
+ dfusuffix[9] != 'F' ||
+ dfusuffix[8] != 'U') {
+ reason = "Invalid DFU suffix signature";
+ missing_suffix = 1;
+ goto checked;
+ }
+
+ file->dwCRC = (dfusuffix[15] << 24) +
+ (dfusuffix[14] << 16) +
+ (dfusuffix[13] << 8) +
+ dfusuffix[12];
+
+ if (file->dwCRC != crc) {
+ reason = "DFU suffix CRC does not match";
+ missing_suffix = 1;
+ goto checked;
+ }
+
+ /* At this point we believe we have a DFU suffix
+ so we require further checks to succeed */
- if (file->dwCRC != crc) {
- fprintf(stderr, "DFU CRC does not match\n");
- goto rewind;
+ file->bcdDFU = (dfusuffix[7] << 8) + dfusuffix[6];
+
+ if (verbose)
+ printf("DFU suffix version %x\n", file->bcdDFU);
+
+ file->size.suffix = dfusuffix[11];
+
+ if (file->size.suffix < DFU_SUFFIX_LENGTH) {
+ errx(EX_IOERR, "Unsupported DFU suffix length %d",
+ file->size.suffix);
+ }
+
+ if (file->size.suffix > file->size.total) {
+ errx(EX_IOERR, "Invalid DFU suffix length %d",
+ file->size.suffix);
+ }
+
+ file->idVendor = (dfusuffix[5] << 8) + dfusuffix[4];
+ file->idProduct = (dfusuffix[3] << 8) + dfusuffix[2];
+ file->bcdDevice = (dfusuffix[1] << 8) + dfusuffix[0];
+
+checked:
+ if (missing_suffix) {
+ if (check_suffix == NEEDS_SUFFIX) {
+ warnx("%s", reason);
+ errx(EX_IOERR, "Valid DFU suffix needed");
+ } else if (check_suffix == MAYBE_SUFFIX) {
+ warnx("%s", reason);
+ warnx("A valid DFU suffix will be required in "
+ "a future dfu-util release!!!");
+ }
+ } else {
+ if (check_suffix == NO_SUFFIX) {
+ errx(EX_SOFTWARE, "Please remove existing DFU suffix before adding a new one.\n");
+ }
+ }
}
+ res = probe_prefix(file);
+ if ((res || file->size.prefix == 0) && check_prefix == NEEDS_PREFIX)
+ errx(EX_IOERR, "Valid DFU prefix needed");
+ if (file->size.prefix && check_prefix == NO_PREFIX)
+ errx(EX_IOERR, "A prefix already exists, please delete it first");
+ if (file->size.prefix && verbose) {
+ uint8_t *data = file->firmware;
+ if (file->prefix_type == LMDFU_PREFIX)
+ printf("Possible TI Stellaris DFU prefix with "
+ "the following properties\n"
+ "Address: 0x%08x\n"
+ "Payload length: %d\n",
+ file->lmdfu_address,
+ data[4] | (data[5] << 8) |
+ (data[6] << 16) | (data[7] << 14));
+ else if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX)
+ printf("Possible unencrypted NXP LPC DFU prefix with "
+ "the following properties\n"
+ "Payload length: %d kiByte\n",
+ data[2] >>1 | (data[3] << 7) );
+ else
+ errx(EX_IOERR, "Unknown DFU prefix type");
+ }
+}
- file->bcdDFU = (dfusuffix[7] << 8) + dfusuffix[6];
- printf("Dfu suffix version %x\n", file->bcdDFU);
+void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix)
+{
+ uint32_t crc = 0xffffffff;
+ int f;
+
+ f = open(file->name, O_WRONLY | O_BINARY | O_TRUNC | O_CREAT, 0666);
+ if (f < 0)
+ err(EX_IOERR, "Could not open file %s for writing", file->name);
+
+ /* write prefix, if any */
+ if (write_prefix) {
+ if (file->prefix_type == LMDFU_PREFIX) {
+ uint8_t lmdfu_prefix[LMDFU_PREFIX_LENGTH];
+ uint32_t addr = file->lmdfu_address / 1024;
+
+ /* lmdfu_dfu_prefix payload length excludes prefix and suffix */
+ uint32_t len = file->size.total -
+ file->size.prefix - file->size.suffix;
+
+ lmdfu_prefix[0] = 0x01; /* STELLARIS_DFU_PROG */
+ lmdfu_prefix[1] = 0x00; /* Reserved */
+ lmdfu_prefix[2] = (uint8_t)(addr & 0xff);
+ lmdfu_prefix[3] = (uint8_t)(addr >> 8);
+ lmdfu_prefix[4] = (uint8_t)(len & 0xff);
+ lmdfu_prefix[5] = (uint8_t)(len >> 8) & 0xff;
+ lmdfu_prefix[6] = (uint8_t)(len >> 16) & 0xff;
+ lmdfu_prefix[7] = (uint8_t)(len >> 24);
+
+ crc = dfu_file_write_crc(f, crc, lmdfu_prefix, LMDFU_PREFIX_LENGTH);
+ }
+ if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX) {
+ uint8_t lpcdfu_prefix[LPCDFU_PREFIX_LENGTH] = {0};
+ int i;
+
+ /* Payload is firmware and prefix rounded to 512 bytes */
+ uint32_t len = (file->size.total - file->size.suffix + 511) /512;
+
+ lpcdfu_prefix[0] = 0x1a; /* Unencypted*/
+ lpcdfu_prefix[1] = 0x3f; /* Reserved */
+ lpcdfu_prefix[2] = (uint8_t)(len & 0xff);
+ lpcdfu_prefix[3] = (uint8_t)((len >> 8) & 0xff);
+ for (i = 12; i < LPCDFU_PREFIX_LENGTH; i++)
+ lpcdfu_prefix[i] = 0xff;
- file->suffixlen = dfusuffix[11];
- if (file->suffixlen < sizeof(dfusuffix)) {
- fprintf(stderr, "Unsupported DFU suffix length %i\n",
- file->suffixlen);
- ret = 0;
- goto rewind;
+ crc = dfu_file_write_crc(f, crc, lpcdfu_prefix, LPCDFU_PREFIX_LENGTH);
+ }
}
+ /* write firmware binary */
+ crc = dfu_file_write_crc(f, crc, file->firmware + file->size.prefix,
+ file->size.total - file->size.prefix - file->size.suffix);
- file->idVendor = (dfusuffix[5] << 8) + dfusuffix[4];
- file->idProduct = (dfusuffix[3] << 8) + dfusuffix[2];
- file->bcdDevice = (dfusuffix[1] << 8) + dfusuffix[0];
+ /* write suffix, if any */
+ if (write_suffix) {
+ uint8_t dfusuffix[DFU_SUFFIX_LENGTH];
-rewind:
- lseek(file->fd, 0, SEEK_SET);
- return ret;
+ dfusuffix[0] = file->bcdDevice & 0xff;
+ dfusuffix[1] = file->bcdDevice >> 8;
+ dfusuffix[2] = file->idProduct & 0xff;
+ dfusuffix[3] = file->idProduct >> 8;
+ dfusuffix[4] = file->idVendor & 0xff;
+ dfusuffix[5] = file->idVendor >> 8;
+ dfusuffix[6] = file->bcdDFU & 0xff;
+ dfusuffix[7] = file->bcdDFU >> 8;
+ dfusuffix[8] = 'U';
+ dfusuffix[9] = 'F';
+ dfusuffix[10] = 'D';
+ dfusuffix[11] = DFU_SUFFIX_LENGTH;
+
+ crc = dfu_file_write_crc(f, crc, dfusuffix,
+ DFU_SUFFIX_LENGTH - 4);
+
+ dfusuffix[12] = crc;
+ dfusuffix[13] = crc >> 8;
+ dfusuffix[14] = crc >> 16;
+ dfusuffix[15] = crc >> 24;
+
+ crc = dfu_file_write_crc(f, crc, dfusuffix + 12, 4);
+ }
+ close(f);
}
+void show_suffix_and_prefix(struct dfu_file *file)
+{
+ if (file->size.prefix == LMDFU_PREFIX_LENGTH) {
+ printf("The file %s contains a TI Stellaris DFU prefix with the following properties:\n", file->name);
+ printf("Address:\t0x%08x\n", file->lmdfu_address);
+ } else if (file->size.prefix == LPCDFU_PREFIX_LENGTH) {
+ uint8_t * prefix = file->firmware;
+ printf("The file %s contains a NXP unencrypted LPC DFU prefix with the following properties:\n", file->name);
+ printf("Size:\t%5d kiB\n", prefix[2]>>1|prefix[3]<<7);
+ } else if (file->size.prefix != 0) {
+ printf("The file %s contains an unknown prefix\n", file->name);
+ }
+ if (file->size.suffix > 0) {
+ printf("The file %s contains a DFU suffix with the following properties:\n", file->name);
+ printf("BCD device:\t0x%04X\n", file->bcdDevice);
+ printf("Product ID:\t0x%04X\n",file->idProduct);
+ printf("Vendor ID:\t0x%04X\n", file->idVendor);
+ printf("BCD DFU:\t0x%04X\n", file->bcdDFU);
+ printf("Length:\t\t%i\n", file->size.suffix);
+ printf("CRC:\t\t0x%08X\n", file->dwCRC);
+ }
+}
diff --git a/src/dfu_file.h b/src/dfu_file.h
index 8c33665..abebd44 100644
--- a/src/dfu_file.h
+++ b/src/dfu_file.h
@@ -1,20 +1,60 @@
-#ifndef _DFU_FILE_H
-#define _DFU_FILE_H
+#ifndef DFU_FILE_H
+#define DFU_FILE_H
+
+#include <stdint.h>
struct dfu_file {
+ /* File name */
const char *name;
- int fd;
- off_t size;
+ /* Pointer to file loaded into memory */
+ uint8_t *firmware;
+ /* Different sizes */
+ struct {
+ int total;
+ int prefix;
+ int suffix;
+ } size;
+ /* From prefix fields */
+ uint32_t lmdfu_address;
+ /* From prefix fields */
+ uint32_t prefix_type;
+
/* From DFU suffix fields */
- u_int32_t dwCRC;
- unsigned char suffixlen;
- u_int16_t bcdDFU;
- u_int16_t idVendor;
- u_int16_t idProduct;
- u_int16_t bcdDevice;
+ uint32_t dwCRC;
+ uint16_t bcdDFU;
+ uint16_t idVendor;
+ uint16_t idProduct;
+ uint16_t bcdDevice;
+};
+
+enum suffix_req {
+ NO_SUFFIX,
+ NEEDS_SUFFIX,
+ MAYBE_SUFFIX
+};
+
+enum prefix_req {
+ NO_PREFIX,
+ NEEDS_PREFIX,
+ MAYBE_PREFIX
+};
+
+enum prefix_type {
+ ZERO_PREFIX,
+ LMDFU_PREFIX,
+ LPCDFU_UNENCRYPTED_PREFIX
};
-int parse_dfu_suffix(struct dfu_file *file);
+extern int verbose;
+
+void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix);
+void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix);
+
+void dfu_progress_bar(const char *desc, unsigned long long curr,
+ unsigned long long max);
+void *dfu_malloc(size_t size);
+uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size);
+void show_suffix_and_prefix(struct dfu_file *file);
-#endif
+#endif /* DFU_FILE_H */
diff --git a/src/dfu_load.c b/src/dfu_load.c
index 85da452..64f7009 100644
--- a/src/dfu_load.c
+++ b/src/dfu_load.c
@@ -1,10 +1,15 @@
-/* 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...
+/*
+ * DFU transfer routines
+ *
+ * This is supposed to be a general DFU implementation, as specified in the
+ * USB DFU 1.0 and 1.1 specification.
*
* The code was originally intended to interface with a USB device running the
* "sam7dfu" firmware (see http://www.openpcd.org/) on an AT91SAM7 processor.
*
- * (C) 2007-2008 by Harald Welte <laforge@gnumonks.org>
+ * Copyright 2007-2008 Harald Welte <laforge@gnumonks.org>
+ * Copyright 2013 Hans Petter Selasky <hps@bitfrost.no>
+ * Copyright 2014 Tormod Volden <debian.tormod@gmail.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
@@ -23,124 +28,108 @@
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <errno.h>
#include <string.h>
+
#include <libusb.h>
-#include "config.h"
+#include "portable.h"
#include "dfu.h"
#include "usb_dfu.h"
#include "dfu_file.h"
#include "dfu_load.h"
#include "quirks.h"
-extern int verbose;
-
-int dfuload_do_upload(struct dfu_if *dif, int xfer_size, struct dfu_file file)
+int dfuload_do_upload(struct dfu_if *dif, int xfer_size,
+ int expected_size, int fd)
{
int total_bytes = 0;
+ unsigned short transaction = 0;
unsigned char *buf;
int ret;
- buf = malloc(xfer_size);
- if (!buf)
- return -ENOMEM;
+ buf = dfu_malloc(xfer_size);
- printf("bytes_per_hash=%u\n", xfer_size);
printf("Copying data from DFU device to PC\n");
- printf("Starting upload: [");
- fflush(stdout);
+ dfu_progress_bar("Upload", 0, 1);
while (1) {
- int rc, write_rc;
- rc = dfu_upload(dif->dev_handle, dif->interface, xfer_size, buf);
+ int rc;
+ rc = dfu_upload(dif->dev_handle, dif->interface,
+ xfer_size, transaction++, buf);
if (rc < 0) {
+ warnx("Error during upload");
ret = rc;
goto out_free;
}
- write_rc = write(file.fd, buf, rc);
- if (write_rc < rc) {
- fprintf(stderr, "Short file write: %s\n",
- strerror(errno));
- ret = total_bytes;
- goto out_free;
- }
+
+ dfu_file_write_crc(fd, 0, buf, rc);
total_bytes += rc;
+
+ if (total_bytes < 0)
+ errx(EX_SOFTWARE, "Received too many bytes (wraparound)");
+
if (rc < xfer_size) {
/* last block, return */
ret = total_bytes;
break;
}
- putchar('#');
- fflush(stdout);
+ dfu_progress_bar("Upload", total_bytes, expected_size);
}
ret = 0;
- printf("] finished!\n");
- fflush(stdout);
-
out_free:
+ dfu_progress_bar("Upload", total_bytes, total_bytes);
+ if (total_bytes == 0)
+ printf("\nFailed.\n");
free(buf);
if (verbose)
printf("Received a total of %i bytes\n", total_bytes);
-
+ if (expected_size != 0 && total_bytes != expected_size)
+ errx(EX_SOFTWARE, "Unexpected number of bytes uploaded from device");
return ret;
}
-#define PROGRESS_BAR_WIDTH 50
-
-int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file file)
+int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file)
{
- int bytes_sent = 0;
- unsigned int bytes_per_hash, hashes = 0;
+ int bytes_sent;
+ int expected_size;
unsigned char *buf;
+ unsigned short transaction = 0;
struct dfu_status dst;
int ret;
- buf = malloc(xfer_size);
- if (!buf)
- return -ENOMEM;
-
- bytes_per_hash = (file.size - file.suffixlen) / PROGRESS_BAR_WIDTH;
- if (bytes_per_hash == 0)
- bytes_per_hash = 1;
- printf("bytes_per_hash=%u\n", bytes_per_hash);
-#if 0
- read(file.fd, DFU_HDR);
-#endif
printf("Copying data from PC to DFU device\n");
- printf("Starting download: [");
- fflush(stdout);
- while (bytes_sent < file.size - file.suffixlen) {
- int hashes_todo;
+
+ buf = file->firmware;
+ expected_size = file->size.total - file->size.suffix;
+ bytes_sent = 0;
+
+ dfu_progress_bar("Download", 0, 1);
+ while (bytes_sent < expected_size) {
int bytes_left;
int chunk_size;
- bytes_left = file.size - file.suffixlen - bytes_sent;
+ bytes_left = expected_size - bytes_sent;
if (bytes_left < xfer_size)
chunk_size = bytes_left;
else
chunk_size = xfer_size;
- ret = read(file.fd, buf, chunk_size);
- if (ret < 0) {
- perror(file.name);
- goto out_free;
- }
- ret = dfu_download(dif->dev_handle, dif->interface, ret, ret ? buf : NULL);
+
+ ret = dfu_download(dif->dev_handle, dif->interface,
+ chunk_size, transaction++, chunk_size ? buf : NULL);
if (ret < 0) {
- fprintf(stderr, "Error during download\n");
- goto out_free;
+ warnx("Error during download");
+ goto out;
}
- bytes_sent += ret;
+ bytes_sent += chunk_size;
+ buf += chunk_size;
do {
- ret = dfu_get_status(dif->dev_handle, dif->interface, &dst);
+ ret = dfu_get_status(dif, &dst);
if (ret < 0) {
- fprintf(stderr, "Error during download get_status\n");
- goto out_free;
+ errx(EX_IOERR, "Error during download get_status");
+ goto out;
}
if (dst.bState == DFU_STATE_dfuDNLOAD_IDLE ||
@@ -148,10 +137,7 @@ int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file file)
break;
/* Wait while device executes flashing */
- if (quirks & QUIRK_POLLTIMEOUT)
- usleep(DEFAULT_POLLTIMEOUT * 1000);
- else
- usleep(dst.bwPollTimeout * 1000);
+ milli_sleep(dst.bwPollTimeout);
} while (1);
if (dst.bStatus != DFU_STATUS_OK) {
@@ -160,40 +146,36 @@ int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file file)
dfu_state_to_string(dst.bState), dst.bStatus,
dfu_status_to_string(dst.bStatus));
ret = -1;
- goto out_free;
+ goto out;
}
-
- hashes_todo = (bytes_sent / bytes_per_hash) - hashes;
- hashes += hashes_todo;
- while (hashes_todo--)
- putchar('#');
- fflush(stdout);
+ dfu_progress_bar("Download", bytes_sent, bytes_sent + bytes_left);
}
/* send one zero sized download request to signalize end */
- ret = dfu_download(dif->dev_handle, dif->interface, 0, NULL);
+ ret = dfu_download(dif->dev_handle, dif->interface,
+ 0, transaction, NULL);
if (ret < 0) {
- fprintf(stderr, "Error sending completion packet\n");
- goto out_free;
+ errx(EX_IOERR, "Error sending completion packet");
+ goto out;
}
- printf("] finished!\n");
- fflush(stdout);
+ dfu_progress_bar("Download", bytes_sent, bytes_sent);
+
if (verbose)
printf("Sent a total of %i bytes\n", bytes_sent);
get_status:
/* Transition to MANIFEST_SYNC state */
- ret = dfu_get_status(dif->dev_handle, dif->interface, &dst);
+ ret = dfu_get_status(dif, &dst);
if (ret < 0) {
- fprintf(stderr, "unable to read DFU status\n");
- goto out_free;
+ warnx("unable to read DFU status after completion");
+ goto out;
}
printf("state(%u) = %s, status(%u) = %s\n", dst.bState,
dfu_state_to_string(dst.bState), dst.bStatus,
dfu_status_to_string(dst.bStatus));
- if (!(quirks & QUIRK_POLLTIMEOUT))
- usleep(dst.bwPollTimeout * 1000);
+
+ milli_sleep(dst.bwPollTimeout);
/* FIXME: deal correctly with ManifestationTolerant=0 / WillDetach bits */
switch (dst.bState) {
@@ -201,30 +183,14 @@ get_status:
case DFU_STATE_dfuMANIFEST:
/* some devices (e.g. TAS1020b) need some time before we
* can obtain the status */
- sleep(1);
+ milli_sleep(1000);
goto get_status;
break;
case DFU_STATE_dfuIDLE:
break;
}
-#if 0
- printf("Resetting USB...\n");
- if (usb_reset(dif->dev_handle) < 0) {
- fprintf(stderr, "error resetting after download: %s\n",
- usb_strerror());
- }
-#endif
printf("Done!\n");
-out_free:
- free(buf);
-
+out:
return bytes_sent;
}
-
-void dfuload_init()
-{
- dfu_debug( debug );
- dfu_init( 5000 );
-}
-
diff --git a/src/dfu_load.h b/src/dfu_load.h
index ba50506..be23e9b 100644
--- a/src/dfu_load.h
+++ b/src/dfu_load.h
@@ -1,7 +1,7 @@
-#ifndef _SAM7DFU_H
-#define _SAM7DFU_H
+#ifndef DFU_LOAD_H
+#define DFU_LOAD_H
-int dfuload_do_upload(struct dfu_if *dif, int xfer_size, struct dfu_file file);
-int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file file);
+int dfuload_do_upload(struct dfu_if *dif, int xfer_size, int expected_size, int fd);
+int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file);
-#endif
+#endif /* DFU_LOAD_H */
diff --git a/src/dfu_util.c b/src/dfu_util.c
new file mode 100644
index 0000000..b94c7cc
--- /dev/null
+++ b/src/dfu_util.c
@@ -0,0 +1,346 @@
+/*
+ * Functions for detecting DFU USB entities
+ *
+ * Written by Harald Welte <laforge@openmoko.org>
+ * Copyright 2007-2008 by OpenMoko, Inc.
+ * Copyright 2013 Hans Petter Selasky <hps@bitfrost.no>
+ *
+ * Based on existing code of dfu-programmer-0.4
+ *
+ * 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
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <libusb.h>
+
+#include "portable.h"
+#include "dfu.h"
+#include "usb_dfu.h"
+#include "dfu_file.h"
+#include "dfu_load.h"
+#include "dfu_util.h"
+#include "dfuse.h"
+#include "quirks.h"
+
+#ifdef HAVE_USBPATH_H
+#include <usbpath.h>
+#endif
+
+/*
+ * Look for a descriptor in a concatenated descriptor list. Will
+ * return upon the first match of the given descriptor type. Returns length of
+ * found descriptor, limited to res_size
+ */
+static int find_descriptor(const uint8_t *desc_list, int list_len,
+ uint8_t desc_type, void *res_buf, int res_size)
+{
+ int p = 0;
+
+ if (list_len < 2)
+ return (-1);
+
+ while (p + 1 < list_len) {
+ int desclen;
+
+ desclen = (int) desc_list[p];
+ if (desclen == 0) {
+ warnx("Invalid descriptor list");
+ return -1;
+ }
+ if (desc_list[p + 1] == desc_type) {
+ if (desclen > res_size)
+ desclen = res_size;
+ if (p + desclen > list_len)
+ desclen = list_len - p;
+ memcpy(res_buf, &desc_list[p], desclen);
+ return desclen;
+ }
+ p += (int) desc_list[p];
+ }
+ return -1;
+}
+
+static void probe_configuration(libusb_device *dev, struct libusb_device_descriptor *desc)
+{
+ struct usb_dfu_func_descriptor func_dfu;
+ libusb_device_handle *devh;
+ struct dfu_if *pdfu;
+ struct libusb_config_descriptor *cfg;
+ const struct libusb_interface_descriptor *intf;
+ const struct libusb_interface *uif;
+ char alt_name[MAX_DESC_STR_LEN + 1];
+ char serial_name[MAX_DESC_STR_LEN + 1];
+ int cfg_idx;
+ int intf_idx;
+ int alt_idx;
+ int ret;
+ int has_dfu;
+
+ for (cfg_idx = 0; cfg_idx != desc->bNumConfigurations; cfg_idx++) {
+ memset(&func_dfu, 0, sizeof(func_dfu));
+ has_dfu = 0;
+
+ ret = libusb_get_config_descriptor(dev, cfg_idx, &cfg);
+ if (ret != 0)
+ return;
+ if (match_config_index > -1 && match_config_index != cfg->bConfigurationValue) {
+ libusb_free_config_descriptor(cfg);
+ continue;
+ }
+
+ /*
+ * In some cases, noticably FreeBSD if uid != 0,
+ * the configuration descriptors are empty
+ */
+ if (!cfg)
+ return;
+
+ ret = find_descriptor(cfg->extra, cfg->extra_length,
+ USB_DT_DFU, &func_dfu, sizeof(func_dfu));
+ if (ret > -1)
+ goto found_dfu;
+
+ for (intf_idx = 0; intf_idx < cfg->bNumInterfaces;
+ intf_idx++) {
+ uif = &cfg->interface[intf_idx];
+ if (!uif)
+ break;
+
+ for (alt_idx = 0; alt_idx < cfg->interface[intf_idx].num_altsetting;
+ alt_idx++) {
+ intf = &uif->altsetting[alt_idx];
+
+ ret = find_descriptor(intf->extra, intf->extra_length, USB_DT_DFU,
+ &func_dfu, sizeof(func_dfu));
+ if (ret > -1)
+ goto found_dfu;
+
+ if (intf->bInterfaceClass != 0xfe ||
+ intf->bInterfaceSubClass != 1)
+ continue;
+
+ has_dfu = 1;
+ }
+ }
+ if (has_dfu) {
+ /*
+ * Finally try to retrieve it requesting the
+ * device directly This is not supported on
+ * all devices for non-standard types
+ */
+ if (libusb_open(dev, &devh) == 0) {
+ ret = libusb_get_descriptor(devh, USB_DT_DFU, 0,
+ (void *)&func_dfu, sizeof(func_dfu));
+ libusb_close(devh);
+ if (ret > -1)
+ goto found_dfu;
+ }
+ warnx("Device has DFU interface, "
+ "but has no DFU functional descriptor");
+
+ /* fake version 1.0 */
+ func_dfu.bLength = 7;
+ func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
+ goto found_dfu;
+ }
+ libusb_free_config_descriptor(cfg);
+ continue;
+
+found_dfu:
+ if (func_dfu.bLength == 7) {
+ printf("Deducing device DFU version from functional descriptor "
+ "length\n");
+ func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
+ } else if (func_dfu.bLength < 9) {
+ printf("Error obtaining DFU functional descriptor\n");
+ printf("Please report this as a bug!\n");
+ printf("Warning: Assuming DFU version 1.0\n");
+ func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
+ printf("Warning: Transfer size can not be detected\n");
+ func_dfu.wTransferSize = 0;
+ }
+
+ for (intf_idx = 0; intf_idx < cfg->bNumInterfaces;
+ intf_idx++) {
+ if (match_iface_index > -1 && match_iface_index != intf_idx)
+ continue;
+
+ uif = &cfg->interface[intf_idx];
+ if (!uif)
+ break;
+
+ for (alt_idx = 0;
+ alt_idx < uif->num_altsetting; alt_idx++) {
+ int dfu_mode;
+
+ intf = &uif->altsetting[alt_idx];
+
+ if (intf->bInterfaceClass != 0xfe ||
+ intf->bInterfaceSubClass != 1)
+ continue;
+
+ dfu_mode = (intf->bInterfaceProtocol == 2);
+ /* e.g. DSO Nano has bInterfaceProtocol 0 instead of 2 */
+ if (func_dfu.bcdDFUVersion == 0x011a && intf->bInterfaceProtocol == 0)
+ dfu_mode = 1;
+
+ if (dfu_mode &&
+ match_iface_alt_index > -1 && match_iface_alt_index != alt_idx)
+ continue;
+
+ if (dfu_mode) {
+ if ((match_vendor_dfu >= 0 && match_vendor_dfu != desc->idVendor) ||
+ (match_product_dfu >= 0 && match_product_dfu != desc->idProduct)) {
+ continue;
+ }
+ } else {
+ if ((match_vendor >= 0 && match_vendor != desc->idVendor) ||
+ (match_product >= 0 && match_product != desc->idProduct)) {
+ continue;
+ }
+ }
+
+ if (libusb_open(dev, &devh)) {
+ warnx("Cannot open DFU device %04x:%04x", desc->idVendor, desc->idProduct);
+ break;
+ }
+ if (intf->iInterface != 0)
+ ret = libusb_get_string_descriptor_ascii(devh,
+ intf->iInterface, (void *)alt_name, MAX_DESC_STR_LEN);
+ else
+ ret = -1;
+ if (ret < 1)
+ strcpy(alt_name, "UNKNOWN");
+ if (desc->iSerialNumber != 0)
+ ret = libusb_get_string_descriptor_ascii(devh,
+ desc->iSerialNumber, (void *)serial_name, MAX_DESC_STR_LEN);
+ else
+ ret = -1;
+ if (ret < 1)
+ strcpy(serial_name, "UNKNOWN");
+ libusb_close(devh);
+
+ if (dfu_mode &&
+ match_iface_alt_name != NULL && strcmp(alt_name, match_iface_alt_name))
+ continue;
+
+ if (dfu_mode) {
+ if (match_serial_dfu != NULL && strcmp(match_serial_dfu, serial_name))
+ continue;
+ } else {
+ if (match_serial != NULL && strcmp(match_serial, serial_name))
+ continue;
+ }
+
+ pdfu = dfu_malloc(sizeof(*pdfu));
+
+ memset(pdfu, 0, sizeof(*pdfu));
+
+ pdfu->func_dfu = func_dfu;
+ pdfu->dev = libusb_ref_device(dev);
+ pdfu->quirks = get_quirks(desc->idVendor,
+ desc->idProduct, desc->bcdDevice);
+ pdfu->vendor = desc->idVendor;
+ pdfu->product = desc->idProduct;
+ pdfu->bcdDevice = desc->bcdDevice;
+ pdfu->configuration = cfg->bConfigurationValue;
+ pdfu->interface = intf->bInterfaceNumber;
+ pdfu->altsetting = intf->bAlternateSetting;
+ pdfu->devnum = libusb_get_device_address(dev);
+ pdfu->busnum = libusb_get_bus_number(dev);
+ pdfu->alt_name = strdup(alt_name);
+ if (pdfu->alt_name == NULL)
+ errx(EX_SOFTWARE, "Out of memory");
+ pdfu->serial_name = strdup(serial_name);
+ if (pdfu->serial_name == NULL)
+ errx(EX_SOFTWARE, "Out of memory");
+ if (dfu_mode)
+ pdfu->flags |= DFU_IFF_DFU;
+ if (pdfu->quirks & QUIRK_FORCE_DFU11) {
+ pdfu->func_dfu.bcdDFUVersion =
+ libusb_cpu_to_le16(0x0110);
+ }
+ pdfu->bMaxPacketSize0 = desc->bMaxPacketSize0;
+
+ /* queue into list */
+ pdfu->next = dfu_root;
+ dfu_root = pdfu;
+ }
+ }
+ libusb_free_config_descriptor(cfg);
+ }
+}
+
+void probe_devices(libusb_context *ctx)
+{
+ libusb_device **list;
+ ssize_t num_devs;
+ ssize_t i;
+
+ num_devs = libusb_get_device_list(ctx, &list);
+ for (i = 0; i < num_devs; ++i) {
+ struct libusb_device_descriptor desc;
+ struct libusb_device *dev = list[i];
+
+ if (match_bus > -1 && match_bus != libusb_get_bus_number(dev))
+ continue;
+ if (match_device > -1 && match_device != libusb_get_device_address(dev))
+ continue;
+ if (libusb_get_device_descriptor(dev, &desc))
+ continue;
+ probe_configuration(dev, &desc);
+ }
+ libusb_free_device_list(list, 0);
+}
+
+void disconnect_devices(void)
+{
+ struct dfu_if *pdfu;
+ struct dfu_if *prev = NULL;
+
+ for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) {
+ free(prev);
+ libusb_unref_device(pdfu->dev);
+ free(pdfu->alt_name);
+ free(pdfu->serial_name);
+ prev = pdfu;
+ }
+ free(prev);
+ dfu_root = NULL;
+}
+
+void print_dfu_if(struct dfu_if *dfu_if)
+{
+ printf("Found %s: [%04x:%04x] ver=%04x, devnum=%u, cfg=%u, intf=%u, "
+ "alt=%u, name=\"%s\", serial=\"%s\"\n",
+ dfu_if->flags & DFU_IFF_DFU ? "DFU" : "Runtime",
+ dfu_if->vendor, dfu_if->product,
+ dfu_if->bcdDevice, dfu_if->devnum,
+ dfu_if->configuration, dfu_if->interface,
+ dfu_if->altsetting, dfu_if->alt_name,
+ dfu_if->serial_name);
+}
+
+/* Walk the device tree and print out DFU devices */
+void list_dfu_interfaces(void)
+{
+ struct dfu_if *pdfu;
+
+ for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next)
+ print_dfu_if(pdfu);
+}
diff --git a/src/dfu_util.h b/src/dfu_util.h
new file mode 100644
index 0000000..fc0c19d
--- /dev/null
+++ b/src/dfu_util.h
@@ -0,0 +1,36 @@
+#ifndef DFU_UTIL_H
+#define DFU_UTIL_H
+
+/* USB string descriptor should contain max 126 UTF-16 characters
+ * but 253 would even accomodate any UTF-8 encoding */
+#define MAX_DESC_STR_LEN 253
+
+enum mode {
+ MODE_NONE,
+ MODE_VERSION,
+ MODE_LIST,
+ MODE_DETACH,
+ MODE_UPLOAD,
+ MODE_DOWNLOAD
+};
+
+extern struct dfu_if *dfu_root;
+extern int match_bus;
+extern int match_device;
+extern int match_vendor;
+extern int match_product;
+extern int match_vendor_dfu;
+extern int match_product_dfu;
+extern int match_config_index;
+extern int match_iface_index;
+extern int match_iface_alt_index;
+extern const char *match_iface_alt_name;
+extern const char *match_serial;
+extern const char *match_serial_dfu;
+
+void probe_devices(libusb_context *);
+void disconnect_devices(void);
+void print_dfu_if(struct dfu_if *);
+void list_dfu_interfaces(void);
+
+#endif /* DFU_UTIL_H */
diff --git a/src/dfuse.c b/src/dfuse.c
index f091bda..fce29fe 100644
--- a/src/dfuse.c
+++ b/src/dfuse.c
@@ -1,7 +1,11 @@
-/* This implements the ST Microsystems DFU extensions (DfuSe)
- * as per the DfuSe 1.1a specification (Document UM0391)
+/*
+ * DfuSe specific functions
+ *
+ * This implements the ST Microsystems DFU extensions (DfuSe)
+ * as per the DfuSe 1.1a specification (ST documents AN3156, AN2606)
+ * The DfuSe file format is described in ST document UM0391.
*
- * (C) 2010-2011 Tormod Volden <debian.tormod@gmail.com>
+ * Copyright 2010-2014 Tormod Volden <debian.tormod@gmail.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
@@ -20,35 +24,95 @@
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
#include <errno.h>
#include <string.h>
-#include <sys/stat.h>
-#include "config.h"
+#include "portable.h"
#include "dfu.h"
#include "usb_dfu.h"
#include "dfu_file.h"
#include "dfuse.h"
#include "dfuse_mem.h"
-/* ugly hack for Win32 */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
#define DFU_TIMEOUT 5000
extern int verbose;
-static unsigned int last_erased = 0;
+static unsigned int last_erased_page = 1; /* non-aligned value, won't match */
static struct memsegment *mem_layout;
+static unsigned int dfuse_address = 0;
+static unsigned int dfuse_length = 0;
+static int dfuse_force = 0;
+static int dfuse_leave = 0;
+static int dfuse_unprotect = 0;
+static int dfuse_mass_erase = 0;
unsigned int quad2uint(unsigned char *p)
{
return (*p + (*(p + 1) << 8) + (*(p + 2) << 16) + (*(p + 3) << 24));
}
+void dfuse_parse_options(const char *options)
+{
+ char *end;
+ const char *endword;
+ unsigned int number;
+
+ /* address, possibly empty, must be first */
+ if (*options != ':') {
+ endword = strchr(options, ':');
+ if (!endword)
+ endword = options + strlen(options); /* GNU strchrnul */
+
+ number = strtoul(options, &end, 0);
+ if (end == endword) {
+ dfuse_address = number;
+ } else {
+ errx(EX_IOERR, "Invalid dfuse address: %s", options);
+ }
+ options = endword;
+ }
+
+ while (*options) {
+ if (*options == ':') {
+ options++;
+ continue;
+ }
+ endword = strchr(options, ':');
+ if (!endword)
+ endword = options + strlen(options);
+
+ if (!strncmp(options, "force", endword - options)) {
+ dfuse_force++;
+ options += 5;
+ continue;
+ }
+ if (!strncmp(options, "leave", endword - options)) {
+ dfuse_leave = 1;
+ options += 5;
+ continue;
+ }
+ if (!strncmp(options, "unprotect", endword - options)) {
+ dfuse_unprotect = 1;
+ options += 9;
+ continue;
+ }
+ if (!strncmp(options, "mass-erase", endword - options)) {
+ dfuse_mass_erase = 1;
+ options += 10;
+ continue;
+ }
+
+ /* any valid number is interpreted as upload length */
+ number = strtoul(options, &end, 0);
+ if (end == endword) {
+ dfuse_length = number;
+ } else {
+ errx(EX_IOERR, "Invalid dfuse modifier: %s", options);
+ }
+ options = endword;
+ }
+}
+
/* DFU_UPLOAD request for DfuSe 1.1a */
int dfuse_upload(struct dfu_if *dif, const unsigned short length,
unsigned char *data, unsigned short transaction)
@@ -66,7 +130,7 @@ int dfuse_upload(struct dfu_if *dif, const unsigned short length,
/* wLength */ length,
DFU_TIMEOUT);
if (status < 0) {
- fprintf(stderr, "%s: libusb_control_msg returned %d\n",
+ errx(EX_IOERR, "%s: libusb_control_msg returned %d",
__FUNCTION__, status);
}
return status;
@@ -89,20 +153,24 @@ int dfuse_download(struct dfu_if *dif, const unsigned short length,
/* wLength */ length,
DFU_TIMEOUT);
if (status < 0) {
- fprintf(stderr, "%s: libusb_control_transfer returned %d\n",
+ errx(EX_IOERR, "%s: libusb_control_transfer returned %d",
__FUNCTION__, status);
}
return status;
}
/* DfuSe only commands */
+/* Leaves the device in dfuDNLOAD-IDLE state */
int dfuse_special_command(struct dfu_if *dif, unsigned int address,
enum dfuse_command command)
{
+ const char* dfuse_command_name[] = { "SET_ADDRESS" , "ERASE_PAGE",
+ "MASS_ERASE", "READ_UNPROTECT"};
unsigned char buf[5];
int length;
int ret;
struct dfu_status dst;
+ int firstpoll = 1;
if (command == ERASE_PAGE) {
struct memsegment *segment;
@@ -110,10 +178,8 @@ int dfuse_special_command(struct dfu_if *dif, unsigned int address,
segment = find_segment(mem_layout, address);
if (!segment || !(segment->memtype & DFUSE_ERASABLE)) {
- fprintf(stderr,
- "Error: Page at 0x%08x can not be erased\n",
+ errx(EX_IOERR, "Page at 0x%08x can not be erased",
address);
- exit(1);
}
page_size = segment->pagesize;
if (verbose > 1)
@@ -122,7 +188,7 @@ int dfuse_special_command(struct dfu_if *dif, unsigned int address,
address & ~(page_size - 1));
buf[0] = 0x41; /* Erase command */
length = 5;
- last_erased = address;
+ last_erased_page = address & ~(page_size - 1);
} else if (command == SET_ADDRESS) {
if (verbose > 2)
printf(" Setting address pointer to 0x%08x\n",
@@ -132,10 +198,11 @@ int dfuse_special_command(struct dfu_if *dif, unsigned int address,
} else if (command == MASS_ERASE) {
buf[0] = 0x41; /* Mass erase command when length = 1 */
length = 1;
+ } else if (command == READ_UNPROTECT) {
+ buf[0] = 0x92;
+ length = 1;
} else {
- fprintf(stderr, "Error: Non-supported special command %d\n",
- command);
- exit(1);
+ errx(EX_IOERR, "Non-supported special command %d", command);
}
buf[1] = address & 0xff;
buf[2] = (address >> 8) & 0xff;
@@ -144,52 +211,80 @@ int dfuse_special_command(struct dfu_if *dif, unsigned int address,
ret = dfuse_download(dif, length, buf, 0);
if (ret < 0) {
- fprintf(stderr, "Error during special command download\n");
- exit(1);
- }
- ret = dfu_get_status(dif->dev_handle, dif->interface, &dst);
- if (ret < 0) {
- fprintf(stderr, "Error during special command get_status\n");
- exit(1);
- }
- if (dst.bState != DFU_STATE_dfuDNBUSY) {
- fprintf(stderr, "Error: Wrong state after command download\n");
- exit(1);
+ errx(EX_IOERR, "Error during special command \"%s\" download",
+ dfuse_command_name[command]);
}
- /* wait while command is executed */
- usleep(dst.bwPollTimeout * 1000);
+ do {
+ ret = dfu_get_status(dif, &dst);
+ if (ret < 0) {
+ errx(EX_IOERR, "Error during special command \"%s\" get_status",
+ dfuse_command_name[command]);
+ }
+ if (firstpoll) {
+ firstpoll = 0;
+ if (dst.bState != DFU_STATE_dfuDNBUSY) {
+ printf("state(%u) = %s, status(%u) = %s\n", dst.bState,
+ dfu_state_to_string(dst.bState), dst.bStatus,
+ dfu_status_to_string(dst.bStatus));
+ errx(EX_IOERR, "Wrong state after command \"%s\" download",
+ dfuse_command_name[command]);
+ }
+ }
+ /* wait while command is executed */
+ if (verbose)
+ printf(" Poll timeout %i ms\n", dst.bwPollTimeout);
+ milli_sleep(dst.bwPollTimeout);
+ if (command == READ_UNPROTECT)
+ return ret;
+ } while (dst.bState == DFU_STATE_dfuDNBUSY);
- ret = dfu_get_status(dif->dev_handle, dif->interface, &dst);
- if (ret < 0) {
- fprintf(stderr, "Error during second get_status\n");
- exit(1);
- }
if (dst.bStatus != DFU_STATUS_OK) {
- fprintf(stderr, "Error: Command not correctly executed\n");
- exit(1);
+ errx(EX_IOERR, "%s not correctly executed",
+ dfuse_command_name[command]);
}
- usleep(dst.bwPollTimeout * 1000);
+ return ret;
+}
- ret = dfu_abort(dif->dev_handle, dif->interface);
- if (ret < 0) {
- fprintf(stderr, "Error sending dfu abort request\n");
- exit(1);
- }
- ret = dfu_get_status(dif->dev_handle, dif->interface, &dst);
+int dfuse_dnload_chunk(struct dfu_if *dif, unsigned char *data, int size,
+ int transaction)
+{
+ int bytes_sent;
+ struct dfu_status dst;
+ int ret;
+
+ ret = dfuse_download(dif, size, size ? data : NULL, transaction);
if (ret < 0) {
- fprintf(stderr, "Error during abort get_status\n");
- exit(1);
+ errx(EX_IOERR, "Error during download");
+ return ret;
}
- if (dst.bState != DFU_STATE_dfuIDLE) {
- fprintf(stderr, "Error: Failed to enter idle state on abort\n");
- exit(1);
+ bytes_sent = ret;
+
+ do {
+ ret = dfu_get_status(dif, &dst);
+ if (ret < 0) {
+ errx(EX_IOERR, "Error during download get_status");
+ return ret;
+ }
+ milli_sleep(dst.bwPollTimeout);
+ } while (dst.bState != DFU_STATE_dfuDNLOAD_IDLE &&
+ dst.bState != DFU_STATE_dfuERROR &&
+ dst.bState != DFU_STATE_dfuMANIFEST);
+
+ if (dst.bState == DFU_STATE_dfuMANIFEST)
+ printf("Transitioning to dfuMANIFEST state\n");
+
+ if (dst.bStatus != DFU_STATUS_OK) {
+ printf(" failed!\n");
+ printf("state(%u) = %s, status(%u) = %s\n", dst.bState,
+ dfu_state_to_string(dst.bState), dst.bStatus,
+ dfu_status_to_string(dst.bStatus));
+ return -1;
}
- usleep(dst.bwPollTimeout * 1000);
- return ret;
+ return bytes_sent;
}
-int dfuse_do_upload(struct dfu_if *dif, int xfer_size, struct dfu_file file,
- unsigned int dfuse_address)
+int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd,
+ const char *dfuse_options)
{
int total_bytes = 0;
int upload_limit = 0;
@@ -197,66 +292,76 @@ int dfuse_do_upload(struct dfu_if *dif, int xfer_size, struct dfu_file file,
int transaction;
int ret;
- buf = malloc(xfer_size);
- if (!buf)
- return -ENOMEM;
+ buf = dfu_malloc(xfer_size);
+ if (dfuse_options)
+ dfuse_parse_options(dfuse_options);
+ if (dfuse_length)
+ upload_limit = dfuse_length;
if (dfuse_address) {
struct memsegment *segment;
mem_layout = parse_memory_layout((char *)dif->alt_name);
- if (!mem_layout) {
- fprintf(stderr,
- "Error: Failed to parse memory layout\n");
- exit(1);
- }
+ if (!mem_layout)
+ errx(EX_IOERR, "Failed to parse memory layout");
+
segment = find_segment(mem_layout, dfuse_address);
- if (!segment || !(segment->memtype & DFUSE_READABLE)) {
- fprintf(stderr,
- "Error: Page at 0x%08x is not readable\n",
+ if (!dfuse_force &&
+ (!segment || !(segment->memtype & DFUSE_READABLE)))
+ errx(EX_IOERR, "Page at 0x%08x is not readable",
dfuse_address);
- exit(1);
+
+ if (!upload_limit) {
+ upload_limit = segment->end - dfuse_address + 1;
+ printf("Limiting upload to end of memory segment, "
+ "%i bytes\n", upload_limit);
}
- upload_limit = segment->end - dfuse_address + 1;
- printf("Limiting upload to end of memory segment, %i bytes\n",
- upload_limit);
dfuse_special_command(dif, dfuse_address, SET_ADDRESS);
+ dfu_abort_to_idle(dif);
} else {
- upload_limit = 0x4000; /* Should be safe for most devices */
+ /* Boot loader decides the start address, unknown to us */
+ /* Use a short length to lower risk of running out of bounds */
+ if (!upload_limit)
+ upload_limit = 0x4000;
printf("Limiting default upload to %i bytes\n", upload_limit);
}
- printf("bytes_per_hash=%u\n", xfer_size);
- printf("Starting upload: [");
- fflush(stdout);
+ dfu_progress_bar("Upload", 0, 1);
transaction = 2;
while (1) {
- int rc, write_rc;
+ int rc;
+
+ /* last chunk can be smaller than original xfer_size */
+ if (upload_limit - total_bytes < xfer_size)
+ xfer_size = upload_limit - total_bytes;
rc = dfuse_upload(dif, xfer_size, buf, transaction++);
if (rc < 0) {
ret = rc;
goto out_free;
}
- write_rc = write(file.fd, buf, rc);
- if (write_rc < rc) {
- fprintf(stderr, "Short file write: %s\n",
- strerror(errno));
- ret = -1;
- goto out_free;
- }
+
+ dfu_file_write_crc(fd, 0, buf, rc);
total_bytes += rc;
+
+ if (total_bytes < 0)
+ errx(EX_SOFTWARE, "Received too many bytes");
+
if (rc < xfer_size || total_bytes >= upload_limit) {
/* last block, return successfully */
ret = total_bytes;
break;
}
- putchar('#');
- fflush(stdout);
+ dfu_progress_bar("Upload", total_bytes, upload_limit);
}
- printf("] finished!\n");
- fflush(stdout);
+ dfu_progress_bar("Upload", total_bytes, total_bytes);
+
+ dfu_abort_to_idle(dif);
+ if (dfuse_leave) {
+ dfuse_special_command(dif, dfuse_address, SET_ADDRESS);
+ dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */
+ }
out_free:
free(buf);
@@ -264,40 +369,6 @@ int dfuse_do_upload(struct dfu_if *dif, int xfer_size, struct dfu_file file,
return ret;
}
-int dfuse_dnload_chunk(struct dfu_if *dif, unsigned char *data, int size,
- int transaction)
-{
- int bytes_sent;
- struct dfu_status dst;
- int ret;
-
- ret = dfuse_download(dif, size, size ? data : NULL, transaction);
- if (ret < 0) {
- fprintf(stderr, "Error during download\n");
- return ret;
- }
- bytes_sent = ret;
-
- do {
- ret = dfu_get_status(dif->dev_handle, dif->interface, &dst);
- if (ret < 0) {
- fprintf(stderr, "Error during download get_status\n");
- return ret;
- }
- usleep(dst.bwPollTimeout * 1000);
- } while (dst.bState != DFU_STATE_dfuDNLOAD_IDLE &&
- dst.bState != DFU_STATE_dfuERROR);
-
- if (dst.bStatus != DFU_STATUS_OK) {
- printf(" failed!\n");
- printf("state(%u) = %s, status(%u) = %s\n", dst.bState,
- dfu_state_to_string(dst.bState), dst.bStatus,
- dfu_status_to_string(dst.bStatus));
- return -1;
- }
- return bytes_sent;
-}
-
/* Writes an element of any size to the device, taking care of page erases */
/* returns 0 on success, otherwise -EINVAL */
int dfuse_dnload_element(struct dfu_if *dif, unsigned int dwElementAddress,
@@ -312,12 +383,13 @@ int dfuse_dnload_element(struct dfu_if *dif, unsigned int dwElementAddress,
segment =
find_segment(mem_layout, dwElementAddress + dwElementSize - 1);
if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) {
- fprintf(stderr, "Error: Last page at 0x%08x is not writeable\n",
+ errx(EX_IOERR, "Last page at 0x%08x is not writeable",
dwElementAddress + dwElementSize - 1);
- exit(1);
}
- for (p = 0; p < dwElementSize; p += xfer_size) {
+ dfu_progress_bar("Download", 0, 1);
+
+ for (p = 0; p < (int)dwElementSize; p += xfer_size) {
int page_size;
unsigned int erase_address;
unsigned int address = dwElementAddress + p;
@@ -325,110 +397,112 @@ int dfuse_dnload_element(struct dfu_if *dif, unsigned int dwElementAddress,
segment = find_segment(mem_layout, address);
if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) {
- fprintf(stderr,
- "Error: Page at 0x%08x is not writeable\n",
+ errx(EX_IOERR, "Page at 0x%08x is not writeable",
address);
- exit(1);
}
page_size = segment->pagesize;
/* check if this is the last chunk */
- if (p + chunk_size > dwElementSize)
+ if (p + chunk_size > (int)dwElementSize)
chunk_size = dwElementSize - p;
/* Erase only for flash memory downloads */
- if (segment->memtype & DFUSE_ERASABLE) {
+ if ((segment->memtype & DFUSE_ERASABLE) && !dfuse_mass_erase) {
/* erase all involved pages */
for (erase_address = address;
erase_address < address + chunk_size;
erase_address += page_size)
if ((erase_address & ~(page_size - 1)) !=
- (last_erased & ~(page_size - 1)))
+ last_erased_page)
dfuse_special_command(dif,
erase_address,
ERASE_PAGE);
if (((address + chunk_size - 1) & ~(page_size - 1)) !=
- (last_erased & ~(page_size - 1))) {
+ last_erased_page) {
if (verbose > 2)
- printf(" Chunk wraps over to next page"
- "\n");
+ printf(" Chunk extends into next page,"
+ " erase it as well\n");
dfuse_special_command(dif,
address + chunk_size - 1,
ERASE_PAGE);
}
}
- if (verbose)
+ if (verbose) {
printf(" Download from image offset "
"%08x to memory %08x-%08x, size %i\n",
p, address, address + chunk_size - 1,
chunk_size);
+ } else {
+ dfu_progress_bar("Download", p, dwElementSize);
+ }
+
dfuse_special_command(dif, address, SET_ADDRESS);
/* transaction = 2 for no address offset */
ret = dfuse_dnload_chunk(dif, data + p, chunk_size, 2);
if (ret != chunk_size) {
- fprintf(stderr, "Failed to write whole chunk: "
- "%i of %i bytes\n", ret, chunk_size);
+ errx(EX_IOERR, "Failed to write whole chunk: "
+ "%i of %i bytes", ret, chunk_size);
return -EINVAL;
}
}
+ if (!verbose)
+ dfu_progress_bar("Download", dwElementSize, dwElementSize);
return 0;
}
+static void
+dfuse_memcpy(unsigned char *dst, unsigned char **src, int *rem, int size)
+{
+ if (size > *rem) {
+ errx(EX_IOERR, "Corrupt DfuSe file: "
+ "Cannot read %d bytes from %d bytes", size, *rem);
+ }
+ if (dst != NULL)
+ memcpy(dst, *src, size);
+ (*src) += size;
+ (*rem) -= size;
+}
+
/* Download raw binary file to DfuSe device */
int dfuse_do_bin_dnload(struct dfu_if *dif, int xfer_size,
- struct dfu_file file, unsigned int start_address)
+ struct dfu_file *file, unsigned int start_address)
{
unsigned int dwElementAddress;
unsigned int dwElementSize;
unsigned char *data;
- int read_bytes = 0;
int ret;
dwElementAddress = start_address;
- dwElementSize = file.size;
- if (verbose)
- printf("Uploading to address = 0x%08x, size = %i\n",
- dwElementAddress, dwElementSize);
-
- data = malloc(dwElementSize);
- if (!data) {
- fprintf(stderr, "Could not allocate data buffer\n");
- return -ENOMEM;
- }
- ret = read(file.fd, data, dwElementSize);
- read_bytes += ret;
- if (ret < dwElementSize) {
- fprintf(stderr, "Could not read data\n");
- ret = -EINVAL;
- goto out_free;
- }
+ dwElementSize = file->size.total -
+ file->size.suffix - file->size.prefix;
+
+ printf("Downloading to address = 0x%08x, size = %i\n",
+ dwElementAddress, dwElementSize);
+
+ data = file->firmware + file->size.prefix;
ret = dfuse_dnload_element(dif, dwElementAddress, dwElementSize, data,
xfer_size);
if (ret != 0)
goto out_free;
- if (read_bytes != file.size) {
- fprintf(stderr, "Warning: Read %i bytes, file size %i\n",
- read_bytes, (int)file.size);
- }
- ret = read_bytes;
+ printf("File downloaded successfully\n");
+ ret = dwElementSize;
out_free:
- free(data);
return ret;
}
/* Parse a DfuSe file and download contents to device */
int dfuse_do_dfuse_dnload(struct dfu_if *dif, int xfer_size,
- struct dfu_file file)
+ struct dfu_file *file)
{
- char dfuprefix[11];
- char targetprefix[274];
- char elementheader[8];
+ uint8_t dfuprefix[11];
+ uint8_t targetprefix[274];
+ uint8_t elementheader[8];
int image;
int element;
int bTargets;
@@ -436,29 +510,28 @@ int dfuse_do_dfuse_dnload(struct dfu_if *dif, int xfer_size,
int dwNbElements;
unsigned int dwElementAddress;
unsigned int dwElementSize;
- unsigned char *data;
- int read_bytes = 0;
+ uint8_t *data;
int ret;
+ int rem;
+ int bFirstAddressSaved = 0;
- /* Must be larger than a minimal DfuSe header and suffix */
- if (file.size <= sizeof(dfuprefix) + file.suffixlen +
- sizeof(targetprefix) + sizeof(elementheader)) {
- fprintf(stderr, "File too small for a DfuSe file\n");
- return -EINVAL;
- }
+ rem = file->size.total - file->size.prefix - file->size.suffix;
+ data = file->firmware + file->size.prefix;
- ret = read(file.fd, dfuprefix, sizeof(dfuprefix));
- if (ret < (int)sizeof(dfuprefix)) {
- fprintf(stderr, "Could not read DfuSe header\n");
- return -EIO;
- }
- read_bytes = ret;
- if (strncmp(dfuprefix, "DfuSe", 5)) {
- fprintf(stderr, "No valid DfuSe signature\n");
+ /* Must be larger than a minimal DfuSe header and suffix */
+ if (rem < (int)(sizeof(dfuprefix) +
+ sizeof(targetprefix) + sizeof(elementheader))) {
+ errx(EX_SOFTWARE, "File too small for a DfuSe file");
+ }
+
+ dfuse_memcpy(dfuprefix, &data, &rem, sizeof(dfuprefix));
+
+ if (strncmp((char *)dfuprefix, "DfuSe", 5)) {
+ errx(EX_IOERR, "No valid DfuSe signature");
return -EINVAL;
}
if (dfuprefix[5] != 0x01) {
- fprintf(stderr, "DFU format revision %i not supported\n",
+ errx(EX_IOERR, "DFU format revision %i not supported",
dfuprefix[5]);
return -EINVAL;
}
@@ -467,14 +540,9 @@ int dfuse_do_dfuse_dnload(struct dfu_if *dif, int xfer_size,
for (image = 1; image <= bTargets; image++) {
printf("parsing DFU image %i\n", image);
- ret = read(file.fd, targetprefix, sizeof(targetprefix));
- read_bytes += ret;
- if (ret < sizeof(targetprefix)) {
- fprintf(stderr, "Could not read DFU header\n");
- return -EIO;
- }
- if (strncmp(targetprefix, "Target", 6)) {
- fprintf(stderr, "No valid target signature\n");
+ dfuse_memcpy(targetprefix, &data, &rem, sizeof(targetprefix));
+ if (strncmp((char *)targetprefix, "Target", 6)) {
+ errx(EX_IOERR, "No valid target signature");
return -EINVAL;
}
bAlternateSetting = targetprefix[6];
@@ -490,14 +558,7 @@ int dfuse_do_dfuse_dnload(struct dfu_if *dif, int xfer_size,
" to download this image!\n");
for (element = 1; element <= dwNbElements; element++) {
printf("parsing element %i, ", element);
- ret =
- read(file.fd, elementheader, sizeof(elementheader));
- read_bytes += ret;
- if (ret < sizeof(elementheader)) {
- fprintf(stderr,
- "Could not read element header\n");
- return -EINVAL;
- }
+ dfuse_memcpy(elementheader, &data, &rem, sizeof(elementheader));
dwElementAddress =
quad2uint((unsigned char *)elementheader);
dwElementSize =
@@ -505,85 +566,87 @@ int dfuse_do_dfuse_dnload(struct dfu_if *dif, int xfer_size,
printf("address = 0x%08x, ", dwElementAddress);
printf("size = %i\n", dwElementSize);
- /* sanity check */
- if (read_bytes + dwElementSize + file.suffixlen >
- file.size) {
- fprintf(stderr,
- "File too small for element size\n");
- return -EINVAL;
- }
- data = malloc(dwElementSize);
- if (!data) {
- fprintf(stderr,
- "Could not allocate data buffer\n");
- return -ENOMEM;
- }
- ret = read(file.fd, data, dwElementSize);
- read_bytes += ret;
- if (ret < dwElementSize) {
- fprintf(stderr, "Could not read data\n");
- free(data);
- return -EIO;
+ if (!bFirstAddressSaved) {
+ bFirstAddressSaved = 1;
+ dfuse_address = dwElementAddress;
}
+ /* sanity check */
+ if ((int)dwElementSize > rem)
+ errx(EX_SOFTWARE, "File too small for element size");
- if (bAlternateSetting == dif->altsetting)
- ret =
- dfuse_dnload_element(dif, dwElementAddress,
- dwElementSize, data,
- xfer_size);
- else
+ if (bAlternateSetting == dif->altsetting) {
+ ret = dfuse_dnload_element(dif, dwElementAddress,
+ dwElementSize, data, xfer_size);
+ } else {
ret = 0;
- free(data);
+ }
+
+ /* advance read pointer */
+ dfuse_memcpy(NULL, &data, &rem, dwElementSize);
+
if (ret != 0)
return ret;
}
}
- /* Just for book-keeping, read through the whole file */
- data = malloc(file.suffixlen);
- if (!data) {
- fprintf(stderr, "Could not allocate data buffer for suffix\n");
- return -ENOMEM;
- }
- ret = read(file.fd, data, file.suffixlen);
- free(data);
- if (ret < file.suffixlen) {
- fprintf(stderr, "Could not read through suffix\n");
- return -EIO;
- }
- read_bytes += ret;
-
- if (read_bytes != file.size) {
- fprintf(stderr, "Warning: Read %i bytes, file size %i\n",
- read_bytes, (int)file.size);
- }
+ if (rem != 0)
+ warnx("%d bytes leftover", rem);
printf("done parsing DfuSe file\n");
- return read_bytes;
+
+ return 0;
}
-int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file file,
- unsigned int address)
+int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file,
+ const char *dfuse_options)
{
+ int ret;
+
+ if (dfuse_options)
+ dfuse_parse_options(dfuse_options);
mem_layout = parse_memory_layout((char *)dif->alt_name);
if (!mem_layout) {
- fprintf(stderr, "Error: Failed to parse memory layout\n");
- exit(1);
+ errx(EX_IOERR, "Failed to parse memory layout");
}
- if (address) {
- if (file.bcdDFU == 0x11a) {
- fprintf(stderr, "Error: This is a DfuSe file, not "
- "meant for raw download\n");
- return -EINVAL;
+ if (dfuse_unprotect) {
+ if (!dfuse_force) {
+ errx(EX_IOERR, "The read unprotect command "
+ "will erase the flash memory"
+ "and can only be used with force\n");
+ }
+ dfuse_special_command(dif, 0, READ_UNPROTECT);
+ printf("Device disconnects, erases flash and resets now\n");
+ exit(0);
+ }
+ if (dfuse_mass_erase) {
+ if (!dfuse_force) {
+ errx(EX_IOERR, "The mass erase command "
+ "can only be used with force");
}
- return dfuse_do_bin_dnload(dif, xfer_size, file, address);
+ printf("Performing mass erase, this can take a moment\n");
+ dfuse_special_command(dif, 0, MASS_ERASE);
+ }
+ if (dfuse_address) {
+ if (file->bcdDFU == 0x11a) {
+ errx(EX_IOERR, "This is a DfuSe file, not "
+ "meant for raw download");
+ }
+ ret = dfuse_do_bin_dnload(dif, xfer_size, file, dfuse_address);
} else {
- if (file.bcdDFU != 0x11a) {
- fprintf(stderr, "Error: Only DfuSe file version 1.1a "
- "is supported\n");
- return -EINVAL;
+ if (file->bcdDFU != 0x11a) {
+ warnx("Only DfuSe file version 1.1a is supported");
+ errx(EX_IOERR, "(for raw binary download, use the "
+ "--dfuse-address option)");
}
- return dfuse_do_dfuse_dnload(dif, xfer_size, file);
+ ret = dfuse_do_dfuse_dnload(dif, xfer_size, file);
}
free_segment_list(mem_layout);
+
+ dfu_abort_to_idle(dif);
+
+ if (dfuse_leave) {
+ dfuse_special_command(dif, dfuse_address, SET_ADDRESS);
+ dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */
+ }
+ return ret;
}
diff --git a/src/dfuse.h b/src/dfuse.h
index 56cbf9f..ed1108c 100644
--- a/src/dfuse.h
+++ b/src/dfuse.h
@@ -1,7 +1,7 @@
/* This implements the ST Microsystems DFU extensions (DfuSe)
* as per the DfuSe 1.1a specification (Document UM0391)
*
- * (C) 2010-2011 Tormod Volden <debian.tormod@gmail.com>
+ * (C) 2010-2012 Tormod Volden <debian.tormod@gmail.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
@@ -18,18 +18,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _DFUSE_H
-#define _DFUSE_H
+#ifndef DFUSE_H
+#define DFUSE_H
-#include <dfu.h>
+#include "dfu.h"
-enum dfuse_command { SET_ADDRESS, ERASE_PAGE, MASS_ERASE };
+enum dfuse_command { SET_ADDRESS, ERASE_PAGE, MASS_ERASE, READ_UNPROTECT };
int dfuse_special_command(struct dfu_if *dif, unsigned int address,
enum dfuse_command command);
-int dfuse_do_upload(struct dfu_if *dif, int xfer_size, struct dfu_file file,
- unsigned int address);
-int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file file,
- unsigned int address);
+int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd,
+ const char *dfuse_options);
+int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file,
+ const char *dfuse_options);
-#endif
+#endif /* DFUSE_H */
diff --git a/src/dfuse_mem.c b/src/dfuse_mem.c
index 379d6fd..a91aacf 100644
--- a/src/dfuse_mem.c
+++ b/src/dfuse_mem.c
@@ -1,7 +1,8 @@
-/* Helper functions for reading the memory map in a device
+/*
+ * Helper functions for reading the memory map of a device
* following the ST DfuSe 1.1a specification.
*
- * (C) 2011 Tormod Volden <debian.tormod@gmail.com>
+ * Copyright 2011-2014 Tormod Volden <debian.tormod@gmail.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
@@ -23,17 +24,15 @@
#include <string.h>
#include <errno.h>
+#include "portable.h"
+#include "dfu_file.h"
#include "dfuse_mem.h"
-extern int verbose;
-
int add_segment(struct memsegment **segment_list, struct memsegment segment)
{
struct memsegment *new_element;
- new_element = malloc(sizeof(struct memsegment));
- if (!new_element)
- return -ENOMEM;
+ new_element = dfu_malloc(sizeof(struct memsegment));
*new_element = segment;
new_element->next = NULL;
@@ -76,6 +75,9 @@ void free_segment_list(struct memsegment *segment_list)
free(segment_list);
}
+/* Parse memory map from interface descriptor string
+ * encoded as per ST document UM0424 section 4.3.2.
+ */
struct memsegment *parse_memory_layout(char *intf_desc)
{
@@ -90,30 +92,19 @@ struct memsegment *parse_memory_layout(char *intf_desc)
struct memsegment *segment_list = NULL;
struct memsegment segment;
-#ifdef DEBUG_DRY
- intf_desc = "@fake /0x08000000/12*001Ka,11*001Kg,9*2Ka,24*4Kg";
-#endif
- name = malloc(strlen(intf_desc));
- if (!name) {
- fprintf(stderr, "Error: Cannot allocate memory\n");
- exit(1);
- }
+ name = dfu_malloc(strlen(intf_desc));
+
ret = sscanf(intf_desc, "@%[^/]%n", name, &scanned);
if (ret < 1) {
- fprintf(stderr, "Error: Could not read name, sscanf returned"
- "%d\n", ret);
free(name);
+ warnx("Could not read name, sscanf returned %d", ret);
return NULL;
}
printf("DfuSe interface name: \"%s\"\n", name);
- free(name);
intf_desc += scanned;
- typestring = malloc(strlen(intf_desc));
- if (!typestring) {
- fprintf(stderr, "Error: Cannot allocate memory\n");
- exit(1);
- }
+ typestring = dfu_malloc(strlen(intf_desc));
+
while (ret = sscanf(intf_desc, "/0x%x/%n", &address, &scanned),
ret > 0) {
@@ -130,14 +121,17 @@ struct memsegment *parse_memory_layout(char *intf_desc)
&& typestring[0] != '/')
memtype = typestring[0];
else {
- fprintf(stderr,
- "Parsing type identifier '%s' "
- "failed for segment %i\n",
+ warnx("Parsing type identifier '%s' "
+ "failed for segment %i",
typestring, count);
continue;
}
}
+ /* Quirk for STM32F4 devices */
+ if (strcmp(name, "Device Feature") == 0)
+ memtype = 'e';
+
switch (multiplier) {
case 'B':
break;
@@ -155,25 +149,21 @@ struct memsegment *parse_memory_layout(char *intf_desc)
case 'f':
case 'g':
if (!memtype) {
- fprintf(stderr,
- "Non-valid multiplier '%c', "
+ warnx("Non-valid multiplier '%c', "
"interpreted as type "
- "identifier instead\n",
+ "identifier instead",
multiplier);
memtype = multiplier;
break;
}
/* fallthrough if memtype was already set */
default:
- fprintf(stderr,
- "Non-valid multiplier '%c', "
- "assuming bytes\n", multiplier);
+ warnx("Non-valid multiplier '%c', "
+ "assuming bytes", multiplier);
}
if (!memtype) {
- fprintf(stderr,
- "No valid type for segment %d\n\n",
- count);
+ warnx("No valid type for segment %d\n", count);
continue;
}
@@ -201,6 +191,7 @@ struct memsegment *parse_memory_layout(char *intf_desc)
} /* while per segment */
} /* while per address */
+ free(name);
free(typestring);
return segment_list;
diff --git a/src/dfuse_mem.h b/src/dfuse_mem.h
index 8765e19..0181f0c 100644
--- a/src/dfuse_mem.h
+++ b/src/dfuse_mem.h
@@ -18,8 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _DFUSE_MEM_H
-#define _DFUSE_MEM_H
+#ifndef DFUSE_MEM_H
+#define DFUSE_MEM_H
#define DFUSE_READABLE 1
#define DFUSE_ERASABLE 2
@@ -41,4 +41,4 @@ void free_segment_list(struct memsegment *list);
struct memsegment *parse_memory_layout(char *intf_desc_str);
-#endif
+#endif /* DFUSE_MEM_H */
diff --git a/src/main.c b/src/main.c
index b3a4cc1..acaed2f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,7 +1,9 @@
/*
* dfu-util
*
- * (C) 2007-2008 by OpenMoko, Inc.
+ * Copyright 2007-2008 by OpenMoko, Inc.
+ * Copyright 2013-2014 Hans Petter Selasky <hps@bitfrost.no>
+ *
* Written by Harald Welte <laforge@openmoko.org>
*
* Based on existing code of dfu-programmer-0.4
@@ -23,544 +25,188 @@
#include <stdlib.h>
#include <stdio.h>
-#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <libusb.h>
#include <errno.h>
#include <fcntl.h>
+#include "portable.h"
#include "dfu.h"
#include "usb_dfu.h"
#include "dfu_file.h"
#include "dfu_load.h"
+#include "dfu_util.h"
#include "dfuse.h"
#include "quirks.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
#ifdef HAVE_USBPATH_H
#include <usbpath.h>
#endif
-/* ugly hack for Win32 */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-int debug;
int verbose = 0;
-/* If we really have to guess (non-compliant devices) */
-#define DEFAULT_TRANSFER_SIZE 1024
-
-/* USB string descriptor should contain max 126 UTF-16 characters
- * but 253 would even accomodate any UTF-8 encoding */
-#define MAX_DESC_STR_LEN 253
-
-/* Find DFU interfaces in a given device.
- * Iterate through all DFU interfaces and their alternate settings
- * and call the passed handler function on each setting until handler
- * returns non-zero. */
-static int find_dfu_if(libusb_device *dev,
- int (*handler)(struct dfu_if *, void *),
- void *v)
+struct dfu_if *dfu_root = NULL;
+
+int match_bus = -1;
+int match_device = -1;
+int match_vendor = -1;
+int match_product = -1;
+int match_vendor_dfu = -1;
+int match_product_dfu = -1;
+int match_config_index = -1;
+int match_iface_index = -1;
+int match_iface_alt_index = -1;
+const char *match_iface_alt_name = NULL;
+const char *match_serial = NULL;
+const char *match_serial_dfu = NULL;
+
+static int parse_match_value(const char *str, int default_value)
{
- struct libusb_device_descriptor desc;
- struct libusb_config_descriptor *cfg;
- const struct libusb_interface_descriptor *intf;
- const struct libusb_interface *uif;
- struct dfu_if _dif, *dfu_if = &_dif;
- int cfg_idx, intf_idx, alt_idx;
- int rc;
-
- memset(dfu_if, 0, sizeof(*dfu_if));
- libusb_get_device_descriptor(dev, &desc);
- for (cfg_idx = 0; cfg_idx < desc.bNumConfigurations;
- cfg_idx++) {
- libusb_get_config_descriptor(dev, cfg_idx, &cfg);
- /* in some cases, noticably FreeBSD if uid != 0,
- * the configuration descriptors are empty */
- if (!cfg)
- return 0;
- for (intf_idx = 0; intf_idx < cfg->bNumInterfaces;
- intf_idx++) {
- uif = &cfg->interface[intf_idx];
- if (!uif)
- return 0;
- for (alt_idx = 0;
- alt_idx < uif->num_altsetting; alt_idx++) {
- intf = &uif->altsetting[alt_idx];
- if (!intf)
- return 0;
- if (intf->bInterfaceClass == 0xfe &&
- intf->bInterfaceSubClass == 1) {
- dfu_if->dev = dev;
- dfu_if->vendor =
- desc.idVendor;
- dfu_if->product =
- desc.idProduct;
- dfu_if->configuration = cfg->
- bConfigurationValue;
- dfu_if->interface =
- intf->bInterfaceNumber;
- dfu_if->altsetting =
- intf->bAlternateSetting;
- if (intf->bInterfaceProtocol == 2)
- dfu_if->flags |= DFU_IFF_DFU;
- else
- dfu_if->flags &= ~DFU_IFF_DFU;
- if (!handler)
- return 1;
- rc = handler(dfu_if, v);
- if (rc != 0)
- return rc;
- }
- }
+ char *remainder;
+ int value;
+
+ if (str == NULL) {
+ value = default_value;
+ } else if (*str == '*') {
+ value = -1; /* Match anything */
+ } else if (*str == '-') {
+ value = 0x10000; /* Impossible vendor/product ID */
+ } else {
+ value = strtoul(str, &remainder, 16);
+ if (remainder == str) {
+ value = default_value;
}
-
- libusb_free_config_descriptor(cfg);
- }
-
- return 0;
-}
-
-static int _get_first_cb(struct dfu_if *dif, void *v)
-{
- struct dfu_if *v_dif = v;
-
- /* Copy everything except the device handle.
- * This depends heavily on this member being last! */
- memcpy(v_dif, dif, sizeof(*v_dif)-sizeof(libusb_device_handle *));
-
- /* return a value that makes find_dfu_if return immediately */
- return 1;
-}
-
-/* Fills in dif with the first found DFU interface */
-static int get_first_dfu_if(struct dfu_if *dif)
-{
- return find_dfu_if(dif->dev, &_get_first_cb, (void *) dif);
-}
-
-static int _check_match_cb(struct dfu_if *dif, void *v)
-{
- struct dfu_if *v_dif = v;
-
- if (v_dif->flags & DFU_IFF_IFACE &&
- dif->interface != v_dif->interface)
- return 0;
- if (v_dif->flags & DFU_IFF_ALT &&
- dif->altsetting != v_dif->altsetting)
- return 0;
- return _get_first_cb(dif, v);
-}
-
-/* Fills in dif from the matching DFU interface/altsetting */
-static int get_matching_dfu_if(struct dfu_if *dif)
-{
- return find_dfu_if(dif->dev, &_check_match_cb, (void *) dif);
-}
-
-static int _count_match_cb(struct dfu_if *dif, void *v)
-{
- struct dfu_if *v_dif = v;
-
- if (v_dif->flags & DFU_IFF_IFACE &&
- dif->interface != v_dif->interface)
- return 0;
- if (v_dif->flags & DFU_IFF_ALT &&
- dif->altsetting != v_dif->altsetting)
- return 0;
- v_dif->count++;
- return 0;
-}
-
-/* Count matching DFU interface/altsetting */
-static int count_matching_dfu_if(struct dfu_if *dif)
-{
- dif->count = 0;
- find_dfu_if(dif->dev, &_count_match_cb, (void *) dif);
- return dif->count;
-}
-
-/* Retrieves alternate interface name string.
- * Returns string length, or negative on error */
-static int get_alt_name(struct dfu_if *dfu_if, unsigned char *name)
-{
- libusb_device *dev = dfu_if->dev;
- struct libusb_config_descriptor *cfg;
- int alt_name_str_idx;
- int ret;
-
- ret = libusb_get_config_descriptor_by_value(dev, dfu_if->configuration,
- &cfg);
- if (ret)
- return ret;
-
- alt_name_str_idx = cfg->interface[dfu_if->interface].
- altsetting[dfu_if->altsetting].iInterface;
- ret = -1;
- if (alt_name_str_idx) {
- if (!dfu_if->dev_handle)
- libusb_open(dfu_if->dev, &dfu_if->dev_handle);
- if (dfu_if->dev_handle)
- ret = libusb_get_string_descriptor_ascii(
- dfu_if->dev_handle, alt_name_str_idx,
- name, MAX_DESC_STR_LEN);
}
- libusb_free_config_descriptor(cfg);
- return ret;
-}
-
-static int print_dfu_if(struct dfu_if *dfu_if, void *v)
-{
- unsigned char name[MAX_DESC_STR_LEN+1] = "UNDEFINED";
-
- get_alt_name(dfu_if, name);
-
- printf("Found %s: [%04x:%04x] devnum=%u, cfg=%u, intf=%u, "
- "alt=%u, name=\"%s\"\n",
- dfu_if->flags & DFU_IFF_DFU ? "DFU" : "Runtime",
- dfu_if->vendor, dfu_if->product, dfu_if->devnum,
- dfu_if->configuration, dfu_if->interface,
- dfu_if->altsetting, name);
- return 0;
+ return value;
}
-/* Walk the device tree and print out DFU devices */
-static int list_dfu_interfaces(libusb_context *ctx)
+static void parse_vendprod(const char *str)
{
- libusb_device **list;
- libusb_device *dev;
- ssize_t num_devs, i;
-
- num_devs = libusb_get_device_list(ctx, &list);
+ const char *comma;
+ const char *colon;
- for (i = 0; i < num_devs; ++i) {
- dev = list[i];
- find_dfu_if(dev, &print_dfu_if, NULL);
+ /* Default to match any DFU device in runtime or DFU mode */
+ match_vendor = -1;
+ match_product = -1;
+ match_vendor_dfu = -1;
+ match_product_dfu = -1;
+
+ comma = strchr(str, ',');
+ if (comma == str) {
+ /* DFU mode vendor/product being specified without any runtime
+ * vendor/product specification, so don't match any runtime device */
+ match_vendor = match_product = 0x10000;
+ } else {
+ colon = strchr(str, ':');
+ if (colon != NULL) {
+ ++colon;
+ if ((comma != NULL) && (colon > comma)) {
+ colon = NULL;
+ }
+ }
+ match_vendor = parse_match_value(str, match_vendor);
+ match_product = parse_match_value(colon, match_product);
+ if (comma != NULL) {
+ /* Both runtime and DFU mode vendor/product specifications are
+ * available, so default DFU mode match components to the given
+ * runtime match components */
+ match_vendor_dfu = match_vendor;
+ match_product_dfu = match_product;
+ }
}
-
- libusb_free_device_list(list, 1);
- return 0;
-}
-
-static int alt_by_name(struct dfu_if *dfu_if, void *v)
-{
- unsigned char name[MAX_DESC_STR_LEN+1];
-
- if (get_alt_name(dfu_if, name) < 0)
- return 0;
- if (strcmp((char *)name, v))
- return 0;
- /*
- * Return altsetting+1 so that we can use return value 0 to indicate
- * "not found".
- */
- return dfu_if->altsetting+1;
-}
-
-static int _count_cb(struct dfu_if *dif, void *v)
-{
- int *count = v;
-
- (*count)++;
-
- return 0;
-}
-
-/* Count DFU interfaces within a single device */
-static int count_dfu_interfaces(libusb_device *dev)
-{
- int num_found = 0;
-
- find_dfu_if(dev, &_count_cb, (void *) &num_found);
-
- return num_found;
-}
-
-
-/* Iterate over all matching DFU capable devices within system */
-static int iterate_dfu_devices(libusb_context *ctx, struct dfu_if *dif,
- int (*action)(struct libusb_device *dev, void *user), void *user)
-{
- libusb_device **list;
- ssize_t num_devs, i;
-
- num_devs = libusb_get_device_list(ctx, &list);
- for (i = 0; i < num_devs; ++i) {
- int retval;
- struct libusb_device_descriptor desc;
- struct libusb_device *dev = list[i];
-
- if (dif && (dif->flags & DFU_IFF_DEVNUM) &&
- (libusb_get_bus_number(dev) != dif->bus ||
- libusb_get_device_address(dev) != dif->devnum))
- continue;
- libusb_get_device_descriptor(dev, &desc);
- if (dif && (dif->flags & DFU_IFF_VENDOR) &&
- desc.idVendor != dif->vendor)
- continue;
- if (dif && (dif->flags & DFU_IFF_PRODUCT) &&
- desc.idProduct != dif->product)
- continue;
- if (!count_dfu_interfaces(dev))
- continue;
-
- retval = action(dev, user);
- if (retval) {
- libusb_free_device_list(list, 0);
- return retval;
+ if (comma != NULL) {
+ ++comma;
+ colon = strchr(comma, ':');
+ if (colon != NULL) {
+ ++colon;
}
+ match_vendor_dfu = parse_match_value(comma, match_vendor_dfu);
+ match_product_dfu = parse_match_value(colon, match_product_dfu);
}
- libusb_free_device_list(list, 0);
- return 0;
}
-
-static int found_dfu_device(struct libusb_device *dev, void *user)
+static void parse_serial(char *str)
{
- struct dfu_if *dif = user;
-
- dif->dev = dev;
- return 1;
-}
+ char *comma;
-
-/* Find the first DFU-capable device, save it in dfu_if->dev */
-static int get_first_dfu_device(libusb_context *ctx, struct dfu_if *dif)
-{
- return iterate_dfu_devices(ctx, dif, found_dfu_device, dif);
-}
-
-
-static int count_one_dfu_device(struct libusb_device *dev, void *user)
-{
- int *num = user;
-
- (*num)++;
- return 0;
-}
-
-
-/* Count DFU capable devices within system */
-static int count_dfu_devices(libusb_context *ctx, struct dfu_if *dif)
-{
- int num_found = 0;
-
- iterate_dfu_devices(ctx, dif, count_one_dfu_device, &num_found);
- return num_found;
-}
-
-
-static void parse_vendprod(u_int16_t *vendor, u_int16_t *product,
- const char *str)
-{
- const char *colon;
-
- *vendor = strtoul(str, NULL, 16);
- colon = strchr(str, ':');
- if (colon)
- *product = strtoul(colon + 1, NULL, 16);
- else
- *product = 0;
+ match_serial = str;
+ comma = strchr(str, ',');
+ if (comma == NULL) {
+ match_serial_dfu = match_serial;
+ } else {
+ *comma++ = 0;
+ match_serial_dfu = comma;
+ }
+ if (*match_serial == 0) match_serial = NULL;
+ if (*match_serial_dfu == 0) match_serial_dfu = NULL;
}
-
#ifdef HAVE_USBPATH_H
-static int resolve_device_path(struct dfu_if *dif)
+static int resolve_device_path(char *path)
{
int res;
- res = usb_path2devnum(dif->path);
+ res = usb_path2devnum(path);
if (res < 0)
return -EINVAL;
if (!res)
return 0;
- dif->bus = atoi(dif->path);
- dif->devnum = res;
- dif->flags |= DFU_IFF_DEVNUM;
- return res;
+ match_bus = atoi(path);
+ match_device = res;
+
+ return 0;
}
#else /* HAVE_USBPATH_H */
-static int resolve_device_path(struct dfu_if *dif)
+static int resolve_device_path(char *path)
{
- fprintf(stderr,
- "USB device paths are not supported by this dfu-util.\n");
- exit(1);
+ (void)path; /* Eliminate unused variable warning */
+ errx(EX_SOFTWARE, "USB device paths are not supported by this dfu-util.\n");
}
#endif /* !HAVE_USBPATH_H */
-/* Look for a descriptor in a concatenated descriptor list
- * Will return desc_index'th match of given descriptor type
- * Returns length of found descriptor, limited to res_size */
-static int find_descriptor(const unsigned char *desc_list, int list_len,
- uint8_t desc_type, uint8_t desc_index,
- uint8_t *res_buf, int res_size)
-{
- int p = 0;
- int hit = 0;
-
- while (p + 1 < list_len) {
- int desclen;
-
- desclen = (int) desc_list[p];
- if (desclen == 0) {
- fprintf(stderr, "Error: Invalid descriptor list\n");
- return -1;
- }
- if (desc_list[p + 1] == desc_type && hit++ == desc_index) {
- if (desclen > res_size)
- desclen = res_size;
- if (p + desclen > list_len)
- desclen = list_len - p;
- memcpy(res_buf, &desc_list[p], desclen);
- return desclen;
- }
- p += (int) desc_list[p];
- }
- return 0;
-}
-
-/* Look for a descriptor in the active configuration
- * Will also find extra descriptors which are normally
- * not returned by the standard libusb_get_descriptor() */
-static int usb_get_any_descriptor(struct libusb_device_handle *dev_handle,
- uint8_t desc_type,
- uint8_t desc_index,
- unsigned char *resbuf, int res_len)
-{
- struct libusb_device *dev = libusb_get_device(dev_handle);
- struct libusb_config_descriptor *config;
- int ret;
- uint16_t conflen;
- unsigned char *cbuf;
-
- /* Get the total length of the configuration descriptors */
- ret = libusb_get_active_config_descriptor(dev, &config);
- if (ret == LIBUSB_ERROR_NOT_FOUND) {
- fprintf(stderr, "Error: Device is unconfigured\n");
- return -1;
- } else if (ret) {
- fprintf(stderr, "Error: failed "
- "libusb_get_active_config_descriptor()\n");
- exit(1);
- }
- conflen = config->wTotalLength;
- libusb_free_config_descriptor(config);
-
- /* Suck in the configuration descriptor list from device */
- cbuf = malloc(conflen);
- ret = libusb_get_descriptor(dev_handle, LIBUSB_DT_CONFIG,
- desc_index, cbuf, conflen);
- if (ret < conflen) {
- fprintf(stderr, "Warning: failed to retrieve complete "
- "configuration descriptor, got %i/%i\n",
- ret, conflen);
- conflen = ret;
- }
- /* Search through the configuration descriptor list */
- ret = find_descriptor(cbuf, conflen, desc_type, desc_index,
- resbuf, res_len);
- free(cbuf);
-
- /* A descriptor must be at least 2 bytes long */
- if (ret > 1) {
- if (verbose)
- printf("Found descriptor in complete configuration "
- "descriptor list\n");
- return ret;
- }
-
- /* Finally try to retrieve it requesting the device directly
- * This is not supported on all devices for non-standard types */
- return libusb_get_descriptor(dev_handle, desc_type, desc_index,
- resbuf, res_len);
-}
-
-/* Get cached extra descriptor from libusb for an interface
- * Returns length of found descriptor */
-static int get_cached_extra_descriptor(struct libusb_device *dev,
- uint8_t bConfValue,
- uint8_t intf,
- uint8_t desc_type, uint8_t desc_index,
- unsigned char *resbuf, int res_len)
-{
- struct libusb_config_descriptor *cfg;
- const unsigned char *extra;
- int extra_len;
- int ret;
- int alt;
-
- ret = libusb_get_config_descriptor_by_value(dev, bConfValue, &cfg);
- if (ret == LIBUSB_ERROR_NOT_FOUND) {
- fprintf(stderr, "Error: Device is unconfigured\n");
- return -1;
- } else if (ret) {
- fprintf(stderr, "Error: failed "
- "libusb_config_descriptor_by_value()\n");
- exit(1);
- }
-
- /* Extra descriptors can be shared between alternate settings but
- * libusb may attach them to one setting. Therefore go through all.
- * Note that desc_index is per alternate setting, hits will not be
- * counted from one to another */
- for (alt = 0; alt < cfg->interface[intf].num_altsetting;
- alt++) {
- extra = cfg->interface[intf].altsetting[alt].extra;
- extra_len = cfg->interface[intf].altsetting[alt].extra_length;
- if (extra_len > 1)
- ret = find_descriptor(extra, extra_len, desc_type,
- desc_index, resbuf, res_len);
- if (ret > 1)
- break;
- }
- libusb_free_config_descriptor(cfg);
- if (ret < 2 && verbose)
- printf("Did not find cached descriptor\n");
- return ret;
-}
-
static void help(void)
{
- printf("Usage: dfu-util [options] ...\n"
+ fprintf(stderr, "Usage: dfu-util [options] ...\n"
" -h --help\t\t\tPrint this help message\n"
" -V --version\t\t\tPrint the version number\n"
" -v --verbose\t\t\tPrint verbose debug statements\n"
- " -l --list\t\t\tList the currently attached DFU capable USB devices\n"
- " -d --device vendor:product\tSpecify Vendor/Product ID of DFU device\n"
- " -p --path bus-port. ... .port\tSpecify path to DFU device\n"
- " -c --cfg config_nr\t\tSpecify the Configuration of DFU device\n"
- " -i --intf intf_nr\t\tSpecify the DFU Interface number\n"
- " -a --alt alt\t\t\tSpecify the Altsetting of the DFU Interface\n"
- "\t\t\t\tby name or by number\n"
- " -t --transfer-size\t\tSpecify the number of bytes per USB Transfer\n"
- " -U --upload file\t\tRead firmware from device into <file>\n"
- " -D --download file\t\tWrite firmware from <file> into device\n"
+ " -l --list\t\t\tList currently attached DFU capable devices\n");
+ fprintf(stderr, " -e --detach\t\t\tDetach currently attached DFU capable devices\n"
+ " -E --detach-delay seconds\tTime to wait before reopening a device after detach\n"
+ " -d --device <vendor>:<product>[,<vendor_dfu>:<product_dfu>]\n"
+ "\t\t\t\tSpecify Vendor/Product ID(s) of DFU device\n"
+ " -p --path <bus-port. ... .port>\tSpecify path to DFU device\n"
+ " -c --cfg <config_nr>\t\tSpecify the Configuration of DFU device\n"
+ " -i --intf <intf_nr>\t\tSpecify the DFU Interface number\n"
+ " -S --serial <serial_string>[,<serial_string_dfu>]\n"
+ "\t\t\t\tSpecify Serial String of DFU device\n"
+ " -a --alt <alt>\t\tSpecify the Altsetting of the DFU Interface\n"
+ "\t\t\t\tby name or by number\n");
+ fprintf(stderr, " -t --transfer-size <size>\tSpecify the number of bytes per USB Transfer\n"
+ " -U --upload <file>\t\tRead firmware from device into <file>\n"
+ " -Z --upload-size <bytes>\tSpecify the expected upload size in bytes\n"
+ " -D --download <file>\t\tWrite firmware from <file> into device\n"
" -R --reset\t\t\tIssue USB Reset signalling once we're finished\n"
- " -s --dfuse-address address\tST DfuSe mode, specify target address for\n"
+ " -s --dfuse-address <address>\tST DfuSe mode, specify target address for\n"
"\t\t\t\traw file download or upload. Not applicable for\n"
"\t\t\t\tDfuSe file (.dfu) downloads\n"
);
+ exit(EX_USAGE);
}
static void print_version(void)
{
- printf("dfu-util %s\n\n", VERSION);
- printf("(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc.\n"
- "(C) 2010-2011 Tormod Volden (DfuSe support)\n"
- "This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n");
-
- printf("dfu-util does currently only support DFU version 1.0\n\n");
-
+ printf(PACKAGE_STRING "\n\n");
+ printf("Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.\n"
+ "Copyright 2010-2014 Tormod Volden and Stefan Schmidt\n"
+ "This program is Free Software and has ABSOLUTELY NO WARRANTY\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n\n");
}
static struct option opts[] = {
@@ -568,6 +214,8 @@ static struct option opts[] = {
{ "version", 0, 0, 'V' },
{ "verbose", 0, 0, 'v' },
{ "list", 0, 0, 'l' },
+ { "detach", 0, 0, 'e' },
+ { "detach-delay", 1, 0, 'E' },
{ "device", 1, 0, 'd' },
{ "path", 1, 0, 'p' },
{ "configuration", 1, 0, 'c' },
@@ -576,49 +224,42 @@ static struct option opts[] = {
{ "intf", 1, 0, 'i' },
{ "altsetting", 1, 0, 'a' },
{ "alt", 1, 0, 'a' },
+ { "serial", 1, 0, 'S' },
{ "transfer-size", 1, 0, 't' },
{ "upload", 1, 0, 'U' },
+ { "upload-size", 1, 0, 'Z' },
{ "download", 1, 0, 'D' },
{ "reset", 0, 0, 'R' },
{ "dfuse-address", 1, 0, 's' },
-};
-
-enum mode {
- MODE_NONE,
- MODE_VERSION,
- MODE_LIST,
- MODE_UPLOAD,
- MODE_DOWNLOAD,
+ { 0, 0, 0, 0 }
};
int main(int argc, char **argv)
{
- struct dfu_if _rt_dif, _dif, *dif = &_dif;
- int num_devs;
- int num_ifs;
+ int expected_size = 0;
unsigned int transfer_size = 0;
- unsigned int host_page_size;
enum mode mode = MODE_NONE;
struct dfu_status status;
- struct usb_dfu_func_descriptor func_dfu = {0}, func_dfu_rt = {0};
libusb_context *ctx;
struct dfu_file file;
- char *alt_name = NULL; /* query alt name if non-NULL */
- char *device_id_filter = NULL;
- unsigned char active_alt_name[MAX_DESC_STR_LEN+1];
char *end;
int final_reset = 0;
int ret;
- int dfuse = 0;
- unsigned int dfuse_address = 0; /* FIXME allow address to be zero? */
+ int dfuse_device = 0;
+ int fd;
+ const char *dfuse_options = NULL;
+ int detach_delay = 5;
+ uint16_t runtime_vendor;
+ uint16_t runtime_product;
+
+ memset(&file, 0, sizeof(file));
- host_page_size = getpagesize();
- memset(dif, 0, sizeof(*dif));
- file.name = NULL;
+ /* make sure all prints are flushed */
+ setvbuf(stdout, NULL, _IONBF, 0);
while (1) {
int c, option_index = 0;
- c = getopt_long(argc, argv, "hVvld:p:c:i:a:t:U:D:Rs:", opts,
+ c = getopt_long(argc, argv, "hVvleE:d:p:c:i:a:S:t:U:D:Rs:Z:", opts,
&option_index);
if (c == -1)
break;
@@ -626,7 +267,6 @@ int main(int argc, char **argv)
switch (c) {
case 'h':
help();
- exit(0);
break;
case 'V':
mode = MODE_VERSION;
@@ -637,40 +277,43 @@ int main(int argc, char **argv)
case 'l':
mode = MODE_LIST;
break;
+ case 'e':
+ mode = MODE_DETACH;
+ match_iface_alt_index = 0;
+ match_iface_index = 0;
+ break;
+ case 'E':
+ detach_delay = atoi(optarg);
+ break;
case 'd':
- device_id_filter = optarg;
+ parse_vendprod(optarg);
break;
case 'p':
/* Parse device path */
- dif->path = optarg;
- dif->flags |= DFU_IFF_PATH;
- ret = resolve_device_path(dif);
- if (ret < 0) {
- fprintf(stderr, "unable to parse `%s'\n",
- optarg);
- exit(2);
- }
- if (!ret) {
- fprintf(stderr, "cannot find `%s'\n", optarg);
- exit(1);
- }
+ ret = resolve_device_path(optarg);
+ if (ret < 0)
+ errx(EX_SOFTWARE, "Unable to parse '%s'", optarg);
+ if (!ret)
+ errx(EX_SOFTWARE, "Cannot find '%s'", optarg);
break;
case 'c':
/* Configuration */
- dif->configuration = atoi(optarg);
- dif->flags |= DFU_IFF_CONFIG;
+ match_config_index = atoi(optarg);
break;
case 'i':
/* Interface */
- dif->interface = atoi(optarg);
- dif->flags |= DFU_IFF_IFACE;
+ match_iface_index = atoi(optarg);
break;
case 'a':
/* Interface Alternate Setting */
- dif->altsetting = strtoul(optarg, &end, 0);
- if (*end)
- alt_name = optarg;
- dif->flags |= DFU_IFF_ALT;
+ match_iface_alt_index = strtoul(optarg, &end, 0);
+ if (*end) {
+ match_iface_alt_name = optarg;
+ match_iface_alt_index = -1;
+ }
+ break;
+ case 'S':
+ parse_serial(optarg);
break;
case 't':
transfer_size = atoi(optarg);
@@ -679,6 +322,9 @@ int main(int argc, char **argv)
mode = MODE_UPLOAD;
file.name = optarg;
break;
+ case 'Z':
+ expected_size = atoi(optarg);
+ break;
case 'D':
mode = MODE_DOWNLOAD;
file.name = optarg;
@@ -687,19 +333,11 @@ int main(int argc, char **argv)
final_reset = 1;
break;
case 's':
- dfuse = 1;
- if (strcmp(optarg, "default")) {
- dfuse_address = strtoul(optarg, &end, 0);
- if (!dfuse_address || (*end)) {
- fprintf(stderr, "invalid dfuse address: %s\n",
- optarg);
- exit(2);
- }
- }
+ dfuse_options = optarg;
break;
default:
help();
- exit(2);
+ break;
}
}
@@ -709,448 +347,353 @@ int main(int argc, char **argv)
}
if (mode == MODE_NONE) {
- fprintf(stderr, "Error: You need to specify one of -D or -U\n\n");
+ fprintf(stderr, "You need to specify one of -D or -U\n");
help();
- exit(2);
}
- if (device_id_filter) {
- /* Parse device ID */
- parse_vendprod(&dif->vendor, &dif->product, device_id_filter);
- printf("Filter on vendor = 0x%04x product = 0x%04x\n",
- dif->vendor, dif->product);
- if (dif->vendor)
- dif->flags |= DFU_IFF_VENDOR;
- if (dif->product)
- dif->flags |= DFU_IFF_PRODUCT;
+ if (match_config_index == 0) {
+ /* Handle "-c 0" (unconfigured device) as don't care */
+ match_config_index = -1;
}
- ret = libusb_init(&ctx);
- if (ret) {
- fprintf(stderr, "unable to initialize libusb: %i\n", ret);
- return EXIT_FAILURE;
+ if (mode == MODE_DOWNLOAD) {
+ dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX);
+ /* If the user didn't specify product and/or vendor IDs to match,
+ * use any IDs from the file suffix for device matching */
+ if (match_vendor < 0 && file.idVendor != 0xffff) {
+ match_vendor = file.idVendor;
+ printf("Match vendor ID from file: %04x\n", match_vendor);
+ }
+ if (match_product < 0 && file.idProduct != 0xffff) {
+ match_product = file.idProduct;
+ printf("Match product ID from file: %04x\n", match_product);
+ }
}
- if (verbose > 1) {
+ ret = libusb_init(&ctx);
+ if (ret)
+ errx(EX_IOERR, "unable to initialize libusb: %i", ret);
+
+ if (verbose > 2) {
libusb_set_debug(ctx, 255);
}
+ probe_devices(ctx);
+
if (mode == MODE_LIST) {
- list_dfu_interfaces(ctx);
+ list_dfu_interfaces();
exit(0);
}
- dfu_init(5000);
-
- num_devs = count_dfu_devices(ctx, dif);
- if (num_devs == 0) {
- fprintf(stderr, "No DFU capable USB device found\n");
- exit(1);
- } else if (num_devs > 1) {
+ if (dfu_root == NULL) {
+ errx(EX_IOERR, "No DFU capable USB device available");
+ } else if (dfu_root->next != NULL) {
/* We cannot safely support more than one DFU capable device
* with same vendor/product ID, since during DFU we need to do
* a USB bus reset, after which the target device will get a
* new address */
- fprintf(stderr, "More than one DFU capable USB device found, "
- "you might try `--list' and then disconnect all but one "
- "device\n");
- exit(3);
+ errx(EX_IOERR, "More than one DFU capable USB device found! "
+ "Try `--list' and specify the serial number "
+ "or disconnect all but one device\n");
}
- if (!get_first_dfu_device(ctx, dif))
- exit(3);
- /* We have exactly one device. Its libusb_device is now in dif->dev */
+ /* We have exactly one device. Its libusb_device is now in dfu_root->dev */
- printf("Opening DFU USB device... ");
- libusb_open(dif->dev, &dif->dev_handle);
- if (!dif->dev_handle) {
- fprintf(stderr, "Cannot open device \n");
- exit(1);
- }
+ printf("Opening DFU capable USB device...\n");
+ ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle);
+ if (ret || !dfu_root->dev_handle)
+ errx(EX_IOERR, "Cannot open device");
+
+ printf("ID %04x:%04x\n", dfu_root->vendor, dfu_root->product);
- /* try to find first DFU interface of device */
- memcpy(&_rt_dif, dif, sizeof(_rt_dif));
- if (!get_first_dfu_if(&_rt_dif))
- exit(1);
-
- printf("ID %04x:%04x\n", _rt_dif.vendor, _rt_dif.product);
-
- /* find set of quirks for this device */
- set_quirks(_rt_dif.vendor, _rt_dif.product);
-
- /* Obtain run-time DFU functional descriptor without asking device
- * E.g. Freerunner does not like to be requested at this point */
- ret = get_cached_extra_descriptor(_rt_dif.dev, _rt_dif.configuration,
- _rt_dif.interface, USB_DT_DFU, 0,
- (unsigned char *) &func_dfu_rt,
- sizeof(func_dfu_rt));
- if (ret == 7) {
- /* DFU 1.0 does not have this field */
- printf("Deducing device DFU version from functional descriptor "
- "length\n");
- func_dfu_rt.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
- } else if (ret < 9) {
- fprintf(stderr, "WARNING: Can not find cached DFU functional "
- "descriptor\n");
- printf("Warning: Assuming DFU version 1.0\n");
- func_dfu_rt.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
- }
printf("Run-time device DFU version %04x\n",
- libusb_le16_to_cpu(func_dfu_rt.bcdDFUVersion));
+ libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion));
/* Transition from run-Time mode to DFU mode */
- if (!(_rt_dif.flags & DFU_IFF_DFU)) {
+ if (!(dfu_root->flags & DFU_IFF_DFU)) {
+ int err;
/* In the 'first round' during runtime mode, there can only be one
* DFU Interface descriptor according to the DFU Spec. */
/* FIXME: check if the selected device really has only one */
+ runtime_vendor = dfu_root->vendor;
+ runtime_product = dfu_root->product;
+
printf("Claiming USB DFU Runtime Interface...\n");
- if (libusb_claim_interface(_rt_dif.dev_handle, _rt_dif.interface) < 0) {
- fprintf(stderr, "Cannot claim interface %d\n",
- _rt_dif.interface);
- exit(1);
+ if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) {
+ errx(EX_IOERR, "Cannot claim interface %d",
+ dfu_root->interface);
}
- if (libusb_set_interface_alt_setting(_rt_dif.dev_handle, _rt_dif.interface, 0) < 0) {
- fprintf(stderr, "Cannot set alt interface\n");
- exit(1);
+ if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, 0) < 0) {
+ errx(EX_IOERR, "Cannot set alt interface zero");
}
printf("Determining device status: ");
- if (dfu_get_status(_rt_dif.dev_handle, _rt_dif.interface, &status ) < 0) {
- fprintf(stderr, "error get_status\n");
- exit(1);
+
+ err = dfu_get_status(dfu_root, &status);
+ if (err == LIBUSB_ERROR_PIPE) {
+ printf("Device does not implement get_status, assuming appIDLE\n");
+ status.bStatus = DFU_STATUS_OK;
+ status.bwPollTimeout = 0;
+ status.bState = DFU_STATE_appIDLE;
+ status.iString = 0;
+ } else if (err < 0) {
+ errx(EX_IOERR, "error get_status");
+ } else {
+ printf("state = %s, status = %d\n",
+ dfu_state_to_string(status.bState), status.bStatus);
}
- printf("state = %s, status = %d\n",
- dfu_state_to_string(status.bState), status.bStatus);
- if (!(quirks & QUIRK_POLLTIMEOUT))
- usleep(status.bwPollTimeout * 1000);
+ milli_sleep(status.bwPollTimeout);
switch (status.bState) {
case DFU_STATE_appIDLE:
case DFU_STATE_appDETACH:
printf("Device really in Runtime Mode, send DFU "
"detach request...\n");
- if (dfu_detach(_rt_dif.dev_handle,
- _rt_dif.interface, 1000) < 0) {
- fprintf(stderr, "error detaching\n");
- exit(1);
- break;
+ if (dfu_detach(dfu_root->dev_handle,
+ dfu_root->interface, 1000) < 0) {
+ warnx("error detaching");
}
- libusb_release_interface(_rt_dif.dev_handle,
- _rt_dif.interface);
- if (func_dfu_rt.bmAttributes & USB_DFU_WILL_DETACH) {
+ if (dfu_root->func_dfu.bmAttributes & USB_DFU_WILL_DETACH) {
printf("Device will detach and reattach...\n");
} else {
printf("Resetting USB...\n");
- ret = libusb_reset_device(_rt_dif.dev_handle);
+ ret = libusb_reset_device(dfu_root->dev_handle);
if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND)
- fprintf(stderr, "error resetting "
- "after detach\n");
+ errx(EX_IOERR, "error resetting "
+ "after detach");
}
- sleep(2);
break;
case DFU_STATE_dfuERROR:
printf("dfuERROR, clearing status\n");
- if (dfu_clear_status(_rt_dif.dev_handle,
- _rt_dif.interface) < 0) {
- fprintf(stderr, "error clear_status\n");
- exit(1);
- break;
+ if (dfu_clear_status(dfu_root->dev_handle,
+ dfu_root->interface) < 0) {
+ errx(EX_IOERR, "error clear_status");
}
- break;
+ /* fall through */
default:
- fprintf(stderr, "WARNING: Runtime device already "
- "in DFU state ?!?\n");
+ warnx("WARNING: Runtime device already in DFU state ?!?");
+ libusb_release_interface(dfu_root->dev_handle,
+ dfu_root->interface);
goto dfustate;
- break;
}
- libusb_release_interface(_rt_dif.dev_handle,
- _rt_dif.interface);
- libusb_close(_rt_dif.dev_handle);
-
- /* now we need to re-scan the bus and locate our device */
-// if (usb_find_devices() < 2)
-// printf("not at least 2 device changes found ?!?\n");
-
- if (dif->flags & DFU_IFF_PATH) {
- ret = resolve_device_path(dif);
- if (ret < 0) {
- fprintf(stderr,
- "internal error: cannot re-parse `%s'\n",
- dif->path);
- abort();
- }
- if (!ret) {
- fprintf(stderr,
- "Can't resolve path after RESET?\n");
- exit(1);
- }
+ libusb_release_interface(dfu_root->dev_handle,
+ dfu_root->interface);
+ libusb_close(dfu_root->dev_handle);
+ dfu_root->dev_handle = NULL;
+
+ if (mode == MODE_DETACH) {
+ libusb_exit(ctx);
+ exit(0);
}
- num_devs = count_dfu_devices(ctx, dif);
- if (num_devs == 0) {
- fprintf(stderr, "Lost device after RESET?\n");
- exit(1);
- } else if (num_devs > 1) {
- fprintf(stderr, "More than one DFU capable USB "
- "device found, you might try `--list' and "
- "then disconnect all but one device\n");
- exit(1);
+ /* keeping handles open might prevent re-enumeration */
+ disconnect_devices();
+
+ milli_sleep(detach_delay * 1000);
+
+ /* Change match vendor and product to impossible values to force
+ * only DFU mode matches in the following probe */
+ match_vendor = match_product = 0x10000;
+
+ probe_devices(ctx);
+
+ if (dfu_root == NULL) {
+ errx(EX_IOERR, "Lost device after RESET?");
+ } else if (dfu_root->next != NULL) {
+ errx(EX_IOERR, "More than one DFU capable USB device found! "
+ "Try `--list' and specify the serial number "
+ "or disconnect all but one device");
}
- if (!get_first_dfu_device(ctx, dif))
- exit(3);
- printf("Opening USB Device...\n");
- libusb_open(dif->dev, &dif->dev_handle);
- if (!dif->dev_handle) {
- fprintf(stderr, "Cannot open device\n");
- exit(1);
+ /* Check for DFU mode device */
+ if (!(dfu_root->flags | DFU_IFF_DFU))
+ errx(EX_SOFTWARE, "Device is not in DFU mode");
+
+ printf("Opening DFU USB Device...\n");
+ ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle);
+ if (ret || !dfu_root->dev_handle) {
+ errx(EX_IOERR, "Cannot open device");
}
} else {
/* we're already in DFU mode, so we can skip the detach/reset
* procedure */
+ /* If a match vendor/product was specified, use that as the runtime
+ * vendor/product, otherwise use the DFU mode vendor/product */
+ runtime_vendor = match_vendor < 0 ? dfu_root->vendor : match_vendor;
+ runtime_product = match_product < 0 ? dfu_root->product : match_product;
}
dfustate:
- if (alt_name) {
- int n;
-
- n = find_dfu_if(dif->dev, &alt_by_name, alt_name);
- if (!n) {
- fprintf(stderr, "No such Alternate Setting: \"%s\"\n",
- alt_name);
- exit(1);
- }
- if (n < 0) {
- fprintf(stderr, "Error %d in name lookup\n", n);
- exit(1);
- }
- dif->altsetting = n-1;
- }
-
- num_ifs = count_matching_dfu_if(dif);
- if (num_ifs < 0) {
- fprintf(stderr, "No matching DFU Interface after RESET?!?\n");
- exit(1);
- } else if (num_ifs > 1 ) {
- fprintf(stderr, "We have %u DFU Interfaces/Altsettings,"
- " you have to specify one via --intf / --alt"
- " options\n", num_ifs);
- exit(1);
- }
-
- if (!get_matching_dfu_if(dif)) {
- fprintf(stderr, "Can't find the matching DFU interface/"
- "altsetting\n");
- exit(1);
- }
- print_dfu_if(dif, NULL);
- if (get_alt_name(dif, active_alt_name) > 0)
- dif->alt_name = active_alt_name;
- else
- dif->alt_name = NULL;
-
#if 0
- printf("Setting Configuration %u...\n", dif->configuration);
- if (libusb_set_configuration(dif->dev_handle, dif->configuration) < 0) {
- fprintf(stderr, "Cannot set configuration\n");
- exit(1);
+ printf("Setting Configuration %u...\n", dfu_root->configuration);
+ if (libusb_set_configuration(dfu_root->dev_handle, dfu_root->configuration) < 0) {
+ errx(EX_IOERR, "Cannot set configuration");
}
#endif
printf("Claiming USB DFU Interface...\n");
- if (libusb_claim_interface(dif->dev_handle, dif->interface) < 0) {
- fprintf(stderr, "Cannot claim interface\n");
- exit(1);
+ if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) {
+ errx(EX_IOERR, "Cannot claim interface");
}
- printf("Setting Alternate Setting #%d ...\n", dif->altsetting);
- if (libusb_set_interface_alt_setting(dif->dev_handle, dif->interface, dif->altsetting) < 0) {
- fprintf(stderr, "Cannot set alternate interface\n");
- exit(1);
+ printf("Setting Alternate Setting #%d ...\n", dfu_root->altsetting);
+ if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, dfu_root->altsetting) < 0) {
+ errx(EX_IOERR, "Cannot set alternate interface");
}
status_again:
printf("Determining device status: ");
- if (dfu_get_status(dif->dev_handle, dif->interface, &status ) < 0) {
- fprintf(stderr, "error get_status\n");
- exit(1);
+ if (dfu_get_status(dfu_root, &status ) < 0) {
+ errx(EX_IOERR, "error get_status");
}
printf("state = %s, status = %d\n",
dfu_state_to_string(status.bState), status.bStatus);
- if (!(quirks & QUIRK_POLLTIMEOUT))
- usleep(status.bwPollTimeout * 1000);
+
+ milli_sleep(status.bwPollTimeout);
switch (status.bState) {
case DFU_STATE_appIDLE:
case DFU_STATE_appDETACH:
- fprintf(stderr, "Device still in Runtime Mode!\n");
- exit(1);
+ errx(EX_IOERR, "Device still in Runtime Mode!");
break;
case DFU_STATE_dfuERROR:
printf("dfuERROR, clearing status\n");
- if (dfu_clear_status(dif->dev_handle, dif->interface) < 0) {
- fprintf(stderr, "error clear_status\n");
- exit(1);
+ if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) {
+ errx(EX_IOERR, "error clear_status");
}
goto status_again;
break;
case DFU_STATE_dfuDNLOAD_IDLE:
case DFU_STATE_dfuUPLOAD_IDLE:
printf("aborting previous incomplete transfer\n");
- if (dfu_abort(dif->dev_handle, dif->interface) < 0) {
- fprintf(stderr, "can't send DFU_ABORT\n");
- exit(1);
+ if (dfu_abort(dfu_root->dev_handle, dfu_root->interface) < 0) {
+ errx(EX_IOERR, "can't send DFU_ABORT");
}
goto status_again;
break;
case DFU_STATE_dfuIDLE:
printf("dfuIDLE, continuing\n");
break;
+ default:
+ break;
}
if (DFU_STATUS_OK != status.bStatus ) {
printf("WARNING: DFU Status: '%s'\n",
dfu_status_to_string(status.bStatus));
/* Clear our status & try again. */
- dfu_clear_status(dif->dev_handle, dif->interface);
- dfu_get_status(dif->dev_handle, dif->interface, &status);
+ if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0)
+ errx(EX_IOERR, "USB communication error");
+ if (dfu_get_status(dfu_root, &status) < 0)
+ errx(EX_IOERR, "USB communication error");
+ if (DFU_STATUS_OK != status.bStatus)
+ errx(EX_SOFTWARE, "Status is not OK: %d", status.bStatus);
- if (DFU_STATUS_OK != status.bStatus) {
- fprintf(stderr, "Error: %d\n", status.bStatus);
- exit(1);
- }
- if (!(quirks & QUIRK_POLLTIMEOUT))
- usleep(status.bwPollTimeout * 1000);
+ milli_sleep(status.bwPollTimeout);
}
- /* Get the DFU mode DFU functional descriptor
- * If it is not found cached, we will request it from the device */
- ret = get_cached_extra_descriptor(dif->dev, dif->configuration,
- dif->interface, USB_DT_DFU, 0,
- (unsigned char *) &func_dfu,
- sizeof(func_dfu));
- if (ret < 7) {
- fprintf(stderr, "Error obtaining cached DFU functional "
- "descriptor\n");
- ret = usb_get_any_descriptor(dif->dev_handle,
- USB_DT_DFU, 0,
- (unsigned char *) &func_dfu,
- sizeof(func_dfu));
- }
- if (ret == 7) {
- printf("Deducing device DFU version from functional descriptor "
- "length\n");
- func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
- } else if (ret < 9) {
- printf("Error obtaining DFU functional descriptor\n");
- printf("Warning: Assuming DFU version 1.0\n");
- func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
- printf("Warning: Transfer size can not be detected\n");
- func_dfu.wTransferSize = 0;
- }
printf("DFU mode device DFU version %04x\n",
- libusb_le16_to_cpu(func_dfu.bcdDFUVersion));
+ libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion));
- if (func_dfu.bcdDFUVersion == 0x11a)
- dfuse = 1;
+ if (dfu_root->func_dfu.bcdDFUVersion == libusb_cpu_to_le16(0x11a))
+ dfuse_device = 1;
+ /* If not overridden by the user */
if (!transfer_size) {
- transfer_size = libusb_le16_to_cpu(func_dfu.wTransferSize);
- printf("Device returned transfer size %i\n", transfer_size);
+ transfer_size = libusb_le16_to_cpu(
+ dfu_root->func_dfu.wTransferSize);
+ if (transfer_size) {
+ printf("Device returned transfer size %i\n",
+ transfer_size);
+ } else {
+ errx(EX_IOERR, "Transfer size must be specified");
+ }
}
- /* if returned zero or not detected (and not user specified) */
- if (!transfer_size) {
- transfer_size = DEFAULT_TRANSFER_SIZE;
- printf("Warning: Trying default transfer size %i\n",
- transfer_size);
- }
+#ifdef HAVE_GETPAGESIZE
+/* autotools lie when cross-compiling for Windows using mingw32/64 */
+#ifndef __MINGW32__
/* limitation of Linux usbdevio */
- if (transfer_size > host_page_size) {
- transfer_size = host_page_size;
+ if ((int)transfer_size > getpagesize()) {
+ transfer_size = getpagesize();
printf("Limited transfer size to %i\n", transfer_size);
}
- /* DFU specification */
- struct libusb_device_descriptor desc;
- libusb_get_device_descriptor(dif->dev, &desc);
- if (transfer_size < desc.bMaxPacketSize0) {
- transfer_size = desc.bMaxPacketSize0;
+#endif /* __MINGW32__ */
+#endif /* HAVE_GETPAGESIZE */
+
+ if (transfer_size < dfu_root->bMaxPacketSize0) {
+ transfer_size = dfu_root->bMaxPacketSize0;
printf("Adjusted transfer size to %i\n", transfer_size);
}
switch (mode) {
case MODE_UPLOAD:
- file.fd = open(file.name, O_WRONLY|O_CREAT|O_EXCL, 0644);
- if (file.fd < 0) {
- perror(file.name);
- exit(1);
- }
- if (dfuse) {
- if (dfuse_do_upload(dif, transfer_size, file,
- dfuse_address) < 0)
+ /* open for "exclusive" writing */
+ fd = open(file.name, O_WRONLY | O_BINARY | O_CREAT | O_EXCL | O_TRUNC, 0666);
+ if (fd < 0)
+ err(EX_IOERR, "Cannot open file %s for writing", file.name);
+
+ if (dfuse_device || dfuse_options) {
+ if (dfuse_do_upload(dfu_root, transfer_size, fd,
+ dfuse_options) < 0)
exit(1);
} else {
- if (dfuload_do_upload(dif, transfer_size, file) < 0)
+ if (dfuload_do_upload(dfu_root, transfer_size,
+ expected_size, fd) < 0) {
exit(1);
+ }
}
- close(file.fd);
+ close(fd);
break;
+
case MODE_DOWNLOAD:
- file.fd = open(file.name, O_RDONLY|O_BINARY);
- if (file.fd < 0) {
- perror(file.name);
- exit(1);
- }
- ret = parse_dfu_suffix(&file);
- if (ret < 0)
- exit(1);
- if (ret == 0) {
- fprintf(stderr, "Warning: File has no DFU suffix\n");
- } else if (file.bcdDFU != 0x0100 && file.bcdDFU != 0x11a) {
- fprintf(stderr, "Unsupported DFU file revision "
- "%04x\n", file.bcdDFU);
- exit(1);
- }
- if (file.idVendor != 0xffff &&
- dif->vendor != file.idVendor) {
- fprintf(stderr, "Warning: File vendor ID %04x does "
- "not match device %04x\n", file.idVendor, dif->vendor);
+ if (((file.idVendor != 0xffff && file.idVendor != runtime_vendor) ||
+ (file.idProduct != 0xffff && file.idProduct != runtime_product)) &&
+ ((file.idVendor != 0xffff && file.idVendor != dfu_root->vendor) ||
+ (file.idProduct != 0xffff && file.idProduct != dfu_root->product))) {
+ errx(EX_IOERR, "Error: File ID %04x:%04x does "
+ "not match device (%04x:%04x or %04x:%04x)",
+ file.idVendor, file.idProduct,
+ runtime_vendor, runtime_product,
+ dfu_root->vendor, dfu_root->product);
}
- if (file.idProduct != 0xffff &&
- dif->product != file.idProduct) {
- fprintf(stderr, "Warning: File product ID %04x does "
- "not match device %04x\n", file.idProduct, dif->product);
- }
- if (dfuse || file.bcdDFU == 0x11a) {
- if (dfuse_do_dnload(dif, transfer_size, file,
- dfuse_address) < 0)
+ if (dfuse_device || dfuse_options || file.bcdDFU == 0x11a) {
+ if (dfuse_do_dnload(dfu_root, transfer_size, &file,
+ dfuse_options) < 0)
exit(1);
} else {
- if (dfuload_do_dnload(dif, transfer_size, file) < 0)
+ if (dfuload_do_dnload(dfu_root, transfer_size, &file) < 0)
exit(1);
}
- close(file.fd);
+ break;
+ case MODE_DETACH:
+ if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) {
+ warnx("can't detach");
+ }
break;
default:
- fprintf(stderr, "Unsupported mode: %u\n", mode);
- exit(1);
+ errx(EX_IOERR, "Unsupported mode: %u", mode);
+ break;
}
if (final_reset) {
- if (dfu_detach(dif->dev_handle, dif->interface, 1000) < 0) {
- fprintf(stderr, "can't detach\n");
+ if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) {
+ /* Even if detach failed, just carry on to leave the
+ device in a known state */
+ warnx("can't detach");
}
printf("Resetting USB to switch back to runtime mode\n");
- ret = libusb_reset_device(dif->dev_handle);
+ ret = libusb_reset_device(dfu_root->dev_handle);
if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) {
- fprintf(stderr, "error resetting after download\n");
+ errx(EX_IOERR, "error resetting after download");
}
}
- libusb_close(dif->dev_handle);
+ libusb_close(dfu_root->dev_handle);
+ dfu_root->dev_handle = NULL;
libusb_exit(ctx);
- exit(0);
-}
+ return (0);
+}
diff --git a/src/portable.h b/src/portable.h
new file mode 100644
index 0000000..cf8d5df
--- /dev/null
+++ b/src/portable.h
@@ -0,0 +1,72 @@
+
+#ifndef PORTABLE_H
+#define PORTABLE_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# define PACKAGE "dfu-util"
+# define PACKAGE_VERSION "0.8-msvc"
+# define PACKAGE_STRING "dfu-util 0.8-msvc"
+# define PACKAGE_BUGREPORT "dfu-util@lists.gnumonks.org"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef HAVE_FTRUNCATE
+# include <unistd.h>
+#else
+# include <io.h>
+#endif /* HAVE_FTRUNCATE */
+
+#ifdef HAVE_NANOSLEEP
+# include <time.h>
+# define milli_sleep(msec) do {\
+ if (msec) {\
+ struct timespec nanosleepDelay = { (msec) / 1000, ((msec) % 1000) * 1000000 };\
+ nanosleep(&nanosleepDelay, NULL);\
+ } } while (0)
+#elif defined HAVE_WINDOWS_H
+# define milli_sleep(msec) do {\
+ if (msec) {\
+ Sleep(msec);\
+ } } while (0)
+#else
+# error "Can't get no sleep! Please report"
+#endif /* HAVE_NANOSLEEP */
+
+#ifdef HAVE_ERR
+# include <err.h>
+#else
+# include <errno.h>
+# include <string.h>
+# define warnx(...) do {\
+ fprintf(stderr, __VA_ARGS__);\
+ fprintf(stderr, "\n"); } while (0)
+# define errx(eval, ...) do {\
+ warnx(__VA_ARGS__);\
+ exit(eval); } while (0)
+# define warn(...) do {\
+ fprintf(stderr, "%s: ", strerror(errno));\
+ warnx(__VA_ARGS__); } while (0)
+# define err(eval, ...) do {\
+ warn(__VA_ARGS__);\
+ exit(eval); } while (0)
+#endif /* HAVE_ERR */
+
+#ifdef HAVE_SYSEXITS_H
+# include <sysexits.h>
+#else
+# define EX_OK 0 /* successful termination */
+# define EX_USAGE 64 /* command line usage error */
+# define EX_SOFTWARE 70 /* internal software error */
+# define EX_IOERR 74 /* input/output error */
+#endif /* HAVE_SYSEXITS_H */
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+#ifndef off_t
+# define off_t long int
+#endif
+
+#endif /* PORTABLE_H */
diff --git a/src/prefix.c b/src/prefix.c
new file mode 100644
index 0000000..be8e3fa
--- /dev/null
+++ b/src/prefix.c
@@ -0,0 +1,176 @@
+/*
+ * dfu-prefix
+ *
+ * Copyright 2011-2012 Stefan Schmidt <stefan@datenfreihafen.org>
+ * Copyright 2013 Hans Petter Selasky <hps@bitfrost.no>
+ * Copyright 2014 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
+ *
+ * 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
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <string.h>
+
+#include "portable.h"
+#include "dfu_file.h"
+
+enum mode {
+ MODE_NONE,
+ MODE_ADD,
+ MODE_DEL,
+ MODE_CHECK
+};
+
+int verbose;
+
+static void help(void)
+{
+ fprintf(stderr, "Usage: dfu-prefix [options] ...\n"
+ " -h --help\t\t\tPrint this help message\n"
+ " -V --version\t\t\tPrint the version number\n"
+ " -c --check <file>\t\tCheck DFU prefix of <file>\n"
+ " -D --delete <file>\t\tDelete DFU prefix from <file>\n"
+ " -a --add <file>\t\tAdd DFU prefix to <file>\n"
+ "In combination with -a:\n"
+ );
+ fprintf(stderr, " -s --stellaris-address <address> Add TI Stellaris address prefix to <file>\n"
+ "In combination with -D or -c:\n"
+ " -T --stellaris\t\tAct on TI Stellaris address prefix of <file>\n"
+ "In combination with -a or -D or -c:\n"
+ " -L --lpc-prefix\t\tUse NXP LPC DFU prefix format\n"
+ );
+ exit(EX_USAGE);
+}
+
+static void print_version(void)
+{
+ printf("dfu-prefix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION);
+ printf("Copyright 2011-2012 Stefan Schmidt, 2014 Uwe Bonnes\n"
+ "This program is Free Software and has ABSOLUTELY NO WARRANTY\n"
+ "Please report bugs to %s\n\n", PACKAGE_BUGREPORT);
+
+}
+
+static struct option opts[] = {
+ { "help", 0, 0, 'h' },
+ { "version", 0, 0, 'V' },
+ { "check", 1, 0, 'c' },
+ { "add", 1, 0, 'a' },
+ { "delete", 1, 0, 'D' },
+ { "stellaris-address", 1, 0, 's' },
+ { "stellaris", 0, 0, 'T' },
+ { "LPC", 0, 0, 'L' },
+};
+int main(int argc, char **argv)
+{
+ struct dfu_file file;
+ enum mode mode = MODE_NONE;
+ enum prefix_type type = ZERO_PREFIX;
+ uint32_t lmdfu_flash_address = 0;
+ char *end;
+
+ /* make sure all prints are flushed */
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ print_version();
+
+ memset(&file, 0, sizeof(file));
+
+ while (1) {
+ int c, option_index = 0;
+ c = getopt_long(argc, argv, "hVc:a:D:p:v:d:s:TL", opts,
+ &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ help();
+ break;
+ case 'V':
+ exit(0);
+ break;
+ case 'D':
+ file.name = optarg;
+ mode = MODE_DEL;
+ break;
+ case 'c':
+ file.name = optarg;
+ mode = MODE_CHECK;
+ break;
+ case 'a':
+ file.name = optarg;
+ mode = MODE_ADD;
+ break;
+ case 's':
+ lmdfu_flash_address = strtoul(optarg, &end, 0);
+ if (*end) {
+ errx(EX_IOERR, "Invalid lmdfu "
+ "address: %s", optarg);
+ }
+ /* fall-through */
+ case 'T':
+ type = LMDFU_PREFIX;
+ break;
+ case 'L':
+ type = LPCDFU_UNENCRYPTED_PREFIX;
+ break;
+ default:
+ help();
+ break;
+ }
+ }
+
+ if (!file.name) {
+ fprintf(stderr, "You need to specify a filename\n");
+ help();
+ }
+
+ switch(mode) {
+ case MODE_ADD:
+ if (type == ZERO_PREFIX)
+ errx(EX_IOERR, "Prefix type must be specified");
+ dfu_load_file(&file, MAYBE_SUFFIX, NO_PREFIX);
+ file.lmdfu_address = lmdfu_flash_address;
+ file.prefix_type = type;
+ printf("Adding prefix to file\n");
+ dfu_store_file(&file, file.size.suffix != 0, 1);
+ break;
+
+ case MODE_CHECK:
+ dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX);
+ show_suffix_and_prefix(&file);
+ if (type > ZERO_PREFIX && file.prefix_type != type)
+ errx(EX_IOERR, "No prefix of requested type");
+ break;
+
+ case MODE_DEL:
+ dfu_load_file(&file, MAYBE_SUFFIX, NEEDS_PREFIX);
+ if (type > ZERO_PREFIX && file.prefix_type != type)
+ errx(EX_IOERR, "No prefix of requested type");
+ printf("Removing prefix from file\n");
+ /* if there was a suffix, rewrite it */
+ dfu_store_file(&file, file.size.suffix != 0, 0);
+ break;
+
+ default:
+ help();
+ break;
+ }
+ return (0);
+}
diff --git a/src/quirks.c b/src/quirks.c
index 0350fb5..de394a6 100644..100755
--- a/src/quirks.c
+++ b/src/quirks.c
@@ -1,5 +1,7 @@
-/* Simple quirk system for dfu-util
- * Copyright 2010 Tormod Volden
+/*
+ * Simple quirk system for dfu-util
+ *
+ * Copyright 2010-2014 Tormod Volden
*
* 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
@@ -16,15 +18,39 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <stdint.h>
#include "quirks.h"
-int quirks = 0;
-
-void set_quirks(unsigned long vendor, unsigned long product)
+uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice)
{
+ uint16_t quirks = 0;
+
/* Device returns bogus bwPollTimeout values */
- if (vendor == VENDOR_OPENMOKO ||
- vendor == VENDOR_FIC ||
- vendor == VENDOR_VOTI)
+ if ((vendor == VENDOR_OPENMOKO || vendor == VENDOR_FIC) &&
+ product >= PRODUCT_FREERUNNER_FIRST &&
+ product <= PRODUCT_FREERUNNER_LAST)
quirks |= QUIRK_POLLTIMEOUT;
+
+ if (vendor == VENDOR_VOTI &&
+ product == PRODUCT_OPENPCD)
+ quirks |= QUIRK_POLLTIMEOUT;
+
+ /* Reports wrong DFU version in DFU descriptor */
+ if (vendor == VENDOR_LEAFLABS &&
+ product == PRODUCT_MAPLE3 &&
+ bcdDevice == 0x0200)
+ quirks |= QUIRK_FORCE_DFU11;
+
+ /* old devices(bcdDevice == 0) return bogus bwPollTimeout values */
+ if (vendor == VENDOR_SIEMENS &&
+ (product == PRODUCT_PXM40 || product == PRODUCT_PXM50) &&
+ bcdDevice == 0)
+ quirks |= QUIRK_POLLTIMEOUT;
+
+ /* M-Audio Transit returns bogus bwPollTimeout values */
+ if (vendor == VENDOR_MIDIMAN &&
+ product == PRODUCT_TRANSIT)
+ quirks |= QUIRK_POLLTIMEOUT;
+
+ return (quirks);
}
diff --git a/src/quirks.h b/src/quirks.h
index fb93fab..0e4b3ec 100644..100755
--- a/src/quirks.h
+++ b/src/quirks.h
@@ -4,14 +4,24 @@
#define VENDOR_OPENMOKO 0x1d50 /* Openmoko Freerunner / GTA02 */
#define VENDOR_FIC 0x1457 /* Openmoko Freerunner / GTA02 */
#define VENDOR_VOTI 0x16c0 /* OpenPCD Reader */
+#define VENDOR_LEAFLABS 0x1eaf /* Maple */
+#define VENDOR_SIEMENS 0x0908 /* Siemens AG */
+#define VENDOR_MIDIMAN 0x0763 /* Midiman */
+
+#define PRODUCT_FREERUNNER_FIRST 0x5117
+#define PRODUCT_FREERUNNER_LAST 0x5126
+#define PRODUCT_OPENPCD 0x076b
+#define PRODUCT_MAPLE3 0x0003 /* rev 3 and 5 */
+#define PRODUCT_PXM40 0x02c4 /* Siemens AG, PXM 40 */
+#define PRODUCT_PXM50 0x02c5 /* Siemens AG, PXM 50 */
+#define PRODUCT_TRANSIT 0x2806 /* M-Audio Transit (Midiman) */
#define QUIRK_POLLTIMEOUT (1<<0)
+#define QUIRK_FORCE_DFU11 (1<<1)
/* Fallback value, works for OpenMoko */
#define DEFAULT_POLLTIMEOUT 5
-extern int quirks;
-
-void set_quirks(unsigned long vendor, unsigned long product);
+uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice);
#endif /* DFU_QUIRKS_H */
diff --git a/src/suffix.c b/src/suffix.c
new file mode 100644
index 0000000..0df248f
--- /dev/null
+++ b/src/suffix.c
@@ -0,0 +1,176 @@
+/*
+ * dfu-suffix
+ *
+ * Copyright 2011-2012 Stefan Schmidt <stefan@datenfreihafen.org>
+ * Copyright 2013 Hans Petter Selasky <hps@bitfrost.no>
+ * Copyright 2014 Tormod Volden <debian.tormod@gmail.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
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <string.h>
+
+#include "portable.h"
+#include "dfu_file.h"
+
+enum mode {
+ MODE_NONE,
+ MODE_ADD,
+ MODE_DEL,
+ MODE_CHECK
+};
+
+int verbose;
+
+static void help(void)
+{
+ fprintf(stderr, "Usage: dfu-suffix [options] ...\n"
+ " -h --help\t\t\tPrint this help message\n"
+ " -V --version\t\t\tPrint the version number\n"
+ " -c --check <file>\t\tCheck DFU suffix of <file>\n"
+ " -a --add <file>\t\tAdd DFU suffix to <file>\n"
+ " -D --delete <file>\t\tDelete DFU suffix from <file>\n"
+ " -p --pid <productID>\t\tAdd product ID into DFU suffix in <file>\n"
+ " -v --vid <vendorID>\t\tAdd vendor ID into DFU suffix in <file>\n"
+ " -d --did <deviceID>\t\tAdd device ID into DFU suffix in <file>\n"
+ " -S --spec <specID>\t\tAdd DFU specification ID into DFU suffix in <file>\n"
+ );
+ exit(EX_USAGE);
+}
+
+static void print_version(void)
+{
+ printf("dfu-suffix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION);
+ printf("Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden\n"
+ "This program is Free Software and has ABSOLUTELY NO WARRANTY\n"
+ "Please report bugs to %s\n\n", PACKAGE_BUGREPORT);
+
+}
+
+static struct option opts[] = {
+ { "help", 0, 0, 'h' },
+ { "version", 0, 0, 'V' },
+ { "check", 1, 0, 'c' },
+ { "add", 1, 0, 'a' },
+ { "delete", 1, 0, 'D' },
+ { "pid", 1, 0, 'p' },
+ { "vid", 1, 0, 'v' },
+ { "did", 1, 0, 'd' },
+ { "spec", 1, 0, 'S' },
+};
+
+int main(int argc, char **argv)
+{
+ struct dfu_file file;
+ int pid, vid, did, spec;
+ enum mode mode = MODE_NONE;
+
+ /* make sure all prints are flushed */
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ print_version();
+
+ pid = vid = did = 0xffff;
+ spec = 0x0100; /* Default to bcdDFU version 1.0 */
+ memset(&file, 0, sizeof(file));
+
+ while (1) {
+ int c, option_index = 0;
+ c = getopt_long(argc, argv, "hVc:a:D:p:v:d:S:s:T", opts,
+ &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ help();
+ break;
+ case 'V':
+ exit(0);
+ break;
+ case 'D':
+ file.name = optarg;
+ mode = MODE_DEL;
+ break;
+ case 'p':
+ pid = strtol(optarg, NULL, 16);
+ break;
+ case 'v':
+ vid = strtol(optarg, NULL, 16);
+ break;
+ case 'd':
+ did = strtol(optarg, NULL, 16);
+ break;
+ case 'S':
+ spec = strtol(optarg, NULL, 16);
+ break;
+ case 'c':
+ file.name = optarg;
+ mode = MODE_CHECK;
+ break;
+ case 'a':
+ file.name = optarg;
+ mode = MODE_ADD;
+ break;
+ default:
+ help();
+ break;
+ }
+ }
+
+ if (!file.name) {
+ fprintf(stderr, "You need to specify a filename\n");
+ help();
+ }
+
+ if (spec != 0x0100 && spec != 0x011a) {
+ fprintf(stderr, "Only DFU specification 0x0100 and 0x011a supported\n");
+ help();
+ }
+
+ switch(mode) {
+ case MODE_ADD:
+ dfu_load_file(&file, NO_SUFFIX, MAYBE_PREFIX);
+ file.idVendor = vid;
+ file.idProduct = pid;
+ file.bcdDevice = did;
+ file.bcdDFU = spec;
+ /* always write suffix, rewrite prefix if there was one */
+ dfu_store_file(&file, 1, file.size.prefix != 0);
+ printf("Suffix successfully added to file\n");
+ break;
+
+ case MODE_CHECK:
+ dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX);
+ show_suffix_and_prefix(&file);
+ break;
+
+ case MODE_DEL:
+ dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX);
+ dfu_store_file(&file, 0, file.size.prefix != 0);
+ if (file.size.suffix) /* had a suffix */
+ printf("Suffix successfully removed from file\n");
+ break;
+
+ default:
+ help();
+ break;
+ }
+ return (0);
+}
diff --git a/src/usb_dfu.h b/src/usb_dfu.h
index e803891..660bedc 100644
--- a/src/usb_dfu.h
+++ b/src/usb_dfu.h
@@ -1,5 +1,5 @@
-#ifndef _USB_DFU_H
-#define _USB_DFU_H
+#ifndef USB_DFU_H
+#define USB_DFU_H
/* USB Device Firmware Update Implementation for OpenPCD
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
*
@@ -23,22 +23,33 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <sys/types.h>
+#include <stdint.h>
#define USB_DT_DFU 0x21
+#ifdef _MSC_VER
+# pragma pack(push)
+# pragma pack(1)
+#endif /* _MSC_VER */
struct usb_dfu_func_descriptor {
- u_int8_t bLength;
- u_int8_t bDescriptorType;
- u_int8_t bmAttributes;
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_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;
+ uint16_t wDetachTimeOut;
+ uint16_t wTransferSize;
+ uint16_t bcdDFUVersion;
+#ifdef _MSC_VER
+};
+# pragma pack(pop)
+#elif defined __GNUC__
} __attribute__ ((packed));
+#else
+ #warning "No way to pack struct on this compiler? This will break!"
+#endif /* _MSC_VER */
#define USB_DT_DFU_SIZE 9
@@ -53,15 +64,7 @@ struct usb_dfu_func_descriptor {
#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
-
+/* DFU_GETSTATUS bStatus values (Section 6.1.2, DFU Rev 1.1) */
#define DFU_STATUS_OK 0x00
#define DFU_STATUS_errTARGET 0x01
#define DFU_STATUS_errFILE 0x02
@@ -90,18 +93,7 @@ enum dfu_state {
DFU_STATE_dfuMANIFEST = 7,
DFU_STATE_dfuMANIFEST_WAIT_RST = 8,
DFU_STATE_dfuUPLOAD_IDLE = 9,
- DFU_STATE_dfuERROR = 10,
+ DFU_STATE_dfuERROR = 10
};
-/* this is the 'swapped' definition, i.e. after/before mirroring */
-struct dfu_file_suffix {
- u_int32_t dwCRC; /* CRC32 ANSI X3.66 */
- u_int8_t bLength; /* 16 bytes */
- char ucDfuSignature[3]; /* "DFU" */
- u_int16_t bcdDFU; /* Version */
- u_int16_t idVendor; /* VendorID */
- u_int16_t idProduct; /* ProductID */
- u_int16_t bcdDevice; /* Device Revision, or 0xffff */
-} __attribute__ ((packed));
-
-#endif /* _USB_DFU_H */
+#endif /* USB_DFU_H */