| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,234 @@ | ||
| Installation Instructions | ||
| ************************* | ||
|
|
||
| Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, | ||
| 2006 Free Software Foundation, Inc. | ||
|
|
||
| This file is free documentation; the Free Software Foundation gives | ||
| unlimited permission to copy, distribute and modify it. | ||
|
|
||
| Basic Installation | ||
| ================== | ||
|
|
||
| Briefly, the shell commands `./configure; make; make install' should | ||
| configure, build, and install this package. The following | ||
| more-detailed instructions are generic; see the `README' file for | ||
| instructions specific to this package. | ||
|
|
||
| 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 | ||
| you can run in the future to recreate the current configuration, and a | ||
| 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. | ||
|
|
||
| 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 | ||
| 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 | ||
| 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 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. | ||
|
|
||
| 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. | ||
|
|
||
| 3. Optionally, type `make check' to run any self-tests that come with | ||
| the package. | ||
|
|
||
| 4. Type `make install' to install the programs and any data files and | ||
| documentation. | ||
|
|
||
| 5. 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 | ||
| 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. | ||
|
|
||
| Compilers and Options | ||
| ===================== | ||
|
|
||
| Some systems require unusual options for compilation or linking that 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: | ||
|
|
||
| ./configure CC=c99 CFLAGS=-g LIBS=-lposix | ||
|
|
||
| *Note Defining Variables::, for more details. | ||
|
|
||
| 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 | ||
| 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 `..'. | ||
|
|
||
| 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 | ||
| reconfiguring for another architecture. | ||
|
|
||
| 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'. | ||
|
|
||
| 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 | ||
| 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. | ||
|
|
||
| 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'. | ||
|
|
||
| Optional Features | ||
| ================= | ||
|
|
||
| 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 | ||
| 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. | ||
|
|
||
| Specifying the System Type | ||
| ========================== | ||
|
|
||
| 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 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: | ||
|
|
||
| CPU-COMPANY-SYSTEM | ||
|
|
||
| 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 | ||
| 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 | ||
| 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'. | ||
|
|
||
| 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. | ||
|
|
||
| Defining Variables | ||
| ================== | ||
|
|
||
| Variables not defined in a site shell script can be set in the | ||
| 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: | ||
|
|
||
| ./configure CC=/usr/local2/bin/gcc | ||
|
|
||
| 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 bug. Until the bug is fixed you can use this workaround: | ||
|
|
||
| CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash | ||
|
|
||
| `configure' Invocation | ||
| ====================== | ||
|
|
||
| `configure' recognizes the following options to control how it operates. | ||
|
|
||
| `--help' | ||
| `-h' | ||
| Print a summary of the options to `configure', and exit. | ||
|
|
||
| `--version' | ||
| `-V' | ||
| Print the version of Autoconf used to generate the `configure' | ||
| script, and exit. | ||
|
|
||
| `--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 | ||
| disable caching. | ||
|
|
||
| `--config-cache' | ||
| `-C' | ||
| Alias for `--cache-file=config.cache'. | ||
|
|
||
| `--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 | ||
| messages will still be shown). | ||
|
|
||
| `--srcdir=DIR' | ||
| Look for the package's source code in directory DIR. Usually | ||
| `configure' can determine that directory automatically. | ||
|
|
||
| `configure' also accepts some other, not widely useful, options. Run | ||
| `configure --help' for more details. | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip | ||
| ACLOCAL_AMFLAGS = -I m4 | ||
| DISTCLEANFILES = libusb-1.0.pc | ||
| EXTRA_DIST = TODO PORTING msvc libusb/libusb-1.0.def libusb/version_nano.h \ | ||
| examples/getopt/getopt.c examples/getopt/getopt1.c examples/getopt/getopt.h | ||
| SUBDIRS = libusb doc | ||
|
|
||
| if BUILD_EXAMPLES | ||
| SUBDIRS += examples | ||
| endif | ||
|
|
||
| if BUILD_TESTS | ||
| SUBDIRS += tests | ||
| endif | ||
|
|
||
| pkgconfigdir=$(libdir)/pkgconfig | ||
| pkgconfig_DATA=libusb-1.0.pc | ||
|
|
||
| .PHONY: dist-up | ||
|
|
||
| reldir = .release/$(distdir) | ||
| dist-up: dist | ||
| rm -rf $(reldir) | ||
| mkdir -p $(reldir) | ||
| cp $(distdir).tar.bz2 $(reldir) | ||
| rsync -rv $(reldir) frs.sourceforge.net:/home/frs/project/l/li/libusb/libusb-1.0/ | ||
| rm -rf $(reldir) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| For the latest libusbx news, please refer to the ChangeLog file, or visit: | ||
| http://libusbx.org |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| PORTING LIBUSBX TO OTHER PLATFORMS | ||
|
|
||
| Introduction | ||
| ============ | ||
|
|
||
| This document is aimed at developers wishing to port libusbx to unsupported | ||
| platforms. I believe the libusbx API is OS-independent, so by supporting | ||
| multiple operating systems we pave the way for cross-platform USB device | ||
| drivers. | ||
|
|
||
| Implementation-wise, the basic idea is that you provide an interface to | ||
| libusbx's internal "backend" API, which performs the appropriate operations on | ||
| your target platform. | ||
|
|
||
| In terms of USB I/O, your backend provides functionality to submit | ||
| asynchronous transfers (synchronous transfers are implemented in the higher | ||
| layers, based on the async interface). Your backend must also provide | ||
| functionality to cancel those transfers. | ||
|
|
||
| Your backend must also provide an event handling function to "reap" ongoing | ||
| transfers and process their results. | ||
|
|
||
| The backend must also provide standard functions for other USB operations, | ||
| e.g. setting configuration, obtaining descriptors, etc. | ||
|
|
||
|
|
||
| File descriptors for I/O polling | ||
| ================================ | ||
|
|
||
| For libusbx to work, your event handling function obviously needs to be called | ||
| at various points in time. Your backend must provide a set of file descriptors | ||
| which libusbx and its users can pass to poll() or select() to determine when | ||
| it is time to call the event handling function. | ||
|
|
||
| On Linux, this is easy: the usbfs kernel interface exposes a file descriptor | ||
| which can be passed to poll(). If something similar is not true for your | ||
| platform, you can emulate this using an internal library thread to reap I/O as | ||
| necessary, and a pipe() with the main library to raise events. The file | ||
| descriptor of the pipe can then be provided to libusbx as an event source. | ||
|
|
||
|
|
||
| Interface semantics and documentation | ||
| ===================================== | ||
|
|
||
| Documentation of the backend interface can be found in libusbi.h inside the | ||
| usbi_os_backend structure definition. | ||
|
|
||
| Your implementations of these functions will need to call various internal | ||
| libusbx functions, prefixed with "usbi_". Documentation for these functions | ||
| can be found in the .c files where they are implemented. | ||
|
|
||
| You probably want to skim over *all* the documentation before starting your | ||
| implementation. For example, you probably need to allocate and store private | ||
| OS-specific data for device handles, but the documentation for the mechanism | ||
| for doing so is probably not the first thing you will see. | ||
|
|
||
| The Linux backend acts as a good example - view it as a reference | ||
| implementation which you should try to match the behaviour of. | ||
|
|
||
|
|
||
| Getting started | ||
| =============== | ||
|
|
||
| 1. Modify configure.ac to detect your platform appropriately (see the OS_LINUX | ||
| stuff for an example). | ||
|
|
||
| 2. Implement your backend in the libusb/os/ directory, modifying | ||
| libusb/os/Makefile.am appropriately. | ||
|
|
||
| 3. Add preprocessor logic to the top of libusb/core.c to statically assign the | ||
| right usbi_backend for your platform. | ||
|
|
||
| 4. Produce and test your implementation. | ||
|
|
||
| 5. Send your implementation to libusbx-devel mailing list. | ||
|
|
||
|
|
||
| Implementation difficulties? Questions? | ||
| ======================================= | ||
|
|
||
| If you encounter difficulties porting libusbx to your platform, please raise | ||
| these issues on the libusbx-devel mailing list. Where possible and sensible, I | ||
| am interested in solving problems preventing libusbx from operating on other | ||
| platforms. | ||
|
|
||
| The libusbx-devel mailing list is also a good place to ask questions and | ||
| make suggestions about the internal API. Hopefully we can produce some | ||
| better documentation based on your questions and other input. | ||
|
|
||
| You are encouraged to get involved in the process; if the library needs | ||
| some infrastructure additions/modifications to better support your platform, | ||
| you are encouraged to make such changes (in cleanly distinct patch | ||
| submissions). Even if you do not make such changes yourself, please do raise | ||
| the issues on the mailing list at the very minimum. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| libusbx | ||
| ======= | ||
|
|
||
| libusbx is a library for USB device access from Linux, Mac OS X, | ||
| Windows and OpenBSD/NetBSD userspace, with OpenBSD/NetBSD, and to a | ||
| lesser extent some of the newest features of Windows (such as libusbK | ||
| and libusb-win32 driver support) being EXPERIMENTAL. | ||
| It is written in C and licensed under the GNU Lesser General Public | ||
| License version 2.1 or, at your option, any later version (see COPYING). | ||
|
|
||
| libusbx is abstracted internally in such a way that it can hopefully | ||
| be ported to other operating systems. Please see the PORTING file | ||
| for more information. | ||
|
|
||
| libusbx homepage: | ||
| http://libusbx.org/ | ||
|
|
||
| Developers will wish to consult the API documentation: | ||
| http://api.libusbx.org | ||
|
|
||
| Use the mailing list for questions, comments, etc: | ||
| http://mailing-list.libusbx.org | ||
|
|
||
| - Pete Batard <pete@akeo.ie> | ||
| - Hans de Goede <hdegoede@redhat.com> | ||
| - Xiaofan Chen <xiaofanc@gmail.com> | ||
| - Ludovic Rousseau <ludovic.rousseau@gmail.com> | ||
| (use the mailing list rather than mailing developers directly) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| Development contributors are listed in the AUTHORS file. Community members who | ||
| have also made significant contributions in other areas are listed below: | ||
|
|
||
| Alan Stern | ||
| Ludovic Rousseau | ||
| Tim Roberts | ||
| Xiaofan Chen |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Please see the libusbx roadmap by visiting: | ||
| https://github.com/libusbx/libusbx/issues/milestones?direction=asc&sort=due_date |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,347 @@ | ||
| #! /bin/sh | ||
| # Wrapper for compilers which do not understand '-c -o'. | ||
|
|
||
| scriptversion=2012-10-14.11; # UTC | ||
|
|
||
| # Copyright (C) 1999-2013 Free Software Foundation, Inc. | ||
| # Written by Tom Tromey <tromey@cygnus.com>. | ||
| # | ||
| # This program is free software; you can redistribute it and/or modify | ||
| # it under the terms of the GNU General Public License as published by | ||
| # the Free Software Foundation; either version 2, 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, see <http://www.gnu.org/licenses/>. | ||
|
|
||
| # As a special exception to the GNU General Public License, if you | ||
| # distribute this file as part of a program that contains a | ||
| # configuration script generated by Autoconf, you may include it under | ||
| # the same distribution terms that you use for the rest of that program. | ||
|
|
||
| # This file is maintained in Automake, please report | ||
| # bugs to <bug-automake@gnu.org> or send patches to | ||
| # <automake-patches@gnu.org>. | ||
|
|
||
| nl=' | ||
| ' | ||
|
|
||
| # We need space, tab and new line, in precisely that order. Quoting is | ||
| # there to prevent tools from complaining about whitespace usage. | ||
| IFS=" "" $nl" | ||
|
|
||
| file_conv= | ||
|
|
||
| # func_file_conv build_file lazy | ||
| # Convert a $build file to $host form and store it in $file | ||
| # Currently only supports Windows hosts. If the determined conversion | ||
| # type is listed in (the comma separated) LAZY, no conversion will | ||
| # take place. | ||
| func_file_conv () | ||
| { | ||
| file=$1 | ||
| case $file in | ||
| / | /[!/]*) # absolute file, and not a UNC file | ||
| if test -z "$file_conv"; then | ||
| # lazily determine how to convert abs files | ||
| case `uname -s` in | ||
| MINGW*) | ||
| file_conv=mingw | ||
| ;; | ||
| CYGWIN*) | ||
| file_conv=cygwin | ||
| ;; | ||
| *) | ||
| file_conv=wine | ||
| ;; | ||
| esac | ||
| fi | ||
| case $file_conv/,$2, in | ||
| *,$file_conv,*) | ||
| ;; | ||
| mingw/*) | ||
| file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` | ||
| ;; | ||
| cygwin/*) | ||
| file=`cygpath -m "$file" || echo "$file"` | ||
| ;; | ||
| wine/*) | ||
| file=`winepath -w "$file" || echo "$file"` | ||
| ;; | ||
| esac | ||
| ;; | ||
| esac | ||
| } | ||
|
|
||
| # func_cl_dashL linkdir | ||
| # Make cl look for libraries in LINKDIR | ||
| func_cl_dashL () | ||
| { | ||
| func_file_conv "$1" | ||
| if test -z "$lib_path"; then | ||
| lib_path=$file | ||
| else | ||
| lib_path="$lib_path;$file" | ||
| fi | ||
| linker_opts="$linker_opts -LIBPATH:$file" | ||
| } | ||
|
|
||
| # func_cl_dashl library | ||
| # Do a library search-path lookup for cl | ||
| func_cl_dashl () | ||
| { | ||
| lib=$1 | ||
| found=no | ||
| save_IFS=$IFS | ||
| IFS=';' | ||
| for dir in $lib_path $LIB | ||
| do | ||
| IFS=$save_IFS | ||
| if $shared && test -f "$dir/$lib.dll.lib"; then | ||
| found=yes | ||
| lib=$dir/$lib.dll.lib | ||
| break | ||
| fi | ||
| if test -f "$dir/$lib.lib"; then | ||
| found=yes | ||
| lib=$dir/$lib.lib | ||
| break | ||
| fi | ||
| if test -f "$dir/lib$lib.a"; then | ||
| found=yes | ||
| lib=$dir/lib$lib.a | ||
| break | ||
| fi | ||
| done | ||
| IFS=$save_IFS | ||
|
|
||
| if test "$found" != yes; then | ||
| lib=$lib.lib | ||
| fi | ||
| } | ||
|
|
||
| # func_cl_wrapper cl arg... | ||
| # Adjust compile command to suit cl | ||
| func_cl_wrapper () | ||
| { | ||
| # Assume a capable shell | ||
| lib_path= | ||
| shared=: | ||
| linker_opts= | ||
| for arg | ||
| do | ||
| if test -n "$eat"; then | ||
| eat= | ||
| else | ||
| case $1 in | ||
| -o) | ||
| # configure might choose to run compile as 'compile cc -o foo foo.c'. | ||
| eat=1 | ||
| case $2 in | ||
| *.o | *.[oO][bB][jJ]) | ||
| func_file_conv "$2" | ||
| set x "$@" -Fo"$file" | ||
| shift | ||
| ;; | ||
| *) | ||
| func_file_conv "$2" | ||
| set x "$@" -Fe"$file" | ||
| shift | ||
| ;; | ||
| esac | ||
| ;; | ||
| -I) | ||
| eat=1 | ||
| func_file_conv "$2" mingw | ||
| set x "$@" -I"$file" | ||
| shift | ||
| ;; | ||
| -I*) | ||
| func_file_conv "${1#-I}" mingw | ||
| set x "$@" -I"$file" | ||
| shift | ||
| ;; | ||
| -l) | ||
| eat=1 | ||
| func_cl_dashl "$2" | ||
| set x "$@" "$lib" | ||
| shift | ||
| ;; | ||
| -l*) | ||
| func_cl_dashl "${1#-l}" | ||
| set x "$@" "$lib" | ||
| shift | ||
| ;; | ||
| -L) | ||
| eat=1 | ||
| func_cl_dashL "$2" | ||
| ;; | ||
| -L*) | ||
| func_cl_dashL "${1#-L}" | ||
| ;; | ||
| -static) | ||
| shared=false | ||
| ;; | ||
| -Wl,*) | ||
| arg=${1#-Wl,} | ||
| save_ifs="$IFS"; IFS=',' | ||
| for flag in $arg; do | ||
| IFS="$save_ifs" | ||
| linker_opts="$linker_opts $flag" | ||
| done | ||
| IFS="$save_ifs" | ||
| ;; | ||
| -Xlinker) | ||
| eat=1 | ||
| linker_opts="$linker_opts $2" | ||
| ;; | ||
| -*) | ||
| set x "$@" "$1" | ||
| shift | ||
| ;; | ||
| *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) | ||
| func_file_conv "$1" | ||
| set x "$@" -Tp"$file" | ||
| shift | ||
| ;; | ||
| *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) | ||
| func_file_conv "$1" mingw | ||
| set x "$@" "$file" | ||
| shift | ||
| ;; | ||
| *) | ||
| set x "$@" "$1" | ||
| shift | ||
| ;; | ||
| esac | ||
| fi | ||
| shift | ||
| done | ||
| if test -n "$linker_opts"; then | ||
| linker_opts="-link$linker_opts" | ||
| fi | ||
| exec "$@" $linker_opts | ||
| exit 1 | ||
| } | ||
|
|
||
| eat= | ||
|
|
||
| case $1 in | ||
| '') | ||
| echo "$0: No command. Try '$0 --help' for more information." 1>&2 | ||
| exit 1; | ||
| ;; | ||
| -h | --h*) | ||
| cat <<\EOF | ||
| Usage: compile [--help] [--version] PROGRAM [ARGS] | ||
| Wrapper for compilers which do not understand '-c -o'. | ||
| Remove '-o dest.o' from ARGS, run PROGRAM with the remaining | ||
| arguments, and rename the output as expected. | ||
| If you are trying to build a whole package this is not the | ||
| right script to run: please start by reading the file 'INSTALL'. | ||
| Report bugs to <bug-automake@gnu.org>. | ||
| EOF | ||
| exit $? | ||
| ;; | ||
| -v | --v*) | ||
| echo "compile $scriptversion" | ||
| exit $? | ||
| ;; | ||
| cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) | ||
| func_cl_wrapper "$@" # Doesn't return... | ||
| ;; | ||
| esac | ||
|
|
||
| ofile= | ||
| cfile= | ||
|
|
||
| for arg | ||
| do | ||
| if test -n "$eat"; then | ||
| eat= | ||
| else | ||
| case $1 in | ||
| -o) | ||
| # configure might choose to run compile as 'compile cc -o foo foo.c'. | ||
| # So we strip '-o arg' only if arg is an object. | ||
| eat=1 | ||
| case $2 in | ||
| *.o | *.obj) | ||
| ofile=$2 | ||
| ;; | ||
| *) | ||
| set x "$@" -o "$2" | ||
| shift | ||
| ;; | ||
| esac | ||
| ;; | ||
| *.c) | ||
| cfile=$1 | ||
| set x "$@" "$1" | ||
| shift | ||
| ;; | ||
| *) | ||
| set x "$@" "$1" | ||
| shift | ||
| ;; | ||
| esac | ||
| fi | ||
| shift | ||
| done | ||
|
|
||
| if test -z "$ofile" || test -z "$cfile"; then | ||
| # If no '-o' option was seen then we might have been invoked from a | ||
| # pattern rule where we don't need one. That is ok -- this is a | ||
| # normal compilation that the losing compiler can handle. If no | ||
| # '.c' file was seen then we are probably linking. That is also | ||
| # ok. | ||
| exec "$@" | ||
| fi | ||
|
|
||
| # Name of file we expect compiler to create. | ||
| cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` | ||
|
|
||
| # Create the lock directory. | ||
| # Note: use '[/\\:.-]' here to ensure that we don't use the same name | ||
| # that we are using for the .o file. Also, base the name on the expected | ||
| # object file name, since that is what matters with a parallel build. | ||
| lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d | ||
| while true; do | ||
| if mkdir "$lockdir" >/dev/null 2>&1; then | ||
| break | ||
| fi | ||
| sleep 1 | ||
| done | ||
| # FIXME: race condition here if user kills between mkdir and trap. | ||
| trap "rmdir '$lockdir'; exit 1" 1 2 15 | ||
|
|
||
| # Run the compile. | ||
| "$@" | ||
| ret=$? | ||
|
|
||
| if test -f "$cofile"; then | ||
| test "$cofile" = "$ofile" || mv "$cofile" "$ofile" | ||
| elif test -f "${cofile}bj"; then | ||
| test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" | ||
| fi | ||
|
|
||
| rmdir "$lockdir" | ||
| exit $ret | ||
|
|
||
| # Local Variables: | ||
| # mode: shell-script | ||
| # sh-indentation: 2 | ||
| # eval: (add-hook 'write-file-hooks 'time-stamp) | ||
| # time-stamp-start: "scriptversion=" | ||
| # time-stamp-format: "%:y-%02m-%02d.%02H" | ||
| # time-stamp-time-zone: "UTC" | ||
| # time-stamp-end: "; # UTC" | ||
| # End: |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| /* config.h.in. Generated from configure.ac by autoheader. */ | ||
|
|
||
| /* Default visibility */ | ||
| #undef DEFAULT_VISIBILITY | ||
|
|
||
| /* Start with debug message logging enabled */ | ||
| #undef ENABLE_DEBUG_LOGGING | ||
|
|
||
| /* Message logging */ | ||
| #undef ENABLE_LOGGING | ||
|
|
||
| /* Define to 1 if you have the <dlfcn.h> header file. */ | ||
| #undef HAVE_DLFCN_H | ||
|
|
||
| /* Define to 1 if you have the `gettimeofday' function. */ | ||
| #undef HAVE_GETTIMEOFDAY | ||
|
|
||
| /* Define to 1 if you have the <inttypes.h> header file. */ | ||
| #undef HAVE_INTTYPES_H | ||
|
|
||
| /* Define to 1 if you have the `udev' library (-ludev). */ | ||
| #undef HAVE_LIBUDEV | ||
|
|
||
| /* Define to 1 if you have the <libudev.h> header file. */ | ||
| #undef HAVE_LIBUDEV_H | ||
|
|
||
| /* Define to 1 if you have the <linux/filter.h> header file. */ | ||
| #undef HAVE_LINUX_FILTER_H | ||
|
|
||
| /* Define to 1 if you have the <linux/netlink.h> header file. */ | ||
| #undef HAVE_LINUX_NETLINK_H | ||
|
|
||
| /* Define to 1 if you have the <memory.h> header file. */ | ||
| #undef HAVE_MEMORY_H | ||
|
|
||
| /* Define to 1 if you have the <poll.h> header file. */ | ||
| #undef HAVE_POLL_H | ||
|
|
||
| /* Define to 1 if you have the <signal.h> header file. */ | ||
| #undef HAVE_SIGNAL_H | ||
|
|
||
| /* Define to 1 if you have the <stdint.h> header file. */ | ||
| #undef HAVE_STDINT_H | ||
|
|
||
| /* Define to 1 if you have the <stdlib.h> header file. */ | ||
| #undef HAVE_STDLIB_H | ||
|
|
||
| /* Define to 1 if you have the <strings.h> header file. */ | ||
| #undef HAVE_STRINGS_H | ||
|
|
||
| /* Define to 1 if you have the <string.h> header file. */ | ||
| #undef HAVE_STRING_H | ||
|
|
||
| /* Define to 1 if the system has the type `struct timespec'. */ | ||
| #undef HAVE_STRUCT_TIMESPEC | ||
|
|
||
| /* Define to 1 if you have the <sys/stat.h> header file. */ | ||
| #undef HAVE_SYS_STAT_H | ||
|
|
||
| /* Define to 1 if you have the <sys/time.h> header file. */ | ||
| #undef HAVE_SYS_TIME_H | ||
|
|
||
| /* Define to 1 if you have the <sys/types.h> header file. */ | ||
| #undef HAVE_SYS_TYPES_H | ||
|
|
||
| /* Define to 1 if you have the <unistd.h> header file. */ | ||
| #undef HAVE_UNISTD_H | ||
|
|
||
| /* Define to the sub-directory in which libtool stores uninstalled libraries. | ||
| */ | ||
| #undef LT_OBJDIR | ||
|
|
||
| /* Define to 1 if your C compiler doesn't accept -c and -o together. */ | ||
| #undef NO_MINUS_C_MINUS_O | ||
|
|
||
| /* Darwin backend */ | ||
| #undef OS_DARWIN | ||
|
|
||
| /* Linux backend */ | ||
| #undef OS_LINUX | ||
|
|
||
| /* OpenBSD/NetBSD backend */ | ||
| #undef OS_OPENBSD | ||
|
|
||
| /* Windows backend */ | ||
| #undef OS_WINDOWS | ||
|
|
||
| /* Name of package */ | ||
| #undef PACKAGE | ||
|
|
||
| /* Define to the address where bug reports for this package should be sent. */ | ||
| #undef PACKAGE_BUGREPORT | ||
|
|
||
| /* Define to the full name of this package. */ | ||
| #undef PACKAGE_NAME | ||
|
|
||
| /* Define to the full name and version of this package. */ | ||
| #undef PACKAGE_STRING | ||
|
|
||
| /* Define to the one symbol short name of this package. */ | ||
| #undef PACKAGE_TARNAME | ||
|
|
||
| /* Define to the home page for this package. */ | ||
| #undef PACKAGE_URL | ||
|
|
||
| /* Define to the version of this package. */ | ||
| #undef PACKAGE_VERSION | ||
|
|
||
| /* type of second poll() argument */ | ||
| #undef POLL_NFDS_TYPE | ||
|
|
||
| /* Define to 1 if you have the ANSI C header files. */ | ||
| #undef STDC_HEADERS | ||
|
|
||
| /* Use POSIX Threads */ | ||
| #undef THREADS_POSIX | ||
|
|
||
| /* timerfd headers available */ | ||
| #undef USBI_TIMERFD_AVAILABLE | ||
|
|
||
| /* Use udev for device enumeration/hotplug */ | ||
| #undef USE_UDEV | ||
|
|
||
| /* Version number of package */ | ||
| #undef VERSION | ||
|
|
||
| /* Use GNU extensions */ | ||
| #undef _GNU_SOURCE | ||
|
|
||
| /* Define to `__inline__' or `__inline' if that's what the C compiler | ||
| calls it, or to nothing if 'inline' is not supported under any name. */ | ||
| #ifndef __cplusplus | ||
| #undef inline | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,249 @@ | ||
| dnl These m4 macros are whitespace sensitive and break if moved around much. | ||
| m4_define([LU_VERSION_H], m4_include([libusb/version.h])) | ||
| m4_define([LU_DEFINE_VERSION_ATOM], | ||
| [m4_define([$1], m4_bregexp(LU_VERSION_H, | ||
| [^#define\s*$1\s*\([0-9]*\).*], [\1]))]) | ||
| m4_define([LU_DEFINE_VERSION_RC_ATOM], | ||
| [m4_define([$1], m4_bregexp(LU_VERSION_H, | ||
| [^#define\s*$1\s*"\(-rc[0-9]*\)".*], [\1]))]) | ||
| dnl The m4_bregexp() returns (only) the numbers following the #define named | ||
| dnl in the first macro parameter. m4_define() then defines the name for use | ||
| dnl in AC_INIT. | ||
|
|
||
| LU_DEFINE_VERSION_ATOM([LIBUSB_MAJOR]) | ||
| LU_DEFINE_VERSION_ATOM([LIBUSB_MINOR]) | ||
| LU_DEFINE_VERSION_ATOM([LIBUSB_MICRO]) | ||
| LU_DEFINE_VERSION_RC_ATOM([LIBUSB_RC]) | ||
|
|
||
| AC_INIT([libusbx],[LIBUSB_MAJOR[.]LIBUSB_MINOR[.]LIBUSB_MICRO[]LIBUSB_RC],[libusbx-devel@lists.sourceforge.net],[libusbx],[http://libusbx.org]) | ||
|
|
||
| # Library versioning | ||
| # These numbers should be tweaked on every release. Read carefully: | ||
| # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html | ||
| # http://sourceware.org/autobook/autobook/autobook_91.html | ||
| lt_current="1" | ||
| lt_revision="0" | ||
| lt_age="1" | ||
| LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}" | ||
|
|
||
| AM_INIT_AUTOMAKE | ||
| AM_MAINTAINER_MODE | ||
|
|
||
| AC_CONFIG_SRCDIR([libusb/core.c]) | ||
| AC_CONFIG_MACRO_DIR([m4]) | ||
| AC_CONFIG_HEADERS([config.h]) | ||
| m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) | ||
|
|
||
| AC_PREREQ([2.50]) | ||
| AC_PROG_CC | ||
| LT_INIT | ||
| LT_LANG([Windows Resource]) | ||
| AC_C_INLINE | ||
| AM_PROG_CC_C_O | ||
| AC_DEFINE([_GNU_SOURCE], 1, [Use GNU extensions]) | ||
|
|
||
| LTLDFLAGS="${LTLDFLAGS} -no-undefined" | ||
|
|
||
| AC_MSG_CHECKING([operating system]) | ||
|
|
||
| case $host in | ||
| *-linux*) | ||
| AC_MSG_RESULT([Linux]) | ||
| backend="linux" | ||
| threads="posix" | ||
| ;; | ||
| *-darwin*) | ||
| AC_MSG_RESULT([Darwin/Mac OS X]) | ||
| backend="darwin" | ||
| threads="posix" | ||
| ;; | ||
| *-openbsd*) | ||
| AC_MSG_RESULT([OpenBSD]) | ||
| backend="bsd" | ||
| threads="posix" | ||
| ;; | ||
| *-netbsd*) | ||
| AC_MSG_RESULT([NetBSD (using OpenBSD backend)]) | ||
| backend="bsd" | ||
| threads="posix" | ||
| ;; | ||
| *-mingw*) | ||
| AC_MSG_RESULT([Windows]) | ||
| backend="windows" | ||
| threads="windows" | ||
| create_import_lib="yes" | ||
| AM_CFLAGS="${AM_CFLAGS} -fno-omit-frame-pointer" | ||
| ;; | ||
| *-cygwin*) | ||
| AC_MSG_RESULT([Cygwin (using Windows backend)]) | ||
| backend="windows" | ||
| threads="posix" | ||
| ;; | ||
| *) | ||
| AC_MSG_ERROR([unsupported operating system]) | ||
| esac | ||
|
|
||
| case $backend in | ||
| linux) | ||
| AC_DEFINE(OS_LINUX, 1, [Linux backend]) | ||
| AC_SUBST(OS_LINUX) | ||
| AC_SEARCH_LIBS(clock_gettime, rt, [], [], -pthread) | ||
| AC_ARG_ENABLE([udev], | ||
| [AC_HELP_STRING([--enable-udev], [use udev for device enumeration and hotplug support (recommended, default: yes)])], | ||
| [], [enable_udev="yes"]) | ||
| if test "x$enable_udev" = "xyes" ; then | ||
| # system has udev. use it or fail! | ||
| AC_CHECK_HEADERS([libudev.h],[],[AC_ERROR(["udev support requested but libudev not installed"])]) | ||
| AC_CHECK_LIB([udev], [udev_new], [], [AC_ERROR(["udev support requested but libudev not installed"])]) | ||
| AC_DEFINE(USE_UDEV, 1, [Use udev for device enumeration/hotplug]) | ||
| else | ||
| AC_CHECK_HEADERS([linux/netlink.h linux/filter.h], [], [AC_ERROR(["Linux netlink headers not found"])]) | ||
| fi | ||
| AC_SUBST(USE_UDEV) | ||
| THREAD_CFLAGS="-pthread" | ||
| LIBS="${LIBS} -pthread" | ||
| AC_CHECK_HEADERS([poll.h]) | ||
| AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) | ||
| ;; | ||
| darwin) | ||
| AC_DEFINE(OS_DARWIN, 1, [Darwin backend]) | ||
| AC_SUBST(OS_DARWIN) | ||
| LIBS="-lobjc -Wl,-framework,IOKit -Wl,-framework,CoreFoundation" | ||
| LTLDFLAGS="${LTLDFLAGS} -Wl,-prebind" | ||
| AC_CHECK_HEADERS([poll.h]) | ||
| AC_CHECK_TYPE([nfds_t], | ||
| [AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])], | ||
| [AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument])], | ||
| [#include <poll.h>]) | ||
| ;; | ||
| bsd) | ||
| AC_DEFINE(OS_OPENBSD, 1, [OpenBSD/NetBSD backend]) | ||
| AC_SUBST(OS_OPENBSD) | ||
| THREAD_CFLAGS="-pthread" | ||
| LIBS="-pthread" | ||
| AC_CHECK_HEADERS([poll.h]) | ||
| AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) | ||
| ;; | ||
| windows) | ||
| AC_DEFINE(OS_WINDOWS, 1, [Windows backend]) | ||
| AC_SUBST(OS_WINDOWS) | ||
| LIBS="" | ||
| LTLDFLAGS="${LTLDFLAGS} -avoid-version -Wl,--add-stdcall-alias" | ||
| AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument]) | ||
| ;; | ||
| esac | ||
|
|
||
| AC_SUBST(LIBS) | ||
|
|
||
| AM_CONDITIONAL(OS_LINUX, test "x$backend" = xlinux) | ||
| AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin) | ||
| AM_CONDITIONAL(OS_OPENBSD, test "x$backend" = xbsd) | ||
| AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows) | ||
| AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix) | ||
| AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = "xyes") | ||
| AM_CONDITIONAL(USE_UDEV, test "x$enable_udev" = xyes) | ||
| if test "$threads" = posix; then | ||
| AC_DEFINE(THREADS_POSIX, 1, [Use POSIX Threads]) | ||
| fi | ||
|
|
||
| # timerfd | ||
| AC_CHECK_HEADER([sys/timerfd.h], [timerfd_h=1], [timerfd_h=0]) | ||
| AC_ARG_ENABLE([timerfd], | ||
| [AS_HELP_STRING([--enable-timerfd], | ||
| [use timerfd for timing (default auto)])], | ||
| [use_timerfd=$enableval], [use_timerfd='auto']) | ||
|
|
||
| if test "x$use_timerfd" = "xyes" -a "x$timerfd_h" = "x0"; then | ||
| AC_MSG_ERROR([timerfd header not available; glibc 2.9+ required]) | ||
| fi | ||
|
|
||
| AC_CHECK_DECL([TFD_NONBLOCK], [tfd_hdr_ok=yes], [tfd_hdr_ok=no], [#include <sys/timerfd.h>]) | ||
| if test "x$use_timerfd" = "xyes" -a "x$tfd_hdr_ok" = "xno"; then | ||
| AC_MSG_ERROR([timerfd header not usable; glibc 2.9+ required]) | ||
| fi | ||
|
|
||
| AC_MSG_CHECKING([whether to use timerfd for timing]) | ||
| if test "x$use_timerfd" = "xno"; then | ||
| AC_MSG_RESULT([no (disabled by user)]) | ||
| else | ||
| if test "x$timerfd_h" = "x1" -a "x$tfd_hdr_ok" = "xyes"; then | ||
| AC_MSG_RESULT([yes]) | ||
| AC_DEFINE(USBI_TIMERFD_AVAILABLE, 1, [timerfd headers available]) | ||
| else | ||
| AC_MSG_RESULT([no (header not available)]) | ||
| fi | ||
| fi | ||
|
|
||
| AC_CHECK_TYPES(struct timespec) | ||
|
|
||
| # Message logging | ||
| AC_ARG_ENABLE([log], [AS_HELP_STRING([--disable-log], [disable all logging])], | ||
| [log_enabled=$enableval], | ||
| [log_enabled='yes']) | ||
| if test "x$log_enabled" != "xno"; then | ||
| AC_DEFINE([ENABLE_LOGGING], 1, [Message logging]) | ||
| fi | ||
|
|
||
| AC_ARG_ENABLE([debug-log], [AS_HELP_STRING([--enable-debug-log], | ||
| [start with debug message logging enabled (default n)])], | ||
| [debug_log_enabled=$enableval], | ||
| [debug_log_enabled='no']) | ||
| if test "x$debug_log_enabled" != "xno"; then | ||
| AC_DEFINE([ENABLE_DEBUG_LOGGING], 1, [Start with debug message logging enabled]) | ||
| fi | ||
|
|
||
| # Examples build | ||
| AC_ARG_ENABLE([examples-build], [AS_HELP_STRING([--enable-examples-build], | ||
| [build example applications (default n)])], | ||
| [build_examples=$enableval], | ||
| [build_examples='no']) | ||
| AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"]) | ||
|
|
||
| # Tests build | ||
| AC_ARG_ENABLE([tests-build], [AS_HELP_STRING([--enable-tests-build], | ||
| [build test applications (default n)])], | ||
| [build_tests=$enableval], | ||
| [build_tests='no']) | ||
| AM_CONDITIONAL([BUILD_TESTS], [test "x$build_tests" != "xno"]) | ||
|
|
||
| # check for -fvisibility=hidden compiler support (GCC >= 3.4) | ||
| saved_cflags="$CFLAGS" | ||
| # -Werror required for cygwin | ||
| CFLAGS="$CFLAGS -Werror -fvisibility=hidden" | ||
| AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], | ||
| [VISIBILITY_CFLAGS="-fvisibility=hidden" | ||
| AC_DEFINE([DEFAULT_VISIBILITY], [__attribute__((visibility("default")))], [Default visibility]) ], | ||
| [ VISIBILITY_CFLAGS="" | ||
| AC_DEFINE([DEFAULT_VISIBILITY], [], [Default visibility]) ], | ||
| ]) | ||
| CFLAGS="$saved_cflags" | ||
|
|
||
| # check for -Wno-pointer-sign compiler support (GCC >= 4) | ||
| saved_cflags="$CFLAGS" | ||
| CFLAGS="$CFLAGS -Wno-pointer-sign" | ||
| AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], | ||
| nopointersign_cflags="-Wno-pointer-sign", nopointersign_cflags="") | ||
| CFLAGS="$saved_cflags" | ||
|
|
||
| # sigaction not available on MinGW | ||
| AC_CHECK_FUNC([sigaction], [have_sigaction=yes], [have_sigaction=no]) | ||
| AM_CONDITIONAL([HAVE_SIGACTION], [test "x$have_sigaction" = "xyes"]) | ||
|
|
||
| # headers not available on all platforms but required on others | ||
| AC_CHECK_HEADERS([sys/time.h]) | ||
| AC_CHECK_FUNCS(gettimeofday) | ||
| AC_CHECK_HEADERS([signal.h]) | ||
|
|
||
| AM_CFLAGS="${AM_CFLAGS} -std=gnu99 -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow ${THREAD_CFLAGS} ${VISIBILITY_CFLAGS}" | ||
|
|
||
| AC_SUBST(AM_CFLAGS) | ||
| AC_SUBST(LTLDFLAGS) | ||
|
|
||
| AC_CONFIG_FILES([libusb-1.0.pc]) | ||
| AC_CONFIG_FILES([Makefile]) | ||
| AC_CONFIG_FILES([libusb/Makefile]) | ||
| AC_CONFIG_FILES([examples/Makefile]) | ||
| AC_CONFIG_FILES([tests/Makefile]) | ||
| AC_CONFIG_FILES([doc/Makefile]) | ||
| AC_CONFIG_FILES([doc/doxygen.cfg]) | ||
| AC_OUTPUT |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| prefix=@prefix@ | ||
| exec_prefix=@exec_prefix@ | ||
| libdir=@libdir@ | ||
| includedir=@includedir@ | ||
|
|
||
| Name: libusbx-1.0 | ||
| Description: C API for USB device access from Linux, Mac OS X, Windows and OpenBSD/NetBSD userspace | ||
| Version: @VERSION@ | ||
| Libs: -L${libdir} -lusb-1.0 | ||
| Libs.private: @LIBS@ | ||
| Cflags: -I${includedir}/libusb-1.0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| all: libusb-1.0.la libusb-1.0.dll | ||
|
|
||
| lib_LTLIBRARIES = libusb-1.0.la | ||
|
|
||
| POSIX_POLL_SRC = os/poll_posix.c | ||
| LINUX_USBFS_SRC = os/linux_usbfs.c | ||
| DARWIN_USB_SRC = os/darwin_usb.c | ||
| OPENBSD_USB_SRC = os/openbsd_usb.c | ||
| WINDOWS_USB_SRC = os/poll_windows.c os/windows_usb.c libusb-1.0.rc libusb-1.0.def | ||
| WINCE_USB_SRC = os/wince_usb.c os/wince_usb.h | ||
|
|
||
| EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \ | ||
| $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \ | ||
| $(POSIX_POLL_SRC) \ | ||
| os/threads_posix.c os/threads_windows.c \ | ||
| os/linux_udev.c os/linux_netlink.c | ||
|
|
||
| if OS_LINUX | ||
|
|
||
| if USE_UDEV | ||
| OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \ | ||
| os/linux_udev.c | ||
| else | ||
| OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \ | ||
| os/linux_netlink.c | ||
| endif | ||
|
|
||
| endif | ||
|
|
||
| if OS_DARWIN | ||
| OS_SRC = $(DARWIN_USB_SRC) $(POSIX_POLL_SRC) | ||
| AM_CFLAGS_EXT = -no-cpp-precomp | ||
| endif | ||
|
|
||
| if OS_OPENBSD | ||
| OS_SRC = $(OPENBSD_USB_SRC) $(POSIX_POLL_SRC) | ||
| endif | ||
|
|
||
| if OS_WINDOWS | ||
| OS_SRC = $(WINDOWS_USB_SRC) | ||
|
|
||
| .rc.lo: | ||
| $(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@ | ||
|
|
||
| libusb-1.0.rc: version.h version_nano.h | ||
| endif | ||
|
|
||
| libusb-1.0.dll: libusb-1.0.def | ||
| if CREATE_IMPORT_LIB | ||
| # Rebuild the import lib from the .def so that MS and MinGW DLLs can be interchanged | ||
| $(AM_V_GEN)$(DLLTOOL) $(DLLTOOLFLAGS) --kill-at --input-def $(srcdir)/libusb-1.0.def --dllname $@ --output-lib .libs/$@.a | ||
| endif | ||
|
|
||
| if THREADS_POSIX | ||
| THREADS_SRC = os/threads_posix.h os/threads_posix.c | ||
| else | ||
| THREADS_SRC = os/threads_windows.h os/threads_windows.c | ||
| endif | ||
|
|
||
| libusb_1_0_la_CFLAGS = $(AM_CFLAGS) | ||
| libusb_1_0_la_LDFLAGS = $(LTLDFLAGS) | ||
| libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c strerror.c sync.c \ | ||
| os/linux_usbfs.h os/darwin_usb.h os/windows_usb.h os/windows_common.h \ | ||
| hotplug.h hotplug.c $(THREADS_SRC) $(OS_SRC) \ | ||
| os/poll_posix.h os/poll_windows.h | ||
|
|
||
| hdrdir = $(includedir)/libusb-1.0 | ||
| hdr_HEADERS = libusb.h |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,320 @@ | ||
| /* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ | ||
| /* | ||
| * Hotplug functions for libusbx | ||
| * Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com> | ||
| * Copyright © 2012-2013 Peter Stuge <peter@stuge.se> | ||
| * | ||
| * 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 <config.h> | ||
|
|
||
| #include <errno.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #ifdef HAVE_SYS_TYPES_H | ||
| #include <sys/types.h> | ||
| #endif | ||
| #include <assert.h> | ||
|
|
||
| #include "libusbi.h" | ||
| #include "hotplug.h" | ||
|
|
||
| /** | ||
| * @defgroup hotplug Device hotplug event notification | ||
| * This page details how to use the libusb hotplug interface, where available. | ||
| * | ||
| * Be mindful that not all platforms currently implement hotplug notification and | ||
| * that you should first call on \ref libusb_has_capability() with parameter | ||
| * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available. | ||
| * | ||
| * \page hotplug Device hotplug event notification | ||
| * | ||
| * \section intro Introduction | ||
| * | ||
| * Version 1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102, has added support | ||
| * for hotplug events on <b>some</b> platforms (you should test if your platform | ||
| * supports hotplug notification by calling \ref libusb_has_capability() with | ||
| * parameter \ref LIBUSB_CAP_HAS_HOTPLUG). | ||
| * | ||
| * This interface allows you to request notification for the arrival and departure | ||
| * of matching USB devices. | ||
| * | ||
| * To receive hotplug notification you register a callback by calling | ||
| * \ref libusb_hotplug_register_callback(). This function will optionally return | ||
| * a handle that can be passed to \ref libusb_hotplug_deregister_callback(). | ||
| * | ||
| * A callback function must return an int (0 or 1) indicating whether the callback is | ||
| * expecting additional events. Returning 0 will rearm the callback and 1 will cause | ||
| * the callback to be deregistered. | ||
| * | ||
| * Callbacks for a particular context are automatically deregistered by libusb_exit(). | ||
| * | ||
| * As of 1.0.16 there are two supported hotplug events: | ||
| * - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use | ||
| * - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available | ||
| * | ||
| * A hotplug event can listen for either or both of these events. | ||
| * | ||
| * Note: If you receive notification that a device has left and you have any | ||
| * a libusb_device_handles for the device it is up to you to call libusb_close() | ||
| * on each handle to free up any remaining resources associated with the device. | ||
| * Once a device has left any libusb_device_handle associated with the device | ||
| * are invalid and will remain so even if the device comes back. | ||
| * | ||
| * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered | ||
| * safe to call any libusbx function that takes a libusb_device. On the other hand, | ||
| * when handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function | ||
| * is libusb_get_device_descriptor(). | ||
| * | ||
| * The following code provides an example of the usage of the hotplug interface: | ||
| \code | ||
| static int count = 0; | ||
| int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, | ||
| libusb_hotplug_event event, void *user_data) { | ||
| static libusb_device_handle *handle = NULL; | ||
| struct libusb_device_descriptor desc; | ||
| int rc; | ||
| (void)libusb_get_device_descriptor(dev, &desc); | ||
| if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) { | ||
| rc = libusb_open(dev, &handle); | ||
| if (LIBUSB_SUCCESS != rc) { | ||
| printf("Could not open USB device\n"); | ||
| } | ||
| } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { | ||
| if (handle) { | ||
| libusb_close(handle); | ||
| handle = NULL; | ||
| } | ||
| } else { | ||
| printf("Unhandled event %d\n", event); | ||
| } | ||
| count++; | ||
| return 0; | ||
| } | ||
| int main (void) { | ||
| libusb_hotplug_callback_handle handle; | ||
| int rc; | ||
| libusb_init(NULL); | ||
| rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | | ||
| LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005, | ||
| LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL, | ||
| &handle); | ||
| if (LIBUSB_SUCCESS != rc) { | ||
| printf("Error creating a hotplug callback\n"); | ||
| libusb_exit(NULL); | ||
| return EXIT_FAILURE; | ||
| } | ||
| while (count < 2) { | ||
| usleep(10000); | ||
| } | ||
| libusb_hotplug_deregister_callback(handle); | ||
| libusb_exit(NULL); | ||
| return 0; | ||
| } | ||
| \endcode | ||
| */ | ||
|
|
||
| static int usbi_hotplug_match_cb (struct libusb_context *ctx, | ||
| struct libusb_device *dev, libusb_hotplug_event event, | ||
| struct libusb_hotplug_callback *hotplug_cb) | ||
| { | ||
| /* Handle lazy deregistration of callback */ | ||
| if (hotplug_cb->needs_free) { | ||
| /* Free callback */ | ||
| return 1; | ||
| } | ||
|
|
||
| if (!(hotplug_cb->events & event)) { | ||
| return 0; | ||
| } | ||
|
|
||
| if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id && | ||
| hotplug_cb->vendor_id != dev->device_descriptor.idVendor) { | ||
| return 0; | ||
| } | ||
|
|
||
| if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id && | ||
| hotplug_cb->product_id != dev->device_descriptor.idProduct) { | ||
| return 0; | ||
| } | ||
|
|
||
| if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class && | ||
| hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) { | ||
| return 0; | ||
| } | ||
|
|
||
| return hotplug_cb->cb (ctx == usbi_default_context ? NULL : ctx, | ||
| dev, event, hotplug_cb->user_data); | ||
| } | ||
|
|
||
| void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, | ||
| libusb_hotplug_event event) | ||
| { | ||
| struct libusb_hotplug_callback *hotplug_cb, *next; | ||
| int ret; | ||
|
|
||
| usbi_mutex_lock(&ctx->hotplug_cbs_lock); | ||
|
|
||
| list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { | ||
| usbi_mutex_unlock(&ctx->hotplug_cbs_lock); | ||
| ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb); | ||
| usbi_mutex_lock(&ctx->hotplug_cbs_lock); | ||
|
|
||
| if (ret) { | ||
| list_del(&hotplug_cb->list); | ||
| free(hotplug_cb); | ||
| } | ||
| } | ||
|
|
||
| usbi_mutex_unlock(&ctx->hotplug_cbs_lock); | ||
|
|
||
| /* loop through and disconnect all open handles for this device */ | ||
| if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { | ||
| struct libusb_device_handle *handle; | ||
|
|
||
| usbi_mutex_lock(&ctx->open_devs_lock); | ||
| list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) { | ||
| if (dev == handle->dev) { | ||
| usbi_handle_disconnect (handle); | ||
| } | ||
| } | ||
| usbi_mutex_unlock(&ctx->open_devs_lock); | ||
| } | ||
| } | ||
|
|
||
| int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, | ||
| libusb_hotplug_event events, libusb_hotplug_flag flags, | ||
| int vendor_id, int product_id, int dev_class, | ||
| libusb_hotplug_callback_fn cb_fn, void *user_data, | ||
| libusb_hotplug_callback_handle *handle) | ||
| { | ||
| libusb_hotplug_callback *new_callback; | ||
| static int handle_id = 1; | ||
|
|
||
| /* check for hotplug support */ | ||
| if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { | ||
| return LIBUSB_ERROR_NOT_SUPPORTED; | ||
| } | ||
|
|
||
| /* check for sane values */ | ||
| if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) || | ||
| (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) || | ||
| (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) || | ||
| !cb_fn) { | ||
| return LIBUSB_ERROR_INVALID_PARAM; | ||
| } | ||
|
|
||
| USBI_GET_CONTEXT(ctx); | ||
|
|
||
| new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback)); | ||
| if (!new_callback) { | ||
| return LIBUSB_ERROR_NO_MEM; | ||
| } | ||
|
|
||
| new_callback->ctx = ctx; | ||
| new_callback->vendor_id = vendor_id; | ||
| new_callback->product_id = product_id; | ||
| new_callback->dev_class = dev_class; | ||
| new_callback->flags = flags; | ||
| new_callback->events = events; | ||
| new_callback->cb = cb_fn; | ||
| new_callback->user_data = user_data; | ||
| new_callback->needs_free = 0; | ||
|
|
||
| usbi_mutex_lock(&ctx->hotplug_cbs_lock); | ||
|
|
||
| /* protect the handle by the context hotplug lock. it doesn't matter if the same handle | ||
| * is used for different contexts only that the handle is unique for this context */ | ||
| new_callback->handle = handle_id++; | ||
|
|
||
| list_add(&new_callback->list, &ctx->hotplug_cbs); | ||
|
|
||
| if (flags & LIBUSB_HOTPLUG_ENUMERATE) { | ||
| struct libusb_device *dev; | ||
|
|
||
| usbi_mutex_lock(&ctx->usb_devs_lock); | ||
|
|
||
| list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) { | ||
| (void) usbi_hotplug_match_cb (ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, new_callback); | ||
| } | ||
|
|
||
| usbi_mutex_unlock(&ctx->usb_devs_lock); | ||
| } | ||
|
|
||
| usbi_mutex_unlock(&ctx->hotplug_cbs_lock); | ||
|
|
||
| if (handle) { | ||
| *handle = new_callback->handle; | ||
| } | ||
|
|
||
| return LIBUSB_SUCCESS; | ||
| } | ||
|
|
||
| void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx, | ||
| libusb_hotplug_callback_handle handle) | ||
| { | ||
| struct libusb_hotplug_callback *hotplug_cb; | ||
| libusb_hotplug_message message; | ||
| ssize_t ret; | ||
|
|
||
| /* check for hotplug support */ | ||
| if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { | ||
| return; | ||
| } | ||
|
|
||
| USBI_GET_CONTEXT(ctx); | ||
|
|
||
| usbi_mutex_lock(&ctx->hotplug_cbs_lock); | ||
| list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, | ||
| struct libusb_hotplug_callback) { | ||
| if (handle == hotplug_cb->handle) { | ||
| /* Mark this callback for deregistration */ | ||
| hotplug_cb->needs_free = 1; | ||
| } | ||
| } | ||
| usbi_mutex_unlock(&ctx->hotplug_cbs_lock); | ||
|
|
||
| /* wakeup handle_events to do the actual free */ | ||
| memset(&message, 0, sizeof(message)); | ||
| ret = usbi_write(ctx->hotplug_pipe[1], &message, sizeof(message)); | ||
| if (sizeof(message) != ret) { | ||
| usbi_err(ctx, "error writing hotplug message"); | ||
| } | ||
| } | ||
|
|
||
| void usbi_hotplug_deregister_all(struct libusb_context *ctx) { | ||
| struct libusb_hotplug_callback *hotplug_cb, *next; | ||
|
|
||
| usbi_mutex_lock(&ctx->hotplug_cbs_lock); | ||
| list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, | ||
| struct libusb_hotplug_callback) { | ||
| list_del(&hotplug_cb->list); | ||
| free(hotplug_cb); | ||
| } | ||
|
|
||
| usbi_mutex_unlock(&ctx->hotplug_cbs_lock); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| /* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ | ||
| /* | ||
| * Hotplug support for libusbx | ||
| * Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com> | ||
| * Copyright © 2012-2013 Peter Stuge <peter@stuge.se> | ||
| * | ||
| * 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 | ||
| */ | ||
|
|
||
| #if !defined(USBI_HOTPLUG_H) | ||
| #define USBI_HOTPLUG_H | ||
|
|
||
| #ifndef LIBUSBI_H | ||
| #include "libusbi.h" | ||
| #endif | ||
|
|
||
| /** \ingroup hotplug | ||
| * The hotplug callback structure. The user populates this structure with | ||
| * libusb_hotplug_prepare_callback() and then calls libusb_hotplug_register_callback() | ||
| * to receive notification of hotplug events. | ||
| */ | ||
| struct libusb_hotplug_callback { | ||
| /** Context this callback is associated with */ | ||
| struct libusb_context *ctx; | ||
|
|
||
| /** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ | ||
| int vendor_id; | ||
|
|
||
| /** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ | ||
| int product_id; | ||
|
|
||
| /** Device class to match or LIBUSB_HOTPLUG_MATCH_ANY */ | ||
| int dev_class; | ||
|
|
||
| /** Hotplug callback flags */ | ||
| libusb_hotplug_flag flags; | ||
|
|
||
| /** Event(s) that will trigger this callback */ | ||
| libusb_hotplug_event events; | ||
|
|
||
| /** Callback function to invoke for matching event/device */ | ||
| libusb_hotplug_callback_fn cb; | ||
|
|
||
| /** Handle for this callback (used to match on deregister) */ | ||
| libusb_hotplug_callback_handle handle; | ||
|
|
||
| /** User data that will be passed to the callback function */ | ||
| void *user_data; | ||
|
|
||
| /** Callback is marked for deletion */ | ||
| int needs_free; | ||
|
|
||
| /** List this callback is registered in (ctx->hotplug_cbs) */ | ||
| struct list_head list; | ||
| }; | ||
|
|
||
| typedef struct libusb_hotplug_callback libusb_hotplug_callback; | ||
|
|
||
| struct libusb_hotplug_message { | ||
| libusb_hotplug_event event; | ||
| struct libusb_device *device; | ||
| }; | ||
|
|
||
| typedef struct libusb_hotplug_message libusb_hotplug_message; | ||
|
|
||
| void usbi_hotplug_deregister_all(struct libusb_context *ctx); | ||
| void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, | ||
| libusb_hotplug_event event); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| LIBRARY "libusb-1.0.dll" | ||
| EXPORTS | ||
| 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_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_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_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_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_interface_alt_setting | ||
| libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting | ||
| 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_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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| /* | ||
| * For Windows: input this file to the Resoure Compiler to produce a binary | ||
| * .res file. This is then embedded in the resultant library (like any other | ||
| * compilation object). | ||
| * The information can then be queried using standard APIs and can also be | ||
| * viewed with utilities such as Windows Explorer. | ||
| */ | ||
| #ifndef _WIN32_WCE | ||
| #include "winresrc.h" | ||
| #endif | ||
|
|
||
| #include "version.h" | ||
| #ifndef LIBUSB_VERSIONSTRING | ||
| #define LU_STR(s) #s | ||
| #define LU_XSTR(s) LU_STR(s) | ||
| #if LIBUSB_NANO > 0 | ||
| #define LIBUSB_VERSIONSTRING \ | ||
| LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." \ | ||
| LU_XSTR(LIBUSB_MICRO) "." LU_XSTR(LIBUSB_NANO) LIBUSB_RC "\0" | ||
| #else | ||
| #define LIBUSB_VERSIONSTRING \ | ||
| LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." \ | ||
| LU_XSTR(LIBUSB_MICRO) LIBUSB_RC "\0" | ||
| #endif | ||
| #endif | ||
|
|
||
| VS_VERSION_INFO VERSIONINFO | ||
| FILEVERSION LIBUSB_MAJOR,LIBUSB_MINOR,LIBUSB_MICRO,LIBUSB_NANO | ||
| PRODUCTVERSION LIBUSB_MAJOR,LIBUSB_MINOR,LIBUSB_MICRO,LIBUSB_NANO | ||
| FILEFLAGSMASK 0x3fL | ||
| #ifdef _DEBUG | ||
| FILEFLAGS 0x1L | ||
| #else | ||
| FILEFLAGS 0x0L | ||
| #endif | ||
| FILEOS 0x40004L | ||
| FILETYPE 0x2L | ||
| FILESUBTYPE 0x0L | ||
| BEGIN | ||
| BLOCK "StringFileInfo" | ||
| BEGIN | ||
| BLOCK "040904b0" | ||
| BEGIN | ||
| VALUE "CompanyName", "libusbx.org\0" | ||
| VALUE "FileDescription", "C library for writing portable USB drivers in userspace\0" | ||
| VALUE "FileVersion", LIBUSB_VERSIONSTRING | ||
| VALUE "InternalName", "libusb\0" | ||
| VALUE "LegalCopyright", "See individual source files, GNU LGPL v2.1 or later.\0" | ||
| VALUE "LegalTrademarks", "http://www.gnu.org/licenses/lgpl-2.1.html\0" | ||
| VALUE "OriginalFilename", "libusb-1.0.dll\0" | ||
| VALUE "PrivateBuild", "\0" | ||
| VALUE "ProductName", "libusb-1.0\0" | ||
| VALUE "ProductVersion", LIBUSB_VERSIONSTRING | ||
| VALUE "SpecialBuild", "\0" | ||
| END | ||
| END | ||
| BLOCK "VarFileInfo" | ||
| BEGIN | ||
| VALUE "Translation", 0x409, 1200 | ||
| END | ||
| END |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| /* | ||
| * darwin backend for libusbx 1.0 | ||
| * Copyright © 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net> | ||
| * | ||
| * 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 | ||
| */ | ||
|
|
||
| #if !defined(LIBUSB_DARWIN_H) | ||
| #define LIBUSB_DARWIN_H | ||
|
|
||
| #include "libusbi.h" | ||
|
|
||
| #include <IOKit/IOTypes.h> | ||
| #include <IOKit/IOCFBundle.h> | ||
| #include <IOKit/usb/IOUSBLib.h> | ||
| #include <IOKit/IOCFPlugIn.h> | ||
|
|
||
| /* IOUSBInterfaceInferface */ | ||
| #if defined (kIOUSBInterfaceInterfaceID550) | ||
|
|
||
| #define usb_interface_t IOUSBInterfaceInterface550 | ||
| #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 | ||
| #define InterfaceVersion 550 | ||
|
|
||
| #elif defined (kIOUSBInterfaceInterfaceID500) | ||
|
|
||
| #define usb_interface_t IOUSBInterfaceInterface500 | ||
| #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500 | ||
| #define InterfaceVersion 500 | ||
|
|
||
| #elif defined (kIOUSBInterfaceInterfaceID300) | ||
|
|
||
| #define usb_interface_t IOUSBInterfaceInterface300 | ||
| #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300 | ||
| #define InterfaceVersion 300 | ||
|
|
||
| #elif defined (kIOUSBInterfaceInterfaceID245) | ||
|
|
||
| #define usb_interface_t IOUSBInterfaceInterface245 | ||
| #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245 | ||
| #define InterfaceVersion 245 | ||
|
|
||
| #elif defined (kIOUSBInterfaceInterfaceID220) | ||
|
|
||
| #define usb_interface_t IOUSBInterfaceInterface220 | ||
| #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 | ||
| #define InterfaceVersion 220 | ||
|
|
||
| #else | ||
|
|
||
| #error "IOUSBFamily is too old. Please upgrade your OS" | ||
|
|
||
| #endif | ||
|
|
||
| /* IOUSBDeviceInterface */ | ||
| #if defined (kIOUSBDeviceInterfaceID500) | ||
|
|
||
| #define usb_device_t IOUSBDeviceInterface500 | ||
| #define DeviceInterfaceID kIOUSBDeviceInterfaceID500 | ||
| #define DeviceVersion 500 | ||
|
|
||
| #elif defined (kIOUSBDeviceInterfaceID320) | ||
|
|
||
| #define usb_device_t IOUSBDeviceInterface320 | ||
| #define DeviceInterfaceID kIOUSBDeviceInterfaceID320 | ||
| #define DeviceVersion 320 | ||
|
|
||
| #elif defined (kIOUSBDeviceInterfaceID300) | ||
|
|
||
| #define usb_device_t IOUSBDeviceInterface300 | ||
| #define DeviceInterfaceID kIOUSBDeviceInterfaceID300 | ||
| #define DeviceVersion 300 | ||
|
|
||
| #elif defined (kIOUSBDeviceInterfaceID245) | ||
|
|
||
| #define usb_device_t IOUSBDeviceInterface245 | ||
| #define DeviceInterfaceID kIOUSBDeviceInterfaceID245 | ||
| #define DeviceVersion 245 | ||
|
|
||
| #elif defined (kIOUSBDeviceInterfaceID220) | ||
| #define usb_device_t IOUSBDeviceInterface197 | ||
| #define DeviceInterfaceID kIOUSBDeviceInterfaceID197 | ||
| #define DeviceVersion 197 | ||
|
|
||
| #else | ||
|
|
||
| #error "IOUSBFamily is too old. Please upgrade your OS" | ||
|
|
||
| #endif | ||
|
|
||
| #if !defined(IO_OBJECT_NULL) | ||
| #define IO_OBJECT_NULL ((io_object_t) 0) | ||
| #endif | ||
|
|
||
| typedef IOCFPlugInInterface *io_cf_plugin_ref_t; | ||
| typedef IONotificationPortRef io_notification_port_t; | ||
|
|
||
| /* private structures */ | ||
| struct darwin_cached_device { | ||
| struct list_head list; | ||
| IOUSBDeviceDescriptor dev_descriptor; | ||
| UInt32 location; | ||
| UInt64 parent_session; | ||
| UInt64 session; | ||
| UInt16 address; | ||
| char sys_path[21]; | ||
| usb_device_t **device; | ||
| int open_count; | ||
| UInt8 first_config, active_config, port; | ||
| int can_enumerate; | ||
| int refcount; | ||
| }; | ||
|
|
||
| struct darwin_device_priv { | ||
| struct darwin_cached_device *dev; | ||
| }; | ||
|
|
||
| struct darwin_device_handle_priv { | ||
| int is_open; | ||
| CFRunLoopSourceRef cfSource; | ||
| int fds[2]; | ||
|
|
||
| struct darwin_interface { | ||
| usb_interface_t **interface; | ||
| uint8_t num_endpoints; | ||
| CFRunLoopSourceRef cfSource; | ||
| uint64_t frames[256]; | ||
| uint8_t endpoint_addrs[USB_MAXENDPOINTS]; | ||
| } interfaces[USB_MAXINTERFACES]; | ||
| }; | ||
|
|
||
| struct darwin_transfer_priv { | ||
| /* Isoc */ | ||
| IOUSBIsocFrame *isoc_framelist; | ||
| int num_iso_packets; | ||
|
|
||
| /* Control */ | ||
| IOUSBDevRequestTO req; | ||
|
|
||
| /* Bulk */ | ||
| }; | ||
|
|
||
| /* structure for signaling io completion */ | ||
| struct darwin_msg_async_io_complete { | ||
| struct usbi_transfer *itransfer; | ||
| IOReturn result; | ||
| UInt32 size; | ||
| }; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,254 @@ | ||
| /* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ | ||
| /* | ||
| * Linux usbfs backend for libusb | ||
| * Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org> | ||
| * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com> | ||
| * Copyright (c) 2013 Nathan Hjelm <hjelmn@mac.com> | ||
| * | ||
| * 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 "config.h" | ||
| #include <ctype.h> | ||
| #include <dirent.h> | ||
| #include <errno.h> | ||
| #include <fcntl.h> | ||
| #include <poll.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <sys/types.h> | ||
| #include <sys/socket.h> | ||
| #include <arpa/inet.h> | ||
|
|
||
| #include "libusb.h" | ||
| #include "libusbi.h" | ||
| #include "linux_usbfs.h" | ||
|
|
||
| #include <linux/netlink.h> | ||
| #include <linux/filter.h> | ||
|
|
||
| #define KERNEL 1 | ||
|
|
||
| static int linux_netlink_socket = -1; | ||
| static pthread_t libusb_linux_event_thread; | ||
|
|
||
| static void *linux_netlink_event_thread_main(void *arg); | ||
|
|
||
| struct sockaddr_nl snl = { .nl_family=AF_NETLINK, .nl_groups=KERNEL }; | ||
|
|
||
| int linux_netlink_start_event_monitor(void) | ||
| { | ||
| int ret; | ||
|
|
||
| snl.nl_groups = KERNEL; | ||
|
|
||
| linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); | ||
| if (-1 == linux_netlink_socket) { | ||
| return LIBUSB_ERROR_OTHER; | ||
| } | ||
|
|
||
| ret = bind(linux_netlink_socket, (struct sockaddr *) &snl, sizeof(snl)); | ||
| if (0 != ret) { | ||
| return LIBUSB_ERROR_OTHER; | ||
| } | ||
|
|
||
| /* TODO -- add authentication */ | ||
| /* setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); */ | ||
|
|
||
| ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL); | ||
| if (0 != ret) { | ||
| return LIBUSB_ERROR_OTHER; | ||
| } | ||
|
|
||
| return LIBUSB_SUCCESS; | ||
| } | ||
|
|
||
| int linux_netlink_stop_event_monitor(void) | ||
| { | ||
| int r; | ||
|
|
||
| if (-1 == linux_netlink_socket) { | ||
| /* already closed. nothing to do */ | ||
| return LIBUSB_SUCCESS; | ||
| } | ||
|
|
||
| r = close(linux_netlink_socket); | ||
| if (0 > r) { | ||
| usbi_err(NULL, "error closing netlink socket. %s", strerror(errno)); | ||
| return LIBUSB_ERROR_OTHER; | ||
| } | ||
|
|
||
| pthread_cancel(libusb_linux_event_thread); | ||
|
|
||
| linux_netlink_socket = -1; | ||
|
|
||
| return LIBUSB_SUCCESS; | ||
| } | ||
|
|
||
| static const char *netlink_message_parse (const char *buffer, size_t len, const char *key) | ||
| { | ||
| size_t keylen = strlen(key); | ||
| size_t offset; | ||
|
|
||
| for (offset = 0 ; offset < len && '\0' != buffer[offset] ; offset += strlen(buffer + offset) + 1) { | ||
| if (0 == strncmp(buffer + offset, key, keylen) && | ||
| '=' == buffer[offset + keylen]) { | ||
| return buffer + offset + keylen + 1; | ||
| } | ||
| } | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| /* parse parts of netlink message common to both libudev and the kernel */ | ||
| static int linux_netlink_parse(char *buffer, size_t len, int *detached, const char **sys_name, | ||
| uint8_t *busnum, uint8_t *devaddr) { | ||
| const char *tmp; | ||
| int i; | ||
|
|
||
| errno = 0; | ||
|
|
||
| *sys_name = NULL; | ||
| *detached = 0; | ||
| *busnum = 0; | ||
| *devaddr = 0; | ||
|
|
||
| tmp = netlink_message_parse((const char *) buffer, len, "ACTION"); | ||
| if (tmp == NULL) | ||
| return -1; | ||
| if (0 == strcmp(tmp, "remove")) { | ||
| *detached = 1; | ||
| } else if (0 != strcmp(tmp, "add")) { | ||
| usbi_dbg("unknown device action %s", tmp); | ||
| return -1; | ||
| } | ||
|
|
||
| /* check that this is a usb message */ | ||
| tmp = netlink_message_parse(buffer, len, "SUBSYSTEM"); | ||
| if (NULL == tmp || 0 != strcmp(tmp, "usb")) { | ||
| /* not usb. ignore */ | ||
| return -1; | ||
| } | ||
|
|
||
| tmp = netlink_message_parse(buffer, len, "BUSNUM"); | ||
| if (NULL == tmp) { | ||
| /* no bus number (likely a usb interface). ignore*/ | ||
| return -1; | ||
| } | ||
|
|
||
| *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); | ||
| if (errno) { | ||
| errno = 0; | ||
| return -1; | ||
| } | ||
|
|
||
| tmp = netlink_message_parse(buffer, len, "DEVNUM"); | ||
| if (NULL == tmp) { | ||
| return -1; | ||
| } | ||
|
|
||
| *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); | ||
| if (errno) { | ||
| errno = 0; | ||
| return -1; | ||
| } | ||
|
|
||
| tmp = netlink_message_parse(buffer, len, "DEVPATH"); | ||
| if (NULL == tmp) { | ||
| return -1; | ||
| } | ||
|
|
||
| for (i = strlen(tmp) - 1 ; i ; --i) { | ||
| if ('/' ==tmp[i]) { | ||
| *sys_name = tmp + i + 1; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| /* found a usb device */ | ||
| return 0; | ||
| } | ||
|
|
||
| static int linux_netlink_read_message(void) | ||
| { | ||
| unsigned char buffer[1024]; | ||
| struct iovec iov = {.iov_base = buffer, .iov_len = sizeof(buffer)}; | ||
| struct msghdr meh = { .msg_iov=&iov, .msg_iovlen=1, | ||
| .msg_name=&snl, .msg_namelen=sizeof(snl) }; | ||
| const char *sys_name = NULL; | ||
| uint8_t busnum, devaddr; | ||
| int detached, r; | ||
| size_t len; | ||
|
|
||
| /* read netlink message */ | ||
| memset(buffer, 0, sizeof(buffer)); | ||
| len = recvmsg(linux_netlink_socket, &meh, 0); | ||
| if (len < 32) { | ||
| if (errno != EAGAIN) | ||
| usbi_dbg("error recieving message from netlink"); | ||
| return -1; | ||
| } | ||
|
|
||
| /* TODO -- authenticate this message is from the kernel or udevd */ | ||
|
|
||
| r = linux_netlink_parse(buffer, len, &detached, &sys_name, | ||
| &busnum, &devaddr); | ||
| if (r) | ||
| return r; | ||
|
|
||
| usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s", | ||
| busnum, devaddr, sys_name, detached ? "yes" : "no"); | ||
|
|
||
| /* signal device is available (or not) to all contexts */ | ||
| if (detached) | ||
| linux_hotplug_disconnected(busnum, devaddr, sys_name); | ||
| else | ||
| linux_hotplug_enumerate(busnum, devaddr, sys_name); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static void *linux_netlink_event_thread_main(void *arg) | ||
| { | ||
| struct pollfd fds = {.fd = linux_netlink_socket, | ||
| .events = POLLIN}; | ||
|
|
||
| /* silence compiler warning */ | ||
| (void) arg; | ||
|
|
||
| while (1 == poll(&fds, 1, -1)) { | ||
| if (POLLIN != fds.revents) { | ||
| break; | ||
| } | ||
|
|
||
| usbi_mutex_static_lock(&linux_hotplug_lock); | ||
| linux_netlink_read_message(); | ||
| usbi_mutex_static_unlock(&linux_hotplug_lock); | ||
| } | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| void linux_netlink_hotplug_poll(void) | ||
| { | ||
| int r; | ||
|
|
||
| usbi_mutex_static_lock(&linux_hotplug_lock); | ||
| do { | ||
| r = linux_netlink_read_message(); | ||
| } while (r == 0); | ||
| usbi_mutex_static_unlock(&linux_hotplug_lock); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,273 @@ | ||
| /* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ | ||
| /* | ||
| * Linux usbfs backend for libusb | ||
| * Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org> | ||
| * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com> | ||
| * Copyright (c) 2012-2013 Nathan Hjelm <hjelmn@mac.com> | ||
| * | ||
| * 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 "config.h" | ||
|
|
||
| #include <assert.h> | ||
| #include <ctype.h> | ||
| #include <dirent.h> | ||
| #include <errno.h> | ||
| #include <fcntl.h> | ||
| #include <poll.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <sys/ioctl.h> | ||
| #include <sys/stat.h> | ||
| #include <sys/types.h> | ||
| #include <sys/utsname.h> | ||
| #include <sys/socket.h> | ||
| #include <unistd.h> | ||
| #include <libudev.h> | ||
|
|
||
| #include "libusb.h" | ||
| #include "libusbi.h" | ||
| #include "linux_usbfs.h" | ||
|
|
||
| /* udev context */ | ||
| static struct udev *udev_ctx = NULL; | ||
| static int udev_monitor_fd = -1; | ||
| static struct udev_monitor *udev_monitor = NULL; | ||
| static pthread_t linux_event_thread; | ||
|
|
||
| static void udev_hotplug_event(struct udev_device* udev_dev); | ||
| static void *linux_udev_event_thread_main(void *arg); | ||
|
|
||
| int linux_udev_start_event_monitor(void) | ||
| { | ||
| int r; | ||
|
|
||
| assert(udev_ctx == NULL); | ||
| udev_ctx = udev_new(); | ||
| if (!udev_ctx) { | ||
| usbi_err(NULL, "could not create udev context"); | ||
| return LIBUSB_ERROR_OTHER; | ||
| } | ||
|
|
||
| udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev"); | ||
| if (!udev_monitor) { | ||
| usbi_err(NULL, "could not initialize udev monitor"); | ||
| goto err_free_ctx; | ||
| } | ||
|
|
||
| r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", 0); | ||
| if (r) { | ||
| usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem"); | ||
| goto err_free_monitor; | ||
| } | ||
|
|
||
| if (udev_monitor_enable_receiving(udev_monitor)) { | ||
| usbi_err(NULL, "failed to enable the udev monitor"); | ||
| goto err_free_monitor; | ||
| } | ||
|
|
||
| udev_monitor_fd = udev_monitor_get_fd(udev_monitor); | ||
|
|
||
| /* Some older versions of udev are not non-blocking by default, | ||
| * so make sure this is set */ | ||
| r = fcntl(udev_monitor_fd, F_GETFL); | ||
| if (r == -1) { | ||
| usbi_err(NULL, "getting udev monitor fd flags (%d)", errno); | ||
| goto err_free_monitor; | ||
| } | ||
| r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK); | ||
| if (r) { | ||
| usbi_err(NULL, "setting udev monitor fd flags (%d)", errno); | ||
| goto err_free_monitor; | ||
| } | ||
|
|
||
| r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL); | ||
| if (r) { | ||
| usbi_err(NULL, "creating hotplug event thread (%d)", r); | ||
| goto err_free_monitor; | ||
| } | ||
|
|
||
| return LIBUSB_SUCCESS; | ||
|
|
||
| err_free_monitor: | ||
| udev_monitor_unref(udev_monitor); | ||
| udev_monitor = NULL; | ||
| udev_monitor_fd = -1; | ||
| err_free_ctx: | ||
| udev_unref(udev_ctx); | ||
| udev_ctx = NULL; | ||
| return LIBUSB_ERROR_OTHER; | ||
| } | ||
|
|
||
| int linux_udev_stop_event_monitor(void) | ||
| { | ||
| assert(udev_ctx != NULL); | ||
| assert(udev_monitor != NULL); | ||
| assert(udev_monitor_fd != -1); | ||
|
|
||
| /* Cancel the event thread. This is the only way to guarantee the | ||
| thread exits since closing the monitor fd won't necessarily cause | ||
| poll to return. */ | ||
| pthread_cancel(linux_event_thread); | ||
| pthread_join(linux_event_thread, NULL); | ||
|
|
||
| /* Release the udev monitor */ | ||
| udev_monitor_unref(udev_monitor); | ||
| udev_monitor = NULL; | ||
| udev_monitor_fd = -1; | ||
|
|
||
| /* Clean up the udev context */ | ||
| udev_unref(udev_ctx); | ||
| udev_ctx = NULL; | ||
|
|
||
| return LIBUSB_SUCCESS; | ||
| } | ||
|
|
||
| static void *linux_udev_event_thread_main(void *arg) | ||
| { | ||
| struct udev_device* udev_dev; | ||
| struct pollfd fds = {.fd = udev_monitor_fd, | ||
| .events = POLLIN}; | ||
|
|
||
| usbi_dbg("udev event thread entering."); | ||
|
|
||
| while (1 == poll(&fds, 1, -1)) { | ||
| if (NULL == udev_monitor || POLLIN != fds.revents) { | ||
| break; | ||
| } | ||
|
|
||
| usbi_mutex_static_lock(&linux_hotplug_lock); | ||
| udev_dev = udev_monitor_receive_device(udev_monitor); | ||
| if (udev_dev) | ||
| udev_hotplug_event(udev_dev); | ||
| usbi_mutex_static_unlock(&linux_hotplug_lock); | ||
| } | ||
|
|
||
| usbi_dbg("udev event thread exiting"); | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| static int udev_device_info(struct libusb_context *ctx, int detached, | ||
| struct udev_device *udev_dev, uint8_t *busnum, | ||
| uint8_t *devaddr, const char **sys_name) { | ||
| const char *dev_node; | ||
|
|
||
| dev_node = udev_device_get_devnode(udev_dev); | ||
| if (!dev_node) { | ||
| return LIBUSB_ERROR_OTHER; | ||
| } | ||
|
|
||
| *sys_name = udev_device_get_sysname(udev_dev); | ||
| if (!*sys_name) { | ||
| return LIBUSB_ERROR_OTHER; | ||
| } | ||
|
|
||
| return linux_get_device_address(ctx, detached, busnum, devaddr, | ||
| dev_node, *sys_name); | ||
| } | ||
|
|
||
| static void udev_hotplug_event(struct udev_device* udev_dev) | ||
| { | ||
| const char* udev_action; | ||
| const char* sys_name = NULL; | ||
| uint8_t busnum = 0, devaddr = 0; | ||
| int detached; | ||
| int r; | ||
|
|
||
| do { | ||
| udev_action = udev_device_get_action(udev_dev); | ||
| if (!udev_action) { | ||
| break; | ||
| } | ||
|
|
||
| detached = !strncmp(udev_action, "remove", 6); | ||
|
|
||
| r = udev_device_info(NULL, detached, udev_dev, &busnum, &devaddr, &sys_name); | ||
| if (LIBUSB_SUCCESS != r) { | ||
| break; | ||
| } | ||
|
|
||
| usbi_dbg("udev hotplug event. action: %s.", udev_action); | ||
|
|
||
| if (strncmp(udev_action, "add", 3) == 0) { | ||
| linux_hotplug_enumerate(busnum, devaddr, sys_name); | ||
| } else if (detached) { | ||
| linux_hotplug_disconnected(busnum, devaddr, sys_name); | ||
| } else { | ||
| usbi_err(NULL, "ignoring udev action %s", udev_action); | ||
| } | ||
| } while (0); | ||
|
|
||
| udev_device_unref(udev_dev); | ||
| } | ||
|
|
||
| int linux_udev_scan_devices(struct libusb_context *ctx) | ||
| { | ||
| struct udev_enumerate *enumerator; | ||
| struct udev_list_entry *devices, *entry; | ||
| struct udev_device *udev_dev; | ||
| const char *sys_name; | ||
| int r; | ||
|
|
||
| assert(udev_ctx != NULL); | ||
|
|
||
| enumerator = udev_enumerate_new(udev_ctx); | ||
| if (NULL == enumerator) { | ||
| usbi_err(ctx, "error creating udev enumerator"); | ||
| return LIBUSB_ERROR_OTHER; | ||
| } | ||
|
|
||
| udev_enumerate_add_match_subsystem(enumerator, "usb"); | ||
| udev_enumerate_scan_devices(enumerator); | ||
| devices = udev_enumerate_get_list_entry(enumerator); | ||
|
|
||
| udev_list_entry_foreach(entry, devices) { | ||
| const char *path = udev_list_entry_get_name(entry); | ||
| uint8_t busnum = 0, devaddr = 0; | ||
|
|
||
| udev_dev = udev_device_new_from_syspath(udev_ctx, path); | ||
|
|
||
| r = udev_device_info(ctx, 0, udev_dev, &busnum, &devaddr, &sys_name); | ||
| if (r) { | ||
| udev_device_unref(udev_dev); | ||
| continue; | ||
| } | ||
|
|
||
| linux_enumerate_device(ctx, busnum, devaddr, sys_name); | ||
| udev_device_unref(udev_dev); | ||
| } | ||
|
|
||
| udev_enumerate_unref(enumerator); | ||
|
|
||
| return LIBUSB_SUCCESS; | ||
| } | ||
|
|
||
| void linux_udev_hotplug_poll(void) | ||
| { | ||
| struct udev_device* udev_dev; | ||
|
|
||
| usbi_mutex_static_lock(&linux_hotplug_lock); | ||
| do { | ||
| udev_dev = udev_monitor_receive_device(udev_monitor); | ||
| if (udev_dev) { | ||
| usbi_dbg("Handling hotplug event from hotplug_poll"); | ||
| udev_hotplug_event(udev_dev); | ||
| } | ||
| } while (udev_dev); | ||
| usbi_mutex_static_unlock(&linux_hotplug_lock); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| /* | ||
| * usbfs header structures | ||
| * Copyright © 2007 Daniel Drake <dsd@gentoo.org> | ||
| * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com> | ||
| * | ||
| * 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 | ||
| */ | ||
|
|
||
| #ifndef LIBUSB_USBFS_H | ||
| #define LIBUSB_USBFS_H | ||
|
|
||
| #include <linux/types.h> | ||
|
|
||
| #define SYSFS_DEVICE_PATH "/sys/bus/usb/devices" | ||
|
|
||
| struct usbfs_ctrltransfer { | ||
| /* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */ | ||
| uint8_t bmRequestType; | ||
| uint8_t bRequest; | ||
| uint16_t wValue; | ||
| uint16_t wIndex; | ||
| uint16_t wLength; | ||
|
|
||
| uint32_t timeout; /* in milliseconds */ | ||
|
|
||
| /* pointer to data */ | ||
| void *data; | ||
| }; | ||
|
|
||
| struct usbfs_bulktransfer { | ||
| /* keep in sync with usbdevice_fs.h:usbdevfs_bulktransfer */ | ||
| unsigned int ep; | ||
| unsigned int len; | ||
| unsigned int timeout; /* in milliseconds */ | ||
|
|
||
| /* pointer to data */ | ||
| void *data; | ||
| }; | ||
|
|
||
| struct usbfs_setinterface { | ||
| /* keep in sync with usbdevice_fs.h:usbdevfs_setinterface */ | ||
| unsigned int interface; | ||
| unsigned int altsetting; | ||
| }; | ||
|
|
||
| #define USBFS_MAXDRIVERNAME 255 | ||
|
|
||
| struct usbfs_getdriver { | ||
| unsigned int interface; | ||
| char driver[USBFS_MAXDRIVERNAME + 1]; | ||
| }; | ||
|
|
||
| #define USBFS_URB_SHORT_NOT_OK 0x01 | ||
| #define USBFS_URB_ISO_ASAP 0x02 | ||
| #define USBFS_URB_BULK_CONTINUATION 0x04 | ||
| #define USBFS_URB_QUEUE_BULK 0x10 | ||
| #define USBFS_URB_ZERO_PACKET 0x40 | ||
|
|
||
| enum usbfs_urb_type { | ||
| USBFS_URB_TYPE_ISO = 0, | ||
| USBFS_URB_TYPE_INTERRUPT = 1, | ||
| USBFS_URB_TYPE_CONTROL = 2, | ||
| USBFS_URB_TYPE_BULK = 3, | ||
| }; | ||
|
|
||
| struct usbfs_iso_packet_desc { | ||
| unsigned int length; | ||
| unsigned int actual_length; | ||
| unsigned int status; | ||
| }; | ||
|
|
||
| #define MAX_ISO_BUFFER_LENGTH 32768 | ||
| #define MAX_BULK_BUFFER_LENGTH 16384 | ||
| #define MAX_CTRL_BUFFER_LENGTH 4096 | ||
|
|
||
| struct usbfs_urb { | ||
| unsigned char type; | ||
| unsigned char endpoint; | ||
| int status; | ||
| unsigned int flags; | ||
| void *buffer; | ||
| int buffer_length; | ||
| int actual_length; | ||
| int start_frame; | ||
| int number_of_packets; | ||
| int error_count; | ||
| unsigned int signr; | ||
| void *usercontext; | ||
| struct usbfs_iso_packet_desc iso_frame_desc[0]; | ||
| }; | ||
|
|
||
| struct usbfs_connectinfo { | ||
| unsigned int devnum; | ||
| unsigned char slow; | ||
| }; | ||
|
|
||
| struct usbfs_ioctl { | ||
| int ifno; /* interface 0..N ; negative numbers reserved */ | ||
| int ioctl_code; /* MUST encode size + direction of data so the | ||
| * macros in <asm/ioctl.h> give correct values */ | ||
| void *data; /* param buffer (in, or out) */ | ||
| }; | ||
|
|
||
| struct usbfs_hub_portinfo { | ||
| unsigned char numports; | ||
| unsigned char port[127]; /* port to device num mapping */ | ||
| }; | ||
|
|
||
| #define USBFS_CAP_ZERO_PACKET 0x01 | ||
| #define USBFS_CAP_BULK_CONTINUATION 0x02 | ||
| #define USBFS_CAP_NO_PACKET_SIZE_LIM 0x04 | ||
| #define USBFS_CAP_BULK_SCATTER_GATHER 0x08 | ||
|
|
||
| #define USBFS_DISCONNECT_CLAIM_IF_DRIVER 0x01 | ||
| #define USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 0x02 | ||
|
|
||
| struct usbfs_disconnect_claim { | ||
| unsigned int interface; | ||
| unsigned int flags; | ||
| char driver[USBFS_MAXDRIVERNAME + 1]; | ||
| }; | ||
|
|
||
| #define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer) | ||
| #define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer) | ||
| #define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int) | ||
| #define IOCTL_USBFS_SETINTF _IOR('U', 4, struct usbfs_setinterface) | ||
| #define IOCTL_USBFS_SETCONFIG _IOR('U', 5, unsigned int) | ||
| #define IOCTL_USBFS_GETDRIVER _IOW('U', 8, struct usbfs_getdriver) | ||
| #define IOCTL_USBFS_SUBMITURB _IOR('U', 10, struct usbfs_urb) | ||
| #define IOCTL_USBFS_DISCARDURB _IO('U', 11) | ||
| #define IOCTL_USBFS_REAPURB _IOW('U', 12, void *) | ||
| #define IOCTL_USBFS_REAPURBNDELAY _IOW('U', 13, void *) | ||
| #define IOCTL_USBFS_CLAIMINTF _IOR('U', 15, unsigned int) | ||
| #define IOCTL_USBFS_RELEASEINTF _IOR('U', 16, unsigned int) | ||
| #define IOCTL_USBFS_CONNECTINFO _IOW('U', 17, struct usbfs_connectinfo) | ||
| #define IOCTL_USBFS_IOCTL _IOWR('U', 18, struct usbfs_ioctl) | ||
| #define IOCTL_USBFS_HUB_PORTINFO _IOR('U', 19, struct usbfs_hub_portinfo) | ||
| #define IOCTL_USBFS_RESET _IO('U', 20) | ||
| #define IOCTL_USBFS_CLEAR_HALT _IOR('U', 21, unsigned int) | ||
| #define IOCTL_USBFS_DISCONNECT _IO('U', 22) | ||
| #define IOCTL_USBFS_CONNECT _IO('U', 23) | ||
| #define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int) | ||
| #define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int) | ||
| #define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32) | ||
| #define IOCTL_USBFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbfs_disconnect_claim) | ||
|
|
||
| extern usbi_mutex_static_t linux_hotplug_lock; | ||
|
|
||
| #if defined(HAVE_LIBUDEV) | ||
| int linux_udev_start_event_monitor(void); | ||
| int linux_udev_stop_event_monitor(void); | ||
| int linux_udev_scan_devices(struct libusb_context *ctx); | ||
| void linux_udev_hotplug_poll(void); | ||
| #else | ||
| int linux_netlink_start_event_monitor(void); | ||
| int linux_netlink_stop_event_monitor(void); | ||
| void linux_netlink_hotplug_poll(void); | ||
| #endif | ||
|
|
||
| void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name); | ||
| void linux_hotplug_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name); | ||
|
|
||
| int linux_get_device_address (struct libusb_context *ctx, int detached, | ||
| uint8_t *busnum, uint8_t *devaddr, const char *dev_node, | ||
| const char *sys_name); | ||
| int linux_enumerate_device(struct libusb_context *ctx, | ||
| uint8_t busnum, uint8_t devaddr, const char *sysfs_dir); | ||
|
|
||
| #endif |