[PATCH] quirks: Wait until device is ready after DFU status requests

Tormod Volden lists.tormod at gmail.com
Sun Nov 14 23:30:35 CET 2010


From: Tormod Volden <debian.tormod at gmail.com>

DFU devices tell the host in the status request answer for how long to
wait before another request.

The previous hardcoded wait of 5 ms while executing the flashing is too
short for many devices, causing (intermittent) failures.

The OpenMoko returns invalid (and random) values, so quirks are needed.
Add a simple quirk system matching vendor/product.

Also fix display of vendor/product, after detection, in lsusb style.
---

On Sun, Nov 14, 2010 at 6:19 PM, Stefan Schmidt wrote:
> The set_quirks call was done to early. With the following incremental
> patch it works reliable for my openmoko devices.

Thanks for checking this.

I wanted to set the quirks as early as possible in case the following
code could need quirks in the future, but I sure made it too early,
and failed to verify it properly.

That also means the "Opening USB Device..." message is broken, since
it uses the same values of dif->vendor and dif->product. And indeed,
I see this when I run it:
Opening USB Device 0x0000:0x0000...

Only if the user would use -d it would be correct, in which case the
message would not bring much value either...  So I fixed it to display
USB ID after detection.

Tormod

 src/Makefile.am |    3 ++-
 src/dfu_load.c  |   11 ++++++++++-
 src/main.c      |   14 +++++++++++++-
 src/quirks.c    |   29 +++++++++++++++++++++++++++++
 src/quirks.h    |   16 ++++++++++++++++
 5 files changed, 70 insertions(+), 3 deletions(-)
 create mode 100644 src/quirks.c
 create mode 100644 src/quirks.h

diff --git a/src/Makefile.am b/src/Makefile.am
index eb1fa94..d844f30 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,6 +12,7 @@ dfu_util_SOURCES = main.c \
 		dfu_load.h \
 		dfu.c \
 		dfu.h \
-		usb_dfu.h
+		usb_dfu.h \
+		quirks.c
 
 EXTRA_DIST = dfu-version.h
diff --git a/src/dfu_load.c b/src/dfu_load.c
index 24f784b..2425d17 100644
--- a/src/dfu_load.c
+++ b/src/dfu_load.c
@@ -34,6 +34,8 @@
 #include "config.h"
 #include "dfu.h"
 #include "usb_dfu.h"
+#include "dfu_load.h"
+#include "quirks.h"
 
 /* ugly hack for Win32 */
 #ifndef O_BINARY
@@ -161,7 +163,12 @@ int dfuload_do_dnload(struct usb_dev_handle *usb_handle, int interface,
 				fprintf(stderr, "Error during download get_status\n");
 				goto out_close;
 			}
-			usleep(5000);
+			/* Wait while device executes flashing */
+			if (quirks & QUIRK_POLLTIMEOUT)
+				usleep(DEFAULT_POLLTIMEOUT * 1000);
+			else
+				usleep(dst.bwPollTimeout * 1000);
+
 		} while (dst.bState != DFU_STATE_dfuDNLOAD_IDLE &&
 			 dst.bState != DFU_STATE_dfuERROR);
 		if (dst.bStatus != DFU_STATUS_OK) {
@@ -200,6 +207,8 @@ get_status:
 	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);
 
 	/* FIXME: deal correctly with ManifestationTolerant=0 / WillDetach bits */
 	switch (dst.bState) {
diff --git a/src/main.c b/src/main.c
index 264b553..7eac8df 100644
--- a/src/main.c
+++ b/src/main.c
@@ -33,6 +33,7 @@
 #include "usb_dfu.h"
 #include "dfu_load.h"
 #include "dfu-version.h"
+#include "quirks.h"
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -603,7 +604,7 @@ int main(int argc, char **argv)
 
 	/* We have exactly one device. Its usb_device is now in dif->dev */
 
-	printf("Opening USB Device 0x%04x:0x%04x...\n", dif->vendor, dif->product);
+	printf("Opening DFU USB device... ");
 	dif->dev_handle = usb_open(dif->dev);
 	if (!dif->dev_handle) {
 		fprintf(stderr, "Cannot open device: %s\n", usb_strerror());
@@ -615,6 +616,11 @@ int main(int argc, char **argv)
 	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);
+
 	if (!_rt_dif.flags & DFU_IFF_DFU) {
 		/* In the 'first round' during runtime mode, there can only be one
 		* DFU Interface descriptor according to the DFU Spec. */
@@ -643,6 +649,8 @@ int main(int argc, char **argv)
 		}
 		printf("state = %s, status = %d\n", 
 		       dfu_state_to_string(status.bState), status.bStatus);
+		if (!(quirks & QUIRK_POLLTIMEOUT))
+			usleep(status.bwPollTimeout * 1000);
 
 		switch (status.bState) {
 		case DFU_STATE_appIDLE:
@@ -791,6 +799,8 @@ status_again:
 	}
 	printf("state = %s, status = %d\n",
 	       dfu_state_to_string(status.bState), status.bStatus);
+	if (!(quirks & QUIRK_POLLTIMEOUT))
+		usleep(status.bwPollTimeout * 1000);
 
 	switch (status.bState) {
 	case DFU_STATE_appIDLE:
@@ -863,6 +873,8 @@ status_again:
 			fprintf(stderr, "Error: %d\n", status.bStatus);
 			exit(1);
 		}
+		if (!(quirks & QUIRK_POLLTIMEOUT))
+			usleep(status.bwPollTimeout * 1000);
         }
 
 	switch (mode) {
diff --git a/src/quirks.c b/src/quirks.c
new file mode 100644
index 0000000..28302d2
--- /dev/null
+++ b/src/quirks.c
@@ -0,0 +1,29 @@
+/*  Simple quirk system for dfu-util
+ *  Copyright 2010 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
+ * 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 "quirks.h"
+
+int quirks = 0;
+
+void set_quirks(unsigned long vendor, unsigned long product)
+{
+	/* Device returns bogus bwPollTimeout values */
+	if (vendor == VENDOR_OPENMOKO ||
+	    vendor == VENDOR_FIC)
+		quirks |= QUIRK_POLLTIMEOUT;
+}
diff --git a/src/quirks.h b/src/quirks.h
new file mode 100644
index 0000000..042b19e
--- /dev/null
+++ b/src/quirks.h
@@ -0,0 +1,16 @@
+#ifndef DFU_QUIRKS_H
+#define DFU_QUIRKS_H
+
+#define VENDOR_OPENMOKO 0x1d50
+#define VENDOR_FIC      0x1457
+
+#define QUIRK_POLLTIMEOUT  (1<<0)
+
+/* Fallback value, works for OpenMoko */
+#define DEFAULT_POLLTIMEOUT  5
+
+extern int quirks;
+
+void set_quirks(unsigned long vendor, unsigned long product);
+
+#endif /* DFU_QUIRKS_H */
-- 
1.7.0.4




More information about the devel mailing list