mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #4463 from leoetlino/libusb
Externals: Update libusb to version 1.0.21
This commit is contained in:
+13
-13
@@ -749,19 +749,19 @@ if(ENABLE_SDL)
|
||||
endif()
|
||||
|
||||
if(NOT ANDROID)
|
||||
add_definitions(-D__LIBUSB__)
|
||||
if(NOT APPLE)
|
||||
find_package(LibUSB)
|
||||
endif()
|
||||
if(LIBUSB_FOUND AND NOT APPLE)
|
||||
message("Using shared LibUSB")
|
||||
include_directories(${LIBUSB_INCLUDE_DIR})
|
||||
else()
|
||||
message("Using static LibUSB from Externals")
|
||||
add_subdirectory(Externals/libusb)
|
||||
set(LIBUSB_LIBRARIES usb)
|
||||
endif()
|
||||
set(LIBUSB_FOUND true)
|
||||
add_definitions(-D__LIBUSB__)
|
||||
if(NOT APPLE)
|
||||
find_package(LibUSB)
|
||||
endif()
|
||||
if(LIBUSB_FOUND AND NOT APPLE)
|
||||
message("Using shared LibUSB")
|
||||
include_directories(${LIBUSB_INCLUDE_DIR})
|
||||
else()
|
||||
message("Using static LibUSB from Externals")
|
||||
add_subdirectory(Externals/libusb)
|
||||
set(LIBUSB_LIBRARIES usb)
|
||||
endif()
|
||||
set(LIBUSB_FOUND true)
|
||||
endif()
|
||||
|
||||
set(SFML_REQD_VERSION 2.1)
|
||||
|
||||
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;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user