pax_global_header00006660000000000000000000000064144523466740014531gustar00rootroot0000000000000052 comment=f23d6dfd6671b46cbf1279a61291f6fa18d7559e dfu-programmer-dfu-programmer-f23d6df/000077500000000000000000000000001445234667400201055ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/.gitattributes000066400000000000000000000000751445234667400230020ustar00rootroot00000000000000AUTHORS text ChangeLog text COPYING text NEWS text *.md textdfu-programmer-dfu-programmer-f23d6df/.github/000077500000000000000000000000001445234667400214455ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/.github/workflows/000077500000000000000000000000001445234667400235025ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/.github/workflows/build.yml000066400000000000000000000241251445234667400253300ustar00rootroot00000000000000name: Build dfu-programmer # concurrency: # group: ${{ github.workflow }}-${{ github.ref }} # cancel-in-progress: true on: push: # pull_request: jobs: Windows-x86: name: Windows x86 runs-on: windows-latest defaults: run: shell: C:/msys64/usr/bin/bash.exe --noprofile --norc -e -x -o pipefail {0} steps: - uses: actions/checkout@v3 - name: Override Version String if: "!startsWith(github.ref, 'refs/tags/v')" id: override shell: bash run: echo 'override=PACKAGE_STRING="dfu-programmer ${{ github.ref_name }} ${{ github.sha }}"' >> $GITHUB_OUTPUT - name: Get version if: startsWith(github.ref, 'refs/tags/v') id: version shell: bash run: echo version=${GITHUB_REF#refs/tags/v} >> $GITHUB_OUTPUT - name: Dependencies run: | # Fix issues with MSYS2 and cygwin tools conflicting by just using MSYS2 export PATH=/usr/bin:/usr/local/bin # While some of these are already available, they are cygwin versions which are incompatible with MSYS2 pacman --color always --noconfirm -S automake-wrapper autoconf-wrapper make mingw-w64-i686-gcc mingw-w64-i686-libusb - name: Bootstrap run: | export PATH=/usr/bin:/usr/local/bin:/mingw32/bin ./bootstrap.sh - name: Configure run: | export PATH=/usr/bin:/usr/local/bin:/mingw32/bin ./configure CFLAGS="-Werror -O2" --disable-dependency-tracking ${{ steps.override.outputs.override }} - name: Build run: | export PATH=/usr/bin:/usr/local/bin:/mingw32/bin make -j4 - name: Prep dist shell: pwsh run: | mkdir dist # The binary cp src/dfu-programmer.exe dist/ # The docs cp docs/dfu-programmer.html dist/ # Libusb 1.0 cp C:/msys64/mingw32/bin/libusb-1.0.dll dist/ cp C:/msys64/mingw32/share/licenses dist/ -Recurse - name: Upload dist as Build Artifact uses: actions/upload-artifact@v3.1.0 with: name: Windows x86 - dfu-programmer path: dist - name: Test shell: pwsh run: dist/dfu-programmer.exe --help - name: Make release archives of binaries if: startsWith(github.ref, 'refs/tags/v') shell: pwsh working-directory: dist run: | 7z a -tzip ../dfu-programmer-x86-${{ steps.version.outputs.version }}.zip * 7z a -t7z ../dfu-programmer-x86-${{ steps.version.outputs.version }}.7z * - name: Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/v') with: fail_on_unmatched_files: true files: | dfu-programmer-x86-${{ steps.version.outputs.version }}.zip dfu-programmer-x86-${{ steps.version.outputs.version }}.7z Windows-x64: name: Windows x64 runs-on: windows-latest defaults: run: shell: C:/msys64/usr/bin/bash.exe --noprofile --norc -e -x -o pipefail {0} steps: - uses: actions/checkout@v3 - name: Override Version String if: "!startsWith(github.ref, 'refs/tags/v')" id: override shell: bash run: echo 'override=PACKAGE_STRING="dfu-programmer ${{ github.ref_name }} ${{ github.sha }}"' >> $GITHUB_OUTPUT - name: Get version if: startsWith(github.ref, 'refs/tags/v') id: version shell: bash run: echo version=${GITHUB_REF#refs/tags/v} >> $GITHUB_OUTPUT - name: Dependencies run: | # Fix issues with MSYS2 and cygwin tools conflicting by just using MSYS2 export PATH=/usr/bin:/usr/local/bin # While some of these are already available, they are cygwin versions which are incompatible with MSYS2 pacman --color always --noconfirm -S automake-wrapper autoconf-wrapper make mingw-w64-x86_64-gcc mingw-w64-x86_64-libusb - name: Bootstrap run: | export PATH=/usr/bin:/usr/local/bin:/mingw64/bin ./bootstrap.sh - name: Configure run: | export PATH=/usr/bin:/usr/local/bin:/mingw64/bin ./configure CFLAGS="-Werror -O2" --disable-dependency-tracking ${{ steps.override.outputs.override }} - name: Build run: | export PATH=/usr/bin:/usr/local/bin:/mingw64/bin make -j4 - name: Prep dist shell: pwsh run: | mkdir dist # The binary cp src/dfu-programmer.exe dist/ # The docs cp docs/dfu-programmer.html dist/ # Libusb 1.0 cp C:/msys64/mingw64/bin/libusb-1.0.dll dist/ cp C:/msys64/mingw64/share/licenses dist/ -Recurse - name: Upload dist as Build Artifact uses: actions/upload-artifact@v3.1.0 with: name: Windows x64 - dfu-programmer path: dist - name: Test shell: pwsh run: dist/dfu-programmer.exe --help - name: Make release archives of binaries if: startsWith(github.ref, 'refs/tags/v') shell: pwsh working-directory: dist run: | 7z a -tzip ../dfu-programmer-x64-${{ steps.version.outputs.version }}.zip * 7z a -t7z ../dfu-programmer-x64-${{ steps.version.outputs.version }}.7z * - name: Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/v') with: fail_on_unmatched_files: true files: | dfu-programmer-x64-${{ steps.version.outputs.version }}.zip dfu-programmer-x64-${{ steps.version.outputs.version }}.7z Linux: name: Linux x64 runs-on: ubuntu-latest steps: - run: sudo apt-get install -y libusb-1.0-0-dev - uses: actions/checkout@v3 - name: Override Version String if: "!startsWith(github.ref, 'refs/tags/v')" id: override run: echo 'override=PACKAGE_STRING="dfu-programmer ${{ github.ref_name }} ${{ github.sha }}"' >> $GITHUB_OUTPUT - name: Get version if: startsWith(github.ref, 'refs/tags/v') id: version run: echo version=${GITHUB_REF#refs/tags/v} >> $GITHUB_OUTPUT - name: Get Changes if: startsWith(github.ref, 'refs/tags/v') id: changes run: | echo "## Changes" > CHANGES echo "" >> CHANGES sed -ne '2,/^== Release/p' NEWS | head -n -2 >> CHANGES - name: bootstrap run: ./bootstrap.sh - name: configure run: ./configure CFLAGS="-Werror -O2" --disable-dependency-tracking ${{ steps.override.outputs.override }} - name: make run: make -j4 - name: Test run: src/dfu-programmer --help - name: Upload Binary as Build Artifact uses: actions/upload-artifact@v3.1.0 with: name: Linux x64 - dfu-programmer binary path: src/dfu-programmer - name: make dist run: make -j4 dist - name: Upload Tarball as Build Artifact uses: actions/upload-artifact@v3.1.0 with: name: Linux x64 - dfu-programmer dist path: "*.tar.gz" - name: Make release archives of binaries if: startsWith(github.ref, 'refs/tags/v') working-directory: src run: | 7z a -tzip ../dfu-programmer-linux-${{ steps.version.outputs.version }}.zip dfu-programmer 7z a -t7z ../dfu-programmer-linux-${{ steps.version.outputs.version }}.7z dfu-programmer - name: Test Release Archives run: | mkdir -p test-build tar xzf dfu-programmer-*.tar.gz -C test-build cd test-build/dfu-programmer-* ./bootstrap.sh ./configure CFLAGS="-Werror -O2" --disable-dependency-tracking make -j4 src/dfu-programmer --help - name: Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/v') with: body_path: CHANGES fail_on_unmatched_files: true files: | dfu-programmer-*.tar.gz dfu-programmer-linux-${{ steps.version.outputs.version }}.zip dfu-programmer-linux-${{ steps.version.outputs.version }}.7z macOS: name: macOS x64 runs-on: macos-latest steps: - run: brew install automake - uses: actions/checkout@v3 - name: Override Version String if: "!startsWith(github.ref, 'refs/tags/v')" id: override run: echo 'override=PACKAGE_STRING="dfu-programmer ${{ github.ref_name }} ${{ github.sha }}"' >> $GITHUB_OUTPUT - name: Get version if: startsWith(github.ref, 'refs/tags/v') id: version run: echo version=${GITHUB_REF#refs/tags/v} >> $GITHUB_OUTPUT - name: bootstrap run: ./bootstrap.sh - name: configure run: ./configure CFLAGS="-Werror -O2" --disable-dependency-tracking ${{ steps.override.outputs.override }} - name: make run: make -j4 - name: Test run: src/dfu-programmer --help - name: Upload Binary as Build Artifact uses: actions/upload-artifact@v3.1.0 with: name: macOS - dfu-programmer binary path: src/dfu-programmer - name: make dist run: make -j4 dist - name: Upload Tarball as Build Artifact uses: actions/upload-artifact@v3.1.0 with: name: macOS - dfu-programmer dist path: "*.tar.gz" - name: Make release archives of binaries if: startsWith(github.ref, 'refs/tags/v') working-directory: src run: | 7z a -tzip ../dfu-programmer-macOS-${{ steps.version.outputs.version }}.zip dfu-programmer 7z a -t7z ../dfu-programmer-macOS-${{ steps.version.outputs.version }}.7z dfu-programmer - name: Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/v') with: fail_on_unmatched_files: true files: | dfu-programmer-macOS-${{ steps.version.outputs.version }}.zip dfu-programmer-macOS-${{ steps.version.outputs.version }}.7z dfu-programmer-dfu-programmer-f23d6df/.github/workflows/test.yml000066400000000000000000000012551445234667400252070ustar00rootroot00000000000000name: Test dfu-programmer with coverage reporting on: push: jobs: avr: # concurrency: # group: ${{ github.workflow }} # cancel-in-progress: true name: Test with AVR Test HAT on a Raspberry Pi runs-on: - self-hosted - avr-test-hat - linux steps: - uses: actions/checkout@v3 - run: ./bootstrap.sh - run: ./configure --disable-dependency-tracking CFLAGS="--coverage -O0" - run: make -j4 - run: npm install - run: npm test id: test - run: coveralls if: success() || steps.test.outcome == 'failure' env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} dfu-programmer-dfu-programmer-f23d6df/.gitignore000066400000000000000000000007731445234667400221040ustar00rootroot00000000000000# Files generate by autotools Makefile Makefile.in aclocal.m4 autom4te.cache configure config.status config.log fedora/dfu-programmer.spec src/.deps/* src/config.h src/config.h.in src/stamp-h1 # Output files src/*.o src/dfu-programmer # Hex files shouldn't generally be in the repo *.hex # No Windows libraries or executables *.dll *.exe # Ignore dist packages *.tar.gz # Node.js dependencies for testing /node_modules/ # tab completion file dfu_programmer # Autotools dir m4/ # Apple temp files *~ dfu-programmer-dfu-programmer-f23d6df/.vscode/000077500000000000000000000000001445234667400214465ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/.vscode/c_cpp_properties.json000066400000000000000000000002611445234667400257000ustar00rootroot00000000000000{ "configurations": [ { "name": "gcc", "defines": ["__VSCODE__"], "includePath": ["src"], "compilerPath": "C:/msys64/mingw64/bin/gcc.exe" } ], "version": 4 } dfu-programmer-dfu-programmer-f23d6df/.vscode/settings.json000066400000000000000000000001141445234667400241750ustar00rootroot00000000000000{ "files.associations": { "*.h": "c", "*.c": "c" } }dfu-programmer-dfu-programmer-f23d6df/AUTHORS000066400000000000000000000075251445234667400211660ustar00rootroot00000000000000Original Author: - Weston Schmidt Contributors: - Reinhard Arlt - at89c5131 chip support - Anton Blad - at90usb162 and at90usb82 chip support - David Brownell - compiler flag improvements - command line argument processing improvements - debugging system improvements - significant man page improvements - support for the at90usb series AVR chips - the beginnings of the move over to using stdint.h - Nick Hibma - bug fixes - Markus Schneider - OS X porting issues - Geoffrey Wossum - added reset command - Sean D'Epagnier - eeprom bug fix - 4K bootloader support fix - Peter Gammie - at90usb647 PID fix - Zachary Clifford - completed AVR32 support - identified a number of off-by-one errors waiting to happen - identified that AVR32 "User Pages" aren't supported yet - patch to allow proper handling of the trampoline code - patch to allow flashing user flash space & STDIN - patch to enable support for windows using mingw32 - patch to enable setting/getting fuses for the AVR32 devices - Donald Davis - patch with new AVR devices & testing of support for the devices - Brad Schick - identified that the flash memory overlaps the bootloader memory - identified the off-by-one issue when the bootloader is in upper memory - Xavier Leprevost - patch to fix an error in the avr32 user flash dump command - Dave Fletcher - patch to enable atmega32u2 chips - Torsten Rottmann - patch to enable libusb 1.0 support - Mitko - patch to enable at32uc3b1512 and at32uc3b0512 chips - Darren Gibbs - identified dead/bad code around the bootloader overlap checking - Holger Steinhaus - patch to enable atmega8u2 - Martin Guy - patch to enable automotive AVR32 flashing without a timeout - Walker Inman - bugfix flash user page for avr32 - add stm32 devices - add progress bar - update algorithm for converting hex and sending program - simplify command structure - add ability to dump to hex file (and hex2bin / bin2hex) - svn -> git migration - update --help -h text - also a lot of formatting updates (sorry) - More info in README - Add autocomplete for Ubuntu - Simon Large - fix atmel_reset function - get rid of compiler warnings around fprintf statements - fix build system for selecting libusb-1.0 - atmega16u2 support - better support for Windows users - improve layout of help text - add security fuse support for AVR32 - fix memory bounds for xmega devices - Johannes Carlsson - patch to fix use of libusb in configure.ac - Grégory S. - identified too-late check for null pointer - Dmitry Nedospasov - support for xmega devices - Kees Bakker - support for atxmega256a3bu - David Nelson - support for at32uc3a4256s - support for using a specific usb bus/address - support for device serialization - correction to --quiet output - Olivier Pisano - support for atxmega16c4 - Neels Hofmeyr - improvements to progress bar - John Szakmeister - Fix exit status of help-related options and improve start sequence - Alban Bedel - Fix infinite loop using rpl_malloc - Cameron Tacklind - GitHub Actions Configuration - Build libusb1 versions for Windows - Nicolas Brûlez (@N-Bz) - '--validate-first' and '--ignore-outside' options - Disabled progress bar when not using a tty - Peter Korsgaard (@jacmet) - Add '--erase-first' optiondfu-programmer-dfu-programmer-f23d6df/COPYING000066400000000000000000000431151445234667400211440ustar00rootroot00000000000000 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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. dfu-programmer-dfu-programmer-f23d6df/Makefile.am000066400000000000000000000005561445234667400221470ustar00rootroot00000000000000SUBDIRS = src docs dfu_programmer: dfu_completion update-bash-completion.sh src/arguments.c ./update-bash-completion.sh bash-completion: dfu_programmer .PHONY: bash-completion all: bash-completion EXTRA_DIST = bootstrap.sh EXTRA_DIST += dfu_completion EXTRA_DIST += fedora/10-dfu-programmer.fdi fedora/dfu-programmer.spec EXTRA_DIST += update-bash-completion.sh dfu-programmer-dfu-programmer-f23d6df/NEWS000066400000000000000000000132011445234667400206010ustar00rootroot00000000000000== Release 1.1.0 [2023-07-08] * Add `--erase-first` option * Fix missing `update-bash-completion.sh` #91 * Fix missing header files #93 #94 == Release 1.0.0 [2022-10-22] * Remove libusb0 support == Release 0.9.0 [2022-10-21] * Add `--validate-first` and `--ignore-outside` options to the flash command * Disabled progress bar when not using a tty == Release 0.8.1 [2022-10-13] * Fix bug preventing specifying a device with libusb0 * Fix bug in order device id was printed with libusb0 * Publish Windows binaries with libusb1 * Update libusb1 include path * Update uses of deprecated libusb1 functions == Release 0.8.0 [2016-01-19] * Experimental support for ST cortex M4 * Enable GitHub Actions for releases [2022-10-13] * Make `./bootstrap.sh` fail if any command fails (and print commands) * Update `configure.ac` features * Added IntelliSense hints for Visual Studio Code == Release 0.7.2 [2015-02-04] * Fix memory bounds used for XMega targets. == Release 0.7.1 [2015-01-03] * Fix use of mandatory filename ChangeLog in distribution tarball * Fix infinite loop in rpl_malloc * Add experimental support for autocomplete on Ubuntu * Fix exit status of help-related options and improve start sequence == Release 0.7.0 [2014-08-02] * Add support for atmega16c4 and atmega32c4 * Fix device erase for bootloaders which return busy status * Better include file defaults for libusb when run bootstrap is run without pkgconfig. * Improved status output * Add hex dump commands * Add blank memory check * Major rework of the flash/user/eeprom code * Replace start and reset commands with launch * Repository and website migrated to GitHub == Release 0.6.2 [2013-07-19] * Use correct default libusb-1.0 path * Workaround for "Device not found" errors == Release 0.6.1 [2013-04-04] * Added support for specifying a USB bus and address * Added support for device serialization * Fix packaging problem which failed to supply the default path for libusb-1.0 files when built on a machine without that package. * Clarified some error messages == Release 0.6.0 [2013-01-29] * Added support for xmega chips currently supported by FLIP * Do not attempt eeprom operations on devices without eeprom * Allow setting the security bit on AVR32 * Add HTML help file for Windows users * Added new commands --version, --help, --targets * Improved built in help text * Improved several error messages == Release 0.5.5 [2012-12-22] * Added support for atmega16u2 * Fixed operation of reset command * More reliable autoconf operation * Better support for Windows users * Fixed erase timeout for AVR32 == Release 0.5.4 [2011-09-22] * Update RPM sources and commit files previously missed. == Release 0.5.3 [2011-01-17] * Added support for a number of chips (at32uc3c series, atmega32u2, at32uc3b1512, at32uc3b0512 and atmega8u2). * Fixed a few off by 1 errors in flash verification & memory dumping. * Added libusb 1.0 support. * Applied a number of bug fixes. == Release 0.5.2 [2009-08-23] * Added ability to read from STDIN. * Added ability to configure AVR32 fuses. * Applied a number of bug fixes. * Fixed AVR device support. == Release 0.5.1 [2008-12-11] * Applied patch that fixes AVR32 support so that the trampoline code can be used. == Release 0.5.0 [2008-12-04] * All known Atmel USB AVR/8051/AVR32 chips are now supported. * A number of cross platform friendly code changes have been added. == Release 0.4.6 [2008-08-30] * Minor release changes - focused on changing the permission handling. code for fedora * This is the last planned 0.4.x release. The next release will be 0.5.0 and will be focused on better cross platform support (for windows, etc) in addition to new chips. == Release 0.4.5 [2008-08-21] * Added support for 4K bootloaders on supported chips. * Added support for eeprom-dump and eeprom-flash on supported chips. == Release 0.4.4 [2007-11-20] * Added new reset command * Added out of the box permission changes to allow the console owner to flash a device without needing to be root. == Release 0.4.3 [2007-08-13] * Added support for the at90usb162 and at90usb82 chips. * Applied patch for incorrect status string conversion. == Release 0.4.2 [2007-07-07] * Minor spec file changes to be Fedora compliant == Release 0.4.1 [2007-04-30] * Added support for flashing both memory pages for the at90usb128x chips. * Updated the man page. == Release 0.4.0 [2007-01-27] * Major set of fixes added for the at90xxx chips. * Optimized the flashing algorithm that only flashes the blocks needed based on the data being flashed, instead of flashing the entire chip each time (potentially saves s good deal of time during development) * The chip should be initialized better than before, increasing the likelihood of a successful operation. * Refined the code to allow OS X to compile and run dfu-programmer. == Release 0.3.1 [2006-10-22] * Minor documentation changes and polishing of the spec file to get the project inline with what is needed to be part of the fedora extras. == Release 0.3.0 [2006-06-20] * Added support for (AVR) at90usb1287, at90usb1286, at90usb647, at90usb646 chips. * Fixes a minor validation bug where the last byte of flash was not being correctly validated. == Release 0.2.2 [2006-05-07] * Minor bug fix for a segmentation fault if only the usage is displayed. == Release 0.2.1 [2005-11-21] * Minor bug fixes and documentation updates. == Release 0.2.0 [2005-09-25] * Limited support for the at89c5132, at89c5131 and at89c5130 chip is added. where the known limitations now have to do with P1_CF, P3_CF, P4_CF not being supported (read or write). == Release 0.1 * Initial release dfu-programmer-dfu-programmer-f23d6df/README.md000066400000000000000000000121641445234667400213700ustar00rootroot00000000000000# dfu-programmer dfu-programmer is an implementation of the Device Firmware Upgrade class USB driver that enables firmware upgrades for various USB enabled (with the correct bootloader) Atmel chips. This program was created because the Atmel "FLIP" program for flashing devices does not support flashing via USB on Linux, and because standard DFU loaders do not work for Atmel's chips. Check out the Atmel website for more information. They are kind enough to provide generally correct specifications this implementation is based on. The project website is http://dfu-programmer.github.io and you can use that to check for updates. All official [builds](https://github.com/dfu-programmer/dfu-programmer/actions) and [releases](https://github.com/dfu-programmer/dfu-programmer/releases) are on [GitHub](https://github.com/dfu-programmer/dfu-programmer). [![Build dfu-programmer](https://github.com/dfu-programmer/dfu-programmer/actions/workflows/build.yml/badge.svg)](https://github.com/dfu-programmer/dfu-programmer/actions/workflows/build.yml) [![Coverage Status](https://coveralls.io/repos/github/dfu-programmer/dfu-programmer/badge.svg?branch=master)](https://coveralls.io/github/dfu-programmer/dfu-programmer?branch=master) ## Simple install procedure for Unix/Linux/MAC ```bash tar -xzf dfu-programmer-.tar.gz # unpack the sources ``` _or_ ```bash git clone https://github.com/dfu-programmer/dfu-programmer.git ``` ```bash cd dfu-programmer # change to the top-level directory ``` > If the source was checked-out from GitHub, run the following command. > You may also need to do this if your libusb is in a non-standard location, or if the build fails to find it for some reason. > This command requires that `autoconf` is installed (`sudo apt-get install autoconf`). > > ```bash > ./bootstrap.sh # regenerate base config files > ``` ```bash ./configure # regenerate configure and run it ``` > Optionally you can specify where dfu-programmer gets installed using the `--prefix=` option to the `./configure` command. > See `./configure --help` for more details. > If usb library is not available try getting `sudo apt-get install libusb-1.0-0-dev`. ```bash make # build dfu-programmer sudo make install # install dfu-programmer ``` > Instructions for installing autocompletion will also be displayed during `make` (or `make bash-completion`). ## Build procedure for Windows Building Windows apps from source is never quite as simple... Firstly you need to have MinGW and MSys with developer tools. Get them from http://sourceforge.net/projects/mingw/files/. See `.github/workflows/build.yml` for examples of building on Windows and the needed tools. If you install the correct package with `pacman`, header and lib files will be installed in the correct locations. - **32-bit:** `pacman -S mingw-w64-i686-libusb` - **64-bit:** `pacman -S mingw-w64-x86_64-libusb` Follow the same install instructions as above. ## Windows Driver Files Windows's built-in WinUSB driver should work out of the box. ### Atmel FLIP Atmel's [FLIP programmer](https://www.microchip.com/en-us/development-tool/flip) also uses libusb-win32, so we can take advantage of Atmel's official certified drivers. ### Zadig [Zadig](https://zadig.akeo.ie) is another popular tool for managing the current USB driver for devices on your system. It can be used to install the libusb-win32, libusbK, WinUSB, or "USB Serial (CDC)" drivers. All but "USB Serial (CDC)" will work with dfu-programmer. ## Testing & Coverage Since most testing depends on hardware, we've set up a custom GitHub Action Runner on a dedicated Raspberry Pi. Read more about the tests [here](test/README.md). ## Currently Supported Chips
8051 based controllers - at89c51snd1c - at89c51snd2c - at89c5130 - at89c5131 - at89c5132
AVR based controllers - at90usb1287 - at90usb1286 - at90usb1287-4k - at90usb1286-4k - at90usb647 - at90usb646 - at90usb162 - at90usb82 - atmega32u6 - atmega32u4 - atmega32u2 - atmega16u4 - atmega16u2 - atmega8u2
AVR32 based controllers - at32uc3a0128 - at32uc3a1128 - at32uc3a0256 - at32uc3a1256 - at32uc3a0512 - at32uc3a1512 - at32uc3a0512es - at32uc3a1512es - at32uc3a364 - at32uc3a364s - at32uc3a3128 - at32uc3a3128s - at32uc3a3256 - at32uc3a3256s - at32uc3a4256s - at32uc3b064 - at32uc3b164 - at32uc3b0128 - at32uc3b1128 - at32uc3b0256 - at32uc3b1256 - at32uc3b0256es - at32uc3b1256es - at32uc3b0512 - at32uc3b1512 - at32uc3c064 - at32uc3c0128 - at32uc3c0256 - at32uc3c0512 - at32uc3c164 - at32uc3c1128 - at32uc3c1256 - at32uc3c1512 - at32uc3c264 - at32uc3c2128 - at32uc3c2256 - at32uc3c2512
XMEGA based controllers - atxmega64a1u - atxmega128a1u - atxmega64a3u - atxmega128a3u - atxmega192a3u - atxmega256a3u - atxmega16a4u - atxmega32a4u - atxmega64a4u - atxmega128a4u - atxmega256a3bu - atxmega64b1 - atxmega128b1 - atxmega64b3 - atxmega128b3 - atxmega64c3 - atxmega128c3 - atxmega256c3 - atxmega384c3 - atxmega16c4 - atxmega32c4
Experimental support for ST cortex M4 - stm32f4_B - stm32f4_C - stm32f4_E - stm32f4_G
dfu-programmer-dfu-programmer-f23d6df/SF_ReadMe.txt000066400000000000000000000011271445234667400223740ustar00rootroot00000000000000dfu-programmer-x.x.x.tar.gz contains the source tree for this project. Download this to build and install on a Linux/Unix/Mac system. dfu-programmer-win-x.x.x.zip contains the pre-compiled Windows executable and the USB drivers for use with Atmel chips in DFU bootloader mode. The Windows executable does not need any installation or setup. Just extract the executable and run it. The Windows driver can be installed when prompted by Windows when a DFU device is attached. Do not let Windows search for a driver; specify the path to search for a driver and point it to the .inf file. dfu-programmer-dfu-programmer-f23d6df/bootstrap.sh000077500000000000000000000002471445234667400224640ustar00rootroot00000000000000#! /bin/sh set -e # exit on error set -x # Enable echoing of commands mkdir -p m4 aclocal -I m4 autoheader automake --foreign --add-missing --force-missing autoconf dfu-programmer-dfu-programmer-f23d6df/cSpell/000077500000000000000000000000001445234667400213275ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/cSpell/dependencies.txt000066400000000000000000000005311445234667400245150ustar00rootroot00000000000000# Words from dependencies # libusb libusb interfaceClass altSetting # Atmel atmel atmega atxmega eeprom bootsz xmega # Linux commands lsusb automake aclocal pkgConfig udev ihex msys noProfile noRC pipeFail cygwin pacman noConfirm pwsh tzip stdint fprintf malloc JTAG uucp mflags buildRoot defattr binDir manDir fixint rpms zadig dfu-programmer-dfu-programmer-f23d6df/cSpell/export.txt000066400000000000000000000001071445234667400234070ustar00rootroot00000000000000# Words and names others should expect to use when calling the module dfu-programmer-dfu-programmer-f23d6df/cSpell/names.txt000066400000000000000000000004371445234667400231770ustar00rootroot00000000000000# Names of people Arlt Bakker Bergmans Blad Brownell Brûlez Carlsson D'Epagnier Dmitry Gammie Gnomovision Grégory Hibma Hofmeyr Holger Inman Kees Leprevost Markus Mitko Nedospasov Neels Reinhard Rottmann schmidtw softprops Steinhaus suisei Szakmeister Tacklind Torsten Wossum Yoyodyne dfu-programmer-dfu-programmer-f23d6df/cSpell/words.txt000066400000000000000000000005501445234667400232260ustar00rootroot00000000000000# Words we're using devnum STALLEDPKT Bitstuff USBR GETSTATUS DNLOAD CLRSTATUS GETSTATE noreset bootloader bootloaders eflash getfuse setfuse edump udump setsecure epfl bootprot bodlevel bodhyst boden datasheet hexbytes hexdigit hexdigits microcontroller microcontrollers getsecure tmpPath devel destDir dataDir thirdParty buin extdf ucDFU unProtect rjmp rNumdfu-programmer-dfu-programmer-f23d6df/configure.ac000066400000000000000000000016161445234667400223770ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) AC_INIT([dfu-programmer],[1.1.0],[https://github.com/dfu-programmer/dfu-programmer/issues],[],[https://dfu-programmer.github.io/]) AC_CONFIG_AUX_DIR(m4) AC_CONFIG_SRCDIR([src/atmel.c]) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([src/config.h]) AM_MAINTAINER_MODE # Checks for programs. AC_PROG_CC # Checks for header files. AC_CHECK_HEADERS([stddef.h stdint.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_MEMCMP #AC_CHECK_FUNC([memset], :, [AC_CHECK_LIB([libc], [libc])]) # Checks for libusb. AC_SEARCH_LIBS(libusb_init, usb-1.0,, [AC_MSG_ERROR([libusb 1.0 not found])]) AC_CONFIG_FILES(fedora/dfu-programmer.spec Makefile docs/Makefile src/Makefile) AC_OUTPUT dfu-programmer-dfu-programmer-f23d6df/cspell.yml000066400000000000000000000006331445234667400221140ustar00rootroot00000000000000version: 0.2 language: en relative: true ignorePaths: - '**/*.svg' - .vscode/extensions.json - .git dictionaries: - en_US - filetypes - names - export - words - dependencies dictionaryDefinitions: - name: names path: ./cSpell/names.txt - name: export path: ./cSpell/export.txt - name: words path: ./cSpell/words.txt - name: dependencies path: ./cSpell/dependencies.txt dfu-programmer-dfu-programmer-f23d6df/dfu_completion000066400000000000000000000106241445234667400230420ustar00rootroot00000000000000# dfu_completion file, partial of dfu_programmer script TARGETS=$( echo $TARGET_INFO | sed 's/::[xX0-9A-Fa-f]*//g' ) COMMANDS=(launch read erase flash setsecure config get getfuse setfuse hex2bin bin2hex) _dfu-programmer () { local i filetype local cur cmd prev target local flags local eeprom_size export cur=${COMP_WORDS[COMP_CWORD]} export target=${COMP_WORDS[1]} export cmd=${COMP_WORDS[2]} export prev=${COMP_WORDS[COMP_CWORD - 1]} COMPREPLY=() # Array variable storing the possible completions. if [[ "$COMP_CWORD" == "1" ]]; then COMPREPLY=( $( compgen -W "$TARGETS" -- $cur ) ) fi if [[ "$COMP_CWORD" == "2" ]]; then COMPREPLY=( $( compgen -W "${COMMANDS[*]}" -- $cur ) ) fi if [[ "$COMP_CWORD" > "2" ]]; then case "$cmd" in hex2bin) filetype="hex" if [[ $filetype != none ]]; then #COMPREPLY+=( $( compgen -f -X "!*.$filetype" -- $cur ) ) COMPREPLY+=( $( compgen -o plusdirs -f -X "!*.$filetype" -- $cur ) ) fi # make sure there isn't a trailing space for directories if [[ ${#COMPREPLY[@]} == 1 ]]; then if [[ -d ${COMPREPLY[0]} ]]; then COMPREPLY[0]=$( echo ${COMPREPLY[0]} | sed 's/$/\//' ) # If there's only one option, without =, then allow a space compopt -o nospace fi if [[ ${COMPREPLY[0]} == "--"*"=" ]]; then compopt -o nospace fi fi ;; bin2hex) ;; launch) if [[ "$COMP_CWORD" == "3" ]]; then COMPREPLY=( $( compgen -W '--no-reset' -- $cur ) ) fi ;; read) # only either user or eeprom should be displayed based on if device has # either feature -- or either one is selected when both features exist flags="--force --user --eeprom --bin" eeprom_size=$( echo $TARGET_INFO | sed "s/.* $target:://" | sed 's/ .*//' ) if [[ "$eeprom_size" == 0 ]]; then flags=$( echo $flags | sed 's/--eeprom//' ) fi COMPREPLY=( $( compgen -W "$flags" -- $cur ) ) ;; erase) COMPREPLY=( $( compgen -W '--force --suppress-validation' -- $cur ) ) ;; flash) filetype="hex" flags="--force --user --eeprom --bin --suppress-validation --suppress-bootloader-mem --validate-first --ignore-outside --serial=" eeprom_size=$( echo $TARGET_INFO | sed "s/.* $target:://" | sed 's/ .*//' ) if [[ "$eeprom_size" == 0 ]]; then flags=$( echo $flags | sed 's/--eeprom//' ) fi for (( i = 3; i < COMP_CWORD; i++ )); do if [[ "${COMP_WORDS[i]}" == *.@(bin|hex) ]]; then filetype="none" flags=$( echo $flags | sed 's/--bin//' ) elif [[ "${COMP_WORDS[i]}" == --bin ]]; then if [[ filetype != none ]]; then filetype="bin" fi flags=$( echo $flags | sed 's/--bin//' ) elif [[ "${COMP_WORDS[i]}" == --@(user|eeprom) ]]; then flags=$( echo $flags | sed 's/--user//' ) flags=$( echo $flags | sed 's/--eeprom//' ) else flags=$( echo $flags | sed "s/${COMP_WORDS[i]}//" ) fi done COMPREPLY=( $( compgen -W "$flags" -- $cur ) ) if [[ $filetype != none ]]; then #COMPREPLY+=( $( compgen -f -X "!*.$filetype" -- $cur ) ) COMPREPLY+=( $( compgen -o plusdirs -f -X "!*.$filetype" -- $cur ) ) fi #if [[ ${#COMPREPLY[@]} == 1 && ${COMPREPLY[0]} != "--"*"=" ]] ; then # make sure there isn't a trailing space for directories if [[ ${#COMPREPLY[@]} == 1 ]]; then if [[ -d ${COMPREPLY[0]} ]]; then COMPREPLY[0]=$( echo ${COMPREPLY[0]} | sed 's/$/\//' ) # If there's only one option, without =, then allow a space compopt -o nospace fi if [[ ${COMPREPLY[0]} == "--"*"=" ]]; then compopt -o nospace fi fi ;; setsecure) ;; configure) ;; get) ;; getfuse) COMPREPLY=( $( compgen -W 'LOCK EPFL BOOTPROT BODLEVEL BODHYST BODEN ISP_BOD_EN ISP_IO_COND_EN ISP_FORCE' -- $cur ) ) ;; setfuse) COMPREPLY=( $( compgen -W 'LOCK EPFL BOOTPROT BODLEVEL BODHYST BODEN ISP_BOD_EN ISP_IO_COND_EN ISP_FORCE' -- $cur ) ) ;; esac fi return 0 } complete -F _dfu-programmer dfu-programmer dfu-programmer-dfu-programmer-f23d6df/docs/000077500000000000000000000000001445234667400210355ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/docs/Makefile.am000066400000000000000000000000661445234667400230730ustar00rootroot00000000000000man_MANS = dfu-programmer.1 EXTRA_DIST = $(man_MANS) dfu-programmer-dfu-programmer-f23d6df/docs/dfu-programmer.1000066400000000000000000000232201445234667400240450ustar00rootroot00000000000000.TH DFU\-PROGRAMMER 1 "May 28, 2014" "DFU\-PROGRAMMER" "" .SH NAME dfu\-programmer \- USB firmware upgrading for Atmel microcontrollers .nh .SH SYNOPSIS .B dfu\-programmer target[:usb\-bus,usb\-addr] command [options] [parameters] .br .B dfu\-programmer \-\-help .br .B dfu\-programmer \-\-targets .br .B dfu\-programmer \-\-version .SH DESCRIPTION .B dfu\-programmer is a multi\-platform command line Device Firmware Upgrade (DFU) based programmer for the flash memory on Atmel AVR, AVR32, XMEGA and 8051 based microcontrollers which ship with a USB boot loader. It supports In System Programming (ISP) for developers and potentially product updates in the field. Those boot loaders are patterned after the standard USB DFU 1.0 class specification, but depend on extensions defined by Atmel to the extent that standard DFU drivers will not work. .PP To use it, first connect the device to be programmed and ensure that it comes up in DFU mode. The microcontrollers come up in that mode as shipped by Atmel; or they may reenter that mode after a special hardware reset. Then invoke this program to issue one or more DFU commands. You will normally need to start by issuing the "erase" command; the default security policies prevent extracting firmware, to prevent reverse engineering of what is usually proprietary code. .SH SUPPORTED MICROCONTROLLERS These chip names are used as the command line "target" parameter. .IP "8051 based controllers:" at89c51snd1c, at89c51snd2c, at89c5130, at89c5131, at89c5132 .IP "AVR based controllers:" at90usb1287, at90usb1286, at90usb1287\-4k, at90usb1286\-4k, at90usb647, at90usb646, at90usb162, at90usb82, atmega32u6, atmega32u4, atmega32u2, atmega16u4, atmega16u2, atmega8u2 .IP "AVR32 based controllers:" at32uc3a0128, at32uc3a1128, at32uc3a0256, at32uc3a1256, at32uc3a0512, at32uc3a1512, at32uc3a0512es, at32uc3a1512es, at32uc3a364, at32uc3a364s, at32uc3a3128, at32uc3a3128s, at32uc3a3256, at32uc3a3256s, at32uc3a4256s, at32uc3b064, at32uc3b164, at32uc3b0128, at32uc3b1128, at32uc3b0256, at32uc3b1256, at32uc3b0256es, at32uc3b1256es, at32uc3b0512, at32uc3b1512, at32uc3c064, at32uc3c0128, at32uc3c0256, at32uc3c0512, at32uc3c164, at32uc3c1128, at32uc3c1256, at32uc3c1512, at32uc3c264, at32uc3c2128, at32uc3c2256, at32uc3c2512 .IP "XMEGA based controllers:" atxmega64a1u, atxmega128a1u, atxmega64a3u, atxmega128a3u, atxmega192a3u, atxmega256a3u, atxmega16a4u, atxmega32a4u, atxmega64a4u, atxmega128a4u, atxmega256a3bu, atxmega64b1, atxmega128b1, atxmega64b3, atxmega128b3, atxmega64c3, atxmega128c3, atxmega256c3, atxmega384c3, atxmega16c4, atxmega32c4 .IP "STM32F4 controllers (experimental):" stm32f4_B, stm32f4_C, stm32f4_E, stm32f4_G .SH USAGE There are no mechanisms to implement gang programming. By default, the first device that matches the id codes for the given target is selected. Many targets share the same id codes. Accordingly, you will usually avoid connecting more than one device of a given family (AVR, XMEGA, AVR32 or 8051) at a time. .PP The target may be qualified with the USB bus and address number of the device you wish to program. This allows programming multiple devices of the same family at the same time. .PP All of these commands support the "global options". Unless you override it, commands which write to the microcontroller will perform a validation step that rereads the data which was written, compares it to the expected result, and reports any errors. .PP Note that unlike Atmel's BatchISP program, dfu\-programmer will only perform a single operation at a time. Erasing and programming require separate commands. .HP .B configure register [\-\-suppress\-validation] data .br Bootloaders for 8051 based controllers support writing certain configuration bytes. .HP .B dump [\-\-force] [\-\-bin] [(flash)|\-\-user|\-\-eeprom] .br Reads the program memory in flash and output non\-blank pages in ihex format to stdout. Use \-\-force to output the entire memory and \-\-bin for binary output. User page and eeprom are selected using \-\-user and \-\-eeprom. .HP .B erase [\-\-force] .br Erases all the flash memory. For AT90 and ATmega type devices a chip erase must be performed before other commands become available. Erase first checks if the memory is blank unless \-\-force flag is set. .HP .B flash [\-\-force] [(flash)|\-\-user|\-\-eeprom] [\-\-suppress\-validation] [\-\-suppress\-bootloader\-mem] [\-\-validate\-first] [\-\-ignore\-outside] [\-\-serial=hexbytes:offset] file or STDIN .br Writes flash memory. The input file (or stdin) must use the "ihex" file format convention for a memory image. \-\-suppress\-bootloader\-mem ignores any data written to the bootloader memory space when flashing the device. This option is particularly useful for the AVR32 chips. The \-\-force flag tells the program to ignore whether memory inside the program region is blank. User page and eeprom are selected using \-\-user and \-\-eeprom. The user space flash on AVR32 chips lies outside of the normal range of flash blocks and is designed to contain configuration parameters. Bootloader configuration uses the last 4 to 8 bytes of the user page. If this data is corrupted, the device will restart into the bootloader until valid data is used (see atmel doc7745 or doc32166). \-\-force is always required here. .PP \-\-serial provides a way to inject a serial number or other unique sequence of bytes into the memory image programmed into the device. This allows using a single .ihex file to program multiple devices, and still give each device its own unique serial number. For example, \-\-serial=ABCDEF01:0x6000 would program the byte at 0x6000 with the hex value AB, the byte at 0x6001 with the value CD, and so on. There must be an even number of hex digits, but the sequence can be any length. The offset is assumed to be given in hex if it starts with a "0x" prefix, octal if it begins with a "0", otherwise is it assumed to be decimal. .PP \-\-validate\-first add a validate before writing the flash memory. If the validate succeeds (i.e. the firmware in the chip is the same as the one given as input), then no further operations are done, and the flash is reported as successful. .PP \-\-ignore\-outside changes the validate behavior to ignore any error outside the programming region. This can be useful for programming a single part of the chip (where errors outside region are expected) without ignoring the validate result. .HP .B setsecure .br Sets the security bit on AVR32 chips. This prevents the content being read back from the chip, except in the same session in which it was programmed. When the security fuse is set, almost nothing will work without first executing the erase command. The only way to clear the security fuse once set is to use a JTAG chip erase, which will also erase the bootloader. .HP .B get register .br Displays various product identifier bytes. .HP .B launch [\-\-no\-reset] .br Launch the application by resetting the device. The \-\-no\-reset flag can be used to launch the device without a reset (jump to the start address of the program). .SS Global Options \-\-quiet \- minimizes the output \-\-debug level \- enables verbose output at the specified level .SS Configure Registers The standard bootloader for 8051 based chips supports writing data bytes which are not relevant for the AVR based chips. .LP BSB \- boot status byte .br SBV \- software boot vector .br SSB \- software security byte .br EB \- extra byte .br HSB \- hardware security byte .SS Get Register bootloader\-version \- currently flashed bootloader version .br ID1 \- device boot identification 1 .br ID2 \- device boot identification 2 .br manufacturer \- the hardware manufacturer code .br family \- the product family code .br product\-name \- the product name .br product\-revision \- the product revision .br HSB \- same as the configure_register version .br BSB \- same as the configure_register version .br SBV \- same as the configure_register version .br SSB \- same as the configure_register version .br EB \- same as the configure_register version .SH BUGS None known. .SH KNOWN ISSUES The at90usb series chips do not make available any read/write protect flags so the .B dump or .B flash command may fail with a less than helpful error message. .PP To remove .B any write or read protection from any chips, a full chip erasure is required. For AVR32 chips an erase operation over USB will remove protection until the device is rebooted. To remove the protection more permanently requires a JTAG erase (which will also erase the bootloader). .PP You may need to be a member of the .B uucp group in order to have access to the device without needing to be root. .SH AUTHOR Weston Schmidt .SH SEE ALSO .UR dfu\-programmer.sourceforge.net http://dfu\-programmer.sourceforge.net .UR USB DFU Bootloader Datasheet (8052, AVR) http://www.atmel.com/Images/doc7618.pdf .UR AVR32 UC3 USB DFU Bootloader Protocol http://www.atmel.com/Images/doc32131.pdf .UR FLIP USB DFU Protocol http://www.atmel.com/Images/doc8457.pdf .UR AVR32 UC3 USB DFU Bootloader http://www.atmel.com/Images/doc7745.pdf .SH COPYRIGHT Copyright (C) 2005\-2015 Weston 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110\-1301, USA dfu-programmer-dfu-programmer-f23d6df/docs/dfu-programmer.html000066400000000000000000000263271445234667400246640ustar00rootroot00000000000000 dfu-programmer

dfu-programmer

USB firmware upgrading for Atmel microcontrollers


SYNOPSIS

dfu-programmer target[:usb-bus,usb-addr] command [options] [parameters]
dfu-programmer --help
dfu-programmer --targets
dfu-programmer --version

DESCRIPTION

dfu-programmer is a multi-platform command line Device Firmware Upgrade (DFU) based programmer for the flash memory on Atmel AVR, AVR32, XMEGA and 8051 based microcontrollers which ship with a USB boot loader. It supports In System Programming (ISP) for developers and potentially product updates in the field. Those boot loaders are patterned after the standard USB DFU 1.0 class specification, but depend on extensions defined by Atmel to the extent that standard DFU drivers will not work.

To use it, first connect the device to be programmed and ensure that it comes up in DFU mode. The microcontrollers come up in that mode as shipped by Atmel; or they may reenter that mode after a special hardware reset. Then invoke this program to issue one or more DFU commands. You will normally need to start by issuing the "erase" command; the default security policies prevent extracting firmware, to prevent reverse engineering of what is usually proprietary code.

SUPPORTED MICROCONTROLLERS

These chip names are used as the command line "target" parameter.

8051 based controllers:

at89c51snd1c, at89c51snd2c, at89c5130, at89c5131, at89c5132

AVR based controllers:

at90usb1287, at90usb1286, at90usb1287-4k, at90usb1286-4k, at90usb647, at90usb646, at90usb162, at90usb82, atmega32u6, atmega32u4, atmega32u2, atmega16u4, atmega16u2, atmega8u2

AVR32 based controllers:

at32uc3a0128, at32uc3a1128, at32uc3a0256, at32uc3a1256, at32uc3a0512, at32uc3a1512, at32uc3a0512es, at32uc3a1512es, at32uc3a364, at32uc3a364s, at32uc3a3128, at32uc3a3128s, at32uc3a3256, at32uc3a3256s, at32uc3a4256s, at32uc3b064, at32uc3b164, at32uc3b0128, at32uc3b1128, at32uc3b0256, at32uc3b1256, at32uc3b0256es, at32uc3b1256es, at32uc3b0512, at32uc3b1512, at32uc3c064, at32uc3c0128, at32uc3c0256, at32uc3c0512, at32uc3c164, at32uc3c1128, at32uc3c1256, at32uc3c1512, at32uc3c264, at32uc3c2128, at32uc3c2256, at32uc3c2512

XMEGA based controllers:

atxmega64a1u, atxmega128a1u, atxmega64a3u, atxmega128a3u, atxmega192a3u, atxmega256a3u, atxmega16a4u, atxmega32a4u, atxmega64a4u, atxmega128a4u, atxmega256a3bu, atxmega64b1, atxmega128b1, atxmega64b3, atxmega128b3, atxmega64c3, atxmega128c3, atxmega256c3, atxmega384c3, atxmega16c4, atxmega32c4

USAGE

There are no mechanisms to implement gang programming. By default, the first device that matches the id codes for the given target is selected. Many targets share the same id codes. Accordingly, you will usually avoid connecting more than one device of a given family (AVR, XMEGA, AVR32 or 8051) at a time.

The target may be qualified with the USB bus and address number of the device you wish to program. This allows programming multiple devices of the same family at the same time.

All of these commands support the "global options". Unless you override it, commands which write to the microcontroller will perform a validation step that rereads the data which was written, compares it to the expected result, and reports any errors.

Note that unlike Atmel's BatchISP program, dfu-programmer will only perform a single operation at a time. Erasing and programming require separate commands.

configure register [--suppress-validation] data

Bootloaders for 8051 based controllers support writing certain configuration bytes.

dump [--force] [--bin] [(flash)|--user|--eeprom]

Reads the program memory in flash and output non-blank pages in ihex format to stdout. Use --force to output the entire memory and --bin for binary output. User page and eeprom are selected using --user and --eeprom.

erase [--force]

Erases all the flash memory. For AT90 and ATmega type devices a chip erase must be performed before other commands become available. Erase first checks if the memory is blank unless --force flag is set.

flash [--force] [(flash)|--user|--eeprom] [--suppress-validation] [--suppress-bootloader-mem] [--validate-first] [--ignore-outside]
[--serial=hexbytes:offset] file or STDIN

Writes flash memory. The input file (or stdin) must use the "ihex" file format convention for a memory image. --suppress-bootloader-mem ignores any data written to the bootloader memory space when flashing the device. This option is particularly useful for the AVR32 chips. The --force flag tells the program to ignore whether memory inside the program region is blank. User page and eeprom are selected using --user and --eeprom. The user space flash on AVR32 chips lies outside of the normal range of flash blocks and is designed to contain configuration parameters. Bootloader configuration uses the last 4 to 8 bytes of the user page. If this data is corrupted, the device will restart into the bootloader until valid data is used (see atmel doc7745 or doc32166). --force is always required here.

--serial provides a way to inject a serial number or other unique sequence of bytes into the memory image programmed into the device. This allows using a single .ihex file to program multiple devices, and still give each device its own unique serial number. For example, --serial=ABCDEF01:0x6000 would program the byte at 0x6000 with the hex value AB, the byte at 0x6001 with the value CD, and so on. There must be an even number of hex digits, but the sequence can be any length. The offset is assumed to be given in hex if it starts with a "0x" prefix, octal if it begins with a "0", otherwise is it assumed to be decimal.

--validate-first add a validate before writing the flash memory. If the validate succeeds (i.e. the firmware in the chip is the same as the one given as input), then no further operations are done, and the flash is reported as successful.

--ignore-outside changes the validate behavior to ignore any error outside the programming region. This can be useful for programming a single part of the chip (where errors outside region are expected) without ignoring the validate result.

setsecure

Sets the security bit on AVR32 chips. This prevents the content being read back from the chip, except in the same session in which it was programmed. When the security fuse is set, almost nothing will work without first executing the erase command. The only way to clear the security fuse once set is to use a JTAG chip erase, which will also erase the bootloader.

get register

Displays various product identifier bytes.

launch [--no-reset]

Launch the application by resetting the device. The --no-reset flag can be used to launch the device without a reset (jump to the start address of the program).

Global Options

--quiet

minimizes the output

--debug level

enables verbose output at the specified level

Configure Registers

The standard bootloader for 8051 based chips supports writing data bytes which are not relevant for the AVR based chips.

BSB - boot status byte
SBV - software boot vector
SSB - software security byte
EB - extra byte
HSB - hardware security byte

Get Register

bootloader-version - currently flashed bootloader version
ID1 - device boot identification 1
ID2 - device boot identification 2
manufacturer - the hardware manufacturer code
family - the product family code
product-name - the product name
product-revision - the product revision
HSB - same as the configure_register version
BSB - same as the configure_register version
SBV - same as the configure_register version
SSB - same as the configure_register version
EB - same as the configure_register version

BUGS

None known.

KNOWN ISSUES

The at90usb series chips do not make available any read/write protect flags so the dump or flash command may fail with a less than helpful error message. To remove any write or read protection from any chips, a full chip erasure is required. For AVR32 chips an erase operation over USB will remove protection until the device is rebooted. To remove the protection more permanently requires a JTAG erase (which will also erase the bootloader).

You may need to be a member of the uucp group in order to have access to the device without needing to be root.

AUTHOR

Weston Schmidt <weston_schmidt@alumni.purdue.edu>

SEE ALSO

dfu-programmer.sourceforge.net,
USB DFU Bootloader Datasheet (8051, AVR),
AVR32 UC3 USB DFU Bootloader Protocol,
FLIP USB DFU Protocol,
AVR32 UC3 USB DFU Bootloader

COPYRIGHT

Copyright © 2005-2014 Weston 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA

dfu-programmer-dfu-programmer-f23d6df/fedora/000077500000000000000000000000001445234667400213455ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/fedora/10-dfu-programmer.fdi000066400000000000000000000016221445234667400251770ustar00rootroot00000000000000 dfu-device access_control linux.device_file dfu-device uucp dfu-programmer-dfu-programmer-f23d6df/fedora/README000066400000000000000000000015531445234667400222310ustar00rootroot00000000000000Building RPM Binary Packages ============================ This section is intended to make it easier for those people that wish to build RPMs from the source included in this package, but aren't sure how. 1) Copy dfu-programmer-.tar.gz to your RPM SOURCES directory. Usually this is /usr/src/redhat/SOURCES/. 2) Extract or copy dfu-programmer.spec into your RPM SPECS directory. Usually this is /usr/src/redhat/SPECS/. 3) In your RPM SPECS directory, issue the command 'rpm -ba dfu-programmer.spec'. This will cause rpm to extract the dfu-programmer sources to a temporary directory, build them, and build rpm packages based on the information in the spec file. The binary rpms will be put into your RPM RPMS directory. Usually this is /usr/src/redhat/RPMS//. If you have any further questions, please refer to the RPM documentation. dfu-programmer-dfu-programmer-f23d6df/fedora/dfu-programmer.spec.in000066400000000000000000000120521445234667400255550ustar00rootroot00000000000000Name: dfu-programmer Version: @VERSION@ Release: 1%{?dist} Summary: A Device Firmware Update based USB programmer for Atmel chips Group: Development/Tools License: GPLv2+ URL: http://dfu-programmer.sourceforge.net/ Source0: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libusb-devel >= 1 %description A linux based command-line programmer for Atmel chips with a USB bootloader supporting ISP. This is a mostly Device Firmware Update (DFU) 1.0 compliant user-space application. Supports all DFU enabled Atmel chips with USB support. %prep %setup -q %build %configure %{__make} %{?_smp_mflags} %install %{__rm} -rf %{buildroot} %{__make} DESTDIR=%{buildroot} install %{__install} -d %{buildroot}%{_datadir}/hal/fdi/information/20thirdparty %{__install} -pm 644 fedora/10-dfu-programmer.fdi %{buildroot}%{_datadir}/hal/fdi/information/20thirdparty/10-dfu-programmer.fdi %clean %{__rm} -rf %{buildroot} %files %defattr(-,root,root,-) %doc AUTHORS ChangeLog NEWS README COPYING %{_bindir}/%{name} %{_mandir}/man1/%{name}.1* %{_datadir}/hal/fdi/information/20thirdparty/10-dfu-programmer.fdi %changelog * Wed Feb 04 2015 Simon Large - 0.7.2-1 - Fix memory bounds used for XMega targets. * Sat Jan 03 2015 Simon Large - 0.7.1-1 - Fix use of mandatory filename ChangeLog in distribution tarball - Fix infinite loop in rpl_malloc - Add experimental support for autocomplete on Ubuntu - Fix exit status of help-related options and improve start sequence * Sat Aug 02 2014 Simon Large - 0.7.0-1 - Add support for atmega16c4 and atmega32c4 - Fix device erase for bootloaders which return busy status - Better include file defaults for libusb when run bootstrap is run without pkgconfig. - Improved status output - Add hex dump commands - Add blank memory check - Major rework of the flash/user/eeprom code - Replace start and reset commands with launch - Repository and website migrated to GitHub * Thu Jul 18 2013 Simon Large - 0.6.2-1 - Ignore false "No device found" errors. - Use the correct linker argument to specify the path for libusb-1.0. * Thu Apr 04 2013 Simon Large - 0.6.1-1 - Added support for specifying a USB bus and address - Added support for device serialization - Fix packaging problem when dist built on a Windows machine. - Clarified some error messages * Tue Jan 29 2013 Simon Large - 0.6.0-1 - Added support for xmega chips currently supported by FLIP - Do not attempt eeprom operations on devices without eeprom - Allow setting the security bit on AVR32 - Add HTML help file for Windows users - Added new commands --version, --help, --targets - Improved built in help text - Improved several error messages * Sat Dec 22 2012 Simon Large - 0.5.5-1 - added atmega16u2 support - fixed operation of reset command - more reliable autoconf operation * Sun Jan 16 2011 Weston Schmidt - 0.5.4-1 - added atmega8u2 support * Sun Jan 16 2011 Weston Schmidt - 0.5.3-1 - added at32uc3c* support - fixed a number of defects * Sat Aug 22 2009 Weston Schmidt - 0.5.2-1 - added ability to read from STDIN - added ability to configure AVR32 fuses - Applied a number of bug fixes - Fixed AVR device support * Wed Dec 10 2008 Weston Schmidt - 0.5.1-1 - add new flag to suppress bootloader memory checking * Wed Dec 03 2008 Weston Schmidt - 0.5.0-1 - update the description - fix the broken hal rules * Fri Aug 29 2008 Weston Schmidt - 0.4.6-1 - change udev rules and permissions to be hal based * Wed Aug 20 2008 Weston Schmidt - 0.4.5-1 - added 4K bootloader support - added eeprom-dump and eeprom-flash support - fixed the Source0 url * Mon Nov 19 2007 Weston Schmidt - 0.4.4-1 - added reset command - added udev rules and permissions * Sun Aug 15 2007 Weston Schmidt - 0.4.3-2 - updated the license tag * Sun Aug 12 2007 Weston Schmidt - 0.4.3-1 - see NEWS for details about this release * Fri Jul 20 2007 Weston Schmidt - 0.4.2-2 - updated the release to include the dist, and remove the runtime lib req. * Fri Jul 06 2007 Weston Schmidt - 0.4.2-1 - updating the release and other information to be ready to be part of fedora * Tue May 08 2007 Weston Schmidt - 0.4.1-1 - fixint the changelog and Source0 URL * Wed Oct 21 2006 Weston Schmidt - 0.3.1-1 - updated the release to get ready to be part of the fedora extras * Wed May 07 2006 Weston Schmidt - 0.3.0-1 - updated the release to Fedora Core 5 & the email address * Wed Aug 31 2005 Weston Schmidt - initial creation dfu-programmer-dfu-programmer-f23d6df/package-lock.json000066400000000000000000007265131445234667400233370ustar00rootroot00000000000000{ "name": "dfu-programmer", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dfu-programmer", "version": "1.0.0", "license": "GPL-2.0", "devDependencies": { "@types/jest": "^29.2.5", "jest": "^29.3.1", "prettier": "^2.8.2", "ts-jest": "^29.0.3", "typescript": "^4.9.4" } }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "dependencies": { "@babel/highlight": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { "version": "7.20.10", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz", "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.20.12", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-module-transforms": "^7.20.11", "@babel/helpers": "^7.20.7", "@babel/parser": "^7.20.7", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.12", "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/babel" } }, "node_modules/@babel/core/node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, "node_modules/@babel/generator": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", "dev": true, "dependencies": { "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/helper-compilation-targets": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", "dev": true, "dependencies": { "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "dependencies": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { "version": "7.20.11", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.10", "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { "version": "7.20.2", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { "version": "7.20.2", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dev": true, "dependencies": { "@babel/types": "^7.20.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { "version": "7.19.4", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", "dev": true, "dependencies": { "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.7", "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { "color-convert": "^1.9.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/parser": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.20.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.19.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/template": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { "version": "7.20.12", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz", "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" }, "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/@jest/console": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz", "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==", "dev": true, "dependencies": { "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "jest-message-util": "^29.3.1", "jest-util": "^29.3.1", "slash": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz", "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==", "dev": true, "dependencies": { "@jest/console": "^29.3.1", "@jest/reporters": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.2.0", "jest-config": "^29.3.1", "jest-haste-map": "^29.3.1", "jest-message-util": "^29.3.1", "jest-regex-util": "^29.2.0", "jest-resolve": "^29.3.1", "jest-resolve-dependencies": "^29.3.1", "jest-runner": "^29.3.1", "jest-runtime": "^29.3.1", "jest-snapshot": "^29.3.1", "jest-util": "^29.3.1", "jest-validate": "^29.3.1", "jest-watcher": "^29.3.1", "micromatch": "^4.0.4", "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { "node-notifier": { "optional": true } } }, "node_modules/@jest/environment": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", "dev": true, "dependencies": { "@jest/fake-timers": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "jest-mock": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz", "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==", "dev": true, "dependencies": { "expect": "^29.3.1", "jest-snapshot": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", "dev": true, "dependencies": { "jest-get-type": "^29.2.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", "dev": true, "dependencies": { "@jest/types": "^29.3.1", "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", "jest-message-util": "^29.3.1", "jest-mock": "^29.3.1", "jest-util": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", "dev": true, "dependencies": { "@jest/environment": "^29.3.1", "@jest/expect": "^29.3.1", "@jest/types": "^29.3.1", "jest-mock": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz", "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", "jest-message-util": "^29.3.1", "jest-util": "^29.3.1", "jest-worker": "^29.3.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { "node-notifier": { "optional": true } } }, "node_modules/@jest/schemas": { "version": "29.0.0", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", "dev": true, "dependencies": { "@sinclair/typebox": "^0.24.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.15", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz", "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==", "dev": true, "dependencies": { "@jest/console": "^29.3.1", "@jest/types": "^29.3.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz", "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==", "dev": true, "dependencies": { "@jest/test-result": "^29.3.1", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.3.1", "slash": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.3.1", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.3.1", "jest-regex-util": "^29.2.0", "jest-util": "^29.3.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^4.0.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/types": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.17", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, "node_modules/@sinclair/typebox": { "version": "0.24.51", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", "dev": true }, "node_modules/@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.7.0" } }, "node_modules/@types/babel__core": { "version": "7.1.20", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "node_modules/@types/babel__generator": { "version": "7.6.4", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__traverse": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "dev": true, "dependencies": { "@babel/types": "^7.3.0" } }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", "dev": true }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { "version": "29.2.5", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.5.tgz", "integrity": "sha512-H2cSxkKgVmqNHXP7TC2L/WUorrZu8ZigyRywfVzv6EyBlxj39n4C00hjXYQWsbwqgElaj/CiAeSRmk5GoaKTgw==", "dev": true, "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" } }, "node_modules/@types/node": { "version": "18.11.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", "dev": true }, "node_modules/@types/prettier": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", "dev": true }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, "node_modules/@types/yargs": { "version": "17.0.19", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz", "integrity": "sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "dependencies": { "type-fest": "^0.21.3" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": ">= 8" } }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/babel-jest": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", "dev": true, "dependencies": { "@jest/transform": "^29.3.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.2.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" } }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" }, "engines": { "node": ">=8" } }, "node_modules/babel-plugin-jest-hoist": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz", "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", "@types/babel__core": "^7.1.14", "@types/babel__traverse": "^7.0.6" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.8.3", "@babel/plugin-syntax-import-meta": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.8.3", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-top-level-await": "^7.8.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/babel-preset-jest": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz", "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==", "dev": true, "dependencies": { "babel-plugin-jest-hoist": "^29.2.0", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" } ], "dependencies": { "caniuse-lite": "^1.0.30001400", "electron-to-chromium": "^1.4.251", "node-releases": "^2.0.6", "update-browserslist-db": "^1.0.9" }, "bin": { "browserslist": "cli.js" }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, "node_modules/bs-logger": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, "dependencies": { "fast-json-stable-stringify": "2.x" }, "engines": { "node": ">= 6" } }, "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, "dependencies": { "node-int64": "^0.4.0" } }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { "version": "1.0.30001442", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz", "integrity": "sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" } ] }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/ci-info": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/sibiraj-s" } ], "engines": { "node": ">=8" } }, "node_modules/cjs-module-lexer": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" }, "engines": { "node": ">=12" } }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" } }, "node_modules/collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, "node_modules/deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/diff-sequences": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "dev": true }, "node_modules/emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" }, "engines": { "node": ">=4" } }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/expect": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", "dev": true, "dependencies": { "@jest/expect-utils": "^29.3.1", "jest-get-type": "^29.2.0", "jest-matcher-utils": "^29.3.1", "jest-message-util": "^29.3.1", "jest-util": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "dependencies": { "bser": "2.1.1" } }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, "engines": { "node": ">=8.0.0" } }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "dependencies": { "function-bind": "^1.1.1" }, "engines": { "node": ">= 0.4.0" } }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, "engines": { "node": ">=10.17.0" } }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" }, "bin": { "import-local-fixture": "fixtures/cli.js" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { "node": ">=0.8.19" } }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, "node_modules/is-core-module": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "dependencies": { "has": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "engines": { "node": ">=0.12.0" } }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" }, "engines": { "node": ">=10" } }, "node_modules/istanbul-reports": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/jest": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", "dev": true, "dependencies": { "@jest/core": "^29.3.1", "@jest/types": "^29.3.1", "import-local": "^3.0.2", "jest-cli": "^29.3.1" }, "bin": { "jest": "bin/jest.js" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { "node-notifier": { "optional": true } } }, "node_modules/jest-changed-files": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz", "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==", "dev": true, "dependencies": { "execa": "^5.0.0", "p-limit": "^3.1.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz", "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==", "dev": true, "dependencies": { "@jest/environment": "^29.3.1", "@jest/expect": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", "jest-each": "^29.3.1", "jest-matcher-utils": "^29.3.1", "jest-message-util": "^29.3.1", "jest-runtime": "^29.3.1", "jest-snapshot": "^29.3.1", "jest-util": "^29.3.1", "p-limit": "^3.1.0", "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-cli": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz", "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==", "dev": true, "dependencies": { "@jest/core": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/types": "^29.3.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", "jest-config": "^29.3.1", "jest-util": "^29.3.1", "jest-validate": "^29.3.1", "prompts": "^2.0.1", "yargs": "^17.3.1" }, "bin": { "jest": "bin/jest.js" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { "node-notifier": { "optional": true } } }, "node_modules/jest-config": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.3.1", "@jest/types": "^29.3.1", "babel-jest": "^29.3.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-circus": "^29.3.1", "jest-environment-node": "^29.3.1", "jest-get-type": "^29.2.0", "jest-regex-util": "^29.2.0", "jest-resolve": "^29.3.1", "jest-runner": "^29.3.1", "jest-util": "^29.3.1", "jest-validate": "^29.3.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@types/node": "*", "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, "ts-node": { "optional": true } } }, "node_modules/jest-diff": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.3.1", "jest-get-type": "^29.2.0", "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz", "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==", "dev": true, "dependencies": { "@jest/types": "^29.3.1", "chalk": "^4.0.0", "jest-get-type": "^29.2.0", "jest-util": "^29.3.1", "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz", "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==", "dev": true, "dependencies": { "@jest/environment": "^29.3.1", "@jest/fake-timers": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "jest-mock": "^29.3.1", "jest-util": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", "dev": true, "dependencies": { "@jest/types": "^29.3.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.2.0", "jest-util": "^29.3.1", "jest-worker": "^29.3.1", "micromatch": "^4.0.4", "walker": "^1.0.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "node_modules/jest-leak-detector": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz", "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==", "dev": true, "dependencies": { "jest-get-type": "^29.2.0", "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.3.1", "jest-get-type": "^29.2.0", "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.3.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-mock": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", "dev": true, "dependencies": { "@jest/types": "^29.3.1", "@types/node": "*", "jest-util": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-pnp-resolver": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "engines": { "node": ">=6" }, "peerDependencies": { "jest-resolve": "*" }, "peerDependenciesMeta": { "jest-resolve": { "optional": true } } }, "node_modules/jest-regex-util": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz", "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.3.1", "jest-pnp-resolver": "^1.2.2", "jest-util": "^29.3.1", "jest-validate": "^29.3.1", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve-dependencies": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz", "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==", "dev": true, "dependencies": { "jest-regex-util": "^29.2.0", "jest-snapshot": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz", "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==", "dev": true, "dependencies": { "@jest/console": "^29.3.1", "@jest/environment": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.2.0", "jest-environment-node": "^29.3.1", "jest-haste-map": "^29.3.1", "jest-leak-detector": "^29.3.1", "jest-message-util": "^29.3.1", "jest-resolve": "^29.3.1", "jest-runtime": "^29.3.1", "jest-util": "^29.3.1", "jest-watcher": "^29.3.1", "jest-worker": "^29.3.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz", "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==", "dev": true, "dependencies": { "@jest/environment": "^29.3.1", "@jest/fake-timers": "^29.3.1", "@jest/globals": "^29.3.1", "@jest/source-map": "^29.2.0", "@jest/test-result": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.3.1", "jest-message-util": "^29.3.1", "jest-mock": "^29.3.1", "jest-regex-util": "^29.2.0", "jest-resolve": "^29.3.1", "jest-snapshot": "^29.3.1", "jest-util": "^29.3.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz", "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", "@jest/expect-utils": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", "expect": "^29.3.1", "graceful-fs": "^4.2.9", "jest-diff": "^29.3.1", "jest-get-type": "^29.2.0", "jest-haste-map": "^29.3.1", "jest-matcher-utils": "^29.3.1", "jest-message-util": "^29.3.1", "jest-util": "^29.3.1", "natural-compare": "^1.4.0", "pretty-format": "^29.3.1", "semver": "^7.3.5" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=10" } }, "node_modules/jest-snapshot/node_modules/semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, "node_modules/jest-snapshot/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/jest-util": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", "dev": true, "dependencies": { "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz", "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==", "dev": true, "dependencies": { "@jest/types": "^29.3.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.2.0", "leven": "^3.1.0", "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate/node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/jest-watcher": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz", "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==", "dev": true, "dependencies": { "@jest/test-result": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", "jest-util": "^29.3.1", "string-length": "^4.0.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", "dev": true, "dependencies": { "@types/node": "*", "jest-util": "^29.3.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, "bin": { "jsesc": "bin/jsesc" }, "engines": { "node": ">=4" } }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" }, "engines": { "node": ">=6" } }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "dependencies": { "yallist": "^3.0.2" } }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "dependencies": { "semver": "^6.0.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, "dependencies": { "tmpl": "1.0.5" } }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, "node_modules/node-releases": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", "dev": true }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "dependencies": { "path-key": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { "wrappy": "1" } }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, "node_modules/p-locate/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "dev": true, "engines": { "node": ">= 6" } }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "dependencies": { "find-up": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/prettier": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.2.tgz", "integrity": "sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/pretty-format": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" }, "engines": { "node": ">= 6" } }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "dependencies": { "resolve-from": "^5.0.0" }, "engines": { "node": ">=8" } }, "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/resolve.exports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" }, "engines": { "node": ">=10" } }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" } }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" }, "engines": { "node": ">=8" } }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/ts-jest": { "version": "29.0.3", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz", "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==", "dev": true, "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", "jest-util": "^29.0.0", "json5": "^2.2.1", "lodash.memoize": "4.x", "make-error": "1.x", "semver": "7.x", "yargs-parser": "^21.0.1" }, "bin": { "ts-jest": "cli.js" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", "typescript": ">=4.3" }, "peerDependenciesMeta": { "@babel/core": { "optional": true }, "@jest/types": { "optional": true }, "babel-jest": { "optional": true }, "esbuild": { "optional": true } } }, "node_modules/ts-jest/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=10" } }, "node_modules/ts-jest/node_modules/semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, "node_modules/ts-jest/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/typescript": { "version": "4.9.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=4.2.0" } }, "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" } ], "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" }, "bin": { "browserslist-lint": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" } }, "node_modules/v8-to-istanbul": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0" }, "engines": { "node": ">=10.12.0" } }, "node_modules/v8-to-istanbul/node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, "dependencies": { "makeerror": "1.0.12" } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, "node_modules/yargs": { "version": "17.6.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" } }, "node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "engines": { "node": ">=12" } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } }, "dependencies": { "@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" } }, "@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "requires": { "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { "version": "7.20.10", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz", "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==", "dev": true }, "@babel/core": { "version": "7.20.12", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-module-transforms": "^7.20.11", "@babel/helpers": "^7.20.7", "@babel/parser": "^7.20.7", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.12", "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", "semver": "^6.3.0" }, "dependencies": { "convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true } } }, "@babel/generator": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", "dev": true, "requires": { "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, "dependencies": { "@jridgewell/gen-mapping": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" } } } }, "@babel/helper-compilation-targets": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", "dev": true, "requires": { "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" } }, "@babel/helper-environment-visitor": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true }, "@babel/helper-function-name": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "requires": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" } }, "@babel/helper-hoist-variables": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "requires": { "@babel/types": "^7.18.6" } }, "@babel/helper-module-imports": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { "@babel/types": "^7.18.6" } }, "@babel/helper-module-transforms": { "version": "7.20.11", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.10", "@babel/types": "^7.20.7" } }, "@babel/helper-plugin-utils": { "version": "7.20.2", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "dev": true }, "@babel/helper-simple-access": { "version": "7.20.2", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dev": true, "requires": { "@babel/types": "^7.20.2" } }, "@babel/helper-split-export-declaration": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "requires": { "@babel/types": "^7.18.6" } }, "@babel/helper-string-parser": { "version": "7.19.4", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", "dev": true }, "@babel/helper-validator-identifier": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true }, "@babel/helper-validator-option": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true }, "@babel/helpers": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", "dev": true, "requires": { "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.7", "@babel/types": "^7.20.7" } }, "@babel/highlight": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, "dependencies": { "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" } }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" } }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" } } } }, "@babel/parser": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", "dev": true }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-bigint": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-jsx": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-typescript": { "version": "7.20.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.19.0" } }, "@babel/template": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7" } }, "@babel/traverse": { "version": "7.20.12", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz", "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } }, "@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "requires": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, "@jest/console": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz", "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==", "dev": true, "requires": { "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "jest-message-util": "^29.3.1", "jest-util": "^29.3.1", "slash": "^3.0.0" } }, "@jest/core": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz", "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==", "dev": true, "requires": { "@jest/console": "^29.3.1", "@jest/reporters": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.2.0", "jest-config": "^29.3.1", "jest-haste-map": "^29.3.1", "jest-message-util": "^29.3.1", "jest-regex-util": "^29.2.0", "jest-resolve": "^29.3.1", "jest-resolve-dependencies": "^29.3.1", "jest-runner": "^29.3.1", "jest-runtime": "^29.3.1", "jest-snapshot": "^29.3.1", "jest-util": "^29.3.1", "jest-validate": "^29.3.1", "jest-watcher": "^29.3.1", "micromatch": "^4.0.4", "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", "dev": true, "requires": { "@jest/fake-timers": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "jest-mock": "^29.3.1" } }, "@jest/expect": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz", "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==", "dev": true, "requires": { "expect": "^29.3.1", "jest-snapshot": "^29.3.1" } }, "@jest/expect-utils": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", "dev": true, "requires": { "jest-get-type": "^29.2.0" } }, "@jest/fake-timers": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", "dev": true, "requires": { "@jest/types": "^29.3.1", "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", "jest-message-util": "^29.3.1", "jest-mock": "^29.3.1", "jest-util": "^29.3.1" } }, "@jest/globals": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", "dev": true, "requires": { "@jest/environment": "^29.3.1", "@jest/expect": "^29.3.1", "@jest/types": "^29.3.1", "jest-mock": "^29.3.1" } }, "@jest/reporters": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz", "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", "jest-message-util": "^29.3.1", "jest-util": "^29.3.1", "jest-worker": "^29.3.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" } }, "@jest/schemas": { "version": "29.0.0", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", "dev": true, "requires": { "@sinclair/typebox": "^0.24.1" } }, "@jest/source-map": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.15", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } }, "@jest/test-result": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz", "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==", "dev": true, "requires": { "@jest/console": "^29.3.1", "@jest/types": "^29.3.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz", "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==", "dev": true, "requires": { "@jest/test-result": "^29.3.1", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.3.1", "slash": "^3.0.0" } }, "@jest/transform": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@jest/types": "^29.3.1", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.3.1", "jest-regex-util": "^29.2.0", "jest-util": "^29.3.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^4.0.1" } }, "@jest/types": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true }, "@jridgewell/set-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true }, "@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "@jridgewell/trace-mapping": { "version": "0.3.17", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dev": true, "requires": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, "@sinclair/typebox": { "version": "0.24.51", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", "dev": true }, "@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0" } }, "@types/babel__core": { "version": "7.1.20", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", "dev": true, "requires": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "@types/babel__generator": { "version": "7.6.4", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", "dev": true, "requires": { "@babel/types": "^7.0.0" } }, "@types/babel__template": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", "dev": true, "requires": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "@types/babel__traverse": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "dev": true, "requires": { "@babel/types": "^7.3.0" } }, "@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, "requires": { "@types/node": "*" } }, "@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", "dev": true }, "@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "*" } }, "@types/istanbul-reports": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, "requires": { "@types/istanbul-lib-report": "*" } }, "@types/jest": { "version": "29.2.5", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.5.tgz", "integrity": "sha512-H2cSxkKgVmqNHXP7TC2L/WUorrZu8ZigyRywfVzv6EyBlxj39n4C00hjXYQWsbwqgElaj/CiAeSRmk5GoaKTgw==", "dev": true, "requires": { "expect": "^29.0.0", "pretty-format": "^29.0.0" } }, "@types/node": { "version": "18.11.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", "dev": true }, "@types/prettier": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", "dev": true }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, "@types/yargs": { "version": "17.0.19", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz", "integrity": "sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==", "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { "type-fest": "^0.21.3" } }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { "color-convert": "^2.0.1" } }, "anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "~1.0.2" } }, "babel-jest": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", "dev": true, "requires": { "@jest/transform": "^29.3.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.2.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" } }, "babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" } }, "babel-plugin-jest-hoist": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz", "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==", "dev": true, "requires": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", "@types/babel__core": "^7.1.14", "@types/babel__traverse": "^7.0.6" } }, "babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, "requires": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.8.3", "@babel/plugin-syntax-import-meta": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.8.3", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-top-level-await": "^7.8.3" } }, "babel-preset-jest": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz", "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==", "dev": true, "requires": { "babel-plugin-jest-hoist": "^29.2.0", "babel-preset-current-node-syntax": "^1.0.0" } }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { "fill-range": "^7.0.1" } }, "browserslist": { "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", "dev": true, "requires": { "caniuse-lite": "^1.0.30001400", "electron-to-chromium": "^1.4.251", "node-releases": "^2.0.6", "update-browserslist-db": "^1.0.9" } }, "bs-logger": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, "requires": { "fast-json-stable-stringify": "2.x" } }, "bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, "requires": { "node-int64": "^0.4.0" } }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "caniuse-lite": { "version": "1.0.30001442", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz", "integrity": "sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==", "dev": true }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true }, "ci-info": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", "dev": true }, "cjs-module-lexer": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, "cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true }, "collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { "color-name": "~1.1.4" } }, "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" } }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, "diff-sequences": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", "dev": true }, "electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "dev": true }, "emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { "is-arrayish": "^0.2.1" } }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, "escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "requires": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true }, "expect": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", "dev": true, "requires": { "@jest/expect-utils": "^29.3.1", "jest-get-type": "^29.2.0", "jest-matcher-utils": "^29.3.1", "jest-message-util": "^29.3.1", "jest-util": "^29.3.1" } }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "requires": { "bser": "2.1.1" } }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { "to-regex-range": "^5.0.1" } }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, "get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" } }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, "import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "requires": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" } }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, "is-core-module": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "requires": { "has": "^1.0.3" } }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true }, "istanbul-lib-instrument": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "requires": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" } }, "istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "requires": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" } }, "istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "requires": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" } }, "istanbul-reports": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "requires": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "jest": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", "dev": true, "requires": { "@jest/core": "^29.3.1", "@jest/types": "^29.3.1", "import-local": "^3.0.2", "jest-cli": "^29.3.1" } }, "jest-changed-files": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz", "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==", "dev": true, "requires": { "execa": "^5.0.0", "p-limit": "^3.1.0" } }, "jest-circus": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz", "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==", "dev": true, "requires": { "@jest/environment": "^29.3.1", "@jest/expect": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", "jest-each": "^29.3.1", "jest-matcher-utils": "^29.3.1", "jest-message-util": "^29.3.1", "jest-runtime": "^29.3.1", "jest-snapshot": "^29.3.1", "jest-util": "^29.3.1", "p-limit": "^3.1.0", "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz", "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==", "dev": true, "requires": { "@jest/core": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/types": "^29.3.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", "jest-config": "^29.3.1", "jest-util": "^29.3.1", "jest-validate": "^29.3.1", "prompts": "^2.0.1", "yargs": "^17.3.1" } }, "jest-config": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.3.1", "@jest/types": "^29.3.1", "babel-jest": "^29.3.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-circus": "^29.3.1", "jest-environment-node": "^29.3.1", "jest-get-type": "^29.2.0", "jest-regex-util": "^29.2.0", "jest-resolve": "^29.3.1", "jest-runner": "^29.3.1", "jest-util": "^29.3.1", "jest-validate": "^29.3.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" } }, "jest-diff": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", "dev": true, "requires": { "chalk": "^4.0.0", "diff-sequences": "^29.3.1", "jest-get-type": "^29.2.0", "pretty-format": "^29.3.1" } }, "jest-docblock": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz", "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==", "dev": true, "requires": { "@jest/types": "^29.3.1", "chalk": "^4.0.0", "jest-get-type": "^29.2.0", "jest-util": "^29.3.1", "pretty-format": "^29.3.1" } }, "jest-environment-node": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz", "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==", "dev": true, "requires": { "@jest/environment": "^29.3.1", "@jest/fake-timers": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "jest-mock": "^29.3.1", "jest-util": "^29.3.1" } }, "jest-get-type": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", "dev": true }, "jest-haste-map": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", "dev": true, "requires": { "@jest/types": "^29.3.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.2.0", "jest-util": "^29.3.1", "jest-worker": "^29.3.1", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "jest-leak-detector": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz", "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==", "dev": true, "requires": { "jest-get-type": "^29.2.0", "pretty-format": "^29.3.1" } }, "jest-matcher-utils": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", "dev": true, "requires": { "chalk": "^4.0.0", "jest-diff": "^29.3.1", "jest-get-type": "^29.2.0", "pretty-format": "^29.3.1" } }, "jest-message-util": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.3.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", "dev": true, "requires": { "@jest/types": "^29.3.1", "@types/node": "*", "jest-util": "^29.3.1" } }, "jest-pnp-resolver": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "requires": {} }, "jest-regex-util": { "version": "29.2.0", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", "dev": true }, "jest-resolve": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz", "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.3.1", "jest-pnp-resolver": "^1.2.2", "jest-util": "^29.3.1", "jest-validate": "^29.3.1", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz", "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==", "dev": true, "requires": { "jest-regex-util": "^29.2.0", "jest-snapshot": "^29.3.1" } }, "jest-runner": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz", "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==", "dev": true, "requires": { "@jest/console": "^29.3.1", "@jest/environment": "^29.3.1", "@jest/test-result": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.2.0", "jest-environment-node": "^29.3.1", "jest-haste-map": "^29.3.1", "jest-leak-detector": "^29.3.1", "jest-message-util": "^29.3.1", "jest-resolve": "^29.3.1", "jest-runtime": "^29.3.1", "jest-util": "^29.3.1", "jest-watcher": "^29.3.1", "jest-worker": "^29.3.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz", "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==", "dev": true, "requires": { "@jest/environment": "^29.3.1", "@jest/fake-timers": "^29.3.1", "@jest/globals": "^29.3.1", "@jest/source-map": "^29.2.0", "@jest/test-result": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.3.1", "jest-message-util": "^29.3.1", "jest-mock": "^29.3.1", "jest-regex-util": "^29.2.0", "jest-resolve": "^29.3.1", "jest-snapshot": "^29.3.1", "jest-util": "^29.3.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz", "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", "@jest/expect-utils": "^29.3.1", "@jest/transform": "^29.3.1", "@jest/types": "^29.3.1", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", "expect": "^29.3.1", "graceful-fs": "^4.2.9", "jest-diff": "^29.3.1", "jest-get-type": "^29.2.0", "jest-haste-map": "^29.3.1", "jest-matcher-utils": "^29.3.1", "jest-message-util": "^29.3.1", "jest-util": "^29.3.1", "natural-compare": "^1.4.0", "pretty-format": "^29.3.1", "semver": "^7.3.5" }, "dependencies": { "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" } }, "semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "jest-util": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", "dev": true, "requires": { "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" } }, "jest-validate": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz", "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==", "dev": true, "requires": { "@jest/types": "^29.3.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.2.0", "leven": "^3.1.0", "pretty-format": "^29.3.1" }, "dependencies": { "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true } } }, "jest-watcher": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz", "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==", "dev": true, "requires": { "@jest/test-result": "^29.3.1", "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", "jest-util": "^29.3.1", "string-length": "^4.0.1" } }, "jest-worker": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", "dev": true, "requires": { "@types/node": "*", "jest-util": "^29.3.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "dependencies": { "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { "has-flag": "^4.0.0" } } } }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { "p-locate": "^4.1.0" } }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "requires": { "yallist": "^3.0.2" } }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { "semver": "^6.0.0" } }, "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, "requires": { "tmpl": "1.0.5" } }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" } }, "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, "node-releases": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", "dev": true }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "requires": { "path-key": "^3.0.0" } }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "requires": { "wrappy": "1" } }, "onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { "mimic-fn": "^2.1.0" } }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { "yocto-queue": "^0.1.0" } }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { "p-limit": "^2.2.0" }, "dependencies": { "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" } } } }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "dev": true }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "requires": { "find-up": "^4.0.0" } }, "prettier": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.2.tgz", "integrity": "sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==", "dev": true }, "pretty-format": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "dependencies": { "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true } } }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "requires": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "requires": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "requires": { "resolve-from": "^5.0.0" } }, "resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, "resolve.exports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", "dev": true }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { "shebang-regex": "^3.0.0" } }, "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "requires": { "escape-string-regexp": "^2.0.0" } }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "requires": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" } }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { "ansi-regex": "^5.0.1" } }, "strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" } }, "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "requires": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" } }, "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { "is-number": "^7.0.0" } }, "ts-jest": { "version": "29.0.3", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz", "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==", "dev": true, "requires": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", "jest-util": "^29.0.0", "json5": "^2.2.1", "lodash.memoize": "4.x", "make-error": "1.x", "semver": "7.x", "yargs-parser": "^21.0.1" }, "dependencies": { "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" } }, "semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true }, "typescript": { "version": "4.9.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true }, "update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", "dev": true, "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" } }, "v8-to-istanbul": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0" }, "dependencies": { "convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true } } }, "walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, "requires": { "makeerror": "1.0.12" } }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { "isexe": "^2.0.0" } }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "requires": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, "yargs": { "version": "17.6.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "dev": true, "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true } } } dfu-programmer-dfu-programmer-f23d6df/package.json000066400000000000000000000016541445234667400224010ustar00rootroot00000000000000{ "name": "dfu-programmer", "private": true, "version": "1.0.0", "description": "A Device Firmware Update based USB programmer for Atmel chips with a USB bootloader", "license": "GPL-2.0", "keywords": [ "dfu" ], "homepage": "https://github.com/dfu-programmer/dfu-programmer#readme", "repository": { "type": "git", "url": "git+https://github.com/dfu-programmer/dfu-programmer.git" }, "bugs": { "url": "https://github.com/dfu-programmer/dfu-programmer/issues" }, "directories": { "doc": "docs", "test": "test" }, "scripts": { "test": "jest" }, "jest": { "verbose": false, "preset": "ts-jest", "testEnvironment": "node", "testMatch": [ "/test/**/*.ts", "!**/test/util/**" ] }, "devDependencies": { "@types/jest": "^29.2.5", "jest": "^29.3.1", "prettier": "^2.8.2", "ts-jest": "^29.0.3", "typescript": "^4.9.4" } } dfu-programmer-dfu-programmer-f23d6df/release_proc.txt000066400000000000000000000040461445234667400233150ustar00rootroot00000000000000Update info files ================= Make sure the following files are up to date: - NEWS - AUTHORS - README.md - docs/dfu-programmer.1 - docs/dfu-programmer.html - fedora/dfu-programmer.spec.in Note that the list of devices shown in README and the docs can be auto-generated using dfu-programmer --targets / --targets-tex / --targets-html Update the version number in configure.ac and push a tag with the format `vX.Y.Z` to GitHub. Actions on GitHub will automatically build the release binaries and tarballs and publish them. If you make a mistake in the automated release, simply force push a the tag to point to the new version. To create the source tarball ============================ If building the tarball on Windows you need to install pkg-config. Get the lite version (without dependencies) from here: http://sourceforge.net/projects/pkgconfiglite The files need to go into MinGW/bin and MinGW/share/aclocal. After updating the version information in configure.ac ./bootstrap.sh ./configure make dist To create the Windows binary zip ================================ Create a folder named something like dfu-prog-usb-1.2.2 containing the Atmel driver set from FLIP. Be sure to include Atmel's COPYING notice too. Copy dfu-programmer.exe to the parent of this directory. Copy the html man page from the doc folder. In the parent directory create a zip archive containing the executable, man page and the dfu-prog-usb-x.x.x directory. Upload ====== Upload the tarball and in file information mark it as the default for everything except Windows. Set the description as "x.x.x tarball" Upload the Windows package and mark it as the default for Windows. Set the description as "x.x.x Windows binary with USB driver" Upload the SF-ReadMe.txt file as ReadMe.txt Web page update =============== Update the dfu-programmer.github.io repository. As soon as the changes are pushed back to the repo the web page will update. dfu-programmer-dfu-programmer-f23d6df/src/000077500000000000000000000000001445234667400206745ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/src/Makefile.am000066400000000000000000000007311445234667400227310ustar00rootroot00000000000000AM_CFLAGS = -Wall bin_PROGRAMS = dfu-programmer dfu_programmer_SOURCES = main.c dfu_programmer_SOURCES += libdfu.c libdfu.h dfu_programmer_SOURCES += arguments.c arguments.h dfu_programmer_SOURCES += atmel.c atmel.h dfu_programmer_SOURCES += commands.c commands.h dfu_programmer_SOURCES += dfu.c dfu.h dfu_programmer_SOURCES += dfu-device.h dfu_programmer_SOURCES += intel_hex.c intel_hex.h dfu_programmer_SOURCES += stm32.c stm32.h dfu_programmer_SOURCES += util.c util.h dfu-programmer-dfu-programmer-f23d6df/src/arguments.c000066400000000000000000001534671445234667400230650ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include #include "dfu-device.h" #include "config.h" #include "arguments.h" #include "util.h" // Modes used to display the list of targets. #define LIST_STD 0 #define LIST_TEX 1 #define LIST_HTML 2 /* Bootloader location options For AVR32 the bootloader is at the bottom of memory space and is included in the total stated memory size. For all other types the bootloader is above the application flash. For AVR and most 8051 types the bootloader space is taken out of the stated memory capacity. For XMega and two of the 8051 chips the bootloader space is a separate flash area in addition to the stated memory capacity. Those 8051 chips are also unusual in that the bootloader location is not immediately above the internal flash. In theory you could have a separate bootloader space in low memory but it is not obvious how the addressing would work and none of the Atmel chips do this at present. */ #define BL_BASE 0 /* Bootloader at bottom */ #define BL_TOP 1 /* Bootloader at top, space included in total memory */ #define BL_EXTRA 2 /* Bootloader at top in separate memory area */ #define BL_SPECIFIC 3 /* Any value greater than this is a specific start address */ extern int debug; /* defined in libdfu.c */ #define ARGUMENTS_DEBUG_THRESHOLD 100 #define DEBUG(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, ARGUMENTS_DEBUG_THRESHOLD, __VA_ARGS__ ) struct option_mapping_structure { const char *name; int32_t value; }; struct target_mapping_structure { const char *name; enum targets_enum value; atmel_device_class_t device_type; uint16_t chip_id; uint16_t vendor_id; size_t memory_size; size_t bootloader_size; size_t bootloader_location; size_t flash_page_size; size_t eeprom_page_size; size_t eeprom_memory_size; }; /* NOTE FOR: at90usb1287, at90usb1286, at90usb647, at90usb646, at90usb162, at90usb82 * * The actual size of the user-programmable section is limited by the * space needed by the bootloader. The size of the bootloader is set * by BOOTSZ0/BOOTSZ1 fuse bits; here we assume the bootloader is 4kb or 8kb. * The window used for the bootloader is at the top of the of memory. * * VID and PID are the USB identifiers returned by the DFU bootloader. * They are defined by Atmel's bootloader code, and are not in the chip datasheet. * An incomplete list can be found the the various DFU bootloader docs. * If you plug the device in, lsusb or the Windows device manager can tell you * the VID and PID values. */ /* ----- target specific structures ----------------------------------------- */ static struct target_mapping_structure target_map[] = { // START_TARGET_LIST_LINE .. used for autocompletion script // Name ID (arguments.h) DevType PID VID MemSize BootSz BootLoc FPage EPage ESize { "at89c51snd1c", tar_at89c51snd1c, ADC_8051, 0x2FFF, 0x03eb, 0x10000, 0x1000, BL_TOP, 128, 0, 0 }, { "at89c51snd2c", tar_at89c51snd2c, ADC_8051, 0x2FFF, 0x03eb, 0x10000, 0x1000, BL_TOP, 128, 0, 0 }, { "at89c5130", tar_at89c5130, ADC_8051, 0x2FFD, 0x03eb, 0x04000, 0x0C00, 0xF400, 128, 128, 0x0400 }, { "at89c5131", tar_at89c5131, ADC_8051, 0x2FFD, 0x03eb, 0x08000, 0x0C00, 0xF400, 128, 128, 0x0400 }, { "at89c5132", tar_at89c5132, ADC_8051, 0x2FFF, 0x03eb, 0x10000, 0x0C00, BL_TOP, 128, 0, 0 }, // Name ID (arguments.h) DevType PID VID MemSize BootSz BootLoc FPage EPage ESize { "at90usb1287", tar_at90usb1287, ADC_AVR, 0x2FFB, 0x03eb, 0x20000, 0x2000, BL_TOP, 128, 128, 0x1000 }, { "at90usb1286", tar_at90usb1286, ADC_AVR, 0x2FFB, 0x03eb, 0x20000, 0x2000, BL_TOP, 128, 128, 0x1000 }, { "at90usb1287-4k", tar_at90usb1287_4k, ADC_AVR, 0x2FFB, 0x03eb, 0x20000, 0x1000, BL_TOP, 128, 128, 0x1000 }, { "at90usb1286-4k", tar_at90usb1286_4k, ADC_AVR, 0x2FFB, 0x03eb, 0x20000, 0x1000, BL_TOP, 128, 128, 0x1000 }, { "at90usb647", tar_at90usb647, ADC_AVR, 0x2FF9, 0x03eb, 0x10000, 0x2000, BL_TOP, 128, 128, 0x0800 }, { "at90usb646", tar_at90usb646, ADC_AVR, 0x2FF9, 0x03eb, 0x10000, 0x2000, BL_TOP, 128, 128, 0x0800 }, { "at90usb162", tar_at90usb162, ADC_AVR, 0x2FFA, 0x03eb, 0x04000, 0x1000, BL_TOP, 128, 128, 0x0200 }, { "at90usb82", tar_at90usb82, ADC_AVR, 0x2FF7, 0x03eb, 0x02000, 0x1000, BL_TOP, 128, 128, 0x0200 }, { "atmega32u6", tar_atmega32u6, ADC_AVR, 0x2FF2, 0x03eb, 0x08000, 0x1000, BL_TOP, 128, 128, 0x0400 }, { "atmega32u4", tar_atmega32u4, ADC_AVR, 0x2FF4, 0x03eb, 0x08000, 0x1000, BL_TOP, 128, 128, 0x0400 }, { "atmega32u2", tar_atmega32u2, ADC_AVR, 0x2FF0, 0x03eb, 0x08000, 0x1000, BL_TOP, 128, 128, 0x0400 }, { "atmega16u4", tar_atmega16u4, ADC_AVR, 0x2FF3, 0x03eb, 0x04000, 0x1000, BL_TOP, 128, 128, 0x0200 }, { "atmega16u2", tar_atmega16u2, ADC_AVR, 0x2FEF, 0x03eb, 0x04000, 0x1000, BL_TOP, 128, 128, 0x0200 }, { "atmega8u2", tar_atmega8u2, ADC_AVR, 0x2FEE, 0x03eb, 0x02000, 0x1000, BL_TOP, 128, 128, 0x0200 }, // Name ID (arguments.h) DevType PID VID MemSize BootSz BootLoc FPage EPage ESize { "at32uc3a0128", tar_at32uc3a0128, ADC_AVR32, 0x2FF8, 0x03eb, 0x20000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a1128", tar_at32uc3a1128, ADC_AVR32, 0x2FF8, 0x03eb, 0x20000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a0256", tar_at32uc3a0256, ADC_AVR32, 0x2FF8, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a1256", tar_at32uc3a1256, ADC_AVR32, 0x2FF8, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a0512", tar_at32uc3a0512, ADC_AVR32, 0x2FF8, 0x03eb, 0x80000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a1512", tar_at32uc3a1512, ADC_AVR32, 0x2FF8, 0x03eb, 0x80000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a0512es", tar_at32uc3a0512es, ADC_AVR32, 0x2FF8, 0x03eb, 0x80000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a1512es", tar_at32uc3a1512es, ADC_AVR32, 0x2FF8, 0x03eb, 0x80000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a364", tar_at32uc3a364, ADC_AVR32, 0x2FF1, 0x03eb, 0x10000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a364s", tar_at32uc3a364s, ADC_AVR32, 0x2FF1, 0x03eb, 0x10000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a3128", tar_at32uc3a3128, ADC_AVR32, 0x2FF1, 0x03eb, 0x20000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a3128s", tar_at32uc3a3128s, ADC_AVR32, 0x2FF1, 0x03eb, 0x20000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a3256", tar_at32uc3a3256, ADC_AVR32, 0x2FF1, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a3256s", tar_at32uc3a3256s, ADC_AVR32, 0x2FF1, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3a4256s", tar_at32uc3a4256s, ADC_AVR32, 0x2FF1, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, // Name ID (arguments.h) DevType PID VID MemSize BootSz BootLoc FPage EPage ESize { "at32uc3b064", tar_at32uc3b064, ADC_AVR32, 0x2FF6, 0x03eb, 0x10000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3b164", tar_at32uc3b164, ADC_AVR32, 0x2FF6, 0x03eb, 0x10000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3b0128", tar_at32uc3b0128, ADC_AVR32, 0x2FF6, 0x03eb, 0x20000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3b1128", tar_at32uc3b1128, ADC_AVR32, 0x2FF6, 0x03eb, 0x20000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3b0256", tar_at32uc3b0256, ADC_AVR32, 0x2FF6, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3b1256", tar_at32uc3b1256, ADC_AVR32, 0x2FF6, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3b0256es", tar_at32uc3b0256es, ADC_AVR32, 0x2FF6, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3b1256es", tar_at32uc3b1256es, ADC_AVR32, 0x2FF6, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3b0512", tar_at32uc3b0512, ADC_AVR32, 0x2FF6, 0x03eb, 0x80000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3b1512", tar_at32uc3b1512, ADC_AVR32, 0x2FF6, 0x03eb, 0x80000, 0x2000, BL_BASE, 512, 0, 0 }, // Name ID (arguments.h) DevType PID VID MemSize BootSz BootLoc FPage EPage ESize { "at32uc3c064", tar_at32uc3c064, ADC_AVR32, 0x2FEB, 0x03eb, 0x10000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c0128", tar_at32uc3c0128, ADC_AVR32, 0x2FEB, 0x03eb, 0x20000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c0256", tar_at32uc3c0256, ADC_AVR32, 0x2FEB, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c0512", tar_at32uc3c0512, ADC_AVR32, 0x2FEB, 0x03eb, 0x80000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c164", tar_at32uc3c164, ADC_AVR32, 0x2FEB, 0x03eb, 0x10000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c1128", tar_at32uc3c1128, ADC_AVR32, 0x2FEB, 0x03eb, 0x20000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c1256", tar_at32uc3c1256, ADC_AVR32, 0x2FEB, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c1512", tar_at32uc3c1512, ADC_AVR32, 0x2FEB, 0x03eb, 0x80000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c264", tar_at32uc3c264, ADC_AVR32, 0x2FEB, 0x03eb, 0x10000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c2128", tar_at32uc3c2128, ADC_AVR32, 0x2FEB, 0x03eb, 0x20000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c2256", tar_at32uc3c2256, ADC_AVR32, 0x2FEB, 0x03eb, 0x40000, 0x2000, BL_BASE, 512, 0, 0 }, { "at32uc3c2512", tar_at32uc3c2512, ADC_AVR32, 0x2FEB, 0x03eb, 0x80000, 0x2000, BL_BASE, 512, 0, 0 }, // Name ID (arguments.h) DevType PID VID MemSize BootSz BootLoc FPage EPage ESize { "atxmega64a1u", tar_atxmega64a1u, ADC_XMEGA, 0x2FE8, 0x03eb, 0x10000, 0x1000, BL_EXTRA, 256, 32, 0x0800 }, { "atxmega128a1u", tar_atxmega128a1u, ADC_XMEGA, 0x2FED, 0x03eb, 0x20000, 0x2000, BL_EXTRA, 256, 32, 0x0800 }, { "atxmega64a3u", tar_atxmega64a3u, ADC_XMEGA, 0x2FE5, 0x03eb, 0x10000, 0x1000, BL_EXTRA, 256, 32, 0x0800 }, { "atxmega128a3u", tar_atxmega128a3u, ADC_XMEGA, 0x2FE6, 0x03eb, 0x20000, 0x2000, BL_EXTRA, 512, 32, 0x0800 }, { "atxmega192a3u", tar_atxmega192a3u, ADC_XMEGA, 0x2FE7, 0x03eb, 0x30000, 0x2000, BL_EXTRA, 512, 32, 0x0800 }, { "atxmega256a3u", tar_atxmega256a3u, ADC_XMEGA, 0x2FEC, 0x03eb, 0x40000, 0x2000, BL_EXTRA, 512, 32, 0x1000 }, { "atxmega16a4u", tar_atxmega16a4u, ADC_XMEGA, 0x2FE3, 0x03eb, 0x04000, 0x1000, BL_EXTRA, 256, 32, 0x0400 }, { "atxmega32a4u", tar_atxmega32a4u, ADC_XMEGA, 0x2FE4, 0x03eb, 0x08000, 0x1000, BL_EXTRA, 256, 32, 0x0400 }, { "atxmega64a4u", tar_atxmega64a4u, ADC_XMEGA, 0x2FDD, 0x03eb, 0x10000, 0x1000, BL_EXTRA, 256, 32, 0x0800 }, { "atxmega128a4u", tar_atxmega128a4u, ADC_XMEGA, 0x2FDE, 0x03eb, 0x20000, 0x2000, BL_EXTRA, 256, 32, 0x0800 }, { "atxmega256a3bu", tar_atxmega256a3bu, ADC_XMEGA, 0x2FE2, 0x03eb, 0x40000, 0x2000, BL_EXTRA, 512, 32, 0x1000 }, // Name ID (arguments.h) DevType PID VID MemSize BootSz BootLoc FPage EPage ESize { "atxmega64b1", tar_atxmega64b1, ADC_XMEGA, 0x2FE1, 0x03eb, 0x10000, 0x1000, BL_EXTRA, 256, 32, 0x0800 }, { "atxmega128b1", tar_atxmega128b1, ADC_XMEGA, 0x2FEA, 0x03eb, 0x20000, 0x2000, BL_EXTRA, 256, 32, 0x0800 }, { "atxmega64b3", tar_atxmega64b3, ADC_XMEGA, 0x2FDF, 0x03eb, 0x10000, 0x1000, BL_EXTRA, 256, 32, 0x0800 }, { "atxmega128b3", tar_atxmega128b3, ADC_XMEGA, 0x2FE0, 0x03eb, 0x20000, 0x2000, BL_EXTRA, 256, 32, 0x0800 }, // Name ID (arguments.h) DevType PID VID MemSize BootSz BootLoc FPage EPage ESize { "atxmega64c3", tar_atxmega64c3, ADC_XMEGA, 0x2FD6, 0x03eb, 0x10000, 0x1000, BL_EXTRA, 256, 32, 0x0800 }, { "atxmega128c3", tar_atxmega128c3, ADC_XMEGA, 0x2FD7, 0x03eb, 0x20000, 0x2000, BL_EXTRA, 512, 32, 0x0800 }, { "atxmega256c3", tar_atxmega256c3, ADC_XMEGA, 0x2FDA, 0x03eb, 0x40000, 0x2000, BL_EXTRA, 512, 32, 0x1000 }, { "atxmega384c3", tar_atxmega384c3, ADC_XMEGA, 0x2FDB, 0x03eb, 0x60000, 0x2000, BL_EXTRA, 512, 32, 0x1000 }, { "atxmega16c4", tar_atxmega16c4, ADC_XMEGA, 0x2FD8, 0x03eb, 0x4000, 0x1000, BL_EXTRA, 256, 32, 0x400 }, { "atxmega32c4", tar_atxmega32c4, ADC_XMEGA, 0x2FD9, 0x03eb, 0x8000, 0x1000, BL_EXTRA, 256, 32, 0x400 }, // Name ID (arguments.h) DevType PID VID MemSize BootSz BootLoc FPage EPage ESize // NOTE : that support for these targets is experimental but has been tested with stm32f4 chips on ubuntu { "stm32f4_B", tar_stm32f4_B, DC_STM32, 0xdf11, 0x0483, 0x20000, 0x0000, BL_EXTRA, 512, 0, 0 }, { "stm32f4_C", tar_stm32f4_C, DC_STM32, 0xdf11, 0x0483, 0x40000, 0x0000, BL_EXTRA, 512, 0, 0 }, { "stm32f4_E", tar_stm32f4_E, DC_STM32, 0xdf11, 0x0483, 0x80000, 0x0000, BL_EXTRA, 512, 0, 0 }, { "stm32f4_G", tar_stm32f4_G, DC_STM32, 0xdf11, 0x0483, 0x100000,0x0000, BL_EXTRA, 512, 0, 0 }, { NULL } // END_TARGET_LIST_LINE .. used for autocompletion script }; /* ----- command specific structures ---------------------------------------- */ static struct option_mapping_structure command_map[] = { { "configure", com_configure }, { "read", com_read }, { "dump", com_dump }, { "dump-eeprom", com_edump }, { "dump-user", com_udump }, { "erase", com_erase }, { "flash", com_flash }, { "flash-user", com_user }, { "flash-eeprom", com_eflash }, { "get", com_get }, { "getfuse", com_getfuse }, { "launch", com_launch }, { "reset", com_reset }, { "setfuse", com_setfuse }, { "setsecure", com_setsecure }, { "start", com_start_app }, { "bin2hex", com_bin2hex }, { "hex2bin", com_hex2bin }, { NULL } }; /* ----- configure specific structures -------------------------------------- */ static struct option_mapping_structure configure_map[] = { { "BSB", conf_BSB }, { "SBV", conf_SBV }, { "SSB", conf_SSB }, { "EB", conf_EB }, { "HSB", conf_HSB }, { NULL } }; /* ----- get specific structures -------------------------------------- */ static struct option_mapping_structure get_map[] = { { "bootloader-version", get_bootloader }, { "ID1", get_ID1 }, { "ID2", get_ID2 }, { "BSB", get_BSB }, { "SBV", get_SBV }, { "SSB", get_SSB }, { "EB", get_EB }, { "manufacturer", get_manufacturer }, { "family", get_family }, { "product-name", get_product_name }, { "product-revision", get_product_rev }, { "HSB", get_HSB }, { NULL } }; /* ----- getfuse specific structures ---------------------------------- */ static struct option_mapping_structure getfuse_map[] = { { "LOCK", get_lock }, { "EPFL", get_epfl }, { "BOOTPROT", get_bootprot }, { "BODLEVEL", get_bodlevel }, { "BODHYST", get_bodhyst }, { "BODEN", get_boden }, { "ISP_BOD_EN", get_isp_bod_en }, { "ISP_IO_COND_EN", get_isp_io_cond_en }, { "ISP_FORCE", get_isp_force }, { NULL } }; /* ----- setfuse specific structures ---------------------------------- */ static struct option_mapping_structure setfuse_map[] = { { "LOCK", set_lock }, { "EPFL", set_epfl }, { "BOOTPROT", set_bootprot }, { "BODLEVEL", set_bodlevel }, { "BODHYST", set_bodhyst }, { "BODEN", set_boden }, { "ISP_BOD_EN", set_isp_bod_en }, { "ISP_IO_COND_EN", set_isp_io_cond_en }, { "ISP_FORCE", set_isp_force }, { NULL } }; static void list_targets(int mode) { struct target_mapping_structure *map = NULL; int col = 0; int group_count = 0; atmel_device_class_t device_type = 0; const char *dev_type_name; map = target_map; while( 0 != *((int32_t *) map) ) { if( device_type != map->device_type ) { device_type = map->device_type; switch( device_type ) { case ADC_8051: dev_type_name = "8051"; break; case ADC_AVR: dev_type_name = "AVR"; break; case ADC_AVR32: dev_type_name = "AVR32"; break; case ADC_XMEGA: dev_type_name = "XMEGA"; break; case DC_STM32: dev_type_name = "STM32F4"; break; default: dev_type_name = NULL; break; } if( dev_type_name != NULL ) { if( LIST_TEX == mode ) { if( map != target_map ) fprintf( stdout, "\n" ); fprintf( stdout, ".IP \"%s based controllers:\"\n", dev_type_name ); } else if( LIST_HTML == mode ) { if( map != target_map ) fprintf( stdout, "\n

\n" ); fprintf( stdout, "

%s based controllers:

\n

\n", dev_type_name ); } else { if( 0 != col ) fprintf( stdout, "\n" ); fprintf( stdout, "%s based controllers:\n", dev_type_name ); } group_count = 0; col = 0; } } if( LIST_STD == mode ) { if( 0 == col ) { fprintf( stdout, " " ); } fprintf( stdout, " %-16s", map->name ); if( 4 == ++col ) { fprintf( stdout, "\n" ); col = 0; } } else { if( 0 == col ) { if( 0 != group_count ) fprintf( stdout, ",\n" ); } else { fprintf( stdout, ", " ); } fprintf( stdout, "%s", map->name ); if( 4 == ++col ) { col = 0; } } map++; group_count++; } if( 0 != col ) fprintf( stdout, "\n" ); if( LIST_HTML == mode ) fprintf( stdout, "

\n" ); } static void basic_help() { fprintf( stderr, PACKAGE_STRING "\n"); fprintf( stderr, PACKAGE_URL "\n" ); fprintf( stderr, "Type 'dfu-programmer --help' for a list of commands\n" ); fprintf( stderr, " 'dfu-programmer --targets' to list supported target devices\n" ); } static void usage() { fprintf( stderr, PACKAGE_STRING "\n"); fprintf( stderr, PACKAGE_URL "\n" ); fprintf( stderr, "Usage: dfu-programmer target[:usb-bus,usb-addr] command [options] " "[global-options] [file|data]\n\n" ); fprintf( stderr, "global-options:\n" " --quiet\n" " --debug level (level is an integer specifying level of detail)\n" " Global options can be used with any command and must come\n" " after the command and before any file or data value\n" ); fprintf( stderr, "\n" ); fprintf( stderr, "command summary:\n" ); fprintf( stderr, " launch [--no-reset]\n" ); fprintf( stderr, " read [--force] [--bin] [(flash)|--user|--eeprom]\n" ); fprintf( stderr, " erase [--force] [--suppress-validation]\n" ); fprintf( stderr, " flash [--force] [(flash)|--user|--eeprom]\n" " [--suppress-validation]\n" " [--suppress-bootloader-mem]\n" " [--validate-first]\n" " [--erase-first]\n" " [--ignore-outside]\n" " [--serial=hexdigits:offset] {file|STDIN}\n" ); fprintf( stderr, " setsecure\n" ); fprintf( stderr, " configure {BSB|SBV|SSB|EB|HSB}" " [--suppress-validation] data\n" ); fprintf( stderr, " get {bootloader-version|ID1|ID2|BSB|SBV|SSB|EB|\n" " manufacturer|family|product-name|\n" " product-revision|HSB}\n" ); fprintf( stderr, " getfuse {LOCK|EPFL|BOOTPROT|BODLEVEL|BODHYST|\n" " BODEN|ISP_BOD_EN|ISP_IO_COND_EN|\n" " ISP_FORCE}\n" ); fprintf( stderr, " setfuse {LOCK|EPFL|BOOTPROT|BODLEVEL|BODHYST|\n" " BODEN|ISP_BOD_EN|ISP_IO_COND_EN|\n" " ISP_FORCE} data\n" ); fprintf( stderr, "\n" ); fprintf( stderr, "additional details:\n" ); fprintf( stderr, " launch: Launch from the bootloader into the main program using a watchdog\n" " reset. To jump directly into the main program use --no-reset.\n"); fprintf( stderr, " read: Read the program memory in flash and output non-blank pages in ihex\n" " format. Use --force to output the entire memory and --bin for binary\n" " output. User page and eeprom are selected using --user and --eeprom\n"); fprintf( stderr, " erase: Erase memory contents if the chip is not blank or always with --force\n"); fprintf( stderr, " flash: Flash a program onto device flash memory. EEPROM and user page are\n" " selected using --eeprom|--user flags. Use --force to ignore warning\n" " when data exists in target memory region. Bootloader configuration\n" " uses last 4 to 8 bytes of user page, --force always required here.\n"); fprintf( stderr, "Note: version 0.6.1 commands still supported.\n"); } static int32_t assign_option( int32_t *arg, char *value, struct option_mapping_structure *map ) { while( 0 != *((int32_t *) map) ) { if( 0 == strcasecmp(value, map->name) ) { *arg = map->value; return 0; } map++; } return -1; } static int32_t assign_target( struct programmer_arguments *args, char *value, struct target_mapping_structure *map ) { while( 0 != *((int32_t *) map) ) { size_t name_len = strlen(map->name); if( 0 == strncasecmp(value, map->name, name_len) && (value[name_len] == '\0' || value[name_len] == ':')) { args->target = map->value; args->chip_id = map->chip_id; args->vendor_id = map->vendor_id; args->bus_id = 0; args->device_address = 0; if (value[name_len] == ':') { /* The target name includes USB bus and address info. * This is used to differentiate between multiple dfu * devices with the same vendor/chip ID numbers. By * specifying the bus and address, multiple units can * be programmed at one time. */ int bus = 0; int address = 0; if( 2 != sscanf(&value[name_len+1], "%i,%i", &bus, &address) ) return -1; if (bus <= 0) return -1; if (address < 0) return -1; args->bus_id = bus; args->device_address = address; } args->device_type = map->device_type; args->eeprom_memory_size = map->eeprom_memory_size; args->flash_page_size = map->flash_page_size; args->eeprom_page_size = map->eeprom_page_size; if ( map->bootloader_location > BL_SPECIFIC ) { /* Bootloader space at a specific location, but does not lie immediately above the application flash area. */ args->flash_address_bottom = 0; args->flash_address_top = map->memory_size - 1; args->bootloader_bottom = map->bootloader_location; args->bootloader_top = map->bootloader_location + map->bootloader_size - 1; args->memory_address_bottom = args->flash_address_bottom; args->memory_address_top = args->bootloader_top; } else if( BL_BASE == map->bootloader_location ) { /* Bootloader space is at bottom of memory and is included within stated memory space. */ args->bootloader_bottom = 0; args->bootloader_top = map->bootloader_size - 1; args->flash_address_bottom = map->bootloader_size; args->flash_address_top = map->memory_size - 1; args->memory_address_bottom = args->bootloader_bottom; args->memory_address_top = args->flash_address_top; } else { /* Bootloader space is at top of memory above application area. */ if( BL_EXTRA == map->bootloader_location ) { /* Bootloader space is additional to stated memory space. */ args->bootloader_bottom = map->memory_size; } else { /* Bootloader space is included within stated memory space. */ args->bootloader_bottom = map->memory_size - map->bootloader_size; } args->flash_address_bottom = 0; args->flash_address_top = args->bootloader_bottom - 1; args->bootloader_top = args->bootloader_bottom + map->bootloader_size - 1; args->memory_address_bottom = args->flash_address_bottom; args->memory_address_top = args->bootloader_top; } switch( args->device_type ) { case ADC_8051: strncpy( args->device_type_string, "8051", DEVICE_TYPE_STRING_MAX_LENGTH ); args->initial_abort = false; //args->honor_interfaceclass = true; break; case ADC_AVR: strncpy( args->device_type_string, "AVR", DEVICE_TYPE_STRING_MAX_LENGTH ); args->initial_abort = true; //args->honor_interfaceclass = false; break; case ADC_AVR32: strncpy( args->device_type_string, "AVR32", DEVICE_TYPE_STRING_MAX_LENGTH ); args->initial_abort = false; //args->honor_interfaceclass = true; break; case ADC_XMEGA: strncpy( args->device_type_string, "XMEGA", DEVICE_TYPE_STRING_MAX_LENGTH ); args->initial_abort = true; //args->honor_interfaceclass = false; break; case DC_STM32: strncpy( args->device_type_string, "STM32", DEVICE_TYPE_STRING_MAX_LENGTH ); break; default : // cSpell:words UNKNO strncpy( args->device_type_string, "UNKNO", DEVICE_TYPE_STRING_MAX_LENGTH ); break; } /* There have been several reports on the mailing list of dfu-programmer reporting "No device present" when there clearly is. It seems Atmel's bootloader has changed (or is buggy) and doesn't report interface class and subclass the way is did before. However we have already matched VID and PID so why would we worry about this? Don't use the device- specific value, just ignore the error for all device types. */ args->honor_interfaceclass = false; return 0; } map++; } return -1; } static int32_t assign_global_options( struct programmer_arguments *args, const size_t argc, char **argv ) { size_t i = 0; /* Find '--quiet' if it is here */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--quiet", argv[i]) ) { *argv[i] = '\0'; args->quiet = 1; break; } } /* Find '--suppress-bootloader-mem' if it is here */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--suppress-bootloader-mem", argv[i]) ) { *argv[i] = '\0'; args->suppressBootloader = 1; break; } } /* Find '--suppress-validation' if it is here - even though it is not * used by all this is easier. */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--suppress-validation", argv[i]) ) { *argv[i] = '\0'; switch( args->command ) { case com_configure: args->com_configure_data.suppress_validation = 1; break; case com_erase: args->com_erase_data.suppress_validation = 1; break; case com_flash: case com_eflash: case com_user: args->com_flash_data.suppress_validation = 1; break; default: /* not supported. */ return -1; } break; } } /* Find '--validate-first' if it is here - even though it is not * used by all this is easier. */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--validate-first", argv[i]) ) { *argv[i] = '\0'; switch( args->command ) { case com_flash: case com_eflash: case com_user: args->com_flash_data.validate_first = 1; break; default: /* not supported. */ return -1; } break; } } /* Find '--erase-first' if it is here - even though it is not * used by all this is easier. */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--erase-first", argv[i]) ) { *argv[i] = '\0'; switch( args->command ) { case com_flash: args->com_flash_data.erase_first = 1; break; default: /* not supported. */ return -1; } break; } } /* Find '--ignore-outside' if it is here - even though it is not * used by all this is easier. */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--ignore-outside", argv[i]) ) { *argv[i] = '\0'; switch( args->command ) { case com_flash: case com_eflash: case com_user: args->com_flash_data.ignore_outside = 1; break; default: /* not supported. */ return -1; } break; } } /* Find '--bin' for read binary */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--bin", argv[i]) ) { *argv[i] = '\0'; switch( args->command ) { case com_read: case com_dump: case com_edump: case com_udump: args->com_read_data.bin = 1; break; default: /* not supported. */ return -1; } break; } } /* Find '--user' for the user page segment */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--user", argv[i]) ) { *argv[i] = '\0'; switch( args->command ) { case com_read: case com_udump: args->com_read_data.segment = mem_user; break; case com_flash: case com_user: args->com_flash_data.segment = mem_user; break; case com_bin2hex: args->com_convert_data.segment = mem_user; break; default: /* not supported. */ return -1; } break; } } /* Find '--eeprom' for the eeprom page segment */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--eeprom", argv[i]) ) { *argv[i] = '\0'; switch( args->command ) { case com_read: case com_udump: args->com_read_data.segment = mem_eeprom; break; case com_flash: case com_user: args->com_flash_data.segment = mem_eeprom; break; case com_bin2hex: args->com_convert_data.segment = mem_eeprom; break; default: /* not supported. */ return -1; } break; } } /* Find '--force' if it is here - even though it is not * used by all this is easier. */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--force", argv[i]) ) { *argv[i] = '\0'; switch( args->command ) { case com_flash : case com_eflash : case com_user : args->com_flash_data.force = true; break; case com_read : args->com_read_data.force = true; break; case com_erase : args->com_erase_data.force = true; break; default: // not supported return -1; } break; } } /* Find '--no-reset' if it is here - even though it is not * used by all this is easier. */ for( i = 0; i < argc; i++ ) { if( 0 == strcmp("--no-reset", argv[i]) ) { *argv[i] = '\0'; if ( args->command == com_launch ) { args->com_launch_config.noreset = true; } else { // not supported return -1; } break; } } /* Find '--debug' if it is here */ for( i = 0; i < argc; i++ ) { if( 0 == strncmp("--debug", argv[i], 7) ) { if( 0 == strncmp("--debug=", argv[i], 8) ) { if( 1 != sscanf(argv[i], "--debug=%i", &debug) ) return -2; } else { if( (i+1) >= argc ) return -3; if( 1 != sscanf(argv[i+1], "%i", &debug) ) return -4; *argv[i+1] = '\0'; } *argv[i] = '\0'; break; } } /* Find '--serial=:' */ for( i = 0; i < argc; i++ ) { if( 0 == strncmp("--serial=", argv[i], 9) ) { *argv[i] = '\0'; switch( args->command ) { case com_flash: case com_eflash: case com_user: { char *hexdigits = &argv[i][9]; char *offset_start = hexdigits; size_t num_digits = 0; int16_t *serial_data = NULL; long serial_offset = 0; size_t j = 0; char buffer[3] = {0,0,0}; while (*offset_start != ':') { char c = *offset_start; if ('\0' == c) { return -1; } else if (('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) { ++offset_start; } else { fprintf(stderr, "other character: '%c'\n", *offset_start); return -1; } } num_digits = offset_start - hexdigits; if (num_digits & 1) { fprintf(stderr,"There must be an even number of hexdigits in the serial data\n"); return -1; } *offset_start++ = '\0'; if( 1 != sscanf(offset_start, "%ld", &serial_offset) ) { fprintf(stderr, "sscanf failed\n"); return -1; } serial_data = (int16_t *) malloc( (num_digits/2) * sizeof(int16_t) ); for (j=0; j < num_digits; j+=2) { int data; buffer[0] = hexdigits[j]; buffer[1] = hexdigits[j+1]; buffer[2] = 0; if( 1 != sscanf(buffer, "%02x", &data) ) { fprintf(stderr, "sscanf failed with buffer: %s\n", buffer); return -1; } serial_data[j/2] = (int16_t)data; } args->com_flash_data.serial_data = serial_data; args->com_flash_data.serial_offset = serial_offset; args->com_flash_data.serial_length = num_digits/2; break; } default: /* not supported. */ fprintf(stderr,"command did not match: %d flash: %d\n", args->command, com_flash); return -1; } fprintf(stderr, "Success getting serial number\n"); break; } } return 0; } static int32_t assign_com_setfuse_option( struct programmer_arguments *args, const int32_t parameter, char *value ) { /* name & value */ if( 0 == parameter ) { /* name */ if( 0 != assign_option((int32_t *) &(args->com_setfuse_data.name), value, setfuse_map) ) { return -1; } } else { int32_t temp = 0; /* value */ if( 1 != sscanf(value, "%i", &(temp)) ) return -2; /* ensure the range is greater than 0 */ if( temp < 0 ) return -3; args->com_setfuse_data.value = temp; } return 0; } static int32_t assign_com_configure_option( struct programmer_arguments *args, const int32_t parameter, char *value ) { /* name & value */ if( 0 == parameter ) { /* name */ if( 0 != assign_option((int32_t *) &(args->com_configure_data.name), value, configure_map) ) { return -1; } } else { int32_t temp = 0; /* value */ if( 1 != sscanf(value, "%i", &(temp)) ) return -2; /* ensure the range is greater than 0 */ if( temp < 0 ) return -3; args->com_configure_data.value = temp; } return 0; } static int32_t assign_com_flash_option( struct programmer_arguments *args, const int32_t parameter, char *value ) { /* file */ args->com_flash_data.original_first_char = *value; args->com_flash_data.file = value; return 0; } static int32_t assign_com_convert_option( struct programmer_arguments *args, const int32_t parameter, char *value ) { /* file */ args->com_convert_data.original_first_char = *value; args->com_convert_data.file = value; return 0; } static int32_t assign_com_getfuse_option( struct programmer_arguments *args, const int32_t parameter, char *value ) { /* name */ if( 0 != assign_option((int32_t *) &(args->com_getfuse_data.name), value, getfuse_map) ) { return -1; } return 0; } static int32_t assign_com_get_option( struct programmer_arguments *args, const int32_t parameter, char *value ) { /* name */ if( 0 != assign_option((int32_t *) &(args->com_get_data.name), value, get_map) ) { return -1; } return 0; } static int32_t assign_command_options( struct programmer_arguments *args, const size_t argc, char **argv ) { size_t i = 0; int32_t param = 0; int32_t required_params = 0; /* Deal with all remaining command-specific arguments. */ for( i = 0; i < argc; i++ ) { if( '\0' == *argv[i] ) continue; switch( args->command ) { case com_configure: required_params = 2; if( 0 != assign_com_configure_option(args, param, argv[i]) ) return -1; break; case com_setfuse: required_params = 2; if( 0 != assign_com_setfuse_option(args, param, argv[i]) ) return -1; break; case com_flash: case com_eflash: case com_user: required_params = 1; if( 0 != assign_com_flash_option(args, param, argv[i]) ) return -3; break; case com_bin2hex: case com_hex2bin: required_params = 1; if( 0 != assign_com_convert_option(args, param, argv[i]) ) return -3; break; case com_getfuse: required_params = 1; if( 0 != assign_com_getfuse_option(args, param, argv[i]) ) return -4; break; case com_get: required_params = 1; if( 0 != assign_com_get_option(args, param, argv[i]) ) return -4; break; default: return -5; } *argv[i] = '\0'; param++; } if( required_params != param ) return -6; return 0; } static void print_args( struct programmer_arguments *args ) { const char *command = "(unknown)"; const char *target = "(unknown)"; size_t i; for( i = 0; i < sizeof(target_map) / sizeof(target_map[0]); i++ ) { if( args->target == target_map[i].value ) { target = target_map[i].name; break; } } for( i = 0; i < sizeof(command_map) / sizeof(command_map[0]); i++ ) { if( args->command == command_map[i].value ) { command = command_map[i].name; break; } } fprintf( stderr, " target: %s\n", target ); fprintf( stderr, " chip_id: 0x%04x\n", args->chip_id ); fprintf( stderr, " vendor_id: 0x%04x\n", args->vendor_id ); fprintf( stderr, " command: %s\n", command ); fprintf( stderr, " quiet: %s\n", (0 == args->quiet) ? "false" : "true" ); fprintf( stderr, " debug: %d\n", debug ); fprintf( stderr, "device_type: %s\n", args->device_type_string ); fprintf( stderr, "------ command specific below ------\n" ); switch( args->command ) { case com_configure: fprintf( stderr, " name: %d\n", args->com_configure_data.name ); fprintf( stderr, " validate: %s\n", (args->com_configure_data.suppress_validation) ? "false" : "true" ); fprintf( stderr, " value: %d\n", args->com_configure_data.value ); break; case com_erase: fprintf( stderr, " validate: %s\n", (args->com_erase_data.suppress_validation) ? "false" : "true" ); break; case com_flash: case com_eflash: case com_user: fprintf( stderr, " validate: %s\n", (args->com_flash_data.suppress_validation) ? "false" : "true" ); fprintf( stderr, " hex file: %s\n", args->com_flash_data.file ); break; case com_get: fprintf( stderr, " name: %d\n", args->com_get_data.name ); break; case com_launch: fprintf( stderr, " no-reset: %d\n", args->com_launch_config.noreset ); break; default: break; } fprintf( stderr, "\n" ); fflush( stdout ); } static int32_t execute_hex2bin( struct programmer_arguments *args ) { int32_t retval = -1; uint32_t i; intel_buffer_out_t bout; size_t memory_size; size_t page_size; uint32_t target_offset = 0; memory_size = args->memory_address_top + 1; page_size = args->flash_page_size; // ----------------- CONVERT HEX FILE TO BINARY ------------------------- if( 0 != intel_init_buffer_out(&bout, memory_size, page_size) ) { DEBUG("ERROR initializing a buffer.\n"); goto error; } if( 0!= intel_hex_to_buffer( args->com_convert_data.file, &bout, target_offset, args->quiet ) ) { DEBUG( "Something went wrong with creating the memory image.\n" ); goto error; } if( !args->quiet ) fprintf( stderr, "Dumping 0x%X bytes from address offset 0x%X.\n", bout.info.data_end + 1, target_offset ); for( i = 0; i <= bout.info.data_end; i++ ) { fprintf( stdout, "%c", bout.data[i] <= 0xFF ? bout.data[i] & 0xFF : 0xFF); } fflush( stdout ); retval = 0; error: if( NULL != bout.data ) { free( bout.data ); bout.data = NULL; } return retval; } static int32_t execute_bin2hex( struct programmer_arguments *args ) { int32_t retval = -1; // return value for this fcn intel_buffer_in_t buin; // buffer in for storing read mem enum atmel_memory_unit_enum mem_segment = args->com_convert_data.segment; size_t mem_size = 0; size_t page_size = 0; uint32_t target_offset = 0; // address offset on the target device // NOTE: target_offset may not be set appropriately for device // classes other than ADC_AVR32 FILE *fp = NULL; char *filename = args->com_convert_data.file; if( ADC_AVR32 == args->device_type ) { target_offset = 0x80000000; } switch( mem_segment ) { case mem_flash: mem_size = args->memory_address_top + 1; page_size = args->flash_page_size; break; case mem_eeprom: mem_size = args->eeprom_memory_size; page_size = args->eeprom_page_size; break; case mem_user: mem_size = args->flash_page_size; page_size = args->flash_page_size; target_offset = 0x80800000; break; default: fprintf( stderr, "Dump not currently supported for this memory.\n" ); goto error; } if( 0 != intel_init_buffer_in(&buin, mem_size, page_size) ) { DEBUG("ERROR initializing a buffer.\n"); goto error; } if( mem_segment == mem_flash ) { buin.info.data_start = args->flash_address_bottom; buin.info.data_end = args->flash_address_top; } if( NULL == filename ) { if( !args->quiet ) fprintf( stderr, "Invalid filename.\n" ); retval = -2; goto error; } if( 0 == strcmp("STDIN", filename) ) { fp = stdin; } else { fp = fopen( filename, "r" ); if( NULL == fp ) { if( !args->quiet ) fprintf( stderr, "Error opening %s\n", filename ); retval = -3; goto error; } } buin.info.data_end = fread(buin.data, 1, buin.info.total_size, fp); if( buin.info.data_end == 0 ) { if( !args->quiet ) fprintf( stderr, "ERROR: no bytes read\n" ); retval = -4; goto error; } if( !args->quiet ) fprintf( stderr, "Read 0x%X bytes, making hex with address offset 0x%X.\n", buin.info.data_end + 1, target_offset ); retval = intel_hex_from_buffer( &buin, args->com_convert_data.force, target_offset ); error: if( NULL != buin.data ) { free( buin.data ); buin.data = NULL; } return retval; } int32_t parse_arguments( struct programmer_arguments *args, const size_t argc, char **argv ) { int32_t i; int32_t status = 0; if( NULL == args ) return -1; /* initialize the argument block to empty, known values */ args->target = tar_none; args->command = com_none; args->quiet = 0; args->suppressBootloader = 0; /* Special case - check for the help commands which do not require a device type */ if( argc == 2 ) { if( 0 == strcasecmp(argv[1], "--version") ) { fprintf( stderr, PACKAGE_STRING "\n"); return 1; } if( 0 == strcasecmp(argv[1], "--targets") ) { list_targets( LIST_STD ); return 1; } if( 0 == strcasecmp(argv[1], "--targets-tex") ) { list_targets( LIST_TEX ); return 1; } if( 0 == strcasecmp(argv[1], "--targets-html") ) { list_targets( LIST_HTML ); return 1; } if( 0 == strcasecmp(argv[1], "--help") || 0 == strcasecmp(argv[1], "-h") || 0 == strcasecmp(argv[1], "--h") ) { usage(); return 1; } } /* Make sure there are the minimum arguments */ if( argc < 3 ) { basic_help(); return -1; } if( 0 != assign_target(args, argv[1], target_map) ) { fprintf( stderr, "Unsupported target '%s'.\n", argv[1]); status = -3; goto done; } if( 0 != assign_option((int32_t *) &(args->command), argv[2], command_map) ) { status = -4; goto done; } /* These were taken care of above. */ *argv[0] = '\0'; *argv[1] = '\0'; *argv[2] = '\0'; /* assign command specific default values */ switch( args->command ) { case com_flash : args->com_flash_data.force = 0; args->com_flash_data.segment = mem_flash; break; case com_launch : args->com_launch_config.noreset = 0; break; case com_dump : args->com_read_data.segment = mem_flash; args->com_flash_data.force = 0; break; case com_bin2hex : args->com_convert_data.segment = mem_flash; break; default : break; } if( 0 != assign_global_options(args, argc, argv) ) { status = -5; goto done; } if( 0 != assign_command_options(args, argc, argv) ) { status = -6; goto done; } /* Make sure there weren't any *extra* options. */ for( i = 0; i < argc; i++ ) { if( '\0' != *argv[i] ) { fprintf( stderr, "unrecognized parameter\n" ); status = -7; goto done; } } /* if this is a flash command, restore the filename */ if( (com_flash == args->command) || (com_eflash == args->command) || (com_user == args->command) ) { if( 0 == args->com_flash_data.file ) { // TODO : it should be ok to not have a filename if --serial=hexdigits:offset is // provided, this should be implemented.. in fact, given that most of this // program is written to use a single command by it self, this probably should // be separated out as a new command. The caveat is if data is written to '\0' // in the hex file, serialize will do nothing bc can't un-write w/o erase fprintf( stderr, "flash filename is missing\n" ); status = -8; goto done; } args->com_flash_data.file[0] = args->com_flash_data.original_first_char; } if( (com_bin2hex == args->command) || (com_hex2bin == args->command) ) { if( 0 == args->com_convert_data.file ) { fprintf( stderr, "conversion filename is missing\n" ); status = -8; goto done; } args->com_convert_data.file[0] = args->com_convert_data.original_first_char; if ( com_bin2hex == args->command ) { return execute_bin2hex( args ); } else { return execute_hex2bin( args ); } } done: if( 1 < debug ) { print_args( args ); } if(-3 == status ) { list_targets( LIST_STD ); } else if( 0 != status ) { usage(); } return status; } dfu-programmer-dfu-programmer-f23d6df/src/arguments.h000066400000000000000000000227361445234667400230640ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef __ARGUMENTS_H__ #define __ARGUMENTS_H__ #include #ifdef __cplusplus extern "C" { #endif #include "dfu-device.h" #include "atmel.h" #define DEVICE_TYPE_STRING_MAX_LENGTH 6 /* * atmel_programmer target command * * configure {BSB|SBV|SSB|EB|HSB} [--suppress-validation, --quiet, --debug level] value * dump [--quiet, --debug level] * erase [--suppress-validation, --quiet, --debug level] * flash [--suppress-validation, --quiet, --debug level] file * get {bootloader-version|ID1|ID2|BSB|SBV|SSB|EB|manufacturer|family|product-name|product-revision|HSB} [--quiet, --debug level] * launch [--no-reset] */ enum return_codes_enum { SUCCESS = 0, UNSPECIFIED_ERROR, /* general error */ ARGUMENT_ERROR, /* invalid command for target etc. */ DEVICE_ACCESS_ERROR, /* security bit etc. */ BUFFER_INIT_ERROR, /* hex files problems etc. */ FLASH_READ_ERROR, FLASH_WRITE_ERROR, VALIDATION_ERROR_IN_REGION, VALIDATION_ERROR_OUTSIDE_REGION }; enum targets_enum { tar_at89c51snd1c, tar_at89c51snd2c, tar_at89c5130, tar_at89c5131, tar_at89c5132, tar_at90usb1287, tar_at90usb1286, tar_at90usb1287_4k, tar_at90usb1286_4k, tar_at90usb647, tar_at90usb646, tar_at90usb162, tar_at90usb82, tar_atmega32u6, tar_atmega32u4, tar_atmega32u2, tar_atmega16u4, tar_atmega16u2, tar_atmega8u2, tar_at32uc3b064, tar_at32uc3b164, tar_at32uc3b0128, tar_at32uc3b1128, tar_at32uc3b0256, tar_at32uc3b1256, tar_at32uc3b0256es, tar_at32uc3b1256es, tar_at32uc3b0512, tar_at32uc3b1512, tar_at32uc3a0128, tar_at32uc3a1128, tar_at32uc3a0256, tar_at32uc3a1256, tar_at32uc3a0512, tar_at32uc3a1512, tar_at32uc3a0512es, tar_at32uc3a1512es, tar_at32uc3a364, tar_at32uc3a364s, tar_at32uc3a3128, tar_at32uc3a3128s, tar_at32uc3a3256, tar_at32uc3a3256s, tar_at32uc3a4256s, tar_at32uc3c064, tar_at32uc3c0128, tar_at32uc3c0256, tar_at32uc3c0512, tar_at32uc3c164, tar_at32uc3c1128, tar_at32uc3c1256, tar_at32uc3c1512, tar_at32uc3c264, tar_at32uc3c2128, tar_at32uc3c2256, tar_at32uc3c2512, tar_atxmega64a1u, tar_atxmega128a1u, tar_atxmega64a3u, tar_atxmega128a3u, tar_atxmega192a3u, tar_atxmega256a3u, tar_atxmega16a4u, tar_atxmega32a4u, tar_atxmega64a4u, tar_atxmega128a4u, tar_atxmega256a3bu, tar_atxmega64b1, tar_atxmega128b1, tar_atxmega64b3, tar_atxmega128b3, tar_atxmega64c3, tar_atxmega128c3, tar_atxmega256c3, tar_atxmega384c3, tar_atxmega16c4, tar_atxmega32c4, tar_stm32f4_B, tar_stm32f4_C, tar_stm32f4_E, tar_stm32f4_G, tar_none }; enum commands_enum { com_none, com_erase, com_flash, com_user, com_eflash, com_configure, com_get, com_getfuse, com_dump, com_edump, com_udump, com_setfuse, com_setsecure, com_start_app, com_reset, com_launch, com_read, com_hex2bin, com_bin2hex }; enum configure_enum { conf_BSB = ATMEL_SET_CONFIG_BSB, conf_SBV = ATMEL_SET_CONFIG_SBV, conf_SSB = ATMEL_SET_CONFIG_SSB, conf_EB = ATMEL_SET_CONFIG_EB, conf_HSB = ATMEL_SET_CONFIG_HSB }; enum setfuse_enum { set_lock, set_epfl, set_bootprot, set_bodlevel, set_bodhyst, set_boden, set_isp_bod_en, set_isp_io_cond_en, set_isp_force }; enum get_enum { get_bootloader, get_ID1, get_ID2, get_BSB, get_SBV, get_SSB, get_EB, get_manufacturer, get_family, get_product_name, get_product_rev, get_HSB }; enum getfuse_enum { get_lock, get_epfl, get_bootprot, get_bodlevel, get_bodhyst, get_boden, get_isp_bod_en, get_isp_io_cond_en, get_isp_force }; struct programmer_arguments { /* target-specific inputs */ enum targets_enum target; uint16_t vendor_id; uint16_t chip_id; uint16_t bus_id; /* if non-zero, use bus_id and device_address */ uint16_t device_address; /* to identify the specific target device. */ atmel_device_class_t device_type; char device_type_string[DEVICE_TYPE_STRING_MAX_LENGTH]; uint32_t memory_address_top; /* the maximum flash memory addr. */ uint32_t memory_address_bottom; /* including bootloader region */ uint32_t flash_address_top; /* the maximum flash-able address */ uint32_t flash_address_bottom; /* excludes bootloader region */ uint32_t bootloader_top; /* top of the bootloader region */ uint32_t bootloader_bottom; /* bottom of the bootloader region */ size_t flash_page_size; /* size of a page in bytes */ bool initial_abort; bool honor_interfaceclass; size_t eeprom_memory_size; size_t eeprom_page_size; /* command-specific state */ enum commands_enum command; char quiet; char suppressBootloader; union { struct com_configure_struct { enum configure_enum name; int32_t suppress_validation; int32_t value; } com_configure_data; struct com_setfuse_struct { enum setfuse_enum name; int32_t value; } com_setfuse_data; struct com_read_struct { bool bin; bool force; /* do not remove blank pages */ enum atmel_memory_unit_enum segment; } com_read_data; struct com_erase_struct { bool force; int32_t suppress_validation; } com_erase_data; struct com_launch_struct { bool noreset; } com_launch_config; struct com_flash_struct { int32_t suppress_validation; char original_first_char; char *file; int16_t *serial_data; /* serial number or other device specific bytes */ size_t serial_offset; /* where the serial_data should be written */ size_t serial_length; /* how many bytes to write */ bool force; /* bootloader configuration for UC3 devices is on last one or two words in the user page depending on the version of the bootloader - force overwrite required */ bool validate_first; /* Do a validate before flashing */ bool ignore_outside; /* Ignore validate errors outside region */ bool erase_first; /* Erase flash before writing */ enum atmel_memory_unit_enum segment; } com_flash_data; struct com_convert_struct { size_t bin_offset; // where the bin data starts char original_first_char; bool force; /* do not remove blank pages */ char *file; // for bin2hex / hex2bin conversions enum atmel_memory_unit_enum segment; // to auto-select offset } com_convert_data; struct com_get_struct { enum get_enum name; } com_get_data; struct com_getfuse_struct { enum getfuse_enum name; } com_getfuse_data; }; }; int32_t parse_arguments( struct programmer_arguments *args, const size_t argc, char **argv ); #ifdef __cplusplus } #endif #endif dfu-programmer-dfu-programmer-f23d6df/src/atmel.c000066400000000000000000001522651445234667400221550ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include #include #include #include #include "dfu-device.h" #include "config.h" #include "arguments.h" #include "dfu.h" #include "atmel.h" #include "util.h" /* Atmel's firmware doesn't export a DFU descriptor in its config * descriptor, so we have to guess about parameters listed there. * We use 3KB for wTransferSize (MAX_TRANSFER_SIZE). */ /* a 64kb page contains 0x10000 values (0 to 0xFFFF). For the largest 512 kb * devices (2^19 bytes) there should be 8 pages. */ #define ATMEL_64KB_PAGE 0x10000 #define ATMEL_MAX_TRANSFER_SIZE 0x0400 #define ATMEL_MAX_FLASH_BUFFER_SIZE (ATMEL_MAX_TRANSFER_SIZE + \ ATMEL_AVR32_CONTROL_BLOCK_SIZE + \ ATMEL_AVR32_CONTROL_BLOCK_SIZE + \ ATMEL_FOOTER_SIZE) #define ATMEL_FOOTER_SIZE 16 #define ATMEL_CONTROL_BLOCK_SIZE 32 #define ATMEL_AVR32_CONTROL_BLOCK_SIZE 64 #define ATMEL_DEBUG_THRESHOLD 50 #define ATMEL_TRACE_THRESHOLD 55 #define DEBUG(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, \ ATMEL_DEBUG_THRESHOLD, __VA_ARGS__ ) #define TRACE(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, \ ATMEL_TRACE_THRESHOLD, __VA_ARGS__ ) #define PROGRESS_METER "0%% 100%% " #define PROGRESS_START "[" #define PROGRESS_BAR ">" #define PROGRESS_END "] " #define PROGRESS_ERROR " X " extern int debug; /* defined in libdfu.c */ // ________ P R O T O T Y P E S _______________________________ static int32_t atmel_read_command( dfu_device_t *device, const uint8_t data0, const uint8_t data1 ); /* returns 0 - 255 on success, < 0 otherwise * * but what is it used for?? */ static int32_t __atmel_flash_block( dfu_device_t *device, intel_buffer_out_t *bout, const bool eeprom ); /* flash the contents of memory into a block of memory. it is assumed that the * appropriate page has already been selected. start and end are the start and * end addresses of the flash data. returns 0 on success, positive dfu error * code if one is obtained, or negative if communication with device fails. */ static int32_t atmel_select_memory_unit( dfu_device_t *device, enum atmel_memory_unit_enum unit ); /* select a memory unit from the following list (enumerated) * flash, eeprom, security, configuration, bootloader, signature, user page */ static int32_t atmel_select_page( dfu_device_t *device, const uint16_t mem_page ); /* select a page in memory, numbering starts with 0, pages are * 64kb pages (0x10000 bytes). Select page when the memory unit * is set to the user page will cause an error. */ static int32_t __atmel_blank_page_check( dfu_device_t *device, const uint32_t start, const uint32_t end ); /* use to check if a certain address range on the current page is blank * it assumes current page has previously been selected. * returns 0 if the page is blank * returns the first non-blank address + 1 if not blank (no zero!) * returns a negative number if the blank check fails */ static int32_t __atmel_read_block( dfu_device_t *device, intel_buffer_in_t *buin, const bool eeprom ); /* assumes block does not cross 64 b page boundaries and ideally aligns * with flash pages. appropriate memory type and 64kb page has already * been selected, max transfer size is not violated it updates the buffer * data between data_start and data_end */ static inline void __print_progress( intel_buffer_info_t *info, uint32_t *progress ); /* calculate how many progress indicator steps to print and print them * update progress value */ // ________ F U N C T I O N S _______________________________ static int32_t atmel_read_command( dfu_device_t *device, const uint8_t data0, const uint8_t data1 ) { intel_buffer_in_t buin; uint8_t buffer[4]; TRACE( "%s( %p, 0x%02x, 0x%02x )\n", __FUNCTION__, device, data0, data1 ); // init the necessary parts of buin buin.info.block_start = data1; buin.info.block_end = data1; buin.data = buffer; if( NULL == device ) { DEBUG( "invalid arguments.\n" ); return -1; } if( GRP_AVR32 & device->type ) { //We need to talk to configuration memory. It comes //in two varieties in this chip. data0 is the command to //select it. Data1 is the byte of that group we want if( 0 != atmel_select_memory_unit(device, data0) ) { return -3; } if( 0 != __atmel_read_block(device, &buin, false) ) { return -5; } return (0xff & buffer[data1]); } else { uint8_t command[3] = { 0x05, 0x00, 0x00 }; uint8_t data[1] = { 0x00 }; dfu_status_t status; command[1] = data0; command[2] = data1; if( 3 != dfu_download(device, 3, command) ) { DEBUG( "dfu_download failed\n" ); return -1; } if( 0 != dfu_get_status(device, &status) ) { DEBUG( "dfu_get_status failed\n" ); return -2; } if( DFU_STATUS_OK != status.bStatus ) { DEBUG( "status(%s) was not OK.\n", dfu_status_to_string(status.bStatus) ); dfu_clear_status( device ); return -3; } if( 1 != dfu_upload(device, 1, data) ) { DEBUG( "dfu_upload failed\n" ); return -4; } return (0xff & data[0]); } } static inline void __print_progress( intel_buffer_info_t *info, uint32_t *progress ) { if ( !(debug > ATMEL_DEBUG_THRESHOLD) && isatty(2) ) { while ( ((info->block_end - info->data_start + 1) * 32) > *progress ) { fprintf( stderr, PROGRESS_BAR ); *progress += info->data_end - info->data_start + 1; } } } int32_t atmel_read_fuses( dfu_device_t *device, atmel_avr32_fuses_t *info ) { intel_buffer_in_t buin; uint8_t buffer[32]; int i; // init the necessary parts of buin buin.info.block_start = 0; buin.info.block_end = 31; buin.data = buffer; if( NULL == device ) { DEBUG( "invalid arguments.\n" ); return ARGUMENT_ERROR; } if( !(ADC_AVR32 & device->type) ) { DEBUG( "target does not support fuse operation.\n" ); fprintf( stderr, "target does not support fuse operation.\n" ); return ARGUMENT_ERROR; } if( 0 != atmel_select_memory_unit(device, mem_config) ) { return -3; } if( 0 != __atmel_read_block(device, &buin, false) ) { return -5; } info->lock = 0; for(i = 0; i < 16; i++) { info->lock = info->lock | (buffer[i] << i); } info->epfl = buffer[16]; info->bootprot = (buffer[19] << 2) | (buffer[18] << 1) | (buffer[17] << 0); info->bodlevel = 0; for(i = 20; i < 26; i++) { info->bodlevel = info->bodlevel | (buffer[i] << (i-20)); } info->bodhyst = buffer[26]; info->boden = (buffer[28] << 1) | (buffer[27] << 0); info->isp_bod_en = buffer[29]; info->isp_io_cond_en = buffer[30]; info->isp_force = buffer[31]; return 0; } int32_t atmel_read_config( dfu_device_t *device, atmel_device_info_t *info ) { typedef struct { uint8_t data0; uint8_t data1; uint8_t device_map; size_t offset; } atmel_read_config_t; /* These commands are documented in Appendix A of the * "AT89C5131A USB Bootloader Datasheet" or * "AT90usb128x/AT90usb64x USB DFU Bootloader Datasheet" */ static const atmel_read_config_t data[] = { { 0x00, 0x00, (ADC_8051 | ADC_AVR), offsetof(atmel_device_info_t, bootloaderVersion) }, { 0x04, 0x00, (ADC_AVR32 | ADC_XMEGA), offsetof(atmel_device_info_t, bootloaderVersion) }, { 0x00, 0x01, (ADC_8051 | ADC_AVR), offsetof(atmel_device_info_t, bootID1) }, { 0x04, 0x01, (ADC_AVR32 | ADC_XMEGA), offsetof(atmel_device_info_t, bootID1) }, { 0x00, 0x02, (ADC_8051 | ADC_AVR), offsetof(atmel_device_info_t, bootID2) }, { 0x04, 0x02, (ADC_AVR32 | ADC_XMEGA), offsetof(atmel_device_info_t, bootID2) }, { 0x01, 0x30, (ADC_8051 | ADC_AVR), offsetof(atmel_device_info_t, manufacturerCode) }, { 0x05, 0x00, (ADC_AVR32 | ADC_XMEGA), offsetof(atmel_device_info_t, manufacturerCode) }, { 0x01, 0x31, (ADC_8051 | ADC_AVR), offsetof(atmel_device_info_t, familyCode) }, { 0x05, 0x01, (ADC_AVR32 | ADC_XMEGA), offsetof(atmel_device_info_t, familyCode) }, { 0x01, 0x60, (ADC_8051 | ADC_AVR), offsetof(atmel_device_info_t, productName) }, { 0x05, 0x02, (ADC_AVR32 | ADC_XMEGA), offsetof(atmel_device_info_t, productName) }, { 0x01, 0x61, (ADC_8051 | ADC_AVR), offsetof(atmel_device_info_t, productRevision) }, { 0x05, 0x03, (ADC_AVR32 | ADC_XMEGA), offsetof(atmel_device_info_t, productRevision) }, { 0x01, 0x00, ADC_8051, offsetof(atmel_device_info_t, bsb) }, { 0x01, 0x01, ADC_8051, offsetof(atmel_device_info_t, sbv) }, { 0x01, 0x05, ADC_8051, offsetof(atmel_device_info_t, ssb) }, { 0x01, 0x06, ADC_8051, offsetof(atmel_device_info_t, eb) }, { 0x02, 0x00, ADC_8051, offsetof(atmel_device_info_t, hsb) } }; int32_t result; int32_t retVal = 0; int32_t i = 0; TRACE( "%s( %p, %p )\n", __FUNCTION__, device, info ); if( NULL == device ) { DEBUG( "invalid arguments.\n" ); return -1; } for( i = 0; i < sizeof(data)/sizeof(atmel_read_config_t); i++ ) { atmel_read_config_t *row = (atmel_read_config_t*) &data[i]; if( row->device_map & device->type ) { int16_t *ptr = row->offset + (void *) info; result = atmel_read_command( device, row->data0, row->data1 ); if( result < 0 ) { retVal = result; } *ptr = result; } } return retVal; } int32_t atmel_erase_flash( dfu_device_t *device, const uint8_t mode, bool quiet ) { uint8_t command[3] = { 0x04, 0x00, 0x00 }; dfu_status_t status; int32_t retries; time_t start; TRACE( "%s( %p, %d )\n", __FUNCTION__, device, mode ); switch( mode ) { case ATMEL_ERASE_BLOCK_0: command[2] = 0x00; break; case ATMEL_ERASE_BLOCK_1: command[2] = 0x20; break; case ATMEL_ERASE_BLOCK_2: command[2] = 0x40; break; case ATMEL_ERASE_BLOCK_3: command[2] = 0x80; break; case ATMEL_ERASE_ALL: command[2] = 0xff; break; default: return -1; } if( !quiet ) fprintf( stderr, "Erasing flash... " ); if( 3 != dfu_download(device, 3, command) ) { if( !quiet ) fprintf( stderr, "ERROR\n" ); DEBUG( "dfu_download failed\n" ); return -2; } /* It looks like it can take a while to erase the chip. * We will try for 20 seconds before giving up. * Different version of the bootloader behave in different ways. * In some the dfu_get_status() call blocks until the operation completes. * In others it returns immediately with an erase-in-progress status. */ #define ERASE_SECONDS 20 start = time(NULL); retries = 0; do { if( 0 == dfu_get_status(device, &status) ) { // Status return is valid if( (DFU_STATUS_ERROR_NOTDONE == status.bStatus) && (STATE_DFU_DOWNLOAD_BUSY == status.bState) ) { // Erase is still in progress. // Wait 100ms and get status again. usleep(100000); } else { // Erase complete. if( !quiet ) fprintf( stderr, "Success\n" ); DEBUG ( "CMD_ERASE status: Erase Done.\n" ); return status.bStatus; } } else { // Status command failed. dfu_clear_status( device ); ++retries; if( !quiet ) fprintf( stderr, "ERROR\n" ); DEBUG ( "CMD_ERASE status check %d returned nonzero.\n", retries ); } } while( (retries < 10) && (start != -1) && ((time(NULL) - start) < ERASE_SECONDS) ); if( retries < 10 ) DEBUG ( "CMD_ERASE time limit %ds exceeded.\n", ERASE_SECONDS ); return -3; } int32_t atmel_set_fuse( dfu_device_t *device, const uint8_t property, const uint32_t value ) { uint16_t buffer[16]; int32_t address; int8_t numbytes; int8_t i; intel_buffer_out_t bout; if( NULL == device ) { DEBUG( "invalid arguments.\n" ); return -1; } if( !(ADC_AVR32 & device->type) ) { DEBUG( "target does not support fuse operation.\n" ); fprintf( stderr, "target does not support fuse operation.\n" ); return -1; } if( 0 != atmel_select_memory_unit(device, mem_config) ) { return -3; } switch( property ) { case set_lock: for( i = 0; i < 16; i++ ) { buffer[i] = value & (0x0001 << i); } numbytes = 16; address = 0; break; case set_epfl: buffer[0] = value & 0x0001; numbytes = 1; address = 16; break; case set_bootprot: buffer[0] = value & 0x0001; buffer[1] = value & 0x0002; buffer[2] = value & 0x0004; numbytes = 3; address = 17; break; case set_bodlevel: #ifdef SUPPORT_SET_BOD_FUSES /* Enable at your own risk - this has not been tested & * may brick your device. */ for(i = 20;i < 26; i++){ buffer[i] = value & (0x0001 << (i-20)); } numbytes = 6; address = 20; break; #else DEBUG( "Setting BODLEVEL can break your chip. Operation not performed\n" ); DEBUG( "Rebuild with the SUPPORT_SET_BOD_FUSES #define enabled if you really want to do this.\n" ); fprintf( stderr, "Setting BODLEVEL can break your chip. Operation not performed.\n" ); return -1; #endif case set_bodhyst: #ifdef SUPPORT_SET_BOD_FUSES /* Enable at your own risk - this has not been tested & * may brick your device. */ buffer[0] = value & 0x0001; numbytes = 1; address = 26; break; #else DEBUG("Setting BODHYST can break your chip. Operation not performed\n"); DEBUG( "Rebuild with the SUPPORT_SET_BOD_FUSES #define enabled if you really want to do this.\n" ); fprintf( stderr, "Setting BODHYST can break your chip. Operation not performed.\n"); return -1; #endif case set_boden: #ifdef SUPPORT_SET_BOD_FUSES /* Enable at your own risk - this has not been tested & * may brick your device. */ buffer[0] = value & 0x0001; buffer[1] = value & 0x0002; numbytes = 2; address = 27; break; #else DEBUG( "Setting BODEN can break your chip. Operation not performed\n" ); DEBUG( "Rebuild with the SUPPORT_SET_BOD_FUSES #define enabled if you really want to do this.\n" ); fprintf( stderr, "Setting BODEN can break your chip. Operation not performed.\n" ); return -1; #endif case set_isp_bod_en: #ifdef SUPPORT_SET_BOD_FUSES /* Enable at your own risk - this has not been tested & * may brick your device. */ buffer[0] = value & 0x0001; numbytes = 1; address = 29; break; #else DEBUG( "Setting ISP_BOD_EN can break your chip. Operation not performed\n" ); DEBUG( "Rebuild with the SUPPORT_SET_BOD_FUSES #define enabled if you really want to do this.\n" ); fprintf( stderr, "Setting ISP_BOD_EN can break your chip. Operation not performed.\n" ); return -1; #endif case set_isp_io_cond_en: buffer[0] = value & 0x0001; numbytes = 1; address = 30; break; case set_isp_force: buffer[0] = value & 0x0001; numbytes = 1; address = 31; break; default: DEBUG( "Fuse bits unrecognized\n" ); fprintf( stderr, "Fuse bits unrecognized.\n" ); return -2; break; } bout.data = buffer; bout.info.block_start = address; bout.info.block_end = address + numbytes - 1; if( 0 != __atmel_flash_block(device, &bout, false) ) { return -6; } return 0; } int32_t atmel_set_config( dfu_device_t *device, const uint8_t property, const uint8_t value ) { uint8_t command[4] = { 0x04, 0x01, 0x00, 0x00 }; dfu_status_t status; TRACE( "%s( %p, %d, 0x%02x )\n", __FUNCTION__, device, property, value ); switch( property ) { case ATMEL_SET_CONFIG_BSB: break; case ATMEL_SET_CONFIG_SBV: command[2] = 0x01; break; case ATMEL_SET_CONFIG_SSB: command[2] = 0x05; break; case ATMEL_SET_CONFIG_EB: command[2] = 0x06; break; case ATMEL_SET_CONFIG_HSB: command[1] = 0x02; break; default: return -1; } command[3] = value; if( 4 != dfu_download(device, 4, command) ) { DEBUG( "dfu_download failed\n" ); return -2; } if( 0 != dfu_get_status(device, &status) ) { DEBUG( "dfu_get_status failed\n" ); return -3; } if( DFU_STATUS_ERROR_WRITE == status.bStatus ) { fprintf( stderr, "Device is write protected.\n" ); } return status.bStatus; } static int32_t __atmel_read_block( dfu_device_t *device, intel_buffer_in_t *buin, const bool eeprom ) { uint8_t command[6] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }; int32_t result; if( buin->info.block_end < buin->info.block_start ) { // this would cause a problem bc read length could be way off DEBUG("ERROR: start address is after end address.\n"); return -1; } else if( buin->info.block_end - buin->info.block_start + 1 > ATMEL_MAX_TRANSFER_SIZE ) { // this could cause a read problem DEBUG("ERROR: transfer size must not exceed %d.\n", ATMEL_MAX_TRANSFER_SIZE ); return -1; } // AVR/8051 requires 0x02 here to read eeprom, XMEGA requires 0x00. if( true == eeprom && (GRP_AVR & device->type) ) { command[1] = 0x02; } command[2] = 0xff & (buin->info.block_start >> 8); command[3] = 0xff & (buin->info.block_start); command[4] = 0xff & (buin->info.block_end >> 8); command[5] = 0xff & (buin->info.block_end); if( 6 != dfu_download(device, 6, command) ) { DEBUG( "dfu_download failed\n" ); return -1; } result = dfu_upload( device, buin->info.block_end - buin->info.block_start + 1, &buin->data[buin->info.block_start] ); if( result < 0) { dfu_status_t status; DEBUG( "dfu_upload result: %d\n", result ); if( 0 == dfu_get_status(device, &status) ) { if( DFU_STATUS_ERROR_FILE == status.bStatus ) { fprintf( stderr, "The device is read protected.\n" ); } else { fprintf( stderr, "Unknown error. Try enabling debug.\n" ); } } else { fprintf( stderr, "Device is unresponsive.\n" ); } dfu_clear_status( device ); return result; } return 0; } int32_t atmel_read_flash( dfu_device_t *device, intel_buffer_in_t *buin, const uint8_t mem_segment, const bool quiet ) { uint8_t mem_page = 0; // tracks the current memory page uint32_t progress = 0; // used to indicate progress int32_t result = 0; // TODO : use status instead of result int32_t retval = -1; // the return value for this function TRACE( "%s( %p, %p, %u, %s )\n", __FUNCTION__, device, buin, mem_segment, ((true == quiet) ? "true" : "false")); if( (NULL == buin) || (NULL == device) ) { DEBUG( "invalid arguments.\n" ); if( !quiet ) fprintf( stderr, "Program Error, use debug for more info.\n" ); return -1; } else if ( mem_segment != mem_flash && mem_segment != mem_user && mem_segment != mem_eeprom ) { DEBUG( "Invalid memory segment %d to read.\n", mem_segment ); if( !quiet ) fprintf( stderr, "Program Error, use debug for more info.\n" ); return -1; } // For the AVR32/XMEGA chips, select the flash space. (safe for all parts) if( 0 != atmel_select_memory_unit(device, mem_segment) ) { DEBUG ("Error selecting memory unit.\n"); if( !quiet ) fprintf( stderr, "Memory access error, use debug for more info.\n" ); return -3; } if( !quiet ) { if( debug <= ATMEL_DEBUG_THRESHOLD && isatty(2) ) { // NOTE: From here on we should go to finally on error fprintf( stderr, PROGRESS_METER ); } fprintf( stderr, "Reading 0x%X bytes...\n", buin->info.data_end - buin->info.data_start + 1 ); if( debug <= ATMEL_DEBUG_THRESHOLD && isatty(2) ) { // NOTE: From here on we should go to finally on error fprintf( stderr, PROGRESS_START ); } } // select the first memory page ( not safe for mem_user ) buin->info.block_start = buin->info.data_start; mem_page = buin->info.block_start / ATMEL_64KB_PAGE; if ( mem_segment != mem_user ) { if( 0 != (result = atmel_select_page( device, mem_page )) ) { DEBUG( "ERROR selecting 64kB page %d.\n", result ); retval = -3; goto finally; } } while (buin->info.block_start <= buin->info.data_end) { // ensure the memory page is correct if ( buin->info.block_start / ATMEL_64KB_PAGE != mem_page ) { mem_page = buin->info.block_start / ATMEL_64KB_PAGE; if( 0 != (result = atmel_select_page( device, mem_page )) ) { DEBUG( "ERROR selecting 64kB page %d.\n", result ); retval = -3; } // check if the entire page is blank () } // find end value for the current transfer buin->info.block_end = buin->info.block_start + ATMEL_MAX_TRANSFER_SIZE - 1; if ( buin->info.block_end / ATMEL_64KB_PAGE > mem_page ) { buin->info.block_end = ATMEL_64KB_PAGE * mem_page - 1; } if ( buin->info.block_end > buin->info.data_end ) { buin->info.block_end = buin->info.data_end; } if( 0 != (result = __atmel_read_block(device, buin, mem_segment == mem_eeprom ? 1 : 0)) ) { DEBUG( "Error reading block 0x%X to 0x%X: err %d.\n", buin->info.block_start, buin->info.block_end, result ); retval = -5; goto finally; } buin->info.block_start = buin->info.block_end + 1; if ( !quiet ) __print_progress( &buin->info, &progress ); } retval = 0; finally: if ( !quiet ) { if( 0 == retval ) { if ( debug <= ATMEL_DEBUG_THRESHOLD && isatty(2) ) { fprintf( stderr, PROGRESS_END ); } fprintf( stderr, "Success\n" ); } else { if ( debug <= ATMEL_DEBUG_THRESHOLD && isatty(2) ) { fprintf( stderr, PROGRESS_ERROR ); } fprintf( stderr, "ERROR\n" ); if( retval==-3 ) fprintf( stderr, "Memory access error, use debug for more info.\n" ); else if( retval==-5 ) fprintf( stderr, "Memory read error, use debug for more info.\n" ); } } return retval; } static int32_t __atmel_blank_page_check( dfu_device_t *device, const uint32_t start, const uint32_t end ) { uint8_t command[6] = { 0x03, 0x01, 0x00, 0x00, 0x00, 0x00 }; dfu_status_t status; TRACE( "%s( %p, 0x%08x, 0x%08x )\n", __FUNCTION__, device, start, end ); if( (NULL == device) ) { DEBUG( "ERROR: Invalid arguments, device pointer is NULL.\n" ); return -1; } else if ( start > end ) { DEBUG( "ERROR: End address 0x%X before start address 0x%X.\n", end, start ); return -1; } else if ( end >= ATMEL_64KB_PAGE ) { DEBUG( "ERROR: Address out of 64kb (0x10000) byte page range.\n", end ); return -1; } command[2] = 0xff & (start >> 8); command[3] = 0xff & start; command[4] = 0xff & (end >> 8); command[5] = 0xff & end; if( 6 != dfu_download(device, 6, command) ) { DEBUG( "__atmel_blank_page_check DFU_DNLOAD failed.\n" ); return -2; } if( 0 != dfu_get_status(device, &status) ) { DEBUG( "__atmel_blank_page_check DFU_GETSTATUS failed.\n" ); return -3; } // check status and proceed accordingly if( DFU_STATUS_OK == status.bStatus ) { DEBUG( "Flash region from 0x%X to 0x%X is blank.\n", start, end ); } else if ( DFU_STATUS_ERROR_CHECK_ERASED == status.bStatus ) { // need to DFU upload to get the address DEBUG( "Region is NOT bank.\n" ); uint8_t addr[2] = { 0x00, 0x00 }; int32_t retval = 0; if ( 2 != dfu_upload(device, 2, addr) ) { DEBUG( "__atmel_blank_page_check DFU_UPLOAD failed.\n" ); return -4; } else { retval = (int32_t) ( ( ((uint16_t) addr[0]) << 8 ) + addr[1] ); DEBUG( " First non-blank address in region is 0x%X.\n", retval ); return retval + 1; } } else { DEBUG( "Error: status (%s) was not OK.\n", dfu_status_to_string(status.bStatus) ); if ( STATE_DFU_ERROR == status.bState ) { dfu_clear_status( device ); } return -4; } return 0; } int32_t atmel_blank_check( dfu_device_t *device, const uint32_t start, const uint32_t end, bool quiet ) { int32_t result; // blank_page_check_result uint32_t blank_upto = start; // up to is not inclusive uint32_t check_until; // end address of page check uint16_t current_page; // 64kb page number int32_t retval; TRACE( "%s( %p, 0x%08X, 0x%08X )\n", __FUNCTION__, device, start, end ); if( (NULL == device) ) { DEBUG( "ERROR: Invalid arguments, device pointer is NULL.\n" ); return -1; } else if ( start > end ) { DEBUG( "ERROR: End address 0x%X before start address 0x%X.\n", end, start ); return -1; } // safe to call this with any type of device if( 0 != atmel_select_memory_unit(device, mem_flash) ) { return -2; } if( !quiet ) { fprintf( stderr, "Checking memory from 0x%X to 0x%X... ", start, end ); // from here need to go to retval on error if( debug > ATMEL_DEBUG_THRESHOLD ) fprintf( stderr, "\n" ); } do { // want to have checks align with pages current_page = blank_upto / ATMEL_64KB_PAGE; check_until = ( current_page + 1 ) * ATMEL_64KB_PAGE - 1; check_until = check_until > end ? end : check_until; // safe to call with any type of device (just bc end address is // below 0x10000 doesn't mean you are definitely on page 0) if ( 0 != atmel_select_page(device, current_page) ) { DEBUG ("page select error.\n"); retval = -3; goto error; } // send the 'page' address, not absolute address result = __atmel_blank_page_check( device, blank_upto % ATMEL_64KB_PAGE, check_until % ATMEL_64KB_PAGE ); if ( result == 0 ) { DEBUG ( "Flash blank from 0x%X to 0x%X.\n", start, check_until ); blank_upto = check_until + 1; } else if ( result > 0 ) { blank_upto = result - 1 + ATMEL_64KB_PAGE * current_page; DEBUG ( "Flash NOT blank beginning at 0x%X.\n", blank_upto ); retval = blank_upto + 1; goto error; } else { DEBUG ( "Blank check fail err %d. Flash status unknown.\n", result ); retval = result; goto error; } } while ( blank_upto < end ); retval = 0; error: if( retval == 0 ) { if( !quiet ) fprintf( stderr, "Empty.\n" ); } else if ( retval > 0 ) { if( !quiet ) fprintf( stderr, "Not blank at 0x%X.\n", retval ); } else { if( !quiet ) fprintf( stderr, "ERROR.\n" ); } return retval; } int32_t atmel_start_app_reset( dfu_device_t *device ) { uint8_t command[3] = { 0x04, 0x03, 0x00 }; int32_t retval; TRACE( "%s( %p )\n", __FUNCTION__, device ); if( 3 != dfu_download(device, 3, command) ) { DEBUG( "dfu_download failed.\n" ); return -1; } if( 0 != (retval = dfu_download(device, 0, NULL)) ) { DEBUG( "dfu_download failed (rv=%d).\n", retval ); return -2; } return 0; } int32_t atmel_start_app_noreset( dfu_device_t *device ) { uint8_t command[5] = { 0x04, 0x03, 0x01, 0x00, 0x00 }; TRACE( "%s( %p )\n", __FUNCTION__, device ); if( 5 != dfu_download(device, 5, command) ) { DEBUG( "dfu_download failed.\n" ); return -1; } if( 0 != dfu_download(device, 0, NULL) ) { DEBUG( "dfu_download failed.\n" ); return -2; } return 0; } static int32_t atmel_select_memory_unit( dfu_device_t *device, enum atmel_memory_unit_enum unit ) { TRACE( "%s( %p, %d )\n", __FUNCTION__, device, unit ); uint8_t command[4] = { 0x06, 0x03, 0x00, (0xFF & unit) }; dfu_status_t status; char *mem_names[] = { ATMEL_MEM_UNIT_NAMES }; // input parameter checks if( NULL == device) { DEBUG ( "ERROR: Device pointer is NULL.\n" ); return -1; } // check compatiblity with various devices if( !(GRP_AVR32 & device->type) ) { DEBUG( "Ignore Select Memory Unit for non GRP_AVR32 device.\n" ); return 0; } else if ( (ADC_AVR32 & device->type) && !( unit == mem_flash || unit == mem_security || unit == mem_config || unit == mem_boot || unit == mem_sig || unit == mem_user ) ) { DEBUG( "%d is not a valid memory unit for AVR32 devices.\n", unit ); fprintf( stderr, "Invalid Memory Unit Selection.\n" ); return -1; } else if ( unit > mem_extdf ) { DEBUG( "Valid Memory Units 0 to 0x%X, not 0x%X.\n", mem_extdf, unit ); fprintf( stderr, "Invalid Memory Unit Selection.\n" ); return -1; } // select memory unit below is OK bc unit < len(mem_names) DEBUG( "Selecting %s memory unit.\n", mem_names[unit] ); if( 4 != dfu_download(device, 4, command) ) { DEBUG( "atmel_select_memory_unit 0x%02X dfu_download failed.\n", unit ); return -2; } // check that memory section was selected if( 0 != dfu_get_status(device, &status) ) { DEBUG( "DFU_GETSTATUS failed after atmel_select_memory_unit.\n" ); return -3; } // if error, report and clear if( DFU_STATUS_OK != status.bStatus ) { DEBUG( "Error: status (%s) was not OK.\n", dfu_status_to_string(status.bStatus) ); if ( STATE_DFU_ERROR == status.bState ) { dfu_clear_status( device ); } return -4; } return 0; } static int32_t atmel_select_page( dfu_device_t *device, const uint16_t mem_page ) { TRACE( "%s( %p, %u )\n", __FUNCTION__, device, mem_page ); dfu_status_t status; if( NULL == device ) { DEBUG ( "ERROR: Device pointer is NULL.\n" ); return -2; } if ( ADC_8051 & device->type ) { DEBUG( "Select page not implemented for 8051 device, ignoring.\n" ); return 0; } DEBUG( "Selecting page %d, address 0x%X.\n", mem_page, ATMEL_64KB_PAGE * mem_page ); if( GRP_AVR32 & device->type ) { uint8_t command[5] = { 0x06, 0x03, 0x01, 0x00, 0x00 }; command[3] = 0xff & (mem_page >> 8); command[4] = 0xff & mem_page; if( 5 != dfu_download(device, 5, command) ) { DEBUG( "atmel_select_page DFU_DNLOAD failed.\n" ); return -1; } } else if( ADC_AVR == device->type ) { // AVR but not 8051 uint8_t command[4] = { 0x06, 0x03, 0x00, 0x00 }; command[3] = 0xff & mem_page; if( 4 != dfu_download(device, 4, command) ) { DEBUG( "atmel_select_page DFU_DNLOAD failed.\n" ); return -1; } } // check that page number was set if( 0 != dfu_get_status(device, &status) ) { DEBUG( "atmel_select_page DFU_GETSTATUS failed.\n" ); return -3; } // if error, report and clear if( DFU_STATUS_OK != status.bStatus ) { DEBUG( "Error: status (%s) was not OK.\n", dfu_status_to_string(status.bStatus) ); if ( STATE_DFU_ERROR == status.bState ) { dfu_clear_status( device ); } return -4; } return 0; } int32_t atmel_user( dfu_device_t *device, intel_buffer_out_t *bout ) { int32_t result = 0; TRACE( "%s( %p, %p )\n", __FUNCTION__, device, bout ); if( (NULL == bout) || (NULL == device ) ) { DEBUG( "invalid arguments.\n" ); return -1; } /* Select USER page */ if( 0 != atmel_select_memory_unit(device, mem_user) ) { DEBUG( "User Page Memory NOT selected.\n" ); return -2; } else { DEBUG( "User Page memory selected.\n" ); } bout->info.block_start = 0; bout->info.block_end = bout->info.page_size - 1; //The user block is one flash page, so we'll just do it all in a block. result = __atmel_flash_block( device, bout, false ); if( result != 0 ) { DEBUG( "error flashing the block: %d\n", result ); return -4; } return 0; } int32_t atmel_secure( dfu_device_t *device ) { int32_t result = 0; uint16_t buffer[1]; intel_buffer_out_t bout; TRACE( "%s( %p )\n", __FUNCTION__, device ); /* Select SECURITY page */ uint8_t command[4] = { 0x06, 0x03, 0x00, 0x02 }; if( 4 != dfu_download(device, 4, command) ) { DEBUG( "dfu_download failed.\n" ); return -2; } bout.info.block_start = 0; bout.info.block_end = 0; bout.data = buffer; // The security block is a single byte, so we'll just do it all in a block. buffer[0] = 0x01; // Non-zero to set security fuse. result = __atmel_flash_block( device, &bout, false ); if( result != 0 ) { DEBUG( "error flashing security fuse: %d\n", result ); return -4; } return 0; } int32_t atmel_getsecure( dfu_device_t *device ) { int32_t result = 0; uint8_t buffer[1]; TRACE( "%s( %p )\n", __FUNCTION__, device ); intel_buffer_in_t buin; // init the necessary parts of buin buin.info.block_start = 0; buin.info.block_end = 0; buin.data = buffer; dfu_clear_status( device ); // TODO : Probably should use select_memory_unit command here /* Select SECURITY page */ uint8_t command[4] = { 0x06, 0x03, 0x00, 0x02 }; result = dfu_download(device, 4, command); if( 4 != result ) { if( -EIO == result ) { /* This also happens on most access attempts * when the security bit is set. It may be a bug * in the bootloader itself. */ return ATMEL_SECURE_MAYBE; } else { DEBUG( "dfu_download failed.\n" ); return -1; } } // The security block is a single byte, so we'll just do it all in a block. if( 0 != __atmel_read_block(device, &buin, false) ) { return -2; } return( (0 == buffer[0]) ? ATMEL_SECURE_OFF : ATMEL_SECURE_ON ); } int32_t atmel_flash( dfu_device_t *device, intel_buffer_out_t *bout, const bool eeprom, const bool force, const bool quiet ) { uint32_t i; uint32_t progress = 0; // keep record of sent progress as bytes * 32 uint8_t mem_page = 0; // tracks the current memory page int32_t result = 0; // result storage for many function calls int32_t retval = -1; // the return value for this function TRACE( "%s( %p, %p, %s, %s )\n", __FUNCTION__, device, bout, ((true == eeprom) ? "true" : "false"), ((true == quiet) ? "true" : "false") ); // check arguments if( (NULL == device) || (NULL == bout) ) { DEBUG( "ERROR: Invalid arguments, device/buffer pointer is NULL.\n" ); if( !quiet ) fprintf( stderr, "Program Error, use debug for more info.\n" ); return -1; } else if ( bout->info.valid_start > bout->info.valid_end ) { DEBUG( "ERROR: No valid target memory, end 0x%X before start 0x%X.\n", bout->info.valid_end, bout->info.valid_start ); if( !quiet ) fprintf( stderr, "Program Error, use debug for more info.\n" ); return -1; } // for each page with data, fill unassigned values on the page with 0xFF // bout->data[0] always aligns with a flash page boundary irrespective // of where valid_start is located if( 0 != intel_flash_prep_buffer( bout ) ) { if( !quiet ) fprintf( stderr, "Program Error, use debug for more info.\n" ); return -2; } // determine the limits of where actual data resides in the buffer bout->info.data_start = UINT32_MAX; for( i = 0; i < bout->info.total_size; i++ ) { if( bout->data[i] <= UINT8_MAX ) { bout->info.data_end = i; if (bout->info.data_start == UINT32_MAX) bout->info.data_start = i; } } // debug info about data limits DEBUG("Flash available from 0x%X to 0x%X (64kB p. %u to %u), 0x%X bytes.\n", bout->info.valid_start, bout->info.valid_end, bout->info.valid_start / ATMEL_64KB_PAGE, bout->info.valid_end / ATMEL_64KB_PAGE, bout->info.valid_end - bout->info.valid_start + 1); // bytes inclusive so +1 DEBUG("Data start @ 0x%X: 64kB p %u; %uB p 0x%X + 0x%X offset.\n", bout->info.data_start, bout->info.data_start / ATMEL_64KB_PAGE, bout->info.page_size, bout->info.data_start / bout->info.page_size, bout->info.data_start % bout->info.page_size); DEBUG("Data end @ 0x%X: 64kB p %u; %uB p 0x%X + 0x%X offset.\n", bout->info.data_end, bout->info.data_end / ATMEL_64KB_PAGE, bout->info.page_size, bout->info.data_end / bout->info.page_size, bout->info.data_end % bout->info.page_size); DEBUG("Totals: 0x%X bytes, %u %uB pages, %u 64kB byte pages.\n", bout->info.data_end - bout->info.data_start + 1, bout->info.data_end/bout->info.page_size - bout->info.data_start/bout->info.page_size + 1, bout->info.page_size, bout->info.data_end/ATMEL_64KB_PAGE - bout->info.data_start/ATMEL_64KB_PAGE + 1 ); // more error checking if( (bout->info.data_start < bout->info.valid_start) || (bout->info.data_end > bout->info.valid_end) ) { DEBUG( "ERROR: Data exists outside of the valid target flash region.\n" ); if( !quiet ) fprintf( stderr, "Hex file error, use debug for more info.\n" ); return -1; } else if( bout->info.data_start == UINT32_MAX ) { DEBUG( "ERROR: No valid data to flash.\n" ); if( !quiet ) fprintf( stderr, "Hex file error, use debug for more info.\n" ); return -1; } else if( !force && 0 != (result = atmel_blank_check(device, bout->info.data_start, bout->info.data_end, quiet)) ) { if ( !quiet ) fprintf( stderr, "The target memory for the program is not blank.\n" "Use --force flag to override this error check.\n"); DEBUG("The target memory is not blank.\n"); return -1; } // select eeprom/flash as the desired memory target, safe for non GRP_AVR32 mem_page = eeprom ? mem_eeprom : mem_flash; if( 0 != atmel_select_memory_unit(device, mem_page) ) { DEBUG ("Error selecting memory unit.\n"); if( !quiet ) fprintf( stderr, "Memory access error, use debug for more info.\n" ); return -2; } if( !quiet ) { if( debug <= ATMEL_DEBUG_THRESHOLD && isatty(2) ) { // NOTE: from here on we need to run finally block fprintf( stderr, PROGRESS_METER ); } fprintf( stderr, "Programming 0x%X bytes...\n", bout->info.data_end - bout->info.data_start + 1 ); if( debug <= ATMEL_DEBUG_THRESHOLD && isatty(2) ) { // NOTE: from here on we need to run finally block fprintf( stderr, PROGRESS_START ); } } // program the data bout->info.block_start = bout->info.data_start; mem_page = bout->info.block_start / ATMEL_64KB_PAGE; if( 0 != (result = atmel_select_page( device, mem_page )) ) { DEBUG( "ERROR selecting 64kB page %d.\n", result ); retval = -3; goto finally; } while (bout->info.block_start <= bout->info.data_end) { // select the memory page if needed (safe for non GRP_AVR32) if ( bout->info.block_start / ATMEL_64KB_PAGE != mem_page ) { mem_page = bout->info.block_start / ATMEL_64KB_PAGE; if( 0 != (result = atmel_select_page( device, mem_page )) ) { DEBUG( "ERROR selecting 64kB page %d.\n", result ); retval = -3; goto finally; } } // find end address (info.block_end) for data section to write for(bout->info.block_end = bout->info.block_start; bout->info.block_end <= bout->info.data_end; bout->info.block_end++) { // check if the current value is valid if( bout->data[bout->info.block_end] > UINT8_MAX ) break; // check if the current data packet is too big if( (bout->info.block_end - bout->info.block_start + 1) > ATMEL_MAX_TRANSFER_SIZE ) break; // check if the current data value is outside of the 64kB flash page if( bout->info.block_end / ATMEL_64KB_PAGE - mem_page ) break; } bout->info.block_end--; // bout->info.block_end was one step beyond the last data value to flash // write the data DEBUG("Program data block: 0x%X to 0x%X (p. %u), 0x%X bytes.\n", bout->info.block_start, bout->info.block_end, bout->info.block_end / ATMEL_64KB_PAGE, bout->info.block_end - bout->info.block_start + 1); result = __atmel_flash_block( device, bout, eeprom ); if( 0 != result ) { DEBUG( "Error flashing the block: err %d.\n", result ); retval = -4; goto finally; } // increment bout->info.block_start to the next valid address for(bout->info.block_start = bout->info.block_end + 1; bout->info.block_start <= bout->info.data_end; bout->info.block_start++) { if( (bout->data[bout->info.block_start] <= UINT8_MAX) ) break; } // bout->info.block_start is now on the first valid data for the next segment // display progress in 32 increments (if not hidden) if ( !quiet ) __print_progress( &bout->info, &progress ); } retval = 0; finally: if ( !quiet ) { if( 0 == retval ) { if ( debug <= ATMEL_DEBUG_THRESHOLD && isatty(2) ) { fprintf( stderr, PROGRESS_END ); } fprintf( stderr, "Success\n" ); } else { if ( debug <= ATMEL_DEBUG_THRESHOLD && isatty(2) ) { fprintf( stderr, PROGRESS_ERROR ); } fprintf( stderr, "ERROR\n" ); if( retval==-3 ) fprintf( stderr, "Memory access error, use debug for more info.\n" ); else if( retval==-4 ) fprintf( stderr, "Memory write error, use debug for more info.\n" ); } } return retval; } static void atmel_flash_populate_footer( uint8_t *message, uint8_t *footer, const uint16_t vendorId, const uint16_t productId, const uint16_t bcdFirmware ) { int32_t crc; TRACE( "%s( %p, %p, %u, %u, %u )\n", __FUNCTION__, message, footer, vendorId, productId, bcdFirmware ); if( (NULL == message) || (NULL == footer) ) { return; } /* TODO: Calculate the message CRC */ crc = 0; /* CRC 4 bytes */ footer[0] = 0xff & (crc >> 24); footer[1] = 0xff & (crc >> 16); footer[2] = 0xff & (crc >> 8); footer[3] = 0xff & crc; /* Length of DFU suffix - always 16. */ footer[4] = 16; /* ucdfuSignature - fixed 'DFU'. */ footer[5] = 'D'; footer[6] = 'F'; footer[7] = 'U'; /* BCD DFU specification number (1.1)*/ footer[8] = 0x01; footer[9] = 0x10; /* Vendor ID or 0xFFFF */ footer[10] = 0xff & (vendorId >> 8); footer[11] = 0xff & vendorId; /* Product ID or 0xFFFF */ footer[12] = 0xff & (productId >> 8); footer[13] = 0xff & productId; /* BCD Firmware release number or 0xFFFF */ footer[14] = 0xff & (bcdFirmware >> 8); footer[15] = 0xff & bcdFirmware; } static void atmel_flash_populate_header( uint8_t *header, const uint32_t start, const uint32_t end, const bool eeprom ) { TRACE( "%s( %p, 0x%X, 0x%X, %s )\n", __FUNCTION__, header, start, end, ((true == eeprom) ? "true" : "false") ); if( NULL == header ) { return; } /* Command Identifier */ header[0] = 0x01; /* ld_prog_start */ /* data[0] */ header[1] = ((true == eeprom) ? 0x01 : 0x00); /* start_address */ header[2] = 0xff & (start >> 8); header[3] = 0xff & start; /* end_address */ header[4] = 0xff & (end >> 8); header[5] = 0xff & end; } static int32_t __atmel_flash_block( dfu_device_t *device, intel_buffer_out_t *bout, const bool eeprom ) { // from doc7618, AT90 / ATmega app note protocol: const size_t length = bout->info.block_end - bout->info.block_start + 1; uint8_t message[ATMEL_MAX_FLASH_BUFFER_SIZE]; uint8_t *header; uint8_t *data; uint8_t *footer; size_t message_length; int32_t result; dfu_status_t status; int32_t i; size_t control_block_size; /* USB control block size */ size_t alignment; TRACE( "%s( %p, %p, %s )\n", __FUNCTION__, device, bout, ((true == eeprom) ? "true" : "false") ); // check input args if( (NULL == device) || (NULL == bout) ) { DEBUG( "ERROR: Invalid arguments, device/buffer pointer is NULL.\n" ); return -1; } else if ( bout->info.block_start > bout->info.block_end ) { DEBUG( "ERROR: End address 0x%X before start address 0x%X.\n", bout->info.block_end, bout->info.block_start ); return -1; } else if ( length > ATMEL_MAX_TRANSFER_SIZE ) { DEBUG( "ERROR: 0x%X byte message > MAX TRANSFER SIZE (0x%X).\n", length, ATMEL_MAX_TRANSFER_SIZE ); return -1; } // 0 out the message memset( message, 0, ATMEL_MAX_FLASH_BUFFER_SIZE ); if( GRP_AVR32 & device->type ) { control_block_size = ATMEL_AVR32_CONTROL_BLOCK_SIZE; alignment = bout->info.block_start % ATMEL_AVR32_CONTROL_BLOCK_SIZE; } else { control_block_size = ATMEL_CONTROL_BLOCK_SIZE; alignment = 0; } header = &message[0]; data = &message[control_block_size + alignment]; footer = &data[length]; atmel_flash_populate_header( header, bout->info.block_start % ATMEL_64KB_PAGE, bout->info.block_end % ATMEL_64KB_PAGE, eeprom ); /* for programming flash or eeprom for xmega or avr32, header[1] = 0x00 */ /* for programming eeprom, memory was selected in atmel_flash */ if( ADC_XMEGA & device->type ) { header[1] = 0x00; } // Copy the data for( i = 0; i < length; i++ ) { data[i] = (uint8_t) bout->data[bout->info.block_start + i]; } atmel_flash_populate_footer( message, footer, 0xffff, 0xffff, 0xffff ); message_length = ((size_t) (footer - header)) + ATMEL_FOOTER_SIZE; result = dfu_download( device, message_length, message ); if( message_length != result ) { if( -EPIPE == result ) { /* The control pipe stalled - this is an error * caused by the device saying "you can't do that" * which means the device is write protected. */ fprintf( stderr, "Device is write protected.\n" ); dfu_clear_status( device ); } else { DEBUG( "atmel_flash: flash data dfu_download failed.\n" ); DEBUG( "Expected message length of %d, got %d.\n", message_length, result ); } return -2; } // check status if( 0 != dfu_get_status(device, &status) ) { DEBUG( "dfu_get_status failed.\n" ); return -3; } if( DFU_STATUS_OK == status.bStatus ) { DEBUG( "Page write success.\n" ); } else { DEBUG( "Page write not unsuccessful (err %s).\n", dfu_status_to_string(status.bStatus) ); if ( STATE_DFU_ERROR == status.bState ) { dfu_clear_status( device ); } return (int32_t) status.bStatus; } return 0; } void atmel_print_device_info( FILE *stream, atmel_device_info_t *info ) { fprintf( stream, "%18s: 0x%04x - %d\n", "Bootloader Version", info->bootloaderVersion, info->bootloaderVersion ); fprintf( stream, "%18s: 0x%04x - %d\n", "Device boot ID 1", info->bootID1, info->bootID1 ); fprintf( stream, "%18s: 0x%04x - %d\n", "Device boot ID 2", info->bootID2, info->bootID2 ); if( /* device is 8051 based */ 0 ) { fprintf( stream, "%18s: 0x%04x - %d\n", "Device BSB", info->bsb, info->bsb ); fprintf( stream, "%18s: 0x%04x - %d\n", "Device SBV", info->sbv, info->sbv ); fprintf( stream, "%18s: 0x%04x - %d\n", "Device SSB", info->ssb, info->ssb ); fprintf( stream, "%18s: 0x%04x - %d\n", "Device EB", info->eb, info->eb ); } fprintf( stream, "%18s: 0x%04x - %d\n", "Manufacturer Code", info->manufacturerCode, info->manufacturerCode ); fprintf( stream, "%18s: 0x%04x - %d\n", "Family Code", info->familyCode, info->familyCode ); fprintf( stream, "%18s: 0x%04x - %d\n", "Product Name", info->productName, info->productName ); fprintf( stream, "%18s: 0x%04x - %d\n", "Product Revision", info->productRevision, info->productRevision ); fprintf( stream, "%18s: 0x%04x - %d\n", "HWB", info->hsb, info->hsb ); } dfu-programmer-dfu-programmer-f23d6df/src/atmel.h000066400000000000000000000156671445234667400221660ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef __ATMEL_H__ #define __ATMEL_H__ #include #include #include #ifdef __cplusplus extern "C" { #endif #include "dfu-device.h" #include "intel_hex.h" #define ATMEL_USER_PAGE_OFFSET 0x80800000 #define ATMEL_ERASE_BLOCK_0 0 #define ATMEL_ERASE_BLOCK_1 1 #define ATMEL_ERASE_BLOCK_2 2 #define ATMEL_ERASE_BLOCK_3 3 #define ATMEL_ERASE_ALL 4 #define ATMEL_SET_CONFIG_BSB 0 #define ATMEL_SET_CONFIG_SBV 1 #define ATMEL_SET_CONFIG_SSB 2 #define ATMEL_SET_CONFIG_EB 3 #define ATMEL_SET_CONFIG_HSB 4 #define ATMEL_SECURE_OFF 0 // Security bit is cleared #define ATMEL_SECURE_ON 1 // Security bit is set #define ATMEL_SECURE_MAYBE 2 // Call to check security bit failed /* All values are valid if in the range of 0-255, invalid otherwise */ typedef struct { int16_t bootloaderVersion; // Bootloader Version int16_t bootID1; // Device boot ID 1 int16_t bootID2; // Device boot ID 2 int16_t bsb; // Boot Status Byte int16_t sbv; // Software Boot Vector int16_t ssb; // Software Security Byte int16_t eb; // Extra Byte int16_t manufacturerCode; // Manufacturer Code int16_t familyCode; // Family Code int16_t productName; // Product Name int16_t productRevision; // Product Revision int16_t hsb; // Hardware Security Byte } atmel_device_info_t; typedef struct { int32_t lock; // Locked region int32_t epfl; // External Privileged fetch lock int32_t bootprot; // Bootloader protected area int32_t bodlevel; // Brown-out detector trigger level int32_t bodhyst; // BOD hysteresis enable int32_t boden; // BOD enable state int32_t isp_bod_en; // Tells the ISP to enable BOD int32_t isp_io_cond_en; // ISP uses User page to launch bootloader int32_t isp_force; // Start the ISP no matter what } atmel_avr32_fuses_t; enum atmel_memory_unit_enum { mem_flash, mem_eeprom, mem_security, mem_config, mem_boot, mem_sig, mem_user, mem_ram, mem_ext0, mem_ext1, mem_ext2, mem_ext3, mem_ext, mem_ext5, mem_ext6, mem_ext7, mem_extdf }; #define ATMEL_MEM_UNIT_NAMES "flash", "eeprom", "security", "config", \ "bootloader", "signature", "user", "int_ram", "ext_cs0", "ext_cs1", \ "ext_cs2", "ext_cs3", "ext_cs4", "ext_cs5", "ext_cs6", "ext_cs7", "ext_df" int32_t atmel_read_config( dfu_device_t *device, atmel_device_info_t *info ); /* atmel_read_config reads in all of the configuration and Manufacturer * Information into the atmel_device_info data structure for easier use later. * * device - the usb_dev_handle to communicate with * info - the data structure to populate * * returns 0 if successful, < 0 if not */ int32_t atmel_read_fuses( dfu_device_t *device, atmel_avr32_fuses_t * info ); int32_t atmel_erase_flash( dfu_device_t *device, const uint8_t mode, bool quiet ); /* atmel_erase_flash * device - the usb_dev_handle to communicate with * mode - the mode to use when erasing flash * ATMEL_ERASE_BLOCK_0 * ATMEL_ERASE_BLOCK_1 * ATMEL_ERASE_BLOCK_2 * ATMEL_ERASE_BLOCK_3 * ATMEL_ERASE_ALL * * returns status DFU_STATUS_OK if ok, anything else on error */ int32_t atmel_set_fuse( dfu_device_t *device, const uint8_t property, const uint32_t value ); int32_t atmel_set_config( dfu_device_t *device, const uint8_t property, const uint8_t value ); int32_t atmel_read_flash( dfu_device_t *device, intel_buffer_in_t *buin, uint8_t mem_segment, const bool quiet); /* read the flash from buin->info.data_start to data_end and place * in buin.data. mem_segment is the segment of memory from the * atmel_memory_unit_enum. */ int32_t atmel_blank_check( dfu_device_t *device, const uint32_t start, const uint32_t end, bool quiet ); /* check if memory between start byte and end byte (inclusive) is blank * returns 0 for success, < 0 for communication errors, > 0 for not blank */ int32_t atmel_start_app_reset( dfu_device_t *device ); /* Reset the processor and start application. * This is done internally by forcing a watchdog reset. * Depending on fuse settings this may go straight back into the bootloader. */ int32_t atmel_start_app_noreset( dfu_device_t *device ); /* Start the app by jumping to the start of the app area. * This does not do a true device reset. */ int32_t atmel_secure( dfu_device_t *device ); int32_t atmel_getsecure( dfu_device_t *device ); int32_t atmel_flash( dfu_device_t *device, intel_buffer_out_t *bout, const bool eeprom, const bool force, const bool hide_progress ); /* Flash data from the buffer to the main program memory on the device. * buffer contains the data to flash where buffer[0] is aligned with memory * address zero (which could be inside the bootloader and unavailable). * buffer[start / end] correspond to the start / end of available memory * outside the bootloader. * flash_page_size is the size of flash pages - used for alignment * eeprom bool tells if you want to flash to eeprom or flash memory * hide_progress bool sets whether to display progress */ int32_t atmel_user( dfu_device_t *device, intel_buffer_out_t *bout ); /* Flash data to the user page. Provide the buffer and the size of * flash pages for the device (this is the size of the user page). * Note that only the entire user page can be flashed because it is * deleted before it is flashed to. Therfore buffer must fill this * space (start at zero and contain page_size bytes). */ void atmel_print_device_info( FILE *stream, atmel_device_info_t *info ); #ifdef __cplusplus } #endif #endif dfu-programmer-dfu-programmer-f23d6df/src/commands.c000066400000000000000000000750341445234667400226520ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include "config.h" #include "commands.h" #include "arguments.h" #include "intel_hex.h" #include "stm32.h" #include "atmel.h" #include "util.h" #define COMMAND_DEBUG_THRESHOLD 40 #define DEBUG(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, \ COMMAND_DEBUG_THRESHOLD, __VA_ARGS__ ) // ________ P R O T O T Y P E S _______________________________ static int32_t execute_validate( dfu_device_t *device, intel_buffer_out_t *bout, uint8_t mem_segment, bool quiet, bool ignore_outside); /* provide an out buffer to validate and whether this is from * flash or eeprom data sections, also wether you want it quiet */ // ________ F U N C T I O N S _______________________________ static void security_check( dfu_device_t *device ) { if( ADC_AVR32 == device->type ) { // Get security bit state for AVR32. device->security_bit_state = atmel_getsecure( device ); DEBUG( "Security bit check returned %d.\n", device->security_bit_state ); } else { // Security bit not present or not testable. device->security_bit_state = ATMEL_SECURE_OFF; } } static void security_message( dfu_device_t *device ) { if( device->security_bit_state > ATMEL_SECURE_OFF ) { fprintf( stderr, "The security bit %s set.\n" "Erase the device to clear temporarily.\n", (ATMEL_SECURE_ON == device->security_bit_state) ? "is" : "may be" ); } } static int32_t execute_erase( dfu_device_t *device, struct programmer_arguments *args ) { int32_t result = SUCCESS; if( !(GRP_STM32 & args->device_type) && !args->com_erase_data.force ) { if( 0 == atmel_blank_check( device, args->flash_address_bottom, args->flash_address_top, args->quiet ) ) { if ( !args->quiet ) { fprintf( stderr, "Chip already blank, to force erase use --force.\n"); } return SUCCESS; } } DEBUG( "erase 0x%X bytes.\n", (args->flash_address_top - args->flash_address_bottom) ); if( GRP_STM32 & args->device_type ) { result = stm32_erase_flash( device, args->quiet ); } else { result = atmel_erase_flash( device, ATMEL_ERASE_ALL, args->quiet ); } if( 0 != result ) { return result; } if( !(GRP_STM32 & args->device_type) && !args->com_erase_data.suppress_validation ) { result = atmel_blank_check( device, args->flash_address_bottom, args->flash_address_top, args->quiet ); } return result; } static int32_t execute_setsecure( dfu_device_t *device, struct programmer_arguments *args ) { int32_t result; if( ADC_AVR32 != args->device_type ) { DEBUG( "target doesn't support security bit set.\n" ); fprintf( stderr, "Operation not supported on %s\n", args->device_type_string ); return ARGUMENT_ERROR; } result = atmel_secure( device ); if( result < 0 ) { DEBUG( "Error while setting security bit. (%d)\n", result ); fprintf( stderr, "Error setting security bit.\n" ); return UNSPECIFIED_ERROR; } return SUCCESS; } // TODO : split this into a new command (no file is needed) - also general // format of this program is that only 1 command is run at a time.. caveat is // that if program sets a section in memory to '\0' and serialize sets it // otherwise, the section will end up '\0' unless a page erase is used.. so may // need to keep this part of the flash command, but specify that serialize data // 'wins' over data from the hex file static int32_t serialize_memory_image( intel_buffer_out_t *bout, struct programmer_arguments *args ) { uint32_t target_offset = 0; if( args->command == com_user ) target_offset = ATMEL_USER_PAGE_OFFSET; else if( args->device_type & GRP_STM32 ) target_offset = STM32_FLASH_OFFSET; if ( NULL != args->com_flash_data.serial_data ) { int16_t *serial_data = args->com_flash_data.serial_data; uint32_t length = args->com_flash_data.serial_length; uint32_t offset = args->com_flash_data.serial_offset; uint32_t i; for( i=0; i < length; ++i ) { if ( 0 != intel_process_data(bout, serial_data[i], target_offset, offset + i) ) { return BUFFER_INIT_ERROR; } } } return SUCCESS; } static int32_t execute_validate( dfu_device_t *device, intel_buffer_out_t *bout, uint8_t mem_segment, const bool quiet, const bool ignore_outside) { int32_t retval = UNSPECIFIED_ERROR; int32_t result; // result of fcn calls intel_buffer_in_t buin; // buffer in for storing read mem if( 0 != intel_init_buffer_in(&buin, bout->info.total_size, bout->info.page_size ) ) { DEBUG("ERROR initializing a buffer.\n"); retval = BUFFER_INIT_ERROR; goto error; } buin.info.data_start = bout->info.valid_start; buin.info.data_end = bout->info.valid_end; if( device->type & GRP_STM32 ) { result = stm32_read_flash( device, &buin, mem_segment, quiet ); } else { result = atmel_read_flash( device, &buin, mem_segment, quiet ); } if( 0 != result ) { DEBUG("ERROR: could not read memory, err %d.\n", result); retval = FLASH_READ_ERROR; goto error; } if( 0 != (result = intel_validate_buffer( &buin, bout, quiet )) ) { if( result < 0 ) { retval = VALIDATION_ERROR_IN_REGION; } else { if (ignore_outside) { retval = SUCCESS; } else { retval = VALIDATION_ERROR_OUTSIDE_REGION; } } goto error; } retval = SUCCESS; error: if( !quiet && SUCCESS != retval ) fprintf( stderr, "FAIL\n" ); if( NULL != buin.data ) { free( buin.data ); buin.data = NULL; } return retval; } static void print_flash_usage( intel_buffer_info_t *info ) { fprintf( stderr, "0x%X bytes written into 0x%X bytes memory (%.02f%%).\n", info->data_end - info->data_start + 1, info->valid_end - info->valid_start + 1, ((float) (100 * (info->data_end - info->data_start + 1)) / (float) (info->valid_end - info->valid_start + 1)) ) ; } static int32_t execute_flash( dfu_device_t *device, struct programmer_arguments *args ) { int32_t retval = UNSPECIFIED_ERROR; int32_t result; uint32_t i; intel_buffer_out_t bout; size_t memory_size; size_t page_size; enum atmel_memory_unit_enum mem_type = args->com_flash_data.segment; uint32_t target_offset = 0; /* assign the correct memory size */ switch ( mem_type ) { case mem_flash: if( args->device_type & GRP_STM32 ) { target_offset = STM32_FLASH_OFFSET; } memory_size = args->memory_address_top + 1; page_size = args->flash_page_size; break; case mem_eeprom: if( 0 == args->eeprom_memory_size ) { fprintf( stderr, "This device has no eeprom.\n" ); return ARGUMENT_ERROR; } memory_size = args->eeprom_memory_size; page_size = args->eeprom_page_size; break; case mem_user: memory_size = args->flash_page_size; page_size = args->flash_page_size; mem_type = mem_user; target_offset = ATMEL_USER_PAGE_OFFSET; if( args->device_type != ADC_AVR32 ){ fprintf(stderr, "Flash User only implemented for ADC_AVR32 devices.\n"); retval = ARGUMENT_ERROR; goto error; } break; default: DEBUG("Unknown memory type %d\n", mem_type); return ARGUMENT_ERROR; } // ----------------- CONVERT HEX FILE TO BINARY ------------------------- if( 0 != intel_init_buffer_out(&bout, memory_size, page_size) ) { DEBUG("ERROR initializing a buffer.\n"); retval = BUFFER_INIT_ERROR; goto error; } result = intel_hex_to_buffer( args->com_flash_data.file, &bout, target_offset, args->quiet ); if ( result < 0 ) { DEBUG( "Something went wrong with creating the memory image.\n" ); retval = BUFFER_INIT_ERROR; goto error; } else if ( result > 0 ) { DEBUG( "WARNING: File contains 0x%X bytes outside target memory.\n", result ); if( mem_type == mem_flash ) { DEBUG( "There may be data in the user page (offset %#X).\n", ATMEL_USER_PAGE_OFFSET ); DEBUG( "Inspect the hex file or try flash-user.\n" ); } if( !args->quiet ) { fprintf( stderr, "WARNING: 0x%X bytes are outside target memory,\n", result ); fprintf( stderr, " and will not be written.\n" ); } } // TODO : consider accepting a string to flash to the user page as well as a hex // file.. this would be easier than using serialize and could return the address // location of the start of the string (to be used in the program file) if (0 != serialize_memory_image( &bout, args )) { retval = BUFFER_INIT_ERROR; goto error; } if( mem_type == mem_flash ) { bout.info.valid_start = args->flash_address_bottom; bout.info.valid_end = args->flash_address_top; // check that there isn't anything overlapping the bootloader for( i = args->bootloader_bottom; i <= args->bootloader_top; i++) { if( bout.data[i] <= UINT8_MAX ) { if( true == args->suppressBootloader ) { //If we're ignoring the bootloader, don't write to it bout.data[i] = UINT16_MAX; } else { fprintf( stderr, "Bootloader and code overlap.\n" ); fprintf( stderr, "Use --suppress-bootloader-mem to ignore\n" ); retval = BUFFER_INIT_ERROR; goto error; } } } } else if ( mem_type == mem_user ) { // check here about overwriting? if ( bout.info.data_start == UINT32_MAX ) { fprintf( stderr, "ERROR: No data to write into the user page.\n" ); retval = BUFFER_INIT_ERROR; goto error; } else { DEBUG("Hex file contains %u bytes to write.\n", bout.info.data_end - bout.info.data_start + 1 ); } if ( !(args->com_flash_data.force) ) { /* depending on the version of the bootloader, there could be * configuration values in the last word or last two words of the * user page. If these are overwritten the device may not start. * A warning should be issued before these values can be changed. */ fprintf( stderr, "ERROR: --force flag is required to write user page.\n" ); fprintf( stderr, " Last word(s) in user page contain configuration data.\n"); fprintf( stderr, " The user page is erased whenever any data is written.\n"); fprintf( stderr, " Without valid config. device always resets in bootloader.\n"); fprintf( stderr, " Use dump-user to obtain valid configuration words.\n"); retval = ARGUMENT_ERROR; goto error; // TODO : implement so this error only appears when data overlaps the // bootloader configuration words. This would require reading the user // page to add that data to the buffer, and also should include // checking the bootloader version to make sure the right number of // words are blocked / written. // ----------- the below for loop is not currently in use ----------- for ( i = bout.info.total_size - 8; i < bout.info.total_size; i++ ) { if ( -1 != bout.data[i] ) { fprintf( stderr, "ERROR: data overlap with bootloader configuration word(s).\n" ); DEBUG( "At position %d, value is %d.\n", i, bout.data[i] ); fprintf( stderr, "ERROR: use the --force-config flag to write the data.\n" ); retval = ARGUMENT_ERROR; goto error; } } } } // ------------------ INITIAL VALIDATE (if required) ------------------- if ( 1 == args->com_flash_data.validate_first ) { if( 0 == ( retval = execute_validate(device, &bout, mem_type, args->quiet, args->com_flash_data.ignore_outside)) ) { goto success; } // Else, continue to flash } // ------------------ WRITE PROGRAM DATA ------------------------------- if( mem_type == mem_user ) { result = atmel_user( device, &bout ); } else { if ( 1 == args->com_flash_data.erase_first ) { if( args->device_type & GRP_STM32 ) { result = stm32_erase_flash( device, args->quiet ); } else { result = atmel_erase_flash( device, ATMEL_ERASE_ALL, args->quiet ); } if( 0 != result ) { DEBUG( "Error erasing flash. (err %d)\n", result ); return result; } } if( args->device_type & GRP_STM32 ) { result = stm32_write_flash( device, &bout, mem_type == mem_eeprom ? true : false, args->com_flash_data.force, args->quiet ); } else { result = atmel_flash(device, &bout, mem_type == mem_eeprom ? true : false, args->com_flash_data.force, args->quiet); } } if( 0 != result ) { DEBUG( "Error writing %s data. (err %d)\n", "memory", result ); retval = FLASH_WRITE_ERROR; goto error; } // ------------------ VALIDATE PROGRAM ------------------------------ if( 0 == args->com_flash_data.suppress_validation ) { if( 0 != ( retval = execute_validate(device, &bout, mem_type, args->quiet, args->com_flash_data.ignore_outside)) ) { fprintf( stderr, "Memory did not validate. Did you erase?\n" ); goto error; } else if ( 0 == args->quiet ) { print_flash_usage( &bout.info ); } } else if( 0 == args->quiet ) { print_flash_usage( &bout.info ); } success: retval = SUCCESS; error: if( NULL != bout.data ) { free( bout.data ); bout.data = NULL; } return retval; } static int32_t execute_getfuse( dfu_device_t *device, struct programmer_arguments *args ) { atmel_avr32_fuses_t info; char *message = NULL; int32_t value = 0; int32_t status; /* only ADC_AVR32 seems to support fuse operation */ if( !(ADC_AVR32 & args->device_type) ) { DEBUG( "target doesn't support fuse set operation.\n" ); fprintf( stderr, "target doesn't support fuse set operation.\n" ); return ARGUMENT_ERROR; } /* Check AVR32 security bit in order to provide a better error message. */ security_check( device ); if( args->device_type & GRP_STM32 ) { fprintf( stderr, "Operation not supported on %s.\n", args->device_type_string ); return ARGUMENT_ERROR; } else { status = atmel_read_fuses( device, &info ); } if( 0 != status ) { DEBUG( "Error reading %s config information.\n", args->device_type_string ); fprintf( stderr, "Error reading %s config information.\n", args->device_type_string ); security_message( device ); return status; } switch( args->com_getfuse_data.name ) { case get_lock: value = info.lock; message = "Locked regions"; break; case get_epfl: value = info.epfl; message = "External Privileged Fetch Lock"; break; case get_bootprot: value = info.bootprot; message = "Bootloader protected area"; break; case get_bodlevel: value = info.bodlevel; message = "Brown-out detector trigger level"; break; case get_bodhyst: value = info.bodhyst; message = "BOD Hysteresis enable"; break; case get_boden: value = info.boden; message = "BOD Enable"; break; case get_isp_bod_en: value = info.isp_bod_en; message = "ISP BOD enable"; break; case get_isp_io_cond_en: value = info.isp_io_cond_en; message = "ISP IO condition enable"; break; case get_isp_force: value = info.isp_force; message = "ISP Force"; break; } fprintf( stdout, "%s%s0x%02x (%d)\n", ((0 == args->quiet) ? message : ""), ((0 == args->quiet) ? ": " : ""), value, value ); return 0; } static int32_t execute_get( dfu_device_t *device, struct programmer_arguments *args ) { atmel_device_info_t info; char *message = NULL; int16_t value = 0; int32_t status; int32_t controller_error = 0; /* Check AVR32 security bit in order to provide a better error message. */ security_check( device ); if( args->device_type & GRP_STM32 ) { fprintf( stderr, "Operation not supported on %s.\n", args->device_type_string ); return -1; } else { status = atmel_read_config( device, &info ); } if( 0 != status ) { DEBUG( "Error reading %s config information.\n", args->device_type_string ); fprintf( stderr, "Error reading %s config information.\n", args->device_type_string ); security_message( device ); return status; } switch( args->com_get_data.name ) { case get_bootloader: value = info.bootloaderVersion; message = "Bootloader Version"; break; case get_ID1: value = info.bootID1; message = "Device boot ID 1"; break; case get_ID2: value = info.bootID2; message = "Device boot ID 2"; break; case get_BSB: value = info.bsb; message = "Boot Status Byte"; if( ADC_8051 != args->device_type ) { controller_error = 1; } break; case get_SBV: value = info.sbv; message = "Software Boot Vector"; if( ADC_8051 != args->device_type ) { controller_error = 1; } break; case get_SSB: value = info.ssb; message = "Software Security Byte"; if( ADC_8051 != args->device_type ) { controller_error = 1; } break; case get_EB: value = info.eb; message = "Extra Byte"; if( ADC_8051 != args->device_type ) { controller_error = 1; } break; case get_manufacturer: value = info.manufacturerCode; message = "Manufacturer Code"; break; case get_family: value = info.familyCode; message = "Family Code"; break; case get_product_name: value = info.productName; message = "Product Name"; break; case get_product_rev: value = info.productRevision; message = "Product Revision"; break; case get_HSB: value = info.hsb; message = "Hardware Security Byte"; if( ADC_8051 != args->device_type ) { controller_error = 1; } break; } if( 0 != controller_error ) { DEBUG( "%s requires 8051 based controller\n", message ); fprintf( stderr, "%s requires 8051 based controller\n", message ); return -1; } if( value < 0 ) { fprintf( stderr, "The requested device info is unavailable.\n" ); return -2; } fprintf( stdout, "%s%s0x%02x (%d)\n", ((0 == args->quiet) ? message : ""), ((0 == args->quiet) ? ": " : ""), value, value ); return 0; } static int32_t execute_dump( dfu_device_t *device, struct programmer_arguments *args ) { int32_t i = 0; int32_t retval = UNSPECIFIED_ERROR; int32_t result; // result of fcn calls intel_buffer_in_t buin; // buffer in for storing read mem enum atmel_memory_unit_enum mem_segment = args->com_read_data.segment; size_t mem_size = 0; size_t page_size = 0; uint32_t target_offset = 0; // address offset on the target device // NOTE: target_offset may not be set appropriately for device // classes other than ADC_AVR32 switch( mem_segment ) { case mem_flash: mem_size = args->memory_address_top + 1; page_size = args->flash_page_size; if( ADC_AVR32 == args->device_type ) { target_offset = 0x80000000; } else if( GRP_STM32 & args->device_type ) { target_offset = STM32_FLASH_OFFSET; } break; case mem_eeprom: mem_size = args->eeprom_memory_size; page_size = args->eeprom_page_size; break; case mem_user: mem_size = args->flash_page_size; page_size = args->flash_page_size; target_offset = 0x80800000; break; default: fprintf( stderr, "Dump not currently supported for this memory.\n" ); retval = ARGUMENT_ERROR; goto error; } if( 0 != intel_init_buffer_in(&buin, mem_size, page_size) ) { DEBUG("ERROR initializing a buffer.\n"); retval = BUFFER_INIT_ERROR; goto error; } if( mem_segment == mem_flash ) { buin.info.data_start = args->flash_address_bottom; buin.info.data_end = args->flash_address_top; } if( args->device_type & GRP_STM32 ) { result = stm32_read_flash(device, &buin, mem_segment, args->quiet); } else { /* Check AVR32 security bit in order to provide a better error message */ security_check( device ); // avr32 has no eeprom, but OK result = atmel_read_flash(device, &buin, mem_segment, args->quiet); } if( 0 != result ) { DEBUG("ERROR: could not read memory, err %d.\n", result); security_message( device ); retval = FLASH_READ_ERROR; goto error; } // determine first & last page with non-blank data if( args->com_read_data.force ) { buin.info.data_start = 0; } else { // find first page with data for( i = buin.info.data_start; i < buin.info.data_end; i++ ) { if( buin.data[i] != 0xFF ) break; if( i / buin.info.page_size > buin.info.data_start / buin.info.page_size ) { // i has just jumped to a different page than buin.data_start buin.info.data_start = i; } } if( i == buin.info.data_end ) { if( !args->quiet ) fprintf( stderr, "Memory is blank, returning a single blank page.\n" "Use --force to return the entire memory regardless.\n"); buin.info.data_start = 0; buin.info.data_end = buin.info.page_size - 1; } else { // find last page with data for( i = buin.info.data_end; i > buin.info.data_start; i-- ) { if( buin.data[i] !=0xFF ) break; if( i / buin.info.page_size < buin.info.data_end / buin.info.page_size ) { buin.info.data_end = i; } } } } if( args->com_read_data.bin ) { if( !args->quiet ) fprintf( stderr, "Dumping 0x%X bytes from address offset 0x%X.\n", buin.info.data_end + 1, target_offset ); for( i = 0; i <= buin.info.data_end; i++ ) { fprintf( stdout, "%c", buin.data[i] ); } } else { if( !args->quiet ) fprintf( stderr, "Dumping 0x%X bytes from address offset 0x%X.\n", buin.info.data_end - buin.info.data_start + 1, target_offset + buin.info.data_start ); intel_hex_from_buffer( &buin, args->com_read_data.force, target_offset ); } fflush( stdout ); retval = SUCCESS; error: if( NULL != buin.data ) { free( buin.data ); buin.data = NULL; } return retval; } static int32_t execute_setfuse( dfu_device_t *device, struct programmer_arguments *args ) { int32_t value = args->com_setfuse_data.value; int32_t name = args->com_setfuse_data.name; /* only ADC_AVR32 seems to support fuse operation */ if( !(ADC_AVR32 & args->device_type) || (GRP_STM32 & args->device_type) ) { fprintf( stderr, "Operation not supported on %s\n", args->device_type_string ); DEBUG( "target doesn't support fuse set operation.\n" ); return -1; } /* Check AVR32 security bit in order to provide a better error message. */ security_check( device ); if( 0 != atmel_set_fuse(device, name, value) ) { DEBUG( "Fuse set failed.\n" ); fprintf( stderr, "Fuse set failed.\n" ); security_message( device ); return -1; } return 0; } static int32_t execute_configure( dfu_device_t *device, struct programmer_arguments *args ) { int32_t value = args->com_configure_data.value; int32_t name = args->com_configure_data.name; if( ADC_8051 != args->device_type ) { fprintf( stderr, "Operation not supported on %s\n", args->device_type_string ); DEBUG( "target doesn't support configure operation.\n" ); return -1; } if( (0xff & value) != value ) { DEBUG( "Value to configure must be in range 0-255.\n" ); fprintf( stderr, "Value to configure must be in range 0-255.\n" ); return -1; } if( 0 != atmel_set_config(device, name, value) ) { DEBUG( "Configuration set failed.\n" ); fprintf( stderr, "Configuration set failed.\n" ); return -1; } return 0; } static int32_t execute_launch( dfu_device_t *device, struct programmer_arguments *args ) { if( args->device_type & GRP_STM32 ) { return stm32_start_app( device, args->quiet ); } else if( args->com_launch_config.noreset ) { return atmel_start_app_noreset( device ); } else { return atmel_start_app_reset( device ); } } int32_t execute_command( dfu_device_t *device, struct programmer_arguments *args ) { device->type = args->device_type; switch( args->command ) { case com_erase: return execute_erase( device, args ); case com_flash: return execute_flash( device, args ); case com_eflash: args->com_flash_data.segment = mem_eeprom; args->command = com_launch; return execute_flash( device, args ); case com_user: args->com_flash_data.segment = mem_user; args->command = com_launch; return execute_flash( device, args ); case com_start_app: args->com_launch_config.noreset = true; case com_reset: args->command = com_launch; case com_launch: return execute_launch( device, args ); case com_get: return execute_get( device, args ); case com_getfuse: return execute_getfuse( device, args ); case com_dump: args->command = com_read; args->com_read_data.force = true; args->com_read_data.bin = 1; return execute_dump( device, args ); case com_edump: args->com_read_data.segment = mem_eeprom; args->com_read_data.force = true; args->command = com_read; args->com_read_data.bin = 1; return execute_dump( device, args ); case com_udump: args->com_read_data.segment = mem_eeprom; args->com_read_data.force = true; args->command = com_read; args->com_read_data.bin = 1; return execute_dump( device, args ); case com_read: return execute_dump( device, args ); case com_configure: return execute_configure( device, args ); case com_setfuse: return execute_setfuse( device, args ); case com_setsecure: return execute_setsecure( device, args ); default: fprintf( stderr, "Not supported at this time.\n" ); } return ARGUMENT_ERROR; } dfu-programmer-dfu-programmer-f23d6df/src/commands.h000066400000000000000000000020431445234667400226450ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef __COMMANDS_H__ #define __COMMANDS_H__ #include #ifdef __cplusplus extern "C" { #endif #include "arguments.h" #include "dfu-device.h" int32_t execute_command( dfu_device_t *device, struct programmer_arguments *args ); #ifdef __cplusplus } #endif #endif dfu-programmer-dfu-programmer-f23d6df/src/dfu-device.h000066400000000000000000000264721445234667400230730ustar00rootroot00000000000000#ifndef __DFU_DEVICE_H__ #define __DFU_DEVICE_H__ #include #include #ifdef __cplusplus extern "C" { #endif // Atmel device classes are now defined with one bit per class. // This simplifies checking in functions which handle more than one class. #define ADC_8051 (1<<0) #define ADC_AVR (1<<1) #define ADC_AVR32 (1<<2) #define ADC_XMEGA (1<<3) #define DC_STM32 (1<<4) // Most commands fall into one of 2 groups. #define GRP_AVR32 (ADC_AVR32 | ADC_XMEGA) #define GRP_AVR (ADC_AVR | ADC_8051) #define GRP_STM32 (DC_STM32) typedef unsigned atmel_device_class_t; typedef struct { struct libusb_device_handle *handle; int32_t interface; atmel_device_class_t type; int security_bit_state; uint16_t transaction; } dfu_device_t; #ifdef __cplusplus } #endif #endif /* __DFU_DEVICE_H__ */ /******************* S T M 3 2 D F U C O M M A N D S ****************** ========= USB DFU Bootloader Requests ============== DFU_DETACH - [ 0x00 ] wTimeout interface zero none > Requests the device to leave DFU mode and enter the application. NOTE : The Detach request is not meaningful in the case of the bootloader. The bootloader is started by a system reset depending on the boot mode configuration settings, which means that no other application is running at this time. DFU_DNLOAD - [ 0x01 ] wBlockNum interface length firmware > Requests data transfer from Host to the device in order to load them into device internal Flash. Includes also erase commands. DFU_UPLOAD - [ 0x02 ] zero interface length firmware > Requests data transfer from device to Host in order to load content of device internal Flash into a Host file. DFU_GETSTATUS - [ 0x03 ] zero interface 6 status > Requests device to send status report to the Host (including status resulting from the last request execution and the state the device will enter immediately after this request). DFU_CLRSTATUS - [ 0x04 ] zero interface zero none > Requests device to clear error status and move to next step. DFU_GETSTATE - [ 0x05 ] zero interface 1 state > Requests the device to send only the state it will enter immediately after this request. DFU_ABORT - [ 0x06 ] zero interface zero none > Requests device to exit the current state/operation and enter idle state immediately. ========= STM32 DFU Commands ============== . DFU_UPLOAD DFU_DNLOAD cmd . wValue wValue first byte READ MEMORY > 1 GET 0 WRITE MEMORY > 1 ERASE 0 0x41 READ UNPROTECT 0 0x92 SET ADDRESS POINTER 0 0x21 LEAVE DFU MODE 0 -- (0 data length) NOTES > before issuing a DNLOAD request the host should check that the device is in a correct sate dfuIDLE or dfuDNLOAD-IDLE and that there are no errors. if the device is not in the correct state a DFU_CLRSTATUS must be called > after a command is sent using DFU_DNLOAD, DFU_GETSTATUS must be called to trigger command execution. a second DFU_GETSTATUS is required to check for success (except when writing to the option bytes because device resets immediately after write) READ COMMAND DFU_UPLOAD with wValue > 1 > host request device send a specified number of data bytes (wLength) where wLength can be 2 to 2048 bytes, for option bytes read size should be the option byte block size > the address to read data from is computed using wBlockNumber (wValue) and the address pointer using the formula: address = ((wBlockNum - 2) x wTransferSize) + Address_Pointer where: wTransferSize is the length of the requested data buffer > the address should be previously specified using SET ADDRESS POINTER otherwise the start of internal flash is assumed (0x0800000) GET COMMAND DFU_UPLOAD with wValue = 0 > host sends DFU_UPLOAD command with wLength = 0, the device will return N bytes representing the command codes where N = 4 WRITE COMMAND DFU_DNLOAD with wValue > 1 > in a write memory operation the write size can be from 2 to 2048 bytes and the start address must be valid. when writing the option bytes the start address must be the start of the option byte area and the size should cover the entire option byte area > the address is computed using the value of the wBlockNumber (wValue) and the address pointer according the formula: address = ((wBlockNum - 2) x wTransferSize) + Address_Pointer where: wTransferSize is the length of the buffer sent by host wBlockNumber is the value of wValue parameter SET ADDRESS POINTER - [ 0x21, mem ptr LSB A[7:0], A[8:15], A[23:16], A[31:24] ] > wValue should be zero > after sending the command host must send a DFU_GETSTATUS in order to execute the command. a second DFU_GETSTATUS is needed to check if the command was correctly executed ERASE COMMAND - [ 0x41, page LSB A[7:0], A[15:8], A[23:16], A[31:24] ] MASS ERASE - [ 0x41 ] > this can take a long time to execute so timeout should be long READ UNPROTECT - [ 0x92 ] LEAVE DFU MODE - DFU_DNLOAD with 0 data length > device disconnect > init registers of peripherals to default reset values > initialize the user application main stack pointer > jumps to memory location programmed in the received 'address pointer + 4' which corresponds to the address of the application's reset handler > the address pointer has to be set (using set address pointer) before launching the LEAVE DFU command otherwise the bootloader will jump to the default memory start address (0x0800000) - see an2606: STM32 microcontroller system memory boot mode - see an3156: USB DFU protocol used in the STM32 bootloader **************************************************************************/ /******************* A T M E L D F U C O M M A N D S ****************** // ---- A L L D E V I C E S ----------------------------------- PROGRAM_MEMORY - [ 0x01, 0x00, start_MSB, start LSB, end_MSB, end_LSB ] > send the command, start should align with page boundary > send DFU_DNLOAD data, use non-significant bytes to align program start > optionally request status: 0 OK, 8 bad address, 3 memory locked > on all error DFU_CLRSTATUS NOTE: batchISP/FLIP send buffers with max size 0x800 bytes including prefix READ_MEMORY - [ 0x03, 0x00, start_MSB, start_LSB, end_MSB, end_LSB ] > send the command > send DFU_UPLOAD > seems like you can request status, possibly only on GRP_AVR32 NOTE: batchISP/FLIP request buffers with max size of 0x400 (1kb) BLANK_CHECK - [ 0x03, 0x01, start_MSB, start_LSB, end_MSB, end_LSB ] > send the command > request status: 0 OK, 5 not blank, 8 bad address, 3 memory locked > on errCHECK_ERASED (5) send DFU_UPLOAD to get first non-blank address > on errWRITE (3), errADDRESS (8) and other error DFU_CLRSTATUS CHIP_ERASE - [ 0x04, 0x00, 0xFF ] > send command > optionally request status: 0 OK, 9 in progress 3 memory locked > on errNOTDONE (9) may need to call CHIP_ERASE again (GRP_AVR) > on errWRITE (3) and any other error DFU_CLRSTATUS START_APP - [ 0x04, 0x03, 0x00/0x01 ] > send command: 0x00 for start by reset, 0x01 for rjmp for start by jmp GRP_AVR devices also provide [ MSB, LSB ] of jump address > for start by reset device code must disable the watchdog timer > no DFU_GETSTATUS SELECT_64KB_PAGE - [ 0x06, 0x03, 0x01, PP_MSB, PP_LSB ] > send command > page (PP) is a 64kb memory page (0x10000 bytes), not the flash page > optionally request status: 0 OK, 8 page value out of range > on errADDRESS (8) and any other error DFU_CLRSTATUS NOTE: not documented for AVR in (doc7618) but must be possible // ---- G R O U P A V R 3 2 ----------------------------------- SELECT_MEMORY_UNIT - [ 0x06, 0x03, 0x00, unit_num ] > send command > unit_num [ flash, eeprom, security, config, bootloader, signature, user, int_ram, ext_mem_cs0 - ext_mem_cs7, ext_mem_df ] - XMEGA ONLY: eeprom (1) and all other sections above user (6) > optionally request status: 0 OK, 8 unsupported memory > on errADDRESS (8) and any other error DFU_CLRSTATUS // ---- G R O U P A V R --------------------------------------- PROGRAM_EEPROM - [ 0x01, 0x00, start_MSB, start_LSB, end_MSB, end_LSB ] > send the command, start should align with page boundary > send DFU_DNLOAD data > optionally request status: 0 OK, all other unspecified error > on all error DFU_CLRSTATUS NOTE: batchISP/FLIP send buffers with max size 0x800 bytes including prefix READ_EEPROM - [ 0x03, 0x02, start_MSB, start_LSB, end_MSB, end_LSB ] > send the command > send DFU_UPLOAD NOTE: batchISP/FLIP request buffers with max size of 0x400 (1kb) READ_CONFIG - [ 0x05, rnum0, rnum1 ] > send command > rnum [0x00, 0x00-0x02] enum boot version, boot ID1, boot ID2 > 8051 only: rnum [0x01, 0x00-6] enum BSB, SBV, P1_CF, P3_CF, P4_CF, SSB, EB > rnum [0x01, 0x30-1, 0x60-1] map MFG_CODE, FAM_CODE, PROD_NAME, PROD_VER > 8051 only: rnum [0x02, 0x00] fuse HWB > optionally get status: 0 OK, 0xb chip is protected > on OK send upload request to get value > on errVENDOR (0xb) send DFU_CLRSTATUS // ---- A D C 8 0 5 1 O N L Y ------------------------------- ERASE_BLOCK - [ 0x04, 0x00, block ] > send the command > block0 0x00 is memory from 0x0 to 0x1FFF > block1 0x20 is memory from 0x2000 to 0x3FFF > block2 0x20 is memory from 0x4000 to 0x7FFF > optionally request status: 0 OK, 3 chip is protected > on errWRITE (3) and all other error DFU_CLRSTATUS SET_CONFIG - [0x04, rnum0, rnum1, value] > send command > rnum [0x01, 0x00-0x06] enum BSB, SBV, P1_CF, P3_CF, P4_CF, SSB, EB > rnum [0x02, 0x00] for Fuse HSB > value is the value to set > optionally request DFU_GETSTATUS: 0 OK, 3 chip is protected > on errWRITE (3) or any other error must DFU_CLRSTATUS Notes: - AT90/ATmega the first command must be a full chip erase, everything else is locked until this command is issued - GRP_AVR provide entry points for low level flash drivers like page erase, page write, load word in the temporary page buffer (see doc7618) - AT89 when starting application through reset, if an external reset chip is make sure the reset pulse is correct (see doc4287) - alignment of program with page boundaries: In order to be in accordance with the Flash page size (128 bytes), X non-significant bytes are added before the first byte to program. The X number is calculated to align the beginning of the firmware with the Flash page. X = start_address[32]. For example, if the start address is 00AFh (175d), X = 175 [32] = 15. - see doc32131: AVR32 UC3 USB DFU Bootloader Protocol (AVR32) - see doc7618: USB DFU Bootloader Datasheet (AT90/ATmega) - see doc4287: AT89C5131A USB Bootloader (AT89) - see doc8457: FLIP USB DFU Protocol (xmega) **************************************************************************/ dfu-programmer-dfu-programmer-f23d6df/src/dfu.c000066400000000000000000000556221445234667400216300ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include #include #include #include "dfu.h" #include "util.h" // cSpell:words DNBUSY /* 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 #define USB_CLASS_APP_SPECIFIC 0xfe #define DFU_SUBCLASS 0x01 /* Wait for 20 seconds before a timeout since erasing/flashing can take some time. * The longest erase cycle is for the AT32UC3A0512-TA automotive part, * which needs a timeout of at least 19 seconds to erase the whole flash. */ #define DFU_TIMEOUT 20000 /* Time (in ms) for the device to wait for the usb reset after being told to detach * before the giving up going into dfu mode. */ #define DFU_DETACH_TIMEOUT 1000 #define DFU_DEBUG_THRESHOLD 100 #define DFU_TRACE_THRESHOLD 200 #define DFU_MESSAGE_DEBUG_THRESHOLD 300 #define DEBUG(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, \ DFU_DEBUG_THRESHOLD, __VA_ARGS__ ) #define TRACE(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, \ DFU_TRACE_THRESHOLD, __VA_ARGS__ ) #define MSG_DEBUG(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, \ DFU_MESSAGE_DEBUG_THRESHOLD, __VA_ARGS__ ) // ________ P R O T O T Y P E S _______________________________ static int32_t dfu_find_interface( struct libusb_device *device, const bool honor_interfaceclass, const uint8_t bNumConfigurations); /* Used to find the dfu interface for a device if there is one. * * device - the device to search * honor_interfaceclass - if the actual interface class information * should be checked, or ignored (bug in device DFU code) * * returns the interface number if found, < 0 otherwise */ static int32_t dfu_make_idle( dfu_device_t *device, const bool initial_abort ); /* Gets the device into the dfuIDLE state if possible. * * device - the dfu device to communicate with * * returns 0 on success, 1 if device was reset, error otherwise */ static int32_t dfu_transfer_out( dfu_device_t *device, uint8_t request, const int32_t value, uint8_t* data, const size_t length ); static int32_t dfu_transfer_in( dfu_device_t *device, uint8_t request, const int32_t value, uint8_t* data, const size_t length ); static void dfu_msg_response_output( const char *function, const int32_t result ); /* Used to output the response from our USB request in a human readable * form. * * function - the calling function to output on behalf of * result - the result to interpret */ // ________ F U N C T I O N S _______________________________ void dfu_set_transaction_num( dfu_device_t *device, uint16_t newNum ) { TRACE( "%s( %u )\n", __FUNCTION__, newNum ); device->transaction = newNum; DEBUG("wValue set to %d\n", device->transaction); } uint16_t dfu_get_transaction_num( dfu_device_t *device ) { TRACE( "%s( %u )\n", __FUNCTION__ ); return device->transaction; } int32_t dfu_detach( dfu_device_t *device, const int32_t timeout ) { int32_t result; TRACE( "%s( %p, %d )\n", __FUNCTION__, device, timeout ); if( (NULL == device) || (NULL == device->handle) || (timeout < 0) ) { DEBUG( "Invalid parameter\n" ); return -1; } result = dfu_transfer_out( device, DFU_DETACH, timeout, NULL, 0 ); dfu_msg_response_output( __FUNCTION__, result ); return result; } int32_t dfu_download( dfu_device_t *device, const size_t length, uint8_t* data ) { int32_t result; TRACE( "%s( %p, %u, %p )\n", __FUNCTION__, device, length, data ); /* Sanity checks */ if( (NULL == device) || (NULL == device->handle) ) { DEBUG( "Invalid parameter\n" ); return -1; } if( (0 != length) && (NULL == data) ) { DEBUG( "data was NULL, but length != 0\n" ); return -2; } if( (0 == length) && (NULL != data) ) { DEBUG( "data was not NULL, but length == 0\n" ); return -3; } { size_t i; for( i = 0; i < length; i++ ) { MSG_DEBUG( "Message: m[%u] = 0x%02x\n", i, data[i] ); } } result = dfu_transfer_out( device, DFU_DNLOAD, device->transaction++, data, length ); dfu_msg_response_output( __FUNCTION__, result ); return result; } int32_t dfu_upload( dfu_device_t *device, const size_t length, uint8_t* data ) { int32_t result; TRACE( "%s( %p, %u, %p )\n", __FUNCTION__, device, length, data ); /* Sanity checks */ if( (NULL == device) || (NULL == device->handle) ) { DEBUG( "Invalid parameter\n" ); return -1; } if( (0 == length) || (NULL == data) ) { DEBUG( "data was NULL, or length is 0\n" ); return -2; } result = dfu_transfer_in( device, DFU_UPLOAD, device->transaction++, data, length ); dfu_msg_response_output( __FUNCTION__, result ); return result; } int32_t dfu_get_status( dfu_device_t *device, dfu_status_t *status ) { uint8_t buffer[6]; int32_t result; TRACE( "%s( %p, %p )\n", __FUNCTION__, device, status ); if( (NULL == device) || (NULL == device->handle) ) { DEBUG( "Invalid parameter\n" ); return -1; } /* Initialize the status data structure */ status->bStatus = DFU_STATUS_ERROR_UNKNOWN; status->bwPollTimeout = 0; status->bState = STATE_DFU_ERROR; status->iString = 0; result = dfu_transfer_in( device, DFU_GETSTATUS, 0, buffer, sizeof(buffer) ); dfu_msg_response_output( __FUNCTION__, result ); if( 6 == result ) { status->bStatus = buffer[0]; status->bwPollTimeout = ((0xff & buffer[3]) << 16) | ((0xff & buffer[2]) << 8) | (0xff & buffer[1]); status->bState = buffer[4]; status->iString = buffer[5]; DEBUG( "==============================\n" ); DEBUG( "status->bStatus: %s (0x%02x)\n", dfu_status_to_string(status->bStatus), status->bStatus ); DEBUG( "status->bwPollTimeout: 0x%04x ms\n", status->bwPollTimeout ); DEBUG( "status->bState: %s (0x%02x)\n", dfu_state_to_string(status->bState), status->bState ); DEBUG( "status->iString: 0x%02x\n", status->iString ); DEBUG( "------------------------------\n" ); } else { if( 0 < result ) { /* There was an error, we didn't get the entire message. */ DEBUG( "result: %d\n", result ); return -2; } } return 0; } int32_t dfu_clear_status( dfu_device_t *device ) { int32_t result; TRACE( "%s( %p )\n", __FUNCTION__, device ); if( (NULL == device) || (NULL == device->handle) ) { DEBUG( "Invalid parameter\n" ); return -1; } result = dfu_transfer_out( device, DFU_CLRSTATUS, 0, NULL, 0 ); dfu_msg_response_output( __FUNCTION__, result ); return result; } int32_t dfu_get_state( dfu_device_t *device ) { int32_t result; uint8_t buffer[1]; TRACE( "%s( %p )\n", __FUNCTION__, device ); if( (NULL == device) || (NULL == device->handle) ) { DEBUG( "Invalid parameter\n" ); return -1; } result = dfu_transfer_in( device, DFU_GETSTATE, 0, buffer, sizeof(buffer) ); dfu_msg_response_output( __FUNCTION__, result ); /* Return the error if there is one. */ if( result < 1 ) { return result; } /* Return the state. */ return buffer[0]; } int32_t dfu_abort( dfu_device_t *device ) { int32_t result; TRACE( "%s( %p )\n", __FUNCTION__, device ); if( (NULL == device) || (NULL == device->handle) ) { DEBUG( "Invalid parameter\n" ); return -1; } result = dfu_transfer_out( device, DFU_ABORT, 0, NULL, 0 ); dfu_msg_response_output( __FUNCTION__, result ); return result; } struct libusb_device *dfu_device_init( const uint32_t vendor, const uint32_t product, const uint32_t bus_number, const uint32_t device_address, dfu_device_t *dfu_device, const bool initial_abort, const bool honor_interfaceclass, libusb_context *usb_context ) { libusb_device **list; size_t i,deviceCount; int32_t retries = 4; TRACE( "%s( %u, %u, %p, %s, %s )\n", __FUNCTION__, vendor, product, dfu_device, ((true == initial_abort) ? "true" : "false"), ((true == honor_interfaceclass) ? "true" : "false") ); DEBUG( "%s(%08x, %08x)\n",__FUNCTION__, vendor, product ); retry: deviceCount = libusb_get_device_list( usb_context, &list ); for( i = 0; i < deviceCount; i++ ) { libusb_device *device = list[i]; struct libusb_device_descriptor descriptor; if( libusb_get_device_descriptor(device, &descriptor) ) { DEBUG( "Failed in libusb_get_device_descriptor\n" ); break; } DEBUG( "%2d: 0x%04x, 0x%04x\n", (int) i, descriptor.idVendor, descriptor.idProduct ); if( vendor != descriptor.idVendor) continue; if( product != descriptor.idProduct) continue; if( bus_number != 0 ) { if ( libusb_get_bus_number(device) != bus_number ) continue; if ( libusb_get_device_address(device) != device_address ) continue; } int32_t tmp; DEBUG( "found device at USB:%d,%d\n", libusb_get_bus_number(device), libusb_get_device_address(device) ); // We found a device that looks like it matches... // Let's try to find the DFU interface, open the device and claim it. tmp = dfu_find_interface( device, honor_interfaceclass, descriptor.bNumConfigurations ); if (tmp < 0) { /* The interface is invalid. */ DEBUG( "Failed to find interface.\n" ); continue; } dfu_device->interface = tmp; DEBUG( "opening interface %d...\n", tmp ); tmp = libusb_open( device, &dfu_device->handle ); DEBUG( "returned %d...\n", tmp ); if (tmp) { DEBUG( "failed to open device\n" ); continue; } DEBUG( "opened interface %d...\n", tmp ); tmp = libusb_set_configuration( dfu_device->handle, 1 ); if (tmp) { DEBUG( "Failed to set configuration.\n" ); goto done; } DEBUG( "set configuration %d...\n", 1 ); tmp = libusb_claim_interface( dfu_device->handle, dfu_device->interface ); if (tmp) { DEBUG( "Failed to claim the DFU interface.\n" ); goto done; } DEBUG( "claimed interface %d...\n", dfu_device->interface ); tmp = dfu_make_idle( dfu_device, initial_abort ); if (tmp == 0 || tmp == 1) { libusb_free_device_list( list, 1 ); if (!tmp) { return device; } retries--; goto retry; } DEBUG( "Failed to put the device in dfuIDLE mode.\n" ); libusb_release_interface( dfu_device->handle, dfu_device->interface ); retries = 4; done: libusb_close( dfu_device->handle ); } libusb_free_device_list( list, 1 ); dfu_device->handle = NULL; dfu_device->interface = 0; return NULL; } char* dfu_state_to_string( const int32_t state ) { char *message = "unknown state"; 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; } return message; } char* dfu_status_to_string( const int32_t status ) { char *message = "unknown status"; switch( status ) { case DFU_STATUS_OK: message = "OK"; break; case DFU_STATUS_ERROR_TARGET: message = "errTARGET"; break; case DFU_STATUS_ERROR_FILE: message = "errFILE"; break; case DFU_STATUS_ERROR_WRITE: message = "errWRITE"; break; case DFU_STATUS_ERROR_ERASE: message = "errERASE"; break; case DFU_STATUS_ERROR_CHECK_ERASED: message = "errCHECK_ERASED"; break; case DFU_STATUS_ERROR_PROG: message = "errPROG"; break; case DFU_STATUS_ERROR_VERIFY: message = "errVERIFY"; break; case DFU_STATUS_ERROR_ADDRESS: message = "errADDRESS"; break; case DFU_STATUS_ERROR_NOTDONE: message = "errNOTDONE"; break; case DFU_STATUS_ERROR_FIRMWARE: message = "errFIRMWARE"; break; case DFU_STATUS_ERROR_VENDOR: message = "errVENDOR"; break; case DFU_STATUS_ERROR_USBR: message = "errUSBR"; break; case DFU_STATUS_ERROR_POR: message = "errPOR"; break; case DFU_STATUS_ERROR_UNKNOWN: message = "errUNKNOWN"; break; case DFU_STATUS_ERROR_STALLEDPKT: message = "errSTALLEDPKT"; break; } return message; } static int32_t dfu_find_interface( struct libusb_device *device, const bool honor_interfaceclass, const uint8_t bNumConfigurations) { int32_t c,i,s; TRACE( "%s()\n", __FUNCTION__ ); /* Loop through all of the configurations */ for( c = 0; c < bNumConfigurations; c++ ) { struct libusb_config_descriptor *config; if( libusb_get_config_descriptor(device, c, &config) ) { DEBUG( "can't get_config_descriptor: %d\n", c ); return -1; } DEBUG( "config %d: MaxPower=%d*2 mA\n", c, config->MaxPower ); /* Loop through all of the interfaces */ for( i = 0; i < config->bNumInterfaces; i++ ) { struct libusb_interface interface; interface = config->interface[i]; DEBUG( "interface %d\n", i ); /* Loop through all of the settings */ for( s = 0; s < interface.num_altsetting; s++ ) { struct libusb_interface_descriptor setting; setting = interface.altsetting[s]; DEBUG( "setting %d: class:%d, subclass %d, protocol:%d\n", s, setting.bInterfaceClass, setting.bInterfaceSubClass, setting.bInterfaceProtocol ); if( honor_interfaceclass ) { /* Check if the interface is a DFU interface */ if( (USB_CLASS_APP_SPECIFIC == setting.bInterfaceClass) && (DFU_SUBCLASS == setting.bInterfaceSubClass) ) { DEBUG( "Found DFU Interface: %d\n", setting.bInterfaceNumber ); return setting.bInterfaceNumber; } } else { /* If there is a bug in the DFU firmware, return the first * found interface. */ DEBUG( "Found DFU Interface: %d\n", setting.bInterfaceNumber ); return setting.bInterfaceNumber; } } } libusb_free_config_descriptor( config ); } return -1; } static int32_t dfu_make_idle( dfu_device_t *device, const bool initial_abort ) { dfu_status_t status; int32_t retries = 4; if( true == initial_abort ) { dfu_abort( device ); } while( 0 < retries ) { if( 0 != dfu_get_status(device, &status) ) { dfu_clear_status( device ); continue; } DEBUG( "State: %s (%d)\n", dfu_state_to_string(status.bState), status.bState ); switch( status.bState ) { case STATE_DFU_IDLE: if( DFU_STATUS_OK == status.bStatus ) { return 0; } /* We need the device to have the DFU_STATUS_OK status. */ dfu_clear_status( device ); break; case STATE_DFU_DOWNLOAD_SYNC: /* abort -> idle */ case STATE_DFU_DOWNLOAD_IDLE: /* abort -> idle */ case STATE_DFU_MANIFEST_SYNC: /* abort -> idle */ case STATE_DFU_UPLOAD_IDLE: /* abort -> idle */ case STATE_DFU_DOWNLOAD_BUSY: /* abort -> error */ case STATE_DFU_MANIFEST: /* abort -> error */ dfu_abort( device ); break; case STATE_DFU_ERROR: dfu_clear_status( device ); break; case STATE_APP_IDLE: dfu_detach( device, DFU_DETACH_TIMEOUT ); break; case STATE_APP_DETACH: case STATE_DFU_MANIFEST_WAIT_RESET: DEBUG( "Resetting the device\n" ); libusb_reset_device( device->handle ); return 1; } retries--; } DEBUG( "Not able to transition the device into the dfuIDLE state.\n" ); return -2; } static int32_t dfu_transfer_out( dfu_device_t *device, uint8_t request, const int32_t value, uint8_t* data, const size_t length ) { return libusb_control_transfer( device->handle, /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, /* bRequest */ request, /* wValue */ value, /* wIndex */ device->interface, /* Data */ data, /* wLength */ length, DFU_TIMEOUT ); } static int32_t dfu_transfer_in( dfu_device_t *device, uint8_t request, const int32_t value, uint8_t* data, const size_t length ) { return libusb_control_transfer( device->handle, /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, /* bRequest */ request, /* wValue */ value, /* wIndex */ device->interface, /* Data */ data, /* wLength */ length, DFU_TIMEOUT ); } static void dfu_msg_response_output( const char *function, const int32_t result ) { char *msg = NULL; if( 0 <= result ) { msg = "No error."; } else { switch( result ) { case LIBUSB_ERROR_IO : msg = "LIBUSB_ERROR_IO: Input/output error."; break; case LIBUSB_ERROR_INVALID_PARAM : msg = "LIBUSB_ERROR_INVALID_PARAM: Invalid parameter."; break; case LIBUSB_ERROR_ACCESS : msg = "LIBUSB_ERROR_ACCESS: Access denied (insufficient permissions)"; break; case LIBUSB_ERROR_NO_DEVICE : msg = "LIBUSB_ERROR_NO_DEVICE: No such device (it may have been disconnected)"; break; case LIBUSB_ERROR_NOT_FOUND : msg = "LIBUSB_ERROR_NOT_FOUND: Entity not found."; break; case LIBUSB_ERROR_BUSY : msg = "LIBUSB_ERROR_BUSY: Resource busy."; break; case LIBUSB_ERROR_TIMEOUT : msg = "LIBUSB_ERROR_TIMEOUT: Operation timed out."; break; case LIBUSB_ERROR_OVERFLOW : msg = "LIBUSB_ERROR_OVERFLOW: Overflow."; break; case LIBUSB_ERROR_PIPE : msg = "LIBUSB_ERROR_PIPE: Pipe error."; break; case LIBUSB_ERROR_INTERRUPTED : msg = "LIBUSB_ERROR_INTERRUPTED: System call interrupted (perhaps due to signal)"; break; case LIBUSB_ERROR_NO_MEM : msg = "LIBUSB_ERROR_NO_MEM: Insufficient memory."; break; case LIBUSB_ERROR_NOT_SUPPORTED : msg = "LIBUSB_ERROR_NOT_SUPPORTED: Operation not supported or unimplemented on this platform."; break; case LIBUSB_ERROR_OTHER : msg = "LIBUSB_ERROR_OTHER: Other error."; break; default: msg = "Unknown error"; break; } DEBUG( "%s ERR: %s 0x%08x (%d)\n", function, msg, result, result ); } } #ifdef malloc #undef malloc void* rpl_malloc( size_t n ) { if( 0 == n ) { n = 1; } return malloc( n ); } #endif dfu-programmer-dfu-programmer-f23d6df/src/dfu.h000066400000000000000000000142431445234667400216270ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef __DFU_H__ #define __DFU_H__ #include #include #include #include #ifdef __cplusplus extern "C" { #endif #include "dfu-device.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 /* This is based off of DFU_GETSTATUS * * 1 unsigned byte bStatus * 3 unsigned byte bwPollTimeout * 1 unsigned byte bState * 1 unsigned byte iString */ typedef struct { uint8_t bStatus; uint32_t bwPollTimeout; uint8_t bState; uint8_t iString; } dfu_status_t; void dfu_set_transaction_num( dfu_device_t *device, uint16_t newNum ); /* set / reset the wValue parameter to a given value. this number is * significant for stm32 device commands (see dfu-device.h) */ uint16_t dfu_get_transaction_num( dfu_device_t *device ); /* get the current transaction number (can be used to calculate address * offset for stm32 devices --- see dfu-device.h) */ int32_t dfu_detach( dfu_device_t *device, const int32_t timeout ); /* DFU_DETACH Request (DFU Spec 1.0, Section 5.1) * * device - the dfu device 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 */ int32_t dfu_download( dfu_device_t *device, const size_t length, uint8_t* data ); /* DFU_DNLOAD Request (DFU Spec 1.0, Section 6.1.1) * * device - the dfu device 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 */ int32_t dfu_upload( dfu_device_t *device, const size_t length, uint8_t* data ); /* DFU_UPLOAD Request (DFU Spec 1.0, Section 6.2) * * device - the dfu device 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 */ int32_t dfu_get_status( dfu_device_t *device, dfu_status_t *status ); /* DFU_GETSTATUS Request (DFU Spec 1.0, Section 6.1.2) * * device - the dfu device to communicate with * status - the data structure to be populated with the results * * return the 0 if successful or < 0 on an error */ int32_t dfu_clear_status( dfu_device_t *device ); /* DFU_CLRSTATUS Request (DFU Spec 1.0, Section 6.1.3) * * device - the dfu device to communicate with * * return 0 or < 0 on an error */ int32_t dfu_get_state( dfu_device_t *device ); /* DFU_GETSTATE Request (DFU Spec 1.0, Section 6.1.5) * * device - the dfu device to communicate with * * returns the state or < 0 on error */ int32_t dfu_abort( dfu_device_t *device ); /* DFU_ABORT Request (DFU Spec 1.0, Section 6.1.4) * * device - the dfu device to communicate with * * returns 0 or < 0 on an error */ struct libusb_device *dfu_device_init( const uint32_t vendor, const uint32_t product, const uint32_t bus, const uint32_t dev_addr, dfu_device_t *device, const bool initial_abort, const bool honor_interfaceclass, libusb_context *usb_context ); /* dfu_device_init is designed to find one of the usb devices which match * the vendor and product parameters passed in. * * vendor - the vender number of the device to look for * product - the product number of the device to look for * [out] device - the dfu device to communicate with * * return a pointer to the usb_device if found, or NULL otherwise */ char* dfu_status_to_string( const int32_t status ); /* Used to convert the DFU status to a string. * * status - the status to convert * * returns the status name or "unknown status" */ char* dfu_state_to_string( const int32_t state ); /* Used to convert the DFU state to a string. * * state - the state to convert * * returns the state name or "unknown state" */ #ifdef __cplusplus } #endif #endif dfu-programmer-dfu-programmer-f23d6df/src/intel_hex.c000066400000000000000000000576251445234667400230360ustar00rootroot00000000000000/* * dfu-programmer * * intel_hex.c * * This reads in a .hex file (Intel format), creates an array representing * memory, populates the array with the data from the .hex file, and * returns the array. * * This implementation is based completely on San Bergmans description * of this file format, last updated on 23 August, 2005. * * http://www.sbprojects.com * In the "Knowledge Base" section. * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #define _GNU_SOURCE #include #include #include #include #include "intel_hex.h" #include "util.h" struct intel_record { uint8_t count; // single byte count uint8_t type; // single byte type uint16_t address; // two byte address uint8_t checksum; // single byte checksum uint8_t data[256]; }; #define IHEX_COLS 16 #define IHEX_64KB_PAGE 0x10000 #define IHEX_DEBUG_THRESHOLD 50 #define IHEX_TRACE_THRESHOLD 55 #define DEBUG(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, \ IHEX_DEBUG_THRESHOLD, __VA_ARGS__ ) #define TRACE(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, \ IHEX_TRACE_THRESHOLD, __VA_ARGS__ ) // ________ P R O T O T Y P E S _______________________________ static int intel_validate_checksum( struct intel_record *record ); /* This walks over the record and ensures that the checksum is * correct for the record. * * returns 0 if checksum validates, anything else on error */ static int32_t ihex_make_line( struct intel_record *record, char *str ); /* provide record type a list of values, they are converted into a line and put at str * values are 2 address bytes, the record type and any values. A checksum * is added to the end and the line length is prepended. */ static int32_t ihex_make_checksum( struct intel_record *record ); /* make a checksum using the values in record, place it in the record and * return 0 */ static int32_t ihex_make_record_04_offset( uint32_t offset, char *str ); /* make an 04 record type offset, where the desired offset address is found by * multiplying value by 0x1000 (or the 64kb page size). Therefore, the given * offset value must be a clean multiple of 0x10000. the offset value * is placed in the buffer at str */ //static int32_t ihex_process_record( struct intel_record *record, // const uint8_t job, uint32_t next_address ); /* call this function when a record needs to be processed (specify w/ job) * and a new blank record needs to be created */ static void ihex_clear_record( struct intel_record *record, uint32_t address ); /* wipes out a record (resets it to zero) */ // ________ F U N C T I O N S _______________________________ static int intel_validate_checksum( struct intel_record *record ) { int i = 0; int checksum = 0; checksum = record->count + record->type + record->checksum + (record->address >> 8) + (0xff & record->address); for( i = 0; i < record->count; i++ ) { checksum += record->data[i]; } return (0xff & checksum); } static int intel_validate_line( struct intel_record *record ) { /* Validate the checksum */ if( 0 != intel_validate_checksum(record) ) { DEBUG( "Checksum error.\n" ); return -1; } /* Validate the type */ switch( record->type ) { /* Intel 1 format, for up to 64K length (types 0, 1) */ case 0: /* data record */ /* Nothing to do. */ break; case 1: /* EOF record */ if( 0 != record->count ) { DEBUG( "EOF record error.\n" ); return -2; } break; /* Intel 2 format, when 20 bit addresses are needed (types 2, 3, 4) */ case 2: /* extended address record */ if( (0 != record->address) || (2 != record->count) || (record->data[1] != (0xf8 & record->data[1])) ) { DEBUG( "Intel2 Format Error.\n" ); return -3; } break; case 3: /* start address record */ /* just ignore these records (could verify addr == 0) */ break; case 4: /* extended linear address record */ if( (0 != record->address) || (2 != record->count) ) { DEBUG( "Extended Linear Address Record Format Error" ); return -4; } break; case 5: /* start linear address record */ if( (0 != record->address) || (4 != record->count) ) { return -6; } break; default: fprintf( stderr, "Unsupported type. %d\n", record->type ); /* Type 5 and other types are unsupported. */ return -5; } return 0; } static int intel_read_data( FILE *fp, struct intel_record *record ) { int i; int c; int status; char buffer[10]; int addr_upper; int addr_lower; int count; int type; int data; int checksum; // cSpell:ignore bbaaaarr /* read in the ':bbaaaarr' * bb - byte count * aaaa - the address in memory * rr - record type */ if( NULL == fgets(buffer, 10, fp) ) return -1; status = sscanf( buffer, ":%02x%02x%02x%02x", &count, &addr_upper, &addr_lower, &type ); if( 4 != status ) return -2; record->count = (uint8_t) count; record->address = (uint16_t) (addr_upper << 8 | addr_lower); record->type = (uint8_t) type; /* Read the data */ for( i = 0; i < record->count; i++ ) { if( NULL == fgets(buffer, 3, fp) ) return -3; if( 1 != sscanf(buffer, "%02x", &data) ) return -4; record->data[i] = (uint8_t) (0xff & data); } /* Read the checksum */ if( NULL == fgets(buffer, 3, fp) ) return -5; if( 1 != sscanf(buffer, "%02x", &checksum) ) return -6; /* Chomp the [\r]\n */ c = fgetc( fp ); if( '\r' == c ) { c = fgetc( fp ); } if( '\n' != c ) { DEBUG( "Error: end of line != \\n.\n" ); return -7; } record->checksum = (uint8_t) checksum; return 0; } static void intel_invalid_addr_warning(uint32_t line_count, uint32_t address, uint32_t target_offset, size_t total_size) { DEBUG("Valid address region from 0x%X to 0x%X.\n", target_offset, target_offset + total_size - 1); fprintf( stderr, "WARNING (line %u): 0x%02x address outside valid region,\n", line_count, address); fprintf( stderr, " suppressing additional address error messages.\n" ); } int32_t intel_process_data( intel_buffer_out_t *bout, char value, uint32_t target_offset, uint32_t address) { /* NOTE : there are some hex program files that contain data in the user * page, which is outside of 'valid' memory. In this situation, the hex * file is processed and used as normal with a warning message containing * the first line with an invalid address. */ uint32_t raddress; // relative address = address - target offset // cSpell:ignore raddress // The Atmel flash page starts at address 0x8000 0000, we need to ignore // stm32 flash page starts at 0x0800 0000 // that bit target_offset &= 0x7fffffff; address &= 0x7fffffff; if( (address < target_offset) || (address > target_offset + bout->info.total_size - 1) ) { DEBUG( "Address 0x%X is outside valid range 0x%X to 0x%X.\n", address, target_offset, target_offset + bout->info.total_size - 1 ); return -1; } else { raddress = address - target_offset; // address >= target_offset so unsigned '-' is OK bout->data[raddress] = (uint16_t) (0xff & value); // update data limits if( raddress < bout->info.data_start ) { bout->info.data_start = raddress; } if( raddress > bout->info.data_end ) { bout->info.data_end = raddress; } } return 0; } int32_t intel_hex_to_buffer( char *filename, intel_buffer_out_t *bout, uint32_t target_offset, bool quiet ) { FILE *fp = NULL; struct intel_record record; // unsigned int count, type, checksum, address; char data[256] uint32_t address = 0; // line address for intel_hex uint32_t address_offset = 0;// offset address from intel_hex uint32_t line_count = 1; // used for debugging hex file int32_t invalid_address_count = 0; // used for error checking int32_t retval; // return value int i = 0; if ( (0 >= bout->info.total_size) ) { DEBUG( "Must provide valid memory size in bout.\n" ); retval = -1; goto error; } if (NULL == filename) { if( !quiet ) fprintf( stderr, "Invalid filename.\n" ); retval = -2; goto error; } if( 0 == strcmp("STDIN", filename) ) { fp = stdin; } else { fp = fopen( filename, "r" ); if( NULL == fp ) { if( !quiet ) fprintf( stderr, "Error opening %s\n", filename ); retval = -3; goto error; } } // iterate through ihex file and assign values to memory and user do { // read the data if( 0 != intel_read_data(fp, &record) ) { if( !quiet ) fprintf( stderr, "Error reading line %u.\n", line_count ); retval = -4; goto error; } else if ( 0 != intel_validate_line( &record ) ) { if( !quiet ) fprintf( stderr, "Error: Line %u does not validate.\n", line_count ); retval = -5; goto error; } else line_count++; // process the data switch( record.type ) { case 0: for( address = address_offset + ((uint32_t) record.address), i = 0; i < record.count; i++, address++ ) { if ( 0 != intel_process_data(bout, record.data[i], target_offset, address) ) { // address was invalid if ( !invalid_address_count ) { intel_invalid_addr_warning(line_count, address, target_offset, bout->info.total_size ); } invalid_address_count++; } } break; case 2: // 0x1238 -> 0x00012380 address_offset = (((uint32_t) record.data[0]) << 12) | ((uint32_t) record.data[1]) << 4; address_offset = (0x7fffffff & address_offset); DEBUG( "Address offset set to 0x%x.\n", address_offset ); break; case 4: // 0x1234 -> 0x12340000 address_offset = (((uint32_t) record.data[0]) << 24) | ((uint32_t) record.data[1]) << 16; address_offset = (0x7fffffff & address_offset); DEBUG( "Address offset set to 0x%x.\n", address_offset ); break; case 5: // 0x12345678 -> 0x12345678 address_offset = (((uint32_t) record.data[0]) << 24) | (((uint32_t) record.data[1]) << 16) | (((uint32_t) record.data[2]) << 8) | ((uint32_t) record.data[3]); /* Note: In AVR32 memory map, FLASH starts at 0x80000000, but * the ISP places this memory at 0. The hex file will use * 0x8..., so mask off that bit. */ address_offset = (0x7fffffff & address_offset); DEBUG( "Address offset set to 0x%x.\n", address_offset ); break; } } while( (1 != record.type) ); if ( invalid_address_count ) { if( !quiet ) fprintf( stderr, "Total of 0x%X bytes in invalid addressed.\n", invalid_address_count ); } retval = invalid_address_count; error: if( NULL != fp ) { fclose( fp ); fp = NULL; } if( retval & !quiet ) { fprintf( stderr, "See --debug=%u or greater for more information.\n", IHEX_DEBUG_THRESHOLD + 1 ); } return retval; } // ___ CONVERT TO INTEL HEX __________________________ static void ihex_clear_record( struct intel_record *record, uint32_t address ) { record->count = 0; record->address = ((uint16_t) (address % 0xffff)); record->type = 0; record->data[0] = 0; record->checksum = 0; } static int32_t ihex_make_checksum( struct intel_record *record ) { uint16_t sum = 0; uint8_t i; sum += record->count; sum += record->type; sum += (record->address & 0xff) + (0xff & (record->address >> 8)); for( i = 0; i < record->count; i++ ) { sum += record->data[i]; } record->checksum = ((uint8_t) (0xff & (0x100 - (0xff & sum)))); return 0; } static int32_t ihex_make_line( struct intel_record *record, char *str ) { uint8_t i; if( record->type > 5 ) { DEBUG( "Record type 0x%X unknown.\n", record->type ); return -1; } else if( record->count > IHEX_COLS ) { DEBUG( "Each line must have no more than 16 values.\n" ); return -1; } if( record->count == 0 ) { // if there is no data set the string to empty, return *str = 0; return 0; } ihex_make_checksum(record); // make the checksum sprintf( str, ":%02X%04X%02X", // ':bbaaaarr' record->count, record->address, record->type ); for ( i = 0; i < record->count; i++ ) { sprintf( str + 9 + 2*i, "%02X", record->data[i] ); } sprintf( str + 9 + 2*i, "%02X", record->checksum ); return 0; } static int32_t ihex_make_record_04_offset( uint32_t offset, char *str ) { struct intel_record record; if ( offset & 0xffff ) { DEBUG( "ihex 04 type offset must be divisible by 0x%X, not 0x%X.\n", 0x10000, offset ); return -1; } record.type = 4; record.count = 2; record.address = 0; record.data[0] = (uint8_t) (0xff & (offset >> 24)); record.data[1] = (uint8_t) (0xff & (offset >> 16)); return ihex_make_line( &record, str ); } //static int32_t ihex_process_record( struct intel_record *record, // const uint8_t job, uint32_t next_address ) { // char line[80]; // if( record->count ) { // if( 0 != ihex_make_line(record, line) ) { // DEBUG( "Error making a line.\n" ); // return -2; // } else { // ihex_clear_record( record, next_address ); // } // if( job==0 ) { // fprintf( stdout, "%s\n", line ); // } // } // return 0; //} int32_t intel_hex_from_buffer( intel_buffer_in_t *buin, bool force_full, uint32_t target_offset ) { char line[80]; uint32_t offset_address = 0; // offset address written to a previous line uint32_t address = 0; // relative offset from previously set addr uint32_t i = buin->info.data_start; uint16_t i_scan; struct intel_record record; ihex_clear_record( &record, i + target_offset ); // target_offset = 0x8000 0000 or 0x8080 0000 // use buin->info.data_start to buin->info.data_stop as range // if target offset > page size, use process 04 // reasons to complete current line: // last value, next page blank, last page value, #cols reached for( i = buin->info.data_start; i <= buin->info.data_end; i++ ) { address = i + target_offset; if( i % buin->info.page_size == 0 && !(force_full) ) { /* you are at the start of a memory page, if force_full is not set * then check if there is any data on the page, if there is none, * then write current line and increment to the next page */ for( i_scan = 0; i_scan < buin->info.page_size; i_scan++ ) { if( buin->data[i + i_scan] != 0xFF ) break; } if( i_scan == buin->info.page_size ) { // no data found: write current, jump to next page if( 0 != ihex_make_line(&record, line) ) { DEBUG( "Error making a line.\n" ); return -2; } else { if( *line ) fprintf( stdout, "%s\n", line ); ihex_clear_record( &record, address + i_scan - offset_address ); } i += buin->info.page_size - 1; continue; } } if( address - offset_address >= 0x10000 ) { offset_address = (address / IHEX_64KB_PAGE) * IHEX_64KB_PAGE; // complete the line, before adding this next point if( 0 != ihex_make_line(&record, line) ) { DEBUG( "Error making a line.\n" ); return -2; } else { if( *line ) fprintf( stdout, "%s\n", line ); ihex_clear_record( &record, address - offset_address ); } // reset offset address if( 0 != ihex_make_record_04_offset(offset_address, line) ) { DEBUG( "Error making a class 4 offset.\n" ); return -2; } else { if( *line ) fprintf( stdout, "%s\n", line ); } } if( record.count == IHEX_COLS ) { if( 0 != ihex_make_line(&record, line) ) { DEBUG( "Error making a line.\n" ); return -2; } else { if( *line ) fprintf( stdout, "%s\n", line ); ihex_clear_record( &record, address - offset_address ); } } record.data[ record.count ] = buin->data[i]; record.count ++; } if( record.count ) { if( 0 != ihex_make_line(&record, line) ) { DEBUG( "Error making a line.\n" ); return -2; } else { if( *line ) fprintf( stdout, "%s\n", line ); ihex_clear_record( &record, address - offset_address ); } } fprintf( stdout, ":00000001FF\n" ); return 0; } int32_t intel_init_buffer_out( intel_buffer_out_t *bout, size_t total_size, size_t page_size ) { uint32_t i; if ( !total_size || !page_size ) { DEBUG("What are you thinking... size must be > 0.\n"); return -1; } bout->info.total_size = total_size; bout->info.page_size = page_size; bout->info.data_start = UINT32_MAX; // invalid data start bout->info.data_end = 0; bout->info.valid_start = 0; bout->info.valid_end = total_size - 1; bout->info.block_start = 0; bout->info.block_end = 0; // allocate the memory bout->data = (uint16_t *) malloc( total_size * sizeof(uint16_t) ); if( NULL == bout->data ) { DEBUG( "ERROR allocating 0x%X bytes of memory.\n", total_size * sizeof(uint16_t)); return -2; } // initialize buffer to 0xFFFF (invalid / unassigned data) for( i = 0; i < total_size; i++ ) { bout->data[i] = UINT16_MAX; } return 0; } int32_t intel_init_buffer_in( intel_buffer_in_t *buin, size_t total_size, size_t page_size ) { // TODO : is there a way to combine this and above? maybe typecast to an // in or out buffer from a char pointer? buin->info.total_size = total_size; buin->info.page_size = page_size; buin->info.data_start = 0; buin->info.data_end = total_size - 1; buin->info.valid_start = 0; buin->info.valid_end = total_size - 1; buin->info.block_start = 0; buin->info.block_end = 0; buin->data = (uint8_t *) malloc( total_size ); if( NULL == buin->data ) { DEBUG( "ERROR allocating 0x%X bytes of memory.\n", total_size ); return -2; } // initialize buffer to 0xFF (blank / unassigned data) memset( buin->data, UINT8_MAX, total_size ); return 0; } int32_t intel_validate_buffer( intel_buffer_in_t *buin, intel_buffer_out_t *bout, bool quiet) { int32_t i; int32_t invalid_data_region = 0; int32_t invalid_outside_data_region = 0; DEBUG( "Validating image from byte 0x%X to 0x%X.\n", bout->info.valid_start, bout->info.valid_end ); if( !quiet ) fprintf( stderr, "Validating... " ); for( i = bout->info.valid_start; i <= bout->info.valid_end; i++ ) { if( bout->data[i] <= UINT8_MAX ) { // Memory should have been programmed here if( ((uint8_t) bout->data[i]) != buin->data[i] ) { if ( !invalid_data_region ) { if( !quiet ) fprintf( stderr, "ERROR\n" ); DEBUG( "Image did not validate at byte: 0x%X of 0x%X.\n", i, bout->info.valid_end - bout->info.valid_start + 1 ); DEBUG( "Wanted 0x%02x but read 0x%02x.\n", 0xff & bout->data[i], buin->data[i] ); DEBUG( "suppressing additional warnings.\n"); } invalid_data_region++; } } else { // Memory should be blank here if( 0xff != buin->data[i] ) { if ( !invalid_data_region ) { DEBUG( "Outside program region: byte 0x%X expected 0xFF.\n", i); DEBUG( "but read 0x%02X. suppressing additional warnings.\n", buin->data[i] ); } invalid_outside_data_region++; } } } if( !quiet ) { if ( 0 == invalid_data_region + invalid_outside_data_region ) { fprintf( stderr, "Success\n" ); } else { fprintf( stderr, "%d invalid bytes in program region, %d outside region.\n", invalid_data_region, invalid_outside_data_region ); } } return invalid_data_region ? -1 * invalid_data_region : invalid_outside_data_region; } int32_t intel_flash_prep_buffer( intel_buffer_out_t *bout ) { uint16_t *page; int32_t i; TRACE( "%s( %p )\n", __FUNCTION__, bout ); // increment pointer by page_size * sizeof(int16) until page_start >= end for( page = bout->data; page < &bout->data[bout->info.valid_end]; page = &page[bout->info.page_size] ) { // check if there is valid data on this page for( i = 0; i < bout->info.page_size; i++ ) { if( page[i] <= UINT8_MAX ) break; } if( bout->info.page_size != i ) { /* There was valid data in the block & we need to make * sure there is no unassigned data. */ for( i = 0; i < bout->info.page_size; i++ ) { if( page[i] > UINT8_MAX ) page[i] = 0xff; // 0xff is blank } } } return 0; } dfu-programmer-dfu-programmer-f23d6df/src/intel_hex.h000066400000000000000000000127541445234667400230350ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef __INTEL_HEX_H__ #define __INTEL_HEX_H__ #include #include #ifdef __cplusplus extern "C" { #endif typedef struct { size_t total_size; // the total size of the buffer size_t page_size; // the size of a flash page uint32_t block_start; // the start addr of a transfer uint32_t block_end; // the end addr of a transfer uint32_t data_start; // the first valid data addr uint32_t data_end; // the last valid data addr uint32_t valid_start; // the first valid memory addr uint32_t valid_end; // the last valid memory addr } intel_buffer_info_t; typedef struct { intel_buffer_info_t info; uint16_t *data; } intel_buffer_out_t; typedef struct { intel_buffer_info_t info; uint8_t *data; } intel_buffer_in_t; int32_t intel_process_data( intel_buffer_out_t *bout, char value, uint32_t target_offset, uint32_t address); /* process a data value by adding to the buffer at the appropriate address or if * the address is out of range do nothing and return -1. Also update the valid * range of data in bout * return 0 on success, -1 on address error */ // NOTE : intel_process_data should be moved to a different module dealing with // processing any data and putting it into a buffer int32_t intel_hex_to_buffer( char *filename, intel_buffer_out_t *bout, uint32_t target_offset, bool quiet ); /* Used to read in a file in intel hex format and return a chunk of * memory containing the memory image described in the file. * * \param filename the name of the intel hex file to process * \param target_offset is the flash memory address location of buffer[0] * \param quiet tells fcn to suppress terminal messages * \param bout buffer_out structure containing pointer to memory data for the * program and for the user page. Each is an array of int16_t's where * the values 0-255 are valid memory values, and anything else * indicates an unused memory location. These do not need to be * initialized before passing this parameter to the function. * * when passed to the function, program_usage and user_usage must * indicate the maximum size of each of these memory sections * in bytes. After the program has run they will indicate the * amount of available memory image used for each section * * \return success integer * 0 = success * + = the amount of data that exists outside the specified memory * area and has not been added to the buffer * - = all sorts of error codes (eg, no data in flash memory, ...) * if the hex file contains no valid data an error is NOT thrown * but the presence of valid data can be checked using the * data_start field in intel_buffer_out_t */ int32_t intel_hex_from_buffer( intel_buffer_in_t *buin, bool force_full, uint32_t target_offset ); /* Used to convert a buffer to an intel hex formatted file. * target offset is the address location of buffer 0 * force_full sets whether to keep writing entirely blank pages. */ int32_t intel_init_buffer_out(intel_buffer_out_t *bout, size_t total_size, size_t page_size ); /* initialize a buffer used to send data to flash memory * the total size and page size must be provided. * the data array is filled with 0xFFFF (an invalid memory * value) indicating that it is unassigned. data start and * data end are initialized with UINT32_MAX indicating there * is no valid data in the buffer. these two values are simply * convenience values so the start and end of data do not need * to be found multiple times. */ int32_t intel_init_buffer_in(intel_buffer_in_t *buin, size_t total_size, size_t page_size ); /* initialize a buffer_in, used for reading the contents of program * memory. total memory size must be provided. the data array is filled * with 0xFF, which is unprogrammed memory. */ int32_t intel_validate_buffer( intel_buffer_in_t *buin, intel_buffer_out_t *bout, bool quiet); /* compare the contents of buffer_in with buffer_out to check that a target * memory image matches with a memory read. * return 0 for full validation, positive number if data bytes outside region do * not validate, negative number if bytes inside region that do not validate */ int32_t intel_flash_prep_buffer( intel_buffer_out_t *bout ); /* prepare the buffer so that valid data fills each page that contains data. * unassigned data in buffer is given a value of 0xff (blank memory) * the buffer pointer must align with the beginning of a flash page * return 0 on success, -1 if assigning data would extend flash above size */ #ifdef __cplusplus } #endif #endif dfu-programmer-dfu-programmer-f23d6df/src/libdfu.c000066400000000000000000000062011445234667400223040ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include "config.h" #include "dfu-device.h" #include "dfu.h" #include "arguments.h" #include "commands.h" #include "atmel.h" #include "libdfu.h" #include "config.h" // NOTE: Technically not thread safe... but since it's not changed when used as a library, it's safe. int debug; static const char *progname = PACKAGE; int dfu_programmer(struct programmer_arguments * args) { int retval = SUCCESS; dfu_device_t dfu_device; struct libusb_device *device = NULL; libusb_context *usbContext; memset(&dfu_device, 0, sizeof(dfu_device)); if (libusb_init(&usbContext)) { fprintf(stderr, "%s: can't init libusb.\n", progname); return DEVICE_ACCESS_ERROR; } if (debug >= 200) { #if LIBUSB_API_VERSION >= 0x01000106 libusb_set_option(usbContext, LIBUSB_OPTION_LOG_LEVEL, debug); #else libusb_set_debug(usbContext, debug); #endif } device = dfu_device_init(args->vendor_id, args->chip_id, args->bus_id, args->device_address, &dfu_device, args->initial_abort, args->honor_interfaceclass, usbContext); if (NULL == device) { fprintf(stderr, "%s: no device present.\n", progname); retval = DEVICE_ACCESS_ERROR; goto error; } retval = execute_command(&dfu_device, args); error: if (NULL != dfu_device.handle) { int rv; rv = libusb_release_interface(dfu_device.handle, dfu_device.interface); /* The RESET command sometimes causes the usb_release_interface command to fail. It is not obvious why this happens but it may be a glitch due to the hardware reset in the attached device. In any event, since reset causes a USB detach this should not matter, so there is no point in raising an alarm. */ if (0 != rv && !(com_launch == args->command && args->com_launch_config.noreset == 0)) { fprintf(stderr, "%s: failed to release interface %d.\n", progname, dfu_device.interface); retval = DEVICE_ACCESS_ERROR; } } if (NULL != dfu_device.handle) { libusb_close(dfu_device.handle); } libusb_exit(usbContext); return retval; } dfu-programmer-dfu-programmer-f23d6df/src/libdfu.h000066400000000000000000000002431445234667400223110ustar00rootroot00000000000000#pragma once #ifdef __cplusplus extern "C" { #endif #include "arguments.h" int dfu_programmer(struct programmer_arguments * args); #ifdef __cplusplus } #endif dfu-programmer-dfu-programmer-f23d6df/src/main.c000066400000000000000000000022721445234667400217670ustar00rootroot00000000000000/* * dfu-programmer * * $Id$ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include "libdfu.h" int main( int argc, char **argv ) { int status; struct programmer_arguments args; memset( &args, 0, sizeof(args) ); status = parse_arguments(&args, argc, argv); if( status < 0 ) { /* Exit with an error. */ return ARGUMENT_ERROR; } else if (status > 0) { /* It was handled by parse_arguments. */ return SUCCESS; } return dfu_programmer(&args); } dfu-programmer-dfu-programmer-f23d6df/src/stm32.c000066400000000000000000000630511445234667400220150ustar00rootroot00000000000000/** dfu-programmer * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ //___ I N C L U D E S ________________________________________________________ #include #include #include #include #include #include #include #include "dfu-device.h" #include "config.h" #include "arguments.h" #include "dfu.h" #include "stm32.h" #include "util.h" //___ M A C R O S ( P R I V A T E ) ________________________________________ #define STM32_DEBUG_THRESHOLD 50 #define STM32_TRACE_THRESHOLD 55 #define DEBUG(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, STM32_DEBUG_THRESHOLD, __VA_ARGS__ ) #define TRACE(...) dfu_debug( __FILE__, __FUNCTION__, __LINE__, STM32_TRACE_THRESHOLD, __VA_ARGS__ ) #define STM32_MAX_TRANSFER_SIZE 0x0800 /* 2048 */ #define STM32_MIN_SECTOR_BOUND 0x4000 /* 16 kb */ #define STM32_OTP_BYTES_SIZE 528 /* number of OTP bytes (0x210) */ #define STM32_OPTION_BYTES_SIZE 16 /* number option bytes */ #define SET_ADDR_PTR 0x21 #define ERASE_CMD 0x41 #define READ_UNPROTECT 0x92 #define GET_CMD 0x00 //___ T Y P E D E F S ( P R I V A T E ) ____________________________________ //___ P R O T O T Y P E S ( P R I V A T E ) ________________________________ static inline int32_t stm32_get_status( dfu_device_t *device ); /* run dfu_get_status to get the current status * return 0 on status OK, -1 on status req fail, -2 on bad status */ static int32_t stm32_set_address_ptr( dfu_device_t *device, uint32_t address ); /* @brief set the address pointer to a certain address * @param the address to set * @return 0 on success, negative on failure */ static int32_t stm32_write_block( dfu_device_t *device, size_t xfer_len, uint8_t *buffer ); /* flash the contents of memory into a block of memory. it is assumed that * the appropriate page has already been selected. start and end are the * start and end addresses of the flash data. returns 0 on success, * positive dfu error code if one is obtained, or negative if communication * with device fails. */ static int32_t stm32_read_block( dfu_device_t *device, size_t xfer_len, uint8_t *buffer ); /* read a block of memory, assumes address pointer is already set */ static inline void print_progress( intel_buffer_info_t *info, uint32_t *progress ); /* calculate how many progress indicator steps to print and print them * update progress value */ static int32_t stm32_erase( dfu_device_t *device, uint8_t *command, uint8_t command_length, bool quiet ); /* erase, erase page, and read unprotect all share this functionality * although with different commands */ //___ V A R I A B L E S ______________________________________________________ extern int debug; /* defined in libdfu.c */ /* FIXME : these should be read from usb device descriptor because they are * device specific */ static const uint32_t stm32_sector_addresses[] = { 0x08000000, /* sector 0, 16 kb */ 0x08004000, /* sector 1, 16 kb */ 0x08008000, /* sector 2, 16 kb */ 0x0800C000, /* sector 3, 16 kb */ 0x08010000, /* sector 4, 64 kb */ 0x08020000, /* sector 5, 128 kb */ 0x08040000, /* sector 6, 128 kb */ 0x08060000, /* sector 7, 128 kb */ 0x08080000, /* sector 8, 128 kb */ 0x080A0000, /* sector 9, 128 kb */ 0x080C0000, /* sector 10, 128 kb */ 0x080E0000, /* sector 11, 128 kb */ 0x1FFF0000, /* system memory, 30 kb */ 0x1FFF7800, /* OTP area, 528 bytes */ 0x1FFFC000, /* Option bytes, 16 bytes */ }; //___ F U N C T I O N S ( P R I V A T E ) __________________________________ static inline int32_t stm32_get_status( dfu_device_t *device ) { dfu_status_t status; if( 0 == dfu_get_status(device, &status) ) { if( status.bStatus == DFU_STATUS_OK ) { DEBUG( "Status OK\n" ); } else { DEBUG( "Status %s not OK, use DFU_CLRSTATUS\n", dfu_status_to_string(status.bStatus) ); dfu_clear_status( device ); return -2; } } else { DEBUG( "DFU_GETSTATUS request failed\n" ); return -1; } return 0; } static int32_t stm32_set_address_ptr( dfu_device_t *device, uint32_t address ) { TRACE( "%s( 0x%X )\n", __FUNCTION__, address ); const uint8_t length = 5; int32_t status; uint8_t command[] = { (uint8_t) SET_ADDR_PTR, (uint8_t) address & 0xFF, /* address LSB */ (uint8_t) (address>>8) & 0xFF, (uint8_t) (address>>16) & 0xFF, (uint8_t) (address>>24) & 0xFF /* address MSB */ }; /* check dfu status for okay to send */ if( (status = stm32_get_status(device)) ) { DEBUG("Error %d getting status on start\n", status); return -1; } dfu_set_transaction_num( device, 0 ); /* set wValue to zero */ if( length != dfu_download(device, length, command) ) { DEBUG( "dfu_download failed\n" ); return -2; } /* call dfu get status to trigger command */ if( (status = stm32_get_status(device)) ) { DEBUG("Error %d triggering %s\n", status, __FUNCTION__); return -3; } /* check command success */ if( (status = stm32_get_status(device)) ) { DEBUG("Error %d: %s unsuccessful\n", status, __FUNCTION__); return -4; } return 0; } static int32_t stm32_write_block( dfu_device_t *device, size_t xfer_len, uint8_t *buffer ) { TRACE( "%s( %p, %u, %p )\n", __FUNCTION__, device, xfer_len, buffer ); int32_t status; /* check input args */ if( (NULL == device) || (NULL == buffer) ) { DEBUG( "ERROR: Invalid arguments, device/buffer pointer is NULL.\n" ); return -1; } else if ( xfer_len > STM32_MAX_TRANSFER_SIZE ) { DEBUG( "ERROR: 0x%X byte message > MAX TRANSFER SIZE (0x%X).\n", xfer_len, STM32_MAX_TRANSFER_SIZE ); return -1; } else if ( xfer_len < 1 ) { DEBUG( "ERROR: xfer_len is %u\n", xfer_len ); return -1; } if( xfer_len != dfu_download(device, xfer_len, buffer) ) { DEBUG( "dfu_download failed\n" ); return -3; } /* call dfu get status to trigger command */ if( (status = stm32_get_status(device)) ) { DEBUG("Error %d triggering %s\n", status, __FUNCTION__); return -3; } /* check that the command was successfully executed */ if( (status = stm32_get_status(device)) ) { DEBUG("Error %d: %s unsuccessful\n", status, __FUNCTION__); return -4; } return 0; } static int32_t stm32_read_block( dfu_device_t *device, size_t xfer_len, uint8_t *buffer ) { TRACE( "%s( %p, %u, %p )\n", __FUNCTION__, device, xfer_len, buffer ); int32_t result; if( buffer == NULL ) { DEBUG("ERROR: buffer ptr is NULL\n"); return -1; } else if( xfer_len > STM32_MAX_TRANSFER_SIZE ) { /* this could cause a read problem */ DEBUG("ERROR: transfer size %d exceeds max %d.\n", xfer_len, STM32_MAX_TRANSFER_SIZE ); return -1; } /* check status before read */ if( (result = stm32_get_status(device)) ) { DEBUG("Status Error %d before read\n", result ); return -2; } result = dfu_upload( device, xfer_len, buffer ); if( result < 0) { dfu_status_t status; DEBUG( "ERROR: dfu_upload result: %d\n", result ); if( 0 == dfu_get_status(device, &status) ) { DEBUG( "Error Status %s, state %s\n", dfu_status_to_string(status.bStatus), dfu_state_to_string(status.bState) ); if( status.bStatus == DFU_STATUS_ERROR_VENDOR ) { /* status = dfuERROR and state = errVENDOR */ DEBUG("Device is read protected\n"); return STM32_READ_PROT_ERROR; } } else { DEBUG("DFU GET_STATUS fail\n"); } dfu_clear_status( device ); return result; } return 0; } static inline void print_progress( intel_buffer_info_t *info, uint32_t *progress ) { if ( !(debug > STM32_DEBUG_THRESHOLD) ) { while ( ((info->block_end - info->data_start + 1) * 32) > *progress ) { fprintf( stderr, ">" ); *progress += info->data_end - info->data_start + 1; } } } static int32_t stm32_erase( dfu_device_t *device, uint8_t *command, uint8_t command_length, bool quiet ) { int32_t status; dfu_set_transaction_num( device, 0 ); /* set wValue to zero */ if( command_length != dfu_download(device, command_length, command) ) { if( !quiet ) fprintf( stderr, "ERROR\n" ); DEBUG( "dfu_download failed\n" ); return UNSPECIFIED_ERROR; } /* call dfu get status to trigger command */ if( (status = stm32_get_status(device)) ) { if( !quiet ) fprintf( stderr, "ERROR\n" ); DEBUG("Error %d triggering %s\n", status, __FUNCTION__); return UNSPECIFIED_ERROR; } /* check status again for erase status, this can take a while */ if( (status = stm32_get_status(device)) ) { DEBUG("Error %d: %s unsuccessful\n", status, __FUNCTION__); if( !quiet ) fprintf( stderr, "ERROR\n" ); return UNSPECIFIED_ERROR; } else { if( !quiet ) fprintf( stderr, "DONE\n" ); } return SUCCESS; } //___ F U N C T I O N S ______________________________________________________ int32_t stm32_erase_flash( dfu_device_t *device, bool quiet ) { TRACE( "%s( %p, %s )\n", __FUNCTION__, device, quiet ? "true" : "false" ); uint8_t command[] = { ERASE_CMD }; uint8_t length = 1; if( !quiet ) { fprintf( stderr, "Erasing flash... " ); DEBUG("\n"); } return stm32_erase( device, command, length, quiet ); } int32_t stm32_page_erase( dfu_device_t *device, uint32_t address, bool quiet ) { TRACE( "%s( %p, 0x%X, %s )\n", __FUNCTION__, device, address, quiet ? "true" : "false" ); uint8_t length = 5; uint8_t command[5] = { ERASE_CMD, (uint8_t) (0xff & address), // page LSB (uint8_t) (0xff & ((address)>>8)), (uint8_t) (0xff & ((address)>>16)), (uint8_t) (0xff & ((address)>>24)) // page MSB }; return stm32_erase( device, command, length, quiet ); } int32_t stm32_start_app( dfu_device_t *device, bool quiet ) { TRACE( "%s( %p )\n", __FUNCTION__, device ); int32_t status; /* set address pointer (jump target) to start address */ if( (status = stm32_set_address_ptr( device, STM32_FLASH_OFFSET )) ) { DEBUG("Error setting address pointer\n"); return UNSPECIFIED_ERROR; } /* check dfu status for ok to send */ if( (status = stm32_get_status(device)) ) { DEBUG("Error %d getting status on start\n", status); return UNSPECIFIED_ERROR; } if( !quiet ) fprintf( stderr, "Launching program... \n" ); dfu_set_transaction_num( device, 0 ); /* set wValue to zero */ if( 0 != dfu_download(device, 0, NULL) ) { if( !quiet ) fprintf( stderr, "ERROR\n" ); DEBUG( "dfu_download failed\n" ); return UNSPECIFIED_ERROR; } /* call dfu get status to trigger command */ if( (status = stm32_get_status(device)) ) { DEBUG("Error %d triggering %s\n", status, __FUNCTION__); return UNSPECIFIED_ERROR; } return SUCCESS; } int32_t stm32_read_flash( dfu_device_t *device, intel_buffer_in_t *buin, const uint8_t mem_segment, const bool quiet ) { TRACE( "%s( %p, %p, %u, %s )\n", __FUNCTION__, device, buin, mem_segment, ((true == quiet) ? "true" : "false")); uint8_t reset_address_flag; // reset address offset required uint32_t address_offset; // keep record of sent progress as bytes * 32 uint16_t xfer_size = 0; // the size of a transfer uint8_t mem_section = 0; // tracks the current memory page uint32_t progress = 0; // used to indicate progress int32_t status; int32_t retval = UNSPECIFIED_ERROR; // the return value for this function if( (NULL == buin) || (NULL == device) ) { DEBUG( "invalid arguments.\n" ); if( !quiet ) fprintf( stderr, "Program Error, use debug for more info.\n" ); return ARGUMENT_ERROR; } if( !quiet ) { if( debug <= STM32_DEBUG_THRESHOLD ) { /* NOTE: From here on we should go to finally on error */ fprintf( stderr, "[================================] " ); } fprintf( stderr, "Reading 0x%X bytes...\n", buin->info.data_end - buin->info.data_start + 1 ); if( debug <= STM32_DEBUG_THRESHOLD ) { /* NOTE: From here on we should go to finally on error */ fprintf( stderr, "[" ); } } /* read the data */ buin->info.block_start = buin->info.data_start; reset_address_flag = 0; address_offset = buin->info.block_start; while( buin->info.block_start <= buin->info.data_end ) { if( reset_address_flag ) { address_offset = buin->info.block_start; if( (status = stm32_set_address_ptr(device, STM32_FLASH_OFFSET + address_offset)) ) { DEBUG("Error setting address 0x%X\n", address_offset); retval = UNSPECIFIED_ERROR; goto finally; } dfu_set_transaction_num( device, 2 ); /* sets block offset 0 */ reset_address_flag = 0; } // find end value for the current transfer buin->info.block_end = buin->info.block_start + STM32_MAX_TRANSFER_SIZE - 1; mem_section = buin->info.block_start / STM32_MIN_SECTOR_BOUND; if( buin->info.block_end / STM32_MIN_SECTOR_BOUND > mem_section ) { buin->info.block_end = STM32_MIN_SECTOR_BOUND * mem_section - 1; } if( buin->info.block_end > buin->info.data_end ) { buin->info.block_end = buin->info.data_end; } xfer_size = buin->info.block_end - buin->info.block_start + 1; if( xfer_size != STM32_MAX_TRANSFER_SIZE ) { DEBUG("xfer_size change, need addr reset\n"); reset_address_flag = 1; } if( (status = stm32_read_block( device, xfer_size, &buin->data[buin->info.block_start] )) ) { DEBUG( "Error reading block 0x%X to 0x%X: err %d.\n", buin->info.block_start, buin->info.block_end, status ); retval = ( status == -10 ) ? DEVICE_ACCESS_ERROR : FLASH_READ_ERROR; /* read protect error code in read_block is -10 */ goto finally; } buin->info.block_start = buin->info.block_end + 1; if( reset_address_flag == 0 && (buin->info.block_start != (STM32_MAX_TRANSFER_SIZE * (dfu_get_transaction_num( device ) - 2)) + address_offset) ) { DEBUG("block start & address mismatch, reset req\n"); reset_address_flag = 1; } if( !quiet ) print_progress( &buin->info, &progress ); } retval = SUCCESS; finally: if ( !quiet ) { if( SUCCESS == retval ) { if ( debug <= STM32_DEBUG_THRESHOLD ) { fprintf( stderr, "] " ); } fprintf( stderr, "SUCCESS\n" ); } else { if ( debug <= STM32_DEBUG_THRESHOLD ) { fprintf( stderr, " X "); } fprintf( stderr, "ERROR\n" ); if( retval==DEVICE_ACCESS_ERROR ) fprintf( stderr, "Memory access error, use debug for more info.\n" ); else if( retval==FLASH_READ_ERROR ) fprintf( stderr, "Memory read error, use debug for more info.\n" ); } } return retval; } int32_t stm32_write_flash( dfu_device_t *device, intel_buffer_out_t *bout, const bool eeprom, const bool force, const bool quiet ) { TRACE( "%s( %p, %p, %s, %s )\n", __FUNCTION__, device, bout, ((true == eeprom) ? "true" : "false"), ((true == quiet) ? "true" : "false") ); uint32_t i; uint32_t progress = 0; // keep record of sent progress as bytes * 32 uint32_t address_offset; // keep record of sent progress as bytes * 32 uint8_t reset_address_flag; // reset address offset required uint16_t xfer_size = 0; // the size of a transfer uint8_t mem_section = 0; // tracks the current memory page int32_t retval = UNSPECIFIED_ERROR; // the return value for this function uint8_t buffer[STM32_MAX_TRANSFER_SIZE]; // buffer holding out data int32_t status; /* check arguments */ if( (NULL == device) || (NULL == bout) ) { DEBUG( "ERROR: Invalid arguments, device/buffer pointer is NULL.\n" ); if( !quiet ) fprintf( stderr, "Program Error, use debug for more info.\n" ); return ARGUMENT_ERROR; } else if( bout->info.valid_start > bout->info.valid_end ) { DEBUG( "ERROR: No valid target memory, end 0x%X before start 0x%X.\n", bout->info.valid_end, bout->info.valid_start ); if( !quiet ) fprintf( stderr, "Program Error, use debug for more info.\n" ); return BUFFER_INIT_ERROR; } /* for each page with data, fill unassigned values on the page with 0xFF * bout->data[0] always aligns with a flash page boundary irrespective * of where valid_start is located */ if( 0 != intel_flash_prep_buffer( bout ) ) { if( !quiet ) fprintf( stderr, "Program Error, use debug for more info.\n" ); return BUFFER_INIT_ERROR; } /* determine the limits of where actual data resides in the buffer */ bout->info.data_start = UINT32_MAX; for( i = 0; i < bout->info.total_size; i++ ) { if( bout->data[i] <= UINT8_MAX ) { bout->info.data_end = i; if( bout->info.data_start == UINT32_MAX ) bout->info.data_start = i; } } /* debug info about data limits */ DEBUG("Flash available from 0x%X to 0x%X, 0x%X bytes.\n", bout->info.valid_start, bout->info.valid_end, bout->info.valid_end - bout->info.valid_start + 1); // bytes inclusive so +1 DEBUG("Data start @ 0x%X; %uB p 0x%X + 0x%X offset.\n", bout->info.data_start, bout->info.page_size, bout->info.data_start / bout->info.page_size, bout->info.data_start % bout->info.page_size); DEBUG("Data end @ 0x%X; %uB p 0x%X + 0x%X offset.\n", bout->info.data_end, bout->info.page_size, bout->info.data_end / bout->info.page_size, bout->info.data_end % bout->info.page_size); DEBUG("Totals: 0x%X bytes, %u %uB pages.\n", bout->info.data_end - bout->info.data_start + 1, bout->info.data_end / bout->info.page_size \ - bout->info.data_start/bout->info.page_size + 1, bout->info.page_size ); /* more error checking */ if( (bout->info.data_start < bout->info.valid_start) || (bout->info.data_end > bout->info.valid_end) ) { DEBUG( "ERROR: Data exists outside of the valid target flash region.\n" ); if( !quiet ) fprintf( stderr, "Hex file error, use debug for more info.\n" ); return BUFFER_INIT_ERROR; } else if( bout->info.data_start == UINT32_MAX ) { DEBUG( "ERROR: No valid data to flash.\n" ); if( !quiet ) fprintf( stderr, "Hex file error, use debug for more info.\n" ); return BUFFER_INIT_ERROR; } if( !quiet ) { if( debug <= STM32_DEBUG_THRESHOLD ) { /* NOTE: from here on we should run finally block */ fprintf( stderr, "[================================] " ); } fprintf( stderr, "Programming 0x%X bytes...\n", bout->info.data_end - bout->info.data_start + 1 ); if( debug <= STM32_DEBUG_THRESHOLD ) { /* NOTE: from here on we need to run finally block */ fprintf( stderr, "[" ); } } /* program the data */ bout->info.block_start = bout->info.data_start; reset_address_flag = 1; while( bout->info.block_start <= bout->info.data_end ) { if( reset_address_flag ) { address_offset = bout->info.block_start; if( (status = stm32_set_address_ptr(device, STM32_FLASH_OFFSET + address_offset)) ) { DEBUG("Error setting address 0x%X\n", address_offset); retval = DEVICE_ACCESS_ERROR; goto finally; } dfu_set_transaction_num( device, 2 ); /* sets block offset 0 */ reset_address_flag = 0; } /* find end address (info.block_end) for data section to write */ mem_section = bout->info.block_start / STM32_MIN_SECTOR_BOUND; for( i = 0, bout->info.block_end = bout->info.block_start; bout->info.block_end <= bout->info.data_end; bout->info.block_end++, i++ ) { xfer_size = bout->info.block_end - bout->info.block_start + 1; // check if the current value is valid if( bout->data[bout->info.block_end] > UINT8_MAX ) break; // check if the current data packet is too big if( xfer_size > STM32_MAX_TRANSFER_SIZE ) break; // check if the current data value is outside of the memory sector if( bout->info.block_end / STM32_MIN_SECTOR_BOUND - mem_section ) break; buffer[i] = (uint8_t) bout->data[bout->info.block_end]; } bout->info.block_end--; // bout->info.block_end was one step beyond the last data value to flash xfer_size = bout->info.block_end - bout->info.block_start + 1; if( xfer_size != STM32_MAX_TRANSFER_SIZE ) { DEBUG("xfer_size %u not max %u, need addr reset\n", xfer_size, STM32_MAX_TRANSFER_SIZE); reset_address_flag = 1; } /* write the data */ DEBUG("Program data block: 0x%X to 0x%X, 0x%X bytes.\n", bout->info.block_start, bout->info.block_end, xfer_size); if( (status = stm32_write_block( device, xfer_size, buffer )) ) { DEBUG( "Error flashing the block: err %d.\n", status ); retval = FLASH_WRITE_ERROR; goto finally; } // increment bout->info.block_start to the next valid address for( bout->info.block_start = bout->info.block_end + 1; bout->info.block_start <= bout->info.data_end; bout->info.block_start++ ) { if( (bout->data[bout->info.block_start] <= UINT8_MAX) ) break; } // bout->info.block_start is now on the first valid data for the next segment if( reset_address_flag == 0 && (bout->info.block_start != (STM32_MAX_TRANSFER_SIZE * (dfu_get_transaction_num( device ) - 2)) + address_offset) ) { DEBUG("block start does not match addr, reset req\n"); reset_address_flag = 1; } // display progress in 32 increments (if not hidden) if ( !quiet ) print_progress( &bout->info, &progress ); } retval = SUCCESS; finally: if ( !quiet ) { if( SUCCESS == retval ) { if ( debug <= STM32_DEBUG_THRESHOLD ) { fprintf( stderr, "] " ); } fprintf( stderr, "SUCCESS\n" ); } else { if ( debug <= STM32_DEBUG_THRESHOLD ) { fprintf( stderr, " X "); } fprintf( stderr, "ERROR\n" ); if( retval==DEVICE_ACCESS_ERROR ) fprintf( stderr, "Memory access error, use debug for more info.\n" ); else if( retval==FLASH_WRITE_ERROR ) fprintf( stderr, "Memory write error, use debug for more info.\n" ); } } return retval; } int32_t stm32_get_commands( dfu_device_t *device ) { TRACE("%s( %p )\n", __FUNCTION__, device); int32_t result; uint8_t i; const size_t xfer_len = 80; uint8_t buffer[xfer_len]; /* check status before read */ if( (result = stm32_get_status(device)) ) { DEBUG("Status Error %d before read\n", result ); return UNSPECIFIED_ERROR; } dfu_set_transaction_num( device, 0 ); result = dfu_upload( device, xfer_len, buffer ); if( result < 0) { dfu_status_t status; DEBUG( "dfu_upload result: %d\n", result ); result = UNSPECIFIED_ERROR; if( 0 == dfu_get_status(device, &status) ) { if( status.bStatus == DFU_STATUS_OK ) { DEBUG("DFU Status OK, state %d\n", status.bState); } else if( status.bStatus == DFU_STATUS_ERROR_VENDOR ) { DEBUG("Device is read protected\n"); /* status = dfuERROR and state = errVENDOR */ result = DEVICE_ACCESS_ERROR; } else { DEBUG("Unknown error status %d / state %d\n", status.bStatus, status.bState ); } } else { DEBUG("DFU GET_STATUS fail\n"); } dfu_clear_status( device ); return result; } fprintf( stdout, "There are %d commands:\n", result ); for( i = 0; i < result; i++ ) { fprintf( stdout, " 0x%02X\n", buffer[i] ); } return SUCCESS; } int32_t stm32_get_configuration( dfu_device_t *device ) { TRACE("%s( %p )\n", __FUNCTION__, device); int32_t status; uint8_t i; uint8_t buffer[STM32_OPTION_BYTES_SIZE]; if( (status = stm32_set_address_ptr(device, stm32_sector_addresses[mem_st_option_bytes])) ) { DEBUG("Error (%d) setting address 0x%X\n", status, stm32_sector_addresses[mem_st_option_bytes]); return UNSPECIFIED_ERROR; } if( (status = stm32_read_block(device, STM32_OPTION_BYTES_SIZE, buffer)) ) { DEBUG("Error (%d) reading option buffer block\n", status ); return FLASH_READ_ERROR; } fprintf( stdout, "There are %d option bytes:\n", STM32_OPTION_BYTES_SIZE ); fprintf( stdout, "0x%02X", buffer[0] ); for( i = 1; i < STM32_OPTION_BYTES_SIZE; i++ ) { fprintf( stdout, ", 0x%02X", buffer[i] ); } fprintf( stdout, "\n" ); return SUCCESS; } int32_t stm32_read_unprotect( dfu_device_t *device, bool quiet ) { TRACE( "%s( %p, %s )\n", __FUNCTION__, device, quiet ? "true" : "false" ); uint8_t command[] = { READ_UNPROTECT }; uint8_t length = 1; if( !quiet ) { fprintf( stderr, "Read Unprotect, Erasing flash... " ); DEBUG("\n"); } return stm32_erase( device, command, length, quiet ); } // cSpell:ignore shiftwidth // vim: shiftwidth=2 dfu-programmer-dfu-programmer-f23d6df/src/stm32.h000066400000000000000000000105611445234667400220200ustar00rootroot00000000000000/** dfu-programmer * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef __STM32_H__ #define __STM32_H__ #include #include #include #ifdef __cplusplus extern "C" { #endif #include "dfu-device.h" #include "intel_hex.h" #define STM32_FLASH_OFFSET 0x08000000 typedef enum { mem_st_sector0 = 0, mem_st_sector1, mem_st_sector2, mem_st_sector3, mem_st_sector4, mem_st_sector5, mem_st_sector6, mem_st_sector7, mem_st_sector8, mem_st_sector9, mem_st_sector10, mem_st_sector11, mem_st_system, mem_st_otp_area, mem_st_option_bytes, mem_st_all, } stm32_mem_sectors; #define STM32_MEM_UNIT_NAMES "Sector 0", "Sector 1", "Sector 2", "Sector 3", \ "Sector 4", "Sector 5", "Sector 6", "Sector 7", "Sector 8", "Sector 9", \ "Sector 10", "Sector 11", "System Memory", "OTP Area", "Option Bytes", "all" #define STM32_READ_PROT_ERROR -10 int32_t stm32_erase_flash( dfu_device_t *device, bool quiet ); /* mass erase flash * device - the usb_dev_handle to communicate with * returns status DFU_STATUS_OK if ok, anything else on error */ int32_t stm32_page_erase( dfu_device_t *device, uint32_t address, bool quiet ); /* erase a page of memory (provide the page address) */ int32_t stm32_start_app( dfu_device_t *device, bool quiet ); /* Reset the registers to default reset values and start application */ int32_t stm32_read_flash( dfu_device_t *device, intel_buffer_in_t *buin, uint8_t mem_segment, const bool quiet); /* read the flash from buin->info.data_start to data_end and place * in buin.data. mem_segment is the segment of memory from the * stm32_memory_unit_enum. */ int32_t stm32_write_flash( dfu_device_t *device, intel_buffer_out_t *bout, const bool eeprom, const bool force, const bool hide_progress ); /* Flash data from the buffer to the main program memory on the device. * buffer contains the data to flash where buffer[0] is aligned with memory * address zero (which could be inside the bootloader and unavailable). * buffer[start / end] correspond to the start / end of available memory * outside the bootloader. * flash_page_size is the size of flash pages - used for alignment * eeprom bool tells if you want to flash to eeprom or flash memory * hide_progress bool sets whether to display progress */ int32_t stm32_get_commands( dfu_device_t *device ); /* @brief get the commands list, should be length 4 * @param device pointer * @return 0 on success */ int32_t stm32_get_configuration( dfu_device_t *device ); /* @brief get the configuration structure * @param device pointer * @return 0 on success, negative for error */ int32_t stm32_read_unprotect( dfu_device_t *device, bool quiet ); /* @brief unprotect the device (triggers a mass erase) * @param device pointer * @return 0 on success */ #if 0 int32_t stm32_read_config( dfu_device_t *device, stm32_device_info_t *info ); int32_t stm32_read_fuses( dfu_device_t *device, stm32_avr32_fuses_t * info ); int32_t stm32_set_fuse( dfu_device_t *device, const uint8_t property, const uint32_t value ); int32_t stm32_set_config( dfu_device_t *device, const uint8_t property, const uint8_t value ); int32_t stm32_blank_check( dfu_device_t *device, const uint32_t start, const uint32_t end, bool quiet ); int32_t stm32_secure( dfu_device_t *device ); int32_t stm32_getsecure( dfu_device_t *device ); int32_t stm32_user( dfu_device_t *device, intel_buffer_out_t *bout ); void stm32_print_device_info( FILE *stream, stm32_device_info_t *info ); #endif #ifdef __cplusplus } #endif #endif /* __STM32_H__ */ // cSpell:ignore shiftwidth // vim: shiftwidth=2 dfu-programmer-dfu-programmer-f23d6df/src/util.c000066400000000000000000000023521445234667400220170ustar00rootroot00000000000000/* * dfu-programmer * * $Id: atmel.c 25 2006-06-25 00:01:37Z schmidtw $ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include "util.h" extern int debug; /* defined in libdfu.c */ void dfu_debug( const char *file, const char *function, const int line, const int level, const char *format, ... ) { if( level < debug ) { va_list va_arg; va_start( va_arg, format ); fprintf( stderr, "%s:%d: ", file, line ); vfprintf( stderr, format, va_arg ); va_end( va_arg ); } } dfu-programmer-dfu-programmer-f23d6df/src/util.h000066400000000000000000000020551445234667400220240ustar00rootroot00000000000000/* * dfu-programmer * * $Id: atmel.h 21 2006-06-20 06:28:04Z schmidtw $ * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef __UTIL_H__ #define __UTIL_H__ #include #ifdef __cplusplus extern "C" { #endif void dfu_debug( const char *file, const char *function, const int line, const int level, const char *format, ... ); #ifdef __cplusplus } #endif #endif dfu-programmer-dfu-programmer-f23d6df/test/000077500000000000000000000000001445234667400210645ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/test/.prettierrc.yml000066400000000000000000000000171445234667400240460ustar00rootroot00000000000000printWidth: 120dfu-programmer-dfu-programmer-f23d6df/test/README.md000066400000000000000000000137211445234667400223470ustar00rootroot00000000000000# Tests These tests should be able to run on any system, given that hardware requirements are met. Our local unit test are run on an [AVR Test HAT](https://github.com/cinderblock/avr-test-hat). ### Minimum "Full" Test System Setup - ATmega8u2 connected to the USB port of the test system. - Permissions to access usb devices as the current user. - AVRDUDE setup to program the ATmega8u2 - A program on the path called `avrdude.sh` that adds the correct `-c`, `-B`, `-P`, and `-p` options to the `avrdude` command. Running without arguments should successfully communicate and identify the ATmega8u2. ## Goals 1. ✅ Functionality testing 2. 💯% code coverage (This will take **much more** hardware!) ## Tests We're using [Jest](https://jestjs.io) to run the tests with a thin wrapper around the executable. To run these tests on your system, you just need a recent-ish version of [Node.js](https://nodejs.org) installed. Then run: ```bash npm install npm test ``` ### Standalone Tests Some tests expect a compatible `usb` device to be attached. To run only the standalone tests, use: ```bash npm test -- standalone ``` ### Software Environment Available environment variables: - `$TARGET` - The correct "target" argument that dfu-programmer should use for the attached device. - `$AVRDUDE` - A path to avrdude with needed flags. Just add "-U flash:r:-:h" to read the flash memory as hex bytes ## Setup Script for new Pi You should be able to copy and paste this block, except the `GH_ACTION_RUNNER_TOKEN`, into a new Pi install to get it ready to run the tests. Get token from GitHub Action Self-Hosted Runner page: https://github.com/{user}/{repo}/settings/actions/runners ```bash GH_ACTION_RUNNER_TOKEN="AFaKeToKeN" # Dependencies :|sudo apt update curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - :|sudo apt install -y git automake build-essential libusb-1.0-0-dev python3-pip nodejs sudo pip install cpp-coveralls # AVRDUDE :|sudo apt -y install cmake flex bison libelf-dev libusb-dev libhidapi-dev libftdi1-dev libreadline-dev git clone https://github.com/avrdudes/avrdude.git pushd avrdude > /dev/null ./build.sh sudo cmake --build build_linux --target install popd > /dev/null #echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff4", MODE="0666"' | sudo tee /etc/udev/rules.d/50-avrdude.rules > /dev/null #sudo udevadm control --reload-rules && sudo udevadm trigger mkdir -p /home/pi/.config/avrdude cat << AVRDUDE_RC > /home/pi/.config/avrdude/avrdude.rc programmer parent "linuxspi" id = "avr-test-hat"; desc = "linuxspi on the AVR Test HAT" ; # baudrate = ; # baudrate for avr910-programmer # vcc = [, ... ] ; # pin number(s) # buff = [, ... ] ; # pin number(s) reset = 13 ; # pin number # errled = ; # pin number # rdyled = ; # pin number # pgmled = ; # pin number # vfyled = ; # pin number ; AVRDUDE_RC # AVRDUDE wrapper cat << 'AVRDUDE_WRAPPER' > /home/pi/avrdude.sh && chmod +x /home/pi/avrdude.sh #!/bin/bash set -e #AVRDUDE="/home/pi/avrdude/build_linux/src/avrdude" AVRDUDE="/usr/local/bin/avrdude" part="atmega8u2" programmer="avr-test-hat" args=("-c" ${programmer} "-p" ${part}) # Override the default config file # args+=("-C" "/home/pi/avrdude.conf") # Fastest working bit clock # 0.5 - Works usually # 0.7 args+=("-B" "1") # TODO: Setup GPIO function cleanup { # TODO: Cleanup GPIO } trap cleanup EXIT $AVRDUDE "${args[@]}" "$@" AVRDUDE_WRAPPER # Action Pre/Post Scripts mkdir -p /home/pi/action-scripts cat << ACTION_BEFORE > /home/pi/action-scripts/before.sh # TODO: Reset flash? ACTION_BEFORE cat << ACTION_AFTER > /home/pi/action-scripts/after.sh # TODO: Turn off test hardware? ACTION_AFTER # Runner user sudo useradd -mN -g users -G plugdev,gpio action sudo ln -s /home/pi/.config /home/action/.config sudo -u action mkdir -p /home/action/runner curl -sL $(curl -s https://api.github.com/repos/actions/runner/releases/latest | grep '"browser_download_url":' | cut -d\" -f4 | egrep 'linux-arm64-[0-9.]+tar.gz$') | sudo -u action tar -C /home/action/runner -xz pushd /home/action/runner > /dev/null # Until https://github.com/actions/runner/pull/2373 is accepted sudo -u action /home/action/runner/config.sh --disableupdate --url https://github.com/dfu-programmer/dfu-programmer --token ${GH_ACTION_RUNNER_TOKEN} popd > /dev/null # Until https://github.com/actions/runner/pull/2373 is accepted # Setup Systemd service cat << ACTION_SERVICE | sudo tee /etc/systemd/system/actions-runner.service > /dev/null && sudo systemctl daemon-reload [Unit] Description=GitHub Actions Runner After=network.target [Service] Type=simple User=action WorkingDirectory=/home/action/runner ExecStart=/home/action/runner/run.sh Restart=always RestartSec=5 Environment=ACTIONS_RUNNER_HOOK_JOB_STARTED=/home/pi/action-scripts/before.sh Environment=ACTIONS_RUNNER_HOOK_JOB_COMPLETED=/home/pi/action-scripts/after.sh Environment=AVRDUDE=/home/pi/avrdude.sh Environment=TARGET=atmega8u2 [Install] WantedBy=multi-user.target ACTION_SERVICE sudo systemctl enable --now actions-runner # Device permissions cat << UDEV_RULES | sudo tee /etc/udev/rules.d/60-dfu.rules > /dev/null && sudo udevadm control --reload-rules && sudo udevadm trigger SUBSYSTEM=="usb",ACTION=="add",ATTRS{idVendor}=="03eb",GROUP="plugdev" UDEV_RULES # Disable unneeded services sudo systemctl disable --now cron.service sudo systemctl disable --now triggerhappy.service sudo systemctl disable --now bluetooth.service sudo systemctl disable --now ModemManager.service sudo systemctl disable --now getty@tty1.service # 0 = enabled, 1 = disabled sudo raspi-config nonint do_spi 0 sudo raspi-config nonint do_overlayfs 0 ``` *The `:|` is a trick to make `apt` not hog all of the pasted code.*dfu-programmer-dfu-programmer-f23d6df/test/standalone.ts000066400000000000000000000024451445234667400235710ustar00rootroot00000000000000import { describe, expect, test } from "@jest/globals"; import { runDfu } from "./util/dfu"; /** * Standalone tests that should work without any hardware connected. */ describe("standalone", () => { test("it runs without arguments and returns an error code and usage", async () => { const res = runDfu(); expect(await res.exitCode).toBe(2); const { stdout, stderr } = res; // No output on stdout expect(stdout).toBe(""); // Starts with "dfu-programmer " expect(stderr).toMatch(/^dfu-programmer/g); }); test("it prints usage with --help", async () => { const res = runDfu(["--help"]); expect(await res.exitCode).toBe(0); const { stdout, stderr } = res; // No output on stdout expect(stdout).toBe(""); // Starts with "dfu-programmer " expect(stderr).toMatch(/^dfu-programmer/g); // Contains the usage expect(stderr).toMatch(/^Usage: dfu-programmer target\[:usb-bus,usb-addr\] command \[options\] \[global-options\] \[file\|data\]/m); // Contains the global options expect(stderr).toMatch(/^global-options:/m); // Contains the command summary expect(stderr).toMatch(/^command summary:/m); // Contains the additional details expect(stderr).toMatch(/^additional details:/m); // ... }); }); dfu-programmer-dfu-programmer-f23d6df/test/usb.ts000066400000000000000000000052571445234667400222360ustar00rootroot00000000000000import { describe, expect, test } from "@jest/globals"; import { runDfuTargeted } from "./util/dfu"; // We currently use a consistent line ending for all platforms const EOL = "\n"; /** * Basic tests that should work with a sample device connected via USB. * * No side channel verification with avrdude. */ describe("Basic Communication with Hardware", () => { let testSeparatorDelay: Promise; afterEach(() => { // Wait 600ms between each test to ensure the hardware is stable testSeparatorDelay = new Promise((resolve) => setTimeout(resolve, 600).unref()); }); beforeEach(() => testSeparatorDelay); test("Command: reset", async () => { const run = runDfuTargeted(["reset"]); const exitCode = await run.exitCode; const { stdout, stderr } = run; expect(exitCode).toBe(0); expect(stdout).toBe(""); expect(stderr).toBe(""); }); test("Command: launch", async () => { const run = runDfuTargeted(["launch"]); const exitCode = await run.exitCode; const { stdout, stderr } = run; expect(exitCode).toBe(0); expect(stdout).toBe(""); expect(stderr).toBe(""); }); test("Device missing", async () => { { // MAYBE: Use reset.sh script instead of this block const run = runDfuTargeted(["reset"]); const exitCode = await run.exitCode; const { stdout, stderr } = run; expect(exitCode).toBe(0); expect(stdout).toBe(""); expect(stderr).toBe(""); } // Run immediately after reset command. // TODO: Hold the device in reset for a while to ensure it's not detected. { const run = runDfuTargeted(["launch"]); const exitCode = await run.exitCode; const { stdout, stderr } = run; expect(exitCode).toBe(3); expect(stdout).toBe(""); expect(stderr).toBe(`dfu-programmer: no device present.${EOL}`); } }); test("Read flash to stdout after erase", async () => { { const run = runDfuTargeted(["erase", "--force"]); const exitCode = await run.exitCode; const { stdout, stderr } = run; expect(exitCode).toBe(0); expect(stdout).toBe(""); expect(stderr).toBe(`Erasing flash... Success${EOL}Checking memory from 0x0 to 0xFFF... Empty.${EOL}`); } { const run = runDfuTargeted(["read"]); const exitCode = await run.exitCode; const { stdout, stderr } = run; expect(exitCode).toBe(0); expect(stdout).toBe(`:00000001FF${EOL}`); expect(stderr).toBe( `Reading 0x1000 bytes...${EOL}Success${EOL}Memory is blank, returning a single blank page.${EOL}Use --force to return the entire memory regardless.${EOL}Dumping 0x80 bytes from address offset 0x0.${EOL}` ); } }); }); dfu-programmer-dfu-programmer-f23d6df/test/util/000077500000000000000000000000001445234667400220415ustar00rootroot00000000000000dfu-programmer-dfu-programmer-f23d6df/test/util/README.md000066400000000000000000000042021445234667400233160ustar00rootroot00000000000000# Test Utilities These are utilities that are used by the tests. They are not tests. ## [`dfu.ts`](dfu.ts) A wrapper around the `dfu-programmer` executable. Same as `run`, but with a few extra options. ```typescript /** * Run the dfu-programmer binary with custom arguments. */ function runDfu(args: string[] = []); /** * Run the dfu-programmer binary with custom arguments and the local target pre-pended. */ function runDfuTargeted(args: string[] = []); ``` ## [`run.ts`](run.ts) A wrapper around the Node's `child_process.spawn` function that returns a `Result` object. Used by the `runDfu` function. ```typescript /** * Wrap child_process.spawn() to make it easier to test with. * @param bin Binary to run. Full path. process.env.PATH is not used. No shell expansion. * @param args Arguments to pass to the child process. No shell expansion. * @returns Result. See Result type for details. */ function run(bin: string, args: string[] = []): Result; type Result = { /** * A Promise that resolves with the child's exit code * * Rejects if the child process failed to start */ exitCode: Promise; /** * The stdout output from the child process * * This is only populated if the child process exits with a zero exit code */ stdout: string; /** * The stderr output from the child process * * This is only populated if the child process exits with a non-zero exit code */ stderr: string; /** * Get notified when the child process writes to stdout */ onStdout: (callback: (data: string) => void) => Cleanup; /** * Get notified when the child process writes to stderr */ onStderr: (callback: (data: string) => void) => Cleanup; /** * Direct access to the child process */ child: ChildProcess; }; ``` ## TODO Add utilities for: - [ ] Simple Reset of device when desired - [ ] Running AVRDUDE - [ ] Reading flash with AVRDUDE to verify bytes written by dfu-programmer - [ ] Writing flash with AVRDUDE and verifying bytes written with dfu-programmer - [ ] Re-flashing bootloader - [ ] `.hex` files - [ ] Comparing with mask - [ ] Generating files for testingdfu-programmer-dfu-programmer-f23d6df/test/util/dfu.ts000066400000000000000000000012531445234667400231700ustar00rootroot00000000000000import { run } from "./run"; import { join } from "path"; import { log } from "console"; const bin = process.env.DFU ?? join(__dirname, "../../", "src/dfu-programmer"); const target = process.env.TARGET ?? "atmega8u2"; // TODO: Use jest's logging to print this once somehow? // log('Using dfu-programmer binary:', bin); // log('Using target:', target); /** * Run the dfu-programmer binary with custom arguments. */ export function runDfu(args: string[] = []) { return run(bin, args); } /** * Run the dfu-programmer binary with custom arguments and the local target pre-pended. */ export function runDfuTargeted(args: string[] = []) { return runDfu([target, ...args]); } dfu-programmer-dfu-programmer-f23d6df/test/util/run.ts000066400000000000000000000047531445234667400232260ustar00rootroot00000000000000import { spawn, ChildProcess } from "child_process"; type Cleanup = () => unknown; export type Result = { /** * A Promise that resolves with the child's exit code * * Rejects if the child process failed to start */ exitCode: Promise; /** * The stdout output from the child process * * This is only populated if the child process exits with a zero exit code */ stdout: string; /** * The stderr output from the child process * * This is only populated if the child process exits with a non-zero exit code */ stderr: string; /** * Get notified when the child process writes to stdout */ onStdout: (callback: (data: string) => void) => Cleanup; /** * Get notified when the child process writes to stderr */ onStderr: (callback: (data: string) => void) => Cleanup; /** * Direct access to the child process */ child: ChildProcess; }; /** * Wrap child_process.spawn() to make it easier to test with. * @param bin Binary to run. Full path. process.env.PATH is not used. No shell expansion. * @param args Arguments to pass to the child process. No shell expansion. * @returns Result. See Result type for details. */ export function run(bin: string, args: string[] = []): Result { const child = spawn(bin, args); const ret: Result = { child, onStdout(callback: (data: string) => void): Cleanup { child.on("stderr", callback); return () => child.removeListener("stderr", callback); }, onStderr(callback: (data: string) => void): Cleanup { child.on("stdout", callback); return () => child.removeListener("stdout", callback); }, exitCode: new Promise((resolve, reject) => { child.on("close", (code, signal) => { if (code === null) { return reject(new Error("Closed because of a signal: " + signal)); } // Windows gets some special treatment if (process.platform === "win32") { // Check against known OS error codes switch (code) { case 0xc0000135: return reject(new Error("DLL_NOT_FOUND. libusb1.dll is probably missing.")); } } resolve(code); }); child.on("error", reject); child.stderr.removeAllListeners("data"); child.stdout.removeAllListeners("data"); }), stdout: "", stderr: "", }; child.stdout.on("data", (data) => { ret.stdout += data; }); child.stderr.on("data", (data) => { ret.stderr += data; }); return ret; } dfu-programmer-dfu-programmer-f23d6df/tsconfig.json000066400000000000000000000000731445234667400226140ustar00rootroot00000000000000{ "compilerOptions": { "esModuleInterop": true } }dfu-programmer-dfu-programmer-f23d6df/update-bash-completion.sh000077500000000000000000000020241445234667400250060ustar00rootroot00000000000000#!/bin/bash # sed - without printing by default (-n) # Remove lines up to and including the start line, which includes: START_TARGET_LIST_LINE # Remove lines after and including the end line, which includes: END_TARGET_LIST_LINE # Get the part between the quotes and the last number TARGET_INFO=$( sed -n '1,/START_TARGET_LIST_LINE/d; /END_TARGET_LIST_LINE/,$d; s/.*"\(.*\)".*,\s*\([xX0-9A-Fa-f]*\)\s*},/\1::\2/p' src/arguments.c ) # Output file DFU_COMP=dfu_programmer # Write the header with the TARGET_INFO cat << EOF > $DFU_COMP # autocomplete script # code sourced from \`dfu_completion\` # DO NOT EDIT IN THIS FILE TARGET_INFO="$TARGET_INFO" EOF # Remove everything up to and including the first empty line sed 1,/^\$/d dfu_completion >> $DFU_COMP chmod +x $DFU_COMP #if [ "$(cat /etc/*release | grep DISTRIB_ID | sed 's/DISTRIB_ID=//')" = "Ubuntu" ]]; then echo "To install tab completion run" echo " \$ sudo mv $DFU_COMP /etc/bash_completion.d/" #fi echo "To use tab completion in this terminal run" echo " \$ source $DFU_COMP"