From: Tormod Volden <debian.tor...@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 _______________________________________________ devel mailing list devel@lists.openmoko.org https://lists.openmoko.org/mailman/listinfo/devel