234 changes: 234 additions & 0 deletions Externals/libusbx/INSTALL
@@ -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.

27 changes: 27 additions & 0 deletions Externals/libusbx/Makefile.am
@@ -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)
875 changes: 875 additions & 0 deletions Externals/libusbx/Makefile.in

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Externals/libusbx/NEWS
@@ -0,0 +1,2 @@
For the latest libusbx news, please refer to the ChangeLog file, or visit:
http://libusbx.org
94 changes: 94 additions & 0 deletions Externals/libusbx/PORTING
@@ -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.
28 changes: 28 additions & 0 deletions Externals/libusbx/README
@@ -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)
7 changes: 7 additions & 0 deletions Externals/libusbx/THANKS
@@ -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
2 changes: 2 additions & 0 deletions Externals/libusbx/TODO
@@ -0,0 +1,2 @@
Please see the libusbx roadmap by visiting:
https://github.com/libusbx/libusbx/issues/milestones?direction=asc&sort=due_date
1,112 changes: 1,112 additions & 0 deletions Externals/libusbx/aclocal.m4

Large diffs are not rendered by default.

347 changes: 347 additions & 0 deletions Externals/libusbx/compile
@@ -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:
1,535 changes: 1,535 additions & 0 deletions Externals/libusbx/config.guess

Large diffs are not rendered by default.

134 changes: 134 additions & 0 deletions Externals/libusbx/config.h.in
@@ -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
1,790 changes: 1,790 additions & 0 deletions Externals/libusbx/config.sub

Large diffs are not rendered by default.

15,137 changes: 15,137 additions & 0 deletions Externals/libusbx/configure

Large diffs are not rendered by default.

249 changes: 249 additions & 0 deletions Externals/libusbx/configure.ac
@@ -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
790 changes: 790 additions & 0 deletions Externals/libusbx/depcomp

Large diffs are not rendered by default.

527 changes: 527 additions & 0 deletions Externals/libusbx/install-sh

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions Externals/libusbx/libusb-1.0.pc.in
@@ -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
68 changes: 68 additions & 0 deletions Externals/libusbx/libusb/Makefile.am
@@ -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
860 changes: 860 additions & 0 deletions Externals/libusbx/libusb/Makefile.in

Large diffs are not rendered by default.

2,228 changes: 2,228 additions & 0 deletions Externals/libusbx/libusb/core.c

Large diffs are not rendered by default.

1,197 changes: 1,197 additions & 0 deletions Externals/libusbx/libusb/descriptor.c

Large diffs are not rendered by default.

320 changes: 320 additions & 0 deletions Externals/libusbx/libusb/hotplug.c
@@ -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);
}
82 changes: 82 additions & 0 deletions Externals/libusbx/libusb/hotplug.h
@@ -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
2,566 changes: 2,566 additions & 0 deletions Externals/libusbx/libusb/io.c

Large diffs are not rendered by default.

158 changes: 158 additions & 0 deletions Externals/libusbx/libusb/libusb-1.0.def
@@ -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
61 changes: 61 additions & 0 deletions Externals/libusbx/libusb/libusb-1.0.rc
@@ -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

Large diffs are not rendered by default.

1,004 changes: 1,004 additions & 0 deletions Externals/libusbx/libusb/libusbi.h

Large diffs are not rendered by default.

1,903 changes: 1,903 additions & 0 deletions Externals/libusbx/libusb/os/darwin_usb.c

Large diffs are not rendered by default.

162 changes: 162 additions & 0 deletions Externals/libusbx/libusb/os/darwin_usb.h
@@ -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
254 changes: 254 additions & 0 deletions Externals/libusbx/libusb/os/linux_netlink.c
@@ -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);
}
273 changes: 273 additions & 0 deletions Externals/libusbx/libusb/os/linux_udev.c
@@ -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);
}
2,568 changes: 2,568 additions & 0 deletions Externals/libusbx/libusb/os/linux_usbfs.c

Large diffs are not rendered by default.

181 changes: 181 additions & 0 deletions Externals/libusbx/libusb/os/linux_usbfs.h
@@ -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