diff --git a/INSTALL b/INSTALL index 2099840..8865734 100644 --- a/INSTALL +++ b/INSTALL @@ -1,8 +1,8 @@ Installation Instructions ************************* -Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, -Inc. + Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software +Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright @@ -12,97 +12,96 @@ without warranty of any kind. Basic Installation ================== - Briefly, the shell command `./configure && make && make install' + Briefly, the shell command './configure && make && make install' should configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for +more-detailed instructions are generic; see the 'README' file for instructions specific to this package. Some packages provide this -`INSTALL' file but do not implement all of the features documented +'INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. - The `configure' shell script attempts to guess correct values for + The 'configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that +those values to create a 'Makefile' in each directory of the package. +It may also create one or more '.h' files containing system-dependent +definitions. Finally, it creates a shell script 'config.status' that you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). +file 'config.log' containing compiler output (useful mainly for +debugging 'configure'). - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. + It can also use an optional file (typically called 'config.cache' and +enabled with '--cache-file=config.cache' or simply '-C') that saves the +results of its tests to speed up reconfiguring. Caching is disabled by +default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can +to figure out how 'configure' could check whether to do them, and mail +diffs or instructions to the address given in the 'README' so they can be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you +some point 'config.cache' contains results you don't want to keep, you may remove or edit it. - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. + The file 'configure.ac' (or 'configure.in') is used to create +'configure' by a program called 'autoconf'. You need 'configure.ac' if +you want to change it or regenerate 'configure' using a newer version of +'autoconf'. The simplest way to compile this package is: - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. + 1. 'cd' to the directory containing the package's source code and type + './configure' to configure the package for your system. - Running `configure' might take a while. While running, it prints + Running 'configure' might take a while. While running, it prints some messages telling which features it is checking for. - 2. Type `make' to compile the package. + 2. Type 'make' to compile the package. - 3. Optionally, type `make check' to run any self-tests that come with + 3. Optionally, type 'make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. - 4. Type `make install' to install the programs and any data files and + 4. Type 'make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular - user, and only the `make install' phase executed with root + user, and only the 'make install' phase executed with root privileges. - 5. Optionally, type `make installcheck' to repeat any self-tests, but + 5. Optionally, type 'make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a - regular user, particularly if the prior `make install' required + regular user, particularly if the prior 'make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly + source code directory by typing 'make clean'. To also remove the + files that 'configure' created (so you can compile the package for + a different kind of computer), type 'make distclean'. There is + also a 'make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. - 7. Often, you can also type `make uninstall' to remove the installed + 7. Often, you can also type 'make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. - 8. Some packages, particularly those that use Automake, provide `make + 8. Some packages, particularly those that use Automake, provide 'make distcheck', which can by used by developers to test that all other - targets like `make install' and `make uninstall' work correctly. + targets like 'make install' and 'make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' +the 'configure' script does not know about. Run './configure --help' for details on some of the pertinent environment variables. - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: + You can give 'configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here is +an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix @@ -113,21 +112,21 @@ Compiling For Multiple Architectures You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the +own directory. To do this, you can use GNU 'make'. 'cd' to the directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. This -is known as a "VPATH" build. +the 'configure' script. 'configure' automatically checks for the source +code in the directory that 'configure' is in and in '..'. This is known +as a "VPATH" build. - With a non-GNU `make', it is safer to compile the package for one + With a non-GNU 'make', it is safer to compile the package for one architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before +installed the package for one architecture, use 'make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple `-arch' options to the -compiler but only a single `-arch' option to the preprocessor. Like +"universal" binaries--by specifying multiple '-arch' options to the +compiler but only a single '-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ @@ -136,105 +135,104 @@ this: This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results -using the `lipo' tool if you have problems. +using the 'lipo' tool if you have problems. Installation Names ================== - By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX', where PREFIX must be an + By default, 'make install' installs the package's commands under +'/usr/local/bin', include files under '/usr/local/include', etc. You +can specify an installation prefix other than '/usr/local' by giving +'configure' the option '--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses +pass the option '--exec-prefix=PREFIX' to 'configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the -default for these options is expressed in terms of `${prefix}', so that -specifying just `--prefix' will affect all of the other directory +options like '--bindir=DIR' to specify different values for particular +kinds of files. Run 'configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the default +for these options is expressed in terms of '${prefix}', so that +specifying just '--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the -correct locations to `configure'; however, many packages provide one or +correct locations to 'configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the -`make install' command line to change installation locations without +'make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each -affected directory. For example, `make install +affected directory. For example, 'make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of -`${prefix}'. Any directories that were specified during `configure', -but not in terms of `${prefix}', must each be overridden at install -time for the entire installation to be relocated. The approach of -makefile variable overrides for each directory variable is required by -the GNU Coding Standards, and ideally causes no recompilation. -However, some platforms have known limitations with the semantics of -shared libraries that end up requiring recompilation when using this -method, particularly noticeable in packages that use GNU Libtool. - - The second method involves providing the `DESTDIR' variable. For -example, `make install DESTDIR=/alternate/directory' will prepend -`/alternate/directory' before all installation names. The approach of -`DESTDIR' overrides is not required by the GNU Coding Standards, and +'${prefix}'. Any directories that were specified during 'configure', +but not in terms of '${prefix}', must each be overridden at install time +for the entire installation to be relocated. The approach of makefile +variable overrides for each directory variable is required by the GNU +Coding Standards, and ideally causes no recompilation. However, some +platforms have known limitations with the semantics of shared libraries +that end up requiring recompilation when using this method, particularly +noticeable in packages that use GNU Libtool. + + The second method involves providing the 'DESTDIR' variable. For +example, 'make install DESTDIR=/alternate/directory' will prepend +'/alternate/directory' before all installation names. The approach of +'DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of `${prefix}' -at `configure' time. +when some directory options were not specified in terms of '${prefix}' +at 'configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the +with an extra prefix or suffix on their names by giving 'configure' the +option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. + + Some packages pay attention to '--enable-FEATURE' options to +'configure', where FEATURE indicates an optional part of the package. +They may also pay attention to '--with-PACKAGE' options, where PACKAGE +is something like 'gnu-as' or 'x' (for the X Window System). The +'README' should mention any '--enable-' and '--with-' options that the package recognizes. - For packages that use the X Window System, `configure' can usually + For packages that use the X Window System, 'configure' can usually find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. +you can use the 'configure' options '--x-includes=DIR' and +'--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the -execution of `make' will be. For these packages, running `./configure +execution of 'make' will be. For these packages, running './configure --enable-silent-rules' sets the default to minimal output, which can be -overridden with `make V=1'; while running `./configure +overridden with 'make V=1'; while running './configure --disable-silent-rules' sets the default to verbose, which can be -overridden with `make V=0'. +overridden with 'make V=0'. Particular systems ================== - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in + On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC +is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. - HP-UX `make' updates targets which have the same time stamps as -their prerequisites, which makes it generally unusable when shipped -generated files such as `configure' are involved. Use GNU `make' -instead. + HP-UX 'make' updates targets which have the same time stamps as their +prerequisites, which makes it generally unusable when shipped generated +files such as 'configure' are involved. Use GNU 'make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its `' header file. The option `-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try +parse its '' header file. The option '-nodtk' can be used as a +workaround. If GNU CC is not installed, it is therefore recommended to +try ./configure CC="cc" @@ -242,26 +240,26 @@ and if that doesn't work, try ./configure CC="cc -nodtk" - On Solaris, don't put `/usr/ucb' early in your `PATH'. This + On Solaris, don't put '/usr/ucb' early in your 'PATH'. This directory contains several dysfunctional programs; working variants of -these programs are available in `/usr/bin'. So, if you need `/usr/ucb' -in your `PATH', put it _after_ `/usr/bin'. +these programs are available in '/usr/bin'. So, if you need '/usr/ucb' +in your 'PATH', put it _after_ '/usr/bin'. - On Haiku, software installed for all users goes in `/boot/common', -not `/usr/local'. It is recommended to use the following options: + On Haiku, software installed for all users goes in '/boot/common', +not '/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== - There may be some features `configure' cannot figure out + There may be some features 'configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints +_same_ architectures, 'configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: +'--build=TYPE' option. TYPE can either be a short name for the system +type, such as 'sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM @@ -270,101 +268,101 @@ where SYSTEM can have one of these forms: OS KERNEL-OS - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't + See the file 'config.sub' for the possible values of each field. If +'config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will +use the option '--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. +eventually be run) with '--host=TYPE'. Sharing Defaults ================ - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. + If you want to set default values for 'configure' scripts to share, +you can create a site shell script called 'config.site' that gives +default values for variables like 'CC', 'cache_file', and 'prefix'. +'configure' looks for 'PREFIX/share/config.site' if it exists, then +'PREFIX/etc/config.site' if it exists. Or, you can set the +'CONFIG_SITE' environment variable to the location of the site script. +A warning: not all 'configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run +environment passed to 'configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: +them in the 'configure' command line, using 'VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc -causes the specified `gcc' to be used as the C compiler (unless it is +causes the specified 'gcc' to be used as the C compiler (unless it is overridden in the site shell script). -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf limitation. Until the limitation is lifted, you can use -this workaround: +Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an +Autoconf limitation. Until the limitation is lifted, you can use this +workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash -`configure' Invocation +'configure' Invocation ====================== - `configure' recognizes the following options to control how it + 'configure' recognizes the following options to control how it operates. -`--help' -`-h' - Print a summary of all of the options to `configure', and exit. +'--help' +'-h' + Print a summary of all of the options to 'configure', and exit. -`--help=short' -`--help=recursive' +'--help=short' +'--help=recursive' Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. + 'configure', and exit. The 'short' variant lists options used only + in the top level, while the 'recursive' variant lists options also + present in any nested packages. -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' +'--version' +'-V' + Print the version of Autoconf used to generate the 'configure' script, and exit. -`--cache-file=FILE' +'--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to + traditionally 'config.cache'. FILE defaults to '/dev/null' to disable caching. -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. +'--config-cache' +'-C' + Alias for '--cache-file=config.cache'. -`--quiet' -`--silent' -`-q' +'--quiet' +'--silent' +'-q' Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error + suppress all normal output, redirect it to '/dev/null' (any error messages will still be shown). -`--srcdir=DIR' +'--srcdir=DIR' Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. + 'configure' can determine that directory automatically. -`--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. +'--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: for + more details, including other options available for fine-tuning the + installation locations. -`--no-create' -`-n' +'--no-create' +'-n' Run the configure checks, but stop before creating any output files. -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. +'configure' also accepts some other, not widely useful, options. Run +'configure --help' for more details. diff --git a/Makefile.in b/Makefile.in index 8ef3565..17655f7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15.1 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2017 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -114,7 +114,7 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = depcomp = -am__depfiles_maybe = +am__maybe_remake_depfiles = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ @@ -137,9 +137,9 @@ am__recursive_targets = \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - cscope distdir dist dist-all distcheck -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ - $(LISP)config.h.in + cscope distdir distdir-am dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. @@ -348,8 +348,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -482,7 +482,10 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -562,6 +565,10 @@ dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @@ -604,6 +611,8 @@ distcheck: dist eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) @@ -780,7 +789,7 @@ uninstall-am: am--refresh check check-am clean clean-cscope clean-generic \ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ - distcheck distclean distclean-generic distclean-hdr \ + dist-zstd distcheck distclean distclean-generic distclean-hdr \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ diff --git a/configure b/configure index 54fc3f7..c1be911 100755 --- a/configure +++ b/configure @@ -2405,7 +2405,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" -am__api_version='1.15' +am__api_version='1.16' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -2950,8 +2950,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The @@ -3002,7 +3002,7 @@ END Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -4239,8 +4239,8 @@ fi pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUSB" >&5 -$as_echo_n "checking for LIBUSB... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libusb-1.0" >&5 +$as_echo_n "checking for libusb-1.0... " >&6; } if test -n "$LIBUSB_CFLAGS"; then pkg_cv_LIBUSB_CFLAGS="$LIBUSB_CFLAGS" @@ -4280,7 +4280,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -4298,7 +4298,7 @@ fi WANT_USB=-1; WANT_HID=0 elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } WANT_USB=-1; WANT_HID=0 else @@ -5336,8 +5336,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUSB" >&5 -$as_echo_n "checking for LIBUSB... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libusb-1.0" >&5 +$as_echo_n "checking for libusb-1.0... " >&6; } if test -n "$LIBUSB_CFLAGS"; then pkg_cv_LIBUSB_CFLAGS="$LIBUSB_CFLAGS" @@ -5377,7 +5377,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -5395,7 +5395,7 @@ fi WANT_USB=-1; WANT_HID=0; LIBUSB_STATIC='' elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } WANT_USB=-1; WANT_HID=0; LIBUSB_STATIC='' else @@ -5409,8 +5409,8 @@ $as_echo "yes" >&6; } fi pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for UDEV" >&5 -$as_echo_n "checking for UDEV... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libudev" >&5 +$as_echo_n "checking for libudev... " >&6; } if test -n "$UDEV_CFLAGS"; then pkg_cv_UDEV_CFLAGS="$UDEV_CFLAGS" @@ -5450,7 +5450,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -5468,7 +5468,7 @@ fi WANT_USB=-1; WANT_HID=0; LIBUSB_STATIC='' elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } WANT_USB=-1; WANT_HID=0; LIBUSB_STATIC='' else @@ -7186,8 +7186,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUSB" >&5 -$as_echo_n "checking for LIBUSB... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libusb-1.0" >&5 +$as_echo_n "checking for libusb-1.0... " >&6; } if test -n "$LIBUSB_CFLAGS"; then pkg_cv_LIBUSB_CFLAGS="$LIBUSB_CFLAGS" @@ -7227,7 +7227,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -7245,7 +7245,7 @@ fi WANT_USB=-1; WANT_HID=0; LIBUSB_STATIC='' elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } WANT_USB=-1; WANT_HID=0; LIBUSB_STATIC='' else @@ -7316,8 +7316,8 @@ fi fi if test "x$WANT_USB" = "x1"; then : - LIBUSB_LIBS="-Llibusb-win32 -lusb-1.0 -lsetupapi" - LIBUSB_CFLAGS="-Ilibusb-win32/libusb-1.0" + LIBUSB_LIBS="-Llibusb-win32/MinGW64/static -lusb-1.0 -lsetupapi" + LIBUSB_CFLAGS="-Ilibusb-win32/include/libusb-1.0" fi if test "x$WANT_HID" = "x1"; then : diff --git a/configure.ac b/configure.ac index d4d98ef..7591686 100644 --- a/configure.ac +++ b/configure.ac @@ -151,8 +151,8 @@ case $host_os in HID_OBJ='hid/linux/hid.$(OBJEXT)' ]) AS_IF([test "x$WANT_USB" = "x1"], [ - LIBUSB_LIBS="-Llibusb-win32 -lusb-1.0 -lsetupapi" - LIBUSB_CFLAGS="-Ilibusb-win32/libusb-1.0" + LIBUSB_LIBS="-Llibusb-win32/MinGW64/static -lusb-1.0 -lsetupapi" + LIBUSB_CFLAGS="-Ilibusb-win32/include/libusb-1.0" ]) AS_IF([test "x$WANT_HID" = "x1"], [ HID_SRC="hid/windows/hid.c" diff --git a/src/Makefile.in b/src/Makefile.in index 51fd29b..665d5f6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15.1 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2017 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -137,7 +137,7 @@ am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = -am__depfiles_maybe = +am__maybe_remake_depfiles = AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent @@ -327,8 +327,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -621,7 +621,10 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ diff --git a/src/libusb-win32/MS32/dll/libusb-1.0.dll b/src/libusb-win32/MS32/dll/libusb-1.0.dll new file mode 100644 index 0000000..e348ff1 Binary files /dev/null and b/src/libusb-win32/MS32/dll/libusb-1.0.dll differ diff --git a/src/libusb-win32/MS32/dll/libusb-1.0.lib b/src/libusb-win32/MS32/dll/libusb-1.0.lib new file mode 100644 index 0000000..75f59f8 Binary files /dev/null and b/src/libusb-win32/MS32/dll/libusb-1.0.lib differ diff --git a/src/libusb-win32/MS32/dll/libusb-1.0.pdb b/src/libusb-win32/MS32/dll/libusb-1.0.pdb new file mode 100644 index 0000000..afec7b0 Binary files /dev/null and b/src/libusb-win32/MS32/dll/libusb-1.0.pdb differ diff --git a/src/libusb-win32/MS32/static/libusb-1.0.lib b/src/libusb-win32/MS32/static/libusb-1.0.lib new file mode 100644 index 0000000..0522a81 Binary files /dev/null and b/src/libusb-win32/MS32/static/libusb-1.0.lib differ diff --git a/src/libusb-win32/MS64/dll/libusb-1.0.dll b/src/libusb-win32/MS64/dll/libusb-1.0.dll new file mode 100644 index 0000000..b2092a8 Binary files /dev/null and b/src/libusb-win32/MS64/dll/libusb-1.0.dll differ diff --git a/src/libusb-win32/MS64/dll/libusb-1.0.lib b/src/libusb-win32/MS64/dll/libusb-1.0.lib new file mode 100644 index 0000000..10af16a Binary files /dev/null and b/src/libusb-win32/MS64/dll/libusb-1.0.lib differ diff --git a/src/libusb-win32/MS64/dll/libusb-1.0.pdb b/src/libusb-win32/MS64/dll/libusb-1.0.pdb new file mode 100644 index 0000000..9faa3eb Binary files /dev/null and b/src/libusb-win32/MS64/dll/libusb-1.0.pdb differ diff --git a/src/libusb-win32/MS64/static/libusb-1.0.lib b/src/libusb-win32/MS64/static/libusb-1.0.lib new file mode 100644 index 0000000..691edda Binary files /dev/null and b/src/libusb-win32/MS64/static/libusb-1.0.lib differ diff --git a/src/libusb-win32/MinGW32/dll/libusb-1.0.dll b/src/libusb-win32/MinGW32/dll/libusb-1.0.dll new file mode 100644 index 0000000..e6a0741 Binary files /dev/null and b/src/libusb-win32/MinGW32/dll/libusb-1.0.dll differ diff --git a/src/libusb-win32/MinGW32/dll/libusb-1.0.dll.a b/src/libusb-win32/MinGW32/dll/libusb-1.0.dll.a new file mode 100644 index 0000000..1e3e26d Binary files /dev/null and b/src/libusb-win32/MinGW32/dll/libusb-1.0.dll.a differ diff --git a/src/libusb-win32/MinGW32/static/libusb-1.0.a b/src/libusb-win32/MinGW32/static/libusb-1.0.a new file mode 100644 index 0000000..1fe83fe Binary files /dev/null and b/src/libusb-win32/MinGW32/static/libusb-1.0.a differ diff --git a/src/libusb-win32/MinGW64/dll/libusb-1.0.dll b/src/libusb-win32/MinGW64/dll/libusb-1.0.dll new file mode 100644 index 0000000..7d04b1f Binary files /dev/null and b/src/libusb-win32/MinGW64/dll/libusb-1.0.dll differ diff --git a/src/libusb-win32/MinGW64/dll/libusb-1.0.dll.a b/src/libusb-win32/MinGW64/dll/libusb-1.0.dll.a new file mode 100644 index 0000000..0512e61 Binary files /dev/null and b/src/libusb-win32/MinGW64/dll/libusb-1.0.dll.a differ diff --git a/src/libusb-win32/MinGW64/static/libusb-1.0.a b/src/libusb-win32/MinGW64/static/libusb-1.0.a new file mode 100644 index 0000000..52a494a Binary files /dev/null and b/src/libusb-win32/MinGW64/static/libusb-1.0.a differ diff --git a/src/libusb-win32/examples/bin32/fxload.exe b/src/libusb-win32/examples/bin32/fxload.exe new file mode 100644 index 0000000..e197c7e Binary files /dev/null and b/src/libusb-win32/examples/bin32/fxload.exe differ diff --git a/src/libusb-win32/examples/bin32/listdevs.exe b/src/libusb-win32/examples/bin32/listdevs.exe new file mode 100644 index 0000000..b3397fe Binary files /dev/null and b/src/libusb-win32/examples/bin32/listdevs.exe differ diff --git a/src/libusb-win32/examples/bin32/xusb.exe b/src/libusb-win32/examples/bin32/xusb.exe new file mode 100644 index 0000000..e2d6f79 Binary files /dev/null and b/src/libusb-win32/examples/bin32/xusb.exe differ diff --git a/src/libusb-win32/examples/bin64/fxload.exe b/src/libusb-win32/examples/bin64/fxload.exe new file mode 100644 index 0000000..d434d69 Binary files /dev/null and b/src/libusb-win32/examples/bin64/fxload.exe differ diff --git a/src/libusb-win32/examples/bin64/listdevs.exe b/src/libusb-win32/examples/bin64/listdevs.exe new file mode 100644 index 0000000..7c73581 Binary files /dev/null and b/src/libusb-win32/examples/bin64/listdevs.exe differ diff --git a/src/libusb-win32/examples/bin64/xusb.exe b/src/libusb-win32/examples/bin64/xusb.exe new file mode 100644 index 0000000..c07bf8b Binary files /dev/null and b/src/libusb-win32/examples/bin64/xusb.exe differ diff --git a/src/libusb-win32/examples/source/ezusb.c b/src/libusb-win32/examples/source/ezusb.c new file mode 100644 index 0000000..1a8dec1 --- /dev/null +++ b/src/libusb-win32/examples/source/ezusb.c @@ -0,0 +1,831 @@ +/* + * Copyright © 2001 Stephen Williams (steve@icarus.com) + * Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net) + * Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net) + * Copyright © 2012 Pete Batard (pete@akeo.ie) + * Copyright © 2013 Federico Manzan (f.manzan@gmail.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#include +#include +#include +#include +#include + +#include "libusb.h" +#include "ezusb.h" + +extern void logerror(const char *format, ...) + __attribute__ ((format(printf, 1, 2))); + +/* + * This file contains functions for uploading firmware into Cypress + * EZ-USB microcontrollers. These chips use control endpoint 0 and vendor + * specific commands to support writing into the on-chip SRAM. They also + * support writing into the CPUCS register, which is how we reset the + * processor after loading firmware (including the reset vector). + * + * These Cypress devices are 8-bit 8051 based microcontrollers with + * special support for USB I/O. They come in several packages, and + * some can be set up with external memory when device costs allow. + * Note that the design was originally by AnchorChips, so you may find + * references to that vendor (which was later merged into Cypress). + * The Cypress FX parts are largely compatible with the Anchorhip ones. + */ + +int verbose = 1; + +/* + * return true if [addr,addr+len] includes external RAM + * for Anchorchips EZ-USB or Cypress EZ-USB FX + */ +static bool fx_is_external(uint32_t addr, size_t len) +{ + /* with 8KB RAM, 0x0000-0x1b3f can be written + * we can't tell if it's a 4KB device here + */ + if (addr <= 0x1b3f) + return ((addr + len) > 0x1b40); + + /* there may be more RAM; unclear if we can write it. + * some bulk buffers may be unused, 0x1b3f-0x1f3f + * firmware can set ISODISAB for 2KB at 0x2000-0x27ff + */ + return true; +} + +/* + * return true if [addr,addr+len] includes external RAM + * for Cypress EZ-USB FX2 + */ +static bool fx2_is_external(uint32_t addr, size_t len) +{ + /* 1st 8KB for data/code, 0x0000-0x1fff */ + if (addr <= 0x1fff) + return ((addr + len) > 0x2000); + + /* and 512 for data, 0xe000-0xe1ff */ + else if (addr >= 0xe000 && addr <= 0xe1ff) + return ((addr + len) > 0xe200); + + /* otherwise, it's certainly external */ + else + return true; +} + +/* + * return true if [addr,addr+len] includes external RAM + * for Cypress EZ-USB FX2LP + */ +static bool fx2lp_is_external(uint32_t addr, size_t len) +{ + /* 1st 16KB for data/code, 0x0000-0x3fff */ + if (addr <= 0x3fff) + return ((addr + len) > 0x4000); + + /* and 512 for data, 0xe000-0xe1ff */ + else if (addr >= 0xe000 && addr <= 0xe1ff) + return ((addr + len) > 0xe200); + + /* otherwise, it's certainly external */ + else + return true; +} + + +/*****************************************************************************/ + +/* + * These are the requests (bRequest) that the bootstrap loader is expected + * to recognize. The codes are reserved by Cypress, and these values match + * what EZ-USB hardware, or "Vend_Ax" firmware (2nd stage loader) uses. + * Cypress' "a3load" is nice because it supports both FX and FX2, although + * it doesn't have the EEPROM support (subset of "Vend_Ax"). + */ +#define RW_INTERNAL 0xA0 /* hardware implements this one */ +#define RW_MEMORY 0xA3 + +/* + * Issues the specified vendor-specific write request. + */ +static int ezusb_write(libusb_device_handle *device, const char *label, + uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len) +{ + int status; + + if (verbose > 1) + logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len); + status = libusb_control_transfer(device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + opcode, addr & 0xFFFF, addr >> 16, + (unsigned char*)data, (uint16_t)len, 1000); + if (status != (signed)len) { + if (status < 0) + logerror("%s: %s\n", label, libusb_error_name(status)); + else + logerror("%s ==> %d\n", label, status); + } + return (status < 0) ? -EIO : 0; +} + +/* + * Issues the specified vendor-specific read request. + */ +static int ezusb_read(libusb_device_handle *device, const char *label, + uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len) +{ + int status; + + if (verbose > 1) + logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len); + status = libusb_control_transfer(device, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + opcode, addr & 0xFFFF, addr >> 16, + (unsigned char*)data, (uint16_t)len, 1000); + if (status != (signed)len) { + if (status < 0) + logerror("%s: %s\n", label, libusb_error_name(status)); + else + logerror("%s ==> %d\n", label, status); + } + return (status < 0) ? -EIO : 0; +} + +/* + * Modifies the CPUCS register to stop or reset the CPU. + * Returns false on error. + */ +static bool ezusb_cpucs(libusb_device_handle *device, uint32_t addr, bool doRun) +{ + int status; + uint8_t data = doRun ? 0x00 : 0x01; + + if (verbose) + logerror("%s\n", data ? "stop CPU" : "reset CPU"); + status = libusb_control_transfer(device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + RW_INTERNAL, addr & 0xFFFF, addr >> 16, + &data, 1, 1000); + if ((status != 1) && + /* We may get an I/O error from libusb as the device disappears */ + ((!doRun) || (status != LIBUSB_ERROR_IO))) + { + const char *mesg = "can't modify CPUCS"; + if (status < 0) + logerror("%s: %s\n", mesg, libusb_error_name(status)); + else + logerror("%s\n", mesg); + return false; + } else + return true; +} + +/* + * Send an FX3 jumpt to address command + * Returns false on error. + */ +static bool ezusb_fx3_jump(libusb_device_handle *device, uint32_t addr) +{ + int status; + + if (verbose) + logerror("transfer execution to Program Entry at 0x%08x\n", addr); + status = libusb_control_transfer(device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + RW_INTERNAL, addr & 0xFFFF, addr >> 16, + NULL, 0, 1000); + /* We may get an I/O error from libusb as the device disappears */ + if ((status != 0) && (status != LIBUSB_ERROR_IO)) + { + const char *mesg = "failed to send jump command"; + if (status < 0) + logerror("%s: %s\n", mesg, libusb_error_name(status)); + else + logerror("%s\n", mesg); + return false; + } else + return true; +} + +/*****************************************************************************/ + +/* + * Parse an Intel HEX image file and invoke the poke() function on the + * various segments to implement policies such as writing to RAM (with + * a one or two stage loader setup, depending on the firmware) or to + * EEPROM (two stages required). + * + * image - the hex image file + * context - for use by poke() + * is_external - if non-null, used to check which segments go into + * external memory (writable only by software loader) + * poke - called with each memory segment; errors indicated + * by returning negative values. + * + * Caller is responsible for halting CPU as needed, such as when + * overwriting a second stage loader. + */ +static int parse_ihex(FILE *image, void *context, + bool (*is_external)(uint32_t addr, size_t len), + int (*poke) (void *context, uint32_t addr, bool external, + const unsigned char *data, size_t len)) +{ + unsigned char data[1023]; + uint32_t data_addr = 0; + size_t data_len = 0; + int rc; + int first_line = 1; + bool external = false; + + /* Read the input file as an IHEX file, and report the memory segments + * as we go. Each line holds a max of 16 bytes, but uploading is + * faster (and EEPROM space smaller) if we merge those lines into larger + * chunks. Most hex files keep memory segments together, which makes + * such merging all but free. (But it may still be worth sorting the + * hex files to make up for undesirable behavior from tools.) + * + * Note that EEPROM segments max out at 1023 bytes; the upload protocol + * allows segments of up to 64 KBytes (more than a loader could handle). + */ + for (;;) { + char buf[512], *cp; + char tmp, type; + size_t len; + unsigned idx, off; + + cp = fgets(buf, sizeof(buf), image); + if (cp == NULL) { + logerror("EOF without EOF record!\n"); + break; + } + + /* EXTENSION: "# comment-till-end-of-line", for copyrights etc */ + if (buf[0] == '#') + continue; + + if (buf[0] != ':') { + logerror("not an ihex record: %s", buf); + return -2; + } + + /* ignore any newline */ + cp = strchr(buf, '\n'); + if (cp) + *cp = 0; + + if (verbose >= 3) + logerror("** LINE: %s\n", buf); + + /* Read the length field (up to 16 bytes) */ + tmp = buf[3]; + buf[3] = 0; + len = strtoul(buf+1, NULL, 16); + buf[3] = tmp; + + /* Read the target offset (address up to 64KB) */ + tmp = buf[7]; + buf[7] = 0; + off = (unsigned int)strtoul(buf+3, NULL, 16); + buf[7] = tmp; + + /* Initialize data_addr */ + if (first_line) { + data_addr = off; + first_line = 0; + } + + /* Read the record type */ + tmp = buf[9]; + buf[9] = 0; + type = (char)strtoul(buf+7, NULL, 16); + buf[9] = tmp; + + /* If this is an EOF record, then make it so. */ + if (type == 1) { + if (verbose >= 2) + logerror("EOF on hexfile\n"); + break; + } + + if (type != 0) { + logerror("unsupported record type: %u\n", type); + return -3; + } + + if ((len * 2) + 11 > strlen(buf)) { + logerror("record too short?\n"); + return -4; + } + + /* FIXME check for _physically_ contiguous not just virtually + * e.g. on FX2 0x1f00-0x2100 includes both on-chip and external + * memory so it's not really contiguous */ + + /* flush the saved data if it's not contiguous, + * or when we've buffered as much as we can. + */ + if (data_len != 0 + && (off != (data_addr + data_len) + /* || !merge */ + || (data_len + len) > sizeof(data))) { + if (is_external) + external = is_external(data_addr, data_len); + rc = poke(context, data_addr, external, data, data_len); + if (rc < 0) + return -1; + data_addr = off; + data_len = 0; + } + + /* append to saved data, flush later */ + for (idx = 0, cp = buf+9 ; idx < len ; idx += 1, cp += 2) { + tmp = cp[2]; + cp[2] = 0; + data[data_len + idx] = (uint8_t)strtoul(cp, NULL, 16); + cp[2] = tmp; + } + data_len += len; + } + + + /* flush any data remaining */ + if (data_len != 0) { + if (is_external) + external = is_external(data_addr, data_len); + rc = poke(context, data_addr, external, data, data_len); + if (rc < 0) + return -1; + } + return 0; +} + +/* + * Parse a binary image file and write it as is to the target. + * Applies to Cypress BIX images for RAM or Cypress IIC images + * for EEPROM. + * + * image - the BIX image file + * context - for use by poke() + * is_external - if non-null, used to check which segments go into + * external memory (writable only by software loader) + * poke - called with each memory segment; errors indicated + * by returning negative values. + * + * Caller is responsible for halting CPU as needed, such as when + * overwriting a second stage loader. + */ +static int parse_bin(FILE *image, void *context, + bool (*is_external)(uint32_t addr, size_t len), int (*poke)(void *context, + uint32_t addr, bool external, const unsigned char *data, size_t len)) +{ + unsigned char data[4096]; + uint32_t data_addr = 0; + size_t data_len = 0; + int rc; + bool external = false; + + for (;;) { + data_len = fread(data, 1, 4096, image); + if (data_len == 0) + break; + if (is_external) + external = is_external(data_addr, data_len); + rc = poke(context, data_addr, external, data, data_len); + if (rc < 0) + return -1; + data_addr += (uint32_t)data_len; + } + return feof(image)?0:-1; +} + +/* + * Parse a Cypress IIC image file and invoke the poke() function on the + * various segments for writing to RAM + * + * image - the IIC image file + * context - for use by poke() + * is_external - if non-null, used to check which segments go into + * external memory (writable only by software loader) + * poke - called with each memory segment; errors indicated + * by returning negative values. + * + * Caller is responsible for halting CPU as needed, such as when + * overwriting a second stage loader. + */ +static int parse_iic(FILE *image, void *context, + bool (*is_external)(uint32_t addr, size_t len), + int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len)) +{ + unsigned char data[4096]; + uint32_t data_addr = 0; + size_t data_len = 0, read_len; + uint8_t block_header[4]; + int rc; + bool external = false; + long file_size, initial_pos; + + initial_pos = ftell(image); + if (initial_pos < 0) + return -1; + + if (fseek(image, 0L, SEEK_END) != 0) + return -1; + file_size = ftell(image); + if (fseek(image, initial_pos, SEEK_SET) != 0) + return -1; + for (;;) { + /* Ignore the trailing reset IIC data (5 bytes) */ + if (ftell(image) >= (file_size - 5)) + break; + if (fread(&block_header, 1, sizeof(block_header), image) != 4) { + logerror("unable to read IIC block header\n"); + return -1; + } + data_len = (block_header[0] << 8) + block_header[1]; + data_addr = (block_header[2] << 8) + block_header[3]; + if (data_len > sizeof(data)) { + /* If this is ever reported as an error, switch to using malloc/realloc */ + logerror("IIC data block too small - please report this error to libusb.info\n"); + return -1; + } + read_len = fread(data, 1, data_len, image); + if (read_len != data_len) { + logerror("read error\n"); + return -1; + } + if (is_external) + external = is_external(data_addr, data_len); + rc = poke(context, data_addr, external, data, data_len); + if (rc < 0) + return -1; + } + return 0; +} + +/* the parse call will be selected according to the image type */ +static int (*parse[IMG_TYPE_MAX])(FILE *image, void *context, bool (*is_external)(uint32_t addr, size_t len), + int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len)) + = { parse_ihex, parse_iic, parse_bin }; + +/*****************************************************************************/ + +/* + * For writing to RAM using a first (hardware) or second (software) + * stage loader and 0xA0 or 0xA3 vendor requests + */ +typedef enum { + _undef = 0, + internal_only, /* hardware first-stage loader */ + skip_internal, /* first phase, second-stage loader */ + skip_external /* second phase, second-stage loader */ +} ram_mode; + +struct ram_poke_context { + libusb_device_handle *device; + ram_mode mode; + size_t total, count; +}; + +#define RETRY_LIMIT 5 + +static int ram_poke(void *context, uint32_t addr, bool external, + const unsigned char *data, size_t len) +{ + struct ram_poke_context *ctx = (struct ram_poke_context*)context; + int rc; + unsigned retry = 0; + + switch (ctx->mode) { + case internal_only: /* CPU should be stopped */ + if (external) { + logerror("can't write %u bytes external memory at 0x%08x\n", + (unsigned)len, addr); + return -EINVAL; + } + break; + case skip_internal: /* CPU must be running */ + if (!external) { + if (verbose >= 2) { + logerror("SKIP on-chip RAM, %u bytes at 0x%08x\n", + (unsigned)len, addr); + } + return 0; + } + break; + case skip_external: /* CPU should be stopped */ + if (external) { + if (verbose >= 2) { + logerror("SKIP external RAM, %u bytes at 0x%08x\n", + (unsigned)len, addr); + } + return 0; + } + break; + case _undef: + default: + logerror("bug\n"); + return -EDOM; + } + + ctx->total += len; + ctx->count++; + + /* Retry this till we get a real error. Control messages are not + * NAKed (just dropped) so time out means is a real problem. + */ + while ((rc = ezusb_write(ctx->device, + external ? "write external" : "write on-chip", + external ? RW_MEMORY : RW_INTERNAL, + addr, data, len)) < 0 + && retry < RETRY_LIMIT) { + if (rc != LIBUSB_ERROR_TIMEOUT) + break; + retry += 1; + } + return rc; +} + +/* + * Load a Cypress Image file into target RAM. + * See http://www.cypress.com/?docID=41351 (AN76405 PDF) for more info. + */ +static int fx3_load_ram(libusb_device_handle *device, const char *path) +{ + uint32_t dCheckSum, dExpectedCheckSum, dAddress, i, dLen, dLength; + uint32_t* dImageBuf; + unsigned char *bBuf, hBuf[4], blBuf[4], rBuf[4096]; + FILE *image; + int ret = 0; + + image = fopen(path, "rb"); + if (image == NULL) { + logerror("unable to open '%s' for input\n", path); + return -2; + } else if (verbose) + logerror("open firmware image %s for RAM upload\n", path); + + // Read header + if (fread(hBuf, sizeof(char), sizeof(hBuf), image) != sizeof(hBuf)) { + logerror("could not read image header"); + ret = -3; + goto exit; + } + + // check "CY" signature byte and format + if ((hBuf[0] != 'C') || (hBuf[1] != 'Y')) { + logerror("image doesn't have a CYpress signature\n"); + ret = -3; + goto exit; + } + + // Check bImageType + switch(hBuf[3]) { + case 0xB0: + if (verbose) + logerror("normal FW binary %s image with checksum\n", (hBuf[2]&0x01)?"data":"executable"); + break; + case 0xB1: + logerror("security binary image is not currently supported\n"); + ret = -3; + goto exit; + case 0xB2: + logerror("VID:PID image is not currently supported\n"); + ret = -3; + goto exit; + default: + logerror("invalid image type 0x%02X\n", hBuf[3]); + ret = -3; + goto exit; + } + + // Read the bootloader version + if (verbose) { + if ((ezusb_read(device, "read bootloader version", RW_INTERNAL, 0xFFFF0020, blBuf, 4) < 0)) { + logerror("Could not read bootloader version\n"); + ret = -8; + goto exit; + } + logerror("FX3 bootloader version: 0x%02X%02X%02X%02X\n", blBuf[3], blBuf[2], blBuf[1], blBuf[0]); + } + + dCheckSum = 0; + if (verbose) + logerror("writing image...\n"); + while (1) { + if ((fread(&dLength, sizeof(uint32_t), 1, image) != 1) || // read dLength + (fread(&dAddress, sizeof(uint32_t), 1, image) != 1)) { // read dAddress + logerror("could not read image"); + ret = -3; + goto exit; + } + if (dLength == 0) + break; // done + + // coverity[tainted_data] + dImageBuf = (uint32_t*)calloc(dLength, sizeof(uint32_t)); + if (dImageBuf == NULL) { + logerror("could not allocate buffer for image chunk\n"); + ret = -4; + goto exit; + } + + // read sections + if (fread(dImageBuf, sizeof(uint32_t), dLength, image) != dLength) { + logerror("could not read image"); + free(dImageBuf); + ret = -3; + goto exit; + } + for (i = 0; i < dLength; i++) + dCheckSum += dImageBuf[i]; + dLength <<= 2; // convert to Byte length + bBuf = (unsigned char*) dImageBuf; + + while (dLength > 0) { + dLen = 4096; // 4K max + if (dLen > dLength) + dLen = dLength; + if ((ezusb_write(device, "write firmware", RW_INTERNAL, dAddress, bBuf, dLen) < 0) || + (ezusb_read(device, "read firmware", RW_INTERNAL, dAddress, rBuf, dLen) < 0)) { + logerror("R/W error\n"); + free(dImageBuf); + ret = -5; + goto exit; + } + // Verify data: rBuf with bBuf + for (i = 0; i < dLen; i++) { + if (rBuf[i] != bBuf[i]) { + logerror("verify error"); + free(dImageBuf); + ret = -6; + goto exit; + } + } + + dLength -= dLen; + bBuf += dLen; + dAddress += dLen; + } + free(dImageBuf); + } + + // read pre-computed checksum data + if ((fread(&dExpectedCheckSum, sizeof(uint32_t), 1, image) != 1) || + (dCheckSum != dExpectedCheckSum)) { + logerror("checksum error\n"); + ret = -7; + goto exit; + } + + // transfer execution to Program Entry + if (!ezusb_fx3_jump(device, dAddress)) { + ret = -6; + } + +exit: + fclose(image); + return ret; +} + +/* + * Load a firmware file into target RAM. device is the open libusb + * device, and the path is the name of the source file. Open the file, + * parse the bytes, and write them in one or two phases. + * + * If stage == 0, this uses the first stage loader, built into EZ-USB + * hardware but limited to writing on-chip memory or CPUCS. Everything + * is written during one stage, unless there's an error such as the image + * holding data that needs to be written to external memory. + * + * Otherwise, things are written in two stages. First the external + * memory is written, expecting a second stage loader to have already + * been loaded. Then file is re-parsed and on-chip memory is written. + */ +int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, int img_type, int stage) +{ + FILE *image; + uint32_t cpucs_addr; + bool (*is_external)(uint32_t off, size_t len); + struct ram_poke_context ctx; + int status; + uint8_t iic_header[8] = { 0 }; + int ret = 0; + + if (fx_type == FX_TYPE_FX3) + return fx3_load_ram(device, path); + + image = fopen(path, "rb"); + if (image == NULL) { + logerror("%s: unable to open for input.\n", path); + return -2; + } else if (verbose > 1) + logerror("open firmware image %s for RAM upload\n", path); + + if (img_type == IMG_TYPE_IIC) { + if ( (fread(iic_header, 1, sizeof(iic_header), image) != sizeof(iic_header)) + || (((fx_type == FX_TYPE_FX2LP) || (fx_type == FX_TYPE_FX2)) && (iic_header[0] != 0xC2)) + || ((fx_type == FX_TYPE_AN21) && (iic_header[0] != 0xB2)) + || ((fx_type == FX_TYPE_FX1) && (iic_header[0] != 0xB6)) ) { + logerror("IIC image does not contain executable code - cannot load to RAM.\n"); + ret = -1; + goto exit; + } + } + + /* EZ-USB original/FX and FX2 devices differ, apart from the 8051 core */ + switch(fx_type) { + case FX_TYPE_FX2LP: + cpucs_addr = 0xe600; + is_external = fx2lp_is_external; + break; + case FX_TYPE_FX2: + cpucs_addr = 0xe600; + is_external = fx2_is_external; + break; + default: + cpucs_addr = 0x7f92; + is_external = fx_is_external; + break; + } + + /* use only first stage loader? */ + if (stage == 0) { + ctx.mode = internal_only; + + /* if required, halt the CPU while we overwrite its code/data */ + if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false)) + { + ret = -1; + goto exit; + } + + /* 2nd stage, first part? loader was already uploaded */ + } else { + ctx.mode = skip_internal; + + /* let CPU run; overwrite the 2nd stage loader later */ + if (verbose) + logerror("2nd stage: write external memory\n"); + } + + /* scan the image, first (maybe only) time */ + ctx.device = device; + ctx.total = ctx.count = 0; + status = parse[img_type](image, &ctx, is_external, ram_poke); + if (status < 0) { + logerror("unable to upload %s\n", path); + ret = status; + goto exit; + } + + /* second part of 2nd stage: rescan */ + // TODO: what should we do for non HEX images there? + if (stage) { + ctx.mode = skip_external; + + /* if needed, halt the CPU while we overwrite the 1st stage loader */ + if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false)) + { + ret = -1; + goto exit; + } + + /* at least write the interrupt vectors (at 0x0000) for reset! */ + rewind(image); + if (verbose) + logerror("2nd stage: write on-chip memory\n"); + status = parse_ihex(image, &ctx, is_external, ram_poke); + if (status < 0) { + logerror("unable to completely upload %s\n", path); + ret = status; + goto exit; + } + } + + if (verbose && (ctx.count != 0)) { + logerror("... WROTE: %d bytes, %d segments, avg %d\n", + (int)ctx.total, (int)ctx.count, (int)(ctx.total/ctx.count)); + } + + /* if required, reset the CPU so it runs what we just uploaded */ + if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, true)) + ret = -1; + +exit: + fclose(image); + return ret; +} diff --git a/src/libusb-win32/examples/source/ezusb.h b/src/libusb-win32/examples/source/ezusb.h new file mode 100644 index 0000000..129bc9a --- /dev/null +++ b/src/libusb-win32/examples/source/ezusb.h @@ -0,0 +1,120 @@ +#ifndef ezusb_H +#define ezusb_H +/* + * Copyright © 2001 Stephen Williams (steve@icarus.com) + * Copyright © 2002 David Brownell (dbrownell@users.sourceforge.net) + * Copyright © 2013 Federico Manzan (f.manzan@gmail.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(_MSC_VER) +#include +#else +#define __attribute__(x) +#if !defined(bool) +#define bool int +#endif +#if !defined(true) +#define true (1 == 1) +#endif +#if !defined(false) +#define false (!true) +#endif +#if defined(_PREFAST_) +#pragma warning(disable:28193) +#endif +#endif + +#define FX_TYPE_UNDEFINED -1 +#define FX_TYPE_AN21 0 /* Original AnchorChips parts */ +#define FX_TYPE_FX1 1 /* Updated Cypress versions */ +#define FX_TYPE_FX2 2 /* USB 2.0 versions */ +#define FX_TYPE_FX2LP 3 /* Updated FX2 */ +#define FX_TYPE_FX3 4 /* USB 3.0 versions */ +#define FX_TYPE_MAX 5 +#define FX_TYPE_NAMES { "an21", "fx", "fx2", "fx2lp", "fx3" } + +#define IMG_TYPE_UNDEFINED -1 +#define IMG_TYPE_HEX 0 /* Intel HEX */ +#define IMG_TYPE_IIC 1 /* Cypress 8051 IIC */ +#define IMG_TYPE_BIX 2 /* Cypress 8051 BIX */ +#define IMG_TYPE_IMG 3 /* Cypress IMG format */ +#define IMG_TYPE_MAX 4 +#define IMG_TYPE_NAMES { "Intel HEX", "Cypress 8051 IIC", "Cypress 8051 BIX", "Cypress IMG format" } + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Automatically identified devices (VID, PID, type, designation). + * TODO: Could use some validation. Also where's the FX2? + */ +typedef struct { + uint16_t vid; + uint16_t pid; + int type; + const char* designation; +} fx_known_device; + +#define FX_KNOWN_DEVICES { \ + { 0x0547, 0x2122, FX_TYPE_AN21, "Cypress EZ-USB (2122S)" },\ + { 0x0547, 0x2125, FX_TYPE_AN21, "Cypress EZ-USB (2121S/2125S)" },\ + { 0x0547, 0x2126, FX_TYPE_AN21, "Cypress EZ-USB (2126S)" },\ + { 0x0547, 0x2131, FX_TYPE_AN21, "Cypress EZ-USB (2131Q/2131S/2135S)" },\ + { 0x0547, 0x2136, FX_TYPE_AN21, "Cypress EZ-USB (2136S)" },\ + { 0x0547, 0x2225, FX_TYPE_AN21, "Cypress EZ-USB (2225)" },\ + { 0x0547, 0x2226, FX_TYPE_AN21, "Cypress EZ-USB (2226)" },\ + { 0x0547, 0x2235, FX_TYPE_AN21, "Cypress EZ-USB (2235)" },\ + { 0x0547, 0x2236, FX_TYPE_AN21, "Cypress EZ-USB (2236)" },\ + { 0x04b4, 0x6473, FX_TYPE_FX1, "Cypress EZ-USB FX1" },\ + { 0x04b4, 0x8613, FX_TYPE_FX2LP, "Cypress EZ-USB FX2LP (68013A/68014A/68015A/68016A)" }, \ + { 0x04b4, 0x00f3, FX_TYPE_FX3, "Cypress FX3" },\ +} + +/* + * This function uploads the firmware from the given file into RAM. + * Stage == 0 means this is a single stage load (or the first of + * two stages). Otherwise it's the second of two stages; the + * caller having preloaded the second stage loader. + * + * The target processor is reset at the end of this upload. + */ +extern int ezusb_load_ram(libusb_device_handle *device, + const char *path, int fx_type, int img_type, int stage); + +/* + * This function uploads the firmware from the given file into EEPROM. + * This uses the right CPUCS address to terminate the EEPROM load with + * a reset command where FX parts behave differently than FX2 ones. + * The configuration byte is as provided here (zero for an21xx parts) + * and the EEPROM type is set so that the microcontroller will boot + * from it. + * + * The caller must have preloaded a second stage loader that knows + * how to respond to the EEPROM write request. + */ +extern int ezusb_load_eeprom(libusb_device_handle *device, + const char *path, int fx_type, int img_type, int config); + +/* Verbosity level (default 1). Can be increased or decreased with options v/q */ +extern int verbose; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/libusb-win32/examples/source/fxload.c b/src/libusb-win32/examples/source/fxload.c new file mode 100644 index 0000000..1cea9c3 --- /dev/null +++ b/src/libusb-win32/examples/source/fxload.c @@ -0,0 +1,309 @@ +/* + * Copyright © 2001 Stephen Williams (steve@icarus.com) + * Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net) + * Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net) + * Copyright © 2012 Pete Batard (pete@akeo.ie) + * Copyright © 2013 Federico Manzan (f.manzan@gmail.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "libusb.h" +#include "ezusb.h" + +#if !defined(_WIN32) || defined(__CYGWIN__ ) +#include +static bool dosyslog = false; +#include +#define _stricmp strcasecmp +#endif + +#ifndef FXLOAD_VERSION +#define FXLOAD_VERSION (__DATE__ " (libusb)") +#endif + +#ifndef ARRAYSIZE +#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif + +void logerror(const char *format, ...) + __attribute__ ((format (__printf__, 1, 2))); + +void logerror(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + +#if !defined(_WIN32) || defined(__CYGWIN__ ) + if (dosyslog) + vsyslog(LOG_ERR, format, ap); + else +#endif + vfprintf(stderr, format, ap); + va_end(ap); +} + +static int print_usage(int error_code) { + fprintf(stderr, "\nUsage: fxload [-v] [-V] [-t type] [-d vid:pid] [-p bus,addr] [-s loader] -i firmware\n"); + fprintf(stderr, " -i -- Firmware to upload\n"); + fprintf(stderr, " -s -- Second stage loader\n"); + fprintf(stderr, " -t -- Target type: an21, fx, fx2, fx2lp, fx3\n"); + fprintf(stderr, " -d -- Target device, as an USB VID:PID\n"); + fprintf(stderr, " -p -- Target device, as a libusb bus number and device address path\n"); + fprintf(stderr, " -v -- Increase verbosity\n"); + fprintf(stderr, " -q -- Decrease verbosity (silent mode)\n"); + fprintf(stderr, " -V -- Print program version\n"); + return error_code; +} + +#define FIRMWARE 0 +#define LOADER 1 +int main(int argc, char*argv[]) +{ + fx_known_device known_device[] = FX_KNOWN_DEVICES; + const char *path[] = { NULL, NULL }; + const char *device_id = NULL; + const char *device_path = getenv("DEVICE"); + const char *type = NULL; + const char *fx_name[FX_TYPE_MAX] = FX_TYPE_NAMES; + const char *ext, *img_name[] = IMG_TYPE_NAMES; + int fx_type = FX_TYPE_UNDEFINED, img_type[ARRAYSIZE(path)]; + int opt, status; + unsigned int i, j; + unsigned vid = 0, pid = 0; + unsigned busnum = 0, devaddr = 0, _busnum, _devaddr; + libusb_device *dev, **devs; + libusb_device_handle *device = NULL; + struct libusb_device_descriptor desc; + + while ((opt = getopt(argc, argv, "qvV?hd:p:i:I:s:S:t:")) != EOF) + switch (opt) { + + case 'd': + device_id = optarg; + if (sscanf(device_id, "%x:%x" , &vid, &pid) != 2 ) { + fputs ("please specify VID & PID as \"vid:pid\" in hexadecimal format\n", stderr); + return -1; + } + break; + + case 'p': + device_path = optarg; + if (sscanf(device_path, "%u,%u", &busnum, &devaddr) != 2 ) { + fputs ("please specify bus number & device number as \"bus,dev\" in decimal format\n", stderr); + return -1; + } + break; + + case 'i': + case 'I': + path[FIRMWARE] = optarg; + break; + + case 's': + case 'S': + path[LOADER] = optarg; + break; + + case 'V': + puts(FXLOAD_VERSION); + return 0; + + case 't': + type = optarg; + break; + + case 'v': + verbose++; + break; + + case 'q': + verbose--; + break; + + case '?': + case 'h': + default: + return print_usage(-1); + + } + + if (path[FIRMWARE] == NULL) { + logerror("no firmware specified!\n"); + return print_usage(-1); + } + if ((device_id != NULL) && (device_path != NULL)) { + logerror("only one of -d or -p can be specified\n"); + return print_usage(-1); + } + + /* determine the target type */ + if (type != NULL) { + for (i=0; i= FX_TYPE_MAX) { + logerror("illegal microcontroller type: %s\n", type); + return print_usage(-1); + } + } + + /* open the device using libusb */ + status = libusb_init(NULL); + if (status < 0) { + logerror("libusb_init() failed: %s\n", libusb_error_name(status)); + return -1; + } + libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, verbose); + + /* try to pick up missing parameters from known devices */ + if ((type == NULL) || (device_id == NULL) || (device_path != NULL)) { + if (libusb_get_device_list(NULL, &devs) < 0) { + logerror("libusb_get_device_list() failed: %s\n", libusb_error_name(status)); + goto err; + } + for (i=0; (dev=devs[i]) != NULL; i++) { + _busnum = libusb_get_bus_number(dev); + _devaddr = libusb_get_device_address(dev); + if ((type != NULL) && (device_path != NULL)) { + // if both a type and bus,addr were specified, we just need to find our match + if ((libusb_get_bus_number(dev) == busnum) && (libusb_get_device_address(dev) == devaddr)) + break; + } else { + status = libusb_get_device_descriptor(dev, &desc); + if (status >= 0) { + if (verbose >= 3) { + logerror("examining %04x:%04x (%d,%d)\n", + desc.idVendor, desc.idProduct, _busnum, _devaddr); + } + for (j=0; j 1) + logerror("single stage: load on-chip memory\n"); + status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 0); + } else { + /* two-stage, put loader into internal memory */ + if (verbose > 1) + logerror("1st stage: load 2nd stage loader\n"); + status = ezusb_load_ram(device, path[LOADER], fx_type, img_type[LOADER], 0); + if (status == 0) { + /* two-stage, put firmware into internal memory */ + if (verbose > 1) + logerror("2nd state: load on-chip memory\n"); + status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 1); + } + } + + libusb_release_interface(device, 0); + libusb_close(device); + libusb_exit(NULL); + return status; +err: + libusb_exit(NULL); + return -1; +} diff --git a/src/libusb-win32/examples/source/listdevs.c b/src/libusb-win32/examples/source/listdevs.c new file mode 100644 index 0000000..fc65bc8 --- /dev/null +++ b/src/libusb-win32/examples/source/listdevs.c @@ -0,0 +1,73 @@ +/* + * libusb example program to list devices on the bus + * Copyright © 2007 Daniel Drake + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libusb.h" + +static void print_devs(libusb_device **devs) +{ + libusb_device *dev; + int i = 0, j = 0; + uint8_t path[8]; + + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor desc; + int r = libusb_get_device_descriptor(dev, &desc); + if (r < 0) { + fprintf(stderr, "failed to get device descriptor"); + return; + } + + printf("%04x:%04x (bus %d, device %d)", + desc.idVendor, desc.idProduct, + libusb_get_bus_number(dev), libusb_get_device_address(dev)); + + r = libusb_get_port_numbers(dev, path, sizeof(path)); + if (r > 0) { + printf(" path: %d", path[0]); + for (j = 1; j < r; j++) + printf(".%d", path[j]); + } + printf("\n"); + } +} + +int main(void) +{ + libusb_device **devs; + int r; + ssize_t cnt; + + r = libusb_init(NULL); + if (r < 0) + return r; + + cnt = libusb_get_device_list(NULL, &devs); + if (cnt < 0){ + libusb_exit(NULL); + return (int) cnt; + } + + print_devs(devs); + libusb_free_device_list(devs, 1); + + libusb_exit(NULL); + return 0; +} diff --git a/src/libusb-win32/examples/source/stdint.h b/src/libusb-win32/examples/source/stdint.h new file mode 100644 index 0000000..00988d9 --- /dev/null +++ b/src/libusb-win32/examples/source/stdint.h @@ -0,0 +1,256 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file was originally part of the w64 mingw-runtime package. + */ + +/* ISO C9x 7.18 Integer types + * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * Contributor: Danny Smith + * Modified for libusb/MSVC: Pete Batard + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2010-04-02 + */ + +#ifndef _MSC_VER +#error This header should only be used with Microsoft compilers +#endif + +#ifndef _STDINT_H +#define _STDINT_H + +#ifndef _INTPTR_T_DEFINED +#define _INTPTR_T_DEFINED +#ifndef __intptr_t_defined +#define __intptr_t_defined +#undef intptr_t +#ifdef _WIN64 + typedef __int64 intptr_t; +#else + typedef int intptr_t; +#endif /* _WIN64 */ +#endif /* __intptr_t_defined */ +#endif /* _INTPTR_T_DEFINED */ + +#ifndef _UINTPTR_T_DEFINED +#define _UINTPTR_T_DEFINED +#ifndef __uintptr_t_defined +#define __uintptr_t_defined +#undef uintptr_t +#ifdef _WIN64 + typedef unsigned __int64 uintptr_t; +#else + typedef unsigned int uintptr_t; +#endif /* _WIN64 */ +#endif /* __uintptr_t_defined */ +#endif /* _UINTPTR_T_DEFINED */ + +#ifndef _PTRDIFF_T_DEFINED +#define _PTRDIFF_T_DEFINED +#ifndef _PTRDIFF_T_ +#define _PTRDIFF_T_ +#undef ptrdiff_t +#ifdef _WIN64 + typedef __int64 ptrdiff_t; +#else + typedef int ptrdiff_t; +#endif /* _WIN64 */ +#endif /* _PTRDIFF_T_ */ +#endif /* _PTRDIFF_T_DEFINED */ + +#ifndef _WCHAR_T_DEFINED +#define _WCHAR_T_DEFINED +#ifndef __cplusplus + typedef unsigned short wchar_t; +#endif /* C++ */ +#endif /* _WCHAR_T_DEFINED */ + +#ifndef _WCTYPE_T_DEFINED +#define _WCTYPE_T_DEFINED +#ifndef _WINT_T +#define _WINT_T + typedef unsigned short wint_t; + typedef unsigned short wctype_t; +#endif /* _WINT_T */ +#endif /* _WCTYPE_T_DEFINED */ + +/* 7.18.1.1 Exact-width integer types */ +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef signed char int_least8_t; +typedef unsigned char uint_least8_t; +typedef short int_least16_t; +typedef unsigned short uint_least16_t; +typedef int int_least32_t; +typedef unsigned uint_least32_t; +typedef __int64 int_least64_t; +typedef unsigned __int64 uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types + * Not actually guaranteed to be fastest for all purposes + * Here we use the exact-width types for 8 and 16-bit ints. + */ +typedef __int8 int_fast8_t; +typedef unsigned __int8 uint_fast8_t; +typedef __int16 int_fast16_t; +typedef unsigned __int16 uint_fast16_t; +typedef __int32 int_fast32_t; +typedef unsigned __int32 uint_fast32_t; +typedef __int64 int_fast64_t; +typedef unsigned __int64 uint_fast64_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64 intmax_t; +typedef unsigned __int64 uintmax_t; + +/* 7.18.2 Limits of specified-width integer types */ + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN (-128) +#define INT16_MIN (-32768) +#define INT32_MIN (-2147483647 - 1) +#define INT64_MIN (-9223372036854775807LL - 1) + +#define INT8_MAX 127 +#define INT16_MAX 32767 +#define INT32_MAX 2147483647 +#define INT64_MAX 9223372036854775807LL + +#define UINT8_MAX 255 +#define UINT16_MAX 65535 +#define UINT32_MAX 0xffffffffU /* 4294967295U */ +#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding + object pointers */ +#ifdef _WIN64 +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#else +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* 7.18.3 Limits of other integer types */ +#ifdef _WIN64 +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX +#else +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX +#endif + +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +#ifndef SIZE_MAX +#ifdef _WIN64 +#define SIZE_MAX UINT64_MAX +#else +#define SIZE_MAX UINT32_MAX +#endif +#endif + +#ifndef WCHAR_MIN /* also in wchar.h */ +#define WCHAR_MIN 0U +#define WCHAR_MAX 0xffffU +#endif + +/* + * wint_t is unsigned short for compatibility with MS runtime + */ +#define WINT_MIN 0U +#define WINT_MAX 0xffffU + + +/* 7.18.4 Macros for integer constants */ + +/* 7.18.4.1 Macros for minimum-width integer constants + + Accoding to Douglas Gwyn : + "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC + 9899:1999 as initially published, the expansion was required + to be an integer constant of precisely matching type, which + is impossible to accomplish for the shorter types on most + platforms, because C99 provides no standard way to designate + an integer constant with width less than that of type int. + TC1 changed this to require just an integer constant + *expression* with *promoted* type." + + The trick used here is from Clive D W Feather. +*/ + +#define INT8_C(val) (INT_LEAST8_MAX-INT_LEAST8_MAX+(val)) +#define INT16_C(val) (INT_LEAST16_MAX-INT_LEAST16_MAX+(val)) +#define INT32_C(val) (INT_LEAST32_MAX-INT_LEAST32_MAX+(val)) +/* The 'trick' doesn't work in C89 for long long because, without + suffix, (val) will be evaluated as int, not intmax_t */ +#define INT64_C(val) val##i64 + +#define UINT8_C(val) (val) +#define UINT16_C(val) (val) +#define UINT32_C(val) (val##i32) +#define UINT64_C(val) val##ui64 + +/* 7.18.4.2 Macros for greatest-width integer constants */ +#define INTMAX_C(val) val##i64 +#define UINTMAX_C(val) val##ui64 + +#endif diff --git a/src/libusb-win32/examples/source/xusb.c b/src/libusb-win32/examples/source/xusb.c new file mode 100644 index 0000000..e20375f --- /dev/null +++ b/src/libusb-win32/examples/source/xusb.c @@ -0,0 +1,1135 @@ +/* + * xusb: Generic USB test program + * Copyright © 2009-2012 Pete Batard + * Contributions to Mass Storage by Alan Stern. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; 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 "libusb.h" + +#if defined(_WIN32) +#define msleep(msecs) Sleep(msecs) +#else +#include +#define msleep(msecs) nanosleep(&(struct timespec){msecs / 1000, (msecs * 1000000) % 1000000000UL}, NULL); +#endif + +#if defined(_MSC_VER) +#define snprintf _snprintf +#define putenv _putenv +#endif + +#if !defined(bool) +#define bool int +#endif +#if !defined(true) +#define true (1 == 1) +#endif +#if !defined(false) +#define false (!true) +#endif + +// Future versions of libusb will use usb_interface instead of interface +// in libusb_config_descriptor => catter for that +#define usb_interface interface + +// Global variables +static bool binary_dump = false; +static bool extra_info = false; +static bool force_device_request = false; // For WCID descriptor queries +static const char* binary_name = NULL; + +static void perr(char const *format, ...) +{ + va_list args; + + va_start (args, format); + vfprintf(stderr, format, args); + va_end(args); +} + +#define ERR_EXIT(errcode) do { perr(" %s\n", libusb_strerror((enum libusb_error)errcode)); return -1; } while (0) +#define CALL_CHECK(fcall) do { int _r=fcall; if (_r < 0) ERR_EXIT(_r); } while (0) +#define CALL_CHECK_CLOSE(fcall, hdl) do { int _r=fcall; if (_r < 0) { libusb_close(hdl); ERR_EXIT(_r); } } while (0) +#define B(x) (((x)!=0)?1:0) +#define be_to_int32(buf) (((buf)[0]<<24)|((buf)[1]<<16)|((buf)[2]<<8)|(buf)[3]) + +#define RETRY_MAX 5 +#define REQUEST_SENSE_LENGTH 0x12 +#define INQUIRY_LENGTH 0x24 +#define READ_CAPACITY_LENGTH 0x08 + +// HID Class-Specific Requests values. See section 7.2 of the HID specifications +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#define HID_REPORT_TYPE_INPUT 0x01 +#define HID_REPORT_TYPE_OUTPUT 0x02 +#define HID_REPORT_TYPE_FEATURE 0x03 + +// Mass Storage Requests values. See section 3 of the Bulk-Only Mass Storage Class specifications +#define BOMS_RESET 0xFF +#define BOMS_GET_MAX_LUN 0xFE + +// Microsoft OS Descriptor +#define MS_OS_DESC_STRING_INDEX 0xEE +#define MS_OS_DESC_STRING_LENGTH 0x12 +#define MS_OS_DESC_VENDOR_CODE_OFFSET 0x10 +static const uint8_t ms_os_desc_string[] = { + MS_OS_DESC_STRING_LENGTH, + LIBUSB_DT_STRING, + 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0, +}; + +// Section 5.1: Command Block Wrapper (CBW) +struct command_block_wrapper { + uint8_t dCBWSignature[4]; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}; + +// Section 5.2: Command Status Wrapper (CSW) +struct command_status_wrapper { + uint8_t dCSWSignature[4]; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}; + +static const uint8_t cdb_length[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06, // 0 + 06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06, // 1 + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 2 + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 3 + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 4 + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 5 + 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // 6 + 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // 7 + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, // 8 + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, // 9 + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, // A + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, // B + 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // C + 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // D + 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // E + 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // F +}; + +static enum test_type { + USE_GENERIC, + USE_PS3, + USE_XBOX, + USE_SCSI, + USE_HID, +} test_mode; +static uint16_t VID, PID; + +static void display_buffer_hex(unsigned char *buffer, unsigned size) +{ + unsigned i, j, k; + + for (i=0; i 126)) { + printf("."); + } else { + printf("%c", buffer[i+j]); + } + } + } + } + printf("\n" ); +} + +static char* uuid_to_string(const uint8_t* uuid) +{ + static char uuid_string[40]; + if (uuid == NULL) return NULL; + snprintf(uuid_string, sizeof(uuid_string), + "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], + uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); + return uuid_string; +} + +// The PS3 Controller is really a HID device that got its HID Report Descriptors +// removed by Sony +static int display_ps3_status(libusb_device_handle *handle) +{ + uint8_t input_report[49]; + uint8_t master_bt_address[8]; + uint8_t device_bt_address[18]; + + // Get the controller's bluetooth address of its master device + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_GET_REPORT, 0x03f5, 0, master_bt_address, sizeof(master_bt_address), 100)); + printf("\nMaster's bluetooth address: %02X:%02X:%02X:%02X:%02X:%02X\n", master_bt_address[2], master_bt_address[3], + master_bt_address[4], master_bt_address[5], master_bt_address[6], master_bt_address[7]); + + // Get the controller's bluetooth address + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_GET_REPORT, 0x03f2, 0, device_bt_address, sizeof(device_bt_address), 100)); + printf("\nMaster's bluetooth address: %02X:%02X:%02X:%02X:%02X:%02X\n", device_bt_address[4], device_bt_address[5], + device_bt_address[6], device_bt_address[7], device_bt_address[8], device_bt_address[9]); + + // Get the status of the controller's buttons via its HID report + printf("\nReading PS3 Input Report...\n"); + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x01, 0, input_report, sizeof(input_report), 1000)); + switch(input_report[2]){ /** Direction pad plus start, select, and joystick buttons */ + case 0x01: + printf("\tSELECT pressed\n"); + break; + case 0x02: + printf("\tLEFT 3 pressed\n"); + break; + case 0x04: + printf("\tRIGHT 3 pressed\n"); + break; + case 0x08: + printf("\tSTART presed\n"); + break; + case 0x10: + printf("\tUP pressed\n"); + break; + case 0x20: + printf("\tRIGHT pressed\n"); + break; + case 0x40: + printf("\tDOWN pressed\n"); + break; + case 0x80: + printf("\tLEFT pressed\n"); + break; + } + switch(input_report[3]){ /** Shapes plus top right and left buttons */ + case 0x01: + printf("\tLEFT 2 pressed\n"); + break; + case 0x02: + printf("\tRIGHT 2 pressed\n"); + break; + case 0x04: + printf("\tLEFT 1 pressed\n"); + break; + case 0x08: + printf("\tRIGHT 1 presed\n"); + break; + case 0x10: + printf("\tTRIANGLE pressed\n"); + break; + case 0x20: + printf("\tCIRCLE pressed\n"); + break; + case 0x40: + printf("\tCROSS pressed\n"); + break; + case 0x80: + printf("\tSQUARE pressed\n"); + break; + } + printf("\tPS button: %d\n", input_report[4]); + printf("\tLeft Analog (X,Y): (%d,%d)\n", input_report[6], input_report[7]); + printf("\tRight Analog (X,Y): (%d,%d)\n", input_report[8], input_report[9]); + printf("\tL2 Value: %d\tR2 Value: %d\n", input_report[18], input_report[19]); + printf("\tL1 Value: %d\tR1 Value: %d\n", input_report[20], input_report[21]); + printf("\tRoll (x axis): %d Yaw (y axis): %d Pitch (z axis) %d\n", + //(((input_report[42] + 128) % 256) - 128), + (int8_t)(input_report[42]), + (int8_t)(input_report[44]), + (int8_t)(input_report[46])); + printf("\tAcceleration: %d\n\n", (int8_t)(input_report[48])); + return 0; +} +// The XBOX Controller is really a HID device that got its HID Report Descriptors +// removed by Microsoft. +// Input/Output reports described at http://euc.jp/periphs/xbox-controller.ja.html +static int display_xbox_status(libusb_device_handle *handle) +{ + uint8_t input_report[20]; + printf("\nReading XBox Input Report...\n"); + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, input_report, 20, 1000)); + printf(" D-pad: %02X\n", input_report[2]&0x0F); + printf(" Start:%d, Back:%d, Left Stick Press:%d, Right Stick Press:%d\n", B(input_report[2]&0x10), B(input_report[2]&0x20), + B(input_report[2]&0x40), B(input_report[2]&0x80)); + // A, B, X, Y, Black, White are pressure sensitive + printf(" A:%d, B:%d, X:%d, Y:%d, White:%d, Black:%d\n", input_report[4], input_report[5], + input_report[6], input_report[7], input_report[9], input_report[8]); + printf(" Left Trigger: %d, Right Trigger: %d\n", input_report[10], input_report[11]); + printf(" Left Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[13]<<8)|input_report[12]), + (int16_t)((input_report[15]<<8)|input_report[14])); + printf(" Right Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[17]<<8)|input_report[16]), + (int16_t)((input_report[19]<<8)|input_report[18])); + return 0; +} + +static int set_xbox_actuators(libusb_device_handle *handle, uint8_t left, uint8_t right) +{ + uint8_t output_report[6]; + + printf("\nWriting XBox Controller Output Report...\n"); + + memset(output_report, 0, sizeof(output_report)); + output_report[1] = sizeof(output_report); + output_report[3] = left; + output_report[5] = right; + + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_SET_REPORT, (HID_REPORT_TYPE_OUTPUT<<8)|0x00, 0, output_report, 06, 1000)); + return 0; +} + +static int send_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint, uint8_t lun, + uint8_t *cdb, uint8_t direction, int data_length, uint32_t *ret_tag) +{ + static uint32_t tag = 1; + uint8_t cdb_len; + int i, r, size; + struct command_block_wrapper cbw; + + if (cdb == NULL) { + return -1; + } + + if (endpoint & LIBUSB_ENDPOINT_IN) { + perr("send_mass_storage_command: cannot send command on IN endpoint\n"); + return -1; + } + + cdb_len = cdb_length[cdb[0]]; + if ((cdb_len == 0) || (cdb_len > sizeof(cbw.CBWCB))) { + perr("send_mass_storage_command: don't know how to handle this command (%02X, length %d)\n", + cdb[0], cdb_len); + return -1; + } + + memset(&cbw, 0, sizeof(cbw)); + cbw.dCBWSignature[0] = 'U'; + cbw.dCBWSignature[1] = 'S'; + cbw.dCBWSignature[2] = 'B'; + cbw.dCBWSignature[3] = 'C'; + *ret_tag = tag; + cbw.dCBWTag = tag++; + cbw.dCBWDataTransferLength = data_length; + cbw.bmCBWFlags = direction; + cbw.bCBWLUN = lun; + // Subclass is 1 or 6 => cdb_len + cbw.bCBWCBLength = cdb_len; + memcpy(cbw.CBWCB, cdb, cdb_len); + + i = 0; + do { + // The transfer length must always be exactly 31 bytes. + r = libusb_bulk_transfer(handle, endpoint, (unsigned char*)&cbw, 31, &size, 1000); + if (r == LIBUSB_ERROR_PIPE) { + libusb_clear_halt(handle, endpoint); + } + i++; + } while ((r == LIBUSB_ERROR_PIPE) && (i HID_REPORT_TYPE_FEATURE)) { + return 0; + } else { + return (record_size[type - HID_REPORT_TYPE_INPUT]+7)/8; + } +} + +static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in) +{ + int r, size, descriptor_size; + uint8_t hid_report_descriptor[256]; + uint8_t *report_buffer; + FILE *fd; + + printf("\nReading HID Report Descriptors:\n"); + descriptor_size = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_STANDARD|LIBUSB_RECIPIENT_INTERFACE, + LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_REPORT<<8, 0, hid_report_descriptor, sizeof(hid_report_descriptor), 1000); + if (descriptor_size < 0) { + printf(" Failed\n"); + return -1; + } + display_buffer_hex(hid_report_descriptor, descriptor_size); + if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) { + if (fwrite(hid_report_descriptor, 1, descriptor_size, fd) != (size_t)descriptor_size) { + printf(" Error writing descriptor to file\n"); + } + fclose(fd); + } + + size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_FEATURE); + if (size <= 0) { + printf("\nSkipping Feature Report readout (None detected)\n"); + } else { + report_buffer = (uint8_t*) calloc(size, 1); + if (report_buffer == NULL) { + return -1; + } + + printf("\nReading Feature Report (length %d)...\n", size); + r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_GET_REPORT, (HID_REPORT_TYPE_FEATURE<<8)|0, 0, report_buffer, (uint16_t)size, 5000); + if (r >= 0) { + display_buffer_hex(report_buffer, size); + } else { + switch(r) { + case LIBUSB_ERROR_NOT_FOUND: + printf(" No Feature Report available for this device\n"); + break; + case LIBUSB_ERROR_PIPE: + printf(" Detected stall - resetting pipe...\n"); + libusb_clear_halt(handle, 0); + break; + default: + printf(" Error: %s\n", libusb_strerror((enum libusb_error)r)); + break; + } + } + free(report_buffer); + } + + size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_INPUT); + if (size <= 0) { + printf("\nSkipping Input Report readout (None detected)\n"); + } else { + report_buffer = (uint8_t*) calloc(size, 1); + if (report_buffer == NULL) { + return -1; + } + + printf("\nReading Input Report (length %d)...\n", size); + r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, report_buffer, (uint16_t)size, 5000); + if (r >= 0) { + display_buffer_hex(report_buffer, size); + } else { + switch(r) { + case LIBUSB_ERROR_TIMEOUT: + printf(" Timeout! Please make sure you act on the device within the 5 seconds allocated...\n"); + break; + case LIBUSB_ERROR_PIPE: + printf(" Detected stall - resetting pipe...\n"); + libusb_clear_halt(handle, 0); + break; + default: + printf(" Error: %s\n", libusb_strerror((enum libusb_error)r)); + break; + } + } + + // Attempt a bulk read from endpoint 0 (this should just return a raw input report) + printf("\nTesting interrupt read using endpoint %02X...\n", endpoint_in); + r = libusb_interrupt_transfer(handle, endpoint_in, report_buffer, size, &size, 5000); + if (r >= 0) { + display_buffer_hex(report_buffer, size); + } else { + printf(" %s\n", libusb_strerror((enum libusb_error)r)); + } + + free(report_buffer); + } + return 0; +} + +// Read the MS WinUSB Feature Descriptors, that are used on Windows 8 for automated driver installation +static void read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uint8_t bRequest, int iface_number) +{ +#define MAX_OS_FD_LENGTH 256 + int i, r; + uint8_t os_desc[MAX_OS_FD_LENGTH]; + uint32_t length; + void* le_type_punning_IS_fine; + struct { + const char* desc; + uint8_t recipient; + uint16_t index; + uint16_t header_size; + } os_fd[2] = { + {"Extended Compat ID", LIBUSB_RECIPIENT_DEVICE, 0x0004, 0x10}, + {"Extended Properties", LIBUSB_RECIPIENT_INTERFACE, 0x0005, 0x0A} + }; + + if (iface_number < 0) return; + // WinUSB has a limitation that forces wIndex to the interface number when issuing + // an Interface Request. To work around that, we can force a Device Request for + // the Extended Properties, assuming the device answers both equally. + if (force_device_request) + os_fd[1].recipient = LIBUSB_RECIPIENT_DEVICE; + + for (i=0; i<2; i++) { + printf("\nReading %s OS Feature Descriptor (wIndex = 0x%04d):\n", os_fd[i].desc, os_fd[i].index); + + // Read the header part + r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_VENDOR|os_fd[i].recipient), + bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i].index, os_desc, os_fd[i].header_size, 1000); + if (r < os_fd[i].header_size) { + perr(" Failed: %s", (r<0)?libusb_strerror((enum libusb_error)r):"header size is too small"); + return; + } + le_type_punning_IS_fine = (void*)os_desc; + length = *((uint32_t*)le_type_punning_IS_fine); + if (length > MAX_OS_FD_LENGTH) { + length = MAX_OS_FD_LENGTH; + } + + // Read the full feature descriptor + r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_VENDOR|os_fd[i].recipient), + bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i].index, os_desc, (uint16_t)length, 1000); + if (r < 0) { + perr(" Failed: %s", libusb_strerror((enum libusb_error)r)); + return; + } else { + display_buffer_hex(os_desc, r); + } + } +} + +static void print_device_cap(struct libusb_bos_dev_capability_descriptor *dev_cap) +{ + switch(dev_cap->bDevCapabilityType) { + case LIBUSB_BT_USB_2_0_EXTENSION: { + struct libusb_usb_2_0_extension_descriptor *usb_2_0_ext = NULL; + libusb_get_usb_2_0_extension_descriptor(NULL, dev_cap, &usb_2_0_ext); + if (usb_2_0_ext) { + printf(" USB 2.0 extension:\n"); + printf(" attributes : %02X\n", usb_2_0_ext->bmAttributes); + libusb_free_usb_2_0_extension_descriptor(usb_2_0_ext); + } + break; + } + case LIBUSB_BT_SS_USB_DEVICE_CAPABILITY: { + struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap = NULL; + libusb_get_ss_usb_device_capability_descriptor(NULL, dev_cap, &ss_usb_device_cap); + if (ss_usb_device_cap) { + printf(" USB 3.0 capabilities:\n"); + printf(" attributes : %02X\n", ss_usb_device_cap->bmAttributes); + printf(" supported speeds : %04X\n", ss_usb_device_cap->wSpeedSupported); + printf(" supported functionality: %02X\n", ss_usb_device_cap->bFunctionalitySupport); + libusb_free_ss_usb_device_capability_descriptor(ss_usb_device_cap); + } + break; + } + case LIBUSB_BT_CONTAINER_ID: { + struct libusb_container_id_descriptor *container_id = NULL; + libusb_get_container_id_descriptor(NULL, dev_cap, &container_id); + if (container_id) { + printf(" Container ID:\n %s\n", uuid_to_string(container_id->ContainerID)); + libusb_free_container_id_descriptor(container_id); + } + break; + } + default: + printf(" Unknown BOS device capability %02x:\n", dev_cap->bDevCapabilityType); + } +} + +static int test_device(uint16_t vid, uint16_t pid) +{ + libusb_device_handle *handle; + libusb_device *dev; + uint8_t bus, port_path[8]; + struct libusb_bos_descriptor *bos_desc; + struct libusb_config_descriptor *conf_desc; + const struct libusb_endpoint_descriptor *endpoint; + int i, j, k, r; + int iface, nb_ifaces, first_iface = -1; + struct libusb_device_descriptor dev_desc; + const char* const speed_name[6] = { "Unknown", "1.5 Mbit/s (USB LowSpeed)", "12 Mbit/s (USB FullSpeed)", + "480 Mbit/s (USB HighSpeed)", "5000 Mbit/s (USB SuperSpeed)", "10000 Mbit/s (USB SuperSpeedPlus)" }; + char string[128]; + uint8_t string_index[3]; // indexes of the string descriptors + uint8_t endpoint_in = 0, endpoint_out = 0; // default IN and OUT endpoints + + printf("Opening device %04X:%04X...\n", vid, pid); + handle = libusb_open_device_with_vid_pid(NULL, vid, pid); + + if (handle == NULL) { + perr(" Failed.\n"); + return -1; + } + + dev = libusb_get_device(handle); + bus = libusb_get_bus_number(dev); + if (extra_info) { + r = libusb_get_port_numbers(dev, port_path, sizeof(port_path)); + if (r > 0) { + printf("\nDevice properties:\n"); + printf(" bus number: %d\n", bus); + printf(" port path: %d", port_path[0]); + for (i=1; i%d", port_path[i]); + } + printf(" (from root hub)\n"); + } + r = libusb_get_device_speed(dev); + if ((r<0) || (r>5)) r=0; + printf(" speed: %s\n", speed_name[r]); + } + + printf("\nReading device descriptor:\n"); + CALL_CHECK_CLOSE(libusb_get_device_descriptor(dev, &dev_desc), handle); + printf(" length: %d\n", dev_desc.bLength); + printf(" device class: %d\n", dev_desc.bDeviceClass); + printf(" S/N: %d\n", dev_desc.iSerialNumber); + printf(" VID:PID: %04X:%04X\n", dev_desc.idVendor, dev_desc.idProduct); + printf(" bcdDevice: %04X\n", dev_desc.bcdDevice); + printf(" iMan:iProd:iSer: %d:%d:%d\n", dev_desc.iManufacturer, dev_desc.iProduct, dev_desc.iSerialNumber); + printf(" nb confs: %d\n", dev_desc.bNumConfigurations); + // Copy the string descriptors for easier parsing + string_index[0] = dev_desc.iManufacturer; + string_index[1] = dev_desc.iProduct; + string_index[2] = dev_desc.iSerialNumber; + + printf("\nReading BOS descriptor: "); + if (libusb_get_bos_descriptor(handle, &bos_desc) == LIBUSB_SUCCESS) { + printf("%d caps\n", bos_desc->bNumDeviceCaps); + for (i = 0; i < bos_desc->bNumDeviceCaps; i++) + print_device_cap(bos_desc->dev_capability[i]); + libusb_free_bos_descriptor(bos_desc); + } else { + printf("no descriptor\n"); + } + + printf("\nReading first configuration descriptor:\n"); + CALL_CHECK_CLOSE(libusb_get_config_descriptor(dev, 0, &conf_desc), handle); + nb_ifaces = conf_desc->bNumInterfaces; + printf(" nb interfaces: %d\n", nb_ifaces); + if (nb_ifaces > 0) + first_iface = conf_desc->usb_interface[0].altsetting[0].bInterfaceNumber; + for (i=0; iusb_interface[i].altsetting[0].bInterfaceNumber); + for (j=0; jusb_interface[i].num_altsetting; j++) { + printf("interface[%d].altsetting[%d]: num endpoints = %d\n", + i, j, conf_desc->usb_interface[i].altsetting[j].bNumEndpoints); + printf(" Class.SubClass.Protocol: %02X.%02X.%02X\n", + conf_desc->usb_interface[i].altsetting[j].bInterfaceClass, + conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass, + conf_desc->usb_interface[i].altsetting[j].bInterfaceProtocol); + if ( (conf_desc->usb_interface[i].altsetting[j].bInterfaceClass == LIBUSB_CLASS_MASS_STORAGE) + && ( (conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass == 0x01) + || (conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass == 0x06) ) + && (conf_desc->usb_interface[i].altsetting[j].bInterfaceProtocol == 0x50) ) { + // Mass storage devices that can use basic SCSI commands + test_mode = USE_SCSI; + } + for (k=0; kusb_interface[i].altsetting[j].bNumEndpoints; k++) { + struct libusb_ss_endpoint_companion_descriptor *ep_comp = NULL; + endpoint = &conf_desc->usb_interface[i].altsetting[j].endpoint[k]; + printf(" endpoint[%d].address: %02X\n", k, endpoint->bEndpointAddress); + // Use the first interrupt or bulk IN/OUT endpoints as default for testing + if ((endpoint->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) & (LIBUSB_TRANSFER_TYPE_BULK | LIBUSB_TRANSFER_TYPE_INTERRUPT)) { + if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) { + if (!endpoint_in) + endpoint_in = endpoint->bEndpointAddress; + } else { + if (!endpoint_out) + endpoint_out = endpoint->bEndpointAddress; + } + } + printf(" max packet size: %04X\n", endpoint->wMaxPacketSize); + printf(" polling interval: %02X\n", endpoint->bInterval); + libusb_get_ss_endpoint_companion_descriptor(NULL, endpoint, &ep_comp); + if (ep_comp) { + printf(" max burst: %02X (USB 3.0)\n", ep_comp->bMaxBurst); + printf(" bytes per interval: %04X (USB 3.0)\n", ep_comp->wBytesPerInterval); + libusb_free_ss_endpoint_companion_descriptor(ep_comp); + } + } + } + } + libusb_free_config_descriptor(conf_desc); + + libusb_set_auto_detach_kernel_driver(handle, 1); + for (iface = 0; iface < nb_ifaces; iface++) + { + printf("\nClaiming interface %d...\n", iface); + r = libusb_claim_interface(handle, iface); + if (r != LIBUSB_SUCCESS) { + perr(" Failed.\n"); + } + } + + printf("\nReading string descriptors:\n"); + for (i=0; i<3; i++) { + if (string_index[i] == 0) { + continue; + } + if (libusb_get_string_descriptor_ascii(handle, string_index[i], (unsigned char*)string, sizeof(string)) > 0) { + printf(" String (0x%02X): \"%s\"\n", string_index[i], string); + } + } + // Read the OS String Descriptor + r = libusb_get_string_descriptor(handle, MS_OS_DESC_STRING_INDEX, 0, (unsigned char*)string, MS_OS_DESC_STRING_LENGTH); + if (r == MS_OS_DESC_STRING_LENGTH && memcmp(ms_os_desc_string, string, sizeof(ms_os_desc_string)) == 0) { + // If this is a Microsoft OS String Descriptor, + // attempt to read the WinUSB extended Feature Descriptors + read_ms_winsub_feature_descriptors(handle, string[MS_OS_DESC_VENDOR_CODE_OFFSET], first_iface); + } + + switch(test_mode) { + case USE_PS3: + CALL_CHECK_CLOSE(display_ps3_status(handle), handle); + break; + case USE_XBOX: + CALL_CHECK_CLOSE(display_xbox_status(handle), handle); + CALL_CHECK_CLOSE(set_xbox_actuators(handle, 128, 222), handle); + msleep(2000); + CALL_CHECK_CLOSE(set_xbox_actuators(handle, 0, 0), handle); + break; + case USE_HID: + test_hid(handle, endpoint_in); + break; + case USE_SCSI: + CALL_CHECK_CLOSE(test_mass_storage(handle, endpoint_in, endpoint_out), handle); + case USE_GENERIC: + break; + } + + printf("\n"); + for (iface = 0; iface= 2) { + for (j = 1; j= 2) ) { + switch(argv[j][1]) { + case 'd': + debug_mode = true; + break; + case 'i': + extra_info = true; + break; + case 'w': + force_device_request = true; + break; + case 'b': + if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) { + printf(" Option -b requires a file name\n"); + return 1; + } + binary_name = argv[++j]; + binary_dump = true; + break; + case 'l': + if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) { + printf(" Option -l requires an ISO 639-1 language parameter\n"); + return 1; + } + error_lang = argv[++j]; + break; + case 'j': + // OLIMEX ARM-USB-TINY JTAG, 2 channel composite device - 2 interfaces + if (!VID && !PID) { + VID = 0x15BA; + PID = 0x0004; + } + break; + case 'k': + // Generic 2 GB USB Key (SCSI Transparent/Bulk Only) - 1 interface + if (!VID && !PID) { + VID = 0x0204; + PID = 0x6025; + } + break; + // The following tests will force VID:PID if already provided + case 'p': + // Sony PS3 Controller - 1 interface + VID = 0x054C; + PID = 0x0268; + test_mode = USE_PS3; + break; + case 's': + // Microsoft Sidewinder Precision Pro Joystick - 1 HID interface + VID = 0x045E; + PID = 0x0008; + test_mode = USE_HID; + break; + case 'x': + // Microsoft XBox Controller Type S - 1 interface + VID = 0x045E; + PID = 0x0289; + test_mode = USE_XBOX; + break; + default: + show_help = true; + break; + } + } else { + for (i=0; i 7)) { + printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-l lang] [-j] [-x] [-s] [-p] [-w] [vid:pid]\n", argv[0]); + printf(" -h : display usage\n"); + printf(" -d : enable debug output\n"); + printf(" -i : print topology and speed info\n"); + printf(" -j : test composite FTDI based JTAG device\n"); + printf(" -k : test Mass Storage device\n"); + printf(" -b file : dump Mass Storage data to file 'file'\n"); + printf(" -p : test Sony PS3 SixAxis controller\n"); + printf(" -s : test Microsoft Sidewinder Precision Pro (HID)\n"); + printf(" -x : test Microsoft XBox Controller Type S\n"); + printf(" -l lang : language to report errors in (ISO 639-1)\n"); + printf(" -w : force the use of device requests when querying WCID descriptors\n"); + printf("If only the vid:pid is provided, xusb attempts to run the most appropriate test\n"); + return 0; + } + + // xusb is commonly used as a debug tool, so it's convenient to have debug output during libusb_init(), + // but since we can't call on libusb_set_option() before libusb_init(), we use the env variable method + old_dbg_str = getenv("LIBUSB_DEBUG"); + if (debug_mode) { + if (putenv("LIBUSB_DEBUG=4") != 0) // LIBUSB_LOG_LEVEL_DEBUG + printf("Unable to set debug level\n"); + } + + version = libusb_get_version(); + printf("Using libusb v%d.%d.%d.%d\n\n", version->major, version->minor, version->micro, version->nano); + r = libusb_init(NULL); + if (r < 0) + return r; + + // If not set externally, and no debug option was given, use info log level + if ((old_dbg_str == NULL) && (!debug_mode)) + libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO); + if (error_lang != NULL) { + r = libusb_setlocale(error_lang); + if (r < 0) + printf("Invalid or unsupported locale '%s': %s\n", error_lang, libusb_strerror((enum libusb_error)r)); + } + + test_device(VID, PID); + + libusb_exit(NULL); + + if (debug_mode) { + snprintf(str, sizeof(str), "LIBUSB_DEBUG=%s", (old_dbg_str == NULL)?"":old_dbg_str); + str[sizeof(str) - 1] = 0; // Windows may not NUL terminate the string + } + + return 0; +} diff --git a/src/libusb-win32/libusb-1.0/libusb.h b/src/libusb-win32/include/libusb-1.0/libusb.h similarity index 87% rename from src/libusb-win32/libusb-1.0/libusb.h rename to src/libusb-win32/include/libusb-1.0/libusb.h index c165a76..394b62b 100644 --- a/src/libusb-win32/libusb-1.0/libusb.h +++ b/src/libusb-win32/include/libusb-1.0/libusb.h @@ -3,7 +3,7 @@ * Copyright © 2001 Johannes Erdfelt * Copyright © 2007-2008 Daniel Drake * Copyright © 2012 Pete Batard - * Copyright © 2012 Nathan Hjelm + * Copyright © 2012-2018 Nathan Hjelm * For more information, please visit: http://libusb.info * * This library is free software; you can redistribute it and/or @@ -54,13 +54,19 @@ typedef unsigned __int32 uint32_t; #include #endif -#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) +#if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) #include #endif #include #include +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#define ZERO_SIZED_ARRAY /* [] - valid C99 code */ +#else +#define ZERO_SIZED_ARRAY 0 /* [0] - non-standard, but usually working code */ +#endif + /* 'interface' might be defined as a macro on Windows, so we need to * undefine it so as not to break the current libusb API, because * libusb_config_descriptor has an 'interface' member @@ -79,12 +85,14 @@ typedef unsigned __int32 uint32_t; #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #define LIBUSB_DEPRECATED_FOR(f) \ __attribute__((deprecated("Use " #f " instead"))) +#elif __GNUC__ >= 3 +#define LIBUSB_DEPRECATED_FOR(f) __attribute__((deprecated)) #else #define LIBUSB_DEPRECATED_FOR(f) #endif /* __GNUC__ */ /** \def LIBUSB_CALL - * \ingroup misc + * \ingroup libusb_misc * libusb's Windows calling convention. * * Under Windows, the selection of available compilers and configurations @@ -122,7 +130,7 @@ typedef unsigned __int32 uint32_t; #endif /** \def LIBUSB_API_VERSION - * \ingroup misc + * \ingroup libusb_misc * libusb's API version. * * Since version 1.0.13, to help with feature detection, libusb defines @@ -141,7 +149,7 @@ typedef unsigned __int32 uint32_t; * Internally, LIBUSB_API_VERSION is defined as follows: * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) */ -#define LIBUSB_API_VERSION 0x01000104 +#define LIBUSB_API_VERSION 0x01000107 /* The following is kept for compatibility, but will be deprecated in the future */ #define LIBUSBX_API_VERSION LIBUSB_API_VERSION @@ -151,7 +159,7 @@ extern "C" { #endif /** - * \ingroup misc + * \ingroup libusb_misc * Convert a 16-bit value from host-endian to little-endian format. On * little endian systems, this function does nothing. On big endian systems, * the bytes are swapped. @@ -170,7 +178,7 @@ static inline uint16_t libusb_cpu_to_le16(const uint16_t x) } /** \def libusb_le16_to_cpu - * \ingroup misc + * \ingroup libusb_misc * Convert a 16-bit value from little-endian to host-endian format. On * little endian systems, this function does nothing. On big endian systems, * the bytes are swapped. @@ -181,7 +189,7 @@ static inline uint16_t libusb_cpu_to_le16(const uint16_t x) /* standard USB stuff */ -/** \ingroup desc +/** \ingroup libusb_desc * Device and/or Interface Class codes */ enum libusb_class_code { /** In the context of a \ref libusb_device_descriptor "device descriptor", @@ -243,7 +251,7 @@ enum libusb_class_code { LIBUSB_CLASS_VENDOR_SPEC = 0xff }; -/** \ingroup desc +/** \ingroup libusb_desc * Descriptor types as defined by the USB specification. */ enum libusb_descriptor_type { /** Device descriptor. See libusb_device_descriptor. */ @@ -311,7 +319,7 @@ enum libusb_descriptor_type { #define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ #define LIBUSB_ENDPOINT_DIR_MASK 0x80 -/** \ingroup desc +/** \ingroup libusb_desc * Endpoint direction. Values for bit 7 of the * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. */ @@ -325,7 +333,7 @@ enum libusb_endpoint_direction { #define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ -/** \ingroup desc +/** \ingroup libusb_desc * Endpoint transfer type. Values for bits 0:1 of the * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. */ @@ -346,7 +354,7 @@ enum libusb_transfer_type { LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4, }; -/** \ingroup misc +/** \ingroup libusb_misc * Standard requests, as defined in table 9-5 of the USB 3.0 specifications */ enum libusb_standard_request { /** Request status of the specific recipient */ @@ -394,7 +402,7 @@ enum libusb_standard_request { LIBUSB_SET_ISOCH_DELAY = 0x31, }; -/** \ingroup misc +/** \ingroup libusb_misc * Request type bits of the * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control * transfers. */ @@ -412,7 +420,7 @@ enum libusb_request_type { LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) }; -/** \ingroup misc +/** \ingroup libusb_misc * Recipient bits of the * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control * transfers. Values 4 through 31 are reserved. */ @@ -432,7 +440,7 @@ enum libusb_request_recipient { #define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C -/** \ingroup desc +/** \ingroup libusb_desc * Synchronization type for isochronous endpoints. Values for bits 2:3 of the * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in * libusb_endpoint_descriptor. @@ -453,7 +461,7 @@ enum libusb_iso_sync_type { #define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 -/** \ingroup desc +/** \ingroup libusb_desc * Usage type for isochronous endpoints. Values for bits 4:5 of the * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in * libusb_endpoint_descriptor. @@ -469,7 +477,7 @@ enum libusb_iso_usage_type { LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2, }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the standard USB device descriptor. This * descriptor is documented in section 9.6.1 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -523,7 +531,7 @@ struct libusb_device_descriptor { uint8_t bNumConfigurations; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the standard USB endpoint descriptor. This * descriptor is documented in section 9.6.6 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -569,11 +577,11 @@ struct libusb_endpoint_descriptor { * it will store them here, should you wish to parse them. */ const unsigned char *extra; - /** Length of the extra descriptors, in bytes. */ + /** Length of the extra descriptors, in bytes. Must be non-negative. */ int extra_length; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the standard USB interface descriptor. This * descriptor is documented in section 9.6.5 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -619,11 +627,11 @@ struct libusb_interface_descriptor { * it will store them here, should you wish to parse them. */ const unsigned char *extra; - /** Length of the extra descriptors, in bytes. */ + /** Length of the extra descriptors, in bytes. Must be non-negative. */ int extra_length; }; -/** \ingroup desc +/** \ingroup libusb_desc * A collection of alternate settings for a particular USB interface. */ struct libusb_interface { @@ -631,11 +639,12 @@ struct libusb_interface { * by the num_altsetting field. */ const struct libusb_interface_descriptor *altsetting; - /** The number of alternate settings that belong to this interface */ + /** The number of alternate settings that belong to this interface. + * Must be non-negative. */ int num_altsetting; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the standard USB configuration descriptor. This * descriptor is documented in section 9.6.3 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -678,11 +687,11 @@ struct libusb_config_descriptor { * descriptors, it will store them here, should you wish to parse them. */ const unsigned char *extra; - /** Length of the extra descriptors, in bytes. */ + /** Length of the extra descriptors, in bytes. Must be non-negative. */ int extra_length; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the superspeed endpoint companion * descriptor. This descriptor is documented in section 9.6.7 of * the USB 3.0 specification. All multiple-byte fields are represented in @@ -700,7 +709,7 @@ struct libusb_ss_endpoint_companion_descriptor { /** The maximum number of packets the endpoint can send or - * recieve as part of a burst. */ + * receive as part of a burst. */ uint8_t bMaxBurst; /** In bulk EP: bits 4:0 represents the maximum number of @@ -714,7 +723,7 @@ struct libusb_ss_endpoint_companion_descriptor { uint16_t wBytesPerInterval; }; -/** \ingroup desc +/** \ingroup libusb_desc * A generic representation of a BOS Device Capability descriptor. It is * advised to check bDevCapabilityType and call the matching * libusb_get_*_descriptor function to get a structure fully matching the type. @@ -729,16 +738,10 @@ struct libusb_bos_dev_capability_descriptor { /** Device Capability type */ uint8_t bDevCapabilityType; /** Device Capability data (bLength - 3 bytes) */ - uint8_t dev_capability_data -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + uint8_t dev_capability_data[ZERO_SIZED_ARRAY]; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the Binary Device Object Store (BOS) descriptor. * This descriptor is documented in section 9.6.2 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -760,16 +763,10 @@ struct libusb_bos_descriptor { uint8_t bNumDeviceCaps; /** bNumDeviceCap Device Capability Descriptors */ - struct libusb_bos_dev_capability_descriptor *dev_capability -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY]; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the USB 2.0 Extension descriptor * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -795,7 +792,7 @@ struct libusb_usb_2_0_extension_descriptor { uint32_t bmAttributes; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the SuperSpeed USB Device Capability descriptor * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -837,7 +834,7 @@ struct libusb_ss_usb_device_capability_descriptor { uint16_t bU2DevExitLat; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the Container ID descriptor. * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification. * All multiple-byte fields, except UUIDs, are represented in host-endian format. @@ -863,7 +860,7 @@ struct libusb_container_id_descriptor { uint8_t ContainerID[16]; }; -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Setup packet for control transfers. */ struct libusb_control_setup { /** Request type. Bits 0:4 determine recipient, see @@ -899,7 +896,7 @@ struct libusb_context; struct libusb_device; struct libusb_device_handle; -/** \ingroup lib +/** \ingroup libusb_lib * Structure providing the version of the libusb runtime */ struct libusb_version { @@ -922,12 +919,12 @@ struct libusb_version { const char* describe; }; -/** \ingroup lib +/** \ingroup libusb_lib * Structure representing a libusb session. The concept of individual libusb * sessions allows for your program to use two libraries (or dynamically * load two modules) which both independently use libusb. This will prevent * interference between the individual libusb users - for example - * libusb_set_debug() will not affect the other user of the library, and + * libusb_set_option() will not affect the other user of the library, and * libusb_exit() will not destroy resources that the other user is still * using. * @@ -937,11 +934,11 @@ struct libusb_version { * every function call where a context is required. The default context * will be used. * - * For more information, see \ref contexts. + * For more information, see \ref libusb_contexts. */ typedef struct libusb_context libusb_context; -/** \ingroup dev +/** \ingroup libusb_dev * Structure representing a USB device detected on the system. This is an * opaque type for which you are only ever provided with a pointer, usually * originating from libusb_get_device_list(). @@ -959,7 +956,7 @@ typedef struct libusb_context libusb_context; typedef struct libusb_device libusb_device; -/** \ingroup dev +/** \ingroup libusb_dev * Structure representing a handle on a USB device. This is an opaque type for * which you are only ever provided with a pointer, usually originating from * libusb_open(). @@ -969,7 +966,7 @@ typedef struct libusb_device libusb_device; */ typedef struct libusb_device_handle libusb_device_handle; -/** \ingroup dev +/** \ingroup libusb_dev * Speed codes. Indicates the speed at which the device is operating. */ enum libusb_speed { @@ -987,9 +984,12 @@ enum libusb_speed { /** The device is operating at super speed (5000MBit/s). */ LIBUSB_SPEED_SUPER = 4, + + /** The device is operating at super speed plus (10000MBit/s). */ + LIBUSB_SPEED_SUPER_PLUS = 5, }; -/** \ingroup dev +/** \ingroup libusb_dev * Supported speeds (wSpeedSupported) bitfield. Indicates what * speeds the device supports. */ @@ -1007,7 +1007,7 @@ enum libusb_supported_speed { LIBUSB_SUPER_SPEED_OPERATION = 8, }; -/** \ingroup dev +/** \ingroup libusb_dev * Masks for the bits of the * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field * of the USB 2.0 Extension descriptor. @@ -1017,7 +1017,7 @@ enum libusb_usb_2_0_extension_attributes { LIBUSB_BM_LPM_SUPPORT = 2, }; -/** \ingroup dev +/** \ingroup libusb_dev * Masks for the bits of the * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field * field of the SuperSpeed USB Device Capability descriptor. @@ -1027,7 +1027,7 @@ enum libusb_ss_usb_device_capability_attributes { LIBUSB_BM_LTM_SUPPORT = 2, }; -/** \ingroup dev +/** \ingroup libusb_dev * USB capability types */ enum libusb_bos_type { @@ -1044,7 +1044,7 @@ enum libusb_bos_type { LIBUSB_BT_CONTAINER_ID = 4, }; -/** \ingroup misc +/** \ingroup libusb_misc * Error codes. Most libusb functions return 0 on success or one of these * codes on failure. * You can call libusb_error_name() to retrieve a string representation of an @@ -1101,7 +1101,7 @@ enum libusb_error { /* Total number of error codes in enum libusb_error */ #define LIBUSB_ERROR_COUNT 14 -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Transfer status codes */ enum libusb_transfer_status { /** Transfer completed without error. Note that this does not indicate @@ -1131,20 +1131,23 @@ enum libusb_transfer_status { when adding new status codes here. */ }; -/** \ingroup asyncio +/** \ingroup libusb_asyncio * libusb_transfer.flags values */ enum libusb_transfer_flags { /** Report short frames as errors */ - LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, + LIBUSB_TRANSFER_SHORT_NOT_OK = 1U << 0, - /** Automatically free() transfer buffer during libusb_free_transfer() */ - LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, + /** Automatically free() transfer buffer during libusb_free_transfer(). + * Note that buffers allocated with libusb_dev_mem_alloc() should not + * be attempted freed in this way, since free() is not an appropriate + * way to release such memory. */ + LIBUSB_TRANSFER_FREE_BUFFER = 1U << 1, /** Automatically call libusb_free_transfer() after callback returns. * If this flag is set, it is illegal to call libusb_free_transfer() * from your transfer callback, as this will result in a double-free * when this flag is acted upon. */ - LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, + LIBUSB_TRANSFER_FREE_TRANSFER = 1U << 2, /** Terminate transfers that are a multiple of the endpoint's * wMaxPacketSize with an extra zero length packet. This is useful @@ -1169,10 +1172,10 @@ enum libusb_transfer_flags { * * Available since libusb-1.0.9. */ - LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3, + LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1U << 3, }; -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Isochronous packet descriptor. */ struct libusb_iso_packet_descriptor { /** Length of data to request in this packet */ @@ -1187,18 +1190,18 @@ struct libusb_iso_packet_descriptor { struct libusb_transfer; -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Asynchronous transfer callback function type. When submitting asynchronous * transfers, you pass a pointer to a callback function of this type via the * \ref libusb_transfer::callback "callback" member of the libusb_transfer * structure. libusb will call this function later, when the transfer has - * completed or failed. See \ref asyncio for more information. + * completed or failed. See \ref libusb_asyncio for more information. * \param transfer The libusb_transfer struct the callback function is being * notified about. */ typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); -/** \ingroup asyncio +/** \ingroup libusb_asyncio * The generic USB transfer structure. The user populates this structure and * then submits it in order to request a transfer. After the transfer has * completed, the library populates the transfer with the results and passes @@ -1217,7 +1220,7 @@ struct libusb_transfer { /** Type of the endpoint from \ref libusb_transfer_type */ unsigned char type; - /** Timeout for this transfer in millseconds. A value of 0 indicates no + /** Timeout for this transfer in milliseconds. A value of 0 indicates no * timeout. */ unsigned int timeout; @@ -1230,7 +1233,7 @@ struct libusb_transfer { * to determine if errors occurred. */ enum libusb_transfer_status status; - /** Length of the data buffer */ + /** Length of the data buffer. Must be non-negative. */ int length; /** Actual length of data that was transferred. Read-only, and only for @@ -1249,20 +1252,14 @@ struct libusb_transfer { unsigned char *buffer; /** Number of isochronous packets. Only used for I/O with isochronous - * endpoints. */ + * endpoints. Must be non-negative. */ int num_iso_packets; /** Isochronous packet descriptors, for isochronous transfers only. */ - struct libusb_iso_packet_descriptor iso_packet_desc -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY]; }; -/** \ingroup misc +/** \ingroup libusb_misc * Capabilities supported by an instance of libusb on the current running * platform. Test if the loaded library supports a given capability by calling * \ref libusb_has_capability(). @@ -1282,27 +1279,51 @@ enum libusb_capability { LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101 }; -/** \ingroup lib +/** \ingroup libusb_lib * Log message levels. * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) * - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr * - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, warning - * and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout, - * warnings and errors to stderr + * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr + * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr */ enum libusb_log_level { LIBUSB_LOG_LEVEL_NONE = 0, - LIBUSB_LOG_LEVEL_ERROR, - LIBUSB_LOG_LEVEL_WARNING, - LIBUSB_LOG_LEVEL_INFO, - LIBUSB_LOG_LEVEL_DEBUG, + LIBUSB_LOG_LEVEL_ERROR = 1, + LIBUSB_LOG_LEVEL_WARNING = 2, + LIBUSB_LOG_LEVEL_INFO = 3, + LIBUSB_LOG_LEVEL_DEBUG = 4, +}; + +/** \ingroup libusb_lib + * Log callback mode. + * \see libusb_set_log_cb() + */ +enum libusb_log_cb_mode { + + /** Callback function handling all log mesages. */ + LIBUSB_LOG_CB_GLOBAL = 1 << 0, + + /** Callback function handling context related log mesages. */ + LIBUSB_LOG_CB_CONTEXT = 1 << 1 }; +/** \ingroup libusb_lib + * Callback function for handling log messages. + * \param ctx the context which is related to the log message, or NULL if it + * is a global log message + * \param level the log level, see \ref libusb_log_level for a description + * \param str the log message + * \see libusb_set_log_cb() + */ +typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx, + enum libusb_log_level level, const char *str); + int LIBUSB_CALL libusb_init(libusb_context **ctx); void LIBUSB_CALL libusb_exit(libusb_context *ctx); +LIBUSB_DEPRECATED_FOR(libusb_set_option) void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); +void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode); const struct libusb_version * LIBUSB_CALL libusb_get_version(void); int LIBUSB_CALL libusb_has_capability(uint32_t capability); const char * LIBUSB_CALL libusb_error_name(int errcode); @@ -1334,7 +1355,7 @@ int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor( struct libusb_ss_endpoint_companion_descriptor **ep_comp); void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor( struct libusb_ss_endpoint_companion_descriptor *ep_comp); -int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *handle, +int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *dev_handle, struct libusb_bos_descriptor **bos); void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos); int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor( @@ -1367,43 +1388,49 @@ int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, unsigned char endpoint); -int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle); +int LIBUSB_CALL libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle); +int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); -int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev, +int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev_handle, int configuration); -int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev, +int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev_handle, int interface_number); -int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev, +int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev_handle, int interface_number); libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); -int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev, +int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, int interface_number, int alternate_setting); -int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev, +int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev_handle, unsigned char endpoint); -int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev); +int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev_handle); -int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev, +int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, int num_endpoints); -int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev, +int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints); -int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev, +unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, + size_t length); +int LIBUSB_CALL libusb_dev_mem_free(libusb_device_handle *dev_handle, + unsigned char *buffer, size_t length); + +int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev_handle, int interface_number); -int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev, +int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev_handle, int interface_number); -int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev, +int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev_handle, int interface_number); int LIBUSB_CALL libusb_set_auto_detach_kernel_driver( - libusb_device_handle *dev, int enable); + libusb_device_handle *dev_handle, int enable); /* async I/O */ -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Get the data section of a control transfer. This convenience function is here * to remind you that the data does not start until 8 bytes into the actual * buffer, as the setup packet comes first. @@ -1421,7 +1448,7 @@ static inline unsigned char *libusb_control_transfer_get_data( return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Get the control setup packet of a control transfer. This convenience * function is here to remind you that the control setup occupies the first * 8 bytes of the transfer data buffer. @@ -1439,7 +1466,7 @@ static inline struct libusb_control_setup *libusb_control_transfer_get_setup( return (struct libusb_control_setup *)(void *) transfer->buffer; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the setup packet (first 8 bytes of the data * buffer) for a control transfer. The wIndex, wValue and wLength values should * be given in host-endian byte order. @@ -1483,7 +1510,7 @@ void LIBUSB_CALL libusb_transfer_set_stream_id( uint32_t LIBUSB_CALL libusb_transfer_get_stream_id( struct libusb_transfer *transfer); -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for a control transfer. * @@ -1529,7 +1556,7 @@ static inline void libusb_fill_control_transfer( transfer->callback = callback; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for a bulk transfer. * @@ -1557,7 +1584,7 @@ static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, transfer->callback = callback; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for a bulk transfer using bulk streams. * @@ -1585,7 +1612,7 @@ static inline void libusb_fill_bulk_stream_transfer( libusb_transfer_set_stream_id(transfer, stream_id); } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for an interrupt transfer. * @@ -1613,7 +1640,7 @@ static inline void libusb_fill_interrupt_transfer( transfer->callback = callback; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for an isochronous transfer. * @@ -1643,7 +1670,7 @@ static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, transfer->callback = callback; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Convenience function to set the length of all packets in an isochronous * transfer, based on the num_iso_packets field in the transfer structure. * @@ -1659,7 +1686,7 @@ static inline void libusb_set_iso_packet_lengths( transfer->iso_packet_desc[i].length = length; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Convenience function to locate the position of an isochronous packet * within the buffer of an isochronous transfer. * @@ -1698,7 +1725,7 @@ static inline unsigned char *libusb_get_iso_packet_buffer( return transfer->buffer + offset; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Convenience function to locate the position of an isochronous packet * within the buffer of an isochronous transfer, for transfers where each * packet is of identical size. @@ -1749,33 +1776,33 @@ int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *actual_length, unsigned int timeout); -/** \ingroup desc +/** \ingroup libusb_desc * Retrieve a descriptor from the default control pipe. * This is a convenience function which formulates the appropriate control * message to retrieve the descriptor. * - * \param dev a device handle + * \param dev_handle a device handle * \param desc_type the descriptor type, see \ref libusb_descriptor_type * \param desc_index the index of the descriptor to retrieve * \param data output buffer for descriptor * \param length size of data buffer * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure */ -static inline int libusb_get_descriptor(libusb_device_handle *dev, +static inline int libusb_get_descriptor(libusb_device_handle *dev_handle, uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) { - return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t) ((desc_type << 8) | desc_index), 0, data, (uint16_t) length, 1000); } -/** \ingroup desc +/** \ingroup libusb_desc * Retrieve a descriptor from a device. * This is a convenience function which formulates the appropriate control * message to retrieve the descriptor. The string returned is Unicode, as * detailed in the USB specifications. * - * \param dev a device handle + * \param dev_handle a device handle * \param desc_index the index of the descriptor to retrieve * \param langid the language ID for the string descriptor * \param data output buffer for descriptor @@ -1783,15 +1810,15 @@ static inline int libusb_get_descriptor(libusb_device_handle *dev, * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure * \see libusb_get_string_descriptor_ascii() */ -static inline int libusb_get_string_descriptor(libusb_device_handle *dev, +static inline int libusb_get_string_descriptor(libusb_device_handle *dev_handle, uint8_t desc_index, uint16_t langid, unsigned char *data, int length) { - return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), langid, data, (uint16_t) length, 1000); } -int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev, +int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, uint8_t desc_index, unsigned char *data, int length); /* polling and timeouts */ @@ -1801,6 +1828,7 @@ void LIBUSB_CALL libusb_lock_events(libusb_context *ctx); void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx); int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx); int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx); +void LIBUSB_CALL libusb_interrupt_event_handler(libusb_context *ctx); void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx); void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx); int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); @@ -1817,7 +1845,7 @@ int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv); -/** \ingroup poll +/** \ingroup libusb_poll * File descriptor for polling */ struct libusb_pollfd { @@ -1831,7 +1859,7 @@ struct libusb_pollfd { short events; }; -/** \ingroup poll +/** \ingroup libusb_poll * Callback function, invoked when a new file descriptor should be added * to the set of file descriptors monitored for events. * \param fd the new file descriptor @@ -1844,7 +1872,7 @@ struct libusb_pollfd { typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, void *user_data); -/** \ingroup poll +/** \ingroup libusb_poll * Callback function, invoked when a file descriptor should be removed from * the set of file descriptors being monitored for events. After returning * from this callback, do not use that file descriptor again. @@ -1862,7 +1890,7 @@ void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, void *user_data); -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Callback handle. * * Callbacks handles are generated by libusb_hotplug_register_callback() @@ -1872,43 +1900,43 @@ void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, * * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * - * For more information, see \ref hotplug. + * For more information, see \ref libusb_hotplug. */ typedef int libusb_hotplug_callback_handle; -/** \ingroup hotplug +/** \ingroup libusb_hotplug * * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * * Flags for hotplug events */ typedef enum { /** Default value when not using any flags. */ - LIBUSB_HOTPLUG_NO_FLAGS = 0, + LIBUSB_HOTPLUG_NO_FLAGS = 0U, /** Arm the callback and fire it for all matching currently attached devices. */ - LIBUSB_HOTPLUG_ENUMERATE = 1<<0, + LIBUSB_HOTPLUG_ENUMERATE = 1U << 0, } libusb_hotplug_flag; -/** \ingroup hotplug +/** \ingroup libusb_hotplug * * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * * Hotplug events */ typedef enum { /** A device has been plugged in and is ready to use */ - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01, + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01U, /** A device has left and is no longer available. * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device. * It is safe to call libusb_get_device_descriptor on a device that has left */ - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02, + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02U, } libusb_hotplug_event; -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Wildcard matching for hotplug events */ #define LIBUSB_HOTPLUG_MATCH_ANY -1 -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Hotplug callback function type. When requesting hotplug event notifications, * you pass a pointer to a callback function of this type. * @@ -1916,7 +1944,7 @@ typedef enum { * recommended the callback do minimal processing before returning. * * libusb will call this function later, when a matching event had happened on - * a matching device. See \ref hotplug for more information. + * a matching device. See \ref libusb_hotplug for more information. * * It is safe to call either libusb_hotplug_register_callback() or * libusb_hotplug_deregister_callback() from within a callback function. @@ -1935,7 +1963,7 @@ typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, libusb_hotplug_event event, void *user_data); -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Register a hotplug callback function * * Register a callback with the libusb_context. The callback will fire @@ -1966,7 +1994,7 @@ typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, * \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY * \param[in] cb_fn the function to be invoked on a matching event/device * \param[in] user_data user data to pass to the callback function - * \param[out] handle pointer to store the handle of the allocated callback (can be NULL) + * \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL) * \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure */ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, @@ -1976,9 +2004,9 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, int dev_class, libusb_hotplug_callback_fn cb_fn, void *user_data, - libusb_hotplug_callback_handle *handle); + libusb_hotplug_callback_handle *callback_handle); -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Deregisters a hotplug callback. * * Deregister a callback from a libusb_context. This function is safe to call from within @@ -1987,10 +2015,49 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * * \param[in] ctx context this callback is registered with - * \param[in] handle the handle of the callback to deregister + * \param[in] callback_handle the handle of the callback to deregister */ void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, - libusb_hotplug_callback_handle handle); + libusb_hotplug_callback_handle callback_handle); + +/** \ingroup libusb_lib + * Available option values for libusb_set_option(). + */ +enum libusb_option { + /** Set the log message verbosity. + * + * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever + * printed. If you choose to increase the message verbosity level, ensure + * that your application does not close the stderr file descriptor. + * + * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative + * with its message logging and most of the time, will only log messages that + * explain error conditions and other oddities. This will help you debug + * your software. + * + * If the LIBUSB_DEBUG environment variable was set when libusb was + * initialized, this function does nothing: the message verbosity is fixed + * to the value in the environment variable. + * + * If libusb was compiled without any message logging, this function does + * nothing: you'll never get any messages. + * + * If libusb was compiled with verbose debug message logging, this function + * does nothing: you'll always get messages from all levels. + */ + LIBUSB_OPTION_LOG_LEVEL, + + /** Use the UsbDk backend for a specific context, if available. + * + * This option should be set immediately after calling libusb_init(), otherwise + * unspecified behavior may occur. + * + * Only valid on Windows. + */ + LIBUSB_OPTION_USE_USBDK, +}; + +int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); #ifdef __cplusplus } diff --git a/src/libusb-win32/libusb-1.0.a b/src/libusb-win32/libusb-1.0.a deleted file mode 100644 index aaa3e5a..0000000 Binary files a/src/libusb-win32/libusb-1.0.a and /dev/null differ diff --git a/src/libusb-win32/libusb-1.0.def b/src/libusb-win32/libusb-1.0.def new file mode 100644 index 0000000..6080040 --- /dev/null +++ b/src/libusb-win32/libusb-1.0.def @@ -0,0 +1,178 @@ +LIBRARY "libusb-1.0.dll" +EXPORTS + libusb_alloc_streams + libusb_alloc_streams@16 = libusb_alloc_streams + libusb_alloc_transfer + libusb_alloc_transfer@4 = libusb_alloc_transfer + libusb_attach_kernel_driver + libusb_attach_kernel_driver@8 = libusb_attach_kernel_driver + libusb_bulk_transfer + libusb_bulk_transfer@24 = libusb_bulk_transfer + libusb_cancel_transfer + libusb_cancel_transfer@4 = libusb_cancel_transfer + libusb_claim_interface + libusb_claim_interface@8 = libusb_claim_interface + libusb_clear_halt + libusb_clear_halt@8 = libusb_clear_halt + libusb_close + libusb_close@4 = libusb_close + libusb_control_transfer + libusb_control_transfer@32 = libusb_control_transfer + libusb_detach_kernel_driver + libusb_detach_kernel_driver@8 = libusb_detach_kernel_driver + libusb_dev_mem_alloc + libusb_dev_mem_alloc@8 = libusb_dev_mem_alloc + libusb_dev_mem_free + libusb_dev_mem_free@12 = libusb_dev_mem_free + libusb_error_name + libusb_error_name@4 = libusb_error_name + libusb_event_handler_active + libusb_event_handler_active@4 = libusb_event_handler_active + libusb_event_handling_ok + libusb_event_handling_ok@4 = libusb_event_handling_ok + libusb_exit + libusb_exit@4 = libusb_exit + libusb_free_bos_descriptor + libusb_free_bos_descriptor@4 = libusb_free_bos_descriptor + libusb_free_config_descriptor + libusb_free_config_descriptor@4 = libusb_free_config_descriptor + libusb_free_container_id_descriptor + libusb_free_container_id_descriptor@4 = libusb_free_container_id_descriptor + libusb_free_device_list + libusb_free_device_list@8 = libusb_free_device_list + libusb_free_pollfds + libusb_free_pollfds@4 = libusb_free_pollfds + libusb_free_ss_endpoint_companion_descriptor + libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor + libusb_free_ss_usb_device_capability_descriptor + libusb_free_ss_usb_device_capability_descriptor@4 = libusb_free_ss_usb_device_capability_descriptor + libusb_free_streams + libusb_free_streams@12 = libusb_free_streams + libusb_free_transfer + libusb_free_transfer@4 = libusb_free_transfer + libusb_free_usb_2_0_extension_descriptor + libusb_free_usb_2_0_extension_descriptor@4 = libusb_free_usb_2_0_extension_descriptor + libusb_get_active_config_descriptor + libusb_get_active_config_descriptor@8 = libusb_get_active_config_descriptor + libusb_get_bos_descriptor + libusb_get_bos_descriptor@8 = libusb_get_bos_descriptor + libusb_get_bus_number + libusb_get_bus_number@4 = libusb_get_bus_number + libusb_get_config_descriptor + libusb_get_config_descriptor@12 = libusb_get_config_descriptor + libusb_get_config_descriptor_by_value + libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value + libusb_get_configuration + libusb_get_configuration@8 = libusb_get_configuration + libusb_get_container_id_descriptor + libusb_get_container_id_descriptor@12 = libusb_get_container_id_descriptor + libusb_get_device + libusb_get_device@4 = libusb_get_device + libusb_get_device_address + libusb_get_device_address@4 = libusb_get_device_address + libusb_get_device_descriptor + libusb_get_device_descriptor@8 = libusb_get_device_descriptor + libusb_get_device_list + libusb_get_device_list@8 = libusb_get_device_list + libusb_get_device_speed + libusb_get_device_speed@4 = libusb_get_device_speed + libusb_get_max_iso_packet_size + libusb_get_max_iso_packet_size@8 = libusb_get_max_iso_packet_size + libusb_get_max_packet_size + libusb_get_max_packet_size@8 = libusb_get_max_packet_size + libusb_get_next_timeout + libusb_get_next_timeout@8 = libusb_get_next_timeout + libusb_get_parent + libusb_get_parent@4 = libusb_get_parent + libusb_get_pollfds + libusb_get_pollfds@4 = libusb_get_pollfds + libusb_get_port_number + libusb_get_port_number@4 = libusb_get_port_number + libusb_get_port_numbers + libusb_get_port_numbers@12 = libusb_get_port_numbers + libusb_get_port_path + libusb_get_port_path@16 = libusb_get_port_path + libusb_get_ss_endpoint_companion_descriptor + libusb_get_ss_endpoint_companion_descriptor@12 = libusb_get_ss_endpoint_companion_descriptor + libusb_get_ss_usb_device_capability_descriptor + libusb_get_ss_usb_device_capability_descriptor@12 = libusb_get_ss_usb_device_capability_descriptor + libusb_get_string_descriptor_ascii + libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii + libusb_get_usb_2_0_extension_descriptor + libusb_get_usb_2_0_extension_descriptor@12 = libusb_get_usb_2_0_extension_descriptor + libusb_get_version + libusb_get_version@0 = libusb_get_version + libusb_handle_events + libusb_handle_events@4 = libusb_handle_events + libusb_handle_events_completed + libusb_handle_events_completed@8 = libusb_handle_events_completed + libusb_handle_events_locked + libusb_handle_events_locked@8 = libusb_handle_events_locked + libusb_handle_events_timeout + libusb_handle_events_timeout@8 = libusb_handle_events_timeout + libusb_handle_events_timeout_completed + libusb_handle_events_timeout_completed@12 = libusb_handle_events_timeout_completed + libusb_has_capability + libusb_has_capability@4 = libusb_has_capability + libusb_hotplug_deregister_callback + libusb_hotplug_deregister_callback@8 = libusb_hotplug_deregister_callback + libusb_hotplug_register_callback + libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback + libusb_init + libusb_init@4 = libusb_init + libusb_interrupt_event_handler + libusb_interrupt_event_handler@4 = libusb_interrupt_event_handler + libusb_interrupt_transfer + libusb_interrupt_transfer@24 = libusb_interrupt_transfer + libusb_kernel_driver_active + libusb_kernel_driver_active@8 = libusb_kernel_driver_active + libusb_lock_event_waiters + libusb_lock_event_waiters@4 = libusb_lock_event_waiters + libusb_lock_events + libusb_lock_events@4 = libusb_lock_events + libusb_open + libusb_open@8 = libusb_open + libusb_open_device_with_vid_pid + libusb_open_device_with_vid_pid@12 = libusb_open_device_with_vid_pid + libusb_pollfds_handle_timeouts + libusb_pollfds_handle_timeouts@4 = libusb_pollfds_handle_timeouts + libusb_ref_device + libusb_ref_device@4 = libusb_ref_device + libusb_release_interface + libusb_release_interface@8 = libusb_release_interface + libusb_reset_device + libusb_reset_device@4 = libusb_reset_device + libusb_set_auto_detach_kernel_driver + libusb_set_auto_detach_kernel_driver@8 = libusb_set_auto_detach_kernel_driver + libusb_set_configuration + libusb_set_configuration@8 = libusb_set_configuration + libusb_set_debug + libusb_set_debug@8 = libusb_set_debug + libusb_set_log_cb + libusb_set_log_cb@12 = libusb_set_log_cb + libusb_set_interface_alt_setting + libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting + libusb_set_option + _libusb_set_option = libusb_set_option + libusb_set_pollfd_notifiers + libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers + libusb_setlocale + libusb_setlocale@4 = libusb_setlocale + libusb_strerror + libusb_strerror@4 = libusb_strerror + libusb_submit_transfer + libusb_submit_transfer@4 = libusb_submit_transfer + libusb_transfer_get_stream_id + libusb_transfer_get_stream_id@4 = libusb_transfer_get_stream_id + libusb_transfer_set_stream_id + libusb_transfer_set_stream_id@8 = libusb_transfer_set_stream_id + libusb_try_lock_events + libusb_try_lock_events@4 = libusb_try_lock_events + libusb_unlock_event_waiters + libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters + libusb_unlock_events + libusb_unlock_events@4 = libusb_unlock_events + libusb_unref_device + libusb_unref_device@4 = libusb_unref_device + libusb_wait_for_event + libusb_wait_for_event@8 = libusb_wait_for_event