Externals: Update libusb to version 1.0.21

1.0.21 adds a usbdk backend, which may be helpful as it could be
used in the future to work around the missing isochronous transfer
support for WinUSB backends.

Here is the full changelog (from libusb).

2016-10-01: v1.0.21:
* Core: Refactor code related to transfer flags and timeout handling
* Darwin: Ignore root hub simulation devices
* Darwin: Improved support for OS X El Capitan
* Darwin: Work around devices with buggy endpoint descriptors
* Darwin: Do not use objc_registerThreadWithCollector after its deprecation
* Darwin: Use C11 atomics on 10.12+ as the OS atomics are now deprecated
* Linux: Support preallocating kernel memory for zerocopy USB
* Linux: Deal with receiving POLLERR before all transfers have completed
* Solaris: Add solaris backend
* Windows: Add Visual Studio 2015 support
* Windows: Add usbdk backend
* Prevent attempts to recursively handle events
* Fix race condition in handle_timeout()
* Allow transferred argument to be optional in bulk APIs
* Various other bug fixes and improvements
This commit is contained in:
Léo Lam
2016-11-20 18:11:42 +01:00
parent 3d21169dfc
commit 04db41adf3
81 changed files with 14306 additions and 1649 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
Copyright © 2010-2012 Peter Stuge <peter@stuge.se>
Copyright © 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net>
Copyright © 2008-2016 Nathan Hjelm <hjelmn@users.sourceforge.net>
Copyright © 2009-2013 Pete Batard <pete@akeo.ie>
Copyright © 2009-2013 Ludovic Rousseau <ludovic.rousseau@gmail.com>
Copyright © 2010-2012 Michael Plante <michael.plante@gmail.com>
+17
View File
@@ -1,6 +1,23 @@
For detailed information about the changes below, please see the git log or
visit: http://log.libusb.info
2016-10-01: v1.0.21:
* Core: Refactor code related to transfer flags and timeout handling
* Darwin: Ignore root hub simulation devices
* Darwin: Improved support for OS X El Capitan
* Darwin: Work around devices with buggy endpoint descriptors
* Darwin: Do not use objc_registerThreadWithCollector after its deprecation
* Darwin: Use C11 atomics on 10.12+ as the OS atomics are now deprecated
* Linux: Support preallocating kernel memory for zerocopy USB
* Linux: Deal with receiving POLLERR before all transfers have completed
* Solaris: Add solaris backend
* Windows: Add Visual Studio 2015 support
* Windows: Add usbdk backend
* Prevent attempts to recursively handle events
* Fix race condition in handle_timeout()
* Allow transferred argument to be optional in bulk APIs
* Various other bug fixes and improvements
2015-09-13: v1.0.20
* Add Haiku support
* Fix multiple memory and resource leaks (#16, #52, #76, #81)
+1 -1
View File
@@ -1,4 +1,4 @@
Dolphin-specific changes (as of 2016-08-25)
Dolphin-specific changes (as of 2016-11-20)
-------------------------------------------
- removed all toplevel directories save msvc/ & libusb/
+174 -38
View File
@@ -1,19 +1,25 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006 Free Software Foundation, Inc.
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
Briefly, the shell command `./configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package.
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
@@ -42,7 +48,7 @@ may remove or edit it.
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
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.
@@ -53,12 +59,22 @@ The simplest way to compile this package is:
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation.
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. You can remove the program binaries and object files from the
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
@@ -67,12 +83,22 @@ The simplest way to compile this package is:
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
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
@@ -85,25 +111,41 @@ is an example:
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
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 `..'.
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
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.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
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'.
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
@@ -114,16 +156,47 @@ 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.
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
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
@@ -135,14 +208,58 @@ 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.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out 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
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:
@@ -150,7 +267,8 @@ type, such as `sun4', or a canonical name which has the form:
where SYSTEM can have one of these forms:
OS KERNEL-OS
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
@@ -168,9 +286,9 @@ 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'.
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.
@@ -179,7 +297,7 @@ 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
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
@@ -191,18 +309,27 @@ 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:
an Autoconf limitation. Until the limitation is lifted, you can use
this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
@@ -229,6 +356,15 @@ an Autoconf bug. Until the bug is fixed you can use this workaround:
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
+10 -6
View File
@@ -1,15 +1,18 @@
libusb
======
# libusb
[![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb)
[![Build status](https://ci.appveyor.com/api/projects/status/xvrfam94jii4a6lw?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb)
libusb is a library for USB device access from Linux, Mac OS X,
Windows, OpenBSD/NetBSD and Haiku userspace.
It is written in C (Haiku backend in C++) and licensed under the GNU
Lesser General Public License version 2.1 or, at your option, any later
version (see COPYING).
version (see [COPYING](COPYING)).
libusb 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.
be ported to other operating systems. Please see the [PORTING](PORTING)
file for more information.
libusb homepage:
http://libusb.info/
@@ -24,6 +27,7 @@ http://mailing-list.libusb.info
- Hans de Goede <hdegoede@redhat.com>
- Xiaofan Chen <xiaofanc@gmail.com>
- Ludovic Rousseau <ludovic.rousseau@gmail.com>
- Nathan Hjelm <hjelmn@users.sourceforge.net>
- Nathan Hjelm <hjelmn@cs.unm.edu>
- Chris Dickens <christopher.a.dickens@gmail.com>
(Please use the mailing list rather than mailing developers directly)
+1 -1
View File
@@ -1,2 +1,2 @@
Please see the libusb roadmap by visiting:
https://github.com/libusb/libusb/issues/milestones?direction=asc&sort=due_date
https://github.com/libusb/libusb/milestones?direction=asc&sort=due_date&state=open
+50 -36
View File
@@ -4,58 +4,71 @@ AUTOMAKE_OPTIONS = subdir-objects
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
POSIX_POLL_SRC = os/poll_posix.h os/poll_posix.c
POSIX_THREADS_SRC = os/threads_posix.h os/threads_posix.c
WINDOWS_POLL_SRC = os/poll_windows.h os/poll_windows.c
WINDOWS_THREADS_SRC = os/threads_windows.h os/threads_windows.c
LINUX_USBFS_SRC = os/linux_usbfs.h os/linux_usbfs.c
DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c
OPENBSD_USB_SRC = os/openbsd_usb.c
NETBSD_USB_SRC = os/netbsd_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
SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h
WINDOWS_COMMON_SRC = os/windows_nt_common.h os/windows_nt_common.c \
os/windows_common.h libusb-1.0.rc libusb-1.0.def
WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c
WINDOWS_USBDK_SRC = os/windows_usbdk.h os/windows_usbdk.c
WINCE_USB_SRC = os/wince_usb.h os/wince_usb.c
HAIKU_USB_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \
os/haiku_usb_raw.h os/haiku_usb_raw.cpp os/haiku_pollfs.cpp
DIST_SUBDIRS =
EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \
$(NETBSD_USB_SRC) $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
$(POSIX_POLL_SRC) \
os/threads_posix.c os/threads_windows.c \
EXTRA_DIST = $(POSIX_POLL_SRC) $(POSIX_THREADS_SRC) \
$(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \
$(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \
$(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \
$(WINDOWS_COMMON_SRC) $(WINDOWS_USB_SRC) $(WINDOWS_USBDK_SRC) \
$(WINCE_USB_SRC) $(HAIKU_USB_SRC) \
os/linux_udev.c os/linux_netlink.c
dist-hook:
cp -r os/haiku $(distdir)/os/haiku
rm -rf $(distdir)/os/haiku/autom4te.cache
if OS_LINUX
if USE_UDEV
OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \
os/linux_udev.c
OS_SRC = $(LINUX_USBFS_SRC) os/linux_udev.c
else
OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \
os/linux_netlink.c
OS_SRC = $(LINUX_USBFS_SRC) os/linux_netlink.c
endif
endif
if OS_DARWIN
OS_SRC = $(DARWIN_USB_SRC) $(POSIX_POLL_SRC)
OS_SRC = $(DARWIN_USB_SRC)
AM_CFLAGS_EXT = -no-cpp-precomp
endif
if OS_OPENBSD
OS_SRC = $(OPENBSD_USB_SRC) $(POSIX_POLL_SRC)
OS_SRC = $(OPENBSD_USB_SRC)
endif
if OS_NETBSD
OS_SRC = $(NETBSD_USB_SRC) $(POSIX_POLL_SRC)
OS_SRC = $(NETBSD_USB_SRC)
endif
if OS_SUNOS
OS_SRC = $(SUNOS_USB_SRC)
endif
if OS_HAIKU
OS_SRC = $(POSIX_POLL_SRC)
SUBDIRS = os/haiku
noinst_LTLIBRARIES = libusb_haiku.la
libusb_haiku_la_SOURCES = $(HAIKU_USB_SRC)
libusb_1_0_la_LIBADD = libusb_haiku.la
endif
if OS_WINDOWS
OS_SRC = $(WINDOWS_USB_SRC)
if USE_USBDK
OS_SRC = $(WINDOWS_USBDK_SRC) $(WINDOWS_COMMON_SRC)
else
OS_SRC = $(WINDOWS_USB_SRC) $(WINDOWS_COMMON_SRC)
endif
.rc.lo:
$(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@
@@ -69,22 +82,23 @@ if CREATE_IMPORT_LIB
$(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
if OS_WINDOWS
POLL_SRC = $(WINDOWS_POLL_SRC)
else
THREADS_SRC = os/threads_windows.h os/threads_windows.c
POLL_SRC = $(POSIX_POLL_SRC)
endif
if THREADS_POSIX
THREADS_SRC = $(POSIX_THREADS_SRC)
else
THREADS_SRC = $(WINDOWS_THREADS_SRC)
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
if OS_HAIKU
libusb_1_0_la_LIBADD = os/haiku/libhaikuusb.la
endif
libusb_1_0_la_SOURCES = libusbi.h libusb.h version.h version_nano.h \
core.c descriptor.c hotplug.h hotplug.c io.c strerror.c sync.c \
$(POLL_SRC) $(THREADS_SRC) $(OS_SRC)
hdrdir = $(includedir)/libusb-1.0
hdr_HEADERS = libusb.h
+269 -274
View File
File diff suppressed because it is too large Load Diff
+267 -187
View File
File diff suppressed because it is too large Load Diff
+42 -52
View File
@@ -35,7 +35,7 @@
#define ENDPOINT_DESC_LENGTH 7
#define ENDPOINT_AUDIO_DESC_LENGTH 9
/** @defgroup desc USB descriptors
/** @defgroup libusb_desc USB descriptors
* This page details how to examine the various standard USB descriptors
* for detected devices
*/
@@ -94,8 +94,7 @@ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
{
if (endpoint->extra)
free((unsigned char *) endpoint->extra);
free((void *) endpoint->extra);
}
static int parse_endpoint(struct libusb_context *ctx,
@@ -198,19 +197,17 @@ static void clear_interface(struct libusb_interface *usb_interface)
struct libusb_interface_descriptor *ifp =
(struct libusb_interface_descriptor *)
usb_interface->altsetting + i;
if (ifp->extra)
free((void *) ifp->extra);
free((void *) ifp->extra);
if (ifp->endpoint) {
for (j = 0; j < ifp->bNumEndpoints; j++)
clear_endpoint((struct libusb_endpoint_descriptor *)
ifp->endpoint + j);
free((void *) ifp->endpoint);
ifp->endpoint + j);
}
free((void *) ifp->endpoint);
}
free((void *) usb_interface->altsetting);
usb_interface->altsetting = NULL;
}
free((void *) usb_interface->altsetting);
usb_interface->altsetting = NULL;
}
static int parse_interface(libusb_context *ctx,
@@ -222,7 +219,6 @@ static int parse_interface(libusb_context *ctx,
int r;
int parsed = 0;
int interface_number = -1;
size_t tmp;
struct usb_descriptor_header header;
struct libusb_interface_descriptor *ifp;
unsigned char *begin;
@@ -323,15 +319,13 @@ static int parse_interface(libusb_context *ctx,
if (ifp->bNumEndpoints > 0) {
struct libusb_endpoint_descriptor *endpoint;
tmp = ifp->bNumEndpoints * sizeof(struct libusb_endpoint_descriptor);
endpoint = malloc(tmp);
endpoint = calloc(ifp->bNumEndpoints, sizeof(struct libusb_endpoint_descriptor));
ifp->endpoint = endpoint;
if (!endpoint) {
r = LIBUSB_ERROR_NO_MEM;
goto err;
}
memset(endpoint, 0, tmp);
for (i = 0; i < ifp->bNumEndpoints; i++) {
r = parse_endpoint(ctx, endpoint + i, buffer, size,
host_endian);
@@ -364,15 +358,14 @@ err:
static void clear_configuration(struct libusb_config_descriptor *config)
{
int i;
if (config->interface) {
int i;
for (i = 0; i < config->bNumInterfaces; i++)
clear_interface((struct libusb_interface *)
config->interface + i);
free((void *) config->interface);
config->interface + i);
}
if (config->extra)
free((void *) config->extra);
free((void *) config->interface);
free((void *) config->extra);
}
static int parse_configuration(struct libusb_context *ctx,
@@ -381,7 +374,6 @@ static int parse_configuration(struct libusb_context *ctx,
{
int i;
int r;
size_t tmp;
struct usb_descriptor_header header;
struct libusb_interface *usb_interface;
@@ -411,13 +403,11 @@ static int parse_configuration(struct libusb_context *ctx,
return LIBUSB_ERROR_IO;
}
tmp = config->bNumInterfaces * sizeof(struct libusb_interface);
usb_interface = malloc(tmp);
usb_interface = calloc(config->bNumInterfaces, sizeof(struct libusb_interface));
config->interface = usb_interface;
if (!config->interface)
if (!usb_interface)
return LIBUSB_ERROR_NO_MEM;
memset(usb_interface, 0, tmp);
buffer += config->bLength;
size -= config->bLength;
@@ -538,7 +528,7 @@ int usbi_device_cache_descriptor(libusb_device *dev)
return LIBUSB_SUCCESS;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Get the USB device descriptor for a given device.
*
* This is a non-blocking function; the device descriptor is cached in memory.
@@ -559,7 +549,7 @@ int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
return 0;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Get the USB configuration descriptor for the currently active configuration.
* This is a non-blocking function which does not involve any requests being
* sent to the device.
@@ -606,7 +596,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
return r;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Get a USB configuration descriptor based on its index.
* This is a non-blocking function which does not involve any requests being
* sent to the device.
@@ -689,7 +679,7 @@ int usbi_get_config_index_by_value(struct libusb_device *dev,
return 0;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Get a USB configuration descriptor with a specific bConfigurationValue.
* This is a non-blocking function which does not involve any requests being
* sent to the device.
@@ -729,7 +719,7 @@ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
return libusb_get_config_descriptor(dev, (uint8_t) idx, config);
}
/** \ingroup desc
/** \ingroup libusb_desc
* Free a configuration descriptor obtained from
* libusb_get_active_config_descriptor() or libusb_get_config_descriptor().
* It is safe to call this function with a NULL config parameter, in which
@@ -747,7 +737,7 @@ void API_EXPORTED libusb_free_config_descriptor(
free(config);
}
/** \ingroup desc
/** \ingroup libusb_desc
* Get an endpoints superspeed endpoint companion descriptor (if any)
*
* \param ctx the context to operate on, or NULL for the default context
@@ -797,7 +787,7 @@ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
return LIBUSB_ERROR_NOT_FOUND;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Free a superspeed endpoint companion descriptor obtained from
* libusb_get_ss_endpoint_companion_descriptor().
* It is safe to call this function with a NULL ep_comp parameter, in which
@@ -890,18 +880,18 @@ static int parse_bos(struct libusb_context *ctx,
return LIBUSB_SUCCESS;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Get a Binary Object Store (BOS) descriptor
* This is a BLOCKING function, which will send requests to the device.
*
* \param handle the handle of an open libusb device
* \param dev_handle the handle of an open libusb device
* \param bos output location for the BOS descriptor. Only valid if 0 was returned.
* Must be freed with \ref libusb_free_bos_descriptor() after use.
* \returns 0 on success
* \returns LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor
* \returns another LIBUSB_ERROR code on error
*/
int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *handle,
int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle,
struct libusb_bos_descriptor **bos)
{
struct libusb_bos_descriptor _bos;
@@ -912,15 +902,15 @@ int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *handle,
/* Read the BOS. This generates 2 requests on the bus,
* one for the header, and one for the full BOS */
r = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, bos_header,
r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_header,
LIBUSB_DT_BOS_SIZE);
if (r < 0) {
if (r != LIBUSB_ERROR_PIPE)
usbi_err(handle->dev->ctx, "failed to read BOS (%d)", r);
usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r);
return r;
}
if (r < LIBUSB_DT_BOS_SIZE) {
usbi_err(handle->dev->ctx, "short BOS read %d/%d",
usbi_err(HANDLE_CTX(dev_handle), "short BOS read %d/%d",
r, LIBUSB_DT_BOS_SIZE);
return LIBUSB_ERROR_IO;
}
@@ -932,18 +922,18 @@ int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *handle,
if (bos_data == NULL)
return LIBUSB_ERROR_NO_MEM;
r = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, bos_data,
r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_data,
_bos.wTotalLength);
if (r >= 0)
r = parse_bos(handle->dev->ctx, bos, bos_data, r, host_endian);
r = parse_bos(HANDLE_CTX(dev_handle), bos, bos_data, r, host_endian);
else
usbi_err(handle->dev->ctx, "failed to read BOS (%d)", r);
usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r);
free(bos_data);
return r;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Free a BOS descriptor obtained from libusb_get_bos_descriptor().
* It is safe to call this function with a NULL bos parameter, in which
* case the function simply returns.
@@ -962,7 +952,7 @@ void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos)
free(bos);
}
/** \ingroup desc
/** \ingroup libusb_desc
* Get an USB 2.0 Extension descriptor
*
* \param ctx the context to operate on, or NULL for the default context
@@ -1006,7 +996,7 @@ int API_EXPORTED libusb_get_usb_2_0_extension_descriptor(
return LIBUSB_SUCCESS;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Free a USB 2.0 Extension descriptor obtained from
* libusb_get_usb_2_0_extension_descriptor().
* It is safe to call this function with a NULL usb_2_0_extension parameter,
@@ -1020,7 +1010,7 @@ void API_EXPORTED libusb_free_usb_2_0_extension_descriptor(
free(usb_2_0_extension);
}
/** \ingroup desc
/** \ingroup libusb_desc
* Get a SuperSpeed USB Device Capability descriptor
*
* \param ctx the context to operate on, or NULL for the default context
@@ -1064,7 +1054,7 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
return LIBUSB_SUCCESS;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Free a SuperSpeed USB Device Capability descriptor obtained from
* libusb_get_ss_usb_device_capability_descriptor().
* It is safe to call this function with a NULL ss_usb_device_cap
@@ -1078,7 +1068,7 @@ void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
free(ss_usb_device_cap);
}
/** \ingroup desc
/** \ingroup libusb_desc
* Get a Container ID descriptor
*
* \param ctx the context to operate on, or NULL for the default context
@@ -1121,7 +1111,7 @@ int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx,
return LIBUSB_SUCCESS;
}
/** \ingroup desc
/** \ingroup libusb_desc
* Free a Container ID descriptor obtained from
* libusb_get_container_id_descriptor().
* It is safe to call this function with a NULL container_id parameter,
@@ -1135,19 +1125,19 @@ void API_EXPORTED libusb_free_container_id_descriptor(
free(container_id);
}
/** \ingroup desc
/** \ingroup libusb_desc
* Retrieve a string descriptor in C style ASCII.
*
* Wrapper around libusb_get_string_descriptor(). Uses the first language
* supported by the device.
*
* \param dev a device handle
* \param dev_handle a device handle
* \param desc_index the index of the descriptor to retrieve
* \param data output buffer for ASCII string descriptor
* \param length size of data buffer
* \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
*/
int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle,
uint8_t desc_index, unsigned char *data, int length)
{
unsigned char tbuf[255]; /* Some devices choke on size > 255 */
@@ -1166,7 +1156,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
if (desc_index == 0)
return LIBUSB_ERROR_INVALID_PARAM;
r = libusb_get_string_descriptor(dev, 0, 0, tbuf, sizeof(tbuf));
r = libusb_get_string_descriptor(dev_handle, 0, 0, tbuf, sizeof(tbuf));
if (r < 0)
return r;
@@ -1175,7 +1165,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
langid = tbuf[2] | (tbuf[3] << 8);
r = libusb_get_string_descriptor(dev, desc_index, langid, tbuf,
r = libusb_get_string_descriptor(dev_handle, desc_index, langid, tbuf,
sizeof(tbuf));
if (r < 0)
return r;
+27 -21
View File
@@ -34,14 +34,14 @@
#include "hotplug.h"
/**
* @defgroup hotplug Device hotplug event notification
* @defgroup libusb_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
* \page libusb_hotplug Device hotplug event notification
*
* \section hotplug_intro Introduction
*
@@ -55,7 +55,7 @@
*
* 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 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
@@ -75,40 +75,47 @@
*
* 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.
* on each device 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 libusb function that takes a libusb_device. On the other hand,
* when handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
* safe to call any libusb function that takes a libusb_device. It also safe to
* open a device and submit asynchronous transfers. However, most other functions
* that take a libusb_device_handle are <b>not</b> safe to call. Examples of such
* functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking
* functions that retrieve various \ref libusb_desc "USB descriptors". These functions must
* be used outside of the context of the hotplug callback.
*
* 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
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <libusb.h>
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;
static libusb_device_handle *dev_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);
rc = libusb_open(dev, &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;
if (dev_handle) {
libusb_close(dev_handle);
dev_handle = NULL;
}
} else {
printf("Unhandled event %d\n", event);
@@ -119,7 +126,7 @@ int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
}
int main (void) {
libusb_hotplug_callback_handle handle;
libusb_hotplug_callback_handle callback_handle;
int rc;
libusb_init(NULL);
@@ -127,7 +134,7 @@ int main (void) {
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);
&callback_handle);
if (LIBUSB_SUCCESS != rc) {
printf("Error creating a hotplug callback\n");
libusb_exit(NULL);
@@ -136,10 +143,10 @@ int main (void) {
while (count < 2) {
libusb_handle_events_completed(NULL, NULL);
usleep(10000);
nanosleep(&(struct timespec){0, 10000000UL}, NULL);
}
libusb_hotplug_deregister_callback(NULL, handle);
libusb_hotplug_deregister_callback(NULL, callback_handle);
libusb_exit(NULL);
return 0;
@@ -231,7 +238,7 @@ 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_handle *callback_handle)
{
libusb_hotplug_callback *new_callback;
static int handle_id = 1;
@@ -298,15 +305,14 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
}
if (handle) {
*handle = new_callback->handle;
}
if (callback_handle)
*callback_handle = new_callback->handle;
return LIBUSB_SUCCESS;
}
void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
libusb_hotplug_callback_handle handle)
libusb_hotplug_callback_handle callback_handle)
{
struct libusb_hotplug_callback *hotplug_cb;
@@ -320,7 +326,7 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_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) {
if (callback_handle == hotplug_cb->handle) {
/* Mark this callback for deregistration */
hotplug_cb->needs_free = 1;
}
+238 -179
View File
File diff suppressed because it is too large Load Diff
+14 -8
View File
@@ -20,6 +20,10 @@ EXPORTS
libusb_control_transfer@32 = libusb_control_transfer
libusb_detach_kernel_driver
libusb_detach_kernel_driver@8 = libusb_detach_kernel_driver
libusb_dev_mem_alloc
libusb_dev_mem_alloc@8 = libusb_dev_mem_alloc
libusb_dev_mem_free
libusb_dev_mem_free@12 = libusb_dev_mem_free
libusb_error_name
libusb_error_name@4 = libusb_error_name
libusb_event_handler_active
@@ -36,6 +40,8 @@ EXPORTS
libusb_free_container_id_descriptor@4 = libusb_free_container_id_descriptor
libusb_free_device_list
libusb_free_device_list@8 = libusb_free_device_list
libusb_free_pollfds
libusb_free_pollfds@4 = libusb_free_pollfds
libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_usb_device_capability_descriptor
@@ -80,8 +86,6 @@ EXPORTS
libusb_get_parent@4 = libusb_get_parent
libusb_get_pollfds
libusb_get_pollfds@4 = libusb_get_pollfds
libusb_free_pollfds
libusb_free_pollfds@4 = libusb_free_pollfds
libusb_get_port_number
libusb_get_port_number@4 = libusb_get_port_number
libusb_get_port_numbers
@@ -116,14 +120,16 @@ EXPORTS
libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback
libusb_init
libusb_init@4 = libusb_init
libusb_interrupt_event_handler
libusb_interrupt_event_handler@4 = libusb_interrupt_event_handler
libusb_interrupt_transfer
libusb_interrupt_transfer@24 = libusb_interrupt_transfer
libusb_kernel_driver_active
libusb_kernel_driver_active@8 = libusb_kernel_driver_active
libusb_lock_event_waiters
libusb_lock_event_waiters@4 = libusb_lock_event_waiters
libusb_lock_events
libusb_lock_events@4 = libusb_lock_events
libusb_lock_event_waiters
libusb_lock_event_waiters@4 = libusb_lock_event_waiters
libusb_open
libusb_open@8 = libusb_open
libusb_open_device_with_vid_pid
@@ -144,10 +150,10 @@ EXPORTS
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_set_pollfd_notifiers
libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
libusb_strerror
libusb_strerror@4 = libusb_strerror
libusb_submit_transfer
@@ -158,10 +164,10 @@ EXPORTS
libusb_transfer_set_stream_id@8 = libusb_transfer_set_stream_id
libusb_try_lock_events
libusb_try_lock_events@4 = libusb_try_lock_events
libusb_unlock_event_waiters
libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters
libusb_unlock_events
libusb_unlock_events@4 = libusb_unlock_events
libusb_unlock_event_waiters
libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters
libusb_unref_device
libusb_unref_device@4 = libusb_unref_device
libusb_wait_for_event
+106 -97
View File
File diff suppressed because it is too large Load Diff
+152 -100
View File
@@ -52,14 +52,14 @@
extern "C" {
#endif
#define DEVICE_DESC_LENGTH 18
#define DEVICE_DESC_LENGTH 18
#define USB_MAXENDPOINTS 32
#define USB_MAXINTERFACES 32
#define USB_MAXCONFIG 8
/* Backend specific capabilities */
#define USBI_CAP_HAS_HID_ACCESS 0x00010000
#define USBI_CAP_HAS_HID_ACCESS 0x00010000
#define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000
/* Maximum number of bytes in a log line */
@@ -68,10 +68,10 @@ extern "C" {
#define USBI_LOG_LINE_END "\n"
/* The following is used to silence warnings for unused variables */
#define UNUSED(var) do { (void)(var); } while(0)
#define UNUSED(var) do { (void)(var); } while(0)
#if !defined(ARRAYSIZE)
#define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0]))
#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
#endif
struct list_head {
@@ -96,14 +96,14 @@ struct list_head {
* type - the type of the first parameter
*/
#define list_for_each_entry(pos, head, member, type) \
for (pos = list_entry((head)->next, type, member); \
&pos->member != (head); \
for (pos = list_entry((head)->next, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, type, member))
#define list_for_each_entry_safe(pos, n, head, member, type) \
for (pos = list_entry((head)->next, type, member), \
n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
#define list_for_each_entry_safe(pos, n, head, member, type) \
for (pos = list_entry((head)->next, type, member), \
n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, type, member))
#define list_empty(entry) ((entry)->next == (entry))
@@ -147,9 +147,9 @@ static inline void *usbi_reallocf(void *ptr, size_t size)
return ret;
}
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *mptr = (ptr); \
(type *)( (char *)mptr - offsetof(type,member) );})
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *mptr = (ptr); \
(type *)( (char *)mptr - offsetof(type,member) );})
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
@@ -160,13 +160,19 @@ static inline void *usbi_reallocf(void *ptr, size_t size)
#define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0)
#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
#define TIMEVAL_TV_SEC_TYPE long
#else
#define TIMEVAL_TV_SEC_TYPE time_t
#endif
/* Some platforms don't have this define */
#ifndef TIMESPEC_TO_TIMEVAL
#define TIMESPEC_TO_TIMEVAL(tv, ts) \
do { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
} while (0)
#define TIMESPEC_TO_TIMEVAL(tv, ts) \
do { \
(tv)->tv_sec = (TIMEVAL_TV_SEC_TYPE) (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
} while (0)
#endif
void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
@@ -192,49 +198,54 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
#else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
#ifdef ENABLE_LOGGING
#define LOG_BODY(ctxt, level) \
{ \
va_list args; \
va_start (args, format); \
usbi_log_v(ctxt, level, "", format, args); \
va_end(args); \
#define LOG_BODY(ctxt, level) \
{ \
va_list args; \
va_start(args, format); \
usbi_log_v(ctxt, level, "", format, args); \
va_end(args); \
}
#else
#define LOG_BODY(ctxt, level) do { (void)(ctxt); } while(0)
#define LOG_BODY(ctxt, level) \
{ \
(void)(ctxt); \
}
#endif
static inline void usbi_info(struct libusb_context *ctx, const char *format,
...)
LOG_BODY(ctx,LIBUSB_LOG_LEVEL_INFO)
static inline void usbi_warn(struct libusb_context *ctx, const char *format,
...)
LOG_BODY(ctx,LIBUSB_LOG_LEVEL_WARNING)
static inline void usbi_err( struct libusb_context *ctx, const char *format,
...)
LOG_BODY(ctx,LIBUSB_LOG_LEVEL_ERROR)
static inline void usbi_info(struct libusb_context *ctx, const char *format, ...)
LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO)
static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...)
LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING)
static inline void usbi_err(struct libusb_context *ctx, const char *format, ...)
LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR)
static inline void usbi_dbg(const char *format, ...)
LOG_BODY(NULL,LIBUSB_LOG_LEVEL_DEBUG)
LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG)
#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
#define USBI_GET_CONTEXT(ctx) if (!(ctx)) (ctx) = usbi_default_context
#define DEVICE_CTX(dev) ((dev)->ctx)
#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev))
#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle))
#define USBI_GET_CONTEXT(ctx) \
do { \
if (!(ctx)) \
(ctx) = usbi_default_context; \
} while(0)
#define DEVICE_CTX(dev) ((dev)->ctx)
#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev))
#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle))
#define ITRANSFER_CTX(transfer) \
(TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)))
#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN))
#define IS_EPOUT(ep) (!IS_EPIN(ep))
#define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN))
#define IS_XFEROUT(xfer) (!IS_XFERIN(xfer))
#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN))
#define IS_EPOUT(ep) (!IS_EPIN(ep))
#define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN))
#define IS_XFEROUT(xfer) (!IS_XFERIN(xfer))
/* Internal abstraction for thread synchronization */
#if defined(THREADS_POSIX)
#include "os/threads_posix.h"
#elif defined(OS_WINDOWS) || defined(OS_WINCE)
#include <os/threads_windows.h>
#include "os/threads_windows.h"
#endif
extern struct libusb_context *usbi_default_context;
@@ -266,6 +277,8 @@ struct libusb_context {
* the list, URBs that will time out later are placed after, and urbs with
* infinite timeout are always placed at the very end. */
struct list_head flying_transfers;
/* Note paths taking both this and usbi_transfer->lock must always
* take this lock first */
usbi_mutex_t flying_transfers_lock;
/* user callbacks for pollfd changes */
@@ -279,6 +292,10 @@ struct libusb_context {
/* used to see if there is an active thread doing event handling */
int event_handler_active;
/* A thread-local storage key to track which thread is performing event
* handling */
usbi_tls_key_t event_handling_key;
/* used to wait for event completion in threads other than the one that is
* event handling */
usbi_mutex_t event_waiters_lock;
@@ -287,18 +304,19 @@ struct libusb_context {
/* A lock to protect internal context event data. */
usbi_mutex_t event_data_lock;
/* A bitmask of flags that are set to indicate specific events that need to
* be handled. Protected by event_data_lock. */
unsigned int event_flags;
/* A counter that is set when we want to interrupt and prevent event handling,
* in order to safely close a device. Protected by event_data_lock. */
unsigned int device_close;
/* list and count of poll fds and an array of poll fd structures that is
* (re)allocated as necessary prior to polling, and a flag to indicate
* when the list of poll fds has changed since the last poll.
* Protected by event_data_lock. */
* (re)allocated as necessary prior to polling. Protected by event_data_lock. */
struct list_head ipollfds;
struct pollfd *pollfds;
POLL_NFDS_TYPE pollfds_cnt;
unsigned int pollfds_modified;
/* A list of pending hotplug messages. Protected by event_data_lock. */
struct list_head hotplug_msgs;
@@ -315,9 +333,27 @@ struct libusb_context {
struct list_head list;
};
enum usbi_event_flags {
/* The list of pollfds has been modified */
USBI_EVENT_POLLFDS_MODIFIED = 1 << 0,
/* The user has interrupted the event handler */
USBI_EVENT_USER_INTERRUPT = 1 << 1,
};
/* Macros for managing event handling state */
#define usbi_handling_events(ctx) \
(usbi_tls_key_get((ctx)->event_handling_key) != NULL)
#define usbi_start_event_handling(ctx) \
usbi_tls_key_set((ctx)->event_handling_key, ctx)
#define usbi_end_event_handling(ctx) \
usbi_tls_key_set((ctx)->event_handling_key, NULL)
/* Update the following macro if new event sources are added */
#define usbi_pending_events(ctx) \
((ctx)->device_close || (ctx)->pollfds_modified \
((ctx)->event_flags || (ctx)->device_close \
|| !list_empty(&(ctx)->hotplug_msgs) || !list_empty(&(ctx)->completed_transfers))
#ifdef USBI_TIMERFD_AVAILABLE
@@ -353,7 +389,11 @@ struct libusb_device {
#else
[0] /* non-standard, but usually working code */
#endif
#if defined(OS_SUNOS)
__attribute__ ((aligned (8)));
#else
;
#endif
};
struct libusb_device_handle {
@@ -370,12 +410,16 @@ struct libusb_device_handle {
#else
[0] /* non-standard, but usually working code */
#endif
#if defined(OS_SUNOS)
__attribute__ ((aligned (8)));
#else
;
#endif
};
enum {
USBI_CLOCK_MONOTONIC,
USBI_CLOCK_REALTIME
USBI_CLOCK_MONOTONIC,
USBI_CLOCK_REALTIME
};
/* in-memory transfer layout:
@@ -398,7 +442,8 @@ struct usbi_transfer {
struct timeval timeout;
int transferred;
uint32_t stream_id;
uint8_t flags;
uint8_t state_flags; /* Protected by usbi_transfer->lock */
uint8_t timeout_flags; /* Protected by the flying_stransfers_lock */
/* this lock is held during libusb_submit_transfer() and
* libusb_cancel_transfer() (allowing the OS backend to prevent duplicate
@@ -406,45 +451,39 @@ struct usbi_transfer {
* should also take this lock in the handle_events path, to prevent the user
* cancelling the transfer from another thread while you are processing
* its completion (presumably there would be races within your OS backend
* if this were possible). */
* if this were possible).
* Note paths taking both this and the flying_transfers_lock must
* always take the flying_transfers_lock first */
usbi_mutex_t lock;
/* this lock should be held whenever viewing or modifying flags
* relating to the transfer state */
usbi_mutex_t flags_lock;
};
enum usbi_transfer_flags {
/* The transfer has timed out */
USBI_TRANSFER_TIMED_OUT = 1 << 0,
/* Set by backend submit_transfer() if the OS handles timeout */
USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 1,
enum usbi_transfer_state_flags {
/* Transfer successfully submitted by backend */
USBI_TRANSFER_IN_FLIGHT = 1 << 0,
/* Cancellation was requested via libusb_cancel_transfer() */
USBI_TRANSFER_CANCELLING = 1 << 2,
USBI_TRANSFER_CANCELLING = 1 << 1,
/* Operation on the transfer failed because the device disappeared */
USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 3,
/* Transfer is currently being submitted */
USBI_TRANSFER_SUBMITTING = 1 << 4,
/* Transfer successfully submitted by backend */
USBI_TRANSFER_IN_FLIGHT = 1 << 5,
/* Completion handler has run */
USBI_TRANSFER_COMPLETED = 1 << 6,
/* The transfer timeout has been handled */
USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 7,
USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 2,
};
#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \
((struct libusb_transfer *)(((unsigned char *)(transfer)) \
enum usbi_transfer_timeout_flags {
/* Set by backend submit_transfer() if the OS handles timeout */
USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 0,
/* The transfer timeout has been handled */
USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1,
/* The transfer timeout was successfully processed */
USBI_TRANSFER_TIMED_OUT = 1 << 2,
};
#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \
((struct libusb_transfer *)(((unsigned char *)(transfer)) \
+ sizeof(struct usbi_transfer)))
#define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \
((struct usbi_transfer *)(((unsigned char *)(transfer)) \
#define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \
((struct usbi_transfer *)(((unsigned char *)(transfer)) \
- sizeof(struct usbi_transfer)))
static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer)
@@ -459,8 +498,8 @@ static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer)
/* All standard descriptors have these 2 fields in common */
struct usb_descriptor_header {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bLength;
uint8_t bDescriptorType;
};
/* shared data and functions */
@@ -473,7 +512,7 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx,
struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx,
unsigned long session_id);
int usbi_sanitize_device(struct libusb_device *dev);
void usbi_handle_disconnect(struct libusb_device_handle *handle);
void usbi_handle_disconnect(struct libusb_device_handle *dev_handle);
int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
enum libusb_transfer_status status);
@@ -493,7 +532,8 @@ int usbi_signal_event(struct libusb_context *ctx);
int usbi_clear_event(struct libusb_context *ctx);
/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_HAIKU)
#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\
defined(OS_HAIKU) || defined(OS_SUNOS)
#include <unistd.h>
#include "os/poll_posix.h"
#elif defined(OS_WINDOWS) || defined(OS_WINCE)
@@ -670,7 +710,7 @@ struct usbi_os_backend {
* Do not worry about freeing the handle on failed open, the upper layers
* do this for you.
*/
int (*open)(struct libusb_device_handle *handle);
int (*open)(struct libusb_device_handle *dev_handle);
/* Close a device such that the handle cannot be used again. Your backend
* should destroy any resources that were allocated in the open path.
@@ -680,7 +720,7 @@ struct usbi_os_backend {
*
* This function is called when the user closes a device handle.
*/
void (*close)(struct libusb_device_handle *handle);
void (*close)(struct libusb_device_handle *dev_handle);
/* Retrieve the device descriptor from a device.
*
@@ -787,7 +827,7 @@ struct usbi_os_backend {
* blocking
* - another LIBUSB_ERROR code on other failure.
*/
int (*get_configuration)(struct libusb_device_handle *handle, int *config);
int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config);
/* Set the active configuration for a device.
*
@@ -804,7 +844,7 @@ struct usbi_os_backend {
* was opened
* - another LIBUSB_ERROR code on other failure.
*/
int (*set_configuration)(struct libusb_device_handle *handle, int config);
int (*set_configuration)(struct libusb_device_handle *dev_handle, int config);
/* Claim an interface. When claimed, the application can then perform
* I/O to an interface's endpoints.
@@ -823,7 +863,7 @@ struct usbi_os_backend {
* was opened
* - another LIBUSB_ERROR code on other failure
*/
int (*claim_interface)(struct libusb_device_handle *handle, int interface_number);
int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number);
/* Release a previously claimed interface.
*
@@ -840,7 +880,7 @@ struct usbi_os_backend {
* was opened
* - another LIBUSB_ERROR code on other failure
*/
int (*release_interface)(struct libusb_device_handle *handle, int interface_number);
int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number);
/* Set the alternate setting for an interface.
*
@@ -856,7 +896,7 @@ struct usbi_os_backend {
* was opened
* - another LIBUSB_ERROR code on other failure
*/
int (*set_interface_altsetting)(struct libusb_device_handle *handle,
int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle,
int interface_number, int altsetting);
/* Clear a halt/stall condition on an endpoint.
@@ -870,12 +910,12 @@ struct usbi_os_backend {
* was opened
* - another LIBUSB_ERROR code on other failure
*/
int (*clear_halt)(struct libusb_device_handle *handle,
int (*clear_halt)(struct libusb_device_handle *dev_handle,
unsigned char endpoint);
/* Perform a USB port reset to reinitialize a device.
*
* If possible, the handle should still be usable after the reset
* If possible, the device handle should still be usable after the reset
* completes, assuming that the device descriptors did not change during
* reset and all previous interface state can be restored.
*
@@ -889,16 +929,26 @@ struct usbi_os_backend {
* has been disconnected since it was opened
* - another LIBUSB_ERROR code on other failure
*/
int (*reset_device)(struct libusb_device_handle *handle);
int (*reset_device)(struct libusb_device_handle *dev_handle);
/* Alloc num_streams usb3 bulk streams on the passed in endpoints */
int (*alloc_streams)(struct libusb_device_handle *handle,
int (*alloc_streams)(struct libusb_device_handle *dev_handle,
uint32_t num_streams, unsigned char *endpoints, int num_endpoints);
/* Free usb3 bulk streams allocated with alloc_streams */
int (*free_streams)(struct libusb_device_handle *handle,
int (*free_streams)(struct libusb_device_handle *dev_handle,
unsigned char *endpoints, int num_endpoints);
/* Allocate persistent DMA memory for the given device, suitable for
* zerocopy. May return NULL on failure. Optional to implement.
*/
unsigned char *(*dev_mem_alloc)(struct libusb_device_handle *handle,
size_t len);
/* Free memory allocated by dev_mem_alloc. */
int (*dev_mem_free)(struct libusb_device_handle *handle,
unsigned char *buffer, size_t len);
/* Determine if a kernel driver is active on an interface. Optional.
*
* The presence of a kernel driver on an interface indicates that any
@@ -911,7 +961,7 @@ struct usbi_os_backend {
* was opened
* - another LIBUSB_ERROR code on other failure
*/
int (*kernel_driver_active)(struct libusb_device_handle *handle,
int (*kernel_driver_active)(struct libusb_device_handle *dev_handle,
int interface_number);
/* Detach a kernel driver from an interface. Optional.
@@ -927,7 +977,7 @@ struct usbi_os_backend {
* was opened
* - another LIBUSB_ERROR code on other failure
*/
int (*detach_kernel_driver)(struct libusb_device_handle *handle,
int (*detach_kernel_driver)(struct libusb_device_handle *dev_handle,
int interface_number);
/* Attach a kernel driver to an interface. Optional.
@@ -944,7 +994,7 @@ struct usbi_os_backend {
* preventing reattachment
* - another LIBUSB_ERROR code on other failure
*/
int (*attach_kernel_driver)(struct libusb_device_handle *handle,
int (*attach_kernel_driver)(struct libusb_device_handle *dev_handle,
int interface_number);
/* Destroy a device. Optional.
@@ -1089,8 +1139,10 @@ extern const struct usbi_os_backend darwin_backend;
extern const struct usbi_os_backend openbsd_backend;
extern const struct usbi_os_backend netbsd_backend;
extern const struct usbi_os_backend windows_backend;
extern const struct usbi_os_backend usbdk_backend;
extern const struct usbi_os_backend wince_backend;
extern const struct usbi_os_backend haiku_usb_raw_backend;
extern const struct usbi_os_backend sunos_backend;
extern struct list_head active_contexts_list;
extern usbi_mutex_static_t active_contexts_lock;
+157 -32
View File
@@ -1,7 +1,7 @@
/* -*- Mode: C; indent-tabs-mode:nil -*- */
/*
* darwin backend for libusb 1.0
* Copyright © 2008-2014 Nathan Hjelm <hjelmn@users.sourceforge.net>
* Copyright © 2008-2016 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
@@ -19,6 +19,7 @@
*/
#include "config.h"
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <pthread.h>
@@ -28,7 +29,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <libkern/OSAtomic.h>
#include <sys/sysctl.h>
#include <mach/clock.h>
#include <mach/clock_types.h>
@@ -36,24 +37,43 @@
#include <mach/mach_port.h>
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
#include <objc/objc-auto.h>
#endif
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
/* Apple deprecated the darwin atomics in 10.12 in favor of C11 atomics */
#include <stdatomic.h>
#define libusb_darwin_atomic_fetch_add(x, y) atomic_fetch_add(x, y)
_Atomic int32_t initCount = ATOMIC_VAR_INIT(0);
#else
/* use darwin atomics if the target is older than 10.12 */
#include <libkern/OSAtomic.h>
/* OSAtomicAdd32Barrier returns the new value */
#define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y)
static volatile int32_t initCount = 0;
#endif
#include "darwin_usb.h"
/* async event thread */
static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
static pthread_once_t darwin_init_once = PTHREAD_ONCE_INIT;
static clock_serv_t clock_realtime;
static clock_serv_t clock_monotonic;
static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
static volatile int32_t initCount = 0;
static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices};
static char *darwin_device_class = kIOUSBDeviceClassName;
#define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev))
@@ -189,7 +209,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
}
static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) {
CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
CFMutableDictionaryRef matchingDict = IOServiceMatching(darwin_device_class);
if (!matchingDict)
return kIOReturnError;
@@ -234,6 +254,27 @@ static int get_ioregistry_value_number (io_service_t service, CFStringRef proper
return ret;
}
static int get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) {
CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
int ret = 0;
if (cfData) {
if (CFGetTypeID (cfData) == CFDataGetTypeID ()) {
CFIndex length = CFDataGetLength (cfData);
if (length < size) {
size = length;
}
CFDataGetBytes (cfData, CFRangeMake(0, size), p);
ret = 1;
}
CFRelease (cfData);
}
return ret;
}
static usb_device_t **darwin_device_from_service (io_service_t service)
{
io_cf_plugin_ref_t *plugInInterface = NULL;
@@ -344,19 +385,24 @@ static void *darwin_event_thread_main (void *arg0) {
struct libusb_context *ctx = (struct libusb_context *)arg0;
CFRunLoopRef runloop;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
/* Set this thread's name, so it can be seen in the debugger
and crash reports. */
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
pthread_setname_np ("org.libusb.device-hotplug");
#endif
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
/* Tell the Objective-C garbage collector about this thread.
This is required because, unlike NSThreads, pthreads are
not automatically registered. Although we don't use
Objective-C, we use CoreFoundation, which does. */
Objective-C, we use CoreFoundation, which does.
Garbage collection support was entirely removed in 10.12,
so don't bother there. */
objc_registerThreadWithCollector();
#endif
/* hotplug (device arrival/removal) sources */
CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
CFRunLoopSourceRef libusb_notification_cfsource;
io_notification_port_t libusb_notification_port;
io_iterator_t libusb_rem_device_iterator;
@@ -367,6 +413,13 @@ static void *darwin_event_thread_main (void *arg0) {
runloop = CFRunLoopGetCurrent ();
CFRetain (runloop);
/* add the shutdown cfsource to the run loop */
memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx));
libusb_shutdown_cfsourcectx.info = runloop;
libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop;
libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx);
CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
/* add the notification port to the run loop */
libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault);
libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port);
@@ -374,7 +427,7 @@ static void *darwin_event_thread_main (void *arg0) {
/* create notifications for removed devices */
kresult = IOServiceAddMatchingNotification (libusb_notification_port, kIOTerminatedNotification,
IOServiceMatching(kIOUSBDeviceClassName),
IOServiceMatching(darwin_device_class),
darwin_devices_detached,
ctx, &libusb_rem_device_iterator);
@@ -386,7 +439,7 @@ static void *darwin_event_thread_main (void *arg0) {
/* create notifications for attached devices */
kresult = IOServiceAddMatchingNotification(libusb_notification_port, kIOFirstMatchNotification,
IOServiceMatching(kIOUSBDeviceClassName),
IOServiceMatching(darwin_device_class),
darwin_devices_attached,
ctx, &libusb_add_device_iterator);
@@ -416,6 +469,9 @@ static void *darwin_event_thread_main (void *arg0) {
/* remove the notification cfsource */
CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
/* remove the shutdown cfsource */
CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
/* delete notification port */
IONotificationPortDestroy (libusb_notification_port);
@@ -423,8 +479,10 @@ static void *darwin_event_thread_main (void *arg0) {
IOObjectRelease (libusb_rem_device_iterator);
IOObjectRelease (libusb_add_device_iterator);
CFRelease (libusb_darwin_acfls);
CFRelease (runloop);
libusb_darwin_acfls = NULL;
libusb_darwin_acfl = NULL;
pthread_exit (NULL);
@@ -441,16 +499,37 @@ static void __attribute__((destructor)) _darwin_finalize(void) {
usbi_mutex_unlock(&darwin_cached_devices_lock);
}
static void darwin_check_version (void) {
/* adjust for changes in the USB stack in xnu 15 */
int sysctl_args[] = {CTL_KERN, KERN_OSRELEASE};
long version;
char version_string[256] = {'\0',};
size_t length = 256;
sysctl(sysctl_args, 2, version_string, &length, NULL, 0);
errno = 0;
version = strtol (version_string, NULL, 10);
if (0 == errno && version >= 15) {
darwin_device_class = "IOUSBHostDevice";
}
}
static int darwin_init(struct libusb_context *ctx) {
host_name_port_t host_self;
int rc;
rc = pthread_once (&darwin_init_once, darwin_check_version);
if (rc) {
return LIBUSB_ERROR_OTHER;
}
rc = darwin_scan_devices (ctx);
if (LIBUSB_SUCCESS != rc) {
return rc;
}
if (OSAtomicIncrement32Barrier(&initCount) == 1) {
if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) {
/* create the clocks that will be used */
host_self = mach_host_self();
@@ -470,12 +549,13 @@ static int darwin_init(struct libusb_context *ctx) {
}
static void darwin_exit (void) {
if (OSAtomicDecrement32Barrier(&initCount) == 0) {
if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) {
mach_port_deallocate(mach_task_self(), clock_realtime);
mach_port_deallocate(mach_task_self(), clock_monotonic);
/* stop the event runloop and wait for the thread to terminate. */
CFRunLoopStop (libusb_darwin_acfl);
CFRunLoopSourceSignal(libusb_darwin_acfls);
CFRunLoopWakeUp (libusb_darwin_acfl);
pthread_join (libusb_darwin_at, NULL);
}
}
@@ -570,6 +650,14 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin
return LIBUSB_ERROR_OTHER; /* no configurations at this speed so we can't use it */
}
/* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is
not usable anyway */
if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) {
usbi_dbg ("ignoring configuration on root hub simulation");
dev->active_config = 0;
return 0;
}
/* find the first configuration */
kresult = (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, 0, &configDesc);
dev->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1;
@@ -710,7 +798,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
if (kIOReturnSuccess != ret) {
usbi_dbg("kernel responded with code: 0x%08x. sleeping for %d ms before trying again", ret, delay/1000);
/* sleep for a little while before trying again */
usleep (delay);
nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL);
}
} while (kIOReturnSuccess != ret && retries--);
@@ -760,6 +848,24 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
return LIBUSB_SUCCESS;
}
static int get_device_port (io_service_t service, UInt8 *port) {
kern_return_t result;
io_service_t parent;
int ret = 0;
if (get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, port)) {
return 1;
}
result = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent);
if (kIOReturnSuccess == result) {
ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port);
IOObjectRelease (parent);
}
return ret;
}
static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service,
struct darwin_cached_device **cached_out) {
struct darwin_cached_device *new_device;
@@ -772,7 +878,9 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser
/* get some info from the io registry */
(void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID);
(void) get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, &port);
if (!get_device_port (service, &port)) {
usbi_dbg("could not get connected port number");
}
usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID);
@@ -1111,7 +1219,7 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
u_int8_t numep, direction, number;
u_int8_t dont_care1, dont_care3;
u_int16_t dont_care2;
int i;
int rc;
usbi_dbg ("building table of endpoints.");
@@ -1123,19 +1231,36 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
}
/* iterate through pipe references */
for (i = 1 ; i <= numep ; i++) {
for (int i = 1 ; i <= numep ; i++) {
kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1,
&dont_care2, &dont_care3);
if (kresult != kIOReturnSuccess) {
usbi_err (HANDLE_CTX (dev_handle), "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult));
/* probably a buggy device. try to get the endpoint address from the descriptors */
struct libusb_config_descriptor *config;
const struct libusb_endpoint_descriptor *endpoint_desc;
UInt8 alt_setting;
return darwin_to_libusb (kresult);
kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting);
if (kresult) {
usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface");
return darwin_to_libusb (kresult);
}
rc = libusb_get_active_config_descriptor (dev_handle->dev, &config);
if (LIBUSB_SUCCESS != rc) {
return rc;
}
endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1;
cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress;
} else {
cInterface->endpoint_addrs[i - 1] = (((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
}
usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number);
cInterface->endpoint_addrs[i - 1] = (((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
cInterface->endpoint_addrs[i - 1] & LIBUSB_ENDPOINT_ADDRESS_MASK);
}
cInterface->num_endpoints = numep;
@@ -1275,7 +1400,7 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
if (kresult != kIOReturnSuccess)
usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
cInterface->interface = IO_OBJECT_NULL;
cInterface->interface = (usb_interface_t **) IO_OBJECT_NULL;
return darwin_to_libusb (kresult);
}
@@ -1407,14 +1532,14 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle,
/* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */
static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
(void)dev_handle;
(void)interface;
UNUSED(dev_handle);
UNUSED(interface);
return LIBUSB_ERROR_NOT_SUPPORTED;
}
static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
(void)dev_handle;
(void)interface;
UNUSED(dev_handle);
UNUSED(interface);
return LIBUSB_ERROR_NOT_SUPPORTED;
}
@@ -1471,7 +1596,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer,
transfer->length, darwin_async_io_callback, itransfer);
} else {
itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
if (IS_XFERIN(transfer))
ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
@@ -1503,7 +1628,7 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) {
return LIBUSB_ERROR_NOT_FOUND;
}
itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
if (IS_XFERIN(transfer))
ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id,
@@ -1619,7 +1744,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
bzero(&tpriv->req, sizeof(tpriv->req));
/* IOUSBDeviceInterface expects the request in cpu endianess */
/* IOUSBDeviceInterface expects the request in cpu endianness */
tpriv->req.bmRequestType = setup->bmRequestType;
tpriv->req.bRequest = setup->bRequest;
/* these values should be in bus order from libusb_fill_control_setup */
@@ -1631,7 +1756,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
tpriv->req.completionTimeout = transfer->timeout;
tpriv->req.noDataTimeout = transfer->timeout;
itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
/* all transfers in libusb-1.0 are async */
@@ -1780,7 +1905,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
}
static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) {
if (itransfer->flags & USBI_TRANSFER_TIMED_OUT)
if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT)
result = kIOUSBTransactionTimeout;
switch (result) {
@@ -1797,7 +1922,7 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_
return LIBUSB_TRANSFER_OVERFLOW;
case kIOUSBTransactionTimeout:
usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out");
itransfer->flags |= USBI_TRANSFER_TIMED_OUT;
itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT;
return LIBUSB_TRANSFER_TIMED_OUT;
default:
usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result);
+8 -2
View File
@@ -1,6 +1,6 @@
/*
* darwin backend for libusb 1.0
* Copyright © 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net>
* Copyright © 2008-2015 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
@@ -28,7 +28,13 @@
#include <IOKit/IOCFPlugIn.h>
/* IOUSBInterfaceInferface */
#if defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
#if defined (kIOUSBInterfaceInterfaceID700) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
#define usb_interface_t IOUSBInterfaceInterface700
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700
#define InterfaceVersion 700
#elif defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
#define usb_interface_t IOUSBInterfaceInterface550
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550
+367
View File
@@ -0,0 +1,367 @@
/*
* Copyright 2007-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#include "haiku_usb.h"
#include <cstdio>
#include <Directory.h>
#include <Entry.h>
#include <Looper.h>
#include <Messenger.h>
#include <Node.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <cstring>
class WatchedEntry {
public:
WatchedEntry(BMessenger *, entry_ref *);
~WatchedEntry();
bool EntryCreated(entry_ref *ref);
bool EntryRemoved(ino_t node);
bool InitCheck();
private:
BMessenger* fMessenger;
node_ref fNode;
bool fIsDirectory;
USBDevice* fDevice;
WatchedEntry* fEntries;
WatchedEntry* fLink;
bool fInitCheck;
};
class RosterLooper : public BLooper {
public:
RosterLooper(USBRoster *);
void Stop();
virtual void MessageReceived(BMessage *);
bool InitCheck();
private:
USBRoster* fRoster;
WatchedEntry* fRoot;
BMessenger* fMessenger;
bool fInitCheck;
};
WatchedEntry::WatchedEntry(BMessenger *messenger, entry_ref *ref)
: fMessenger(messenger),
fIsDirectory(false),
fDevice(NULL),
fEntries(NULL),
fLink(NULL),
fInitCheck(false)
{
BEntry entry(ref);
entry.GetNodeRef(&fNode);
BDirectory directory;
if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) {
fIsDirectory = true;
while (directory.GetNextEntry(&entry) >= B_OK) {
if (entry.GetRef(ref) < B_OK)
continue;
WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref);
if (child == NULL)
continue;
if (child->InitCheck() == false) {
delete child;
continue;
}
child->fLink = fEntries;
fEntries = child;
}
watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger);
}
else {
if (strncmp(ref->name, "raw", 3) == 0)
return;
BPath path, parent_path;
entry.GetPath(&path);
fDevice = new(std::nothrow) USBDevice(path.Path());
if (fDevice != NULL && fDevice->InitCheck() == true) {
// Add this new device to each active context's device list
struct libusb_context *ctx;
unsigned long session_id = (unsigned long)&fDevice;
usbi_mutex_lock(&active_contexts_lock);
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
struct libusb_device *dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev) {
usbi_dbg("using previously allocated device with location %lu", session_id);
libusb_unref_device(dev);
continue;
}
usbi_dbg("allocating new device with location %lu", session_id);
dev = usbi_alloc_device(ctx, session_id);
if (!dev) {
usbi_dbg("device allocation failed");
continue;
}
*((USBDevice **)dev->os_priv) = fDevice;
// Calculate pseudo-device-address
int addr, tmp;
if (strcmp(path.Leaf(), "hub") == 0)
tmp = 100; //Random Number
else
sscanf(path.Leaf(), "%d", &tmp);
addr = tmp + 1;
path.GetParent(&parent_path);
while (strcmp(parent_path.Leaf(), "usb") != 0) {
sscanf(parent_path.Leaf(), "%d", &tmp);
addr += tmp + 1;
parent_path.GetParent(&parent_path);
}
sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number);
dev->device_address = addr - (dev->bus_number + 1);
if (usbi_sanitize_device(dev) < 0) {
usbi_dbg("device sanitization failed");
libusb_unref_device(dev);
continue;
}
usbi_connect_device(dev);
}
usbi_mutex_unlock(&active_contexts_lock);
}
else if (fDevice) {
delete fDevice;
fDevice = NULL;
return;
}
}
fInitCheck = true;
}
WatchedEntry::~WatchedEntry()
{
if (fIsDirectory) {
watch_node(&fNode, B_STOP_WATCHING, *fMessenger);
WatchedEntry *child = fEntries;
while (child) {
WatchedEntry *next = child->fLink;
delete child;
child = next;
}
}
if (fDevice) {
// Remove this device from each active context's device list
struct libusb_context *ctx;
struct libusb_device *dev;
unsigned long session_id = (unsigned long)&fDevice;
usbi_mutex_lock(&active_contexts_lock);
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev != NULL) {
usbi_disconnect_device(dev);
libusb_unref_device(dev);
} else {
usbi_dbg("device with location %lu not found", session_id);
}
}
usbi_mutex_static_unlock(&active_contexts_lock);
delete fDevice;
}
}
bool
WatchedEntry::EntryCreated(entry_ref *ref)
{
if (!fIsDirectory)
return false;
if (ref->directory != fNode.node) {
WatchedEntry *child = fEntries;
while (child) {
if (child->EntryCreated(ref))
return true;
child = child->fLink;
}
return false;
}
WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref);
if (child == NULL)
return false;
child->fLink = fEntries;
fEntries = child;
return true;
}
bool
WatchedEntry::EntryRemoved(ino_t node)
{
if (!fIsDirectory)
return false;
WatchedEntry *child = fEntries;
WatchedEntry *lastChild = NULL;
while (child) {
if (child->fNode.node == node) {
if (lastChild)
lastChild->fLink = child->fLink;
else
fEntries = child->fLink;
delete child;
return true;
}
if (child->EntryRemoved(node))
return true;
lastChild = child;
child = child->fLink;
}
return false;
}
bool
WatchedEntry::InitCheck()
{
return fInitCheck;
}
RosterLooper::RosterLooper(USBRoster *roster)
: BLooper("LibusbRoster Looper"),
fRoster(roster),
fRoot(NULL),
fMessenger(NULL),
fInitCheck(false)
{
BEntry entry("/dev/bus/usb");
if (!entry.Exists()) {
usbi_err(NULL, "usb_raw not published");
return;
}
Run();
fMessenger = new(std::nothrow) BMessenger(this);
if (fMessenger == NULL) {
usbi_err(NULL, "error creating BMessenger object");
return;
}
if (Lock()) {
entry_ref ref;
entry.GetRef(&ref);
fRoot = new(std::nothrow) WatchedEntry(fMessenger, &ref);
Unlock();
if (fRoot == NULL)
return;
if (fRoot->InitCheck() == false) {
delete fRoot;
fRoot = NULL;
return;
}
}
fInitCheck = true;
}
void
RosterLooper::Stop()
{
Lock();
delete fRoot;
delete fMessenger;
Quit();
}
void
RosterLooper::MessageReceived(BMessage *message)
{
int32 opcode;
if (message->FindInt32("opcode", &opcode) < B_OK)
return;
switch (opcode) {
case B_ENTRY_CREATED:
{
dev_t device;
ino_t directory;
const char *name;
if (message->FindInt32("device", &device) < B_OK ||
message->FindInt64("directory", &directory) < B_OK ||
message->FindString("name", &name) < B_OK)
break;
entry_ref ref(device, directory, name);
fRoot->EntryCreated(&ref);
break;
}
case B_ENTRY_REMOVED:
{
ino_t node;
if (message->FindInt64("node", &node) < B_OK)
break;
fRoot->EntryRemoved(node);
break;
}
}
}
bool
RosterLooper::InitCheck()
{
return fInitCheck;
}
USBRoster::USBRoster()
: fLooper(NULL)
{
}
USBRoster::~USBRoster()
{
Stop();
}
int
USBRoster::Start()
{
if (fLooper == NULL) {
fLooper = new(std::nothrow) RosterLooper(this);
if (fLooper == NULL || ((RosterLooper *)fLooper)->InitCheck() == false) {
if (fLooper)
fLooper = NULL;
return LIBUSB_ERROR_OTHER;
}
}
return LIBUSB_SUCCESS;
}
void
USBRoster::Stop()
{
if (fLooper) {
((RosterLooper *)fLooper)->Stop();
fLooper = NULL;
}
}
+112
View File
@@ -0,0 +1,112 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.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 <List.h>
#include <Locker.h>
#include <Autolock.h>
#include <USBKit.h>
#include <map>
#include "libusbi.h"
#include "haiku_usb_raw.h"
using namespace std;
class USBDevice;
class USBDeviceHandle;
class USBTransfer;
class USBDevice {
public:
USBDevice(const char *);
virtual ~USBDevice();
const char* Location() const;
uint8 CountConfigurations() const;
const usb_device_descriptor* Descriptor() const;
const usb_configuration_descriptor* ConfigurationDescriptor(uint32) const;
const usb_configuration_descriptor* ActiveConfiguration() const;
uint8 EndpointToIndex(uint8) const;
uint8 EndpointToInterface(uint8) const;
int ClaimInterface(int);
int ReleaseInterface(int);
int CheckInterfacesFree(int);
int SetActiveConfiguration(int);
int ActiveConfigurationIndex() const;
bool InitCheck();
private:
int Initialise();
unsigned int fClaimedInterfaces; // Max Interfaces can be 32. Using a bitmask
usb_device_descriptor fDeviceDescriptor;
unsigned char** fConfigurationDescriptors;
int fActiveConfiguration;
char* fPath;
map<uint8,uint8> fConfigToIndex;
map<uint8,uint8>* fEndpointToIndex;
map<uint8,uint8>* fEndpointToInterface;
bool fInitCheck;
};
class USBDeviceHandle {
public:
USBDeviceHandle(USBDevice *dev);
virtual ~USBDeviceHandle();
int ClaimInterface(int);
int ReleaseInterface(int);
int SetConfiguration(int);
int SetAltSetting(int, int);
status_t SubmitTransfer(struct usbi_transfer *);
status_t CancelTransfer(USBTransfer *);
bool InitCheck();
private:
int fRawFD;
static status_t TransfersThread(void *);
void TransfersWorker();
USBDevice* fUSBDevice;
unsigned int fClaimedInterfaces;
BList fTransfers;
BLocker fTransfersLock;
sem_id fTransfersSem;
thread_id fTransfersThread;
bool fInitCheck;
};
class USBTransfer {
public:
USBTransfer(struct usbi_transfer *, USBDevice *);
virtual ~USBTransfer();
void Do(int);
struct usbi_transfer* UsbiTransfer();
void SetCancelled();
bool IsCancelled();
private:
struct usbi_transfer* fUsbiTransfer;
struct libusb_transfer* fLibusbTransfer;
USBDevice* fUSBDevice;
BLocker fStatusLock;
bool fCancelled;
};
class USBRoster {
public:
USBRoster();
virtual ~USBRoster();
int Start();
void Stop();
private:
void* fLooper;
};
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More