mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
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:
Vendored
+1
-1
@@ -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>
|
||||
|
||||
Vendored
+17
@@ -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)
|
||||
|
||||
Vendored
+1
-1
@@ -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/
|
||||
|
||||
Vendored
+174
-38
@@ -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.
|
||||
|
||||
|
||||
Vendored
+10
-6
@@ -1,15 +1,18 @@
|
||||
libusb
|
||||
======
|
||||
# libusb
|
||||
|
||||
[](https://travis-ci.org/libusb/libusb)
|
||||
[](https://ci.appveyor.com/project/LudovicRousseau/libusb)
|
||||
[](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)
|
||||
|
||||
Vendored
+1
-1
@@ -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
|
||||
|
||||
Vendored
+50
-36
@@ -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
|
||||
|
||||
Vendored
+269
-274
File diff suppressed because it is too large
Load Diff
Vendored
+267
-187
File diff suppressed because it is too large
Load Diff
Vendored
+42
-52
@@ -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;
|
||||
|
||||
Vendored
+27
-21
@@ -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;
|
||||
}
|
||||
|
||||
Vendored
+238
-179
File diff suppressed because it is too large
Load Diff
+14
-8
@@ -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
|
||||
|
||||
Vendored
+106
-97
File diff suppressed because it is too large
Load Diff
Vendored
+152
-100
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
};
|
||||
+517
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
Reference in New Issue
Block a user