diff --git a/tools/src/dfu-util/AUTHORS b/tools/src/dfu-util/AUTHORS new file mode 100755 index 0000000..bc16c9c --- /dev/null +++ b/tools/src/dfu-util/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/tools/src/dfu-util/COPYING b/tools/src/dfu-util/COPYING new file mode 100755 index 0000000..fbdd65f --- /dev/null +++ b/tools/src/dfu-util/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tools/src/dfu-util/ChangeLog b/tools/src/dfu-util/ChangeLog new file mode 100755 index 0000000..35a1da7 --- /dev/null +++ b/tools/src/dfu-util/ChangeLog @@ -0,0 +1,93 @@ +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 + +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 + +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 + +0.5: + o DfuSe extension support for ST devices (Tormod Volden) + o Add initial support for bitWillDetach flag from DFU 1.1 (Tormod + Volden) + o Internal cleanup and some manual page fixes (Tormod Volden) + +2011-11-02: Stefan Schmidt + +0.4: + o Rework to use libusb-1.0 (Stefan Schmidt) + o DFU suffix support (Tormod Volden, Stefan Schmidt) + o Sspeed up DFU downloads directly into memory (Bernard Blackham) + o More flexible -d vid:pid parsing (Tormod Volden) + o Many bug fixes and cleanups + +2011-07-20: Stefan Schmidt + +0.3: + o quirks: Add OpenOCD to the poll timeout quirk table. + +2010-12-22: Stefan Schmidt + +0.2: + o Fix some typos on the website and the README (Antonio Ospite, Uwe + Hermann) + o Remove build rule for a static binary. We can use autotools for this. + (Mike Frysinger) + o Fix infinite loop in download error path (C. Scott Ananian) + o Break out to show the 'finished' in upload (C. Scott Ananian) + o Add GPLv2+ headers (Harald Welte) + o Remove dead code (commands.[ch]) remnescent of dfu-programmer (Harald + Welte) + o Simple quirk system with Openmoko quirk for missing bwPollTimeout (Tormod Volden) + o New default (1024) and clamping of transfer size (Tormod Volden) + o Verify sending of completion packet (Tormod Volden) + o Look for DFU functional descriptor among all descriptors (Tormod + Volden) + o Print out in which direction we are transferring data + o Abort in upload if the file already exists + +2010-11-17 Stefan Schmidt + +0.1: + Initial release + +2010-05-23 Stefan Schmidt diff --git a/tools/src/dfu-util/DEVICES.txt b/tools/src/dfu-util/DEVICES.txt new file mode 100755 index 0000000..682e62c --- /dev/null +++ b/tools/src/dfu-util/DEVICES.txt @@ -0,0 +1,20 @@ +List of supported software and hardware products: + +Software user (bootloader, etc) +------------------------------- +- Sam7DFU: http://www.openpcd.org/Sam7dfu +- U-boot: DFU patches +- Barebox: http://www.barebox.org/ +- Leaflabs: http://code.google.com/p/leaflabs/ +- Blackmagic DFU + +Products using DFU +------------------ +- OpenPCD (sam7dfu) +- 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/tools/src/dfu-util/Makefile.am b/tools/src/dfu-util/Makefile.am new file mode 100755 index 0000000..7318dd8 --- /dev/null +++ b/tools/src/dfu-util/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src doc + +EXTRA_DIST = autogen.sh TODO DEVICES.txt dfuse-pack.py diff --git a/tools/src/dfu-util/README b/tools/src/dfu-util/README new file mode 100755 index 0000000..acda06a --- /dev/null +++ b/tools/src/dfu-util/README @@ -0,0 +1,20 @@ +Dfu-util - Device Firmware Upgrade Utilities + +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. + +dfu-util has been tested with Openmoko Neo1973 and Freerunner and many +other devices. + +[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: + + http://dfu-util.gnumonks.org/ + diff --git a/tools/src/dfu-util/TODO b/tools/src/dfu-util/TODO new file mode 100755 index 0000000..7574512 --- /dev/null +++ b/tools/src/dfu-util/TODO @@ -0,0 +1,14 @@ +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: +- Logo +- Re-License as LGPL for usage as library? diff --git a/tools/src/dfu-util/autogen.sh b/tools/src/dfu-util/autogen.sh new file mode 100755 index 0000000..5959508 --- /dev/null +++ b/tools/src/dfu-util/autogen.sh @@ -0,0 +1,2 @@ +#! /bin/sh +autoreconf -v -i diff --git a/tools/src/dfu-util/configure.ac b/tools/src/dfu-util/configure.ac new file mode 100755 index 0000000..8810f56 --- /dev/null +++ b/tools/src/dfu-util/configure.ac @@ -0,0 +1,41 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([dfu-util],[0.8],[dfu-util@lists.gnumonks.org],,[http://dfu-util.gnumonks.org]) +AC_CONFIG_AUX_DIR(m4) +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])]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. +# 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" +CFLAGS="$CFLAGS $USB_CFLAGS" + +# Checks for header files. +AC_HEADER_STDC +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_MEMCMP +AC_CHECK_FUNCS([ftruncate getpagesize nanosleep err]) + +AC_CONFIG_FILES(Makefile src/Makefile doc/Makefile) +AC_OUTPUT diff --git a/tools/src/dfu-util/device-logs/README b/tools/src/dfu-util/device-logs/README new file mode 100755 index 0000000..c1de3e7 --- /dev/null +++ b/tools/src/dfu-util/device-logs/README @@ -0,0 +1,77 @@ +Device: +------- +qi-hardware-atusb: +- Qi Hardware ben-wpan +- DFU implementation: + http://projects.qi-hardware.com/index.php/p/ben-wpan/source/tree/master/atusb/fw/usb +- Tester: Stefan Schmidt + +openpcd: +- OpenPCD RFID reader +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +simtrace: +- Sysmocom SimTrace +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +openmoko-freerunner: +- Openmoko Freerunner +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +openmoko-neo1973: +- Openmoko Neo1073 +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +tdk-bluetooth: +- TDK Corp. Bluetooth Adapter +- DFU implementation: closed soure +- Only upload has been tested +- Tester: Stefan Schmidt + +stm32f107: +- STM32 microcontrollers with built-in (ROM) DFU loader +- DFU implementation: Closed source but probably similar to the one + in their USB device libraries. Some relevant application notes: + http://www.st.com -> AN3156 and AN2606 +- Tested by Uwe Bonnes + +stm32f4discovery: +- STM32 microcontroller board with built-in (ROM) DFU loader +- DFU implementation: Closed source, probably similar to stm32f107. +- Tested by Joe Rothweiler + +dso-nano: +- DSO Nano pocket oscilloscope +- DFU implementation: Based on ST Microelectronics USB FS Library 1.0 + http://dsonano.googlecode.com/files/DS0201_OpenSource.rar +- Tester: Tormod Volden + +opc-20: +- Custom devices based on STM32F1xx +- DFU implementation: ST Microelectronics USB FS Device Library 3.1.0 + http://www.st.com -> um0424.zip +- Tester: Tormod Volden + +lpc-link, lpclink2: +- NXP LPCXpresso debug adapters +- Proprietary DFU implementation, uses special download files with + LPC prefix and encoding of the target firmware code +- Tested by Uwe Bonnes + +Adding the lsusb output and a download log of your device here helps +us to avoid regressions for hardware we cannot test while working on +the code. To extract the lsusb output use this command: +sudo lsusb -v -d $USBID > $DEVICE.lsusb +Prepare a description snippet as above, and send it to us. A log +(copy-paste of the command window) of a firmware download is also +nice, please use the double verbose option -v -v and include the +command line in the log file. + diff --git a/tools/src/dfu-util/device-logs/dsonano.lsusb b/tools/src/dfu-util/device-logs/dsonano.lsusb new file mode 100755 index 0000000..44a5d28 --- /dev/null +++ b/tools/src/dfu-util/device-logs/dsonano.lsusb @@ -0,0 +1,60 @@ + +Bus 002 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 1.1a + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 001 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 5 @SPI Flash : M25P64/0x00000000/64*064Kg,64*064Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/tools/src/dfu-util/device-logs/lpclink.log b/tools/src/dfu-util/device-logs/lpclink.log new file mode 100755 index 0000000..f2a04f7 --- /dev/null +++ b/tools/src/dfu-util/device-logs/lpclink.log @@ -0,0 +1,59 @@ +(The on-board LPC3154 has some encryption key set and LPCXpressoWIN.enc +is encrypted.) + +$ lsusb | grep NXP +Bus 003 Device 011: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link + +$ dfu-util -v -v -v -R -D /opt/lpc/lpcxpresso/bin/LPCXpressoWIN.enc + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Deducing device DFU version from functional descriptor length +Opening DFU capable USB device... +ID 0471:df55 +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 6% 2048 bytes +Download [=== ] 13% 4096 bytes +Download [==== ] 19% 6144 bytes +Download [====== ] 26% 8192 bytes +Download [======== ] 32% 10240 bytes +Download [========= ] 39% 12288 bytes +Download [=========== ] 45% 14336 bytes +Download [============= ] 52% 16384 bytes +Download [============== ] 59% 18432 bytes +Download [================ ] 65% 20480 bytes +Download [================== ] 72% 22528 bytes +Download [=================== ] 78% 24576 bytes +Download [===================== ] 85% 26624 bytes +Download [====================== ] 91% 28672 bytes +Download [======================== ] 98% 29192 bytes +Download [=========================] 100% 29192 bytes +Download done. +Sent a total of 29192 bytes +state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present +Done! +dfu-util: can't detach +Resetting USB to switch back to runtime mode + +$ lsusb | grep NXP +Bus 003 Device 012: ID 1fc9:0009 NXP Semiconductors diff --git a/tools/src/dfu-util/device-logs/lpclink.lsusb b/tools/src/dfu-util/device-logs/lpclink.lsusb new file mode 100755 index 0000000..c80d2b7 --- /dev/null +++ b/tools/src/dfu-util/device-logs/lpclink.lsusb @@ -0,0 +1,58 @@ + +Bus 003 Device 008: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0471 Philips (or NXP) + idProduct 0xdf55 LPCXpresso LPC-Link + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 25 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 1 + Will Not Detach + Manifestation Intolerant + Upload Unsupported + Download Supported + wDetachTimeout 65535 milliseconds + wTransferSize 2048 bytes +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/tools/src/dfu-util/device-logs/lpclink2.log b/tools/src/dfu-util/device-logs/lpclink2.log new file mode 100755 index 0000000..f33e671 --- /dev/null +++ b/tools/src/dfu-util/device-logs/lpclink2.log @@ -0,0 +1,59 @@ +$ lsusb | grep NXP +Bus 003 Device 013: ID 1fc9:000c NXP Semiconductors + +$ dfu-util -D ~/devel/dfu-util/firmware.bin.qthdr + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Possible unencryptes NXP LPC DFU prefix with the following properties +Payload length: 39 kiByte +Opening DFU capable USB device... +ID 1fc9:000c +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 4% 2048 bytes +Download [== ] 9% 4096 bytes +Download [=== ] 14% 6144 bytes +Download [==== ] 19% 8192 bytes +Download [====== ] 24% 10240 bytes +Download [======= ] 28% 12288 bytes +Download [======== ] 33% 14336 bytes +Download [========= ] 38% 16384 bytes +Download [========== ] 43% 18432 bytes +Download [============ ] 48% 20480 bytes +Download [============= ] 53% 22528 bytes +Download [============== ] 57% 24576 bytes +Download [=============== ] 62% 26624 bytes +Download [================ ] 67% 28672 bytes +Download [================== ] 72% 30720 bytes +Download [=================== ] 77% 32768 bytes +Download [==================== ] 82% 34816 bytes +Download [===================== ] 86% 36864 bytes +Download [====================== ] 91% 38912 bytes +Download [======================== ] 96% 40356 bytes +Download [=========================] 100% 40356 bytes +Download done. +Sent a total of 40356 bytes +dfu-util: unable to read DFU status + +$ lsusb | grep NXP +Bus 003 Device 014: ID 1fc9:0018 NXP Semiconductors diff --git a/tools/src/dfu-util/device-logs/lpclink2.lsusb b/tools/src/dfu-util/device-logs/lpclink2.lsusb new file mode 100755 index 0000000..d8d6e0c --- /dev/null +++ b/tools/src/dfu-util/device-logs/lpclink2.lsusb @@ -0,0 +1,203 @@ + +Bus 003 Device 007: ID 0c72:000c PEAK System PCAN-USB +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x0c72 PEAK System + idProduct 0x000c PCAN-USB + bcdDevice 1c.ff + iManufacturer 0 + iProduct 3 VER1:PEAK +VER2:02.8.01 +DAT :06.05.2004 +TIME:09:35:37 + ... + iSerial 0 + bNumConfigurations 3 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 2 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 394mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 3 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 +Device Status: 0x0001 + Self Powered diff --git a/tools/src/dfu-util/device-logs/opc-20.lsusb b/tools/src/dfu-util/device-logs/opc-20.lsusb new file mode 100755 index 0000000..25ad12f --- /dev/null +++ b/tools/src/dfu-util/device-logs/opc-20.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 2.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 ÿÿÿÿÿÿÿÿÿÿÿÿ + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : M25P64/0x00000000/128*64Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1a.01 +Device Status: 0x0001 + Self Powered diff --git a/tools/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb b/tools/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb new file mode 100755 index 0000000..64bd018 --- /dev/null +++ b/tools/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb @@ -0,0 +1,109 @@ +Bus 003 Device 017: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 81 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 7 USB Device Firmware Upgrade + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 8 RAM 0x32000000 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 9 u-boot + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 10 u-boot_env + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 11 kernel + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 4 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 12 splash + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 5 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 13 factory + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 6 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 14 rootfs + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 +Device Status: 0x0a00 + (Bus Powered) diff --git a/tools/src/dfu-util/device-logs/openmoko-freerunner.lsusb b/tools/src/dfu-util/device-logs/openmoko-freerunner.lsusb new file mode 100755 index 0000000..cf148e5 --- /dev/null +++ b/tools/src/dfu-util/device-logs/openmoko-freerunner.lsusb @@ -0,0 +1,179 @@ +Bus 005 Device 033: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 USB Device Firmware Upgrade + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x9a00 + (Bus Powered) diff --git a/tools/src/dfu-util/device-logs/openmoko-neo1973.lsusb b/tools/src/dfu-util/device-logs/openmoko-neo1973.lsusb new file mode 100755 index 0000000..dc1fe7c --- /dev/null +++ b/tools/src/dfu-util/device-logs/openmoko-neo1973.lsusb @@ -0,0 +1,182 @@ + +Bus 006 Device 020: ID 1457:5119 First International Computer, Inc. OpenMoko Neo1973 u-boot cdc_acm serial port +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1457 First International Computer, Inc. + idProduct 0x5119 OpenMoko Neo1973 u-boot cdc_acm serial port + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 + iSerial 3 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x0006 + (Bus Powered) + Remote Wakeup Enabled + Test Mode diff --git a/tools/src/dfu-util/device-logs/openpcd.lsusb b/tools/src/dfu-util/device-logs/openpcd.lsusb new file mode 100755 index 0000000..8618647 --- /dev/null +++ b/tools/src/dfu-util/device-logs/openpcd.lsusb @@ -0,0 +1,60 @@ + +Bus 006 Device 016: ID 16c0:076b VOTI OpenPCD 13.56MHz RFID Reader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x076b OpenPCD 13.56MHz RFID Reader + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 OpenPCD RFID Simulator - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/tools/src/dfu-util/device-logs/qi-hardware-atusb.lsusb b/tools/src/dfu-util/device-logs/qi-hardware-atusb.lsusb new file mode 100755 index 0000000..d1da57a --- /dev/null +++ b/tools/src/dfu-util/device-logs/qi-hardware-atusb.lsusb @@ -0,0 +1,59 @@ + +Bus 006 Device 013: ID 20b7:1540 Qi Hardware ben-wpan, AT86RF230-based +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 255 Vendor Specific Class + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x20b7 Qi Hardware + idProduct 0x1540 ben-wpan, AT86RF230-based + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 1 4630333438371508231a + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 34 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 40mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 255 Vendor Specific Class + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 0 +Device Status: 0x0000 + (Bus Powered) diff --git a/tools/src/dfu-util/device-logs/simtrace.lsusb b/tools/src/dfu-util/device-logs/simtrace.lsusb new file mode 100755 index 0000000..fd51539 --- /dev/null +++ b/tools/src/dfu-util/device-logs/simtrace.lsusb @@ -0,0 +1,70 @@ + +Bus 006 Device 017: ID 16c0:0762 VOTI +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x0762 + bcdDevice 0.00 + iManufacturer 1 sysmocom - systems for mobile communications GmbH + iProduct 2 SimTrace SIM Sniffer - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 45 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 3 SimTrace DFU Configuration + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 SimTrace DFU Interface - Application Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 SimTrace DFU Interface - Bootloader Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 SimTrace DFU Interface - RAM + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/tools/src/dfu-util/device-logs/sparkcore.lsusb b/tools/src/dfu-util/device-logs/sparkcore.lsusb new file mode 100755 index 0000000..79c529b --- /dev/null +++ b/tools/src/dfu-util/device-logs/sparkcore.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 008: ID 1d50:607f OpenMoko, Inc. +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x607f + bcdDevice 2.00 + iManufacturer 1 Spark Devices + iProduct 2 CORE DFU + iSerial 3 8D80527B5055 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/20*001Ka,108*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : SST25x/0x00000000/512*04Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/tools/src/dfu-util/device-logs/stm32f107.bin-download b/tools/src/dfu-util/device-logs/stm32f107.bin-download new file mode 100755 index 0000000..4d803fb --- /dev/null +++ b/tools/src/dfu-util/device-logs/stm32f107.bin-download @@ -0,0 +1,48 @@ +> src/dfu-util --intf 0 --alt 0 -v -v -v -s 0x8000000 -D test3 +dfu-util 0.4 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Opening DFU USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/128*002Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +No valid DFU suffix signature +Warning: File has no DFU suffix +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 128 x 2048 = 262144 (rew) +Uploading to address = 0x08000000, size = 16384 +Erasing page size 2048 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 +Erasing page size 2048 at address 0x08000800, page starting at 0x08000800 + Download from image offset 00000800 to memory 08000800-08000fff, size 2048 + Setting address pointer to 0x08000800 +Erasing page size 2048 at address 0x08001000, page starting at 0x08001000 + Download from image offset 00001000 to memory 08001000-080017ff, size 2048 + Setting address pointer to 0x08001000 +Erasing page size 2048 at address 0x08001800, page starting at 0x08001800 + Download from image offset 00001800 to memory 08001800-08001fff, size 2048 + Setting address pointer to 0x08001800 +Erasing page size 2048 at address 0x08002000, page starting at 0x08002000 + Download from image offset 00002000 to memory 08002000-080027ff, size 2048 + Setting address pointer to 0x08002000 +Erasing page size 2048 at address 0x08002800, page starting at 0x08002800 + Download from image offset 00002800 to memory 08002800-08002fff, size 2048 + Setting address pointer to 0x08002800 +Erasing page size 2048 at address 0x08003000, page starting at 0x08003000 + Download from image offset 00003000 to memory 08003000-080037ff, size 2048 + Setting address pointer to 0x08003000 +Erasing page size 2048 at address 0x08003800, page starting at 0x08003800 + Download from image offset 00003800 to memory 08003800-08003fff, size 2048 + Setting address pointer to 0x08003800 + diff --git a/tools/src/dfu-util/device-logs/stm32f107.lsusb b/tools/src/dfu-util/device-logs/stm32f107.lsusb new file mode 100755 index 0000000..89d8d38 --- /dev/null +++ b/tools/src/dfu-util/device-logs/stm32f107.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 028: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 20.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 0x418 DFU Bootloader + iSerial 3 STM32 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/128*002Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFF800/01*016 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/tools/src/dfu-util/device-logs/stm32f4discovery.bin-download b/tools/src/dfu-util/device-logs/stm32f4discovery.bin-download new file mode 100755 index 0000000..d5a2679 --- /dev/null +++ b/tools/src/dfu-util/device-logs/stm32f4discovery.bin-download @@ -0,0 +1,36 @@ +dfu-util --device 0483:df11 --alt 0 \ + --dfuse-address 0x08000000 \ + -v -v -v \ + --download arm/iotoggle.bin +No valid DFU suffix signature +Warning: File has no DFU suffix +dfu-util 0.5 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Filter on vendor = 0x0483 product = 0xdf11 +Opening DFU capable USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuERROR, status = 10 +dfuERROR, clearing status +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 4 x 16384 = 65536 (rew) +Memory segment at 0x08010000 1 x 65536 = 65536 (rew) +Memory segment at 0x08020000 7 x 131072 = 917504 (rew) +Uploading to address = 0x08000000, size = 2308 +Erasing page size 16384 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 + Download from image offset 00000800 to memory 08000800-08000903, size 260 + Setting address pointer to 0x08000800 diff --git a/tools/src/dfu-util/device-logs/stm32f4discovery.lsusb b/tools/src/dfu-util/device-logs/stm32f4discovery.lsusb new file mode 100755 index 0000000..c78530c --- /dev/null +++ b/tools/src/dfu-util/device-logs/stm32f4discovery.lsusb @@ -0,0 +1,80 @@ + +Bus 001 Device 010: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 21.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 BOOTLOADER + iSerial 3 315A28A0B956 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 54 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFC000/01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 @OTP Memory /0x1FFF7800/01*512 g,01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 7 @Device Feature/0xFFFF0000/01*004 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/tools/src/dfu-util/device-logs/tdk-bluetooth.lsusb b/tools/src/dfu-util/device-logs/tdk-bluetooth.lsusb new file mode 100755 index 0000000..ac07bb7 --- /dev/null +++ b/tools/src/dfu-util/device-logs/tdk-bluetooth.lsusb @@ -0,0 +1,269 @@ + +Bus 006 Device 014: ID 04bf:0320 TDK Corp. Bluetooth Adapter +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 224 Wireless + bDeviceSubClass 1 Radio Frequency + bDeviceProtocol 1 Bluetooth + bMaxPacketSize0 64 + idVendor 0x04bf TDK Corp. + idProduct 0x0320 Bluetooth Adapter + bcdDevice 26.52 + iManufacturer 1 Ezurio + iProduct 2 Turbo Bluetooth Adapter + iSerial 3 008098D4FFBD + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 193 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 3 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 2 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 4 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 5 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 5000 milliseconds + wTransferSize 1023 bytes +Device Status: 0x0000 + (Bus Powered) diff --git a/tools/src/dfu-util/dfuse-pack.py b/tools/src/dfu-util/dfuse-pack.py new file mode 100755 index 0000000..022df6a --- /dev/null +++ b/tools/src/dfu-util/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(' and +Harald Welte . 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 COPYRIGHT +This manual page was originally written by Uwe Hermann , +and is now part of the dfu-util project. diff --git a/tools/src/dfu-util/msvc/README_msvc.txt b/tools/src/dfu-util/msvc/README_msvc.txt new file mode 100755 index 0000000..25aeeed --- /dev/null +++ b/tools/src/dfu-util/msvc/README_msvc.txt @@ -0,0 +1,10 @@ +# (C) Roger Meier +# (C) Pascal Schweizer +# msvc folder is GPL-2.0+, LGPL-2.1+, BSD-3-Clause or MIT license(SPDX) + +Building dfu-util native on Windows with Visual Studio + +3rd party dependencies: +- libusbx ( git clone https://github.com/libusbx/libusbx.git ) + - getopt (part of libusbx: libusbx/examples/getopt) + diff --git a/tools/src/dfu-util/msvc/dfu-suffix_2010.vcxproj b/tools/src/dfu-util/msvc/dfu-suffix_2010.vcxproj new file mode 100755 index 0000000..87b7ead --- /dev/null +++ b/tools/src/dfu-util/msvc/dfu-suffix_2010.vcxproj @@ -0,0 +1,100 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA} + dfusuffix + dfu-suffix + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/tools/src/dfu-util/msvc/dfu-util_2010.sln b/tools/src/dfu-util/msvc/dfu-util_2010.sln new file mode 100755 index 0000000..e6c932c --- /dev/null +++ b/tools/src/dfu-util/msvc/dfu-util_2010.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-util", "dfu-util_2010.vcxproj", "{0E071A60-7EF2-4427-BAA8-9143CACB5BCB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C4F8746D-B27E-4806-95E5-2052174E923B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-suffix", "dfu-suffix_2010.vcxproj", "{8F7600A2-3B37-4956-B39B-A1D43EF29EDA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt_2010", "..\..\libusbx\msvc\getopt_2010.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "..\..\libusbx\msvc\libusb_static_2010.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.Build.0 = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|x64.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.ActiveCfg = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.Build.0 = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|x64.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.Build.0 = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|x64.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.Build.0 = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|x64.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.ActiveCfg = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.Build.0 = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tools/src/dfu-util/msvc/dfu-util_2010.vcxproj b/tools/src/dfu-util/msvc/dfu-util_2010.vcxproj new file mode 100755 index 0000000..cb07b64 --- /dev/null +++ b/tools/src/dfu-util/msvc/dfu-util_2010.vcxproj @@ -0,0 +1,120 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB} + dfuutil + dfu-util + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + copy $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0.dll $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + + + + + + + + + + + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/tools/src/dfu-util/src/Makefile.am b/tools/src/dfu-util/src/Makefile.am new file mode 100755 index 0000000..b1f810a --- /dev/null +++ b/tools/src/dfu-util/src/Makefile.am @@ -0,0 +1,28 @@ +AM_CFLAGS = -Wall -Wextra + +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 \ + dfuse_mem.h \ + dfu.c \ + dfu.h \ + usb_dfu.h \ + dfu_file.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/tools/src/dfu-util/src/dfu.c b/tools/src/dfu-util/src/dfu.c new file mode 100755 index 0000000..050ad50 --- /dev/null +++ b/tools/src/dfu-util/src/dfu.c @@ -0,0 +1,357 @@ +/* + * 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). + * + * Copyright 2005-2006 Weston Schmidt + * Copyright 2011-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 + * 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 +#include + +#include + +#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) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * timeout - the timeout in ms the USB device should wait for a pending + * USB reset before giving up and terminating the operation + * + * returns 0 or < 0 on error + */ +int dfu_detach( libusb_device_handle *device, + const unsigned short interface, + const unsigned short timeout ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DETACH, + /* wValue */ timeout, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_DNLOAD Request (DFU Spec 1.0, Section 6.1.1) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the total number of bytes to transfer to the USB + * device - must be less than wTransferSize + * data - the data to transfer + * + * returns the number of bytes written or < 0 on error + */ +int dfu_download( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_UPLOAD Request (DFU Spec 1.0, Section 6.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the number of bytes received or < 0 on error + */ +int dfu_upload( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_GETSTATUS Request (DFU Spec 1.0, Section 6.1.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * status - the data structure to be populated with the results + * + * return the number of bytes read in or < 0 on an error + */ +int dfu_get_status( struct dfu_if *dif, struct dfu_status *status ) +{ + unsigned char buffer[6]; + int result; + + /* 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( dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATUS, + /* wValue */ 0, + /* wIndex */ dif->interface, + /* Data */ buffer, + /* wLength */ 6, + dfu_timeout ); + + if( 6 == result ) { + status->bStatus = buffer[0]; + 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]; + } + + return result; +} + + +/* + * DFU_CLRSTATUS Request (DFU Spec 1.0, Section 6.1.3) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * return 0 or < 0 on an error + */ +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT| LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_CLRSTATUS, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_GETSTATE Request (DFU Spec 1.0, Section 6.1.5) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the state or < 0 on error + */ +int dfu_get_state( libusb_device_handle *device, + const unsigned short interface ) +{ + int result; + unsigned char buffer[1]; + + result = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATE, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ buffer, + /* wLength */ 1, + dfu_timeout ); + + /* Return the error if there is one. */ + if (result < 1) + return -1; + + /* Return the state. */ + return buffer[0]; +} + + +/* + * DFU_ABORT Request (DFU Spec 1.0, Section 6.1.4) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * returns 0 or < 0 on an error + */ +int dfu_abort( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_ABORT, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +const char* dfu_state_to_string( int state ) +{ + const char *message; + + switch (state) { + case STATE_APP_IDLE: + message = "appIDLE"; + break; + case STATE_APP_DETACH: + message = "appDETACH"; + break; + case STATE_DFU_IDLE: + message = "dfuIDLE"; + break; + case STATE_DFU_DOWNLOAD_SYNC: + message = "dfuDNLOAD-SYNC"; + break; + case STATE_DFU_DOWNLOAD_BUSY: + message = "dfuDNBUSY"; + break; + case STATE_DFU_DOWNLOAD_IDLE: + message = "dfuDNLOAD-IDLE"; + break; + case STATE_DFU_MANIFEST_SYNC: + message = "dfuMANIFEST-SYNC"; + break; + case STATE_DFU_MANIFEST: + message = "dfuMANIFEST"; + break; + case STATE_DFU_MANIFEST_WAIT_RESET: + message = "dfuMANIFEST-WAIT-RESET"; + break; + case STATE_DFU_UPLOAD_IDLE: + message = "dfuUPLOAD-IDLE"; + break; + case STATE_DFU_ERROR: + message = "dfuERROR"; + break; + default: + message = NULL; + break; + } + + return message; +} + +/* Chapter 6.1.2 */ +static const char *dfu_status_names[] = { + /* DFU_STATUS_OK */ + "No error condition is present", + /* DFU_STATUS_errTARGET */ + "File is not targeted for use by this device", + /* DFU_STATUS_errFILE */ + "File is for this device but fails some vendor-specific test", + /* DFU_STATUS_errWRITE */ + "Device is unable to write memory", + /* DFU_STATUS_errERASE */ + "Memory erase function failed", + /* DFU_STATUS_errCHECK_ERASED */ + "Memory erase check failed", + /* DFU_STATUS_errPROG */ + "Program memory function failed", + /* DFU_STATUS_errVERIFY */ + "Programmed memory failed verification", + /* DFU_STATUS_errADDRESS */ + "Cannot program memory due to received address that is out of range", + /* DFU_STATUS_errNOTDONE */ + "Received DFU_DNLOAD with wLength = 0, but device does not think that it has all data yet", + /* DFU_STATUS_errFIRMWARE */ + "Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations", + /* DFU_STATUS_errVENDOR */ + "iString indicates a vendor specific error", + /* DFU_STATUS_errUSBR */ + "Device detected unexpected USB reset signalling", + /* DFU_STATUS_errPOR */ + "Device detected unexpected power on reset", + /* DFU_STATUS_errUNKNOWN */ + "Something went wrong, but the device does not know what it was", + /* DFU_STATUS_errSTALLEDPKT */ + "Device stalled an unexpected request" +}; + + +const char *dfu_status_to_string(int status) +{ + if (status > DFU_STATUS_errSTALLEDPKT) + return "INVALID"; + 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/tools/src/dfu-util/src/dfu.h b/tools/src/dfu-util/src/dfu.h new file mode 100755 index 0000000..39f18c3 --- /dev/null +++ b/tools/src/dfu-util/src/dfu.h @@ -0,0 +1,133 @@ +/* + * dfu-programmer + * + * $Id: dfu.h,v 1.2 2005/09/25 01:27:42 schmidtw Exp $ + * + * 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 + */ + +#ifndef DFU_H +#define DFU_H + +#include +#include "usb_dfu.h" + +/* DFU states */ +#define STATE_APP_IDLE 0x00 +#define STATE_APP_DETACH 0x01 +#define STATE_DFU_IDLE 0x02 +#define STATE_DFU_DOWNLOAD_SYNC 0x03 +#define STATE_DFU_DOWNLOAD_BUSY 0x04 +#define STATE_DFU_DOWNLOAD_IDLE 0x05 +#define STATE_DFU_MANIFEST_SYNC 0x06 +#define STATE_DFU_MANIFEST 0x07 +#define STATE_DFU_MANIFEST_WAIT_RESET 0x08 +#define STATE_DFU_UPLOAD_IDLE 0x09 +#define STATE_DFU_ERROR 0x0a + + +/* DFU status */ +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_ERROR_TARGET 0x01 +#define DFU_STATUS_ERROR_FILE 0x02 +#define DFU_STATUS_ERROR_WRITE 0x03 +#define DFU_STATUS_ERROR_ERASE 0x04 +#define DFU_STATUS_ERROR_CHECK_ERASED 0x05 +#define DFU_STATUS_ERROR_PROG 0x06 +#define DFU_STATUS_ERROR_VERIFY 0x07 +#define DFU_STATUS_ERROR_ADDRESS 0x08 +#define DFU_STATUS_ERROR_NOTDONE 0x09 +#define DFU_STATUS_ERROR_FIRMWARE 0x0a +#define DFU_STATUS_ERROR_VENDOR 0x0b +#define DFU_STATUS_ERROR_USBR 0x0c +#define DFU_STATUS_ERROR_POR 0x0d +#define DFU_STATUS_ERROR_UNKNOWN 0x0e +#define DFU_STATUS_ERROR_STALLEDPKT 0x0f + +/* DFU commands */ +#define DFU_DETACH 0 +#define DFU_DNLOAD 1 +#define DFU_UPLOAD 2 +#define DFU_GETSTATUS 3 +#define DFU_CLRSTATUS 4 +#define DFU_GETSTATE 5 +#define DFU_ABORT 6 + +/* DFU interface */ +#define DFU_IFF_DFU 0x0001 /* DFU Mode, (not Runtime) */ + +/* This is based off of DFU_GETSTATUS + * + * 1 unsigned byte bStatus + * 3 unsigned byte bwPollTimeout + * 1 unsigned byte bState + * 1 unsigned byte iString +*/ + +struct dfu_status { + unsigned char bStatus; + unsigned int bwPollTimeout; + unsigned char bState; + unsigned char iString; +}; + +struct dfu_if { + 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; +}; + +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( struct dfu_if *dif, + struct dfu_status *status ); +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ); +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); + +const char *dfu_state_to_string( int state ); + +const char *dfu_status_to_string( int status ); + +#endif /* DFU_H */ diff --git a/tools/src/dfu-util/src/dfu_file.c b/tools/src/dfu-util/src/dfu_file.c new file mode 100755 index 0000000..2f5a585 --- /dev/null +++ b/tools/src/dfu-util/src/dfu_file.c @@ -0,0 +1,444 @@ +/* + * Load or store DFU files including suffix and prefix + * + * Copyright 2014 Tormod Volden + * Copyright 2012 Stefan Schmidt + * + * 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 +#include +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +#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, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + +static uint32_t crc32_byte(uint32_t accum, uint8_t delta) +{ + return crc32_table[(accum ^ delta) & 0xff] ^ (accum >> 8); +} + +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 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; + int res; + + file->size.prefix = 0; + file->size.suffix = 0; + + /* default values, if no valid suffix is found */ + file->bcdDFU = 0; + file->idVendor = 0xffff; /* wildcard value */ + file->idProduct = 0xffff; /* wildcard value */ + file->bcdDevice = 0xffff; /* wildcard value */ + + /* default values, if no valid prefix is found */ + file->lmdfu_address = 0; + + free(file->firmware); + + if (!strcmp(file->name, "-")) { + int read_bytes; + +#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); + + offset = lseek(f, 0, SEEK_END); + + if ((int)offset < 0 || (int)offset != offset) + err(EX_IOERR, "File size is too big"); + + if (lseek(f, 0, SEEK_SET) != 0) + err(EX_IOERR, "Could not seek to beginning"); + + file->size.total = offset; + file->firmware = dfu_malloc(file->size.total); + + 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); + } + + /* 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 */ + + 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"); + } +} + +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; + + 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); + + /* write suffix, if any */ + if (write_suffix) { + uint8_t dfusuffix[DFU_SUFFIX_LENGTH]; + + 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/tools/src/dfu-util/src/dfu_file.h b/tools/src/dfu-util/src/dfu_file.h new file mode 100755 index 0000000..31c90b8 --- /dev/null +++ b/tools/src/dfu-util/src/dfu_file.h @@ -0,0 +1,60 @@ + +#ifndef DFU_FILE_H +#define DFU_FILE_H + +#include + +struct dfu_file { + /* File name */ + const char *name; + /* 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 */ + 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 +}; + +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 /* DFU_FILE_H */ diff --git a/tools/src/dfu-util/src/dfu_load.c b/tools/src/dfu-util/src/dfu_load.c new file mode 100755 index 0000000..d4ff51c --- /dev/null +++ b/tools/src/dfu-util/src/dfu_load.c @@ -0,0 +1,196 @@ +/* + * 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. + * + * Copyright 2007-2008 Harald Welte + * Copyright 2013 Hans Petter Selasky + * Copyright 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 + * 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 +#include +#include +#include + +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "quirks.h" + +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 = dfu_malloc(xfer_size); + + printf("Copying data from DFU device to PC\n"); + dfu_progress_bar("Upload", 0, 1); + + while (1) { + 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; + } + + 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; + } + dfu_progress_bar("Upload", total_bytes, expected_size); + } + ret = 0; + +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; +} + +int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file) +{ + int bytes_sent; + int expected_size; + unsigned char *buf; + unsigned short transaction = 0; + struct dfu_status dst; + int ret; + + printf("Copying data from PC to DFU device\n"); + + 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 = expected_size - bytes_sent; + if (bytes_left < xfer_size) + chunk_size = bytes_left; + else + chunk_size = xfer_size; + + ret = dfu_download(dif->dev_handle, dif->interface, + chunk_size, transaction++, chunk_size ? buf : NULL); + if (ret < 0) { + warnx("Error during download"); + goto out; + } + bytes_sent += chunk_size; + buf += chunk_size; + + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during download get_status"); + goto out; + } + + if (dst.bState == DFU_STATE_dfuDNLOAD_IDLE || + dst.bState == DFU_STATE_dfuERROR) + break; + + /* Wait while device executes flashing */ + milli_sleep(dst.bwPollTimeout); + + } while (1); + 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)); + ret = -1; + goto out; + } + 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, transaction, NULL); + if (ret < 0) { + errx(EX_IOERR, "Error sending completion packet"); + goto out; + } + + 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, &dst); + if (ret < 0) { + 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)); + + milli_sleep(dst.bwPollTimeout); + + /* FIXME: deal correctly with ManifestationTolerant=0 / WillDetach bits */ + switch (dst.bState) { + case DFU_STATE_dfuMANIFEST_SYNC: + case DFU_STATE_dfuMANIFEST: + /* some devices (e.g. TAS1020b) need some time before we + * can obtain the status */ + milli_sleep(1000); + goto get_status; + break; + case DFU_STATE_dfuIDLE: + break; + } + printf("Done!\n"); + +out: + return bytes_sent; +} diff --git a/tools/src/dfu-util/src/dfu_load.h b/tools/src/dfu-util/src/dfu_load.h new file mode 100755 index 0000000..fe363aa --- /dev/null +++ b/tools/src/dfu-util/src/dfu_load.h @@ -0,0 +1,7 @@ +#ifndef DFU_LOAD_H +#define DFU_LOAD_H + +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 /* DFU_LOAD_H */ diff --git a/tools/src/dfu-util/src/dfu_util.c b/tools/src/dfu-util/src/dfu_util.c new file mode 100755 index 0000000..d9ad2d0 --- /dev/null +++ b/tools/src/dfu-util/src/dfu_util.c @@ -0,0 +1,346 @@ +/* + * Functions for detecting DFU USB entities + * + * Written by Harald Welte + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013 Hans Petter Selasky + * + * 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 +#include +#include +#include +#include + +#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 +#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/tools/src/dfu-util/src/dfu_util.h b/tools/src/dfu-util/src/dfu_util.h new file mode 100755 index 0000000..24e50c1 --- /dev/null +++ b/tools/src/dfu-util/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/tools/src/dfu-util/src/dfuse.c b/tools/src/dfu-util/src/dfuse.c new file mode 100755 index 0000000..39bc72d --- /dev/null +++ b/tools/src/dfu-util/src/dfuse.c @@ -0,0 +1,652 @@ +/* + * 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. + * + * 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 + * 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 +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfuse.h" +#include "dfuse_mem.h" + +#define DFU_TIMEOUT 5000 + +extern int verbose; +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) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + errx(EX_IOERR, "%s: libusb_control_msg returned %d", + __FUNCTION__, status); + } + return status; +} + +/* DFU_DNLOAD request for DfuSe 1.1a */ +int dfuse_download(struct dfu_if *dif, const unsigned short length, + unsigned char *data, unsigned short transaction) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + 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; + int page_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_ERASABLE)) { + errx(EX_IOERR, "Page at 0x%08x can not be erased", + address); + } + page_size = segment->pagesize; + if (verbose > 1) + printf("Erasing page size %i at address 0x%08x, page " + "starting at 0x%08x\n", page_size, address, + address & ~(page_size - 1)); + buf[0] = 0x41; /* Erase command */ + length = 5; + last_erased_page = address & ~(page_size - 1); + } else if (command == SET_ADDRESS) { + if (verbose > 2) + printf(" Setting address pointer to 0x%08x\n", + address); + buf[0] = 0x21; /* Set Address Pointer command */ + length = 5; + } 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 { + errx(EX_IOERR, "Non-supported special command %d", command); + } + buf[1] = address & 0xff; + buf[2] = (address >> 8) & 0xff; + buf[3] = (address >> 16) & 0xff; + buf[4] = (address >> 24) & 0xff; + + ret = dfuse_download(dif, length, buf, 0); + if (ret < 0) { + errx(EX_IOERR, "Error during special command \"%s\" download", + dfuse_command_name[command]); + } + 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); + + if (dst.bStatus != DFU_STATUS_OK) { + errx(EX_IOERR, "%s not correctly executed", + dfuse_command_name[command]); + } + 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) { + errx(EX_IOERR, "Error during download"); + return ret; + } + 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; + } + return bytes_sent; +} + +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; + unsigned char *buf; + int transaction; + int ret; + + 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) + errx(EX_IOERR, "Failed to parse memory layout"); + + segment = find_segment(mem_layout, dfuse_address); + if (!dfuse_force && + (!segment || !(segment->memtype & DFUSE_READABLE))) + errx(EX_IOERR, "Page at 0x%08x is not readable", + dfuse_address); + + if (!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 { + /* 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); + } + + dfu_progress_bar("Upload", 0, 1); + + transaction = 2; + while (1) { + 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; + } + + 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; + } + dfu_progress_bar("Upload", total_bytes, upload_limit); + } + + 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); + + return ret; +} + +/* 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, + unsigned int dwElementSize, unsigned char *data, + int xfer_size) +{ + int p; + int ret; + struct memsegment *segment; + + /* Check at least that we can write to the last address */ + segment = + find_segment(mem_layout, dwElementAddress + dwElementSize - 1); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Last page at 0x%08x is not writeable", + dwElementAddress + dwElementSize - 1); + } + + 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; + int chunk_size = xfer_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Page at 0x%08x is not writeable", + address); + } + page_size = segment->pagesize; + + /* check if this is the last chunk */ + if (p + chunk_size > (int)dwElementSize) + chunk_size = dwElementSize - p; + + /* Erase only for flash memory downloads */ + 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) + dfuse_special_command(dif, + erase_address, + ERASE_PAGE); + + if (((address + chunk_size - 1) & ~(page_size - 1)) != + last_erased_page) { + if (verbose > 2) + printf(" Chunk extends into next page," + " erase it as well\n"); + dfuse_special_command(dif, + address + chunk_size - 1, + ERASE_PAGE); + } + } + + 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) { + 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) +{ + unsigned int dwElementAddress; + unsigned int dwElementSize; + unsigned char *data; + int ret; + + dwElementAddress = start_address; + 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; + + printf("File downloaded successfully\n"); + ret = dwElementSize; + + out_free: + 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) +{ + uint8_t dfuprefix[11]; + uint8_t targetprefix[274]; + uint8_t elementheader[8]; + int image; + int element; + int bTargets; + int bAlternateSetting; + int dwNbElements; + unsigned int dwElementAddress; + unsigned int dwElementSize; + uint8_t *data; + int ret; + int rem; + int bFirstAddressSaved = 0; + + rem = file->size.total - file->size.prefix - file->size.suffix; + data = file->firmware + file->size.prefix; + + /* 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) { + errx(EX_IOERR, "DFU format revision %i not supported", + dfuprefix[5]); + return -EINVAL; + } + bTargets = dfuprefix[10]; + printf("file contains %i DFU images\n", bTargets); + + for (image = 1; image <= bTargets; image++) { + printf("parsing DFU image %i\n", image); + 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]; + dwNbElements = quad2uint((unsigned char *)targetprefix + 270); + printf("image for alternate setting %i, ", bAlternateSetting); + printf("(%i elements, ", dwNbElements); + printf("total size = %i)\n", + quad2uint((unsigned char *)targetprefix + 266)); + if (bAlternateSetting != dif->altsetting) + printf("Warning: Image does not match current alternate" + " setting.\n" + "Please rerun with the correct -a option setting" + " to download this image!\n"); + for (element = 1; element <= dwNbElements; element++) { + printf("parsing element %i, ", element); + dfuse_memcpy(elementheader, &data, &rem, sizeof(elementheader)); + dwElementAddress = + quad2uint((unsigned char *)elementheader); + dwElementSize = + quad2uint((unsigned char *)elementheader + 4); + printf("address = 0x%08x, ", dwElementAddress); + printf("size = %i\n", dwElementSize); + + 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 { + ret = 0; + } + + /* advance read pointer */ + dfuse_memcpy(NULL, &data, &rem, dwElementSize); + + if (ret != 0) + return ret; + } + } + + if (rem != 0) + warnx("%d bytes leftover", rem); + + printf("done parsing DfuSe file\n"); + + return 0; +} + +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) { + errx(EX_IOERR, "Failed to parse memory layout"); + } + 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"); + } + 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) { + warnx("Only DfuSe file version 1.1a is supported"); + errx(EX_IOERR, "(for raw binary download, use the " + "--dfuse-address option)"); + } + 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/tools/src/dfu-util/src/dfuse.h b/tools/src/dfu-util/src/dfuse.h new file mode 100755 index 0000000..e82f058 --- /dev/null +++ b/tools/src/dfu-util/src/dfuse.h @@ -0,0 +1,35 @@ +/* This implements the ST Microsystems DFU extensions (DfuSe) + * as per the DfuSe 1.1a specification (Document UM0391) + * + * (C) 2010-2012 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 + */ + +#ifndef DFUSE_H +#define DFUSE_H + +#include "dfu.h" + +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, 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 /* DFUSE_H */ diff --git a/tools/src/dfu-util/src/dfuse_mem.c b/tools/src/dfu-util/src/dfuse_mem.c new file mode 100755 index 0000000..ae339fb --- /dev/null +++ b/tools/src/dfu-util/src/dfuse_mem.c @@ -0,0 +1,198 @@ +/* + * Helper functions for reading the memory map of a device + * following the ST DfuSe 1.1a specification. + * + * Copyright 2011-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 + * 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 +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" +#include "dfuse_mem.h" + +int add_segment(struct memsegment **segment_list, struct memsegment segment) +{ + struct memsegment *new_element; + + new_element = dfu_malloc(sizeof(struct memsegment)); + *new_element = segment; + new_element->next = NULL; + + if (*segment_list == NULL) + /* list can be empty on first call */ + *segment_list = new_element; + else { + struct memsegment *next_element; + + /* find last element in list */ + next_element = *segment_list; + while (next_element->next != NULL) + next_element = next_element->next; + next_element->next = new_element; + } + return 0; +} + +struct memsegment *find_segment(struct memsegment *segment_list, + unsigned int address) +{ + while (segment_list != NULL) { + if (segment_list->start <= address && + segment_list->end >= address) + return segment_list; + segment_list = segment_list->next; + } + return NULL; +} + +void free_segment_list(struct memsegment *segment_list) +{ + struct memsegment *next_element; + + while (segment_list->next != NULL) { + next_element = segment_list->next; + free(segment_list); + segment_list = next_element; + } + 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) +{ + + char multiplier, memtype; + unsigned int address; + int sectors, size; + char *name, *typestring; + int ret; + int count = 0; + char separator; + int scanned; + struct memsegment *segment_list = NULL; + struct memsegment segment; + + name = dfu_malloc(strlen(intf_desc)); + + ret = sscanf(intf_desc, "@%[^/]%n", name, &scanned); + if (ret < 1) { + free(name); + warnx("Could not read name, sscanf returned %d", ret); + return NULL; + } + printf("DfuSe interface name: \"%s\"\n", name); + + intf_desc += scanned; + typestring = dfu_malloc(strlen(intf_desc)); + + while (ret = sscanf(intf_desc, "/0x%x/%n", &address, &scanned), + ret > 0) { + + intf_desc += scanned; + while (ret = sscanf(intf_desc, "%d*%d%c%[^,/]%n", + §ors, &size, &multiplier, typestring, + &scanned), ret > 2) { + intf_desc += scanned; + + count++; + memtype = 0; + if (ret == 4) { + if (strlen(typestring) == 1 + && typestring[0] != '/') + memtype = typestring[0]; + else { + 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; + case 'K': + size *= 1024; + break; + case 'M': + size *= 1024 * 1024; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + if (!memtype) { + warnx("Non-valid multiplier '%c', " + "interpreted as type " + "identifier instead", + multiplier); + memtype = multiplier; + break; + } + /* fallthrough if memtype was already set */ + default: + warnx("Non-valid multiplier '%c', " + "assuming bytes", multiplier); + } + + if (!memtype) { + warnx("No valid type for segment %d\n", count); + continue; + } + + segment.start = address; + segment.end = address + sectors * size - 1; + segment.pagesize = size; + segment.memtype = memtype & 7; + add_segment(&segment_list, segment); + + if (verbose) + printf("Memory segment at 0x%08x %3d x %4d = " + "%5d (%s%s%s)\n", + address, sectors, size, sectors * size, + memtype & DFUSE_READABLE ? "r" : "", + memtype & DFUSE_ERASABLE ? "e" : "", + memtype & DFUSE_WRITEABLE ? "w" : ""); + + address += sectors * size; + + separator = *intf_desc; + if (separator == ',') + intf_desc += 1; + else + break; + } /* while per segment */ + + } /* while per address */ + free(name); + free(typestring); + + return segment_list; +} diff --git a/tools/src/dfu-util/src/dfuse_mem.h b/tools/src/dfu-util/src/dfuse_mem.h new file mode 100755 index 0000000..8fe7cc4 --- /dev/null +++ b/tools/src/dfu-util/src/dfuse_mem.h @@ -0,0 +1,44 @@ +/* Helper functions for reading the memory map in a device + * following the ST DfuSe 1.1a specification. + * + * (C) 2011 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 + */ + +#ifndef DFUSE_MEM_H +#define DFUSE_MEM_H + +#define DFUSE_READABLE 1 +#define DFUSE_ERASABLE 2 +#define DFUSE_WRITEABLE 4 + +struct memsegment { + unsigned int start; + unsigned int end; + int pagesize; + int memtype; + struct memsegment *next; +}; + +int add_segment(struct memsegment **list, struct memsegment new_element); + +struct memsegment *find_segment(struct memsegment *list, unsigned int address); + +void free_segment_list(struct memsegment *list); + +struct memsegment *parse_memory_layout(char *intf_desc_str); + +#endif /* DFUSE_MEM_H */ diff --git a/tools/src/dfu-util/src/main.c b/tools/src/dfu-util/src/main.c new file mode 100755 index 0000000..f59d27d --- /dev/null +++ b/tools/src/dfu-util/src/main.c @@ -0,0 +1,699 @@ +/* + * dfu-util + * + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013-2014 Hans Petter Selasky + * + * Written by Harald Welte + * + * 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 +#include +#include +#include +#include +#include +#include + +#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 +#endif + +int verbose = 0; + +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) +{ + 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; + } + } + return value; +} + +static void parse_vendprod(const char *str) +{ + const char *comma; + const char *colon; + + /* 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; + } + } + 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); + } +} + +static void parse_serial(char *str) +{ + char *comma; + + 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(char *path) +{ + int res; + + res = usb_path2devnum(path); + if (res < 0) + return -EINVAL; + if (!res) + return 0; + + match_bus = atoi(path); + match_device = res; + + return 0; +} + +#else /* HAVE_USBPATH_H */ + +static int resolve_device_path(char *path) +{ + (void)path; /* Eliminate unused variable warning */ + errx(EX_SOFTWARE, "USB device paths are not supported by this dfu-util.\n"); +} + +#endif /* !HAVE_USBPATH_H */ + +static void help(void) +{ + 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 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 :[,:]\n" + "\t\t\t\tSpecify Vendor/Product ID(s) of DFU device\n" + " -p --path \tSpecify path to DFU device\n" + " -c --cfg \t\tSpecify the Configuration of DFU device\n" + " -i --intf \t\tSpecify the DFU Interface number\n" + " -S --serial [,]\n" + "\t\t\t\tSpecify Serial String of DFU device\n" + " -a --alt \t\tSpecify the Altsetting of the DFU Interface\n" + "\t\t\t\tby name or by number\n"); + fprintf(stderr, " -t --transfer-size \tSpecify the number of bytes per USB Transfer\n" + " -U --upload \t\tRead firmware from device into \n" + " -Z --upload-size \tSpecify the expected upload size in bytes\n" + " -D --download \t\tWrite firmware from into device\n" + " -R --reset\t\t\tIssue USB Reset signalling once we're finished\n" + " -s --dfuse-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(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[] = { + { "help", 0, 0, 'h' }, + { "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' }, + { "cfg", 1, 0, 'c' }, + { "interface", 1, 0, 'i' }, + { "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' }, + { 0, 0, 0, 0 } +}; + +int main(int argc, char **argv) +{ + int expected_size = 0; + unsigned int transfer_size = 0; + enum mode mode = MODE_NONE; + struct dfu_status status; + libusb_context *ctx; + struct dfu_file file; + char *end; + int final_reset = 0; + int ret; + 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)); + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVvleE:d:p:c:i:a:S:t:U:D:Rs:Z:", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + mode = MODE_VERSION; + break; + case 'v': + verbose++; + break; + 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': + parse_vendprod(optarg); + break; + case 'p': + /* Parse device path */ + 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 */ + match_config_index = atoi(optarg); + break; + case 'i': + /* Interface */ + match_iface_index = atoi(optarg); + break; + case 'a': + /* Interface Alternate Setting */ + 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); + break; + case 'U': + mode = MODE_UPLOAD; + file.name = optarg; + break; + case 'Z': + expected_size = atoi(optarg); + break; + case 'D': + mode = MODE_DOWNLOAD; + file.name = optarg; + break; + case 'R': + final_reset = 1; + break; + case 's': + dfuse_options = optarg; + break; + default: + help(); + break; + } + } + + print_version(); + if (mode == MODE_VERSION) { + exit(0); + } + + if (mode == MODE_NONE) { + fprintf(stderr, "You need to specify one of -D or -U\n"); + help(); + } + + if (match_config_index == 0) { + /* Handle "-c 0" (unconfigured device) as don't care */ + match_config_index = -1; + } + + 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); + } + } + + 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(); + exit(0); + } + + 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 */ + 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"); + } + + /* We have exactly one device. Its libusb_device is now in dfu_root->dev */ + + 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); + + printf("Run-time device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + /* Transition from run-Time mode to DFU mode */ + 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(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface %d", + dfu_root->interface); + } + + 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: "); + + 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); + } + 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(dfu_root->dev_handle, + dfu_root->interface, 1000) < 0) { + warnx("error detaching"); + } + 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(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) + errx(EX_IOERR, "error resetting " + "after detach"); + } + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + if (dfu_clear_status(dfu_root->dev_handle, + dfu_root->interface) < 0) { + errx(EX_IOERR, "error clear_status"); + } + /* fall through */ + default: + warnx("WARNING: Runtime device already in DFU state ?!?"); + libusb_release_interface(dfu_root->dev_handle, + dfu_root->interface); + goto dfustate; + } + 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); + } + + /* 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"); + } + + /* 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 0 + 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(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface"); + } + + 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(dfu_root, &status ) < 0) { + errx(EX_IOERR, "error get_status"); + } + printf("state = %s, status = %d\n", + dfu_state_to_string(status.bState), status.bStatus); + + milli_sleep(status.bwPollTimeout); + + switch (status.bState) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + errx(EX_IOERR, "Device still in Runtime Mode!"); + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + 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(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. */ + 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); + + milli_sleep(status.bwPollTimeout); + } + + printf("DFU mode device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + 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( + 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"); + } + } + +#ifdef HAVE_GETPAGESIZE +/* autotools lie when cross-compiling for Windows using mingw32/64 */ +#ifndef __MINGW32__ + /* limitation of Linux usbdevio */ + if ((int)transfer_size > getpagesize()) { + transfer_size = getpagesize(); + printf("Limited transfer size to %i\n", transfer_size); + } +#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: + /* 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(dfu_root, transfer_size, + expected_size, fd) < 0) { + exit(1); + } + } + close(fd); + break; + + case MODE_DOWNLOAD: + 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 (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(dfu_root, transfer_size, &file) < 0) + exit(1); + } + break; + case MODE_DETACH: + if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { + warnx("can't detach"); + } + break; + default: + errx(EX_IOERR, "Unsupported mode: %u", mode); + break; + } + + if (final_reset) { + 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(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) { + errx(EX_IOERR, "error resetting after download"); + } + } + + libusb_close(dfu_root->dev_handle); + dfu_root->dev_handle = NULL; + libusb_exit(ctx); + + return (0); +} diff --git a/tools/src/dfu-util/src/portable.h b/tools/src/dfu-util/src/portable.h new file mode 100755 index 0000000..2609232 --- /dev/null +++ b/tools/src/dfu-util/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 +#else +# include +#endif /* HAVE_FTRUNCATE */ + +#ifdef HAVE_NANOSLEEP +# include +# 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 +#else +# include +# include +# 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 +#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/tools/src/dfu-util/src/prefix.c b/tools/src/dfu-util/src/prefix.c new file mode 100755 index 0000000..05692f9 --- /dev/null +++ b/tools/src/dfu-util/src/prefix.c @@ -0,0 +1,176 @@ +/* + * dfu-prefix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Uwe Bonnes + * + * 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 +#include +#include +#include +#include + +#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 \t\tCheck DFU prefix of \n" + " -D --delete \t\tDelete DFU prefix from \n" + " -a --add \t\tAdd DFU prefix to \n" + "In combination with -a:\n" + ); + fprintf(stderr, " -s --stellaris-address
Add TI Stellaris address prefix to \n" + "In combination with -D or -c:\n" + " -T --stellaris\t\tAct on TI Stellaris address prefix of \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/tools/src/dfu-util/src/quirks.c b/tools/src/dfu-util/src/quirks.c new file mode 100755 index 0000000..c90e585 --- /dev/null +++ b/tools/src/dfu-util/src/quirks.c @@ -0,0 +1,56 @@ +/* + * 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 + * 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 +#include "quirks.h" + +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) && + 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/tools/src/dfu-util/src/quirks.h b/tools/src/dfu-util/src/quirks.h new file mode 100755 index 0000000..3193f25 --- /dev/null +++ b/tools/src/dfu-util/src/quirks.h @@ -0,0 +1,27 @@ +#ifndef DFU_QUIRKS_H +#define DFU_QUIRKS_H + +#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 + +uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice); + +#endif /* DFU_QUIRKS_H */ diff --git a/tools/src/dfu-util/src/suffix.c b/tools/src/dfu-util/src/suffix.c new file mode 100755 index 0000000..ba02a01 --- /dev/null +++ b/tools/src/dfu-util/src/suffix.c @@ -0,0 +1,176 @@ +/* + * dfu-suffix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 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 + * 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 +#include +#include +#include +#include + +#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 \t\tCheck DFU suffix of \n" + " -a --add \t\tAdd DFU suffix to \n" + " -D --delete \t\tDelete DFU suffix from \n" + " -p --pid \t\tAdd product ID into DFU suffix in \n" + " -v --vid \t\tAdd vendor ID into DFU suffix in \n" + " -d --did \t\tAdd device ID into DFU suffix in \n" + " -S --spec \t\tAdd DFU specification ID into DFU suffix in \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/tools/src/dfu-util/src/usb_dfu.h b/tools/src/dfu-util/src/usb_dfu.h new file mode 100755 index 0000000..f6fe270 --- /dev/null +++ b/tools/src/dfu-util/src/usb_dfu.h @@ -0,0 +1,99 @@ +#ifndef USB_DFU_H +#define USB_DFU_H +/* USB Device Firmware Update Implementation for OpenPCD + * (C) 2006 by Harald Welte + * + * Protocol definitions for USB DFU + * + * This ought to be compliant to the USB DFU Spec 1.0 as available from + * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf + * + * 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 + +#define USB_DT_DFU 0x21 + +#ifdef _MSC_VER +# pragma pack(push) +# pragma pack(1) +#endif /* _MSC_VER */ +struct usb_dfu_func_descriptor { + 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) + 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 + +#define USB_TYPE_DFU (LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE) + +/* DFU class-specific requests (Section 3, DFU Rev 1.1) */ +#define USB_REQ_DFU_DETACH 0x00 +#define USB_REQ_DFU_DNLOAD 0x01 +#define USB_REQ_DFU_UPLOAD 0x02 +#define USB_REQ_DFU_GETSTATUS 0x03 +#define USB_REQ_DFU_CLRSTATUS 0x04 +#define USB_REQ_DFU_GETSTATE 0x05 +#define USB_REQ_DFU_ABORT 0x06 + +/* 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 +#define DFU_STATUS_errWRITE 0x03 +#define DFU_STATUS_errERASE 0x04 +#define DFU_STATUS_errCHECK_ERASED 0x05 +#define DFU_STATUS_errPROG 0x06 +#define DFU_STATUS_errVERIFY 0x07 +#define DFU_STATUS_errADDRESS 0x08 +#define DFU_STATUS_errNOTDONE 0x09 +#define DFU_STATUS_errFIRMWARE 0x0a +#define DFU_STATUS_errVENDOR 0x0b +#define DFU_STATUS_errUSBR 0x0c +#define DFU_STATUS_errPOR 0x0d +#define DFU_STATUS_errUNKNOWN 0x0e +#define DFU_STATUS_errSTALLEDPKT 0x0f + +enum dfu_state { + DFU_STATE_appIDLE = 0, + DFU_STATE_appDETACH = 1, + DFU_STATE_dfuIDLE = 2, + DFU_STATE_dfuDNLOAD_SYNC = 3, + DFU_STATE_dfuDNBUSY = 4, + DFU_STATE_dfuDNLOAD_IDLE = 5, + DFU_STATE_dfuMANIFEST_SYNC = 6, + DFU_STATE_dfuMANIFEST = 7, + DFU_STATE_dfuMANIFEST_WAIT_RST = 8, + DFU_STATE_dfuUPLOAD_IDLE = 9, + DFU_STATE_dfuERROR = 10 +}; + +#endif /* USB_DFU_H */ diff --git a/tools/src/dfu-util/www/build.html b/tools/src/dfu-util/www/build.html new file mode 100755 index 0000000..2e6de0c --- /dev/null +++ b/tools/src/dfu-util/www/build.html @@ -0,0 +1,147 @@ + + + + + + + Building dfu-util from source + + + + + + + + + +
+

How to build dfu-util from source

+ +

Prerequisites for building from git

+

Mac OS X

+

+First install MacPorts (and if you are on 10.6 or older, the Java Developer Package) and then run: +

+
+	sudo port install libusb-devel git-core
+
+ +

FreeBSD

+
+	sudo pkg_add -r git pkgconf
+
+ +

Ubuntu and Debian and derivatives

+
+	sudo apt-get build-dep dfu-util
+	sudo apt-get install libusb-1.0-0-dev
+
+ +

Get the source code and build it

+

+The first time you will have to clone the git repository: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	cd dfu-util
+
+

+If you later want to update to latest git version, just run this: +

+
+	make maintainer-clean
+	git pull
+
+

+To build the source: +

+
+	./autogen.sh
+	./configure  # on most systems
+	make
+
+ +

+If you are building on Mac OS X, replace the ./configure command with: +

+
+	./configure --libdir=/opt/local/lib --includedir=/opt/local/include  # on MacOSX only
+
+ +

+Your dfu-util binary will be inside the src folder. Use it from there, or install it to /usr/local/bin by running "sudo make install". +

+ +

Cross-building for Windows

+ +

+Windows binaries can be built in a MinGW +environment, on a Windows computer or cross-hosted in another OS. +To build it on a Debian or Ubuntu host, first install build dependencies: +

+
+	sudo apt-get build-dep libusb-1.0-0 dfu-util
+	sudo apt-get install mingw32
+
+ +

+The below example builds dfu-util 0.8 and libusb 1.0.19 from unpacked release +tarballs. If you instead build from git, you will have to run "./autogen.sh" +before running the "./configure" steps. +

+ +
+mkdir -p build
+cd libusb-1.0.19
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+# WINVER workaround needed for 1.0.19 only
+make CFLAGS="-DWINVER=0x0501"
+make install
+cd ..
+
+cd dfu-util-0.8
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+make
+make install
+cd ..
+
+The build files will now be in build/bin. +

+ +

Building on Windows using MinGW

+This assumes using release tarballs or having run ./autogen.sh on +the git sources. +
+cd libusb-1.0.19
+./configure --prefix=$HOME
+# WINVER workaround needed for 1.0.19 only
+# MKDIR_P setting should not really be needed...
+make CFLAGS="-DWINVER=0x0501" MKDIR_P="mkdir -p"
+make install
+cd ..
+
+cd dfu-util-0.8
+./configure USB_CFLAGS="-I$HOME/include/libusb-1.0" \
+            USB_LIBS="-L $HOME/lib -lusb-1.0" PKG_CONFIG=true
+make
+make install
+cd ..
+
+To link libusb statically into dfu-util.exe use instead of "make": +
+make LDFLAGS=-static
+
+The built executables (and DLL) will now be under $HOME/bin. + +

+[Back to dfu-util main page] +

+ +
+ + diff --git a/tools/src/dfu-util/www/dfu-util.1.html b/tools/src/dfu-util/www/dfu-util.1.html new file mode 100755 index 0000000..667a369 --- /dev/null +++ b/tools/src/dfu-util/www/dfu-util.1.html @@ -0,0 +1,411 @@ + + +Man page of DFU-UTIL + + +

DFU-UTIL(1)

+ +  +

NAME

+ +dfu-util - Device firmware update (DFU) USB programmer +  +

SYNOPSIS

+ + +
+
+dfu-util + +-l + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + + +
+dfu-util + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + +[-t + +size] + +[-Z + +size] + +[-s + +address] + +[-R] + +[-D|-U + +file] + + +
+dfu-util + +[-hV] + +
+  +

DESCRIPTION

+ +dfu-util + +is a program that implements the host (computer) side of the USB DFU +(Universal Serial Bus Device Firmware Upgrade) protocol. +

+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. +  +

OPTIONS

+ +
+
-l, --list + +
+List the currently attached DFU capable USB devices. +
-d, --device [Run-Time VENDOR]:[Run-Time PRODUCT][,[DFU Mode VENDOR]:[DFU Mode PRODUCT]] + +
+
+Specify run-time and/or DFU mode vendor and/or product IDs of the DFU device +to work with. VENDOR and PRODUCT 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. +

+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. +

+If only run-time IDs are specified (e.g. "--device 1457:51ab"), 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. +

+If only DFU mode IDs are specified (e.g. "--device ,951:26"), then all +run-time devices will be ignored, making it easy to target a specific device in +DFU mode. +

+If both run-time and DFU mode IDs are specified (e.g. "--device +1457:51ab,:2bc"), then unspecified DFU mode components will use the run-time +value specified. +

+Examples: +

+
--device 1457:51ab,951:26 + +
+
+ +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 +

+

--device 1457:51ab,:2bc + +
+
+ +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 +

+

--device 1457:51ab + +
+
+ +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 +

+

--device ,951:26 + +
+
+ +Work with a device in DFU mode with vendor ID 0x0951 and product ID 0x0026 +

+

--device *,- + +
+
+ +Work with any device in run-time mode, and ignore any device in DFU mode +

+

--device , + +
+
+ +Ignore any device in run-time mode, and Work with any device in DFU mode +
+
+ +
-p, --path BUS-PORT. ... .PORT + +
+Specify the path to the DFU device. +
-c, --cfg CONFIG-NR + +
+Specify the configuration of the DFU device. Note that this is only used for matching, the configuration is not set by dfu-util. +
-i, --intf INTF-NR + +
+Specify the DFU interface number. +
-a, --alt ALT + +
+Specify the altsetting of the DFU interface by name or by number. +
-S, --serial [Run-Time SERIAL][,[DFU Mode SERIAL]] + +
+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. +

+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. +

-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. +
-Z, --upload-size SIZE + +
+Specify the expected upload size, in bytes. +
-U, --upload FILE + +
+Read firmware from device into +FILE. + +
-D, --download FILE + +
+Write firmware from +FILE + +into device. +
-R, --reset + +
+Issue USB reset signalling after upload or download has finished. +
-s, --dfuse-address address + +
+Specify target address for raw binary download/upload on DfuSe devices. Do +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. +
-v, --verbose + +
+Print more information about dfu-util's operation. A second +-v + +will turn on verbose logging of USB requests. Repeat this option to further +increase verbosity. +
-h, --help + +
+Show a help text and exit. +
-V, --version + +
+Show version information and exit. +
+  +

EXAMPLES

+ +  +

Using dfu-util in the OpenMoko project

+ +(with the Neo1973 hardware) +

+ +Flashing the rootfs: +
+ + $ dfu-util -a rootfs -R -D /path/to/openmoko-devel-image.jffs2 + +

+ +Flashing the kernel: +
+ + $ dfu-util -a kernel -R -D /path/to/uImage + +

+ +Flashing the bootloader: +
+ + $ dfu-util -a u-boot -R -D /path/to/u-boot.bin + +

+ +Copying a kernel into RAM: +
+ + $ dfu-util -a 0 -R -D /path/to/uImage + +

+Once this has finished, the kernel will be available at the default load +address of 0x32000000 in Neo1973 RAM. +Note: + +You cannot transfer more than 2MB of data into RAM using this method. +

+  +

Using dfu-util with a DfuSe device

+ +

+ +Flashing a +.dfu + +(special DfuSe format) file to the device: +
+ + $ dfu-util -a 0 -D /path/to/dfuse-image.dfu + +

+ +Reading out 1 KB of flash starting at address 0x8000000: +
+ + $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin + +

+ +Flashing a binary file to address 0x8004000 of device memory and +ask the device to leave DFU mode: +
+ + $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin + + +  +

BUGS

+ +Please report any bugs to the dfu-util mailing list at +dfu-util@lists.gnumonks.org. + +Please use the +--verbose option (repeated as necessary) to provide more + +information in your bug report. +  +

SEE ALSO

+ +The dfu-util home page is +http://dfu-util.gnumonks.org + +  +

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. +  +

LICENCE

+ +dfu-util + +is covered by the GNU General Public License (GPL), version 2 or later. +  +

COPYRIGHT

+ +This manual page was originally written by Uwe Hermann <uwe@hermann-uwe.de>, +and is now part of the dfu-util project. +

+ +


+ 

Index

+
+
NAME
+
SYNOPSIS
+
DESCRIPTION
+
OPTIONS
+
EXAMPLES
+
+
Using dfu-util in the OpenMoko project
+
Using dfu-util with a DfuSe device
+
+
BUGS
+
SEE ALSO
+
HISTORY
+
LICENCE
+
COPYRIGHT
+
+
+This document was created by man2html, +using the doc/dfu-util.1 manual page from dfu-util 0.8.
+Time: 14:40:57 GMT, September 13, 2014 + + diff --git a/tools/src/dfu-util/www/dfuse.html b/tools/src/dfu-util/www/dfuse.html new file mode 100755 index 0000000..ebb9784 --- /dev/null +++ b/tools/src/dfu-util/www/dfuse.html @@ -0,0 +1,135 @@ + + + + + + DfuSe and dfu-util + + + + + + + + + +
+

Using dfu-util with DfuSe devices

+

DfuSe

+

+ DfuSe (DFU with ST Microsystems extensions) is a protocol based on + DFU 1.1. However, in expanding the functionality of the DFU protocol, + ST Microsystems broke all compatibility with the DFU 1.1 standard. + DfuSe devices report the DFU version as "1.1a". +

+

+ DfuSe can be used to download firmware and other data + from a host computer to a conforming device (or upload in the + opposite direction) over USB similar to standard DFU. +

+

+ The main difference from standard DFU is that the target address in + the device (flash) memory is specified by the host, so that a + download can be performed to parts of the device memory. The host + program is also responsible for erasing flash pages before they + are written to. +

+

.dfu files

+

+ A special file format is defined by ST Microsystems to carry firmware + for DfuSe devices. The file contains target information such as address + and alternate interface information in addition to the binary data. + Several blocks of binary data can be combined in one .dfu file. +

+

Alternate interfaces

+

+ Different memory locations of the device may have different + characteristics that the host program (dfu-util) has to take + into considerations, such as flash memory page size, read-only + versus read-write segments, the need to erase, and so on. + These parameters are reported by the device in the string + descriptors meant for describing the USB interfaces. + The host program decodes these strings to build a memory map of + the device. Different memory units or address spaces are listed + in separate alternate interface settings that must be selected + according to the memory unit to access. +

+

+ Note that dfu-util leaves it to the user to select alternate + interface. When parsing a .dfu file it will skip file segments + not matching the selected alternate interface. Also, some + DfuSe device firmware implementations ignore the setting of + alternate interface and deduct the memory unit from the + address, since they have no address space overlap. +

+

DfuSe special commands

+

+ DfuSe special commands are used by the host program during normal + downloads or uploads, such as SET_ADDRESS and ERASE_PAGE. Also + the normal DFU_DNLOAD and DFU_UPLOAD commands have special + implementations in DfuSe. + Many DfuSe devices also support commands to leave DFU mode, + read unprotect the flash memory or mass erase the flash memory. + dfu-util (from version 0.7) + supports adding "leave", "unprotect", or "mass-erase" + to the -s option argument to send such requests in combination + with a download request. These modifiers are separated with a colon. +

+

+ Some DfuSe devices have their DfuSe bootloader running from flash + memory. Erasing the whole flash memory would therefore destroy + the DfuSe bootloader itself and practically brick the device + for most users. Any use of modifiers such as "unprotect" + and "mass-erase" therefore needs to be combined with the "force" + modifer. This is not included in the examples, to not encourage + ignorant users to copy and paste such instructions and shoot + themselves in the foot. +

+

+ Devices based on for instance STM32F103 all run the bootloader + from flash, since there is no USB bootloader in ROM. +

+

+ For instance STM32F107, STM32F2xx and STM32F4xx devices have a + DfuSe bootloader in ROM, so the flash can be erased while + keeping the device available for USB DFU transfers as long + as the device designers use this built-in bootloader and have + not implemented another DfuSe bootloader in flash that the user is + dependent upon. +

+

+ Well-written bootloaders running from flash will report their + own memory region as read-only and not eraseable, but this does + not prevent dfu-util from sending a "unprotect" or "mass-erase" + request which overrides this, if the user insists. +

+

Example usage

+

+ Flashing a .dfu (special DfuSe format) file to the device: +

+
+         $ dfu-util -a 0 -D /path/to/dfuse-image.dfu
+	
+

+ Reading out 1 KB of flash starting at address 0x8000000: +

+
+         $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin
+	
+

+ Flashing a binary file to address 0x8004000 of device memory and ask + the device to leave DFU mode: +

+
+         $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin
+	
+

+ [Back to dfu-util main page] +

+ +
+ + diff --git a/tools/src/dfu-util/www/index.html b/tools/src/dfu-util/www/index.html new file mode 100755 index 0000000..9bb3223 --- /dev/null +++ b/tools/src/dfu-util/www/index.html @@ -0,0 +1,119 @@ + + + + + + dfu-util Homepage + + + + + + + + + +
+

dfu-util - Device Firmware Upgrade Utilities

+

Description

+

+ dfu-util is a host side implementation of the DFU 1.0 and DFU 1.1 specifications of the USB forum. + + DFU is intended to download and upload firmware to/from devices connected + over USB. It ranges from small devices like micro-controller boards + to mobile phones. Using dfu-util you can download firmware to your + DFU-enabled device or upload firmware from it. dfu-util has been + tested with the Openmoko Neo1973 and Freerunner and many other devices. +

+

+ See the manual page for examples of use. +

+

Supported Devices

+ +

Releases

+

+ Releases of the dfu-util software can be found in the + releases folder. + The current release is 0.8. +

+

+ We offer binaries for Microsoft Windows and some other platforms. + dfu-util uses libusb 1.0 to access your device, so + on Windows you have to register the device with the WinUSB driver + (alternatively libusb-win32 or libusbK), please see the libusbx wiki + for more details. +

+

+ Mac OS X users can also get dfu-util from Homebrew with "brew install dfu-util" or from MacPorts. +

+

+ Most Linux distributions ship dfu-util in binary packages for those + who do not want to compile dfu-util from source. + On Debian, Ubuntu, Fedora and Gentoo you can install it through the + normal software package tools. For other distributions +(namely OpenSuSe, Mandriva, and CentOS) Holger Freyther was kind enough to +provide binary packages through the Open Build Service. +

+

Development

+

+ Development happens in a GIT repository. Browse it via the web +interface or clone it with: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	
+

+ See our build instructions for how to + build the source on different platforms. +

+

License

+

+ This software is licensed under the GPL version 2. +

+

Contact

+

+ If you have questions about the development or use of dfu-util please + send an e-mail to our dedicated +mailing list for dfu-util. +

+

People

+

+ dfu-util was originally written by + Harald Welte partially based on code from + dfu-programmer 0.4 and is currently maintained by Stefan Schmidt and + Tormod Volden. +

+ +
+ + diff --git a/tools/src/dfu-util/www/simple.css b/tools/src/dfu-util/www/simple.css new file mode 100755 index 0000000..10b7c1d --- /dev/null +++ b/tools/src/dfu-util/www/simple.css @@ -0,0 +1,56 @@ +body { + margin: 10px; + font-size: 0.82em; + background-color: #EEE; +} + +h1 { + clear: both; + padding: 0 0 12px 0; + margin: 0; + font-size: 2em; + font-weight: bold; +} + +h2 { + clear: both; + margin: 0; + font-size: 1.5em; + font-weight: normal; +} + +h3 { + clear: both; + margin: 15px 0 0 0; + font-size: 1.0em; + font-weight: bold; +} + +p { + line-height: 20px; + padding: 8px 0 8px 0; + margin: 0; + font-size: 1.1em; +} + +pre { + white-space: pre-wrap; + background-color: #CCC; + padding: 3px; +} + +a:hover { + background-color: #DDD; +} + +#middlebox { + width: 600px; + margin: 0px auto; + text-align: left; +} + +#footer { + height: 100px; + padding: 28px 3px 0 0; + margin: 20px 0 20px 0; +}